121 SYS_FILE vfs_openRO(VFSContext *ctx, char *path) { |
121 SYS_FILE vfs_openRO(VFSContext *ctx, char *path) { |
122 return vfs_open(ctx, path, O_RDONLY); |
122 return vfs_open(ctx, path, O_RDONLY); |
123 } |
123 } |
124 |
124 |
125 SYS_FILE vfs_openWO(VFSContext *ctx, char *path) { |
125 SYS_FILE vfs_openWO(VFSContext *ctx, char *path) { |
126 return vfs_open(ctx, path, O_WRONLY); |
126 return vfs_open(ctx, path, O_WRONLY | O_CREAT); |
127 } |
127 } |
128 |
128 |
129 SYS_FILE vfs_openRW(VFSContext *ctx, char *path) { |
129 SYS_FILE vfs_openRW(VFSContext *ctx, char *path) { |
130 return vfs_open(ctx, path, O_RDONLY); |
130 return vfs_open(ctx, path, O_RDONLY | O_WRONLY | O_CREAT); |
131 } |
131 } |
132 |
132 |
133 int vfs_stat(VFSContext *ctx, char *path, struct stat *buf) { |
133 int vfs_stat(VFSContext *ctx, char *path, struct stat *buf) { |
134 Session *sn; |
134 Session *sn; |
135 Request *rq; |
135 Request *rq; |
290 } else { |
290 } else { |
291 free(dir); |
291 free(dir); |
292 } |
292 } |
293 } |
293 } |
294 |
294 |
|
295 int vfs_mkdir(VFSContext *ctx, char *path) { |
|
296 if(ctx && ctx->vfs) { |
|
297 return vfs_path_op(ctx, path, ctx->vfs->mkdir, ACL_ADD_FILE); |
|
298 } else { |
|
299 return vfs_path_op(ctx, path, sys_mkdir, ACL_ADD_FILE); |
|
300 } |
|
301 } |
|
302 |
|
303 int vfs_unlink(VFSContext *ctx, char *path) { |
|
304 if(ctx && ctx->vfs) { |
|
305 return vfs_path_op(ctx, path, ctx->vfs->unlink, ACL_DELETE); |
|
306 } else { |
|
307 return vfs_path_op(ctx, path, sys_unlink, ACL_DELETE); |
|
308 } |
|
309 } |
|
310 |
295 |
311 |
296 // private |
312 // private |
|
313 int vfs_path_op(VFSContext *ctx, char *path, vfs_op_f op, uint32_t access) { |
|
314 Session *sn; |
|
315 Request *rq; |
|
316 uint32_t access_mask; |
|
317 |
|
318 if(ctx) { |
|
319 access_mask = ctx->aclreqaccess; |
|
320 access_mask |= access; |
|
321 if(!ctx->pool) { |
|
322 // TODO: log warning |
|
323 // broken VFSContext |
|
324 } |
|
325 if(ctx->vfs) { |
|
326 // ctx->aclreqaccess should be the complete access mask |
|
327 uint32_t m = ctx->aclreqaccess; // save original access mask |
|
328 ctx->aclreqaccess = access_mask; // set mask for vfs->fstat call |
|
329 int ret = op(ctx, path); |
|
330 ctx->aclreqaccess = m; // restore original access mask |
|
331 return ret; |
|
332 } |
|
333 } else { |
|
334 sn = NULL; |
|
335 rq = NULL; |
|
336 access_mask = access; |
|
337 } |
|
338 |
|
339 // check ACLs |
|
340 uid_t uid; // uid and gid will be initialized by sys_acl_check |
|
341 gid_t gid; |
|
342 if(sys_acl_check(ctx, access_mask, &uid, &gid)) { |
|
343 return NULL; |
|
344 } |
|
345 |
|
346 // do path operation |
|
347 if(op(ctx, path)) { |
|
348 // error |
|
349 if(ctx) { |
|
350 ctx->vfs_errno = errno; |
|
351 sys_set_error_status(ctx); |
|
352 } |
|
353 return -1; |
|
354 } |
|
355 |
|
356 return 0; |
|
357 } |
297 |
358 |
298 int sys_acl_check(VFSContext *ctx, uint32_t acm, uid_t *uid, gid_t *gid) { |
359 int sys_acl_check(VFSContext *ctx, uint32_t acm, uid_t *uid, gid_t *gid) { |
299 /* |
360 /* |
300 * we don't allow remote root access, so a uid of 0 means that |
361 * we don't allow remote root access, so a uid of 0 means that |
301 * no file system acl check is needed |
362 * no file system acl check is needed |
327 return 0; |
388 return 0; |
328 } |
389 } |
329 |
390 |
330 void sys_set_error_status(VFSContext *ctx) { |
391 void sys_set_error_status(VFSContext *ctx) { |
331 if(ctx->sn && ctx->rq) { |
392 if(ctx->sn && ctx->rq) { |
332 int status = 500; |
393 int status = util_errno2status(ctx->vfs_errno); |
333 switch(ctx->vfs_errno) { |
|
334 case EACCES: { |
|
335 status = 403; |
|
336 break; |
|
337 } |
|
338 case ENOENT: { |
|
339 status = 404; |
|
340 break; |
|
341 } |
|
342 } |
|
343 protocol_status(ctx->sn, ctx->rq, status, NULL); |
394 protocol_status(ctx->sn, ctx->rq, status, NULL); |
344 } |
395 } |
345 } |
396 } |
346 |
397 |
347 ssize_t sys_file_read(SYS_FILE fd, void *buf, size_t nbyte) { |
398 ssize_t sys_file_read(SYS_FILE fd, void *buf, size_t nbyte) { |