# HG changeset patch # User Olaf Wintermann # Date 1485628942 -3600 # Node ID 6942a8c3e737878eeb5d275189c56505e19b49e5 # Parent 9ba9f8befa8064c05c8b7a129a31e337f7e9a4a0 refactors vfs code diff -r 9ba9f8befa80 -r 6942a8c3e737 src/server/daemon/vfs.c --- 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; } diff -r 9ba9f8befa80 -r 6942a8c3e737 src/server/daemon/vfs.h --- 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); diff -r 9ba9f8befa80 -r 6942a8c3e737 src/server/public/vfs.h --- 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 {