// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include #include #include #include #include #include #include #include #include #include #include #include #include "debug.hpp" #include namespace { int (*real_fprintf)(FILE *__restrict __stream, const char *__restrict __format, ...); void __attribute__((constructor)) _lib_posix_initialize() { real_fprintf = reinterpret_cast(dlsym(RTLD_NEXT, "fprintf")); if(!real_fprintf) { abort(); } } } extern "C" { using namespace vfsn::linux::internal; int link(const char *oldpath, const char *newpath) { TRACE_SYSCALL(); if(redirect_to_image(oldpath)) { errno = ENOSYS; real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ ); return -1; } else { auto r_link = reinterpret_cast(dlsym(RTLD_NEXT,"link")); char tmp[PATH_MAX], tmp2[PATH_MAX]; const auto oldp = npath_translate(oldpath,tmp); const auto newp = npath_translate(newpath,tmp2); return r_link(oldp,newp); } } __asm__(".symver link,link@GLIBC_2.2.5"); int unlink(const char *name) { TRACE_SYSCALL(); if(redirect_to_image(name)) { return invoke_fs(&purefs::fs::filesystem::unlink, name); } else { char tmp[PATH_MAX]; const auto path = npath_translate(name,tmp); auto r_unlink = reinterpret_cast(dlsym(RTLD_NEXT,"unlink")); return r_unlink(path); } } __asm__(".symver unlink,unlink@GLIBC_2.2.5"); int stat(const char *file, struct stat *pstat) { TRACE_SYSCALL(); if(redirect_to_image(file)) { return invoke_fs(&purefs::fs::filesystem::stat, file, *pstat); } else { char tmp[PATH_MAX]; const auto newfile = npath_translate(file,tmp); auto r_xstat = reinterpret_cast(dlsym(RTLD_NEXT, "__xstat")); return r_xstat(1,newfile,pstat); } } __asm__(".symver stat,stat@GLIBC_2.2.5"); int fstat(int fd, struct stat *pstat) { TRACE_SYSCALL(); if(is_image_fd(fd)) { return invoke_fs(&purefs::fs::filesystem::fstat,fd,*pstat); } else { auto r_fxstat = reinterpret_cast(dlsym(RTLD_NEXT, "__fxstat")); return r_fxstat(1,fd,pstat); } } __asm__(".symver fstat,fstat@GLIBC_2.2.5"); int lstat(const char *pathname, struct stat *statbuf) { TRACE_SYSCALL(); if(redirect_to_image(pathname)) { return invoke_fs(&purefs::fs::filesystem::stat, pathname, *statbuf); } else { char tmp[PATH_MAX]; const auto newpath = npath_translate(pathname,tmp); auto r_lxstat = reinterpret_cast(dlsym(RTLD_NEXT, "__lxstat")); return r_lxstat(1,newpath,statbuf); } } __asm__(".symver lstat,lstat@GLIBC_2.2.5"); int fcntl(int fd, int cmd, ... /* arg */ ) { TRACE_SYSCALL(); if(is_image_fd(fd)) { TRACE_SYSCALL(); errno = ENOSYS; real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ ); return -1; } else { uintptr_t param; va_list args; auto r_fcntl = reinterpret_cast(dlsym(RTLD_NEXT, "fcntl")); va_start(args,cmd); param = va_arg(args,uintptr_t); auto ret = r_fcntl(fd, cmd, param ); va_end(args); return ret; } } __asm__(".symver fcntl,fcntl@GLIBC_2.2.5"); int fcntl64(int fd, int cmd, ... /* arg */ ) { TRACE_SYSCALL(); if(is_image_fd(fd)) { TRACE_SYSCALL(); real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ ); errno = ENOSYS; return -1; } else { uintptr_t param; va_list args; auto r_fcntl = reinterpret_cast(dlsym(RTLD_NEXT, "fcntl64")); va_start(args,cmd); param = va_arg(args,uintptr_t); auto ret = r_fcntl(fd, cmd, param); va_end(args); return ret; } } __asm__(".symver fcntl64,fcntl64@GLIBC_2.2.5"); int chdir(const char *path) { TRACE_SYSCALL(); if(redirect_to_image(path)) { return invoke_fs(&purefs::fs::filesystem::chdir, path); } else { char tmp[PATH_MAX]; const auto newpath = npath_translate(path,tmp); auto r_chdir = reinterpret_cast(dlsym(RTLD_NEXT,"chdir")); return r_chdir(newpath); } } __asm__(".symver chdir,chdir@GLIBC_2.2.5"); int fchdir(int fd) { TRACE_SYSCALL(); if(is_image_fd(fd)) { errno = ENOSYS; real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ ); return -1; } else { auto r_fchdir = reinterpret_cast(dlsym(RTLD_NEXT,"fchdir")); return r_fchdir(fd); } } __asm__(".symver fchdir,fchdir@GLIBC_2.2.5"); char *getcwd(char *buf, size_t size) { TRACE_SYSCALL(); if(redirect_to_image()) { auto vfs = purefs::subsystem::vfs_core(); if(!vfs) { errno = EIO; return nullptr; } auto xwd = vfs->getcwd(); xwd.copy(buf,size); return buf; } else { auto r_getcwd = reinterpret_cast(dlsym(RTLD_NEXT,"getcwd")); return r_getcwd(buf,size); } } __asm__(".symver getcwd,getcwd@GLIBC_2.2.5"); char *getwd(char *buf) { TRACE_SYSCALL(); if(redirect_to_image()) { auto vfs = purefs::subsystem::vfs_core(); if(!vfs) { errno = EIO; return nullptr; } auto xwd = vfs->getcwd(); xwd.copy(buf,xwd.size()); return buf; } else { auto r_getwd = reinterpret_cast(dlsym(RTLD_NEXT,"getwd")); return r_getwd(buf); } } __asm__(".symver getwd,getwd@GLIBC_2.2.5"); char *get_current_dir_name(void) { TRACE_SYSCALL(); if(redirect_to_image()) { auto vfs = purefs::subsystem::vfs_core(); if(!vfs) { errno = EIO; return nullptr; } auto xwd = vfs->getcwd(); auto ret = new char[xwd.size()+1]; xwd.copy(ret,xwd.size()); ret[xwd.size()] = '\0'; return ret; } else { auto r_getrd = reinterpret_cast(dlsym(RTLD_NEXT,"get_current_dir_name")); return r_getrd(); } } __asm__(".symver get_current_dir_name,get_current_dir_name@GLIBC_2.2.5"); int rename(const char *oldpath, const char *newpath) { TRACE_SYSCALL(); if(redirect_to_image(oldpath)) { return invoke_fs(&purefs::fs::filesystem::rename, oldpath, newpath); } else { char tmp[PATH_MAX], tmp2[PATH_MAX]; const auto oldp = npath_translate(oldpath,tmp); const auto newp = npath_translate(newpath,tmp2); auto r_rename = reinterpret_cast(dlsym(RTLD_NEXT,"rename")); return r_rename(oldp,newp); } } __asm__(".symver rename,rename@GLIBC_2.2.5"); int mkdir(const char *pathname, mode_t mode) { if(redirect_to_image(pathname)) { return invoke_fs(&purefs::fs::filesystem::mkdir, pathname, mode); } else { char tmp[PATH_MAX]; const auto path = npath_translate(pathname,tmp); auto r_mkdir = reinterpret_cast(dlsym(RTLD_NEXT,"mkdir")); return r_mkdir(path,mode); } } __asm__(".symver mkdir,mkdir@GLIBC_2.2.5"); int chmod(const char *pathname, mode_t mode) { TRACE_SYSCALL(); if(redirect_to_image(pathname)) { return invoke_fs(&purefs::fs::filesystem::chmod,pathname,mode); } else { char tmp[PATH_MAX]; const auto path = npath_translate(pathname,tmp); auto r_chmod = reinterpret_cast(dlsym(RTLD_NEXT,"chmod")); return r_chmod(path,mode); } } __asm__(".symver chmod,chmod@GLIBC_2.2.5"); int fchmod(int fd, mode_t mode) { TRACE_SYSCALL(); if(is_image_fd(fd)) { return invoke_fs(&purefs::fs::filesystem::fchmod,fd,mode); } else { auto r_fchmod = reinterpret_cast(dlsym(RTLD_NEXT,"fchmod")); return r_fchmod(fd,mode); } } __asm__(".symver fchmod,fchmod@GLIBC_2.2.5"); int fsync(int fd) { TRACE_SYSCALL(); if(is_image_fd(fd)) { return invoke_fs(&purefs::fs::filesystem::fsync, fd); } else { auto r_fsync = reinterpret_cast(dlsym(RTLD_NEXT,"fsync")); return r_fsync(fd); } } __asm__(".symver fsync,fsync@GLIBC_2.2.5"); int fdatasync(int fd) { TRACE_SYSCALL(); return fsync(fd); } __asm__(".symver fdatasync,fdatasync@GLIBC_2.2.5"); int symlink(const char *target, const char *linkpath) { TRACE_SYSCALL(); if(redirect_to_image(target)) { return invoke_fs(&purefs::fs::filesystem::symlink,target,linkpath); } else { char tmp[PATH_MAX], tmp2[PATH_MAX]; const auto tgtp = npath_translate(target,tmp); const auto linp = npath_translate(linkpath,tmp2); auto r_symlink = reinterpret_cast(dlsym(RTLD_NEXT,"symlink")); return r_symlink(tgtp,linp); } } __asm__(".symver symlink,symlink@GLIBC_2.2.5"); int __symlink(const char *target, const char *linkpath) { return symlink(target,linkpath); } int fstatat(int dirfd, const char *pathname, struct stat *statbuf, int flags) { TRACE_SYSCALL(); errno = ENOSYS; real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ ); return -1; } __asm__(".symver fstatat,fstatat@GLIBC_2.2.5"); int __xstat(int ver, const char * path, struct stat * stat_buf) { if( redirect_to_image(path) ) { return invoke_fs(&purefs::fs::filesystem::stat, path, *stat_buf); } else { char tmp[PATH_MAX]; const auto newp = npath_translate(path,tmp); auto r_xstat = reinterpret_cast(dlsym(RTLD_NEXT, "__xstat")); return r_xstat(ver,newp,stat_buf); } } int __lxstat(int ver, const char * path, struct stat * stat_buf) { if( redirect_to_image(path) ) { return invoke_fs(&purefs::fs::filesystem::stat, path, *stat_buf); } else { char tmp[PATH_MAX]; const auto newp = npath_translate(path,tmp); auto r_xstat = reinterpret_cast(dlsym(RTLD_NEXT, "__lxstat")); return r_xstat(ver,newp,stat_buf); } } int __fxstat(int ver, int fildes, struct stat * stat_buf) { if( is_image_fd(fildes) ) { return invoke_fs(&purefs::fs::filesystem::fstat, fildes, *stat_buf); } else { auto r_fxstat = reinterpret_cast(dlsym(RTLD_NEXT, "__fxstat")); return r_fxstat(ver,fildes,stat_buf); } } }