src/server/daemon/vfs.c

changeset 193
aa8393527b1e
parent 171
af7e2d80dee6
parent 190
1f73302461e0
child 211
2160585200ac
equal deleted inserted replaced
183:f33974f0dce0 193:aa8393527b1e
30 30
31 #include <stdio.h> 31 #include <stdio.h>
32 #include <stdlib.h> 32 #include <stdlib.h>
33 #include <unistd.h> 33 #include <unistd.h>
34 #include <sys/types.h> 34 #include <sys/types.h>
35 #include <aio.h>
35 #include <ucx/map.h> 36 #include <ucx/map.h>
36 37
37 #include "../util/pool.h" 38 #include "../util/pool.h"
38 #include "netsite.h" 39 #include "netsite.h"
39 #include "acl.h" 40 #include "acl.h"
40 #include "vfs.h" 41 #include "vfs.h"
42 #include "threadpools.h"
43 #include "event.h"
44
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)
41 47
42 static UcxMap *vfs_map; 48 static UcxMap *vfs_map;
49
50 static VFS sys_vfs = {
51 sys_vfs_open,
52 sys_vfs_stat,
53 sys_vfs_fstat,
54 sys_vfs_opendir,
55 sys_vfs_mkdir,
56 sys_vfs_unlink,
57 VFS_CHECKS_ACL
58 };
43 59
44 static VFS_IO sys_file_io = { 60 static VFS_IO sys_file_io = {
45 sys_file_read, 61 sys_file_read,
46 sys_file_write, 62 sys_file_write,
63 sys_file_pread,
64 sys_file_pwrite,
47 sys_file_seek, 65 sys_file_seek,
48 sys_file_close 66 sys_file_close,
67 //sys_file_aioread,
68 //sys_file_aiowrite,
69 NULL,
70 NULL
49 }; 71 };
50 72
51 static VFS_DIRIO sys_dir_io = { 73 static VFS_DIRIO sys_dir_io = {
52 sys_dir_read, 74 sys_dir_read,
53 sys_dir_close 75 sys_dir_close
75 WS_ASSERT(rq); 97 WS_ASSERT(rq);
76 98
77 VFSContext *ctx = pool_malloc(sn->pool, sizeof(VFSContext)); 99 VFSContext *ctx = pool_malloc(sn->pool, sizeof(VFSContext));
78 ctx->sn = sn; 100 ctx->sn = sn;
79 ctx->rq = rq; 101 ctx->rq = rq;
80 ctx->vfs = rq->vfs; 102 ctx->vfs = rq->vfs ? rq->vfs : &sys_vfs;
81 ctx->user = acllist_getuser(sn, rq, rq->acllist); 103 ctx->user = acllist_getuser(sn, rq, rq->acllist);
82 ctx->acllist = rq->acllist; 104 ctx->acllist = rq->acllist;
83 ctx->aclreqaccess = rq->aclreqaccess; 105 ctx->aclreqaccess = rq->aclreqaccess;
84 ctx->pool = sn->pool; 106 ctx->pool = sn->pool;
85 ctx->vfs_errno = 0; 107 ctx->vfs_errno = 0;
86 return ctx; 108 return ctx;
87 } 109 }
88 110
89 SYS_FILE vfs_open(VFSContext *ctx, char *path, int oflags) { 111 SYS_FILE vfs_open(VFSContext *ctx, char *path, int oflags) {
112 WS_ASSERT(ctx);
90 WS_ASSERT(path); 113 WS_ASSERT(path);
91 114
92 Session *sn; 115 uint32_t access_mask = ctx->aclreqaccess | acl_oflag2mask(oflags);
93 Request *rq; 116
94 pool_handle_t *pool; 117 // ctx->aclreqaccess should be the complete access mask
95 uint32_t access_mask; 118 uint32_t m = ctx->aclreqaccess; // save original access mask
96 119 ctx->aclreqaccess = access_mask; // set mask for vfs->open call
97 if(ctx) { 120 if((ctx->vfs->flags & VFS_CHECKS_ACL) != VFS_CHECKS_ACL) {
98 access_mask = ctx->aclreqaccess; 121 // VFS does not evaluates the ACL itself, so we have to do it here
99 access_mask |= acl_oflag2mask(oflags); 122 SysACL sysacl;
100 if(!ctx->pool) { 123 if(sys_acl_check(ctx, access_mask, &sysacl)) {
101 // TODO: log warning 124 return NULL;
102 // broken VFSContext 125 }
103 } 126 }
104 if(ctx->vfs) { 127 SYS_FILE file = ctx->vfs->open(ctx, path, oflags);
105 // ctx->aclreqaccess should be the complete access mask 128 ctx->aclreqaccess = m; // restore original access mask
106 uint32_t m = ctx->aclreqaccess; // save original access mask 129 return file;
107 ctx->aclreqaccess = access_mask; // set mask for vfs->open call 130 }
108 SYS_FILE file = ctx->vfs->open(ctx, path, oflags); 131
109 ctx->aclreqaccess = m; // restore original access mask 132 SYS_FILE vfs_openRO(VFSContext *ctx, char *path) {
110 return file; 133 return vfs_open(ctx, path, O_RDONLY);
111 } else { 134 }
112 pool = ctx->pool; 135
113 } 136 SYS_FILE vfs_openWO(VFSContext *ctx, char *path) {
137 return vfs_open(ctx, path, O_WRONLY | O_CREAT);
138 }
139
140 SYS_FILE vfs_openRW(VFSContext *ctx, char *path) {
141 return vfs_open(ctx, path, O_RDONLY | O_WRONLY | O_CREAT);
142 }
143
144 int vfs_stat(VFSContext *ctx, char *path, struct stat *buf) {
145 WS_ASSERT(ctx);
146 WS_ASSERT(path);
147
148 uint32_t access_mask = ctx->aclreqaccess | ACL_READ_ATTRIBUTES;
149
150 // ctx->aclreqaccess should be the complete access mask
151 uint32_t m = ctx->aclreqaccess; // save original access mask
152 ctx->aclreqaccess = access_mask; // set mask for vfs->open call
153 if((ctx->vfs->flags & VFS_CHECKS_ACL) != VFS_CHECKS_ACL) {
154 // VFS does not evaluates the ACL itself, so we have to do it here
155 SysACL sysacl;
156 if(sys_acl_check(ctx, access_mask, &sysacl)) {
157 return -1;
158 }
159 }
160 int ret = ctx->vfs->stat(ctx, path, buf);
161 ctx->aclreqaccess = m; // restore original access mask
162 return ret;
163 }
164
165 int vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf) {
166 WS_ASSERT(ctx);
167 WS_ASSERT(fd);
168 WS_ASSERT(buf);
169
170 return ctx->vfs->fstat(ctx, fd, buf);
171 }
172
173 void vfs_close(SYS_FILE fd) {
174 WS_ASSERT(fd);
175
176 fd->io->close(fd);
177 if(fd->ctx) {
178 pool_free(fd->ctx->pool, fd);
114 } else { 179 } else {
115 sn = NULL; 180 free(fd);
116 rq = NULL; 181 }
117 pool = NULL; 182 }
118 access_mask = acl_oflag2mask(oflags); 183
119 } 184 VFS_DIR vfs_opendir(VFSContext *ctx, char *path) {
185 WS_ASSERT(ctx);
186 WS_ASSERT(path);
187
188 uint32_t access_mask = ctx->aclreqaccess | ACL_LIST;
189
190 // ctx->aclreqaccess should be the complete access mask
191 uint32_t m = ctx->aclreqaccess; // save original access mask
192 ctx->aclreqaccess = access_mask; // set mask for vfs->open call
193 if((ctx->vfs->flags & VFS_CHECKS_ACL) != VFS_CHECKS_ACL) {
194 // VFS does not evaluates the ACL itself, so we have to do it here
195 SysACL sysacl;
196 if(sys_acl_check(ctx, access_mask, &sysacl)) {
197 return NULL;
198 }
199 }
200 VFS_DIR dir = ctx->vfs->opendir(ctx, path);
201 ctx->aclreqaccess = m; // restore original access mask
202 return dir;
203 }
204
205 int vfs_readdir(VFS_DIR dir, VFS_ENTRY *entry) {
206 WS_ASSERT(dir);
207 WS_ASSERT(entry);
208
209 return dir->io->readdir(dir, entry, 0);
210 }
211
212 int vfs_readdir_stat(VFS_DIR dir, VFS_ENTRY *entry) {
213 WS_ASSERT(dir);
214 WS_ASSERT(entry);
215
216 return dir->io->readdir(dir, entry, 1);
217 }
218
219 void vfs_closedir(VFS_DIR dir) {
220 WS_ASSERT(dir);
221
222 dir->io->close(dir);
223 if(dir->ctx) {
224 VFS_FREE(dir->ctx->pool, dir);
225 } else {
226 free(dir);
227 }
228 }
229
230 int vfs_mkdir(VFSContext *ctx, char *path) {
231 WS_ASSERT(ctx);
232 WS_ASSERT(path);
233
234 return vfs_path_op(ctx, path, ctx->vfs->mkdir, ACL_ADD_FILE);
235 }
236
237 int vfs_unlink(VFSContext *ctx, char *path) {
238 WS_ASSERT(ctx);
239 WS_ASSERT(path);
240
241 return vfs_path_op(ctx, path, ctx->vfs->unlink, ACL_DELETE);
242 }
243
244
245 // private
246 int vfs_path_op(VFSContext *ctx, char *path, vfs_op_f op, uint32_t access) {
247 uint32_t access_mask = ctx->aclreqaccess;
248 access_mask |= access;
249
250 // ctx->aclreqaccess should be the complete access mask
251 uint32_t m = ctx->aclreqaccess; // save original access mask
252 ctx->aclreqaccess = access_mask; // set mask for vfs function call
253 if((ctx->vfs->flags & VFS_CHECKS_ACL) != VFS_CHECKS_ACL) {
254 // VFS does not evaluates the ACL itself, so we have to do it here
255 SysACL sysacl;
256 if(sys_acl_check(ctx, access_mask, &sysacl)) {
257 return -1;
258 }
259 }
260 int ret = op(ctx, path);
261 ctx->aclreqaccess = m; // restore original access mask
262 return ret;
263 }
264
265 /* system vfs implementation */
266
267 SYS_FILE sys_vfs_open(VFSContext *ctx, char *path, int oflags) {
268 uint32_t access_mask = ctx->aclreqaccess;
269 pool_handle_t *pool = ctx->pool;
120 270
121 // check ACLs 271 // check ACLs
122 SysACL sysacl; 272 SysACL sysacl;
123 if(sys_acl_check(ctx, access_mask, &sysacl)) { 273 if(sys_acl_check(ctx, access_mask, &sysacl)) {
124 return NULL; 274 return NULL;
149 system_close(fd); 299 system_close(fd);
150 return NULL; 300 return NULL;
151 } 301 }
152 } 302 }
153 303
154 304 VFSFile *file = VFS_MALLOC(pool, sizeof(VFSFile));
155 VFSFile *file = pool ?
156 pool_malloc(pool, sizeof(VFSFile)) : malloc(sizeof(VFSFile));
157 if(!file) { 305 if(!file) {
158 system_close(fd); 306 system_close(fd);
159 return NULL; 307 return NULL;
160 } 308 }
161 file->ctx = ctx; 309 file->ctx = ctx;
163 file->fd = fd; 311 file->fd = fd;
164 file->io = &sys_file_io; 312 file->io = &sys_file_io;
165 return file; 313 return file;
166 } 314 }
167 315
168 SYS_FILE vfs_openRO(VFSContext *ctx, char *path) { 316 int sys_vfs_stat(VFSContext *ctx, char *path, struct stat *buf) {
169 return vfs_open(ctx, path, O_RDONLY); 317 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 318
206 // check ACLs 319 // check ACLs
207 SysACL sysacl; 320 SysACL sysacl;
208 if(sys_acl_check(ctx, access_mask, &sysacl)) { 321 if(sys_acl_check(ctx, access_mask, &sysacl)) {
209 return -1; 322 return -1;
226 } 339 }
227 340
228 return 0; 341 return 0;
229 } 342 }
230 343
231 int vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf) { 344 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 345 // stat
243 if(fstat(fd->fd, buf)) { 346 if(fstat(fd->fd, buf)) {
244 if(ctx) { 347 if(ctx) {
245 ctx->vfs_errno = errno; 348 ctx->vfs_errno = errno;
246 } 349 }
248 } 351 }
249 352
250 return 0; 353 return 0;
251 } 354 }
252 355
253 void vfs_close(SYS_FILE fd) { 356 VFS_DIR sys_vfs_opendir(VFSContext *ctx, char *path) {
254 fd->io->close(fd); 357 uint32_t access_mask = ctx->aclreqaccess;
255 if(fd->ctx) { 358 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 359
294 // check ACLs 360 // check ACLs
295 SysACL sysacl; 361 SysACL sysacl;
296 if(sys_acl_check(ctx, access_mask, &sysacl)) { 362 if(sys_acl_check(ctx, access_mask, &sysacl)) {
297 return NULL; 363 return NULL;
325 sys_set_error_status(ctx); 391 sys_set_error_status(ctx);
326 } 392 }
327 return NULL; 393 return NULL;
328 } 394 }
329 395
330 SysVFSDir *dir_data = pool ? 396 SysVFSDir *dir_data = VFS_MALLOC(pool, sizeof(SysVFSDir));
331 pool_malloc(pool, sizeof(SysVFSDir)) : malloc(sizeof(SysVFSDir));
332 if(!dir_data) { 397 if(!dir_data) {
333 closedir(sys_dir); 398 closedir(sys_dir);
334 return NULL; 399 return NULL;
335 } 400 }
336 long maxfilelen = fpathconf(dir_fd, _PC_NAME_MAX); 401 long maxfilelen = fpathconf(dir_fd, _PC_NAME_MAX);
337 size_t entry_len = offsetof(struct dirent, d_name) + maxfilelen + 1; 402 size_t entry_len = offsetof(struct dirent, d_name) + maxfilelen + 1;
338 dir_data->cur = pool ? 403 dir_data->cur = VFS_MALLOC(pool, entry_len);
339 pool_malloc(pool, entry_len) : malloc(entry_len);
340 if(!dir_data->cur) { 404 if(!dir_data->cur) {
341 closedir(sys_dir); 405 closedir(sys_dir);
406 VFS_FREE(pool, dir_data);
342 return NULL; 407 return NULL;
343 } 408 }
344 dir_data->dir = sys_dir; 409 dir_data->dir = sys_dir;
345 410
346 VFSDir *dir = pool ? 411 VFSDir *dir = VFS_MALLOC(pool, sizeof(VFSDir));
347 pool_malloc(pool, sizeof(VFSDir)) : malloc(sizeof(VFSDir));
348 if(!dir) { 412 if(!dir) {
349 closedir(sys_dir); 413 closedir(sys_dir);
414 VFS_FREE(pool, dir_data->cur);
415 VFS_FREE(pool, dir_data);
350 return NULL; 416 return NULL;
351 } 417 }
352 dir->ctx = ctx; 418 dir->ctx = ctx;
353 dir->data = dir_data; 419 dir->data = dir_data;
354 dir->fd = dir_fd; 420 dir->fd = dir_fd;
355 dir->io = &sys_dir_io; 421 dir->io = &sys_dir_io;
356 return dir; 422 return dir;
357 } 423 }
358 424
359 int vfs_readdir(VFS_DIR dir, VFS_ENTRY *entry) { 425 int sys_vfs_mkdir(VFSContext *ctx, char *path) {
360 return dir->io->readdir(dir, entry, 0); 426 return sys_path_op(ctx, path, sys_mkdir);
361 } 427 }
362 428
363 int vfs_readdir_stat(VFS_DIR dir, VFS_ENTRY *entry) { 429 int sys_vfs_unlink(VFSContext *ctx, char *path) {
364 return dir->io->readdir(dir, entry, 1); 430 return sys_path_op(ctx, path, sys_unlink);
365 } 431 }
366 432
367 void vfs_closedir(VFS_DIR dir) { 433
368 dir->io->close(dir); 434 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; 435 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 436
419 // check ACLs 437 // check ACLs
420 SysACL sysacl; 438 SysACL sysacl;
421 if(sys_acl_check(ctx, access, &sysacl)) { 439 if(sys_acl_check(ctx, access_mask, &sysacl)) {
422 return -1; 440 return -1;
423 } 441 }
424 442
425 if(sysacl.acl) { 443 if(sysacl.acl) {
426 if(!fs_acl_check(&sysacl, ctx->user, path, access)) { 444 if(!fs_acl_check(&sysacl, ctx->user, path, access_mask)) {
427 acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user); 445 acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user);
428 return -1; 446 return -1;
429 } 447 }
430 } 448 }
431 449
432 // do path operation 450 // do path operation
433 if(op(ctx, path, &sysacl)) { 451 if(op(ctx, path, &sysacl)) {
434 // error 452 // error
435 if(ctx) { 453 ctx->vfs_errno = errno;
436 ctx->vfs_errno = errno; 454 sys_set_error_status(ctx);
437 sys_set_error_status(ctx);
438 }
439 return -1; 455 return -1;
440 } 456 }
441 457
442 return 0; 458 return 0;
443 } 459 }
480 496
481 ssize_t sys_file_write(SYS_FILE fd, const void *buf, size_t nbyte) { 497 ssize_t sys_file_write(SYS_FILE fd, const void *buf, size_t nbyte) {
482 return write(fd->fd, buf, nbyte); 498 return write(fd->fd, buf, nbyte);
483 } 499 }
484 500
501 ssize_t sys_file_pread(SYS_FILE fd, void *buf, size_t nbyte, off_t offset) {
502 return pread(fd->fd, buf, nbyte, offset);
503 }
504
505 ssize_t sys_file_pwrite(SYS_FILE fd, const void *buf, size_t nbyte, off_t offset) {
506 return pwrite(fd->fd, buf, nbyte, offset);
507 }
508
485 off_t sys_file_seek(SYS_FILE fd, off_t offset, int whence) { 509 off_t sys_file_seek(SYS_FILE fd, off_t offset, int whence) {
486 return lseek(fd->fd, offset, whence); 510 return lseek(fd->fd, offset, whence);
487 } 511 }
488 512
489 void sys_file_close(SYS_FILE fd) { 513 void sys_file_close(SYS_FILE fd) {
490 system_close(fd->fd); 514 system_close(fd->fd);
491 } 515 }
516
517 int sys_file_aioread(aiocb_s *aiocb) {
518 WS_ASSERT(aiocb->buf);
519 WS_ASSERT(aiocb->nbytes > 0);
520 return ev_aioread(aiocb->filedes->fd, aiocb);
521 }
522
523 int sys_file_aiowrite(aiocb_s *aiocb) {
524 WS_ASSERT(aiocb->buf);
525 WS_ASSERT(aiocb->nbytes > 0);
526 return ev_aiowrite(aiocb->filedes->fd, aiocb);
527 }
528
492 529
493 int sys_dir_read(VFS_DIR dir, VFS_ENTRY *entry, int getstat) { 530 int sys_dir_read(VFS_DIR dir, VFS_ENTRY *entry, int getstat) {
494 SysVFSDir *dirdata = dir->data; 531 SysVFSDir *dirdata = dir->data;
495 struct dirent *result = NULL; 532 struct dirent *result = NULL;
496 int s = readdir_r(dirdata->dir, dirdata->cur, &result); 533 int s = readdir_r(dirdata->dir, dirdata->cur, &result);
498 char *name = result->d_name; 535 char *name = result->d_name;
499 if(!strcmp(name, ".") || !strcmp(name, "..")) { 536 if(!strcmp(name, ".") || !strcmp(name, "..")) {
500 return sys_dir_read(dir, entry, getstat); 537 return sys_dir_read(dir, entry, getstat);
501 } else { 538 } else {
502 entry->name = name; 539 entry->name = name;
503 #ifndef OSX
504 /* TODO:
505 * implement alternative for fstat for OS X and other crappy
506 * Unices
507 */
508 if(getstat) { 540 if(getstat) {
509 // TODO: check ACLs again for new path 541 // TODO: check ACLs again for new path
510 if(fstatat(dir->fd, result->d_name, &entry->stat, 0)) { 542 if(fstatat(dir->fd, result->d_name, &entry->stat, 0)) {
511 entry->stat_errno = errno; 543 entry->stat_errno = errno;
512 } 544 }
513 entry->stat_extra = NULL; 545 entry->stat_extra = NULL;
514 } 546 }
515 #endif
516 return 1; 547 return 1;
517 } 548 }
518 } else { 549 } else {
519 return 0; 550 return 0;
520 } 551 }
561 592
562 NSAPI_PUBLIC int system_fwrite(SYS_FILE fd, const void *buf, int nbyte) { 593 NSAPI_PUBLIC int system_fwrite(SYS_FILE fd, const void *buf, int nbyte) {
563 return fd->io->write(fd, buf, nbyte); 594 return fd->io->write(fd, buf, nbyte);
564 } 595 }
565 596
597 NSAPI_PUBLIC int system_pread(SYS_FILE fd, void *buf, int nbyte, off_t offset) {
598 return fd->io->pread(fd, buf, nbyte, offset);
599 }
600
601 NSAPI_PUBLIC int system_pwrite(SYS_FILE fd, const void *buf, int nbyte, off_t offset) {
602 return fd->io->pwrite(fd, buf, nbyte, offset);
603 }
604
566 NSAPI_PUBLIC off_t system_lseek(SYS_FILE fd, off_t offset, int whence) { 605 NSAPI_PUBLIC off_t system_lseek(SYS_FILE fd, off_t offset, int whence) {
567 return fd->io->seek(fd, offset, whence); 606 return fd->io->seek(fd, offset, whence);
568 } 607 }
569 608
570 NSAPI_PUBLIC int system_fclose(SYS_FILE fd) { 609 NSAPI_PUBLIC int system_fclose(SYS_FILE fd) {
571 vfs_close(fd); 610 vfs_close(fd);
572 return 0; 611 return 0;
573 } 612 }
613
614 // AIO API
615
616 NSAPI_PUBLIC int system_aio_read(aiocb_s *aiocb) {
617 if(!aiocb->event || !aiocb->evhandler) {
618 return -1;
619 }
620
621 SYS_FILE file = aiocb->filedes;
622 aiocb->event->object = (intptr_t)aiocb;
623 if(file->io->opt_aioread) {
624 return file->io->opt_aioread(aiocb);
625 } else {
626 vfs_queue_aio(aiocb, VFS_AIO_READ);
627 return 0;
628 }
629 }
630
631 NSAPI_PUBLIC int system_aio_write(aiocb_s *aiocb) {
632 if(!aiocb->event || !aiocb->evhandler) {
633 return -1;
634 }
635
636 SYS_FILE file = aiocb->filedes;
637 aiocb->event->object = (intptr_t)aiocb;
638 if(file->io->opt_aiowrite) {
639 return file->io->opt_aiowrite(aiocb);
640 } else {
641 vfs_queue_aio(aiocb, VFS_AIO_WRITE);
642 return 0;
643 }
644 }
645
646 static void* vfs_aio_read(aiocb_s *aiocb) {
647 int result = system_pread(aiocb->filedes, aiocb->buf, aiocb->nbytes, aiocb->offset);
648 aiocb->result = result;
649 if(result < 0) {
650 aiocb->result_errno = errno;
651 }
652 event_send(aiocb->evhandler, aiocb->event);
653 return NULL;
654 }
655
656 static void* vfs_aio_write(aiocb_s *aiocb) {
657 int result = system_pwrite(aiocb->filedes, aiocb->buf, aiocb->nbytes, aiocb->offset);
658 aiocb->result = result;
659 if(result < 0) {
660 aiocb->result_errno = errno;
661 }
662 event_send(aiocb->evhandler, aiocb->event);
663 return NULL;
664 }
665
666 void vfs_queue_aio(aiocb_s *aiocb, VFSAioOp op) {
667 threadpool_t *pool = get_default_iopool(); // TODO: use specific IOPool
668 if(op == VFS_AIO_READ) {
669 threadpool_run(pool, (job_callback_f)vfs_aio_read, aiocb);
670 } else if(VFS_AIO_WRITE) {
671 threadpool_run(pool, (job_callback_f)vfs_aio_write, aiocb);
672 }
673 }

mercurial