refactors vfs code aio

Sat, 28 Jan 2017 19:42:22 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 28 Jan 2017 19:42:22 +0100
branch
aio
changeset 165
6942a8c3e737
parent 159
9ba9f8befa80
child 170
711d00eeed25

refactors vfs code

src/server/daemon/vfs.c file | annotate | diff | comparison | revisions
src/server/daemon/vfs.h file | annotate | diff | comparison | revisions
src/server/public/vfs.h file | annotate | diff | comparison | revisions
--- a/src/server/daemon/vfs.c	Wed Jan 25 19:19:47 2017 +0100
+++ b/src/server/daemon/vfs.c	Sat Jan 28 19:42:22 2017 +0100
@@ -39,8 +39,21 @@
 #include "acl.h"
 #include "vfs.h"
 
+#define VFS_MALLOC(pool, size) pool ? pool_malloc(pool, size) : malloc(size)
+#define VFS_FREE(pool, ptr) pool ? pool_free(pool, ptr) : free(ptr)
+
 static UcxMap *vfs_map;
 
+static VFS sys_vfs = {
+    sys_vfs_open,
+    sys_vfs_stat,
+    sys_vfs_fstat,
+    sys_vfs_opendir,
+    sys_vfs_mkdir,
+    sys_vfs_unlink,
+    VFS_CHECKS_ACL
+};
+
 static VFS_IO sys_file_io = {
     sys_file_read,
     sys_file_write,
@@ -77,7 +90,7 @@
     VFSContext *ctx = pool_malloc(sn->pool, sizeof(VFSContext));
     ctx->sn = sn;
     ctx->rq = rq;
-    ctx->vfs = rq->vfs;
+    ctx->vfs = rq->vfs ? rq->vfs : &sys_vfs;
     ctx->user = acllist_getuser(sn, rq, rq->acllist);
     ctx->acllist = rq->acllist;
     ctx->aclreqaccess = rq->aclreqaccess;
@@ -87,36 +100,164 @@
 }
 
 SYS_FILE vfs_open(VFSContext *ctx, char *path, int oflags) {
+    WS_ASSERT(ctx);
+    WS_ASSERT(path);
+    
+    uint32_t access_mask = ctx->aclreqaccess | acl_oflag2mask(oflags);
+    
+    // ctx->aclreqaccess should be the complete access mask
+    uint32_t m = ctx->aclreqaccess; // save original access mask
+    ctx->aclreqaccess = access_mask; // set mask for vfs->open call
+    if((ctx->vfs->flags & VFS_CHECKS_ACL) != VFS_CHECKS_ACL) {
+        // VFS does not evaluates the ACL itself, so we have to do it here
+        SysACL sysacl;
+        if(sys_acl_check(ctx, access_mask, &sysacl)) {
+            return NULL;
+        }
+    }
+    SYS_FILE file = ctx->vfs->open(ctx, path, oflags);
+    ctx->aclreqaccess = m; // restore original access mask
+    return file;
+}
+
+SYS_FILE vfs_openRO(VFSContext *ctx, char *path) {
+    return vfs_open(ctx, path, O_RDONLY);
+}
+
+SYS_FILE vfs_openWO(VFSContext *ctx, char *path) {
+    return vfs_open(ctx, path, O_WRONLY | O_CREAT);
+}
+
+SYS_FILE vfs_openRW(VFSContext *ctx, char *path) {
+    return vfs_open(ctx, path, O_RDONLY | O_WRONLY | O_CREAT);
+}
+
+int vfs_stat(VFSContext *ctx, char *path, struct stat *buf) {
+    WS_ASSERT(ctx);
+    WS_ASSERT(path);
+    
+    uint32_t access_mask = ctx->aclreqaccess | ACL_READ_ATTRIBUTES;
+    
+    // ctx->aclreqaccess should be the complete access mask
+    uint32_t m = ctx->aclreqaccess; // save original access mask
+    ctx->aclreqaccess = access_mask; // set mask for vfs->open call
+    if((ctx->vfs->flags & VFS_CHECKS_ACL) != VFS_CHECKS_ACL) {
+        // VFS does not evaluates the ACL itself, so we have to do it here
+        SysACL sysacl;
+        if(sys_acl_check(ctx, access_mask, &sysacl)) {
+            return -1;
+        }
+    }
+    int ret = ctx->vfs->stat(ctx, path, buf);
+    ctx->aclreqaccess = m; // restore original access mask
+    return ret;
+}
+
+int vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf) {
+    WS_ASSERT(ctx);
+    WS_ASSERT(fd);
+    WS_ASSERT(buf);
+    
+    return ctx->vfs->fstat(ctx, fd, buf);
+}
+
+void vfs_close(SYS_FILE fd) {
+    WS_ASSERT(fd);
+    
+    fd->io->close(fd);
+    if(fd->ctx) {
+        pool_free(fd->ctx->pool, fd);
+    } else {
+        free(fd);
+    }
+}
+
+VFS_DIR vfs_opendir(VFSContext *ctx, char *path) {
+    WS_ASSERT(ctx);
     WS_ASSERT(path);
     
-    Session *sn;
-    Request *rq;
-    pool_handle_t *pool;
-    uint32_t access_mask;
+    uint32_t access_mask = ctx->aclreqaccess | ACL_LIST;
     
-    if(ctx) {
-        access_mask = ctx->aclreqaccess;
-        access_mask |= acl_oflag2mask(oflags);
-        if(!ctx->pool) {
-            // TODO: log warning
-            // broken VFSContext
+    // ctx->aclreqaccess should be the complete access mask
+    uint32_t m = ctx->aclreqaccess; // save original access mask
+    ctx->aclreqaccess = access_mask; // set mask for vfs->open call
+    if((ctx->vfs->flags & VFS_CHECKS_ACL) != VFS_CHECKS_ACL) {
+        // VFS does not evaluates the ACL itself, so we have to do it here
+        SysACL sysacl;
+        if(sys_acl_check(ctx, access_mask, &sysacl)) {
+            return NULL;
         }
-        if(ctx->vfs) {
-            // ctx->aclreqaccess should be the complete access mask
-            uint32_t m = ctx->aclreqaccess; // save original access mask
-            ctx->aclreqaccess = access_mask; // set mask for vfs->open call
-            SYS_FILE file = ctx->vfs->open(ctx, path, oflags);
-            ctx->aclreqaccess = m; // restore original access mask
-            return file;
-        } else {
-            pool = ctx->pool;
+    }
+    VFS_DIR dir = ctx->vfs->opendir(ctx, path);
+    ctx->aclreqaccess = m; // restore original access mask
+    return dir;
+}
+
+int vfs_readdir(VFS_DIR dir, VFS_ENTRY *entry) {
+    WS_ASSERT(dir);
+    WS_ASSERT(entry);
+    
+    return dir->io->readdir(dir, entry, 0);
+}
+
+int vfs_readdir_stat(VFS_DIR dir, VFS_ENTRY *entry) {
+    WS_ASSERT(dir);
+    WS_ASSERT(entry);
+    
+    return dir->io->readdir(dir, entry, 1);
+}
+
+void vfs_closedir(VFS_DIR dir) {
+    WS_ASSERT(dir);
+    
+    dir->io->close(dir);
+    if(dir->ctx) {
+        VFS_FREE(dir->ctx->pool, dir);
+    } else {
+        free(dir);
+    }
+}
+
+int vfs_mkdir(VFSContext *ctx, char *path) {
+    WS_ASSERT(ctx);
+    WS_ASSERT(path);
+    
+    return vfs_path_op(ctx, path, ctx->vfs->mkdir, ACL_ADD_FILE);
+}
+
+int vfs_unlink(VFSContext *ctx, char *path) {
+    WS_ASSERT(ctx);
+    WS_ASSERT(path);
+    
+    return vfs_path_op(ctx, path, ctx->vfs->unlink, ACL_DELETE);
+}
+
+
+// private
+int vfs_path_op(VFSContext *ctx, char *path, vfs_op_f op, uint32_t access) {  
+    uint32_t access_mask = ctx->aclreqaccess;
+    access_mask |= access;
+    
+    // ctx->aclreqaccess should be the complete access mask
+    uint32_t m = ctx->aclreqaccess; // save original access mask
+    ctx->aclreqaccess = access_mask; // set mask for vfs function call
+    if((ctx->vfs->flags & VFS_CHECKS_ACL) != VFS_CHECKS_ACL) {
+        // VFS does not evaluates the ACL itself, so we have to do it here
+        SysACL sysacl;
+        if(sys_acl_check(ctx, access_mask, &sysacl)) {
+            return -1;
         }
-    } else {
-        sn = NULL;
-        rq = NULL;
-        pool = NULL;
-        access_mask = acl_oflag2mask(oflags);
     }
+    int ret = op(ctx, path);
+    ctx->aclreqaccess = m; // restore original access mask
+    return ret;
+}
+
+/* system vfs implementation */
+
+SYS_FILE sys_vfs_open(VFSContext *ctx, char *path, int oflags) {
+    uint32_t access_mask = ctx->aclreqaccess;
+    pool_handle_t *pool = ctx->pool;
     
     // check ACLs
     SysACL sysacl;
@@ -151,9 +292,7 @@
         }
     }
     
-    
-    VFSFile *file = pool ?
-            pool_malloc(pool, sizeof(VFSFile)) : malloc(sizeof(VFSFile));
+    VFSFile *file = VFS_MALLOC(pool, sizeof(VFSFile));
     if(!file) {
         close(fd);
         return NULL;
@@ -165,43 +304,8 @@
     return file;
 }
 
-SYS_FILE vfs_openRO(VFSContext *ctx, char *path) {
-    return vfs_open(ctx, path, O_RDONLY);
-}
-
-SYS_FILE vfs_openWO(VFSContext *ctx, char *path) {
-    return vfs_open(ctx, path, O_WRONLY | O_CREAT);
-}
-
-SYS_FILE vfs_openRW(VFSContext *ctx, char *path) {
-    return vfs_open(ctx, path, O_RDONLY | O_WRONLY | O_CREAT);
-}
-
-int vfs_stat(VFSContext *ctx, char *path, struct stat *buf) {
-    Session *sn;
-    Request *rq;
-    uint32_t access_mask;
-    
-    if(ctx) {
-        access_mask = ctx->aclreqaccess;
-        access_mask |= ACL_READ_ATTRIBUTES;
-        if(!ctx->pool) {
-            // TODO: log warning
-            // broken VFSContext
-        }
-        if(ctx->vfs) {
-            // ctx->aclreqaccess should be the complete access mask
-            uint32_t m = ctx->aclreqaccess; // save original access mask
-            ctx->aclreqaccess = access_mask; // set mask for vfs->fstat call
-            int ret = ctx->vfs->stat(ctx, path, buf);
-            ctx->aclreqaccess = m; // restore original access mask
-            return ret;
-        }
-    } else {
-        sn = NULL;
-        rq = NULL;
-        access_mask = ACL_READ_ATTRIBUTES;
-    }
+int sys_vfs_stat(VFSContext *ctx, char *path, struct stat *buf) {
+    uint32_t access_mask = ctx->aclreqaccess;
     
     // check ACLs
     SysACL sysacl;
@@ -228,17 +332,7 @@
     return 0;
 }
 
-int vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf) { 
-    if(ctx) {
-        if(!ctx->pool) {
-            // TODO: log warning
-            // broken VFSContext
-        }
-        if(ctx->vfs) {
-            return ctx->vfs->fstat(ctx, fd, buf);
-        }
-    }
-    
+int sys_vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf) {
     // stat
     if(fstat(fd->fd, buf)) {
         if(ctx) {
@@ -250,46 +344,9 @@
     return 0;
 }
 
-void vfs_close(SYS_FILE fd) {
-    fd->io->close(fd);
-    if(fd->ctx) {
-        pool_free(fd->ctx->pool, fd);
-    } else {
-        free(fd);
-    }
-}
-
-VFS_DIR vfs_opendir(VFSContext *ctx, char *path) {
-    WS_ASSERT(path);
-    
-    Session *sn;
-    Request *rq;
-    pool_handle_t *pool;
-    uint32_t access_mask;
-    
-    if(ctx) {
-        access_mask = ctx->aclreqaccess;
-        access_mask |= ACL_LIST;
-        if(!ctx->pool) {
-            // TODO: log warning
-            // broken VFSContext
-        }
-        if(ctx->vfs) {
-            // ctx->aclreqaccess should be the complete access mask
-            uint32_t m = ctx->aclreqaccess; // save original access mask
-            ctx->aclreqaccess = access_mask; // set mask for vfs->opendir call
-            VFS_DIR dir = ctx->vfs->opendir(ctx, path);
-            ctx->aclreqaccess = m; // restore original access mask
-            return dir;
-        } else {
-            pool = ctx->pool;
-        }
-    } else {
-        sn = NULL;
-        rq = NULL;
-        pool = NULL;
-        access_mask = ACL_LIST;
-    }
+VFS_DIR sys_vfs_opendir(VFSContext *ctx, char *path) {
+    uint32_t access_mask = ctx->aclreqaccess;
+    pool_handle_t *pool = ctx->pool;
     
     // check ACLs
     SysACL sysacl;
@@ -327,26 +384,26 @@
         return NULL;
     }
     
-    SysVFSDir *dir_data = pool ?
-            pool_malloc(pool, sizeof(SysVFSDir)) : malloc(sizeof(SysVFSDir));
+    SysVFSDir *dir_data = VFS_MALLOC(pool, sizeof(SysVFSDir));
     if(!dir_data) {
         closedir(sys_dir);
         return NULL;
     }
     long maxfilelen = fpathconf(dir_fd, _PC_NAME_MAX);
     size_t entry_len = offsetof(struct dirent, d_name) + maxfilelen + 1;
-    dir_data->cur = pool ?
-            pool_malloc(pool, entry_len) : malloc(entry_len);
+    dir_data->cur = VFS_MALLOC(pool, entry_len);
     if(!dir_data->cur) {
         closedir(sys_dir);
+        VFS_FREE(pool, dir_data);
         return NULL;
     }
     dir_data->dir = sys_dir;
     
-    VFSDir *dir = pool ?
-            pool_malloc(pool, sizeof(VFSDir)) : malloc(sizeof(VFSDir));
+    VFSDir *dir = VFS_MALLOC(pool, sizeof(VFSDir));
     if(!dir) {
         closedir(sys_dir);
+        VFS_FREE(pool, dir_data->cur);
+        VFS_FREE(pool, dir_data);
         return NULL;
     }
     dir->ctx = ctx;
@@ -356,74 +413,26 @@
     return dir;
 }
 
-int vfs_readdir(VFS_DIR dir, VFS_ENTRY *entry) {
-    return dir->io->readdir(dir, entry, 0);
-}
-
-int vfs_readdir_stat(VFS_DIR dir, VFS_ENTRY *entry) {
-    return dir->io->readdir(dir, entry, 1);
+int sys_vfs_mkdir(VFSContext *ctx, char *path) {
+    return sys_path_op(ctx, path, sys_mkdir);
 }
 
-void vfs_closedir(VFS_DIR dir) {
-    dir->io->close(dir);
-    if(dir->ctx) {
-        pool_free(dir->ctx->pool, dir);
-    } else {
-        free(dir);
-    }
-}
-
-int vfs_mkdir(VFSContext *ctx, char *path) {
-    if(ctx && ctx->vfs) {
-        return vfs_path_op(ctx, path, ctx->vfs->mkdir, ACL_ADD_FILE);
-    } else {
-        return sys_path_op(ctx, path, sys_mkdir, ACL_ADD_FILE);
-    }
-}
-
-int vfs_unlink(VFSContext *ctx, char *path) {
-    if(ctx && ctx->vfs) {
-        return vfs_path_op(ctx, path, ctx->vfs->unlink, ACL_DELETE);
-    } else {
-        return sys_path_op(ctx, path, sys_unlink, ACL_DELETE);
-    }
+int sys_vfs_unlink(VFSContext *ctx, char *path) {
+    return sys_path_op(ctx, path, sys_unlink);
 }
 
 
-// private
-int vfs_path_op(VFSContext *ctx, char *path, vfs_op_f op, uint32_t access) {
-    Session *sn;
-    Request *rq;
-    
+int sys_path_op(VFSContext *ctx, char *path, sys_op_f op) {
     uint32_t access_mask = ctx->aclreqaccess;
-    access_mask |= access;
-    if(!ctx->pool) {
-        // TODO: log warning
-        // broken VFSContext
-        return -1;
-    }
-    
-    // ctx->aclreqaccess should be the complete access mask
-    uint32_t m = ctx->aclreqaccess; // save original access mask
-    ctx->aclreqaccess = access_mask; // set mask for vfs function call
-    int ret = op(ctx, path);
-    ctx->aclreqaccess = m; // restore original access mask
-    return ret;
-}
-
-int sys_path_op(VFSContext *ctx, char *path, sys_op_f op, uint32_t access) {
-    if(ctx) {
-        access |= ctx->aclreqaccess;
-    }
     
     // check ACLs
     SysACL sysacl;
-    if(sys_acl_check(ctx, access, &sysacl)) {
+    if(sys_acl_check(ctx, access_mask, &sysacl)) {
         return -1;
     }
     
     if(sysacl.acl) {
-        if(!fs_acl_check(&sysacl, ctx->user, path, access)) {
+        if(!fs_acl_check(&sysacl, ctx->user, path, access_mask)) {
             acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user);
             return -1;
         }
@@ -432,10 +441,8 @@
     // do path operation
     if(op(ctx, path, &sysacl)) {
         // error
-        if(ctx) {
-            ctx->vfs_errno = errno;
-            sys_set_error_status(ctx);
-        }
+        ctx->vfs_errno = errno;
+        sys_set_error_status(ctx);
         return -1;
     }
     
--- a/src/server/daemon/vfs.h	Wed Jan 25 19:19:47 2017 +0100
+++ b/src/server/daemon/vfs.h	Sat Jan 28 19:42:22 2017 +0100
@@ -46,16 +46,26 @@
 typedef int(*vfs_op_f)(VFSContext *, char *);
 typedef int(*sys_op_f)(VFSContext *, char *, SysACL *);
 int vfs_path_op(VFSContext *ctx, char *path, vfs_op_f op, uint32_t access);
-int sys_path_op(VFSContext *ctx, char *path, sys_op_f op, uint32_t access);
 
+SYS_FILE sys_vfs_open(VFSContext *ctx, char *path, int oflags);
+int sys_vfs_stat(VFSContext *ctx, char *path, struct stat *buf);
+int sys_vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf);
+VFS_DIR sys_vfs_opendir(VFSContext *ctx, char *path);
+int sys_vfs_mkdir(VFSContext *ctx, char *path);
+int sys_vfs_unlink(VFSContext *ctx, char *path);
+
+int sys_path_op(VFSContext *ctx, char *path, sys_op_f op);
 int sys_acl_check(VFSContext *ctx, uint32_t access_mask, SysACL *externacl);
 void sys_set_error_status(VFSContext *ctx);
+
 ssize_t sys_file_read(SYS_FILE fd, void *buf, size_t nbyte);
 ssize_t sys_file_write(SYS_FILE fd, const void *buf, size_t nbyte);
 off_t sys_file_seek(SYS_FILE fd, off_t offset, int whence);
 void sys_file_close(SYS_FILE fd);
+
 int sys_dir_read(VFS_DIR dir, VFS_ENTRY *entry, int getstat);
 void sys_dir_close(VFS_DIR dir);
+
 int sys_mkdir(VFSContext *ctx, char *path, SysACL *sysacl);
 int sys_unlink(VFSContext *ctx, char *path, SysACL *sysacl);
 
--- a/src/server/public/vfs.h	Wed Jan 25 19:19:47 2017 +0100
+++ b/src/server/public/vfs.h	Sat Jan 28 19:42:22 2017 +0100
@@ -36,6 +36,8 @@
 extern "C" {
 #endif
 
+#define VFS_CHECKS_ACL 0x0001  
+    
 typedef struct VFS_IO     VFS_IO;
 typedef struct VFS_DIRIO  VFS_DIRIO;
 typedef struct VFSFile    VFSFile;
@@ -52,6 +54,7 @@
     VFS_DIR (*opendir)(VFSContext *ctx, char *path);
     int (*mkdir)(VFSContext *ctx, char *path);
     int (*unlink)(VFSContext *ctx, char *path);
+    uint32_t flags;
 };
 
 struct VFSContext {

mercurial