Commit 9a2a38f5 authored by Ramon Nou's avatar Ramon Nou
Browse files

Add fstat64 and open64 functions; enhance close_range and fd management

parent efdbca69
Loading
Loading
Loading
Loading
+127 −20
Original line number Diff line number Diff line
@@ -188,6 +188,8 @@ 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, fstat64, ( int fd,struct stat64* buf), ( fd, buf),
              "__fxstat64")
DLSYM_WRAPPER(int, fxstatat,
              (int ver, int dfd, const char* path, struct stat* buf, int flags),
              (ver, dfd, path, buf, flags), "__fxstatat")
@@ -329,7 +331,7 @@ resolve_gkfs_path(int dirfd, const char* path, std::string& resolved,
    auto res = std::mismatch(CTX->mountdir().begin(), CTX->mountdir().end(),
                             std::string(path).begin());

    if(res.first != CTX->mountdir().end()) {
    if(res.first != CTX->mountdir().end() and dirfd==AT_FDCWD) {
        return PathStatus::External;
    }

@@ -433,6 +435,16 @@ open64(const char* path, int flags, ...) {
    GKFS_FALLBACK(open64, const_cast<char*>(path), flags, mode)
}

int
open64(const char* path, int flags, mode_t mode) {
   

    initializeGekko();
    GKFS_PATH_OPERATION(open, AT_FDCWD, path, mode, flags)
    GKFS_FALLBACK(open64, const_cast<char*>(path), flags, mode)
}



int
openat(int dirfd, const char* path, int flags, ...) {
@@ -465,24 +477,94 @@ close(int fd) {
    GKFS_FALLBACK(close, fd);
}


std::vector<int>
get_open_fds() {
    std::vector<int> fds;
    const std::string fd_path = "/proc/self/fd";

    DIR* dir = dlsym_opendir(fd_path.c_str());
    if(!dir) {
        perror("opendir() failed");
        return fds;
    }

    struct dirent* entry;
    while((entry = dlsym_readdir(dir))) {
        // Skip "." and ".." entries
        if(entry->d_type == DT_DIR)
            continue;

        try {
            int fd = std::stoi(entry->d_name);
            // Skip the directory FD itself
            if(fd != dirfd(dir)) {
                fds.push_back(fd);
            }
        } catch(const std::exception&) {
            // Ignore non-integer entries
        }
    }

    dlsym_closedir(dir);

    fds.erase(std::remove_if(fds.begin(), fds.end(),
                             [](int fd) { return fcntl(fd, F_GETFD) < 0; }),
              fds.end());

    return fds;
}


int
close_range(unsigned low, unsigned high, int flags) {

    LOG(DEBUG, "close_range({}, {}, {})", low, high, flags);
    //return 0;
    auto fds = get_open_fds();
    if(flags & CLOSE_RANGE_UNSHARE) {
        // Unshare the file descriptor table
        LOG(DEBUG, "close_range with CLOSE_RANGE_UNSHARE");
        if(unshare(CLONE_FILES) == -1) {
            perror("unshare() failed");
            return -1;
        }
    }
    if(flags & CLOSE_RANGE_CLOEXEC) {
        // Close all file descriptors in the range
        LOG(DEBUG, "close_range with CLOSE_RANGE_CLOEXEC");
    }
    // Is fd from gekkofs ?
    initializeGekko();
    if(CTX->interception_enabled()) {
        for(unsigned int i = low; i <= high; i++) {
            if(i > GKFS_MAX_OPEN_FDS)
                break;
        for(unsigned int i : fds) {
            if(i < low || i > high)
                continue;

            if(is_gkfs_fd(i)) {
                LOG_DEBUG("[GKFS] Closing fd {}", i);
                gkfs::syscall::gkfs_close(i);
            } else {
                LOG_DEBUG("[NONGKFS] Closing fd {}", i);
                close(i);
            }
        }
        // Fall back to close the original range (it may not be a good idea)
        return 0;
    } else {

        std::cout << "Not in gekko: close_range" << std::endl;
        for(unsigned int i : fds) {
            if(i < low || i > high)
                continue;

            std::cout << "Not in gekko: close_range " << i << std::endl;
            close(i);
        }
    GKFS_FALLBACK(close_range, low, high, flags);
    }
    // We are not in gekko just do it...
    // GKFS_FALLBACK(close_range, low, high, flags);
    return 0;
}


int
creat(const char* path, mode_t mode) {
@@ -752,7 +834,7 @@ stat64(const char* path, struct stat64* buf) {
        std::string resolved;
        switch(resolve_gkfs_path(AT_FDCWD, path, resolved)) {
            case PathStatus::Internal: {
                LOG(DEBUG, "[GKFS] {}", CTX->file_map()->get(fd)->path());
                LOG(DEBUG, "[GKFS] {}", resolved);
                auto res = gkfs::syscall::gkfs_stat(resolved, &st);
                convert(&st, buf);
                return res;
@@ -787,7 +869,7 @@ fstatat(int dfd, const char* path, struct stat* buf, int flags) {
        std::string resolved;
        switch(resolve_gkfs_path(dfd, path, resolved)) {
            case PathStatus::Internal: {
                LOG(DEBUG, "[GKFS] {}", CTX->file_map()->get(fd)->path());
                LOG(DEBUG, "[GKFS] {}", resolved);
                auto res = gkfs::syscall::gkfs_stat(resolved, buf);
                return res;
            }
@@ -866,13 +948,12 @@ fork(void) {
int
pipe(int pipefd[2]) {
    initializeGekko();
    if(is_gkfs_fd(pipefd[0])) {
        LOG(DEBUG, "[GKFS] 0 {}", pipefd[0]);
    }
    if(is_gkfs_fd(pipefd[1])) {
        LOG(DEBUG, "[GKFS] 1 {}", pipefd[1]);
    }
    GKFS_FALLBACK(pipe, pipefd);
    
    auto res = dlsym_pipe(pipefd);
    LOG(DEBUG, "pipe {} <---> {}", pipefd[0], pipefd[1]);

    // GKFS_FALLBACK(pipe, pipefd);
    return res;
}

int
@@ -885,7 +966,20 @@ dup(int fd) {
int
dup2(int fd, int fd2) {
    initializeGekko();
    GKFS_OPERATION(dup2, fd, fd2);
    if(is_gkfs_fd(fd) && is_gkfs_fd(fd2)) {
        LOG(DEBUG, "[GKFS] DUP2 G{} --> G{}", fd, fd2);
        return gkfs::syscall::gkfs_dup2(fd, fd2);
    }else
    if(is_gkfs_fd(fd2)) {
        LOG(DEBUG, "[GKFS-NON] DUP2 {} --> G{}", fd, fd2);
        return gkfs::syscall::gkfs_dup(fd);
    }else
    if(is_gkfs_fd(fd)) {
        LOG(DEBUG, "[GKFS-NON] DUP2 G{} --> {}", fd, fd2);
        return gkfs::syscall::gkfs_dup2(fd, fd2);
    }

    //GKFS_OPERATION(dup2, fd, fd2);
    GKFS_FALLBACK(dup2, fd, fd2);
}

@@ -1032,7 +1126,7 @@ realpath(const char* path, char* resolved_path) {
                return nullptr;

            case gkfs::preload::RelativizeStatus::internal:
                LOG(DEBUG, "[GKFS] {}", resolved);
                LOG(DEBUG, "[GKFS] {} --> {}", resolved, path);
                if(resolved_path == nullptr) {
                    resolved_path =
                            static_cast<char*>(malloc(resolved.size() + 1));
@@ -1287,8 +1381,21 @@ fdopen(int fd, const char* mode) {

    if(CTX->interception_enabled()) {
        if(is_gkfs_fd(fd)) {
            FILE* ret;
            ret = dlsym_fopen("/dev/null", mode);
            FILE* ret = static_cast<FILE*>(malloc(sizeof(FILE)));
            if(ret == NULL) {
                errno = ENOMEM;
                return NULL;
            }
            ret->_mode = 0666;
            ret->_flags = 0;
            if(strchr(mode, 'r') != NULL)
                ret->_flags |= O_RDONLY;
            if(strchr(mode, 'w'))
                ret->_flags = O_WRONLY | O_CREAT | O_TRUNC;
            if(strchr(mode, 'a'))
                ret->_flags = O_WRONLY | O_CREAT | O_APPEND;
            if(strchr(mode, '+'))
                ret->_flags = O_RDWR | O_CREAT;
            ret->_fileno = fd;
            return ret;
        }