1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #define _POSIX_PTHREAD_SEMANTIS
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <aio.h>
36 #include <cx/hash_map.h>
37
38 #include "../util/pool.h"
39 #include "netsite.h"
40 #include "acl.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)
47
48 static CxMap *vfs_type_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_fdopendir,
56 sys_vfs_mkdir,
57 sys_vfs_unlink,
58 sys_vfs_rmdir,
59 VFS_CHECKS_ACL,
60 NULL
61 };
62
63 static VFS_IO sys_file_io = {
64 sys_file_read,
65 sys_file_write,
66 sys_file_pread,
67 sys_file_pwrite,
68 sys_file_seek,
69 sys_file_close,
70
71
72 NULL,
73 NULL,
74 NULL
75 };
76
77 static VFS_DIRIO sys_dir_io = {
78 sys_dir_read,
79 sys_dir_close
80 };
81
82 int vfs_init(
void) {
83 vfs_type_map = cxHashMapCreate(cxDefaultAllocator,
CX_STORE_POINTERS,
16);
84 if(!vfs_type_map) {
85 return -
1;
86 }
87 return 0;
88 }
89
90 int vfs_register_type(
const char *name, vfs_init_func vfsInit, vfs_create_func vfsCreate) {
91 WS_ASSERT(name);
92
93 if(!vfs_type_map) {
94 if(vfs_init()) {
95 return 1;
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 cxMapPut(vfs_type_map, cx_hash_key_str(name), vfsType);
107 }
108
109 VfsType* vfs_get_type(cxstring vfs_class) {
110 return cxMapGet(vfs_type_map, cx_hash_key_bytes((
const unsigned char*)vfs_class.ptr, vfs_class.length));
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 = cxMapGet(vfs_type_map, cx_hash_key_str(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);
134 }
135
136 VFSContext* vfs_request_context(Session *sn, Request *rq) {
137 WS_ASSERT(sn);
138 WS_ASSERT(rq);
139
140 VFSContext *ctx = pool_malloc(sn->pool,
sizeof(VFSContext));
141 if(!ctx) {
142 return NULL;
143 }
144 ctx->sn = sn;
145 ctx->rq = rq;
146 ctx->vfs = rq->vfs ? rq->vfs : &sys_vfs;
147 ctx->user = acllist_getuser(sn, rq, rq->acllist);
148 ctx->acllist = rq->acllist;
149 ctx->aclreqaccess = rq->aclreqaccess;
150 ctx->pool = sn->pool;
151 ctx->vfs_errno =
0;
152 ctx->error_response_set =
0;
153 return ctx;
154 }
155
156 SYS_FILE vfs_open(VFSContext *ctx,
const char *path,
int oflags) {
157 WS_ASSERT(ctx);
158 WS_ASSERT(path);
159
160 uint32_t access_mask = ctx->aclreqaccess | acl_oflag2mask(oflags);
161
162
163 uint32_t m = ctx->aclreqaccess;
164 ctx->aclreqaccess = access_mask;
165 if((ctx->vfs->flags &
VFS_CHECKS_ACL) !=
VFS_CHECKS_ACL) {
166
167 SysACL sysacl;
168 if(sys_acl_check(ctx, access_mask, &sysacl)) {
169 return NULL;
170 }
171 }
172 SYS_FILE file = ctx->vfs->open(ctx, path, oflags);
173 ctx->aclreqaccess = m;
174 if(!file && ctx) {
175 sys_set_error_status(ctx);
176 }
177 return file;
178 }
179
180 SYS_FILE vfs_openRO(VFSContext *ctx,
const char *path) {
181 return vfs_open(ctx, path,
O_RDONLY);
182 }
183
184 SYS_FILE vfs_openWO(VFSContext *ctx,
const char *path) {
185 return vfs_open(ctx, path,
O_WRONLY |
O_CREAT);
186 }
187
188 SYS_FILE vfs_openRW(VFSContext *ctx,
const char *path) {
189 return vfs_open(ctx, path,
O_RDONLY |
O_WRONLY |
O_CREAT);
190 }
191
192 int vfs_stat(VFSContext *ctx,
const char *path,
struct stat *buf) {
193 WS_ASSERT(ctx);
194 WS_ASSERT(path);
195
196 uint32_t access_mask = ctx->aclreqaccess |
ACL_READ_ATTRIBUTES;
197
198
199 uint32_t m = ctx->aclreqaccess;
200 ctx->aclreqaccess = access_mask;
201 if((ctx->vfs->flags &
VFS_CHECKS_ACL) !=
VFS_CHECKS_ACL) {
202
203 SysACL sysacl;
204 if(sys_acl_check(ctx, access_mask, &sysacl)) {
205 return -
1;
206 }
207 }
208 int ret = ctx->vfs->stat(ctx, path, buf);
209 ctx->aclreqaccess = m;
210 if(ret && ctx) {
211 sys_set_error_status(ctx);
212 }
213 return ret;
214 }
215
216 int vfs_fstat(VFSContext *ctx,
SYS_FILE fd,
struct stat *buf) {
217 WS_ASSERT(ctx);
218 WS_ASSERT(fd);
219 WS_ASSERT(buf);
220
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;
235 }
236
237 void vfs_close(
SYS_FILE fd) {
238 WS_ASSERT(fd);
239
240 fd->io->close(fd);
241 if(fd->ctx) {
242 pool_free(fd->ctx->pool, fd);
243 }
else {
244 free(fd);
245 }
246 }
247
248 VFS_DIR vfs_opendir(VFSContext *ctx,
const char *path) {
249 WS_ASSERT(ctx);
250 WS_ASSERT(path);
251
252 uint32_t access_mask = ctx->aclreqaccess |
ACL_LIST;
253
254
255 uint32_t m = ctx->aclreqaccess;
256 ctx->aclreqaccess = access_mask;
257 if((ctx->vfs->flags &
VFS_CHECKS_ACL) !=
VFS_CHECKS_ACL) {
258
259 SysACL sysacl;
260 if(sys_acl_check(ctx, access_mask, &sysacl)) {
261 return NULL;
262 }
263 }
264 VFS_DIR dir = ctx->vfs->opendir(ctx, path);
265 ctx->aclreqaccess = m;
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
279 uint32_t m = ctx->aclreqaccess;
280 ctx->aclreqaccess = access_mask;
281 if((ctx->vfs->flags &
VFS_CHECKS_ACL) !=
VFS_CHECKS_ACL) {
282
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;
290 if(!dir && ctx) {
291 sys_set_error_status(ctx);
292 }
293 return dir;
294 }
295
296 int vfs_readdir(
VFS_DIR dir,
VFS_ENTRY *entry) {
297 WS_ASSERT(dir);
298 WS_ASSERT(entry);
299
300 return dir->io->readdir(dir, entry,
0);
301 }
302
303 int vfs_readdir_stat(
VFS_DIR dir,
VFS_ENTRY *entry) {
304 WS_ASSERT(dir);
305 WS_ASSERT(entry);
306
307 return dir->io->readdir(dir, entry,
1);
308 }
309
310 void vfs_closedir(
VFS_DIR dir) {
311 WS_ASSERT(dir);
312
313 dir->io->close(dir);
314 if(dir->ctx) {
315 VFS_FREE(dir->ctx->pool, dir);
316 }
else {
317 free(dir);
318 }
319 }
320
321 int vfs_mkdir(VFSContext *ctx,
const char *path) {
322 WS_ASSERT(ctx);
323 WS_ASSERT(path);
324
325 return vfs_path_op(ctx, path, ctx->vfs->mkdir,
ACL_ADD_FILE);
326 }
327
328 int vfs_unlink(VFSContext *ctx,
const char *path) {
329 WS_ASSERT(ctx);
330 WS_ASSERT(path);
331
332 return vfs_path_op(ctx, path, ctx->vfs->unlink,
ACL_DELETE);
333 }
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 }
341
342
343 int vfs_path_op(VFSContext *ctx,
const char *path, vfs_op_f op,
uint32_t access) {
344 uint32_t access_mask = ctx->aclreqaccess;
345 access_mask |= access;
346
347
348 uint32_t m = ctx->aclreqaccess;
349 ctx->aclreqaccess = access_mask;
350 if((ctx->vfs->flags &
VFS_CHECKS_ACL) !=
VFS_CHECKS_ACL) {
351
352 SysACL sysacl;
353 if(sys_acl_check(ctx, access_mask, &sysacl)) {
354 return -
1;
355 }
356 }
357 int ret = op(ctx, path);
358 ctx->aclreqaccess = m;
359 if(ret && ctx) {
360 sys_set_error_status(ctx);
361 }
362 return ret;
363 }
364
365
366
367 SYS_FILE sys_vfs_open(VFSContext *ctx,
const char *path,
int oflags) {
368 uint32_t access_mask = ctx->aclreqaccess;
369 pool_handle_t *pool = ctx->pool;
370
371
372 SysACL sysacl;
373 if(sys_acl_check(ctx, access_mask, &sysacl)) {
374 return NULL;
375 }
376
377 if(sysacl.acl) {
378 if(!fs_acl_check(&sysacl, ctx->user, path, access_mask)) {
379 acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user);
380 return NULL;
381 }
382 }
383
384
385 mode_t mode =
S_IRUSR |
S_IWUSR |
S_IRGRP |
S_IROTH;
386 int fd = open(path, oflags, mode);
387 if(fd == -
1) {
388 if(ctx) {
389 ctx->vfs_errno = errno;
390 sys_set_error_status(ctx);
391 }
392 return NULL;
393 }
394
395
396 if(((oflags &
O_CREAT) ==
O_CREAT) && sysacl.acl) {
397 if(fchown(fd, sysacl.user_uid, sysacl.user_gid)) {
398 perror(
"vfs_open: fchown");
399 system_close(fd);
400 return NULL;
401 }
402 }
403
404 VFSFile *file =
VFS_MALLOC(pool,
sizeof(VFSFile));
405 if(!file) {
406 system_close(fd);
407 return NULL;
408 }
409 file->ctx = ctx;
410 file->data =
NULL;
411 file->fd = fd;
412 file->io = &sys_file_io;
413 return file;
414 }
415
416 int sys_vfs_stat(VFSContext *ctx,
const char *path,
struct stat *buf) {
417 uint32_t access_mask = ctx->aclreqaccess;
418
419
420 SysACL sysacl;
421 if(sys_acl_check(ctx, access_mask, &sysacl)) {
422 return -
1;
423 }
424
425 if(sysacl.acl) {
426 if(!fs_acl_check(&sysacl, ctx->user, path, access_mask)) {
427 acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user);
428 return -
1;
429 }
430 }
431
432
433 if(stat(path, buf)) {
434 if(ctx) {
435 ctx->vfs_errno = errno;
436 sys_set_error_status(ctx);
437 }
438 return -
1;
439 }
440
441 return 0;
442 }
443
444 int sys_vfs_fstat(VFSContext *ctx,
SYS_FILE fd,
struct stat *buf) {
445
446 if(fstat(fd->fd, buf)) {
447 if(ctx) {
448 ctx->vfs_errno = errno;
449 }
450 return -
1;
451 }
452
453 return 0;
454 }
455
456 VFS_DIR sys_vfs_opendir(VFSContext *ctx,
const char *path) {
457 uint32_t access_mask = ctx->aclreqaccess;
458 pool_handle_t *pool = ctx->pool;
459
460
461 SysACL sysacl;
462 if(sys_acl_check(ctx, access_mask, &sysacl)) {
463 return NULL;
464 }
465
466 if(sysacl.acl) {
467 if(!fs_acl_check(&sysacl, ctx->user, path, access_mask)) {
468 acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user);
469 return NULL;
470 }
471 }
472
473
474 #ifdef BSD
475 DIR *sys_dir = opendir(path);
476 int dir_fd = sys_dir ? dirfd(sys_dir) :
0;
477 #else
478 int dir_fd = open(path,
O_RDONLY);
479 if(dir_fd == -
1) {
480 if(ctx) {
481 ctx->vfs_errno = errno;
482 sys_set_error_status(ctx);
483 }
484 return NULL;
485 }
486 DIR *sys_dir = fdopendir(dir_fd);
487 #endif
488 if(!sys_dir) {
489 if(dir_fd >
0) {
490 close(dir_fd);
491 }
492 if(ctx) {
493 ctx->vfs_errno = errno;
494 sys_set_error_status(ctx);
495 }
496 return NULL;
497 }
498
499 SysVFSDir *dir_data =
VFS_MALLOC(pool,
sizeof(SysVFSDir));
500 if(!dir_data) {
501 closedir(sys_dir);
502 return NULL;
503 }
504 long maxfilelen = fpathconf(dir_fd,
_PC_NAME_MAX);
505 size_t entry_len = offsetof(
struct dirent, d_name) + maxfilelen +
1;
506 dir_data->cur =
VFS_MALLOC(pool, entry_len);
507 if(!dir_data->cur) {
508 closedir(sys_dir);
509 VFS_FREE(pool, dir_data);
510 return NULL;
511 }
512 dir_data->dir = sys_dir;
513
514 VFSDir *dir =
VFS_MALLOC(pool,
sizeof(VFSDir));
515 if(!dir) {
516 closedir(sys_dir);
517 VFS_FREE(pool, dir_data->cur);
518 VFS_FREE(pool, dir_data);
519 return NULL;
520 }
521 dir->ctx = ctx;
522 dir->data = dir_data;
523 dir->fd = dir_fd;
524 dir->io = &sys_dir_io;
525 return dir;
526 }
527
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
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
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) {
585 return sys_path_op(ctx, path, sys_mkdir);
586 }
587
588 int sys_vfs_unlink(VFSContext *ctx,
const char *path) {
589 return sys_path_op(ctx, path, sys_unlink);
590 }
591
592 int sys_vfs_rmdir(VFSContext *ctx,
const char *path) {
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) {
598 uint32_t access_mask = ctx->aclreqaccess;
599
600
601 SysACL sysacl;
602 if(sys_acl_check(ctx, access_mask, &sysacl)) {
603 return -
1;
604 }
605
606 if(sysacl.acl) {
607 if(!fs_acl_check(&sysacl, ctx->user, path, access_mask)) {
608 acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user);
609 return -
1;
610 }
611 }
612
613
614 if(op(ctx, path, &sysacl)) {
615
616 ctx->vfs_errno = errno;
617 sys_set_error_status(ctx);
618 return -
1;
619 }
620
621 return 0;
622 }
623
624 int sys_acl_check(VFSContext *ctx,
uint32_t access_mask, SysACL *sysacl) {
625 if(sysacl) {
626 sysacl->acl =
NULL;
627 }
628 if(!ctx) {
629 return 0;
630 }
631
632 ACLListHandle *acllist = ctx->acllist;
633 if(acllist) {
634 ACLList *acl = acl_evallist(
635 acllist,
636 ctx->user,
637 access_mask,
638 &sysacl->acl);
639
640 if(acl) {
641 acl_set_error_status(ctx->sn, ctx->rq, acl, ctx->user);
642 return 1;
643 }
644 }
645
646 return 0;
647 }
648
649 void sys_set_error_status(VFSContext *ctx) {
650 if(ctx->sn && ctx->rq && !ctx->error_response_set) {
651 int status = util_errno2status(ctx->vfs_errno);
652 protocol_status(ctx->sn, ctx->rq, status,
NULL);
653 ctx->error_response_set =
TRUE;
654 }
655 }
656
657 ssize_t sys_file_read(
SYS_FILE fd,
void *buf,
size_t nbyte) {
658 return read(fd->fd, buf, nbyte);
659 }
660
661 ssize_t sys_file_write(
SYS_FILE fd,
const void *buf,
size_t nbyte) {
662 return write(fd->fd, buf, nbyte);
663 }
664
665 ssize_t sys_file_pread(
SYS_FILE fd,
void *buf,
size_t nbyte,
off_t offset) {
666 return pread(fd->fd, buf, nbyte, offset);
667 }
668
669 ssize_t sys_file_pwrite(
SYS_FILE fd,
const void *buf,
size_t nbyte,
off_t offset) {
670 return pwrite(fd->fd, buf, nbyte, offset);
671 }
672
673 off_t sys_file_seek(
SYS_FILE fd,
off_t offset,
int whence) {
674 return lseek(fd->fd, offset, whence);
675 }
676
677 void sys_file_close(
SYS_FILE fd) {
678 system_close(fd->fd);
679 }
680
681 int sys_file_aioread(aiocb_s *aiocb) {
682 WS_ASSERT(aiocb->buf);
683 WS_ASSERT(aiocb->nbytes >
0);
684 return ev_aioread(aiocb->filedes->fd, aiocb);
685 }
686
687 int sys_file_aiowrite(aiocb_s *aiocb) {
688 WS_ASSERT(aiocb->buf);
689 WS_ASSERT(aiocb->nbytes >
0);
690 return ev_aiowrite(aiocb->filedes->fd, aiocb);
691 }
692
693
694 int sys_dir_read(
VFS_DIR dir,
VFS_ENTRY *entry,
int getstat) {
695 SysVFSDir *dirdata = dir->data;
696 struct dirent *result =
NULL;
697 int s = readdir_r(dirdata->dir, dirdata->cur, &result);
698 if(!s && result) {
699 char *name = result->d_name;
700 if(!strcmp(name,
".") || !strcmp(name,
"..")) {
701 return sys_dir_read(dir, entry, getstat);
702 }
else {
703 entry->name = name;
704 if(getstat) {
705
706 entry->stat_errno =
0;
707 if(fstatat(dir->fd, result->d_name, &entry->stat,
0)) {
708 entry->stat_errno = errno;
709 }
710 entry->stat_extra =
NULL;
711 }
712 return 1;
713 }
714 }
else {
715 return 0;
716 }
717 }
718
719 void sys_dir_close(
VFS_DIR dir) {
720 SysVFSDir *dirdata = dir->data;
721 closedir(dirdata->dir);
722
723 pool_handle_t *pool = dir->ctx->pool;
724 if(pool) {
725 pool_free(pool, dirdata->cur);
726 pool_free(pool, dirdata);
727 pool_free(pool, dir);
728 }
else {
729 free(dirdata->cur);
730 free(dirdata);
731 free(dir);
732 }
733 }
734
735 int sys_mkdir(VFSContext *ctx,
const char *path, SysACL *sysacl) {
736 mode_t mode =
S_IRWXU |
S_IRGRP |
S_IXGRP |
S_IROTH |
S_IXOTH;
737 int ret = mkdir(path, mode);
738 if(ret ==
0) {
739 if(sysacl->user_uid != -
1) {
740 if(chown(path, sysacl->user_uid, sysacl->user_gid)) {
741
742 }
743 }
744 }
745 return ret;
746 }
747
748 int sys_unlink(VFSContext *ctx,
const char *path, SysACL *sysacl) {
749 return unlink(path);
750 }
751
752 int sys_rmdir(VFSContext *ctx,
const char *path, SysACL *sysacl) {
753 return rmdir(path);
754 }
755
756
757
758 NSAPI_PUBLIC int system_fread(
SYS_FILE fd,
void *buf,
int nbyte) {
759 return fd->io->read(fd, buf, nbyte);
760 }
761
762 NSAPI_PUBLIC int system_fwrite(
SYS_FILE fd,
const void *buf,
int nbyte) {
763 return fd->io->write(fd, buf, nbyte);
764 }
765
766 NSAPI_PUBLIC int system_pread(
SYS_FILE fd,
void *buf,
int nbyte,
off_t offset) {
767 return fd->io->pread(fd, buf, nbyte, offset);
768 }
769
770 NSAPI_PUBLIC int system_pwrite(
SYS_FILE fd,
const void *buf,
int nbyte,
off_t offset) {
771 return fd->io->pwrite(fd, buf, nbyte, offset);
772 }
773
774 NSAPI_PUBLIC off_t system_lseek(
SYS_FILE fd,
off_t offset,
int whence) {
775 return fd->io->seek(fd, offset, whence);
776 }
777
778 NSAPI_PUBLIC int system_fclose(
SYS_FILE fd) {
779 vfs_close(fd);
780 return 0;
781 }
782
783 NSAPI_PUBLIC int vfs_is_sys(
VFS *vfs) {
784 if(!vfs)
return 1;
785 if(vfs == &sys_vfs)
return 1;
786 return 0;
787 }
788
789
790
791 NSAPI_PUBLIC int system_aio_read(aiocb_s *aiocb) {
792 if(!aiocb->event || !aiocb->evhandler) {
793 return -
1;
794 }
795
796 SYS_FILE file = aiocb->filedes;
797 aiocb->event->object = (
intptr_t)aiocb;
798 if(file->io->opt_aioread) {
799 return file->io->opt_aioread(aiocb);
800 }
else {
801 vfs_queue_aio(aiocb,
VFS_AIO_READ);
802 return 0;
803 }
804 }
805
806 NSAPI_PUBLIC int system_aio_write(aiocb_s *aiocb) {
807 if(!aiocb->event || !aiocb->evhandler) {
808 return -
1;
809 }
810
811 SYS_FILE file = aiocb->filedes;
812 aiocb->event->object = (
intptr_t)aiocb;
813 if(file->io->opt_aiowrite) {
814 return file->io->opt_aiowrite(aiocb);
815 }
else {
816 vfs_queue_aio(aiocb,
VFS_AIO_WRITE);
817 return 0;
818 }
819 }
820
821 static void* vfs_aio_read(aiocb_s *aiocb) {
822 int result = system_pread(aiocb->filedes, aiocb->buf, aiocb->nbytes, aiocb->offset);
823 aiocb->result = result;
824 if(result <
0) {
825 aiocb->result_errno = errno;
826 }
827 event_send(aiocb->evhandler, aiocb->event);
828 return NULL;
829 }
830
831 static void* vfs_aio_write(aiocb_s *aiocb) {
832 int result = system_pwrite(aiocb->filedes, aiocb->buf, aiocb->nbytes, aiocb->offset);
833 aiocb->result = result;
834 if(result <
0) {
835 aiocb->result_errno = errno;
836 }
837 event_send(aiocb->evhandler, aiocb->event);
838 return NULL;
839 }
840
841 void vfs_queue_aio(aiocb_s *aiocb, VFSAioOp op) {
842 threadpool_t *pool = get_default_iopool();
843 if(op ==
VFS_AIO_READ) {
844 threadpool_run(pool, (job_callback_f)vfs_aio_read, aiocb);
845 }
else if(
VFS_AIO_WRITE) {
846 threadpool_run(pool, (job_callback_f)vfs_aio_write, aiocb);
847 }
848 }
849