200 VFS_DIR dir = ctx->vfs->opendir(ctx, path); |
202 VFS_DIR dir = ctx->vfs->opendir(ctx, path); |
201 ctx->aclreqaccess = m; // restore original access mask |
203 ctx->aclreqaccess = m; // restore original access mask |
202 return dir; |
204 return dir; |
203 } |
205 } |
204 |
206 |
|
207 VFS_DIR vfs_fdopendir(VFSContext *ctx, SYS_FILE fd) { |
|
208 WS_ASSERT(ctx); |
|
209 WS_ASSERT(path); |
|
210 |
|
211 uint32_t access_mask = ctx->aclreqaccess | ACL_LIST; |
|
212 |
|
213 // ctx->aclreqaccess should be the complete access mask |
|
214 uint32_t m = ctx->aclreqaccess; // save original access mask |
|
215 ctx->aclreqaccess = access_mask; // set mask for vfs->open call |
|
216 if((ctx->vfs->flags & VFS_CHECKS_ACL) != VFS_CHECKS_ACL) { |
|
217 // VFS does not evaluates the ACL itself, so we have to do it here |
|
218 SysACL sysacl; |
|
219 if(sys_acl_check(ctx, access_mask, &sysacl)) { |
|
220 return NULL; |
|
221 } |
|
222 } |
|
223 VFS_DIR dir = ctx->vfs->fdopendir(ctx, fd); |
|
224 ctx->aclreqaccess = m; // restore original access mask |
|
225 return dir; |
|
226 } |
|
227 |
205 int vfs_readdir(VFS_DIR dir, VFS_ENTRY *entry) { |
228 int vfs_readdir(VFS_DIR dir, VFS_ENTRY *entry) { |
206 WS_ASSERT(dir); |
229 WS_ASSERT(dir); |
207 WS_ASSERT(entry); |
230 WS_ASSERT(entry); |
208 |
231 |
209 return dir->io->readdir(dir, entry, 0); |
232 return dir->io->readdir(dir, entry, 0); |
416 return NULL; |
439 return NULL; |
417 } |
440 } |
418 dir->ctx = ctx; |
441 dir->ctx = ctx; |
419 dir->data = dir_data; |
442 dir->data = dir_data; |
420 dir->fd = dir_fd; |
443 dir->fd = dir_fd; |
|
444 dir->io = &sys_dir_io; |
|
445 return dir; |
|
446 } |
|
447 |
|
448 VFS_DIR sys_vfs_fdopendir(VFSContext *ctx, SYS_FILE fd) { |
|
449 uint32_t access_mask = ctx->aclreqaccess; |
|
450 pool_handle_t *pool = ctx->pool; |
|
451 |
|
452 // check ACLs |
|
453 SysACL sysacl; |
|
454 if(sys_acl_check(ctx, access_mask, &sysacl)) { |
|
455 return NULL; |
|
456 } |
|
457 |
|
458 if(sysacl.acl) { |
|
459 if(!fs_acl_check_fd(&sysacl, ctx->user, fd->fd, access_mask)) { |
|
460 acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user); |
|
461 return NULL; |
|
462 } |
|
463 } |
|
464 |
|
465 // open directory |
|
466 DIR *sys_dir = fdopendir(fd->fd); |
|
467 if(!sys_dir) { |
|
468 if(ctx) { |
|
469 ctx->vfs_errno = errno; |
|
470 sys_set_error_status(ctx); |
|
471 } |
|
472 return NULL; |
|
473 } |
|
474 |
|
475 SysVFSDir *dir_data = VFS_MALLOC(pool, sizeof(SysVFSDir)); |
|
476 if(!dir_data) { |
|
477 closedir(sys_dir); |
|
478 return NULL; |
|
479 } |
|
480 long maxfilelen = fpathconf(fd->fd, _PC_NAME_MAX); |
|
481 size_t entry_len = offsetof(struct dirent, d_name) + maxfilelen + 1; |
|
482 dir_data->cur = VFS_MALLOC(pool, entry_len); |
|
483 if(!dir_data->cur) { |
|
484 closedir(sys_dir); |
|
485 VFS_FREE(pool, dir_data); |
|
486 return NULL; |
|
487 } |
|
488 dir_data->dir = sys_dir; |
|
489 |
|
490 VFSDir *dir = VFS_MALLOC(pool, sizeof(VFSDir)); |
|
491 if(!dir) { |
|
492 closedir(sys_dir); |
|
493 VFS_FREE(pool, dir_data->cur); |
|
494 VFS_FREE(pool, dir_data); |
|
495 return NULL; |
|
496 } |
|
497 dir->ctx = ctx; |
|
498 dir->data = dir_data; |
|
499 dir->fd = fd->fd; |
421 dir->io = &sys_dir_io; |
500 dir->io = &sys_dir_io; |
422 return dir; |
501 return dir; |
423 } |
502 } |
424 |
503 |
425 int sys_vfs_mkdir(VFSContext *ctx, char *path) { |
504 int sys_vfs_mkdir(VFSContext *ctx, char *path) { |
537 return sys_dir_read(dir, entry, getstat); |
616 return sys_dir_read(dir, entry, getstat); |
538 } else { |
617 } else { |
539 entry->name = name; |
618 entry->name = name; |
540 if(getstat) { |
619 if(getstat) { |
541 // TODO: check ACLs again for new path |
620 // TODO: check ACLs again for new path |
|
621 entry->stat_errno = 0; |
542 if(fstatat(dir->fd, result->d_name, &entry->stat, 0)) { |
622 if(fstatat(dir->fd, result->d_name, &entry->stat, 0)) { |
543 entry->stat_errno = errno; |
623 entry->stat_errno = errno; |
544 } |
624 } |
545 entry->stat_extra = NULL; |
625 entry->stat_extra = NULL; |
546 } |
626 } |