Loading ifs/include/preload/adafs_functions.hpp +3 −1 Original line number Diff line number Diff line Loading @@ -69,7 +69,9 @@ ssize_t adafs_read(int fd, void* buf, size_t count); int adafs_opendir(const std::string& path); struct dirent * adafs_readdir(int fd); int getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count); int adafs_rmdir(const std::string& path); Loading ifs/include/preload/hooks.hpp +1 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ int hook_lseek(unsigned int fd, off_t offset, unsigned int whence); int hook_dup(unsigned int fd); int hook_dup2(unsigned int oldfd, unsigned int newfd); int hook_dup3(unsigned int oldfd, unsigned int newfd, int flags); int hook_getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count); #endif ifs/include/preload/open_dir.hpp +11 −14 Original line number Diff line number Diff line Loading @@ -10,28 +10,25 @@ #include <preload/open_file_map.hpp> class OpenDir: public OpenFile { private: class DirEntry { private: std::string name_; FileType type_; public: std::string name; FileType type; DirEntry(const std::string& name, const FileType type); const std::string& name(); FileType type(); }; class OpenDir: public OpenFile { private: std::vector<DirEntry> entries; struct dirent dirent_; bool is_dirent_valid; void update_dirent(unsigned int pos); public: OpenDir(const std::string& path); void add(const std::string& name, const FileType& type); struct dirent * readdir(); const DirEntry& getdent(unsigned int pos); size_t size(); }; Loading ifs/src/preload/adafs_functions.cpp +62 −8 Original line number Diff line number Diff line Loading @@ -8,6 +8,20 @@ #include <preload/rpc/ld_rpc_data_ws.hpp> #include <preload/open_dir.hpp> #include <dirent.h> #define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) #define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1) #define ALIGN(x, a) __ALIGN_KERNEL((x), (a)) struct linux_dirent { unsigned long d_ino; unsigned long d_off; unsigned short d_reclen; char d_name[1]; }; using namespace std; int adafs_open(const std::string& path, mode_t mode, int flags) { Loading Loading @@ -469,15 +483,55 @@ int adafs_rmdir(const std::string& path) { return rpc_send_rm_node(path, true); } struct dirent * adafs_readdir(int fd){ CTX->log()->trace("{}() called on fd: {}", __func__, fd); auto open_file = CTX->file_map()->get(fd); assert(open_file != nullptr); auto open_dir = static_pointer_cast<OpenDir>(open_file); if(!open_dir){ int getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count) { CTX->log()->trace("{}() called on fd: {}, count {}", __func__, fd, count); auto open_dir = CTX->file_map()->get_dir(fd); if(open_dir == nullptr){ //Cast did not succeeded: open_file is a regular file errno = EBADF; return nullptr; return -1; } auto pos = open_dir->pos(); if (pos >= open_dir->size()) { return 0; } unsigned int written = 0; struct linux_dirent * current_dirp = nullptr; while(pos < open_dir->size()) { DirEntry de = open_dir->getdent(pos); auto total_size = ALIGN(offsetof(struct linux_dirent, d_name) + de.name().size() + 3, sizeof(long)); if (total_size > (count - written)) { //no enough space left on user buffer to insert next dirent break; } current_dirp = reinterpret_cast<struct linux_dirent *>( reinterpret_cast<char*>(dirp) + written); current_dirp->d_ino = std::hash<std::string>()( open_dir->path() + "/" + de.name()); current_dirp->d_reclen = total_size; *(reinterpret_cast<char*>(current_dirp) + total_size - 1) = ((de.type() == FileType::regular)? DT_REG : DT_DIR); CTX->log()->trace("{}() name {}: {}", __func__, pos, de.name()); std::strcpy(&(current_dirp->d_name[0]), de.name().c_str()); ++pos; current_dirp->d_off = pos; written += total_size; } if (written == 0) { errno = EINVAL; return -1; } return open_dir->readdir(); open_dir->pos(pos); return written; } No newline at end of file ifs/src/preload/hooks.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -168,3 +168,11 @@ int hook_dup3(unsigned int oldfd, unsigned int newfd, int flags) { } return syscall_no_intercept(SYS_dup3, oldfd, newfd, flags); } int hook_getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count) { CTX->log()->trace("{}() called with fd {}, count {}", __func__, fd, count); if (CTX->file_map()->exist(fd)) { return with_errno(getdents(fd, dirp, count)); } return syscall_no_intercept(SYS_getdents, fd, dirp, count); } Loading
ifs/include/preload/adafs_functions.hpp +3 −1 Original line number Diff line number Diff line Loading @@ -69,7 +69,9 @@ ssize_t adafs_read(int fd, void* buf, size_t count); int adafs_opendir(const std::string& path); struct dirent * adafs_readdir(int fd); int getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count); int adafs_rmdir(const std::string& path); Loading
ifs/include/preload/hooks.hpp +1 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ int hook_lseek(unsigned int fd, off_t offset, unsigned int whence); int hook_dup(unsigned int fd); int hook_dup2(unsigned int oldfd, unsigned int newfd); int hook_dup3(unsigned int oldfd, unsigned int newfd, int flags); int hook_getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count); #endif
ifs/include/preload/open_dir.hpp +11 −14 Original line number Diff line number Diff line Loading @@ -10,28 +10,25 @@ #include <preload/open_file_map.hpp> class OpenDir: public OpenFile { private: class DirEntry { private: std::string name_; FileType type_; public: std::string name; FileType type; DirEntry(const std::string& name, const FileType type); const std::string& name(); FileType type(); }; class OpenDir: public OpenFile { private: std::vector<DirEntry> entries; struct dirent dirent_; bool is_dirent_valid; void update_dirent(unsigned int pos); public: OpenDir(const std::string& path); void add(const std::string& name, const FileType& type); struct dirent * readdir(); const DirEntry& getdent(unsigned int pos); size_t size(); }; Loading
ifs/src/preload/adafs_functions.cpp +62 −8 Original line number Diff line number Diff line Loading @@ -8,6 +8,20 @@ #include <preload/rpc/ld_rpc_data_ws.hpp> #include <preload/open_dir.hpp> #include <dirent.h> #define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) #define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1) #define ALIGN(x, a) __ALIGN_KERNEL((x), (a)) struct linux_dirent { unsigned long d_ino; unsigned long d_off; unsigned short d_reclen; char d_name[1]; }; using namespace std; int adafs_open(const std::string& path, mode_t mode, int flags) { Loading Loading @@ -469,15 +483,55 @@ int adafs_rmdir(const std::string& path) { return rpc_send_rm_node(path, true); } struct dirent * adafs_readdir(int fd){ CTX->log()->trace("{}() called on fd: {}", __func__, fd); auto open_file = CTX->file_map()->get(fd); assert(open_file != nullptr); auto open_dir = static_pointer_cast<OpenDir>(open_file); if(!open_dir){ int getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count) { CTX->log()->trace("{}() called on fd: {}, count {}", __func__, fd, count); auto open_dir = CTX->file_map()->get_dir(fd); if(open_dir == nullptr){ //Cast did not succeeded: open_file is a regular file errno = EBADF; return nullptr; return -1; } auto pos = open_dir->pos(); if (pos >= open_dir->size()) { return 0; } unsigned int written = 0; struct linux_dirent * current_dirp = nullptr; while(pos < open_dir->size()) { DirEntry de = open_dir->getdent(pos); auto total_size = ALIGN(offsetof(struct linux_dirent, d_name) + de.name().size() + 3, sizeof(long)); if (total_size > (count - written)) { //no enough space left on user buffer to insert next dirent break; } current_dirp = reinterpret_cast<struct linux_dirent *>( reinterpret_cast<char*>(dirp) + written); current_dirp->d_ino = std::hash<std::string>()( open_dir->path() + "/" + de.name()); current_dirp->d_reclen = total_size; *(reinterpret_cast<char*>(current_dirp) + total_size - 1) = ((de.type() == FileType::regular)? DT_REG : DT_DIR); CTX->log()->trace("{}() name {}: {}", __func__, pos, de.name()); std::strcpy(&(current_dirp->d_name[0]), de.name().c_str()); ++pos; current_dirp->d_off = pos; written += total_size; } if (written == 0) { errno = EINVAL; return -1; } return open_dir->readdir(); open_dir->pos(pos); return written; } No newline at end of file
ifs/src/preload/hooks.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -168,3 +168,11 @@ int hook_dup3(unsigned int oldfd, unsigned int newfd, int flags) { } return syscall_no_intercept(SYS_dup3, oldfd, newfd, flags); } int hook_getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count) { CTX->log()->trace("{}() called with fd {}, count {}", __func__, fd, count); if (CTX->file_map()->exist(fd)) { return with_errno(getdents(fd, dirp, count)); } return syscall_no_intercept(SYS_getdents, fd, dirp, count); }