Commit 7196453f authored by Ramon Nou's avatar Ramon Nou
Browse files

File ops fast implementation

parent 7c234aa7
Loading
Loading
Loading
Loading
+280 −0
Original line number Diff line number Diff line
@@ -114,6 +114,17 @@ int (*real_flock)(int, int) = NULL;
void* (*real_mmap)(void*, size_t, int, int, int, off_t) = NULL;
int (*real_clone)(int(void*), void*, int, void*, pid_t*, void*, pid_t*) = NULL;

// fILE ops
FILE* (*real_fopen)(const char*, const char*) = NULL;
FILE* (*real_fdopen)(int, const char*) = NULL;
int (*real_fclose)(FILE*) = NULL;
size_t (*real_fread)(void*, size_t, size_t, FILE*) = NULL;
size_t (*real_fwrite)(const void*, size_t, size_t, FILE*) = NULL;
int (*real_fseek)(FILE*, long int, int) = NULL;
long (*real_ftell)(FILE*) = NULL;
void (*real_rewind)(FILE*) = NULL;
int (*real_feof)(FILE*) = NULL;

void
initializeGekko() {
    // if the activated is false call init
@@ -877,6 +888,106 @@ dlsym_mmap(void* addr, size_t length, int prot, int flags, int fd,
}


// FILE operations
// File API (stdio)
FILE*
dlsym_fopen(const char* filename, const char* mode){
    if(real_fopen == NULL) {
        real_fopen = (FILE* (*)(const char*, const char*)) dlsym(RTLD_NEXT, "fopen");
    }

    FILE* ret = real_fopen(filename, mode);

    return ret;

}
FILE*
dlsym_fdopen(int fd, const char* mode) {
    if(real_fdopen == NULL) {
        real_fdopen = (FILE* (*)(int, const char*)) dlsym(RTLD_NEXT, "fdopen");
    }

    FILE* ret = real_fdopen(fd, mode);

    return ret;

}

int
dlsym_fclose(FILE* stream) {
    if(real_fclose == NULL) {
        real_fclose = (int (*)(FILE*)) dlsym(RTLD_NEXT, "fclose");
    }

    int ret = real_fclose(stream);

    return ret;
}

size_t
dlsym_fread(void* ptr, size_t size, size_t nmemb, FILE* stream){
    if(real_fread == NULL) {
        real_fread = (size_t (*)(void*, size_t, size_t, FILE*)) dlsym(RTLD_NEXT, "fread");
        }

    size_t ret = real_fread(ptr, size, nmemb, stream);

    return ret;
}
size_t
dlsym_fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream){
    if(real_fwrite == NULL) {
        real_fwrite = (size_t (*)(const void*, size_t, size_t, FILE*)) dlsym(RTLD_NEXT, "fwrite");
    }

    size_t ret = real_fwrite(ptr, size, nmemb, stream);

    return ret;

}

int
dlsym_fseek(FILE* stream, long int offset, int whence){
    if(real_fseek == NULL) {
        real_fseek = (int (*)(FILE*, long int, int)) dlsym(RTLD_NEXT, "fseek");
    }

    int ret = real_fseek(stream, offset, whence);

    return ret;

}
long
dlsym_ftell(FILE* stream){
    if(real_ftell == NULL) {
        real_ftell = (long (*)(FILE*)) dlsym(RTLD_NEXT, "ftell");
    }

    long ret = real_ftell(stream);

    return ret;

}
void
dlsym_rewind(FILE* stream){
    if(real_rewind == NULL) {
        real_rewind = (void (*)(FILE*)) dlsym(RTLD_NEXT, "rewind");
    }

    real_rewind(stream);
}

int
dlsym_feof(FILE* stream){
    if(real_feof == NULL) {
        real_feof = (int (*)(FILE*)) dlsym(RTLD_NEXT, "feof");
    }

    int ret = real_feof(stream);

    return ret;
}

/**
 * stat management
 */
@@ -2451,3 +2562,172 @@ getdents64(int fd, struct dirent64* dirp, unsigned int count) {
    return ret;
}
*/

// File ops

FILE*
fdopen(int fd, const char* mode) {
    initializeGekko();
    FILE* ret;
    if(CTX->interception_enabled()) {
        if(CTX->file_map()->exist(fd)) {
            ret = (FILE*) malloc(sizeof(FILE));
            ret->_flags = 0;
            ret->_IO_read_ptr = 0;
            ret->_IO_read_end = 0;
            ret->_IO_read_base = 0;
            ret->_IO_write_base = 0;
            ret->_IO_write_ptr = 0;
            ret->_IO_write_end = 0;
            ret->_IO_buf_base = 0;
            ret->_IO_buf_end = 0;
            ret->_IO_save_base = 0;
            ret->_IO_backup_base = 0;
            ret->_IO_save_end = 0;
            ret->_fileno = fd;
            ret->_lock = 0;
            ret->_offset = 0;
            return ret;
        }
    }
   
    return ret;
}



FILE*
fopen(const char* filename, const char* mode) {
    initializeGekko();
    FILE* ret;
    if(CTX->interception_enabled()) {
        std::string resolved;
        auto rstatus = CTX->relativize_fd_path(AT_FDCWD, filename, resolved);
        switch(rstatus) {
            case gkfs::preload::RelativizeStatus::fd_not_a_dir:
                errno = ENOTDIR;
                return NULL;
            case gkfs::preload::RelativizeStatus::internal:
            {
                int fd = gkfs::syscall::gkfs_open(resolved, 0, O_RDONLY);
                if(fd == -1) {
                    return NULL;
                }
                ret = fdopen(fd, mode);
                return ret;
            }
            default:
                break;
        }
    }
    ret = dlsym_fopen(filename, mode);
    return ret;
}


size_t
fread(void* ptr, size_t size, size_t nmemb, FILE* stream) {
    initializeGekko();
    size_t ret;
    if(CTX->interception_enabled()) {
        if(CTX->file_map()->exist(stream->_fileno)) {
            return gkfs::syscall::gkfs_read(stream->_fileno, ptr,
                                            size * nmemb);
        }
    }

    ret = dlsym_fread(ptr, size, nmemb, stream);
    return ret;
}

size_t
fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream) {
    initializeGekko();
    size_t ret;
    if(CTX->interception_enabled()) {
        if(CTX->file_map()->exist(stream->_fileno)) {
            return gkfs::syscall::gkfs_write(stream->_fileno, ptr,
                                             size * nmemb);
        }
    }

    ret = dlsym_fwrite(ptr, size, nmemb, stream);
    return ret;
}

int
fseek(FILE* stream, long int offset, int whence) {
    initializeGekko();
    int ret;
    if(CTX->interception_enabled()) {
        if(CTX->file_map()->exist(stream->_fileno)) {
            return gkfs::syscall::gkfs_lseek(stream->_fileno, offset, whence);
        }
    }

    ret = dlsym_fseek(stream, offset, whence);
    return ret;
}

long
ftell(FILE* stream) {
    initializeGekko();
    long ret;
    if(CTX->interception_enabled()) {
        if(CTX->file_map()->exist(stream->_fileno)) {
            return gkfs::syscall::gkfs_lseek(stream->_fileno, 0, SEEK_CUR);
        }
    }

    ret = dlsym_ftell(stream);
    return ret;
}

void
rewind(FILE* stream) {
    initializeGekko();
    if(CTX->interception_enabled()) {
        if(CTX->file_map()->exist(stream->_fileno)) {
            gkfs::syscall::gkfs_lseek(stream->_fileno, 0, SEEK_SET);
        }
    }

    dlsym_rewind(stream);
}

int
fclose(FILE* stream) {
    initializeGekko();
    int ret;
    if(CTX->interception_enabled()) {
        if(CTX->file_map()->exist(stream->_fileno)) {
            ret = gkfs::syscall::gkfs_close(stream->_fileno);
            free(stream);
            return ret;
        }
    }

    ret = dlsym_fclose(stream);
    return ret;
}

// feof implementation with lseek
int
feof(FILE* stream) {
    initializeGekko();
    int ret;
    if(CTX->interception_enabled()) {
        if(CTX->file_map()->exist(stream->_fileno)) {
            off_t cur = gkfs::syscall::gkfs_lseek(stream->_fileno, 0, SEEK_CUR);
            off_t end = gkfs::syscall::gkfs_lseek(stream->_fileno, 0, SEEK_END);
            gkfs::syscall::gkfs_lseek(stream->_fileno, cur, SEEK_SET);
            return (cur == end);
        }
    }

    ret = dlsym_feof(stream);
    return ret;
}