etc/services - sync with NetBSD-8
[minix.git] / minix / lib / libfsdriver / call.c
blobf7bb9e50a90f70fca637fc1b61087915859d0d8a
2 #include "fsdriver.h"
3 #include <minix/ds.h>
4 #include <sys/mman.h>
6 static int fsdriver_vmcache; /* have we used the VM cache? */
8 /*
9 * Process a READSUPER request from VFS.
11 int
12 fsdriver_readsuper(const struct fsdriver * __restrict fdp,
13 const message * __restrict m_in, message * __restrict m_out)
15 struct fsdriver_node root_node;
16 char label[DS_MAX_KEYLEN];
17 cp_grant_id_t label_grant;
18 size_t label_len;
19 unsigned int flags, res_flags;
20 dev_t dev;
21 int r;
23 dev = m_in->m_vfs_fs_readsuper.device;
24 label_grant = m_in->m_vfs_fs_readsuper.grant;
25 label_len = m_in->m_vfs_fs_readsuper.path_len;
26 flags = m_in->m_vfs_fs_readsuper.flags;
28 if (fdp->fdr_mount == NULL)
29 return ENOSYS;
31 if (fsdriver_mounted) {
32 printf("fsdriver: attempt to mount multiple times\n");
33 return EBUSY;
36 if ((r = fsdriver_getname(m_in->m_source, label_grant, label_len,
37 label, sizeof(label), FALSE /*not_empty*/)) != OK)
38 return r;
40 if (fdp->fdr_driver != NULL)
41 fdp->fdr_driver(dev, label);
43 res_flags = RES_NOFLAGS;
45 r = fdp->fdr_mount(dev, flags, &root_node, &res_flags);
47 if (r == OK) {
48 /* This one we can set on the file system's behalf. */
49 if ((fdp->fdr_peek != NULL && fdp->fdr_bpeek != NULL) ||
50 major(dev) == NONE_MAJOR)
51 res_flags |= RES_HASPEEK;
53 m_out->m_fs_vfs_readsuper.inode = root_node.fn_ino_nr;
54 m_out->m_fs_vfs_readsuper.mode = root_node.fn_mode;
55 m_out->m_fs_vfs_readsuper.file_size = root_node.fn_size;
56 m_out->m_fs_vfs_readsuper.uid = root_node.fn_uid;
57 m_out->m_fs_vfs_readsuper.gid = root_node.fn_gid;
58 m_out->m_fs_vfs_readsuper.flags = res_flags;
60 /* Update library-local state. */
61 fsdriver_mounted = TRUE;
62 fsdriver_device = dev;
63 fsdriver_root = root_node.fn_ino_nr;
64 fsdriver_vmcache = FALSE;
67 return r;
71 * Process an UNMOUNT request from VFS.
73 int
74 fsdriver_unmount(const struct fsdriver * __restrict fdp,
75 const message * __restrict __unused m_in,
76 message * __restrict __unused m_out)
79 if (fdp->fdr_unmount != NULL)
80 fdp->fdr_unmount();
82 /* If we used mmap emulation, clear any cached blocks from VM. */
83 if (fsdriver_vmcache)
84 vm_clear_cache(fsdriver_device);
86 /* Update library-local state. */
87 fsdriver_mounted = FALSE;
89 return OK;
93 * Process a PUTNODE request from VFS.
95 int
96 fsdriver_putnode(const struct fsdriver * __restrict fdp,
97 const message * __restrict m_in, message * __restrict __unused m_out)
99 ino_t ino_nr;
100 unsigned int count;
102 ino_nr = m_in->m_vfs_fs_putnode.inode;
103 count = m_in->m_vfs_fs_putnode.count;
105 if (count == 0 || count > INT_MAX) {
106 printf("fsdriver: invalid reference count\n");
107 return EINVAL;
110 if (fdp->fdr_putnode != NULL)
111 return fdp->fdr_putnode(ino_nr, count);
112 else
113 return OK;
117 * Process a NEWNODE request from VFS.
120 fsdriver_newnode(const struct fsdriver * __restrict fdp,
121 const message * __restrict m_in, message * __restrict m_out)
123 struct fsdriver_node node;
124 mode_t mode;
125 uid_t uid;
126 gid_t gid;
127 dev_t dev;
128 int r;
130 mode = m_in->m_vfs_fs_newnode.mode;
131 uid = m_in->m_vfs_fs_newnode.uid;
132 gid = m_in->m_vfs_fs_newnode.gid;
133 dev = m_in->m_vfs_fs_newnode.device;
135 if (fdp->fdr_newnode == NULL)
136 return ENOSYS;
138 if ((r = fdp->fdr_newnode(mode, uid, gid, dev, &node)) == OK) {
139 m_out->m_fs_vfs_newnode.inode = node.fn_ino_nr;
140 m_out->m_fs_vfs_newnode.mode = node.fn_mode;
141 m_out->m_fs_vfs_newnode.file_size = node.fn_size;
142 m_out->m_fs_vfs_newnode.uid = node.fn_uid;
143 m_out->m_fs_vfs_newnode.gid = node.fn_gid;
144 m_out->m_fs_vfs_newnode.device = node.fn_dev;
147 return r;
151 * Process a read or write request from VFS.
153 static int
154 read_write(const struct fsdriver * __restrict fdp,
155 const message * __restrict m_in, message * __restrict m_out, int call)
157 struct fsdriver_data data;
158 ino_t ino_nr;
159 off_t pos;
160 size_t nbytes;
161 ssize_t r;
163 ino_nr = m_in->m_vfs_fs_readwrite.inode;
164 pos = m_in->m_vfs_fs_readwrite.seek_pos;
165 nbytes = m_in->m_vfs_fs_readwrite.nbytes;
167 if (pos < 0 || nbytes > SSIZE_MAX)
168 return EINVAL;
170 data.endpt = m_in->m_source;
171 data.grant = m_in->m_vfs_fs_readwrite.grant;
172 data.size = nbytes;
174 if (call == FSC_WRITE)
175 r = fdp->fdr_write(ino_nr, &data, nbytes, pos, call);
176 else
177 r = fdp->fdr_read(ino_nr, &data, nbytes, pos, call);
179 if (r >= 0) {
180 pos += r;
182 m_out->m_fs_vfs_readwrite.seek_pos = pos;
183 m_out->m_fs_vfs_readwrite.nbytes = r;
184 r = OK;
187 return r;
191 * Process a READ request from VFS.
194 fsdriver_read(const struct fsdriver * __restrict fdp,
195 const message * __restrict m_in, message * __restrict m_out)
198 if (fdp->fdr_read == NULL)
199 return ENOSYS;
201 return read_write(fdp, m_in, m_out, FSC_READ);
205 * Process a WRITE request from VFS.
208 fsdriver_write(const struct fsdriver * __restrict fdp,
209 const message * __restrict m_in, message * __restrict m_out)
212 if (fdp->fdr_write == NULL)
213 return ENOSYS;
215 return read_write(fdp, m_in, m_out, FSC_WRITE);
219 * A read-based peek implementation. This allows file systems that do not have
220 * a buffer cache and do not implement peek, to support a limited form of mmap.
221 * We map in a block, fill it by calling the file system's read function, tell
222 * VM about the page, and then unmap the block again. We tell VM not to cache
223 * the block beyond its immediate use for the mmap request, so as to prevent
224 * potentially stale data from being cached--at the cost of performance.
226 static ssize_t
227 builtin_peek(const struct fsdriver * __restrict fdp, ino_t ino_nr,
228 size_t nbytes, off_t pos)
230 static u32_t flags = 0; /* storage for the VMMC_ flags of all blocks */
231 static off_t dev_off = 0; /* fake device offset, see below */
232 struct fsdriver_data data;
233 char *buf;
234 ssize_t r;
236 if ((buf = mmap(NULL, nbytes, PROT_READ | PROT_WRITE,
237 MAP_ANON | MAP_PRIVATE, -1, 0)) == MAP_FAILED)
238 return ENOMEM;
240 data.endpt = SELF;
241 data.grant = (cp_grant_id_t)buf;
242 data.size = nbytes;
244 r = fdp->fdr_read(ino_nr, &data, nbytes, pos, FSC_READ);
246 if (r >= 0) {
247 if ((size_t)r < nbytes)
248 memset(&buf[r], 0, nbytes - r);
251 * VM uses serialized communication to VFS. Since the page is
252 * to be used only once, VM will use and then discard it before
253 * sending a new peek request. Thus, it should be safe to
254 * reuse the same device offset all the time. However, relying
255 * on assumptions in protocols elsewhere a bit dangerous, so we
256 * use an ever-increasing device offset just to be safe.
258 r = vm_set_cacheblock(buf, fsdriver_device, dev_off, ino_nr,
259 pos, &flags, nbytes, VMSF_ONCE);
261 if (r == OK) {
262 fsdriver_vmcache = TRUE;
264 dev_off += nbytes;
266 r = nbytes;
270 munmap(buf, nbytes);
272 return r;
276 * Process a PEEK request from VFS.
279 fsdriver_peek(const struct fsdriver * __restrict fdp,
280 const message * __restrict m_in, message * __restrict __unused m_out)
282 ino_t ino_nr;
283 off_t pos;
284 size_t nbytes;
285 ssize_t r;
287 ino_nr = m_in->m_vfs_fs_readwrite.inode;
288 pos = m_in->m_vfs_fs_readwrite.seek_pos;
289 nbytes = m_in->m_vfs_fs_readwrite.nbytes;
291 if (pos < 0 || nbytes > SSIZE_MAX)
292 return EINVAL;
294 if (fdp->fdr_peek == NULL) {
295 if (major(fsdriver_device) != NONE_MAJOR)
296 return ENOSYS;
299 * For file systems that have no backing device, emulate peek
300 * support by reading into temporary buffers and passing these
301 * to VM.
303 r = builtin_peek(fdp, ino_nr, nbytes, pos);
304 } else
305 r = fdp->fdr_peek(ino_nr, NULL /*data*/, nbytes, pos,
306 FSC_PEEK);
308 /* Do not return a new position. */
309 if (r >= 0) {
310 m_out->m_fs_vfs_readwrite.nbytes = r;
311 r = OK;
314 return r;
318 * Process a GETDENTS request from VFS.
321 fsdriver_getdents(const struct fsdriver * __restrict fdp,
322 const message * __restrict m_in, message * __restrict m_out)
324 struct fsdriver_data data;
325 ino_t ino_nr;
326 off_t pos;
327 size_t nbytes;
328 ssize_t r;
330 ino_nr = m_in->m_vfs_fs_getdents.inode;
331 pos = m_in->m_vfs_fs_getdents.seek_pos;
332 nbytes = m_in->m_vfs_fs_getdents.mem_size;
334 if (fdp->fdr_getdents == NULL)
335 return ENOSYS;
337 if (pos < 0 || nbytes > SSIZE_MAX)
338 return EINVAL;
340 data.endpt = m_in->m_source;
341 data.grant = m_in->m_vfs_fs_getdents.grant;
342 data.size = nbytes;
344 r = fdp->fdr_getdents(ino_nr, &data, nbytes, &pos);
346 if (r >= 0) {
347 m_out->m_fs_vfs_getdents.seek_pos = pos;
348 m_out->m_fs_vfs_getdents.nbytes = r;
349 r = OK;
352 return r;
356 * Process a FTRUNC request from VFS.
359 fsdriver_trunc(const struct fsdriver * __restrict fdp,
360 const message * __restrict m_in, message * __restrict __unused m_out)
362 ino_t ino_nr;
363 off_t start_pos, end_pos;
365 ino_nr = m_in->m_vfs_fs_ftrunc.inode;
366 start_pos = m_in->m_vfs_fs_ftrunc.trc_start;
367 end_pos = m_in->m_vfs_fs_ftrunc.trc_end;
369 if (start_pos < 0 || end_pos < 0)
370 return EINVAL;
372 if (fdp->fdr_trunc == NULL)
373 return ENOSYS;
375 return fdp->fdr_trunc(ino_nr, start_pos, end_pos);
379 * Process a INHIBREAD request from VFS.
382 fsdriver_inhibread(const struct fsdriver * __restrict fdp,
383 const message * __restrict m_in, message * __restrict __unused m_out)
385 ino_t ino_nr;
387 ino_nr = m_in->m_vfs_fs_inhibread.inode;
389 if (fdp->fdr_seek != NULL)
390 fdp->fdr_seek(ino_nr);
392 return OK;
396 * Process a CREATE request from VFS.
399 fsdriver_create(const struct fsdriver * __restrict fdp,
400 const message * __restrict m_in, message * __restrict m_out)
402 struct fsdriver_node node;
403 char name[NAME_MAX+1];
404 cp_grant_id_t grant;
405 size_t len;
406 ino_t dir_nr;
407 mode_t mode;
408 uid_t uid;
409 gid_t gid;
410 int r;
412 grant = m_in->m_vfs_fs_create.grant;
413 len = m_in->m_vfs_fs_create.path_len;
414 dir_nr = m_in->m_vfs_fs_create.inode;
415 mode = m_in->m_vfs_fs_create.mode;
416 uid = m_in->m_vfs_fs_create.uid;
417 gid = m_in->m_vfs_fs_create.gid;
419 if (fdp->fdr_create == NULL)
420 return ENOSYS;
422 if ((r = fsdriver_getname(m_in->m_source, grant, len, name,
423 sizeof(name), TRUE /*not_empty*/)) != OK)
424 return r;
426 if (!strcmp(name, ".") || !strcmp(name, ".."))
427 return EEXIST;
429 if ((r = fdp->fdr_create(dir_nr, name, mode, uid, gid, &node)) == OK) {
430 m_out->m_fs_vfs_create.inode = node.fn_ino_nr;
431 m_out->m_fs_vfs_create.mode = node.fn_mode;
432 m_out->m_fs_vfs_create.file_size = node.fn_size;
433 m_out->m_fs_vfs_create.uid = node.fn_uid;
434 m_out->m_fs_vfs_create.gid = node.fn_gid;
437 return r;
441 * Process a MKDIR request from VFS.
444 fsdriver_mkdir(const struct fsdriver * __restrict fdp,
445 const message * __restrict m_in, message * __restrict __unused m_out)
447 char name[NAME_MAX+1];
448 cp_grant_id_t grant;
449 size_t path_len;
450 ino_t dir_nr;
451 mode_t mode;
452 uid_t uid;
453 gid_t gid;
454 int r;
456 grant = m_in->m_vfs_fs_mkdir.grant;
457 path_len = m_in->m_vfs_fs_mkdir.path_len;
458 dir_nr = m_in->m_vfs_fs_mkdir.inode;
459 mode = m_in->m_vfs_fs_mkdir.mode;
460 uid = m_in->m_vfs_fs_mkdir.uid;
461 gid = m_in->m_vfs_fs_mkdir.gid;
463 if (fdp->fdr_mkdir == NULL)
464 return ENOSYS;
466 if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name,
467 sizeof(name), TRUE /*not_empty*/)) != OK)
468 return r;
470 if (!strcmp(name, ".") || !strcmp(name, ".."))
471 return EEXIST;
473 return fdp->fdr_mkdir(dir_nr, name, mode, uid, gid);
477 * Process a MKNOD request from VFS.
480 fsdriver_mknod(const struct fsdriver * __restrict fdp,
481 const message * __restrict m_in, message * __restrict __unused m_out)
483 char name[NAME_MAX+1];
484 cp_grant_id_t grant;
485 size_t path_len;
486 ino_t dir_nr;
487 mode_t mode;
488 uid_t uid;
489 gid_t gid;
490 dev_t dev;
491 int r;
493 grant = m_in->m_vfs_fs_mknod.grant;
494 path_len = m_in->m_vfs_fs_mknod.path_len;
495 dir_nr = m_in->m_vfs_fs_mknod.inode;
496 mode = m_in->m_vfs_fs_mknod.mode;
497 uid = m_in->m_vfs_fs_mknod.uid;
498 gid = m_in->m_vfs_fs_mknod.gid;
499 dev = m_in->m_vfs_fs_mknod.device;
501 if (fdp->fdr_mknod == NULL)
502 return ENOSYS;
504 if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name,
505 sizeof(name), TRUE /*not_empty*/)) != OK)
506 return r;
508 if (!strcmp(name, ".") || !strcmp(name, ".."))
509 return EEXIST;
511 return fdp->fdr_mknod(dir_nr, name, mode, uid, gid, dev);
515 * Process a LINK request from VFS.
518 fsdriver_link(const struct fsdriver * __restrict fdp,
519 const message * __restrict m_in, message * __restrict __unused m_out)
521 char name[NAME_MAX+1];
522 cp_grant_id_t grant;
523 size_t path_len;
524 ino_t dir_nr, ino_nr;
525 int r;
527 grant = m_in->m_vfs_fs_link.grant;
528 path_len = m_in->m_vfs_fs_link.path_len;
529 dir_nr = m_in->m_vfs_fs_link.dir_ino;
530 ino_nr = m_in->m_vfs_fs_link.inode;
532 if (fdp->fdr_link == NULL)
533 return ENOSYS;
535 if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name,
536 sizeof(name), TRUE /*not_empty*/)) != OK)
537 return r;
539 if (!strcmp(name, ".") || !strcmp(name, ".."))
540 return EEXIST;
542 return fdp->fdr_link(dir_nr, name, ino_nr);
546 * Process an UNLINK request from VFS.
549 fsdriver_unlink(const struct fsdriver * __restrict fdp,
550 const message * __restrict m_in, message * __restrict __unused m_out)
552 char name[NAME_MAX+1];
553 cp_grant_id_t grant;
554 size_t path_len;
555 ino_t dir_nr;
556 int r;
558 grant = m_in->m_vfs_fs_unlink.grant;
559 path_len = m_in->m_vfs_fs_unlink.path_len;
560 dir_nr = m_in->m_vfs_fs_unlink.inode;
562 if (fdp->fdr_unlink == NULL)
563 return ENOSYS;
565 if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name,
566 sizeof(name), TRUE /*not_empty*/)) != OK)
567 return r;
569 if (!strcmp(name, ".") || !strcmp(name, ".."))
570 return EPERM;
572 return fdp->fdr_unlink(dir_nr, name, FSC_UNLINK);
576 * Process a RMDIR request from VFS.
579 fsdriver_rmdir(const struct fsdriver * __restrict fdp,
580 const message * __restrict m_in, message * __restrict __unused m_out)
582 char name[NAME_MAX+1];
583 cp_grant_id_t grant;
584 size_t path_len;
585 ino_t dir_nr;
586 int r;
588 grant = m_in->m_vfs_fs_unlink.grant;
589 path_len = m_in->m_vfs_fs_unlink.path_len;
590 dir_nr = m_in->m_vfs_fs_unlink.inode;
592 if (fdp->fdr_rmdir == NULL)
593 return ENOSYS;
595 if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name,
596 sizeof(name), TRUE /*not_empty*/)) != OK)
597 return r;
599 if (!strcmp(name, "."))
600 return EINVAL;
602 if (!strcmp(name, ".."))
603 return ENOTEMPTY;
605 return fdp->fdr_rmdir(dir_nr, name, FSC_RMDIR);
609 * Process a RENAME request from VFS.
612 fsdriver_rename(const struct fsdriver * __restrict fdp,
613 const message * __restrict m_in, message * __restrict __unused m_out)
615 char old_name[NAME_MAX+1], new_name[NAME_MAX+1];
616 cp_grant_id_t old_grant, new_grant;
617 size_t old_len, new_len;
618 ino_t old_dir_nr, new_dir_nr;
619 int r;
621 old_grant = m_in->m_vfs_fs_rename.grant_old;
622 old_len = m_in->m_vfs_fs_rename.len_old;
623 old_dir_nr = m_in->m_vfs_fs_rename.dir_old;
624 new_grant = m_in->m_vfs_fs_rename.grant_new;
625 new_len = m_in->m_vfs_fs_rename.len_new;
626 new_dir_nr = m_in->m_vfs_fs_rename.dir_new;
628 if (fdp->fdr_rename == NULL)
629 return ENOSYS;
631 if ((r = fsdriver_getname(m_in->m_source, old_grant, old_len, old_name,
632 sizeof(old_name), TRUE /*not_empty*/)) != OK)
633 return r;
635 if (!strcmp(old_name, ".") || !strcmp(old_name, ".."))
636 return EINVAL;
638 if ((r = fsdriver_getname(m_in->m_source, new_grant, new_len, new_name,
639 sizeof(new_name), TRUE /*not_empty*/)) != OK)
640 return r;
642 if (!strcmp(new_name, ".") || !strcmp(new_name, ".."))
643 return EINVAL;
645 return fdp->fdr_rename(old_dir_nr, old_name, new_dir_nr, new_name);
649 * Process a SLINK request from VFS.
652 fsdriver_slink(const struct fsdriver * __restrict fdp,
653 const message * __restrict m_in, message * __restrict __unused m_out)
655 struct fsdriver_data data;
656 char name[NAME_MAX+1];
657 cp_grant_id_t grant;
658 size_t path_len;
659 ino_t dir_nr;
660 uid_t uid;
661 gid_t gid;
662 int r;
664 grant = m_in->m_vfs_fs_slink.grant_path;
665 path_len = m_in->m_vfs_fs_slink.path_len;
666 dir_nr = m_in->m_vfs_fs_slink.inode;
667 uid = m_in->m_vfs_fs_slink.uid;
668 gid = m_in->m_vfs_fs_slink.gid;
670 if (fdp->fdr_slink == NULL)
671 return ENOSYS;
673 if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name,
674 sizeof(name), TRUE /*not_empty*/)) != OK)
675 return r;
677 if (!strcmp(name, ".") || !strcmp(name, ".."))
678 return EEXIST;
680 data.endpt = m_in->m_source;
681 data.grant = m_in->m_vfs_fs_slink.grant_target;
682 data.size = m_in->m_vfs_fs_slink.mem_size;
684 return fdp->fdr_slink(dir_nr, name, uid, gid, &data, data.size);
688 * Process a RDLINK request from VFS.
691 fsdriver_rdlink(const struct fsdriver * __restrict fdp,
692 const message * __restrict m_in, message * __restrict m_out)
694 struct fsdriver_data data;
695 ssize_t r;
697 if (fdp->fdr_rdlink == NULL)
698 return ENOSYS;
700 data.endpt = m_in->m_source;
701 data.grant = m_in->m_vfs_fs_rdlink.grant;
702 data.size = m_in->m_vfs_fs_rdlink.mem_size;
704 r = fdp->fdr_rdlink(m_in->m_vfs_fs_rdlink.inode, &data, data.size);
706 if (r >= 0) {
707 m_out->m_fs_vfs_rdlink.nbytes = r;
708 r = OK;
711 return r;
715 * Process a STAT request from VFS.
718 fsdriver_stat(const struct fsdriver * __restrict fdp,
719 const message * __restrict m_in, message * __restrict __unused m_out)
721 struct stat buf;
722 cp_grant_id_t grant;
723 ino_t ino_nr;
724 int r;
726 ino_nr = m_in->m_vfs_fs_stat.inode;
727 grant = m_in->m_vfs_fs_stat.grant;
729 if (fdp->fdr_stat == NULL)
730 return ENOSYS;
732 memset(&buf, 0, sizeof(buf));
733 buf.st_dev = fsdriver_device;
734 buf.st_ino = ino_nr;
736 if ((r = fdp->fdr_stat(ino_nr, &buf)) == OK)
737 r = sys_safecopyto(m_in->m_source, grant, 0, (vir_bytes)&buf,
738 (phys_bytes)sizeof(buf));
740 return r;
744 * Process a CHOWN request from VFS.
747 fsdriver_chown(const struct fsdriver * __restrict fdp,
748 const message * __restrict m_in, message * __restrict m_out)
750 ino_t ino_nr;
751 uid_t uid;
752 gid_t gid;
753 mode_t mode;
754 int r;
756 ino_nr = m_in->m_vfs_fs_chown.inode;
757 uid = m_in->m_vfs_fs_chown.uid;
758 gid = m_in->m_vfs_fs_chown.gid;
760 if (fdp->fdr_chown == NULL)
761 return ENOSYS;
763 if ((r = fdp->fdr_chown(ino_nr, uid, gid, &mode)) == OK)
764 m_out->m_fs_vfs_chown.mode = mode;
766 return r;
770 * Process a CHMOD request from VFS.
773 fsdriver_chmod(const struct fsdriver * __restrict fdp,
774 const message * __restrict m_in, message * __restrict m_out)
776 ino_t ino_nr;
777 mode_t mode;
778 int r;
780 ino_nr = m_in->m_vfs_fs_chmod.inode;
781 mode = m_in->m_vfs_fs_chmod.mode;
783 if (fdp->fdr_chmod == NULL)
784 return ENOSYS;
786 if ((r = fdp->fdr_chmod(ino_nr, &mode)) == OK)
787 m_out->m_fs_vfs_chmod.mode = mode;
789 return r;
793 * Process a UTIME request from VFS.
796 fsdriver_utime(const struct fsdriver * __restrict fdp,
797 const message * __restrict m_in, message * __restrict __unused m_out)
799 ino_t ino_nr;
800 struct timespec atime, mtime;
802 ino_nr = m_in->m_vfs_fs_utime.inode;
803 atime.tv_sec = m_in->m_vfs_fs_utime.actime;
804 atime.tv_nsec = m_in->m_vfs_fs_utime.acnsec;
805 mtime.tv_sec = m_in->m_vfs_fs_utime.modtime;
806 mtime.tv_nsec = m_in->m_vfs_fs_utime.modnsec;
808 if (fdp->fdr_utime == NULL)
809 return ENOSYS;
811 return fdp->fdr_utime(ino_nr, &atime, &mtime);
815 * Process a MOUNTPOINT request from VFS.
818 fsdriver_mountpoint(const struct fsdriver * __restrict fdp,
819 const message * __restrict m_in, message * __restrict __unused m_out)
821 ino_t ino_nr;
823 ino_nr = m_in->m_vfs_fs_mountpoint.inode;
825 if (fdp->fdr_mountpt == NULL)
826 return ENOSYS;
828 return fdp->fdr_mountpt(ino_nr);
832 * Process a STATVFS request from VFS.
835 fsdriver_statvfs(const struct fsdriver * __restrict fdp,
836 const message * __restrict m_in, message * __restrict __unused m_out)
838 struct statvfs buf;
839 int r;
841 if (fdp->fdr_statvfs == NULL)
842 return ENOSYS;
844 memset(&buf, 0, sizeof(buf));
846 if ((r = fdp->fdr_statvfs(&buf)) != OK)
847 return r;
849 return sys_safecopyto(m_in->m_source, m_in->m_vfs_fs_statvfs.grant, 0,
850 (vir_bytes)&buf, (phys_bytes)sizeof(buf));
854 * Process a SYNC request from VFS.
857 fsdriver_sync(const struct fsdriver * __restrict fdp,
858 const message * __restrict __unused m_in,
859 message * __restrict __unused m_out)
862 if (fdp->fdr_sync != NULL)
863 fdp->fdr_sync();
865 return OK;
869 * Process a NEW_DRIVER request from VFS.
872 fsdriver_newdriver(const struct fsdriver * __restrict fdp,
873 const message * __restrict m_in, message * __restrict __unused m_out)
875 char label[DS_MAX_KEYLEN];
876 cp_grant_id_t grant;
877 size_t path_len;
878 dev_t dev;
879 int r;
881 dev = m_in->m_vfs_fs_new_driver.device;
882 grant = m_in->m_vfs_fs_new_driver.grant;
883 path_len = m_in->m_vfs_fs_new_driver.path_len;
885 if (fdp->fdr_driver == NULL)
886 return OK;
888 if ((r = fsdriver_getname(m_in->m_source, grant, path_len, label,
889 sizeof(label), FALSE /*not_empty*/)) != OK)
890 return r;
892 fdp->fdr_driver(dev, label);
894 return OK;
898 * Process a block read or write request from VFS.
900 static ssize_t
901 bread_bwrite(const struct fsdriver * __restrict fdp,
902 const message * __restrict m_in, message * __restrict m_out, int call)
904 struct fsdriver_data data;
905 dev_t dev;
906 off_t pos;
907 size_t nbytes;
908 ssize_t r;
910 dev = m_in->m_vfs_fs_breadwrite.device;
911 pos = m_in->m_vfs_fs_breadwrite.seek_pos;
912 nbytes = m_in->m_vfs_fs_breadwrite.nbytes;
914 if (pos < 0 || nbytes > SSIZE_MAX)
915 return EINVAL;
917 data.endpt = m_in->m_source;
918 data.grant = m_in->m_vfs_fs_breadwrite.grant;
919 data.size = nbytes;
921 if (call == FSC_WRITE)
922 r = fdp->fdr_bwrite(dev, &data, nbytes, pos, call);
923 else
924 r = fdp->fdr_bread(dev, &data, nbytes, pos, call);
926 if (r >= 0) {
927 pos += r;
929 m_out->m_fs_vfs_breadwrite.seek_pos = pos;
930 m_out->m_fs_vfs_breadwrite.nbytes = r;
931 r = OK;
934 return r;
938 * Process a BREAD request from VFS.
940 ssize_t
941 fsdriver_bread(const struct fsdriver * __restrict fdp,
942 const message * __restrict m_in, message * __restrict m_out)
945 if (fdp->fdr_bread == NULL)
946 return ENOSYS;
948 return bread_bwrite(fdp, m_in, m_out, FSC_READ);
952 * Process a BWRITE request from VFS.
954 ssize_t
955 fsdriver_bwrite(const struct fsdriver * __restrict fdp,
956 const message * __restrict m_in, message * __restrict m_out)
959 if (fdp->fdr_bwrite == NULL)
960 return ENOSYS;
962 return bread_bwrite(fdp, m_in, m_out, FSC_WRITE);
966 * Process a BPEEK request from VFS.
969 fsdriver_bpeek(const struct fsdriver * __restrict fdp,
970 const message * __restrict m_in, message * __restrict __unused m_out)
972 dev_t dev;
973 off_t pos;
974 size_t nbytes;
975 ssize_t r;
977 dev = m_in->m_vfs_fs_breadwrite.device;
978 pos = m_in->m_vfs_fs_breadwrite.seek_pos;
979 nbytes = m_in->m_vfs_fs_breadwrite.nbytes;
981 if (fdp->fdr_bpeek == NULL)
982 return ENOSYS;
984 if (pos < 0 || nbytes > SSIZE_MAX)
985 return EINVAL;
987 r = fdp->fdr_bpeek(dev, NULL /*data*/, nbytes, pos, FSC_PEEK);
989 /* Do not return a new position. */
990 if (r >= 0) {
991 m_out->m_fs_vfs_breadwrite.nbytes = r;
992 r = OK;
995 return r;
999 * Process a FLUSH request from VFS.
1002 fsdriver_flush(const struct fsdriver * __restrict fdp,
1003 const message * __restrict m_in, message * __restrict __unused m_out)
1005 dev_t dev;
1007 dev = m_in->m_vfs_fs_flush.device;
1009 if (fdp->fdr_bflush != NULL)
1010 fdp->fdr_bflush(dev);
1012 return OK;