src/server/daemon/vfs.c

changeset 385
a1f4cb076d2f
parent 366
47bc686fafe4
child 415
d938228c382e
equal deleted inserted replaced
210:21274e5950af 385:a1f4cb076d2f
43 #include "event.h" 43 #include "event.h"
44 44
45 #define VFS_MALLOC(pool, size) pool ? pool_malloc(pool, size) : malloc(size) 45 #define VFS_MALLOC(pool, size) pool ? pool_malloc(pool, size) : malloc(size)
46 #define VFS_FREE(pool, ptr) pool ? pool_free(pool, ptr) : free(ptr) 46 #define VFS_FREE(pool, ptr) pool ? pool_free(pool, ptr) : free(ptr)
47 47
48 static UcxMap *vfs_map; 48 static UcxMap *vfs_type_map;
49 49
50 static VFS sys_vfs = { 50 static VFS sys_vfs = {
51 sys_vfs_open, 51 sys_vfs_open,
52 sys_vfs_stat, 52 sys_vfs_stat,
53 sys_vfs_fstat, 53 sys_vfs_fstat,
54 sys_vfs_opendir, 54 sys_vfs_opendir,
55 sys_vfs_fdopendir,
55 sys_vfs_mkdir, 56 sys_vfs_mkdir,
56 sys_vfs_unlink, 57 sys_vfs_unlink,
57 VFS_CHECKS_ACL 58 sys_vfs_rmdir,
59 VFS_CHECKS_ACL,
60 NULL
58 }; 61 };
59 62
60 static VFS_IO sys_file_io = { 63 static VFS_IO sys_file_io = {
61 sys_file_read, 64 sys_file_read,
62 sys_file_write, 65 sys_file_write,
64 sys_file_pwrite, 67 sys_file_pwrite,
65 sys_file_seek, 68 sys_file_seek,
66 sys_file_close, 69 sys_file_close,
67 //sys_file_aioread, 70 //sys_file_aioread,
68 //sys_file_aiowrite, 71 //sys_file_aiowrite,
69 NULL, 72 NULL, // aioread
70 NULL 73 NULL, // aiowrite
74 NULL // getetag
71 }; 75 };
72 76
73 static VFS_DIRIO sys_dir_io = { 77 static VFS_DIRIO sys_dir_io = {
74 sys_dir_read, 78 sys_dir_read,
75 sys_dir_close 79 sys_dir_close
76 }; 80 };
77 81
78 int vfs_init() { 82 int vfs_init(void) {
79 vfs_map = ucx_map_new(16); 83 vfs_type_map = ucx_map_new(16);
80 if(!vfs_map) { 84 if(!vfs_type_map) {
81 return -1; 85 return -1;
82 } 86 }
83 return 0; 87 return 0;
84 } 88 }
85 89
86 void vfs_add(char *name, VFS *vfs) { 90 int vfs_register_type(const char *name, vfs_init_func vfsInit, vfs_create_func vfsCreate) {
87 WS_ASSERT(name); 91 WS_ASSERT(name);
88 92
89 if(!vfs_map) { 93 if(!vfs_type_map) {
90 vfs_init(); 94 if(vfs_init()) {
91 } 95 return 1;
92 ucx_map_cstr_put(vfs_map, name, vfs); 96 }
97 }
98
99 VfsType *vfsType = malloc(sizeof(VfsType));
100 if(!vfsType) {
101 return 1;
102 }
103 vfsType->init = vfsInit;
104 vfsType->create = vfsCreate;
105
106 return ucx_map_cstr_put(vfs_type_map, name, vfsType);
107 }
108
109 VfsType* vfs_get_type(scstr_t vfs_class) {
110 return ucx_map_sstr_get(vfs_type_map, vfs_class);
111 }
112
113 void* vfs_init_backend(ServerConfiguration *cfg, pool_handle_t *pool, VfsType *vfs_class, WSConfigNode *config, int *error) {
114 *error = 0;
115 if(vfs_class->init) {
116 void *initData = vfs_class->init(cfg, pool, config);
117 if(!initData) {
118 *error = 1;
119 }
120 return initData;
121 } else {
122 return NULL;
123 }
124 }
125
126 VFS* vfs_create(Session *sn, Request *rq, const char *vfs_class, pblock *pb, void *initData) {
127 VfsType *vfsType = ucx_map_cstr_get(vfs_type_map, vfs_class);
128 if(!vfsType) {
129 log_ereport(LOG_MISCONFIG, "vfs_create: unkown VFS type %s", vfs_class);
130 return NULL;
131 }
132
133 return vfsType->create(sn, rq, pb, initData);
93 } 134 }
94 135
95 VFSContext* vfs_request_context(Session *sn, Request *rq) { 136 VFSContext* vfs_request_context(Session *sn, Request *rq) {
96 WS_ASSERT(sn); 137 WS_ASSERT(sn);
97 WS_ASSERT(rq); 138 WS_ASSERT(rq);
98 139
99 VFSContext *ctx = pool_malloc(sn->pool, sizeof(VFSContext)); 140 VFSContext *ctx = pool_malloc(sn->pool, sizeof(VFSContext));
141 if(!ctx) {
142 return NULL;
143 }
100 ctx->sn = sn; 144 ctx->sn = sn;
101 ctx->rq = rq; 145 ctx->rq = rq;
102 ctx->vfs = rq->vfs ? rq->vfs : &sys_vfs; 146 ctx->vfs = rq->vfs ? rq->vfs : &sys_vfs;
103 ctx->user = acllist_getuser(sn, rq, rq->acllist); 147 ctx->user = acllist_getuser(sn, rq, rq->acllist);
104 ctx->acllist = rq->acllist; 148 ctx->acllist = rq->acllist;
105 ctx->aclreqaccess = rq->aclreqaccess; 149 ctx->aclreqaccess = rq->aclreqaccess;
106 ctx->pool = sn->pool; 150 ctx->pool = sn->pool;
107 ctx->vfs_errno = 0; 151 ctx->vfs_errno = 0;
152 ctx->error_response_set = 0;
108 return ctx; 153 return ctx;
109 } 154 }
110 155
111 SYS_FILE vfs_open(VFSContext *ctx, char *path, int oflags) { 156 SYS_FILE vfs_open(VFSContext *ctx, const char *path, int oflags) {
112 WS_ASSERT(ctx); 157 WS_ASSERT(ctx);
113 WS_ASSERT(path); 158 WS_ASSERT(path);
114 159
115 uint32_t access_mask = ctx->aclreqaccess | acl_oflag2mask(oflags); 160 uint32_t access_mask = ctx->aclreqaccess | acl_oflag2mask(oflags);
116 161
123 if(sys_acl_check(ctx, access_mask, &sysacl)) { 168 if(sys_acl_check(ctx, access_mask, &sysacl)) {
124 return NULL; 169 return NULL;
125 } 170 }
126 } 171 }
127 SYS_FILE file = ctx->vfs->open(ctx, path, oflags); 172 SYS_FILE file = ctx->vfs->open(ctx, path, oflags);
128 ctx->aclreqaccess = m; // restore original access mask 173 ctx->aclreqaccess = m; // restore original access mask
174 if(!file && ctx) {
175 sys_set_error_status(ctx);
176 }
129 return file; 177 return file;
130 } 178 }
131 179
132 SYS_FILE vfs_openRO(VFSContext *ctx, char *path) { 180 SYS_FILE vfs_openRO(VFSContext *ctx, const char *path) {
133 return vfs_open(ctx, path, O_RDONLY); 181 return vfs_open(ctx, path, O_RDONLY);
134 } 182 }
135 183
136 SYS_FILE vfs_openWO(VFSContext *ctx, char *path) { 184 SYS_FILE vfs_openWO(VFSContext *ctx, const char *path) {
137 return vfs_open(ctx, path, O_WRONLY | O_CREAT); 185 return vfs_open(ctx, path, O_WRONLY | O_CREAT);
138 } 186 }
139 187
140 SYS_FILE vfs_openRW(VFSContext *ctx, char *path) { 188 SYS_FILE vfs_openRW(VFSContext *ctx, const char *path) {
141 return vfs_open(ctx, path, O_RDONLY | O_WRONLY | O_CREAT); 189 return vfs_open(ctx, path, O_RDONLY | O_WRONLY | O_CREAT);
142 } 190 }
143 191
144 int vfs_stat(VFSContext *ctx, char *path, struct stat *buf) { 192 int vfs_stat(VFSContext *ctx, const char *path, struct stat *buf) {
145 WS_ASSERT(ctx); 193 WS_ASSERT(ctx);
146 WS_ASSERT(path); 194 WS_ASSERT(path);
147 195
148 uint32_t access_mask = ctx->aclreqaccess | ACL_READ_ATTRIBUTES; 196 uint32_t access_mask = ctx->aclreqaccess | ACL_READ_ATTRIBUTES;
149 197
157 return -1; 205 return -1;
158 } 206 }
159 } 207 }
160 int ret = ctx->vfs->stat(ctx, path, buf); 208 int ret = ctx->vfs->stat(ctx, path, buf);
161 ctx->aclreqaccess = m; // restore original access mask 209 ctx->aclreqaccess = m; // restore original access mask
210 if(ret && ctx) {
211 sys_set_error_status(ctx);
212 }
162 return ret; 213 return ret;
163 } 214 }
164 215
165 int vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf) { 216 int vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf) {
166 WS_ASSERT(ctx); 217 WS_ASSERT(ctx);
167 WS_ASSERT(fd); 218 WS_ASSERT(fd);
168 WS_ASSERT(buf); 219 WS_ASSERT(buf);
169 220
170 return ctx->vfs->fstat(ctx, fd, buf); 221 int ret = ctx->vfs->fstat(ctx, fd, buf);
222 if(ret && ctx) {
223 sys_set_error_status(ctx);
224 }
225 return ret;
226 }
227
228 const char * vfs_getetag(SYS_FILE fd) {
229 WS_ASSERT(fd);
230
231 if(fd->io->opt_getetag) {
232 return fd->io->opt_getetag(fd);
233 }
234 return NULL;
171 } 235 }
172 236
173 void vfs_close(SYS_FILE fd) { 237 void vfs_close(SYS_FILE fd) {
174 WS_ASSERT(fd); 238 WS_ASSERT(fd);
175 239
179 } else { 243 } else {
180 free(fd); 244 free(fd);
181 } 245 }
182 } 246 }
183 247
184 VFS_DIR vfs_opendir(VFSContext *ctx, char *path) { 248 VFS_DIR vfs_opendir(VFSContext *ctx, const char *path) {
185 WS_ASSERT(ctx); 249 WS_ASSERT(ctx);
186 WS_ASSERT(path); 250 WS_ASSERT(path);
187 251
188 uint32_t access_mask = ctx->aclreqaccess | ACL_LIST; 252 uint32_t access_mask = ctx->aclreqaccess | ACL_LIST;
189 253
197 return NULL; 261 return NULL;
198 } 262 }
199 } 263 }
200 VFS_DIR dir = ctx->vfs->opendir(ctx, path); 264 VFS_DIR dir = ctx->vfs->opendir(ctx, path);
201 ctx->aclreqaccess = m; // restore original access mask 265 ctx->aclreqaccess = m; // restore original access mask
266 if(!dir && ctx) {
267 sys_set_error_status(ctx);
268 }
269 return dir;
270 }
271
272 VFS_DIR vfs_fdopendir(VFSContext *ctx, SYS_FILE fd) {
273 WS_ASSERT(ctx);
274 WS_ASSERT(path);
275
276 uint32_t access_mask = ctx->aclreqaccess | ACL_LIST;
277
278 // ctx->aclreqaccess should be the complete access mask
279 uint32_t m = ctx->aclreqaccess; // save original access mask
280 ctx->aclreqaccess = access_mask; // set mask for vfs->open call
281 if((ctx->vfs->flags & VFS_CHECKS_ACL) != VFS_CHECKS_ACL) {
282 // VFS does not evaluates the ACL itself, so we have to do it here
283 SysACL sysacl;
284 if(sys_acl_check(ctx, access_mask, &sysacl)) {
285 return NULL;
286 }
287 }
288 VFS_DIR dir = ctx->vfs->fdopendir(ctx, fd);
289 ctx->aclreqaccess = m; // restore original access mask
290 if(!dir && ctx) {
291 sys_set_error_status(ctx);
292 }
202 return dir; 293 return dir;
203 } 294 }
204 295
205 int vfs_readdir(VFS_DIR dir, VFS_ENTRY *entry) { 296 int vfs_readdir(VFS_DIR dir, VFS_ENTRY *entry) {
206 WS_ASSERT(dir); 297 WS_ASSERT(dir);
225 } else { 316 } else {
226 free(dir); 317 free(dir);
227 } 318 }
228 } 319 }
229 320
230 int vfs_mkdir(VFSContext *ctx, char *path) { 321 int vfs_mkdir(VFSContext *ctx, const char *path) {
231 WS_ASSERT(ctx); 322 WS_ASSERT(ctx);
232 WS_ASSERT(path); 323 WS_ASSERT(path);
233 324
234 return vfs_path_op(ctx, path, ctx->vfs->mkdir, ACL_ADD_FILE); 325 return vfs_path_op(ctx, path, ctx->vfs->mkdir, ACL_ADD_FILE);
235 } 326 }
236 327
237 int vfs_unlink(VFSContext *ctx, char *path) { 328 int vfs_unlink(VFSContext *ctx, const char *path) {
238 WS_ASSERT(ctx); 329 WS_ASSERT(ctx);
239 WS_ASSERT(path); 330 WS_ASSERT(path);
240 331
241 return vfs_path_op(ctx, path, ctx->vfs->unlink, ACL_DELETE); 332 return vfs_path_op(ctx, path, ctx->vfs->unlink, ACL_DELETE);
242 } 333 }
243 334
335 int vfs_rmdir(VFSContext *ctx, const char *path) {
336 WS_ASSERT(ctx);
337 WS_ASSERT(path);
338
339 return vfs_path_op(ctx, path, ctx->vfs->rmdir, ACL_DELETE);
340 }
244 341
245 // private 342 // private
246 int vfs_path_op(VFSContext *ctx, char *path, vfs_op_f op, uint32_t access) { 343 int vfs_path_op(VFSContext *ctx, const char *path, vfs_op_f op, uint32_t access) {
247 uint32_t access_mask = ctx->aclreqaccess; 344 uint32_t access_mask = ctx->aclreqaccess;
248 access_mask |= access; 345 access_mask |= access;
249 346
250 // ctx->aclreqaccess should be the complete access mask 347 // ctx->aclreqaccess should be the complete access mask
251 uint32_t m = ctx->aclreqaccess; // save original access mask 348 uint32_t m = ctx->aclreqaccess; // save original access mask
257 return -1; 354 return -1;
258 } 355 }
259 } 356 }
260 int ret = op(ctx, path); 357 int ret = op(ctx, path);
261 ctx->aclreqaccess = m; // restore original access mask 358 ctx->aclreqaccess = m; // restore original access mask
359 if(ret && ctx) {
360 sys_set_error_status(ctx);
361 }
262 return ret; 362 return ret;
263 } 363 }
264 364
265 /* system vfs implementation */ 365 /* system vfs implementation */
266 366
267 SYS_FILE sys_vfs_open(VFSContext *ctx, char *path, int oflags) { 367 SYS_FILE sys_vfs_open(VFSContext *ctx, const char *path, int oflags) {
268 uint32_t access_mask = ctx->aclreqaccess; 368 uint32_t access_mask = ctx->aclreqaccess;
269 pool_handle_t *pool = ctx->pool; 369 pool_handle_t *pool = ctx->pool;
270 370
271 // check ACLs 371 // check ACLs
272 SysACL sysacl; 372 SysACL sysacl;
311 file->fd = fd; 411 file->fd = fd;
312 file->io = &sys_file_io; 412 file->io = &sys_file_io;
313 return file; 413 return file;
314 } 414 }
315 415
316 int sys_vfs_stat(VFSContext *ctx, char *path, struct stat *buf) { 416 int sys_vfs_stat(VFSContext *ctx, const char *path, struct stat *buf) {
317 uint32_t access_mask = ctx->aclreqaccess; 417 uint32_t access_mask = ctx->aclreqaccess;
318 418
319 // check ACLs 419 // check ACLs
320 SysACL sysacl; 420 SysACL sysacl;
321 if(sys_acl_check(ctx, access_mask, &sysacl)) { 421 if(sys_acl_check(ctx, access_mask, &sysacl)) {
351 } 451 }
352 452
353 return 0; 453 return 0;
354 } 454 }
355 455
356 VFS_DIR sys_vfs_opendir(VFSContext *ctx, char *path) { 456 VFS_DIR sys_vfs_opendir(VFSContext *ctx, const char *path) {
357 uint32_t access_mask = ctx->aclreqaccess; 457 uint32_t access_mask = ctx->aclreqaccess;
358 pool_handle_t *pool = ctx->pool; 458 pool_handle_t *pool = ctx->pool;
359 459
360 // check ACLs 460 // check ACLs
361 SysACL sysacl; 461 SysACL sysacl;
384 return NULL; 484 return NULL;
385 } 485 }
386 DIR *sys_dir = fdopendir(dir_fd); 486 DIR *sys_dir = fdopendir(dir_fd);
387 #endif 487 #endif
388 if(!sys_dir) { 488 if(!sys_dir) {
489 if(dir_fd > 0) {
490 close(dir_fd);
491 }
389 if(ctx) { 492 if(ctx) {
390 ctx->vfs_errno = errno; 493 ctx->vfs_errno = errno;
391 sys_set_error_status(ctx); 494 sys_set_error_status(ctx);
392 } 495 }
393 return NULL; 496 return NULL;
420 dir->fd = dir_fd; 523 dir->fd = dir_fd;
421 dir->io = &sys_dir_io; 524 dir->io = &sys_dir_io;
422 return dir; 525 return dir;
423 } 526 }
424 527
425 int sys_vfs_mkdir(VFSContext *ctx, char *path) { 528 VFS_DIR sys_vfs_fdopendir(VFSContext *ctx, SYS_FILE fd) {
529 uint32_t access_mask = ctx->aclreqaccess;
530 pool_handle_t *pool = ctx->pool;
531
532 // check ACLs
533 SysACL sysacl;
534 if(sys_acl_check(ctx, access_mask, &sysacl)) {
535 return NULL;
536 }
537
538 if(sysacl.acl) {
539 if(!fs_acl_check_fd(&sysacl, ctx->user, fd->fd, access_mask)) {
540 acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user);
541 return NULL;
542 }
543 }
544
545 // open directory
546 DIR *sys_dir = fdopendir(fd->fd);
547 if(!sys_dir) {
548 if(ctx) {
549 ctx->vfs_errno = errno;
550 sys_set_error_status(ctx);
551 }
552 return NULL;
553 }
554
555 SysVFSDir *dir_data = VFS_MALLOC(pool, sizeof(SysVFSDir));
556 if(!dir_data) {
557 closedir(sys_dir);
558 return NULL;
559 }
560 long maxfilelen = fpathconf(fd->fd, _PC_NAME_MAX);
561 size_t entry_len = offsetof(struct dirent, d_name) + maxfilelen + 1;
562 dir_data->cur = VFS_MALLOC(pool, entry_len);
563 if(!dir_data->cur) {
564 closedir(sys_dir);
565 VFS_FREE(pool, dir_data);
566 return NULL;
567 }
568 dir_data->dir = sys_dir;
569
570 VFSDir *dir = VFS_MALLOC(pool, sizeof(VFSDir));
571 if(!dir) {
572 closedir(sys_dir);
573 VFS_FREE(pool, dir_data->cur);
574 VFS_FREE(pool, dir_data);
575 return NULL;
576 }
577 dir->ctx = ctx;
578 dir->data = dir_data;
579 dir->fd = fd->fd;
580 dir->io = &sys_dir_io;
581 return dir;
582 }
583
584 int sys_vfs_mkdir(VFSContext *ctx, const char *path) {
426 return sys_path_op(ctx, path, sys_mkdir); 585 return sys_path_op(ctx, path, sys_mkdir);
427 } 586 }
428 587
429 int sys_vfs_unlink(VFSContext *ctx, char *path) { 588 int sys_vfs_unlink(VFSContext *ctx, const char *path) {
430 return sys_path_op(ctx, path, sys_unlink); 589 return sys_path_op(ctx, path, sys_unlink);
431 } 590 }
432 591
433 592 int sys_vfs_rmdir(VFSContext *ctx, const char *path) {
434 int sys_path_op(VFSContext *ctx, char *path, sys_op_f op) { 593 return sys_path_op(ctx, path, sys_rmdir);
594 }
595
596
597 int sys_path_op(VFSContext *ctx, const char *path, sys_op_f op) {
435 uint32_t access_mask = ctx->aclreqaccess; 598 uint32_t access_mask = ctx->aclreqaccess;
436 599
437 // check ACLs 600 // check ACLs
438 SysACL sysacl; 601 SysACL sysacl;
439 if(sys_acl_check(ctx, access_mask, &sysacl)) { 602 if(sys_acl_check(ctx, access_mask, &sysacl)) {
482 645
483 return 0; 646 return 0;
484 } 647 }
485 648
486 void sys_set_error_status(VFSContext *ctx) { 649 void sys_set_error_status(VFSContext *ctx) {
487 if(ctx->sn && ctx->rq) { 650 if(ctx->sn && ctx->rq && !ctx->error_response_set) {
488 int status = util_errno2status(ctx->vfs_errno); 651 int status = util_errno2status(ctx->vfs_errno);
489 protocol_status(ctx->sn, ctx->rq, status, NULL); 652 protocol_status(ctx->sn, ctx->rq, status, NULL);
653 ctx->error_response_set = TRUE;
490 } 654 }
491 } 655 }
492 656
493 ssize_t sys_file_read(SYS_FILE fd, void *buf, size_t nbyte) { 657 ssize_t sys_file_read(SYS_FILE fd, void *buf, size_t nbyte) {
494 return read(fd->fd, buf, nbyte); 658 return read(fd->fd, buf, nbyte);
537 return sys_dir_read(dir, entry, getstat); 701 return sys_dir_read(dir, entry, getstat);
538 } else { 702 } else {
539 entry->name = name; 703 entry->name = name;
540 if(getstat) { 704 if(getstat) {
541 // TODO: check ACLs again for new path 705 // TODO: check ACLs again for new path
706 entry->stat_errno = 0;
542 if(fstatat(dir->fd, result->d_name, &entry->stat, 0)) { 707 if(fstatat(dir->fd, result->d_name, &entry->stat, 0)) {
543 entry->stat_errno = errno; 708 entry->stat_errno = errno;
544 } 709 }
545 entry->stat_extra = NULL; 710 entry->stat_extra = NULL;
546 } 711 }
565 free(dirdata); 730 free(dirdata);
566 free(dir); 731 free(dir);
567 } 732 }
568 } 733 }
569 734
570 int sys_mkdir(VFSContext *ctx, char *path, SysACL *sysacl) { 735 int sys_mkdir(VFSContext *ctx, const char *path, SysACL *sysacl) {
571 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 736 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
572 int ret = mkdir(path, mode); 737 int ret = mkdir(path, mode);
573 if(ret == 0) { 738 if(ret == 0) {
574 if(sysacl->user_uid != -1) { 739 if(sysacl->user_uid != -1) {
575 if(chown(path, sysacl->user_uid, sysacl->user_gid)) { 740 if(chown(path, sysacl->user_uid, sysacl->user_gid)) {
578 } 743 }
579 } 744 }
580 return ret; 745 return ret;
581 } 746 }
582 747
583 int sys_unlink(VFSContext *ctx, char *path, SysACL *sysacl) { 748 int sys_unlink(VFSContext *ctx, const char *path, SysACL *sysacl) {
584 return unlink(path); 749 return unlink(path);
750 }
751
752 int sys_rmdir(VFSContext *ctx, const char *path, SysACL *sysacl) {
753 return rmdir(path);
585 } 754 }
586 755
587 /* public file api */ 756 /* public file api */
588 757
589 NSAPI_PUBLIC int system_fread(SYS_FILE fd, void *buf, int nbyte) { 758 NSAPI_PUBLIC int system_fread(SYS_FILE fd, void *buf, int nbyte) {

mercurial