Unverified Commit 31c180d3 authored by Ramon Nou's avatar Ramon Nou Committed by Tommaso Tocci
Browse files

getdents64 implemented

parent 0b62cb45
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -69,6 +69,10 @@ int getdents(unsigned int fd,
             struct linux_dirent *dirp,
             unsigned int count);

int getdents64(unsigned int fd,
             struct linux_dirent64 *dirp,
             unsigned int count);

int adafs_rmdir(const std::string& path);

#endif //IFS_ADAFS_FUNCTIONS_HPP
+1 −1
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
#include <fcntl.h>
#include <sys/types.h>


int hook_openat(int dirfd, const char *cpath, int flags, mode_t mode);
int hook_close(int fd);
int hook_stat(const char* path, struct stat* buf);
@@ -42,6 +41,7 @@ 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);
int hook_getdents64(unsigned int fd, struct linux_dirent64 *dirp, unsigned int count);
int hook_mkdirat(int dirfd, const char * cpath, mode_t mode);
int hook_fchmodat(int dirfd, const char* path, mode_t mode);
int hook_fchmod(unsigned int dirfd, mode_t mode);
+61 −2
Original line number Diff line number Diff line
@@ -23,8 +23,6 @@
#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)
@@ -37,6 +35,14 @@ struct linux_dirent {
    char		d_name[1];
};

struct linux_dirent64 {
    unsigned long long  d_ino;
    unsigned long long  d_off;
    unsigned short  d_reclen;
    unsigned char d_type;
    char        d_name[1];
};

using namespace std;

int adafs_open(const std::string& path, mode_t mode, int flags) {
@@ -572,6 +578,59 @@ int getdents(unsigned int fd,
    return written;
}


int getdents64(unsigned int fd,
             struct linux_dirent64 *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 -1;
    }

    auto pos = open_dir->pos();
    if (pos >= open_dir->size()) {
        return 0;
    }

    unsigned int written = 0;
    struct linux_dirent64 * current_dirp = nullptr;
    while(pos < open_dir->size()) {
        DirEntry de = open_dir->getdent(pos);
        auto total_size = ALIGN(offsetof(struct linux_dirent64, 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_dirent64 *>(
                        reinterpret_cast<char*>(dirp) + written);
        current_dirp->d_ino = std::hash<std::string>()(
                open_dir->path() + "/" + de.name());

        current_dirp->d_reclen = total_size;
        current_dirp->d_type =  ((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

int adafs_mk_symlink(const std::string& path, const std::string& target_path) {
+10 −0
Original line number Diff line number Diff line
@@ -347,6 +347,16 @@ int hook_getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count
    return syscall_no_intercept(SYS_getdents, fd, dirp, count);
}


int hook_getdents64(unsigned int fd, struct linux_dirent64 *dirp, unsigned int count) {
    CTX->log()->trace("{}() called with fd {}, count {}", __func__, fd, count);
    if (CTX->file_map()->exist(fd)) {
        return with_errno(getdents64(fd, dirp, count));
    }
    return syscall_no_intercept(SYS_getdents64, fd, dirp, count);
}


int hook_mkdirat(int dirfd, const char * cpath, mode_t mode) {
    CTX->log()->trace("{}() called with fd: {}, path: {}, mode: {}",
                      __func__, dirfd, cpath, mode);
+7 −0
Original line number Diff line number Diff line
@@ -201,6 +201,13 @@ static inline int hook(long syscall_number,
                                static_cast<unsigned int>(arg2));
        break;

    case SYS_getdents64:
        *result = hook_getdents64(static_cast<unsigned int>(arg0),
                                reinterpret_cast<struct linux_dirent64 *>(arg1),
                                static_cast<unsigned int>(arg2));
        break;


    case SYS_mkdirat:
        *result = hook_mkdirat(static_cast<unsigned int>(arg0),
                               reinterpret_cast<const char *>(arg1),