make vfs & filesystems use failable copying
[minix3.git] / servers / vfs / request.c
bloba68d2eea93aced5429e4d93046bd5b2337021519
1 /* This file contains the wrapper functions for issuing a request
2 * and receiving response from FS processes.
3 * Each function builds a request message according to the request
4 * parameter, calls the most low-level fs_sendrec, and copies
5 * back the response.
6 */
8 #include "fs.h"
9 #include <minix/com.h>
10 #include <minix/const.h>
11 #include <minix/endpoint.h>
12 #include <minix/u64.h>
13 #include <minix/vfsif.h>
14 #include <sys/dirent.h>
15 #include <sys/stat.h>
16 #include <sys/statvfs.h>
17 #include <assert.h>
18 #include <stddef.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <time.h>
22 #include "path.h"
23 #include "vmnt.h"
24 #include "vnode.h"
27 /*===========================================================================*
28 * req_breadwrite_actual *
29 *===========================================================================*/
30 static int req_breadwrite_actual(endpoint_t fs_e, endpoint_t user_e, dev_t dev, off_t pos,
31 unsigned int num_of_bytes, vir_bytes user_addr, int rw_flag,
32 off_t *new_pos, unsigned int *cum_iop, int cpflag)
34 int r;
35 cp_grant_id_t grant_id;
36 message m;
38 grant_id = cpf_grant_magic(fs_e, user_e, user_addr, num_of_bytes,
39 (rw_flag == READING ? CPF_WRITE : CPF_READ) | cpflag);
40 if(grant_id == -1)
41 panic("req_breadwrite: cpf_grant_magic failed");
43 /* Fill in request message */
44 m.m_type = rw_flag == READING ? REQ_BREAD : REQ_BWRITE;
45 m.REQ_DEV = dev;
46 m.REQ_GRANT = grant_id;
47 m.REQ_SEEK_POS = pos;
48 m.REQ_NBYTES = num_of_bytes;
50 /* Send/rec request */
51 r = fs_sendrec(fs_e, &m);
52 cpf_revoke(grant_id);
53 if (r != OK) return(r);
55 /* Fill in response structure */
56 *new_pos = m.RES_SEEK_POS;
57 *cum_iop = m.RES_NBYTES;
59 return(OK);
62 int req_breadwrite(endpoint_t fs_e, endpoint_t user_e, dev_t dev, off_t pos,
63 unsigned int num_of_bytes, vir_bytes user_addr, int rw_flag,
64 off_t *new_pos, unsigned int *cum_iop)
66 int r;
68 r = req_breadwrite_actual(fs_e, user_e, dev, pos, num_of_bytes,
69 user_addr, rw_flag, new_pos, cum_iop, CPF_TRY);
71 if(r == EFAULT) {
72 if((r=vm_vfs_procctl_handlemem(user_e, user_addr, num_of_bytes,
73 rw_flag == READING)) != OK) {
74 return r;
77 r = req_breadwrite_actual(fs_e, user_e, dev, pos, num_of_bytes,
78 user_addr, rw_flag, new_pos, cum_iop, 0);
81 return r;
84 /*===========================================================================*
85 * req_bpeek *
86 *===========================================================================*/
87 int req_bpeek(endpoint_t fs_e, dev_t dev, off_t pos, unsigned int num_of_bytes)
89 message m;
91 memset(&m, 0, sizeof(m));
93 /* Fill in request message */
94 m.m_type = REQ_BPEEK;
95 m.REQ_DEV = dev;
96 m.REQ_SEEK_POS = pos;
97 m.REQ_NBYTES = num_of_bytes;
99 /* Send/rec request */
100 return fs_sendrec(fs_e, &m);
103 /*===========================================================================*
104 * req_chmod *
105 *===========================================================================*/
106 int req_chmod(
107 endpoint_t fs_e,
108 ino_t inode_nr,
109 mode_t rmode,
110 mode_t *new_modep
113 message m;
114 int r;
116 /* Fill in request message */
117 m.m_type = REQ_CHMOD;
118 m.REQ_INODE_NR = (pino_t) inode_nr;
119 m.REQ_MODE = (pmode_t) rmode;
121 /* Send/rec request */
122 r = fs_sendrec(fs_e, &m);
124 /* Copy back actual mode. */
125 *new_modep = (mode_t) m.RES_MODE;
127 return(r);
131 /*===========================================================================*
132 * req_chown *
133 *===========================================================================*/
134 int req_chown(
135 endpoint_t fs_e,
136 ino_t inode_nr,
137 uid_t newuid,
138 gid_t newgid,
139 mode_t *new_modep
142 message m;
143 int r;
145 /* Fill in request message */
146 m.m_type = REQ_CHOWN;
147 m.REQ_INODE_NR = (pino_t) inode_nr;
148 m.REQ_UID = (puid_t) newuid;
149 m.REQ_GID = (pgid_t) newgid;
151 /* Send/rec request */
152 r = fs_sendrec(fs_e, &m);
154 /* Return new mode to caller. */
155 *new_modep = (mode_t) m.RES_MODE;
157 return(r);
161 /*===========================================================================*
162 * req_create *
163 *===========================================================================*/
164 int req_create(
165 endpoint_t fs_e,
166 ino_t inode_nr,
167 int omode,
168 uid_t uid,
169 gid_t gid,
170 char *path,
171 node_details_t *res
174 int r;
175 cp_grant_id_t grant_id;
176 size_t len;
177 message m;
178 struct vmnt *vmp;
180 vmp = find_vmnt(fs_e);
182 len = strlen(path) + 1;
183 grant_id = cpf_grant_direct(fs_e, (vir_bytes) path, len, CPF_READ);
184 if (grant_id == -1)
185 panic("req_create: cpf_grant_direct failed");
187 /* Fill in request message */
188 m.m_type = REQ_CREATE;
189 m.REQ_INODE_NR = (pino_t) inode_nr;
190 m.REQ_MODE = (pmode_t) omode;
191 m.REQ_UID = (puid_t) uid;
192 m.REQ_GID = (pgid_t) gid;
193 m.REQ_GRANT = grant_id;
194 m.REQ_PATH_LEN = len;
196 /* Send/rec request */
197 r = fs_sendrec(fs_e, &m);
198 cpf_revoke(grant_id);
199 if (r != OK) return(r);
201 /* Fill in response structure */
202 res->fs_e = m.m_source;
203 res->inode_nr = (ino_t) m.RES_INODE_NR;
204 res->fmode = (mode_t) m.RES_MODE;
205 res->fsize = m.RES_FILE_SIZE;
206 res->uid = (uid_t) m.RES_UID;
207 res->gid = (gid_t) m.RES_GID;
208 res->dev = NO_DEV;
210 return(OK);
214 /*===========================================================================*
215 * req_flush *
216 *===========================================================================*/
217 int req_flush(endpoint_t fs_e, dev_t dev)
219 message m;
221 /* Fill in request message */
222 m.m_type = REQ_FLUSH;
223 m.REQ_DEV = dev;
225 /* Send/rec request */
226 return fs_sendrec(fs_e, &m);
230 /*===========================================================================*
231 * req_statvfs *
232 *===========================================================================*/
233 int req_statvfs(endpoint_t fs_e, struct statvfs *buf)
235 int r;
236 cp_grant_id_t grant_id;
237 message m;
239 grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, sizeof(struct statvfs),
240 CPF_WRITE);
241 if(grant_id == GRANT_INVALID)
242 panic("req_statvfs: cpf_grant_direct failed");
244 /* Fill in request message */
245 m.m_type = REQ_STATVFS;
246 m.REQ_GRANT = grant_id;
248 /* Send/rec request */
249 r = fs_sendrec(fs_e, &m);
250 cpf_revoke(grant_id);
252 return(r);
256 /*===========================================================================*
257 * req_ftrunc *
258 *===========================================================================*/
259 int req_ftrunc(endpoint_t fs_e, ino_t inode_nr, off_t start, off_t end)
261 message m;
262 struct vmnt *vmp;
264 vmp = find_vmnt(fs_e);
266 /* Fill in request message */
267 m.m_type = REQ_FTRUNC;
268 m.REQ_INODE_NR = (pino_t) inode_nr;
269 m.REQ_TRC_START = start;
270 m.REQ_TRC_END = end;
272 if (!(vmp->m_fs_flags & RES_64BIT) &&
273 ((start > INT_MAX) || (end > INT_MAX))) {
274 /* FS does not support 64-bit off_t and 32 bits is not enough */
275 return EINVAL;
278 /* Send/rec request */
279 return fs_sendrec(fs_e, &m);
283 /*===========================================================================*
284 * req_getdents_actual *
285 *===========================================================================*/
286 static int req_getdents_actual(
287 endpoint_t fs_e,
288 ino_t inode_nr,
289 off_t pos,
290 char *buf,
291 size_t size,
292 off_t *new_pos,
293 int direct,
294 int cpflag
297 int r;
298 message m;
299 cp_grant_id_t grant_id;
300 struct vmnt *vmp;
302 vmp = find_vmnt(fs_e);
303 assert(vmp != NULL);
305 if (direct) {
306 grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, size, CPF_WRITE);
307 } else {
308 grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, size,
309 CPF_WRITE | cpflag);
312 if (grant_id < 0)
313 panic("req_getdents: cpf_grant_direct/cpf_grant_magic failed: %d",
314 grant_id);
316 m.m_type = REQ_GETDENTS;
317 m.REQ_INODE_NR = (pino_t) inode_nr;
318 m.REQ_GRANT = grant_id;
319 m.REQ_MEM_SIZE = size;
320 m.REQ_SEEK_POS = pos;
321 if (!(vmp->m_fs_flags & RES_64BIT) && (pos > INT_MAX)) {
322 /* FS does not support 64-bit off_t and 32 bits is not enough */
323 return EINVAL;
326 r = fs_sendrec(fs_e, &m);
327 cpf_revoke(grant_id);
329 if (r == OK) {
330 *new_pos = m.RES_SEEK_POS;
331 r = m.RES_NBYTES;
334 return(r);
337 /*===========================================================================*
338 * req_getdents *
339 *===========================================================================*/
340 int req_getdents(
341 endpoint_t fs_e,
342 ino_t inode_nr,
343 off_t pos,
344 char *buf,
345 size_t size,
346 off_t *new_pos,
347 int direct)
349 int r;
351 r = req_getdents_actual(fs_e, inode_nr, pos, buf, size, new_pos,
352 direct, CPF_TRY);
354 if(r == EFAULT && !direct) {
355 if((r=vm_vfs_procctl_handlemem(who_e, (vir_bytes) buf,
356 size, 1)) != OK) {
357 return r;
360 r = req_getdents_actual(fs_e, inode_nr, pos, buf, size,
361 new_pos, direct, 0);
364 return r;
367 /*===========================================================================*
368 * req_inhibread *
369 *===========================================================================*/
370 int req_inhibread(endpoint_t fs_e, ino_t inode_nr)
372 message m;
374 /* Fill in request message */
375 m.m_type = REQ_INHIBREAD;
376 m.REQ_INODE_NR = (pino_t) inode_nr;
378 /* Send/rec request */
379 return fs_sendrec(fs_e, &m);
383 /*===========================================================================*
384 * req_link *
385 *===========================================================================*/
386 int req_link(
387 endpoint_t fs_e,
388 ino_t link_parent,
389 char *lastc,
390 ino_t linked_file
393 int r;
394 cp_grant_id_t grant_id;
395 const size_t len = strlen(lastc) + 1;
396 message m;
398 grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
399 if(grant_id == -1)
400 panic("req_link: cpf_grant_direct failed");
402 /* Fill in request message */
403 m.m_type = REQ_LINK;
404 m.REQ_INODE_NR = (pino_t) linked_file;
405 m.REQ_DIR_INO = (pino_t) link_parent;
406 m.REQ_GRANT = grant_id;
407 m.REQ_PATH_LEN = len;
409 /* Send/rec request */
410 r = fs_sendrec(fs_e, &m);
411 cpf_revoke(grant_id);
413 return(r);
417 /*===========================================================================*
418 * req_lookup *
419 *===========================================================================*/
420 int req_lookup(
421 endpoint_t fs_e,
422 ino_t dir_ino,
423 ino_t root_ino,
424 uid_t uid,
425 gid_t gid,
426 struct lookup *resolve,
427 lookup_res_t *res,
428 struct fproc *rfp
431 message m;
432 vfs_ucred_t credentials;
433 int r, flags;
434 size_t len;
435 struct vmnt *vmp;
436 cp_grant_id_t grant_id=0, grant_id2=0;
438 vmp = find_vmnt(fs_e);
440 grant_id = cpf_grant_direct(fs_e, (vir_bytes) resolve->l_path, PATH_MAX,
441 CPF_READ | CPF_WRITE);
442 if(grant_id == -1)
443 panic("req_lookup: cpf_grant_direct failed");
445 flags = resolve->l_flags;
446 len = strlen(resolve->l_path) + 1;
448 m.m_type = REQ_LOOKUP;
449 m.REQ_GRANT = grant_id;
450 m.REQ_PATH_LEN = len;
451 m.REQ_PATH_SIZE = PATH_MAX + 1;
452 m.REQ_DIR_INO = (pino_t) dir_ino;
453 m.REQ_ROOT_INO = (pino_t) root_ino;
455 if(rfp->fp_ngroups > 0) { /* Is the process member of multiple groups? */
456 /* In that case the FS has to copy the uid/gid credentials */
457 int i;
459 /* Set credentials */
460 credentials.vu_uid = rfp->fp_effuid;
461 credentials.vu_gid = rfp->fp_effgid;
462 credentials.vu_ngroups = rfp->fp_ngroups;
463 for (i = 0; i < rfp->fp_ngroups; i++)
464 credentials.vu_sgroups[i] = rfp->fp_sgroups[i];
466 grant_id2 = cpf_grant_direct(fs_e, (vir_bytes) &credentials,
467 sizeof(credentials), CPF_READ);
468 if(grant_id2 == -1)
469 panic("req_lookup: cpf_grant_direct failed");
471 m.REQ_GRANT2 = grant_id2;
472 m.REQ_UCRED_SIZE= sizeof(credentials);
473 flags |= PATH_GET_UCRED;
474 } else {
475 /* When there's only one gid, we can send it directly */
476 m.REQ_UID = (pgid_t) uid;
477 m.REQ_GID = (pgid_t) gid;
478 flags &= ~PATH_GET_UCRED;
481 m.REQ_FLAGS = flags;
483 /* Send/rec request */
484 r = fs_sendrec(fs_e, &m);
485 cpf_revoke(grant_id);
486 if(rfp->fp_ngroups > 0) cpf_revoke(grant_id2);
488 /* Fill in response according to the return value */
489 res->fs_e = m.m_source;
491 switch (r) {
492 case OK:
493 res->inode_nr = (ino_t) m.RES_INODE_NR;
494 res->fmode = (mode_t) m.RES_MODE;
495 res->fsize = m.RES_FILE_SIZE;
496 res->dev = m.RES_DEV;
497 res->uid = (uid_t) m.RES_UID;
498 res->gid = (gid_t) m.RES_GID;
499 break;
500 case EENTERMOUNT:
501 res->inode_nr = (ino_t) m.RES_INODE_NR;
502 res->char_processed = m.RES_OFFSET;
503 res->symloop = m.RES_SYMLOOP;
504 break;
505 case ELEAVEMOUNT:
506 res->char_processed = m.RES_OFFSET;
507 res->symloop = m.RES_SYMLOOP;
508 break;
509 case ESYMLINK:
510 res->char_processed = m.RES_OFFSET;
511 res->symloop = m.RES_SYMLOOP;
512 break;
513 default:
514 break;
517 return(r);
521 /*===========================================================================*
522 * req_mkdir *
523 *===========================================================================*/
524 int req_mkdir(
525 endpoint_t fs_e,
526 ino_t inode_nr,
527 char *lastc,
528 uid_t uid,
529 gid_t gid,
530 mode_t dmode
533 int r;
534 cp_grant_id_t grant_id;
535 size_t len;
536 message m;
538 len = strlen(lastc) + 1;
539 grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
540 if(grant_id == -1)
541 panic("req_mkdir: cpf_grant_direct failed");
543 /* Fill in request message */
544 m.m_type = REQ_MKDIR;
545 m.REQ_INODE_NR = (pino_t) inode_nr;
546 m.REQ_MODE = (pmode_t) dmode;
547 m.REQ_UID = (puid_t) uid;
548 m.REQ_GID = (pgid_t) gid;
549 m.REQ_GRANT = grant_id;
550 m.REQ_PATH_LEN = len;
552 /* Send/rec request */
553 r = fs_sendrec(fs_e, &m);
554 cpf_revoke(grant_id);
556 return(r);
560 /*===========================================================================*
561 * req_mknod *
562 *===========================================================================*/
563 int req_mknod(
564 endpoint_t fs_e,
565 ino_t inode_nr,
566 char *lastc,
567 uid_t uid,
568 gid_t gid,
569 mode_t dmode,
570 dev_t dev
573 int r;
574 size_t len;
575 cp_grant_id_t grant_id;
576 message m;
578 len = strlen(lastc) + 1;
579 grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
580 if(grant_id == -1)
581 panic("req_mknod: cpf_grant_direct failed");
583 /* Fill in request message */
584 m.m_type = REQ_MKNOD;
585 m.REQ_INODE_NR = (pino_t) inode_nr;
586 m.REQ_MODE = (pmode_t) dmode;
587 m.REQ_DEV = dev;
588 m.REQ_UID = (puid_t) uid;
589 m.REQ_GID = (pgid_t) gid;
590 m.REQ_GRANT = grant_id;
591 m.REQ_PATH_LEN = len;
593 /* Send/rec request */
594 r = fs_sendrec(fs_e, &m);
595 cpf_revoke(grant_id);
597 return(r);
601 /*===========================================================================*
602 * req_mountpoint *
603 *===========================================================================*/
604 int req_mountpoint(endpoint_t fs_e, ino_t inode_nr)
606 message m;
608 /* Fill in request message */
609 m.m_type = REQ_MOUNTPOINT;
610 m.REQ_INODE_NR = (pino_t) inode_nr;
612 /* Send/rec request */
613 return fs_sendrec(fs_e, &m);
617 /*===========================================================================*
618 * req_newnode *
619 *===========================================================================*/
620 int req_newnode(
621 endpoint_t fs_e,
622 uid_t uid,
623 gid_t gid,
624 mode_t dmode,
625 dev_t dev,
626 struct node_details *res
629 struct vmnt *vmp;
630 int r;
631 message m;
633 vmp = find_vmnt(fs_e);
635 /* Fill in request message */
636 m.m_type = REQ_NEWNODE;
637 m.REQ_MODE = (pmode_t) dmode;
638 m.REQ_DEV = dev;
639 m.REQ_UID = (puid_t) uid;
640 m.REQ_GID = (pgid_t) gid;
642 /* Send/rec request */
643 r = fs_sendrec(fs_e, &m);
645 res->fs_e = m.m_source;
646 res->inode_nr = (ino_t) m.RES_INODE_NR;
647 res->fmode = (mode_t) m.RES_MODE;
648 res->fsize = m.RES_FILE_SIZE;
649 res->dev = m.RES_DEV;
650 res->uid = (uid_t) m.RES_UID;
651 res->gid = (gid_t) m.RES_GID;
653 return(r);
657 /*===========================================================================*
658 * req_newdriver *
659 *===========================================================================*/
660 int req_newdriver(
661 endpoint_t fs_e,
662 dev_t dev,
663 char *label
666 cp_grant_id_t grant_id;
667 size_t len;
668 message m;
669 int r;
671 /* Grant access to label */
672 len = strlen(label) + 1;
673 grant_id = cpf_grant_direct(fs_e, (vir_bytes) label, len, CPF_READ);
674 if (grant_id == -1)
675 panic("req_newdriver: cpf_grant_direct failed");
677 /* Fill in request message */
678 m.m_type = REQ_NEW_DRIVER;
679 m.REQ_DEV = dev;
680 m.REQ_GRANT = grant_id;
681 m.REQ_PATH_LEN = len;
683 /* Issue request */
684 r = fs_sendrec(fs_e, &m);
686 cpf_revoke(grant_id);
688 return(r);
692 /*===========================================================================*
693 * req_putnode *
694 *===========================================================================*/
695 int req_putnode(fs_e, inode_nr, count)
696 int fs_e;
697 ino_t inode_nr;
698 int count;
700 message m;
702 /* Fill in request message */
703 m.m_type = REQ_PUTNODE;
704 m.REQ_INODE_NR = (pino_t) inode_nr;
705 m.REQ_COUNT = count;
707 /* Send/rec request */
708 return fs_sendrec(fs_e, &m);
712 /*===========================================================================*
713 * req_rdlink_actual *
714 *===========================================================================*/
715 static int req_rdlink_actual(endpoint_t fs_e, ino_t inode_nr,
716 endpoint_t proc_e, vir_bytes buf, size_t len,
717 int direct, /* set to 1 to use direct grants instead of magic grants */
718 int cpflag)
720 message m;
721 int r;
722 cp_grant_id_t grant_id;
724 if (direct) {
725 grant_id = cpf_grant_direct(fs_e, buf, len, CPF_WRITE);
726 } else {
727 grant_id = cpf_grant_magic(fs_e, proc_e, buf, len, CPF_WRITE | cpflag);
729 if (grant_id == -1)
730 panic("req_rdlink: cpf_grant_magic failed");
732 /* Fill in request message */
733 m.m_type = REQ_RDLINK;
734 m.REQ_INODE_NR = (pino_t) inode_nr;
735 m.REQ_GRANT = grant_id;
736 m.REQ_MEM_SIZE = len;
738 /* Send/rec request */
739 r = fs_sendrec(fs_e, &m);
740 cpf_revoke(grant_id);
742 if (r == OK) r = m.RES_NBYTES;
744 return(r);
747 /*===========================================================================*
748 * req_rdlink *
749 *===========================================================================*/
750 int req_rdlink(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e,
751 vir_bytes buf, size_t len,
752 int direct /* set to 1 to use direct grants instead of magic grants */
755 int r;
757 r = req_rdlink_actual(fs_e, inode_nr, proc_e, buf, len, direct,
758 CPF_TRY);
760 if(r == EFAULT && !direct) {
761 if((r=vm_vfs_procctl_handlemem(proc_e, buf, len, 1)) != OK) {
762 return r;
765 r = req_rdlink_actual(fs_e, inode_nr, proc_e, buf, len,
766 direct, 0);
769 return r;
772 /*===========================================================================*
773 * req_readsuper *
774 *===========================================================================*/
775 int req_readsuper(
776 struct vmnt *vmp,
777 char *label,
778 dev_t dev,
779 int readonly,
780 int isroot,
781 struct node_details *res,
782 unsigned int *fs_flags
785 int r;
786 cp_grant_id_t grant_id;
787 size_t len;
788 message m;
789 endpoint_t fs_e;
791 fs_e = vmp->m_fs_e;
793 len = strlen(label)+1;
794 grant_id = cpf_grant_direct(fs_e, (vir_bytes) label, len, CPF_READ);
795 if (grant_id == -1)
796 panic("req_readsuper: cpf_grant_direct failed");
798 /* Fill in request message */
799 m.m_type = REQ_READSUPER;
800 m.REQ_FLAGS = 0;
801 if(readonly) m.REQ_FLAGS |= REQ_RDONLY;
802 if(isroot) m.REQ_FLAGS |= REQ_ISROOT;
803 m.REQ_GRANT = grant_id;
804 m.REQ_DEV = dev;
805 m.REQ_PATH_LEN = len;
807 /* Send/rec request */
808 r = fs_sendrec(fs_e, &m);
809 cpf_revoke(grant_id);
811 if(r == OK) {
812 /* Fill in response structure */
813 res->fs_e = m.m_source;
814 res->inode_nr = (ino_t) m.RES_INODE_NR;
815 res->fmode = (mode_t) m.RES_MODE;
816 res->fsize = m.RES_FILE_SIZE;
817 res->uid = (uid_t) m.RES_UID;
818 res->gid = (gid_t) m.RES_GID;
819 *fs_flags = m.RES_FLAGS;
822 return(r);
826 /*===========================================================================*
827 * req_readwrite_actual *
828 *===========================================================================*/
829 static int req_readwrite_actual(endpoint_t fs_e, ino_t inode_nr, off_t pos,
830 int rw_flag, endpoint_t user_e, vir_bytes user_addr,
831 unsigned int num_of_bytes, off_t *new_posp, unsigned int *cum_iop,
832 int cpflag)
834 struct vmnt *vmp;
835 int r;
836 cp_grant_id_t grant_id;
837 message m;
839 vmp = find_vmnt(fs_e);
841 grant_id = cpf_grant_magic(fs_e, user_e, user_addr, num_of_bytes,
842 (rw_flag==READING ? CPF_WRITE:CPF_READ) | cpflag);
843 if (grant_id == -1)
844 panic("req_readwrite: cpf_grant_magic failed");
846 /* Fill in request message */
847 m.m_type = rw_flag == READING ? REQ_READ : REQ_WRITE;
848 m.REQ_INODE_NR = (pino_t) inode_nr;
849 m.REQ_GRANT = grant_id;
850 m.REQ_SEEK_POS = pos;
851 if ((!(vmp->m_fs_flags & RES_64BIT)) && (pos > INT_MAX)) {
852 return EINVAL;
854 m.REQ_NBYTES = num_of_bytes;
856 /* Send/rec request */
857 r = fs_sendrec(fs_e, &m);
858 cpf_revoke(grant_id);
860 if (r == OK) {
861 /* Fill in response structure */
862 *new_posp = m.RES_SEEK_POS;
863 *cum_iop = m.RES_NBYTES;
866 return(r);
869 /*===========================================================================*
870 * req_readwrite *
871 *===========================================================================*/
872 int req_readwrite(endpoint_t fs_e, ino_t inode_nr, off_t pos,
873 int rw_flag, endpoint_t user_e, vir_bytes user_addr,
874 unsigned int num_of_bytes, off_t *new_posp, unsigned int *cum_iop)
876 int r;
878 r = req_readwrite_actual(fs_e, inode_nr, pos, rw_flag, user_e,
879 user_addr, num_of_bytes, new_posp, cum_iop, CPF_TRY);
881 if(r == EFAULT) {
882 if((r=vm_vfs_procctl_handlemem(user_e, (vir_bytes) user_addr, num_of_bytes,
883 rw_flag == READING)) != OK) {
884 return r;
887 r = req_readwrite_actual(fs_e, inode_nr, pos, rw_flag, user_e,
888 user_addr, num_of_bytes, new_posp, cum_iop, 0);
891 return r;
894 /*===========================================================================*
895 * req_peek *
896 *===========================================================================*/
897 int req_peek(endpoint_t fs_e, ino_t inode_nr, off_t pos, unsigned int bytes)
899 message m;
901 memset(&m, 0, sizeof(m));
903 if (ex64hi(pos) != 0)
904 panic("req_peek: pos too large");
906 /* Fill in request message */
907 m.m_type = REQ_PEEK;
908 m.REQ_INODE_NR = inode_nr;
909 m.REQ_GRANT = -1;
910 m.REQ_SEEK_POS = pos;
911 m.REQ_NBYTES = bytes;
913 /* Send/rec request */
914 return fs_sendrec(fs_e, &m);
917 /*===========================================================================*
918 * req_rename *
919 *===========================================================================*/
920 int req_rename(fs_e, old_dir, old_name, new_dir, new_name)
921 endpoint_t fs_e;
922 ino_t old_dir;
923 char *old_name;
924 ino_t new_dir;
925 char *new_name;
927 int r;
928 cp_grant_id_t gid_old, gid_new;
929 size_t len_old, len_new;
930 message m;
932 len_old = strlen(old_name) + 1;
933 gid_old = cpf_grant_direct(fs_e, (vir_bytes) old_name, len_old, CPF_READ);
934 if(gid_old == -1)
935 panic("req_rename: cpf_grant_direct failed");
937 len_new = strlen(new_name) + 1;
938 gid_new = cpf_grant_direct(fs_e, (vir_bytes) new_name, len_new, CPF_READ);
939 if(gid_new == -1)
940 panic("req_rename: cpf_grant_direct failed");
942 /* Fill in request message */
943 m.m_type = REQ_RENAME;
944 m.REQ_REN_OLD_DIR = (pino_t) old_dir;
945 m.REQ_REN_NEW_DIR = (pino_t) new_dir;
946 m.REQ_REN_GRANT_OLD = gid_old;
947 m.REQ_REN_LEN_OLD = len_old;
948 m.REQ_REN_GRANT_NEW = gid_new;
949 m.REQ_REN_LEN_NEW = len_new;
951 /* Send/rec request */
952 r = fs_sendrec(fs_e, &m);
953 cpf_revoke(gid_old);
954 cpf_revoke(gid_new);
956 return(r);
960 /*===========================================================================*
961 * req_rmdir *
962 *===========================================================================*/
963 int req_rmdir(fs_e, inode_nr, lastc)
964 endpoint_t fs_e;
965 ino_t inode_nr;
966 char *lastc;
968 int r;
969 cp_grant_id_t grant_id;
970 size_t len;
971 message m;
973 len = strlen(lastc) + 1;
974 grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
975 if(grant_id == -1)
976 panic("req_rmdir: cpf_grant_direct failed");
978 /* Fill in request message */
979 m.m_type = REQ_RMDIR;
980 m.REQ_INODE_NR = (pino_t) inode_nr;
981 m.REQ_GRANT = grant_id;
982 m.REQ_PATH_LEN = len;
984 /* Send/rec request */
985 r = fs_sendrec(fs_e, &m);
986 cpf_revoke(grant_id);
988 return(r);
992 /*===========================================================================*
993 * req_slink_actual *
994 *===========================================================================*/
995 static int req_slink_actual(
996 endpoint_t fs_e,
997 ino_t inode_nr,
998 char *lastc,
999 endpoint_t proc_e,
1000 vir_bytes path_addr,
1001 size_t path_length,
1002 uid_t uid,
1003 gid_t gid,
1004 int cpflag
1007 int r;
1008 size_t len;
1009 cp_grant_id_t gid_name, gid_buf;
1010 message m;
1012 len = strlen(lastc) + 1;
1013 gid_name = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
1014 if (gid_name == GRANT_INVALID)
1015 panic("req_slink: cpf_grant_direct failed");
1017 gid_buf = cpf_grant_magic(fs_e, proc_e, path_addr, path_length,
1018 CPF_READ | cpflag);
1020 if (gid_buf == GRANT_INVALID) {
1021 cpf_revoke(gid_name);
1022 panic("req_slink: cpf_grant_magic failed");
1025 /* Fill in request message */
1026 m.m_type = REQ_SLINK;
1027 m.REQ_INODE_NR = (pino_t) inode_nr;
1028 m.REQ_UID = (puid_t) uid;
1029 m.REQ_GID = (pgid_t) gid;
1030 m.REQ_GRANT = gid_name;
1031 m.REQ_PATH_LEN = len;
1032 m.REQ_GRANT3 = gid_buf;
1033 m.REQ_MEM_SIZE = path_length;
1035 /* Send/rec request */
1036 r = fs_sendrec(fs_e, &m);
1037 cpf_revoke(gid_name);
1038 cpf_revoke(gid_buf);
1040 return(r);
1043 /*===========================================================================*
1044 * req_slink *
1045 *===========================================================================*/
1046 int req_slink(
1047 endpoint_t fs_e,
1048 ino_t inode_nr,
1049 char *lastc,
1050 endpoint_t proc_e,
1051 vir_bytes path_addr,
1052 size_t path_length,
1053 uid_t uid,
1054 gid_t gid
1057 int r;
1059 r = req_slink_actual(fs_e, inode_nr, lastc, proc_e, path_addr,
1060 path_length, uid, gid, CPF_TRY);
1062 if(r == EFAULT) {
1063 if((r=vm_vfs_procctl_handlemem(proc_e, (vir_bytes) path_addr,
1064 path_length, 0)) != OK) {
1065 return r;
1068 r = req_slink_actual(fs_e, inode_nr, lastc, proc_e, path_addr,
1069 path_length, uid, gid, 0);
1072 return r;
1075 /*===========================================================================*
1076 * req_stat_actual *
1077 *===========================================================================*/
1078 int req_stat_actual(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e,
1079 vir_bytes buf, int cpflag)
1081 cp_grant_id_t grant_id;
1082 int r;
1083 message m;
1085 /* Grant FS access to copy straight into user provided buffer */
1086 grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct stat),
1087 CPF_WRITE | cpflag);
1089 if (grant_id < 0)
1090 panic("req_stat: cpf_grant_* failed");
1092 /* Fill in request message */
1093 m.m_type = REQ_STAT;
1094 m.REQ_INODE_NR = (pino_t) inode_nr;
1095 m.REQ_GRANT = grant_id;
1097 /* Send/rec request */
1098 r = fs_sendrec(fs_e, &m);
1099 cpf_revoke(grant_id);
1101 return(r);
1105 /*===========================================================================*
1106 * req_stat *
1107 *===========================================================================*/
1108 int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e,
1109 vir_bytes buf)
1111 int r;
1113 r = req_stat_actual(fs_e, inode_nr, proc_e, buf, CPF_TRY);
1115 if(r == EFAULT) {
1116 if((r=vm_vfs_procctl_handlemem(proc_e, (vir_bytes) buf,
1117 sizeof(struct stat), 1)) != OK) {
1118 return r;
1121 r = req_stat_actual(fs_e, inode_nr, proc_e, buf, 0);
1124 return r;
1127 /*===========================================================================*
1128 * req_sync *
1129 *===========================================================================*/
1130 int req_sync(fs_e)
1131 endpoint_t fs_e;
1133 message m;
1135 /* Fill in request message */
1136 m.m_type = REQ_SYNC;
1138 /* Send/rec request */
1139 return fs_sendrec(fs_e, &m);
1143 /*===========================================================================*
1144 * req_unlink *
1145 *===========================================================================*/
1146 int req_unlink(fs_e, inode_nr, lastc)
1147 endpoint_t fs_e;
1148 ino_t inode_nr;
1149 char *lastc;
1151 cp_grant_id_t grant_id;
1152 size_t len;
1153 int r;
1154 message m;
1156 len = strlen(lastc) + 1;
1157 grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
1158 if(grant_id == -1)
1159 panic("req_unlink: cpf_grant_direct failed");
1161 /* Fill in request message */
1162 m.m_type = REQ_UNLINK;
1163 m.REQ_INODE_NR = (pino_t) inode_nr;
1164 m.REQ_GRANT = grant_id;
1165 m.REQ_PATH_LEN = len;
1167 /* Send/rec request */
1168 r = fs_sendrec(fs_e, &m);
1169 cpf_revoke(grant_id);
1171 return(r);
1175 /*===========================================================================*
1176 * req_unmount *
1177 *===========================================================================*/
1178 int req_unmount(fs_e)
1179 endpoint_t fs_e;
1181 message m;
1183 /* Fill in request message */
1184 m.m_type = REQ_UNMOUNT;
1186 /* Send/rec request */
1187 return fs_sendrec(fs_e, &m);
1191 /*===========================================================================*
1192 * req_utime *
1193 *===========================================================================*/
1194 int req_utime(endpoint_t fs_e, ino_t inode_nr, struct timespec * actimespec,
1195 struct timespec * modtimespec)
1197 message m;
1199 assert(actimespec != NULL);
1200 assert(modtimespec != NULL);
1202 /* Fill in request message */
1203 m.m_type = REQ_UTIME;
1204 m.REQ_INODE_NR = (pino_t) inode_nr;
1205 m.REQ_INODE_NR = inode_nr;
1206 m.REQ_ACTIME = actimespec->tv_sec;
1207 m.REQ_MODTIME = modtimespec->tv_sec;
1208 m.REQ_ACNSEC = actimespec->tv_nsec;
1209 m.REQ_MODNSEC = modtimespec->tv_nsec;
1211 /* Send/rec request */
1212 return fs_sendrec(fs_e, &m);