Loading include/client/adafs_functions.hpp +3 −1 Original line number Diff line number Diff line Loading @@ -65,7 +65,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 include/client/hooks.hpp +1 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,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 include/client/open_dir.hpp +11 −14 Original line number Diff line number Diff line Loading @@ -23,28 +23,25 @@ #include <client/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 src/client/adafs_functions.cpp +61 −8 Original line number Diff line number Diff line Loading @@ -23,6 +23,20 @@ #include <client/rpc/ld_rpc_data_ws.hpp> #include <client/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 @@ -506,17 +520,56 @@ 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; } return open_dir->readdir(); 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; } open_dir->pos(pos); return written; } #ifdef HAS_SYMLINKS Loading src/client/hooks.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -181,3 +181,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
include/client/adafs_functions.hpp +3 −1 Original line number Diff line number Diff line Loading @@ -65,7 +65,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
include/client/hooks.hpp +1 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,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
include/client/open_dir.hpp +11 −14 Original line number Diff line number Diff line Loading @@ -23,28 +23,25 @@ #include <client/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
src/client/adafs_functions.cpp +61 −8 Original line number Diff line number Diff line Loading @@ -23,6 +23,20 @@ #include <client/rpc/ld_rpc_data_ws.hpp> #include <client/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 @@ -506,17 +520,56 @@ 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; } return open_dir->readdir(); 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; } open_dir->pos(pos); return written; } #ifdef HAS_SYMLINKS Loading
src/client/hooks.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -181,3 +181,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); }