Commit 5b78f4df authored by Julius Athenstaedt's avatar Julius Athenstaedt Committed by Ramon Nou
Browse files

unlink, rmdir, releasedir, lseek and access handlers

parent f913614b
Loading
Loading
Loading
Loading
+86 −8
Original line number Diff line number Diff line
@@ -251,6 +251,18 @@ open_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) {
    fuse_reply_open(req, fi);
}

static void
lseek_handler(fuse_req_t req, fuse_ino_t ino, off_t off, int whence,
             struct fuse_file_info* fi) {
    fuse_log(FUSE_LOG_DEBUG, "lseek handler \n");
    int lc = gkfs::syscall::gkfs_lseek(fi->fh, off, whence);
    if(lc < 0) {
        fuse_reply_err(req, 1);
        return;
    }
    fuse_reply_lseek(req, lc);
}

static void
read_handler(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
             struct fuse_file_info* fi) {
@@ -342,6 +354,25 @@ create_handler(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode,
    fuse_reply_create(req, &e, fi);
}

/// TODO normally, the file should only be removed if the lookup count is zero,
/// problem?
static void
unlink_handler(fuse_req_t req, fuse_ino_t parent, const char* name) {
    fuse_log(FUSE_LOG_DEBUG, "unlink handler \n");
    auto* parent_inode = get_inode(parent);
    if(!parent_inode) {
        fuse_reply_err(req, ENOENT);
        return;
    }
    std::string path = get_path(parent_inode, name);
    int rc = gkfs::syscall::gkfs_remove(path);
    if(rc == -1) {
        fuse_reply_err(req, 1);
        return;
    }
    fuse_reply_err(req, 0);
}

static void
opendir_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) {
    fuse_log(FUSE_LOG_DEBUG, "opendir handler \n");
@@ -443,6 +474,24 @@ readdir_handler(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
    free(buf);
}

static void
releasedir_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) {
    fuse_log(FUSE_LOG_DEBUG, "releasedir handler \n");
    GkfsDir* dir_ptr = reinterpret_cast<GkfsDir*>(fi->fh);
    if(CTX->interception_enabled() && CTX->file_map()->exist(dir_ptr->fd)) {
        int fd = dir_ptr->fd;
        int ret = gkfs::syscall::gkfs_close(fd); // Close GekkoFS internal FD

        if(dir_ptr->path) { // Check if path was strdup'd
            free(dir_ptr->path);
        }
        free(dir_ptr); // Free the DIR struct itself
        fuse_reply_err(req, ret);
        return;
    }
    fuse_reply_err(req, 0);
}

/// releases file descriptor, not connected to lookup_count
static void
release_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) {
@@ -495,17 +544,30 @@ flush_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) {
    fuse_log(FUSE_LOG_DEBUG, "flush handler \n");
    auto* inode = get_inode(ino);
    if(!inode) {
        fuse_log(FUSE_LOG_DEBUG, "flush here \n");
        fuse_reply_err(req, ENOENT);
        return;
    }
    int lc = gkfs::syscall::gkfs_fsync(fi->fh);
    if(lc < 0) {
        fuse_log(FUSE_LOG_DEBUG, "flush there \n");
        fuse_reply_err(req, 1);
        return;
    }
    fuse_log(FUSE_LOG_DEBUG, "flush success \n");
    fuse_reply_err(req, 0);
}

static void
access_handler(fuse_req_t req, fuse_ino_t ino, int mask) {
    fuse_log(FUSE_LOG_DEBUG, "access handler \n");
    auto* inode = get_inode(ino);
    if(!inode) {
        fuse_reply_err(req, ENOENT);
        return;
    }
    int lc = gkfs::syscall::gkfs_access(inode->path, mask, true);
    if(lc < 0) {
        fuse_reply_err(req, 1);
        return;
    }
    fuse_reply_err(req, 0);
}

@@ -544,6 +606,22 @@ mkdir_handler(fuse_req_t req, fuse_ino_t parent, const char* name,
    fuse_reply_entry(req, &e);
}

static void
rmdir_handler(fuse_req_t req, fuse_ino_t parent, const char* name) {
    auto* parent_inode = get_inode(parent);
    if(!parent_inode) {
        fuse_reply_err(req, ENOENT);
        return;
    }
    std::string path = get_path(parent_inode, name);
    int rc = gkfs::syscall::gkfs_rmdir(path);
    if(rc == -1) {
        fuse_reply_err(req, 1);
        return;
    }
    fuse_reply_err(req, 0);
}

static void
init_gekkofs() {
    // TODO how to handle mount point
@@ -579,7 +657,7 @@ init_ll_ops(fuse_lowlevel_ops* ops) {
    ops->setattr = setattr_handler;
    ops->open = open_handler;
    ops->create = create_handler;
    // ops->unlink
    ops->unlink = unlink_handler;
    ops->forget = forget_handler;
    // ops->forget_multi
    // ops->readlink
@@ -591,6 +669,7 @@ init_ll_ops(fuse_lowlevel_ops* ops) {
    ops->release = release_handler;
    // ops->fsync
    // ops->write_buf
    ops->lseek = lseek_handler;

    // xattr
    // ops->setxattr
@@ -601,10 +680,10 @@ init_ll_ops(fuse_lowlevel_ops* ops) {
    // directory
    ops->lookup = lookup_handler;
    ops->mkdir = mkdir_handler;
    // ops->rmdir
    ops->rmdir = rmdir_handler;
    ops->readdir = readdir_handler;
    ops->opendir = opendir_handler;
    // ops->releasedir
    ops->releasedir = releasedir_handler;
    // ops->fsyncdir = nullptr;
    // ops->readdirplus

@@ -613,7 +692,7 @@ init_ll_ops(fuse_lowlevel_ops* ops) {
    ops->read = read_handler;

    // permission
    // ops->access
    ops->access = access_handler;

    // misc
    ops->init = init_handler;
@@ -629,7 +708,6 @@ init_ll_ops(fuse_lowlevel_ops* ops) {
    // ops->retrive_reply
    // ops->fallocate
    // ops->copy_file_range
    // ops->lseek
    // ops->tmpfile
    // ops->statx
}
+21 −3
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ from harness.logger import logger

nonexisting = "nonexisting"

# somehow are multiple test causing an error in the fuse client...
def test_read(gkfs_daemon, fuse_client):

    file = gkfs_daemon.mountdir / "file"
@@ -58,6 +59,23 @@ def test_read(gkfs_daemon, fuse_client):
    assert sh.ls(fuse_client.mountdir) == "dir  file  file2\n"
    sh.cd(str(dir))
    assert sh.pwd() == str(dir) + "\n"
    sh.mkdir("-p", "fu/bar")
    assert sh.ls() == "fu\n"
    sh.cd("fu")
    sh.mkdir("-p", "foo/bar")
    assert sh.ls() == "foo\n"
    sh.cd("foo")
    sh.rmdir("bar")
    sh.cd("..")
    sh.rmdir("foo")
    sh.rm(str(file2))
    assert sh.ls(fuse_client.mountdir) == "dir  file\n"

    # lseek test
    path = gkfs_daemon.mountdir / "lseek_file"
    with open(path, "wb") as f:
        f.write(b"HelloWorld")  # 10 bytes
    fd = os.open(path, os.O_RDONLY)
    pos = os.lseek(fd, 5, os.SEEK_SET)  # absolute seek
    assert pos == 5
    data = os.read(fd, 5)
    assert data == b"World"
    os.close(fd)
    os.remove(path)