src/server/daemon/vfs.c

branch
aio
changeset 165
6942a8c3e737
parent 105
63d9051fe35c
child 172
5580517faafc
equal deleted inserted replaced
159:9ba9f8befa80 165:6942a8c3e737
37 37
38 #include "../util/pool.h" 38 #include "../util/pool.h"
39 #include "acl.h" 39 #include "acl.h"
40 #include "vfs.h" 40 #include "vfs.h"
41 41
42 #define VFS_MALLOC(pool, size) pool ? pool_malloc(pool, size) : malloc(size)
43 #define VFS_FREE(pool, ptr) pool ? pool_free(pool, ptr) : free(ptr)
44
42 static UcxMap *vfs_map; 45 static UcxMap *vfs_map;
46
47 static VFS sys_vfs = {
48 sys_vfs_open,
49 sys_vfs_stat,
50 sys_vfs_fstat,
51 sys_vfs_opendir,
52 sys_vfs_mkdir,
53 sys_vfs_unlink,
54 VFS_CHECKS_ACL
55 };
43 56
44 static VFS_IO sys_file_io = { 57 static VFS_IO sys_file_io = {
45 sys_file_read, 58 sys_file_read,
46 sys_file_write, 59 sys_file_write,
47 sys_file_seek, 60 sys_file_seek,
75 WS_ASSERT(rq); 88 WS_ASSERT(rq);
76 89
77 VFSContext *ctx = pool_malloc(sn->pool, sizeof(VFSContext)); 90 VFSContext *ctx = pool_malloc(sn->pool, sizeof(VFSContext));
78 ctx->sn = sn; 91 ctx->sn = sn;
79 ctx->rq = rq; 92 ctx->rq = rq;
80 ctx->vfs = rq->vfs; 93 ctx->vfs = rq->vfs ? rq->vfs : &sys_vfs;
81 ctx->user = acllist_getuser(sn, rq, rq->acllist); 94 ctx->user = acllist_getuser(sn, rq, rq->acllist);
82 ctx->acllist = rq->acllist; 95 ctx->acllist = rq->acllist;
83 ctx->aclreqaccess = rq->aclreqaccess; 96 ctx->aclreqaccess = rq->aclreqaccess;
84 ctx->pool = sn->pool; 97 ctx->pool = sn->pool;
85 ctx->vfs_errno = 0; 98 ctx->vfs_errno = 0;
86 return ctx; 99 return ctx;
87 } 100 }
88 101
89 SYS_FILE vfs_open(VFSContext *ctx, char *path, int oflags) { 102 SYS_FILE vfs_open(VFSContext *ctx, char *path, int oflags) {
103 WS_ASSERT(ctx);
90 WS_ASSERT(path); 104 WS_ASSERT(path);
91 105
92 Session *sn; 106 uint32_t access_mask = ctx->aclreqaccess | acl_oflag2mask(oflags);
93 Request *rq; 107
94 pool_handle_t *pool; 108 // ctx->aclreqaccess should be the complete access mask
95 uint32_t access_mask; 109 uint32_t m = ctx->aclreqaccess; // save original access mask
96 110 ctx->aclreqaccess = access_mask; // set mask for vfs->open call
97 if(ctx) { 111 if((ctx->vfs->flags & VFS_CHECKS_ACL) != VFS_CHECKS_ACL) {
98 access_mask = ctx->aclreqaccess; 112 // VFS does not evaluates the ACL itself, so we have to do it here
99 access_mask |= acl_oflag2mask(oflags); 113 SysACL sysacl;
100 if(!ctx->pool) { 114 if(sys_acl_check(ctx, access_mask, &sysacl)) {
101 // TODO: log warning 115 return NULL;
102 // broken VFSContext 116 }
103 } 117 }
104 if(ctx->vfs) { 118 SYS_FILE file = ctx->vfs->open(ctx, path, oflags);
105 // ctx->aclreqaccess should be the complete access mask 119 ctx->aclreqaccess = m; // restore original access mask
106 uint32_t m = ctx->aclreqaccess; // save original access mask 120 return file;
107 ctx->aclreqaccess = access_mask; // set mask for vfs->open call 121 }
108 SYS_FILE file = ctx->vfs->open(ctx, path, oflags); 122
109 ctx->aclreqaccess = m; // restore original access mask 123 SYS_FILE vfs_openRO(VFSContext *ctx, char *path) {
110 return file; 124 return vfs_open(ctx, path, O_RDONLY);
111 } else { 125 }
112 pool = ctx->pool; 126
113 } 127 SYS_FILE vfs_openWO(VFSContext *ctx, char *path) {
128 return vfs_open(ctx, path, O_WRONLY | O_CREAT);
129 }
130
131 SYS_FILE vfs_openRW(VFSContext *ctx, char *path) {
132 return vfs_open(ctx, path, O_RDONLY | O_WRONLY | O_CREAT);
133 }
134
135 int vfs_stat(VFSContext *ctx, char *path, struct stat *buf) {
136 WS_ASSERT(ctx);
137 WS_ASSERT(path);
138
139 uint32_t access_mask = ctx->aclreqaccess | ACL_READ_ATTRIBUTES;
140
141 // ctx->aclreqaccess should be the complete access mask
142 uint32_t m = ctx->aclreqaccess; // save original access mask
143 ctx->aclreqaccess = access_mask; // set mask for vfs->open call
144 if((ctx->vfs->flags & VFS_CHECKS_ACL) != VFS_CHECKS_ACL) {
145 // VFS does not evaluates the ACL itself, so we have to do it here
146 SysACL sysacl;
147 if(sys_acl_check(ctx, access_mask, &sysacl)) {
148 return -1;
149 }
150 }
151 int ret = ctx->vfs->stat(ctx, path, buf);
152 ctx->aclreqaccess = m; // restore original access mask
153 return ret;
154 }
155
156 int vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf) {
157 WS_ASSERT(ctx);
158 WS_ASSERT(fd);
159 WS_ASSERT(buf);
160
161 return ctx->vfs->fstat(ctx, fd, buf);
162 }
163
164 void vfs_close(SYS_FILE fd) {
165 WS_ASSERT(fd);
166
167 fd->io->close(fd);
168 if(fd->ctx) {
169 pool_free(fd->ctx->pool, fd);
114 } else { 170 } else {
115 sn = NULL; 171 free(fd);
116 rq = NULL; 172 }
117 pool = NULL; 173 }
118 access_mask = acl_oflag2mask(oflags); 174
119 } 175 VFS_DIR vfs_opendir(VFSContext *ctx, char *path) {
176 WS_ASSERT(ctx);
177 WS_ASSERT(path);
178
179 uint32_t access_mask = ctx->aclreqaccess | ACL_LIST;
180
181 // ctx->aclreqaccess should be the complete access mask
182 uint32_t m = ctx->aclreqaccess; // save original access mask
183 ctx->aclreqaccess = access_mask; // set mask for vfs->open call
184 if((ctx->vfs->flags & VFS_CHECKS_ACL) != VFS_CHECKS_ACL) {
185 // VFS does not evaluates the ACL itself, so we have to do it here
186 SysACL sysacl;
187 if(sys_acl_check(ctx, access_mask, &sysacl)) {
188 return NULL;
189 }
190 }
191 VFS_DIR dir = ctx->vfs->opendir(ctx, path);
192 ctx->aclreqaccess = m; // restore original access mask
193 return dir;
194 }
195
196 int vfs_readdir(VFS_DIR dir, VFS_ENTRY *entry) {
197 WS_ASSERT(dir);
198 WS_ASSERT(entry);
199
200 return dir->io->readdir(dir, entry, 0);
201 }
202
203 int vfs_readdir_stat(VFS_DIR dir, VFS_ENTRY *entry) {
204 WS_ASSERT(dir);
205 WS_ASSERT(entry);
206
207 return dir->io->readdir(dir, entry, 1);
208 }
209
210 void vfs_closedir(VFS_DIR dir) {
211 WS_ASSERT(dir);
212
213 dir->io->close(dir);
214 if(dir->ctx) {
215 VFS_FREE(dir->ctx->pool, dir);
216 } else {
217 free(dir);
218 }
219 }
220
221 int vfs_mkdir(VFSContext *ctx, char *path) {
222 WS_ASSERT(ctx);
223 WS_ASSERT(path);
224
225 return vfs_path_op(ctx, path, ctx->vfs->mkdir, ACL_ADD_FILE);
226 }
227
228 int vfs_unlink(VFSContext *ctx, char *path) {
229 WS_ASSERT(ctx);
230 WS_ASSERT(path);
231
232 return vfs_path_op(ctx, path, ctx->vfs->unlink, ACL_DELETE);
233 }
234
235
236 // private
237 int vfs_path_op(VFSContext *ctx, char *path, vfs_op_f op, uint32_t access) {
238 uint32_t access_mask = ctx->aclreqaccess;
239 access_mask |= access;
240
241 // ctx->aclreqaccess should be the complete access mask
242 uint32_t m = ctx->aclreqaccess; // save original access mask
243 ctx->aclreqaccess = access_mask; // set mask for vfs function call
244 if((ctx->vfs->flags & VFS_CHECKS_ACL) != VFS_CHECKS_ACL) {
245 // VFS does not evaluates the ACL itself, so we have to do it here
246 SysACL sysacl;
247 if(sys_acl_check(ctx, access_mask, &sysacl)) {
248 return -1;
249 }
250 }
251 int ret = op(ctx, path);
252 ctx->aclreqaccess = m; // restore original access mask
253 return ret;
254 }
255
256 /* system vfs implementation */
257
258 SYS_FILE sys_vfs_open(VFSContext *ctx, char *path, int oflags) {
259 uint32_t access_mask = ctx->aclreqaccess;
260 pool_handle_t *pool = ctx->pool;
120 261
121 // check ACLs 262 // check ACLs
122 SysACL sysacl; 263 SysACL sysacl;
123 if(sys_acl_check(ctx, access_mask, &sysacl)) { 264 if(sys_acl_check(ctx, access_mask, &sysacl)) {
124 return NULL; 265 return NULL;
149 close(fd); 290 close(fd);
150 return NULL; 291 return NULL;
151 } 292 }
152 } 293 }
153 294
154 295 VFSFile *file = VFS_MALLOC(pool, sizeof(VFSFile));
155 VFSFile *file = pool ?
156 pool_malloc(pool, sizeof(VFSFile)) : malloc(sizeof(VFSFile));
157 if(!file) { 296 if(!file) {
158 close(fd); 297 close(fd);
159 return NULL; 298 return NULL;
160 } 299 }
161 file->ctx = ctx; 300 file->ctx = ctx;
163 file->fd = fd; 302 file->fd = fd;
164 file->io = &sys_file_io; 303 file->io = &sys_file_io;
165 return file; 304 return file;
166 } 305 }
167 306
168 SYS_FILE vfs_openRO(VFSContext *ctx, char *path) { 307 int sys_vfs_stat(VFSContext *ctx, char *path, struct stat *buf) {
169 return vfs_open(ctx, path, O_RDONLY); 308 uint32_t access_mask = ctx->aclreqaccess;
170 }
171
172 SYS_FILE vfs_openWO(VFSContext *ctx, char *path) {
173 return vfs_open(ctx, path, O_WRONLY | O_CREAT);
174 }
175
176 SYS_FILE vfs_openRW(VFSContext *ctx, char *path) {
177 return vfs_open(ctx, path, O_RDONLY | O_WRONLY | O_CREAT);
178 }
179
180 int vfs_stat(VFSContext *ctx, char *path, struct stat *buf) {
181 Session *sn;
182 Request *rq;
183 uint32_t access_mask;
184
185 if(ctx) {
186 access_mask = ctx->aclreqaccess;
187 access_mask |= ACL_READ_ATTRIBUTES;
188 if(!ctx->pool) {
189 // TODO: log warning
190 // broken VFSContext
191 }
192 if(ctx->vfs) {
193 // ctx->aclreqaccess should be the complete access mask
194 uint32_t m = ctx->aclreqaccess; // save original access mask
195 ctx->aclreqaccess = access_mask; // set mask for vfs->fstat call
196 int ret = ctx->vfs->stat(ctx, path, buf);
197 ctx->aclreqaccess = m; // restore original access mask
198 return ret;
199 }
200 } else {
201 sn = NULL;
202 rq = NULL;
203 access_mask = ACL_READ_ATTRIBUTES;
204 }
205 309
206 // check ACLs 310 // check ACLs
207 SysACL sysacl; 311 SysACL sysacl;
208 if(sys_acl_check(ctx, access_mask, &sysacl)) { 312 if(sys_acl_check(ctx, access_mask, &sysacl)) {
209 return -1; 313 return -1;
226 } 330 }
227 331
228 return 0; 332 return 0;
229 } 333 }
230 334
231 int vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf) { 335 int sys_vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf) {
232 if(ctx) {
233 if(!ctx->pool) {
234 // TODO: log warning
235 // broken VFSContext
236 }
237 if(ctx->vfs) {
238 return ctx->vfs->fstat(ctx, fd, buf);
239 }
240 }
241
242 // stat 336 // stat
243 if(fstat(fd->fd, buf)) { 337 if(fstat(fd->fd, buf)) {
244 if(ctx) { 338 if(ctx) {
245 ctx->vfs_errno = errno; 339 ctx->vfs_errno = errno;
246 } 340 }
248 } 342 }
249 343
250 return 0; 344 return 0;
251 } 345 }
252 346
253 void vfs_close(SYS_FILE fd) { 347 VFS_DIR sys_vfs_opendir(VFSContext *ctx, char *path) {
254 fd->io->close(fd); 348 uint32_t access_mask = ctx->aclreqaccess;
255 if(fd->ctx) { 349 pool_handle_t *pool = ctx->pool;
256 pool_free(fd->ctx->pool, fd);
257 } else {
258 free(fd);
259 }
260 }
261
262 VFS_DIR vfs_opendir(VFSContext *ctx, char *path) {
263 WS_ASSERT(path);
264
265 Session *sn;
266 Request *rq;
267 pool_handle_t *pool;
268 uint32_t access_mask;
269
270 if(ctx) {
271 access_mask = ctx->aclreqaccess;
272 access_mask |= ACL_LIST;
273 if(!ctx->pool) {
274 // TODO: log warning
275 // broken VFSContext
276 }
277 if(ctx->vfs) {
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->opendir call
281 VFS_DIR dir = ctx->vfs->opendir(ctx, path);
282 ctx->aclreqaccess = m; // restore original access mask
283 return dir;
284 } else {
285 pool = ctx->pool;
286 }
287 } else {
288 sn = NULL;
289 rq = NULL;
290 pool = NULL;
291 access_mask = ACL_LIST;
292 }
293 350
294 // check ACLs 351 // check ACLs
295 SysACL sysacl; 352 SysACL sysacl;
296 if(sys_acl_check(ctx, access_mask, &sysacl)) { 353 if(sys_acl_check(ctx, access_mask, &sysacl)) {
297 return NULL; 354 return NULL;
325 sys_set_error_status(ctx); 382 sys_set_error_status(ctx);
326 } 383 }
327 return NULL; 384 return NULL;
328 } 385 }
329 386
330 SysVFSDir *dir_data = pool ? 387 SysVFSDir *dir_data = VFS_MALLOC(pool, sizeof(SysVFSDir));
331 pool_malloc(pool, sizeof(SysVFSDir)) : malloc(sizeof(SysVFSDir));
332 if(!dir_data) { 388 if(!dir_data) {
333 closedir(sys_dir); 389 closedir(sys_dir);
334 return NULL; 390 return NULL;
335 } 391 }
336 long maxfilelen = fpathconf(dir_fd, _PC_NAME_MAX); 392 long maxfilelen = fpathconf(dir_fd, _PC_NAME_MAX);
337 size_t entry_len = offsetof(struct dirent, d_name) + maxfilelen + 1; 393 size_t entry_len = offsetof(struct dirent, d_name) + maxfilelen + 1;
338 dir_data->cur = pool ? 394 dir_data->cur = VFS_MALLOC(pool, entry_len);
339 pool_malloc(pool, entry_len) : malloc(entry_len);
340 if(!dir_data->cur) { 395 if(!dir_data->cur) {
341 closedir(sys_dir); 396 closedir(sys_dir);
397 VFS_FREE(pool, dir_data);
342 return NULL; 398 return NULL;
343 } 399 }
344 dir_data->dir = sys_dir; 400 dir_data->dir = sys_dir;
345 401
346 VFSDir *dir = pool ? 402 VFSDir *dir = VFS_MALLOC(pool, sizeof(VFSDir));
347 pool_malloc(pool, sizeof(VFSDir)) : malloc(sizeof(VFSDir));
348 if(!dir) { 403 if(!dir) {
349 closedir(sys_dir); 404 closedir(sys_dir);
405 VFS_FREE(pool, dir_data->cur);
406 VFS_FREE(pool, dir_data);
350 return NULL; 407 return NULL;
351 } 408 }
352 dir->ctx = ctx; 409 dir->ctx = ctx;
353 dir->data = dir_data; 410 dir->data = dir_data;
354 dir->fd = dir_fd; 411 dir->fd = dir_fd;
355 dir->io = &sys_dir_io; 412 dir->io = &sys_dir_io;
356 return dir; 413 return dir;
357 } 414 }
358 415
359 int vfs_readdir(VFS_DIR dir, VFS_ENTRY *entry) { 416 int sys_vfs_mkdir(VFSContext *ctx, char *path) {
360 return dir->io->readdir(dir, entry, 0); 417 return sys_path_op(ctx, path, sys_mkdir);
361 } 418 }
362 419
363 int vfs_readdir_stat(VFS_DIR dir, VFS_ENTRY *entry) { 420 int sys_vfs_unlink(VFSContext *ctx, char *path) {
364 return dir->io->readdir(dir, entry, 1); 421 return sys_path_op(ctx, path, sys_unlink);
365 } 422 }
366 423
367 void vfs_closedir(VFS_DIR dir) { 424
368 dir->io->close(dir); 425 int sys_path_op(VFSContext *ctx, char *path, sys_op_f op) {
369 if(dir->ctx) {
370 pool_free(dir->ctx->pool, dir);
371 } else {
372 free(dir);
373 }
374 }
375
376 int vfs_mkdir(VFSContext *ctx, char *path) {
377 if(ctx && ctx->vfs) {
378 return vfs_path_op(ctx, path, ctx->vfs->mkdir, ACL_ADD_FILE);
379 } else {
380 return sys_path_op(ctx, path, sys_mkdir, ACL_ADD_FILE);
381 }
382 }
383
384 int vfs_unlink(VFSContext *ctx, char *path) {
385 if(ctx && ctx->vfs) {
386 return vfs_path_op(ctx, path, ctx->vfs->unlink, ACL_DELETE);
387 } else {
388 return sys_path_op(ctx, path, sys_unlink, ACL_DELETE);
389 }
390 }
391
392
393 // private
394 int vfs_path_op(VFSContext *ctx, char *path, vfs_op_f op, uint32_t access) {
395 Session *sn;
396 Request *rq;
397
398 uint32_t access_mask = ctx->aclreqaccess; 426 uint32_t access_mask = ctx->aclreqaccess;
399 access_mask |= access;
400 if(!ctx->pool) {
401 // TODO: log warning
402 // broken VFSContext
403 return -1;
404 }
405
406 // ctx->aclreqaccess should be the complete access mask
407 uint32_t m = ctx->aclreqaccess; // save original access mask
408 ctx->aclreqaccess = access_mask; // set mask for vfs function call
409 int ret = op(ctx, path);
410 ctx->aclreqaccess = m; // restore original access mask
411 return ret;
412 }
413
414 int sys_path_op(VFSContext *ctx, char *path, sys_op_f op, uint32_t access) {
415 if(ctx) {
416 access |= ctx->aclreqaccess;
417 }
418 427
419 // check ACLs 428 // check ACLs
420 SysACL sysacl; 429 SysACL sysacl;
421 if(sys_acl_check(ctx, access, &sysacl)) { 430 if(sys_acl_check(ctx, access_mask, &sysacl)) {
422 return -1; 431 return -1;
423 } 432 }
424 433
425 if(sysacl.acl) { 434 if(sysacl.acl) {
426 if(!fs_acl_check(&sysacl, ctx->user, path, access)) { 435 if(!fs_acl_check(&sysacl, ctx->user, path, access_mask)) {
427 acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user); 436 acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user);
428 return -1; 437 return -1;
429 } 438 }
430 } 439 }
431 440
432 // do path operation 441 // do path operation
433 if(op(ctx, path, &sysacl)) { 442 if(op(ctx, path, &sysacl)) {
434 // error 443 // error
435 if(ctx) { 444 ctx->vfs_errno = errno;
436 ctx->vfs_errno = errno; 445 sys_set_error_status(ctx);
437 sys_set_error_status(ctx);
438 }
439 return -1; 446 return -1;
440 } 447 }
441 448
442 return 0; 449 return 0;
443 } 450 }

mercurial