Loading src/client/gkfs_libc.cpp +198 −41 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ std::atomic<bool> initializing{false}; // Define a debug macro, can be easily disabled // #define GKFS_TRACE #define PATH_SHORTCUT // #define PATH_SHORTCUT #ifdef GKFS_DEBUG_BUILD #ifdef GKFS_TRACE Loading Loading @@ -155,6 +155,23 @@ log_argumentsx(const char* symbol, Args&&... args) { return real_##func_name args; \ } #define NOLOGDLSYM_WRAPPER(return_type, func_name, params, args, symbol_name) \ static return_type(*real_##func_name) params = nullptr; \ return_type dlsym_##func_name params { \ if(!real_##func_name) { \ real_##func_name = reinterpret_cast<return_type(*) params>( \ dlsym(RTLD_NEXT, symbol_name)); \ if(!real_##func_name) { \ fprintf(stderr, "dlsym failed for %s: %s\n", symbol_name, \ dlerror()); \ errno = ENOSYS; /* Set errno to ENOSYS to indicate function \ not supported */ \ return (return_type) - 1; /* Return error value */ \ } \ } \ return real_##func_name args; \ } #define CDLSYM_WRAPPER(return_type, func_name, params, args, symbol_name) \ static return_type(*real_##func_name) params = nullptr; \ Loading Loading @@ -225,10 +242,15 @@ DLSYM_WRAPPER(int, fxstat64, (int ver, int fd, struct stat64* buf), (ver, fd, buf), "__fxstat64") DLSYM_WRAPPER(int, lstat, (int ver, const char* path, struct stat* buf), (ver, path, buf), "__lxstat") DLSYM_WRAPPER(int, lstat64, (const char* path, struct stat64* buf), (path, buf), "lstat64") DLSYM_WRAPPER(int, stat, (int ver, const char* path, struct stat* buf), (ver, path, buf), "__xstat") DLSYM_WRAPPER(int, fstat, (int ver, int fd, struct stat* buf), (ver, fd, buf), "__fxstat") DLSYM_WRAPPER(int, __fxstat, (int ver, int fd, struct stat* buf), (ver, fd, buf), "__fxstat") DLSYM_WRAPPER(int, fstat, (int fd, struct stat* buf), (fd, buf), "fstat") DLSYM_WRAPPER(int, fstat64, (int fd, struct stat64* buf), (fd, buf), "fstat64") DLSYM_WRAPPER(int, fxstatat, (int ver, int dfd, const char* path, struct stat* buf, int flags), Loading Loading @@ -333,15 +355,34 @@ DLSYM_WRAPPER(void, rewind, (FILE * stream), (stream), "rewind") DLSYM_WRAPPER(int, feof, (FILE * stream), (stream), "feof") DLSYM_WRAPPER(int, fputs, (const char* str, FILE* stream), (str, stream), "fputs") DLSYM_WRAPPER(char*, fgets, (char* str, int n, FILE* stream), (str, n, stream), "fgets") DLSYM_WRAPPER(int, fflush, (FILE * stream), (stream), "fflush") NOLOGDLSYM_WRAPPER(char*, fgets, (char* str, int n, FILE* stream), (str, n, stream), "fgets") NOLOGDLSYM_WRAPPER(int, fflush, (FILE * stream), (stream), "fflush") DLSYM_WRAPPER(int, fchown, (int fd, uid_t owner, gid_t group), (fd, owner, group), "fchown") DLSYM_WRAPPER(int, futimes, (int fd, const struct timeval times[2]), (fd, times), "futimes") DLSYM_WRAPPER(int, utimes, (const char* path, const struct timeval times[2]), (path, times), "utimes") // listxattr DLSYM_WRAPPER(ssize_t, listxattr, (const char* path, char* list, size_t size), (path, list, size), "listxattr") DLSYM_WRAPPER(ssize_t, llistxattr, (const char* path, char* list, size_t size), (path, list, size), "llistxattr") DLSYM_WRAPPER(ssize_t, flistxattr, (int fd, char* list, size_t size), (fd, list, size), "flistxattr") //DLSYM_WRAPPER(long, syscall, (long number, char* cmd, void* arg, void* env), // (number, cmd, arg, env), "syscall") DLSYM_WRAPPER(DIR*, fdopendir, (int fd), (fd), "fdopendir") DLSYM_WRAPPER(int, scandir, (const char* dirp, struct dirent*** namelist, typeof(int(const struct dirent*))* filter, typeof(int(const struct dirent**, const struct dirent**))* compar), (dirp, namelist, filter, compar), "scandir") /*CDLSYM_WRAPPER(ssize_t, readlink, (const char* path, char* buf, size_t bufsize), (path, buf, bufsize), "readlink") Loading Loading @@ -377,23 +418,7 @@ argv[]), (filename, argv), "execvp") DLSYM_WRAPPER(long, syscall, (long number, char* cmd, void* arg, void* env), (number, cmd, arg, env), "syscall") long syscall(long number, ...) { if(number == SYS_execve or number == SYS_execveat) { DEBUG_INFO("execve {}", number); } va_list myargs; va_start(myargs, number); auto res = syscall_no_intercept_wrapper(number, myargs); va_end(myargs); return res; } */ /* not used */ /*static void Loading Loading @@ -811,10 +836,11 @@ unlink(const char* path) { int __xstat(int ver, const char* path, struct stat* buf) { GKFS_PATH_OPERATION(stat, AT_FDCWD, path, buf) auto res = dlsym_stat(_STAT_VER, path, buf); auto res = dlsym_stat(ver, path, buf); return res; } int __xstat64(int ver, const char* path, struct stat64* buf) { struct stat st; Loading @@ -835,7 +861,7 @@ __xstat64(int ver, const char* path, struct stat64* buf) { } } } auto res = dlsym_stat(_STAT_VER, path, &st); auto res = dlsym_stat(ver, path, &st); convert(&st, buf); return res; } Loading Loading @@ -910,7 +936,7 @@ __fxstat(int ver, int fd, struct stat* buf) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); return gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), buf); } GKFS_FALLBACK(fstat, ver, fd, buf); GKFS_FALLBACK(__fxstat, ver, fd, buf); } int Loading Loading @@ -950,6 +976,17 @@ fstat64(int fd, struct stat64* buf) { GKFS_FALLBACK(fstat64, fd, buf); } int fstat(int fd, struct stat* buf) { initializeGekko(); if(is_gkfs_fd(fd)) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); int res = gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), buf); return res; } GKFS_FALLBACK(fstat, fd, buf); } int __fxstatat64(int ver, int dfd, const char* path, struct stat64* buf, Loading Loading @@ -1008,16 +1045,6 @@ stat64(const char* path, struct stat64* buf) { return ret; } int fstat(int fd, struct stat* buf) { initializeGekko(); if(is_gkfs_fd(fd)) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); return gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), buf); } GKFS_FALLBACK(fstat, _STAT_VER, fd, buf); } int fstatat(int dfd, const char* path, struct stat* buf, int flags) { initializeGekko(); Loading Loading @@ -1182,19 +1209,21 @@ chdir(const char* path) { initializeGekko(); // is the path from gekkofs // return gkfs::hook::hook_chdir(path); if(CTX->interception_enabled()) { std::string resolved; auto rstatus = CTX->relativize_fd_path(AT_FDCWD, path, resolved); DEBUG_INFO("[GKFS] chdir status {} {} --> {}", (int) rstatus, resolved, path); switch(rstatus) { case gkfs::preload::RelativizeStatus::fd_not_a_dir: return -ENOTDIR; case gkfs::preload::RelativizeStatus::internal: DEBUG_INFO("[GKFS] NOT IMPLEMENTED {}", path); return gkfs::hook::hook_chdir(path); break; default: Loading @@ -1202,7 +1231,7 @@ chdir(const char* path) { break; } } CTX->cwd(path); GKFS_FALLBACK(chdir, const_cast<char*>(path)); } Loading Loading @@ -1390,6 +1419,19 @@ opendir64(const char* dirname) { return dlsym_opendir64(const_cast<char*>(dirname)); } DIR* fdopendir(int fd) { if(CTX->interception_enabled()) { if(is_gkfs_fd(fd)) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); return gekko_opendir(CTX->file_map()->get(fd)->path()); } } GKFS_FALLBACK(fdopendir, fd); } // clang-format off #ifndef __ALIGN_KERNEL_MASK Loading Loading @@ -1748,7 +1790,7 @@ fgets(char* str, int n, FILE* stream) { GKFS_FALLBACK(fgets, str, n, stream) } // implement fflush and bypass if gekko // implement fflush and bypass if gekko (no need to log) int fflush(FILE* stream) { initializeGekko(); Loading @@ -1756,7 +1798,7 @@ fflush(FILE* stream) { // flush stream with gkfs_fsync return 0; } GKFS_FALLBACK(fflush, stream) return dlsym_fflush(stream); } Loading Loading @@ -1870,3 +1912,118 @@ utimes(const char* path, const struct timeval tv[2]) { } GKFS_FALLBACK(utimes, path, tv); } // Without use... goes directly to the syscall (ls -l) ssize_t listxattr(const char* path, char* list, size_t size) { initializeGekko(); if(CTX->interception_enabled()) { std::string resolved; if(resolve_gkfs_path(AT_FDCWD, path, resolved) == PathStatus::Internal) { DEBUG_INFO("[GKFS] {}", resolved); return 0; } } GKFS_FALLBACK(listxattr, path, list, size); } ssize_t flistxattr(int fd, char* list, size_t size) { initializeGekko(); if(is_gkfs_fd(fd)) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); return 0; } GKFS_FALLBACK(flistxattr, fd, list, size); } ssize_t llistxattr(const char* path, char* list, size_t size) { initializeGekko(); return 0; if(CTX->interception_enabled()) { std::string resolved; if(resolve_gkfs_path(AT_FDCWD, path, resolved) == PathStatus::Internal) { DEBUG_INFO("[GKFS] {}", resolved); return 0; } } GKFS_FALLBACK(llistxattr, path, list, size); } int lstat64(const char* path, struct stat64* buf) { initializeGekko(); if(CTX->interception_enabled()) { std::string resolved; struct stat st; if(resolve_gkfs_path(AT_FDCWD, path, resolved) == PathStatus::Internal) { DEBUG_INFO("[GKFS] {}", resolved); auto res = gkfs::syscall::gkfs_stat(resolved, &st); convert(&st, buf); return res; } } GKFS_FALLBACK(lstat64, path, buf); } int scandir(const char* dirname, struct dirent*** namelist, int (*filter)(const struct dirent*), int (*compar)(const struct dirent**, const struct dirent**)) { initializeGekko(); if(CTX->interception_enabled()) { std::string resolved; if(resolve_gkfs_path(AT_FDCWD, dirname, resolved) == PathStatus::Internal) { DEBUG_INFO("[GKFS] {}", resolved); // implement scandir : The scandir() function scans the directory // dirp, calling filter() on each directory entry. Entries for // which filter() returns nonzero are stored in strings allocated // via malloc(3), sorted using qsort(3) with the comparison function // compar(), and collected in // array namelist which is allocated via malloc(3). If filter // is NULL, all entries are selected. DIR* dirp = gekko_opendir(resolved); if(dirp == nullptr) { return -1; } std::vector<struct dirent*> entries; struct dirent* entry; while((entry = readdir(dirp)) != nullptr) { if(filter == nullptr || filter(entry) != 0) { entries.push_back(entry); } } closedir(dirp); if(entries.empty()) { *namelist = nullptr; return 0; } if(compar != nullptr) { qsort(entries.data(), entries.size(), sizeof(struct dirent*), reinterpret_cast<int (*)(const void*, const void*)>( compar)); } *namelist = static_cast<struct dirent**>( malloc(sizeof(struct dirent*) * (entries.size() + 1))); if(*namelist == nullptr) { for(auto e : entries) { free(e); } return -1; } for(size_t i = 0; i < entries.size(); ++i) { (*namelist)[i] = entries[i]; } (*namelist)[entries.size()] = nullptr; return entries.size(); } } GKFS_FALLBACK(scandir, dirname, namelist, filter, compar); } src/client/path.cpp +14 −2 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ extern "C" { #include <sys/stat.h> #include <dlfcn.h> } using namespace std; Loading Loading @@ -208,9 +209,20 @@ resolve_new(const string& path, bool resolve_last_link) { if(resolved.empty()) { resolved.push_back(path::separator); } // TODO: redo auto real = reinterpret_cast<char* (*) (const char* path, char* resolved_path)>( dlsym(((void*) -1l), "realpath")); auto link_resolved = ::unique_ptr<char[]>(new char[PATH_MAX]); if(real(path.c_str(), link_resolved.get()) == nullptr) { LOG(DEBUG, "nonresolved: \"{}\"", resolved); return make_pair(false, resolved); } else { resolved = link_resolved.get(); LOG(DEBUG, "external: \"{}\"", resolved); return make_pair(false, resolved); } } /** Resolve path to its canonical representation * Loading Loading
src/client/gkfs_libc.cpp +198 −41 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ std::atomic<bool> initializing{false}; // Define a debug macro, can be easily disabled // #define GKFS_TRACE #define PATH_SHORTCUT // #define PATH_SHORTCUT #ifdef GKFS_DEBUG_BUILD #ifdef GKFS_TRACE Loading Loading @@ -155,6 +155,23 @@ log_argumentsx(const char* symbol, Args&&... args) { return real_##func_name args; \ } #define NOLOGDLSYM_WRAPPER(return_type, func_name, params, args, symbol_name) \ static return_type(*real_##func_name) params = nullptr; \ return_type dlsym_##func_name params { \ if(!real_##func_name) { \ real_##func_name = reinterpret_cast<return_type(*) params>( \ dlsym(RTLD_NEXT, symbol_name)); \ if(!real_##func_name) { \ fprintf(stderr, "dlsym failed for %s: %s\n", symbol_name, \ dlerror()); \ errno = ENOSYS; /* Set errno to ENOSYS to indicate function \ not supported */ \ return (return_type) - 1; /* Return error value */ \ } \ } \ return real_##func_name args; \ } #define CDLSYM_WRAPPER(return_type, func_name, params, args, symbol_name) \ static return_type(*real_##func_name) params = nullptr; \ Loading Loading @@ -225,10 +242,15 @@ DLSYM_WRAPPER(int, fxstat64, (int ver, int fd, struct stat64* buf), (ver, fd, buf), "__fxstat64") DLSYM_WRAPPER(int, lstat, (int ver, const char* path, struct stat* buf), (ver, path, buf), "__lxstat") DLSYM_WRAPPER(int, lstat64, (const char* path, struct stat64* buf), (path, buf), "lstat64") DLSYM_WRAPPER(int, stat, (int ver, const char* path, struct stat* buf), (ver, path, buf), "__xstat") DLSYM_WRAPPER(int, fstat, (int ver, int fd, struct stat* buf), (ver, fd, buf), "__fxstat") DLSYM_WRAPPER(int, __fxstat, (int ver, int fd, struct stat* buf), (ver, fd, buf), "__fxstat") DLSYM_WRAPPER(int, fstat, (int fd, struct stat* buf), (fd, buf), "fstat") DLSYM_WRAPPER(int, fstat64, (int fd, struct stat64* buf), (fd, buf), "fstat64") DLSYM_WRAPPER(int, fxstatat, (int ver, int dfd, const char* path, struct stat* buf, int flags), Loading Loading @@ -333,15 +355,34 @@ DLSYM_WRAPPER(void, rewind, (FILE * stream), (stream), "rewind") DLSYM_WRAPPER(int, feof, (FILE * stream), (stream), "feof") DLSYM_WRAPPER(int, fputs, (const char* str, FILE* stream), (str, stream), "fputs") DLSYM_WRAPPER(char*, fgets, (char* str, int n, FILE* stream), (str, n, stream), "fgets") DLSYM_WRAPPER(int, fflush, (FILE * stream), (stream), "fflush") NOLOGDLSYM_WRAPPER(char*, fgets, (char* str, int n, FILE* stream), (str, n, stream), "fgets") NOLOGDLSYM_WRAPPER(int, fflush, (FILE * stream), (stream), "fflush") DLSYM_WRAPPER(int, fchown, (int fd, uid_t owner, gid_t group), (fd, owner, group), "fchown") DLSYM_WRAPPER(int, futimes, (int fd, const struct timeval times[2]), (fd, times), "futimes") DLSYM_WRAPPER(int, utimes, (const char* path, const struct timeval times[2]), (path, times), "utimes") // listxattr DLSYM_WRAPPER(ssize_t, listxattr, (const char* path, char* list, size_t size), (path, list, size), "listxattr") DLSYM_WRAPPER(ssize_t, llistxattr, (const char* path, char* list, size_t size), (path, list, size), "llistxattr") DLSYM_WRAPPER(ssize_t, flistxattr, (int fd, char* list, size_t size), (fd, list, size), "flistxattr") //DLSYM_WRAPPER(long, syscall, (long number, char* cmd, void* arg, void* env), // (number, cmd, arg, env), "syscall") DLSYM_WRAPPER(DIR*, fdopendir, (int fd), (fd), "fdopendir") DLSYM_WRAPPER(int, scandir, (const char* dirp, struct dirent*** namelist, typeof(int(const struct dirent*))* filter, typeof(int(const struct dirent**, const struct dirent**))* compar), (dirp, namelist, filter, compar), "scandir") /*CDLSYM_WRAPPER(ssize_t, readlink, (const char* path, char* buf, size_t bufsize), (path, buf, bufsize), "readlink") Loading Loading @@ -377,23 +418,7 @@ argv[]), (filename, argv), "execvp") DLSYM_WRAPPER(long, syscall, (long number, char* cmd, void* arg, void* env), (number, cmd, arg, env), "syscall") long syscall(long number, ...) { if(number == SYS_execve or number == SYS_execveat) { DEBUG_INFO("execve {}", number); } va_list myargs; va_start(myargs, number); auto res = syscall_no_intercept_wrapper(number, myargs); va_end(myargs); return res; } */ /* not used */ /*static void Loading Loading @@ -811,10 +836,11 @@ unlink(const char* path) { int __xstat(int ver, const char* path, struct stat* buf) { GKFS_PATH_OPERATION(stat, AT_FDCWD, path, buf) auto res = dlsym_stat(_STAT_VER, path, buf); auto res = dlsym_stat(ver, path, buf); return res; } int __xstat64(int ver, const char* path, struct stat64* buf) { struct stat st; Loading @@ -835,7 +861,7 @@ __xstat64(int ver, const char* path, struct stat64* buf) { } } } auto res = dlsym_stat(_STAT_VER, path, &st); auto res = dlsym_stat(ver, path, &st); convert(&st, buf); return res; } Loading Loading @@ -910,7 +936,7 @@ __fxstat(int ver, int fd, struct stat* buf) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); return gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), buf); } GKFS_FALLBACK(fstat, ver, fd, buf); GKFS_FALLBACK(__fxstat, ver, fd, buf); } int Loading Loading @@ -950,6 +976,17 @@ fstat64(int fd, struct stat64* buf) { GKFS_FALLBACK(fstat64, fd, buf); } int fstat(int fd, struct stat* buf) { initializeGekko(); if(is_gkfs_fd(fd)) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); int res = gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), buf); return res; } GKFS_FALLBACK(fstat, fd, buf); } int __fxstatat64(int ver, int dfd, const char* path, struct stat64* buf, Loading Loading @@ -1008,16 +1045,6 @@ stat64(const char* path, struct stat64* buf) { return ret; } int fstat(int fd, struct stat* buf) { initializeGekko(); if(is_gkfs_fd(fd)) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); return gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), buf); } GKFS_FALLBACK(fstat, _STAT_VER, fd, buf); } int fstatat(int dfd, const char* path, struct stat* buf, int flags) { initializeGekko(); Loading Loading @@ -1182,19 +1209,21 @@ chdir(const char* path) { initializeGekko(); // is the path from gekkofs // return gkfs::hook::hook_chdir(path); if(CTX->interception_enabled()) { std::string resolved; auto rstatus = CTX->relativize_fd_path(AT_FDCWD, path, resolved); DEBUG_INFO("[GKFS] chdir status {} {} --> {}", (int) rstatus, resolved, path); switch(rstatus) { case gkfs::preload::RelativizeStatus::fd_not_a_dir: return -ENOTDIR; case gkfs::preload::RelativizeStatus::internal: DEBUG_INFO("[GKFS] NOT IMPLEMENTED {}", path); return gkfs::hook::hook_chdir(path); break; default: Loading @@ -1202,7 +1231,7 @@ chdir(const char* path) { break; } } CTX->cwd(path); GKFS_FALLBACK(chdir, const_cast<char*>(path)); } Loading Loading @@ -1390,6 +1419,19 @@ opendir64(const char* dirname) { return dlsym_opendir64(const_cast<char*>(dirname)); } DIR* fdopendir(int fd) { if(CTX->interception_enabled()) { if(is_gkfs_fd(fd)) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); return gekko_opendir(CTX->file_map()->get(fd)->path()); } } GKFS_FALLBACK(fdopendir, fd); } // clang-format off #ifndef __ALIGN_KERNEL_MASK Loading Loading @@ -1748,7 +1790,7 @@ fgets(char* str, int n, FILE* stream) { GKFS_FALLBACK(fgets, str, n, stream) } // implement fflush and bypass if gekko // implement fflush and bypass if gekko (no need to log) int fflush(FILE* stream) { initializeGekko(); Loading @@ -1756,7 +1798,7 @@ fflush(FILE* stream) { // flush stream with gkfs_fsync return 0; } GKFS_FALLBACK(fflush, stream) return dlsym_fflush(stream); } Loading Loading @@ -1870,3 +1912,118 @@ utimes(const char* path, const struct timeval tv[2]) { } GKFS_FALLBACK(utimes, path, tv); } // Without use... goes directly to the syscall (ls -l) ssize_t listxattr(const char* path, char* list, size_t size) { initializeGekko(); if(CTX->interception_enabled()) { std::string resolved; if(resolve_gkfs_path(AT_FDCWD, path, resolved) == PathStatus::Internal) { DEBUG_INFO("[GKFS] {}", resolved); return 0; } } GKFS_FALLBACK(listxattr, path, list, size); } ssize_t flistxattr(int fd, char* list, size_t size) { initializeGekko(); if(is_gkfs_fd(fd)) { DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path()); return 0; } GKFS_FALLBACK(flistxattr, fd, list, size); } ssize_t llistxattr(const char* path, char* list, size_t size) { initializeGekko(); return 0; if(CTX->interception_enabled()) { std::string resolved; if(resolve_gkfs_path(AT_FDCWD, path, resolved) == PathStatus::Internal) { DEBUG_INFO("[GKFS] {}", resolved); return 0; } } GKFS_FALLBACK(llistxattr, path, list, size); } int lstat64(const char* path, struct stat64* buf) { initializeGekko(); if(CTX->interception_enabled()) { std::string resolved; struct stat st; if(resolve_gkfs_path(AT_FDCWD, path, resolved) == PathStatus::Internal) { DEBUG_INFO("[GKFS] {}", resolved); auto res = gkfs::syscall::gkfs_stat(resolved, &st); convert(&st, buf); return res; } } GKFS_FALLBACK(lstat64, path, buf); } int scandir(const char* dirname, struct dirent*** namelist, int (*filter)(const struct dirent*), int (*compar)(const struct dirent**, const struct dirent**)) { initializeGekko(); if(CTX->interception_enabled()) { std::string resolved; if(resolve_gkfs_path(AT_FDCWD, dirname, resolved) == PathStatus::Internal) { DEBUG_INFO("[GKFS] {}", resolved); // implement scandir : The scandir() function scans the directory // dirp, calling filter() on each directory entry. Entries for // which filter() returns nonzero are stored in strings allocated // via malloc(3), sorted using qsort(3) with the comparison function // compar(), and collected in // array namelist which is allocated via malloc(3). If filter // is NULL, all entries are selected. DIR* dirp = gekko_opendir(resolved); if(dirp == nullptr) { return -1; } std::vector<struct dirent*> entries; struct dirent* entry; while((entry = readdir(dirp)) != nullptr) { if(filter == nullptr || filter(entry) != 0) { entries.push_back(entry); } } closedir(dirp); if(entries.empty()) { *namelist = nullptr; return 0; } if(compar != nullptr) { qsort(entries.data(), entries.size(), sizeof(struct dirent*), reinterpret_cast<int (*)(const void*, const void*)>( compar)); } *namelist = static_cast<struct dirent**>( malloc(sizeof(struct dirent*) * (entries.size() + 1))); if(*namelist == nullptr) { for(auto e : entries) { free(e); } return -1; } for(size_t i = 0; i < entries.size(); ++i) { (*namelist)[i] = entries[i]; } (*namelist)[entries.size()] = nullptr; return entries.size(); } } GKFS_FALLBACK(scandir, dirname, namelist, filter, compar); }
src/client/path.cpp +14 −2 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ extern "C" { #include <sys/stat.h> #include <dlfcn.h> } using namespace std; Loading Loading @@ -208,9 +209,20 @@ resolve_new(const string& path, bool resolve_last_link) { if(resolved.empty()) { resolved.push_back(path::separator); } // TODO: redo auto real = reinterpret_cast<char* (*) (const char* path, char* resolved_path)>( dlsym(((void*) -1l), "realpath")); auto link_resolved = ::unique_ptr<char[]>(new char[PATH_MAX]); if(real(path.c_str(), link_resolved.get()) == nullptr) { LOG(DEBUG, "nonresolved: \"{}\"", resolved); return make_pair(false, resolved); } else { resolved = link_resolved.get(); LOG(DEBUG, "external: \"{}\"", resolved); return make_pair(false, resolved); } } /** Resolve path to its canonical representation * Loading