src/server/daemon/vfs.c

changeset 56
c6cf20b09043
parent 55
b7908bf38f9f
child 57
b3a89736b23e
--- a/src/server/daemon/vfs.c	Sun Mar 17 12:47:59 2013 +0100
+++ b/src/server/daemon/vfs.c	Sun Mar 17 17:54:20 2013 +0100
@@ -123,11 +123,11 @@
 }
 
 SYS_FILE vfs_openWO(VFSContext *ctx, char *path) {
-    return vfs_open(ctx, path, O_WRONLY);
+    return vfs_open(ctx, path, O_WRONLY | O_CREAT);
 }
 
 SYS_FILE vfs_openRW(VFSContext *ctx, char *path) {
-    return vfs_open(ctx, path, O_RDONLY);
+    return vfs_open(ctx, path, O_RDONLY | O_WRONLY | O_CREAT);
 }
 
 int vfs_stat(VFSContext *ctx, char *path, struct stat *buf) {
@@ -292,8 +292,69 @@
     }
 }
 
+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 vfs_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 vfs_path_op(ctx, path, sys_unlink, ACL_DELETE);
+    }
+}
+
 
 // private
+int vfs_path_op(VFSContext *ctx, char *path, vfs_op_f op, uint32_t access) {
+    Session *sn;
+    Request *rq;
+    uint32_t access_mask;
+    
+    if(ctx) {
+        access_mask = ctx->aclreqaccess;
+        access_mask |= access;
+        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 = op(ctx, path);
+            ctx->aclreqaccess = m; // restore original access mask
+            return ret;
+        }
+    } else {
+        sn = NULL;
+        rq = NULL;
+        access_mask = access;
+    }
+    
+    // check ACLs
+    uid_t uid; // uid and gid will be initialized by sys_acl_check
+    gid_t gid;
+    if(sys_acl_check(ctx, access_mask, &uid, &gid)) {
+        return NULL;
+    }
+    
+    // do path operation
+    if(op(ctx, path)) {
+        // error
+        if(ctx) {
+            ctx->vfs_errno = errno;
+            sys_set_error_status(ctx);
+        }
+        return -1;
+    }
+    
+    return 0;
+}
 
 int sys_acl_check(VFSContext *ctx, uint32_t acm, uid_t *uid, gid_t *gid) {
     /*
@@ -329,17 +390,7 @@
 
 void sys_set_error_status(VFSContext *ctx) {
     if(ctx->sn && ctx->rq) {
-        int status = 500;
-        switch(ctx->vfs_errno) {
-            case EACCES: {
-                status = 403;
-                break;
-            }
-            case ENOENT: {
-                status = 404;
-                break;
-            }
-        }
+        int status = util_errno2status(ctx->vfs_errno);
         protocol_status(ctx->sn, ctx->rq, status, NULL);
     }
 }
@@ -375,3 +426,12 @@
 void sys_dir_close(VFS_DIR dir) {
     closedir(dir->data);
 }
+
+int sys_mkdir(VFSContext *ctx, char *path) {
+    mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+    return mkdir(path, mode);
+}
+
+int sys_unlink(VFSContext *ctx, char *path) {
+    return unlink(path);
+}

mercurial