xref: /minix/minix/servers/vfs/request.c (revision fb9c64b2)
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  */
7 
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"
25 
26 
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, size_t *cum_iop, int cpflag)
33 {
34   int r;
35   cp_grant_id_t grant_id;
36   message m;
37 
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");
42 
43   /* Fill in request message */
44   m.m_type = rw_flag == READING ? REQ_BREAD : REQ_BWRITE;
45   m.m_vfs_fs_breadwrite.device = dev;
46   m.m_vfs_fs_breadwrite.grant = grant_id;
47   m.m_vfs_fs_breadwrite.seek_pos = pos;
48   m.m_vfs_fs_breadwrite.nbytes = num_of_bytes;
49 
50   /* Send/rec request */
51   r = fs_sendrec(fs_e, &m);
52 
53   if (cpf_revoke(grant_id) == GRANT_FAULTED) return(ERESTART);
54 
55   if (r != OK) return(r);
56 
57   /* Fill in response structure */
58   *new_pos = m.m_fs_vfs_breadwrite.seek_pos;
59   *cum_iop = m.m_fs_vfs_breadwrite.nbytes;
60 
61   return(OK);
62 }
63 
64 int req_breadwrite(endpoint_t fs_e, endpoint_t user_e, dev_t dev, off_t pos,
65         unsigned int num_of_bytes, vir_bytes user_addr, int rw_flag,
66         off_t *new_pos, size_t *cum_iop)
67 {
68 	int r;
69 
70 	r = req_breadwrite_actual(fs_e, user_e, dev, pos, num_of_bytes,
71 		user_addr, rw_flag, new_pos, cum_iop, CPF_TRY);
72 
73 	if (r == ERESTART) {
74 		if((r=vm_vfs_procctl_handlemem(user_e, user_addr, num_of_bytes,
75 			rw_flag == READING)) != OK) {
76 			return r;
77 		}
78 
79 		r = req_breadwrite_actual(fs_e, user_e, dev, pos, num_of_bytes,
80 			user_addr, rw_flag, new_pos, cum_iop, 0);
81 	}
82 
83 	return r;
84 }
85 
86 /*===========================================================================*
87  *			req_bpeek					     *
88  *===========================================================================*/
89 int req_bpeek(endpoint_t fs_e, dev_t dev, off_t pos, unsigned int num_of_bytes)
90 {
91   message m;
92 
93   memset(&m, 0, sizeof(m));
94 
95   /* Fill in request message */
96   m.m_type = REQ_BPEEK;
97   m.m_vfs_fs_breadwrite.device = dev;
98   m.m_vfs_fs_breadwrite.seek_pos = pos;
99   m.m_vfs_fs_breadwrite.nbytes = num_of_bytes;
100 
101   /* Send/rec request */
102   return fs_sendrec(fs_e, &m);
103 }
104 
105 /*===========================================================================*
106  *				req_chmod	      			     *
107  *===========================================================================*/
108 int req_chmod(
109   endpoint_t fs_e,
110   ino_t inode_nr,
111   mode_t rmode,
112   mode_t *new_modep
113 )
114 {
115   message m;
116   int r;
117 
118   /* Fill in request message */
119   m.m_type = REQ_CHMOD;
120   m.m_vfs_fs_chmod.inode = inode_nr;
121   m.m_vfs_fs_chmod.mode = rmode;
122 
123   /* Send/rec request */
124   r = fs_sendrec(fs_e, &m);
125 
126   /* Copy back actual mode. */
127   *new_modep = m.m_fs_vfs_chmod.mode;
128 
129   return(r);
130 }
131 
132 
133 /*===========================================================================*
134  *				req_chown          			     *
135  *===========================================================================*/
136 int req_chown(
137   endpoint_t fs_e,
138   ino_t inode_nr,
139   uid_t newuid,
140   gid_t newgid,
141   mode_t *new_modep
142 )
143 {
144   message m;
145   int r;
146 
147   /* Fill in request message */
148   m.m_type = REQ_CHOWN;
149   m.m_vfs_fs_chown.inode = inode_nr;
150   m.m_vfs_fs_chown.uid = newuid;
151   m.m_vfs_fs_chown.gid = newgid;
152 
153   /* Send/rec request */
154   r = fs_sendrec(fs_e, &m);
155 
156   /* Return new mode to caller. */
157   *new_modep = m.m_fs_vfs_chown.mode;
158 
159   return(r);
160 }
161 
162 
163 /*===========================================================================*
164  *				req_create				     *
165  *===========================================================================*/
166 int req_create(
167   endpoint_t fs_e,
168   ino_t inode_nr,
169   int omode,
170   uid_t uid,
171   gid_t gid,
172   char *path,
173   node_details_t *res
174 )
175 {
176   int r;
177   cp_grant_id_t grant_id;
178   size_t len;
179   message m;
180 //  struct vmnt *vmp;
181 
182 //  vmp = find_vmnt(fs_e);
183 
184   len = strlen(path) + 1;
185   grant_id = cpf_grant_direct(fs_e, (vir_bytes) path, len, CPF_READ);
186   if (grant_id == -1)
187 	panic("req_create: cpf_grant_direct failed");
188 
189   /* Fill in request message */
190   m.m_type = REQ_CREATE;
191   m.m_vfs_fs_create.inode = inode_nr;
192   m.m_vfs_fs_create.mode = omode;
193   m.m_vfs_fs_create.uid = uid;
194   m.m_vfs_fs_create.gid = gid;
195   m.m_vfs_fs_create.grant = grant_id;
196   m.m_vfs_fs_create.path_len = len;
197 
198   /* Send/rec request */
199   r = fs_sendrec(fs_e, &m);
200   cpf_revoke(grant_id);
201   if (r != OK) return(r);
202 
203   /* Fill in response structure */
204   res->fs_e	= m.m_source;
205   res->inode_nr	= m.m_fs_vfs_create.inode;
206   res->fmode	= m.m_fs_vfs_create.mode;
207   res->fsize    = m.m_fs_vfs_create.file_size;
208   res->uid	= m.m_fs_vfs_create.uid;
209   res->gid	= m.m_fs_vfs_create.gid;
210   res->dev	= NO_DEV;
211 
212   return(OK);
213 }
214 
215 
216 /*===========================================================================*
217  *				req_flush	      			     *
218  *===========================================================================*/
219 int req_flush(endpoint_t fs_e, dev_t dev)
220 {
221   message m;
222 
223   /* Fill in request message */
224   m.m_type = REQ_FLUSH;
225   m.m_vfs_fs_flush.device = dev;
226 
227   /* Send/rec request */
228   return fs_sendrec(fs_e, &m);
229 }
230 
231 
232 /*===========================================================================*
233  *				req_statvfs	    			     *
234  *===========================================================================*/
235 int req_statvfs(endpoint_t fs_e, struct statvfs *buf)
236 {
237   int r;
238   cp_grant_id_t grant_id;
239   message m;
240 
241   grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, sizeof(struct statvfs),
242 			CPF_WRITE);
243   if(grant_id == GRANT_INVALID)
244 	panic("req_statvfs: cpf_grant_direct failed");
245 
246   /* Fill in request message */
247   m.m_type = REQ_STATVFS;
248   m.m_vfs_fs_statvfs.grant = grant_id;
249 
250   /* Send/rec request */
251   r = fs_sendrec(fs_e, &m);
252   cpf_revoke(grant_id);
253 
254   return(r);
255 }
256 
257 
258 /*===========================================================================*
259  *				req_ftrunc	     			     *
260  *===========================================================================*/
261 int req_ftrunc(endpoint_t fs_e, ino_t inode_nr, off_t start, off_t end)
262 {
263   message m;
264   struct vmnt *vmp;
265 
266   vmp = find_vmnt(fs_e);
267 
268   /* Fill in request message */
269   m.m_type = REQ_FTRUNC;
270   m.m_vfs_fs_ftrunc.inode = inode_nr;
271   m.m_vfs_fs_ftrunc.trc_start = start;
272   m.m_vfs_fs_ftrunc.trc_end = end;
273 
274   if (!(vmp->m_fs_flags & RES_64BIT) &&
275 	((start > INT_MAX) || (end > INT_MAX))) {
276 	/* FS does not support 64-bit off_t and 32 bits is not enough */
277 	return EINVAL;
278   }
279 
280   /* Send/rec request */
281   return fs_sendrec(fs_e, &m);
282 }
283 
284 
285 /*===========================================================================*
286  *				req_getdents_actual    			     *
287  *===========================================================================*/
288 static int req_getdents_actual(
289   endpoint_t fs_e,
290   ino_t inode_nr,
291   off_t pos,
292   vir_bytes buf,
293   size_t size,
294   off_t *new_pos,
295   int direct,
296   int cpflag
297 )
298 {
299   int r;
300   message m;
301   cp_grant_id_t grant_id;
302   struct vmnt *vmp;
303 
304   vmp = find_vmnt(fs_e);
305   assert(vmp != NULL);
306 
307   if (direct) {
308 	grant_id = cpf_grant_direct(fs_e, buf, size, CPF_WRITE);
309   } else {
310 	grant_id = cpf_grant_magic(fs_e, who_e, buf, size,
311 				   CPF_WRITE | cpflag);
312   }
313 
314   if (grant_id < 0)
315 	panic("req_getdents: cpf_grant_direct/cpf_grant_magic failed: %d",
316 								grant_id);
317 
318   m.m_type = REQ_GETDENTS;
319   m.m_vfs_fs_getdents.inode = inode_nr;
320   m.m_vfs_fs_getdents.grant = grant_id;
321   m.m_vfs_fs_getdents.mem_size = size;
322   m.m_vfs_fs_getdents.seek_pos = pos;
323   if (!(vmp->m_fs_flags & RES_64BIT) && (pos > INT_MAX)) {
324 	/* FS does not support 64-bit off_t and 32 bits is not enough */
325 	return EINVAL;
326   }
327 
328   r = fs_sendrec(fs_e, &m);
329 
330   if (cpf_revoke(grant_id) == GRANT_FAULTED) return(ERESTART);
331 
332   if (r == OK) {
333 	*new_pos = m.m_fs_vfs_getdents.seek_pos;
334 	r = m.m_fs_vfs_getdents.nbytes;
335   }
336 
337   return(r);
338 }
339 
340 /*===========================================================================*
341  *				req_getdents	     			     *
342  *===========================================================================*/
343 int req_getdents(
344   endpoint_t fs_e,
345   ino_t inode_nr,
346   off_t pos,
347   vir_bytes buf,
348   size_t size,
349   off_t *new_pos,
350   int direct)
351 {
352 	int r;
353 
354 	r = req_getdents_actual(fs_e, inode_nr, pos, buf, size, new_pos,
355 		direct, CPF_TRY);
356 
357 	if (r == ERESTART) {
358 		assert(!direct);
359 
360 		if((r=vm_vfs_procctl_handlemem(who_e, buf, size, 1)) != OK) {
361 			return r;
362 		}
363 
364 		r = req_getdents_actual(fs_e, inode_nr, pos, buf, size,
365 			new_pos, direct, 0);
366 	}
367 
368 	return r;
369 }
370 
371 /*===========================================================================*
372  *				req_inhibread	  			     *
373  *===========================================================================*/
374 int req_inhibread(endpoint_t fs_e, ino_t inode_nr)
375 {
376   message m;
377 
378   /* Fill in request message */
379   m.m_type = REQ_INHIBREAD;
380   m.m_vfs_fs_inhibread.inode = inode_nr;
381 
382   /* Send/rec request */
383   return fs_sendrec(fs_e, &m);
384 }
385 
386 
387 /*===========================================================================*
388  *				req_link	       			     *
389  *===========================================================================*/
390 int req_link(
391   endpoint_t fs_e,
392   ino_t link_parent,
393   char *lastc,
394   ino_t linked_file
395 )
396 {
397   int r;
398   cp_grant_id_t grant_id;
399   const size_t len = strlen(lastc) + 1;
400   message m;
401 
402   grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
403   if(grant_id == -1)
404 	  panic("req_link: cpf_grant_direct failed");
405 
406   /* Fill in request message */
407   m.m_type = REQ_LINK;
408   m.m_vfs_fs_link.inode = linked_file;
409   m.m_vfs_fs_link.dir_ino = link_parent;
410   m.m_vfs_fs_link.grant = grant_id;
411   m.m_vfs_fs_link.path_len = len;
412 
413   /* Send/rec request */
414   r = fs_sendrec(fs_e, &m);
415   cpf_revoke(grant_id);
416 
417   return(r);
418 }
419 
420 
421 /*===========================================================================*
422  *				req_lookup	                   	     *
423  *===========================================================================*/
424 int req_lookup(
425   endpoint_t fs_e,
426   ino_t dir_ino,
427   ino_t root_ino,
428   uid_t uid,
429   gid_t gid,
430   struct lookup *resolve,
431   lookup_res_t *res,
432   struct fproc *rfp
433 )
434 {
435   message m;
436   vfs_ucred_t credentials;
437   int r, flags;
438   size_t len;
439 //  struct vmnt *vmp;
440   cp_grant_id_t grant_id=0, grant_id2=0;
441 
442 //  vmp = find_vmnt(fs_e);
443 
444   grant_id = cpf_grant_direct(fs_e, (vir_bytes) resolve->l_path, PATH_MAX,
445 			      CPF_READ | CPF_WRITE);
446   if(grant_id == -1)
447 	  panic("req_lookup: cpf_grant_direct failed");
448 
449   flags = resolve->l_flags;
450   len = strlen(resolve->l_path) + 1;
451 
452   m.m_type			= REQ_LOOKUP;
453   m.m_vfs_fs_lookup.grant_path	= grant_id;
454   m.m_vfs_fs_lookup.path_len 	= len;
455   m.m_vfs_fs_lookup.path_size 	= PATH_MAX + 1;
456   m.m_vfs_fs_lookup.dir_ino 	= dir_ino;
457   m.m_vfs_fs_lookup.root_ino 	= root_ino;
458 
459   if(rfp->fp_ngroups > 0) { /* Is the process member of multiple groups? */
460 	/* In that case the FS has to copy the uid/gid credentials */
461 	int i;
462 
463 	/* Set credentials */
464 	credentials.vu_uid = rfp->fp_effuid;
465 	credentials.vu_gid = rfp->fp_effgid;
466 	credentials.vu_ngroups = rfp->fp_ngroups;
467 	for (i = 0; i < rfp->fp_ngroups; i++)
468 		credentials.vu_sgroups[i] = rfp->fp_sgroups[i];
469 
470 	grant_id2 = cpf_grant_direct(fs_e, (vir_bytes) &credentials,
471 				     sizeof(credentials), CPF_READ);
472 	if(grant_id2 == -1)
473 		panic("req_lookup: cpf_grant_direct failed");
474 
475 	m.m_vfs_fs_lookup.grant_ucred	= grant_id2;
476 	m.m_vfs_fs_lookup.ucred_size	= sizeof(credentials);
477 	flags		|= PATH_GET_UCRED;
478   } else {
479 	/* When there's only one gid, we can send it directly */
480 	m.m_vfs_fs_lookup.uid = uid;
481 	m.m_vfs_fs_lookup.gid = gid;
482 	flags		&= ~PATH_GET_UCRED;
483   }
484 
485   m.m_vfs_fs_lookup.flags = flags;
486 
487   /* Send/rec request */
488   r = fs_sendrec(fs_e, &m);
489   cpf_revoke(grant_id);
490   if(rfp->fp_ngroups > 0) cpf_revoke(grant_id2);
491 
492   /* Fill in response according to the return value */
493   res->fs_e = m.m_source;
494 
495   switch (r) {
496   case OK:
497 	res->inode_nr = m.m_fs_vfs_lookup.inode;
498 	res->fmode = m.m_fs_vfs_lookup.mode;
499 	res->fsize = m.m_fs_vfs_lookup.file_size;
500 	res->dev = m.m_fs_vfs_lookup.device;
501 	res->uid = m.m_fs_vfs_lookup.uid;
502 	res->gid = m.m_fs_vfs_lookup.gid;
503 	break;
504   case EENTERMOUNT:
505 	res->inode_nr = m.m_fs_vfs_lookup.inode;
506 	res->char_processed = m.m_fs_vfs_lookup.offset;
507 	res->symloop = m.m_fs_vfs_lookup.symloop;
508 	break;
509   case ELEAVEMOUNT:
510 	res->char_processed = m.m_fs_vfs_lookup.offset;
511 	res->symloop = m.m_fs_vfs_lookup.symloop;
512 	break;
513   case ESYMLINK:
514 	res->char_processed = m.m_fs_vfs_lookup.offset;
515 	res->symloop = m.m_fs_vfs_lookup.symloop;
516 	break;
517   default:
518 	break;
519   }
520 
521   return(r);
522 }
523 
524 
525 /*===========================================================================*
526  *				req_mkdir	      			     *
527  *===========================================================================*/
528 int req_mkdir(
529   endpoint_t fs_e,
530   ino_t inode_nr,
531   char *lastc,
532   uid_t uid,
533   gid_t gid,
534   mode_t dmode
535 )
536 {
537   int r;
538   cp_grant_id_t grant_id;
539   size_t len;
540   message m;
541 
542   len = strlen(lastc) + 1;
543   grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
544   if(grant_id == -1)
545 	  panic("req_mkdir: cpf_grant_direct failed");
546 
547   /* Fill in request message */
548   m.m_type = REQ_MKDIR;
549   m.m_vfs_fs_mkdir.inode = inode_nr;
550   m.m_vfs_fs_mkdir.mode = dmode;
551   m.m_vfs_fs_mkdir.uid = uid;
552   m.m_vfs_fs_mkdir.gid = gid;
553   m.m_vfs_fs_mkdir.grant = grant_id;
554   m.m_vfs_fs_mkdir.path_len = len;
555 
556   /* Send/rec request */
557   r = fs_sendrec(fs_e, &m);
558   cpf_revoke(grant_id);
559 
560   return(r);
561 }
562 
563 
564 /*===========================================================================*
565  *				req_mknod	      			     *
566  *===========================================================================*/
567 int req_mknod(
568   endpoint_t fs_e,
569   ino_t inode_nr,
570   char *lastc,
571   uid_t uid,
572   gid_t gid,
573   mode_t dmode,
574   dev_t dev
575 )
576 {
577   int r;
578   size_t len;
579   cp_grant_id_t grant_id;
580   message m;
581 
582   len = strlen(lastc) + 1;
583   grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
584   if(grant_id == -1)
585 	  panic("req_mknod: cpf_grant_direct failed");
586 
587   /* Fill in request message */
588   m.m_type = REQ_MKNOD;
589   m.m_vfs_fs_mknod.inode = inode_nr;
590   m.m_vfs_fs_mknod.mode = dmode;
591   m.m_vfs_fs_mknod.device = dev;
592   m.m_vfs_fs_mknod.uid = uid;
593   m.m_vfs_fs_mknod.gid = gid;
594   m.m_vfs_fs_mknod.grant = grant_id;
595   m.m_vfs_fs_mknod.path_len = len;
596 
597   /* Send/rec request */
598   r = fs_sendrec(fs_e, &m);
599   cpf_revoke(grant_id);
600 
601   return(r);
602 }
603 
604 
605 /*===========================================================================*
606  *				req_mountpoint	                 	     *
607  *===========================================================================*/
608 int req_mountpoint(endpoint_t fs_e, ino_t inode_nr)
609 {
610   message m;
611 
612   /* Fill in request message */
613   m.m_type = REQ_MOUNTPOINT;
614   m.m_vfs_fs_mountpoint.inode = inode_nr;
615 
616   /* Send/rec request */
617   return fs_sendrec(fs_e, &m);
618 }
619 
620 
621 /*===========================================================================*
622  *				req_newnode	      			     *
623  *===========================================================================*/
624 int req_newnode(
625   endpoint_t fs_e,
626   uid_t uid,
627   gid_t gid,
628   mode_t dmode,
629   dev_t dev,
630   struct node_details *res
631 )
632 {
633 //  struct vmnt *vmp;
634   int r;
635   message m;
636 
637 //  vmp = find_vmnt(fs_e);
638 
639   /* Fill in request message */
640   m.m_type = REQ_NEWNODE;
641   m.m_vfs_fs_newnode.mode = dmode;
642   m.m_vfs_fs_newnode.device = dev;
643   m.m_vfs_fs_newnode.uid = uid;
644   m.m_vfs_fs_newnode.gid = gid;
645 
646   /* Send/rec request */
647   r = fs_sendrec(fs_e, &m);
648 
649   res->fs_e	= m.m_source;
650   res->inode_nr = m.m_fs_vfs_newnode.inode;
651   res->fmode	= m.m_fs_vfs_newnode.mode;
652   res->fsize    = m.m_fs_vfs_newnode.file_size;
653   res->dev	= m.m_fs_vfs_newnode.device;
654   res->uid	= m.m_fs_vfs_newnode.uid;
655   res->gid	= m.m_fs_vfs_newnode.gid;
656 
657   return(r);
658 }
659 
660 
661 /*===========================================================================*
662  *				req_newdriver          			     *
663  *===========================================================================*/
664 int req_newdriver(
665   endpoint_t fs_e,
666   dev_t dev,
667   char *label
668 )
669 {
670   cp_grant_id_t grant_id;
671   size_t len;
672   message m;
673   int r;
674 
675   /* Grant access to label */
676   len = strlen(label) + 1;
677   grant_id = cpf_grant_direct(fs_e, (vir_bytes) label, len, CPF_READ);
678   if (grant_id == -1)
679 	panic("req_newdriver: cpf_grant_direct failed");
680 
681   /* Fill in request message */
682   m.m_type = REQ_NEW_DRIVER;
683   m.m_vfs_fs_new_driver.device = dev;
684   m.m_vfs_fs_new_driver.grant = grant_id;
685   m.m_vfs_fs_new_driver.path_len = len;
686 
687   /* Issue request */
688   r = fs_sendrec(fs_e, &m);
689 
690   cpf_revoke(grant_id);
691 
692   return(r);
693 }
694 
695 
696 /*===========================================================================*
697  *				req_putnode				     *
698  *===========================================================================*/
699 int
700 req_putnode(int fs_e, ino_t inode_nr, int count)
701 {
702   message m;
703 
704   /* Fill in request message */
705   m.m_type = REQ_PUTNODE;
706   m.m_vfs_fs_putnode.inode = inode_nr;
707   m.m_vfs_fs_putnode.count = count;
708 
709   /* Send/rec request */
710   return fs_sendrec(fs_e, &m);
711 }
712 
713 
714 /*===========================================================================*
715  *				req_rdlink_actual     			     *
716  *===========================================================================*/
717 static int req_rdlink_actual(endpoint_t fs_e, ino_t inode_nr,
718 	endpoint_t proc_e, vir_bytes buf, size_t len,
719 	int direct, /* set to 1 to use direct grants instead of magic grants */
720 	int cpflag)
721 {
722   message m;
723   int r;
724   cp_grant_id_t grant_id;
725 
726   if (direct) {
727 	grant_id = cpf_grant_direct(fs_e, buf, len, CPF_WRITE);
728   } else {
729 	grant_id = cpf_grant_magic(fs_e, proc_e, buf, len, CPF_WRITE | cpflag);
730   }
731   if (grant_id == -1)
732 	  panic("req_rdlink: cpf_grant_magic failed");
733 
734   /* Fill in request message */
735   m.m_type = REQ_RDLINK;
736   m.m_vfs_fs_rdlink.inode = inode_nr;
737   m.m_vfs_fs_rdlink.grant = grant_id;
738   m.m_vfs_fs_rdlink.mem_size = len;
739 
740   /* Send/rec request */
741   r = fs_sendrec(fs_e, &m);
742 
743   if (cpf_revoke(grant_id) == GRANT_FAULTED) return(ERESTART);
744 
745   if (r == OK) r = m.m_fs_vfs_rdlink.nbytes;
746 
747   return(r);
748 }
749 
750 /*===========================================================================*
751  *				req_rdlink	     			     *
752  *===========================================================================*/
753 int req_rdlink(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e,
754 	vir_bytes buf, size_t len,
755 	int direct /* set to 1 to use direct grants instead of magic grants */
756 )
757 {
758 	int r;
759 
760 	r = req_rdlink_actual(fs_e, inode_nr, proc_e, buf, len, direct,
761 		CPF_TRY);
762 
763 	if (r == ERESTART) {
764 		assert(!direct);
765 
766 		if((r=vm_vfs_procctl_handlemem(proc_e, buf, len, 1)) != OK) {
767 			return r;
768 		}
769 
770 		r = req_rdlink_actual(fs_e, inode_nr, proc_e, buf, len,
771 			direct, 0);
772 	}
773 
774 	return r;
775 }
776 
777 /*===========================================================================*
778  *				req_readsuper	                  	     *
779  *===========================================================================*/
780 int req_readsuper(
781   struct vmnt *vmp,
782   char *label,
783   dev_t dev,
784   int readonly,
785   int isroot,
786   struct node_details *res,
787   unsigned int *fs_flags
788 )
789 {
790   int r;
791   cp_grant_id_t grant_id;
792   size_t len;
793   message m;
794   endpoint_t fs_e;
795 
796   fs_e = vmp->m_fs_e;
797 
798   len = strlen(label)+1;
799   grant_id = cpf_grant_direct(fs_e, (vir_bytes) label, len, CPF_READ);
800   if (grant_id == -1)
801 	  panic("req_readsuper: cpf_grant_direct failed");
802 
803   /* Fill in request message */
804   m.m_type = REQ_READSUPER;
805   m.m_vfs_fs_readsuper.flags = 0;
806   if(readonly) m.m_vfs_fs_readsuper.flags |= REQ_RDONLY;
807   if(isroot)   m.m_vfs_fs_readsuper.flags |= REQ_ISROOT;
808   m.m_vfs_fs_readsuper.grant = grant_id;
809   m.m_vfs_fs_readsuper.device = dev;
810   m.m_vfs_fs_readsuper.path_len = len;
811 
812   /* Send/rec request */
813   r = fs_sendrec(fs_e, &m);
814   cpf_revoke(grant_id);
815 
816   if(r == OK) {
817 	/* Fill in response structure */
818 	res->fs_e = m.m_source;
819 	res->inode_nr = m.m_fs_vfs_readsuper.inode;
820 	res->fmode = m.m_fs_vfs_readsuper.mode;
821 	res->fsize = m.m_fs_vfs_readsuper.file_size;
822 	res->uid = m.m_fs_vfs_readsuper.uid;
823 	res->gid = m.m_fs_vfs_readsuper.gid;
824 	*fs_flags = m.m_fs_vfs_readsuper.flags;
825   }
826 
827   return(r);
828 }
829 
830 
831 /*===========================================================================*
832  *				req_readwrite_actual			     *
833  *===========================================================================*/
834 static int req_readwrite_actual(endpoint_t fs_e, ino_t inode_nr, off_t pos,
835 	int rw_flag, endpoint_t user_e, vir_bytes user_addr,
836 	unsigned int num_of_bytes, off_t *new_posp, size_t *cum_iop,
837 	int cpflag)
838 {
839   struct vmnt *vmp;
840   int r;
841   cp_grant_id_t grant_id;
842   message m;
843 
844   vmp = find_vmnt(fs_e);
845 
846   grant_id = cpf_grant_magic(fs_e, user_e, user_addr, num_of_bytes,
847 			     (rw_flag==READING ? CPF_WRITE:CPF_READ) | cpflag);
848   if (grant_id == -1)
849 	  panic("req_readwrite: cpf_grant_magic failed");
850 
851   /* Fill in request message */
852   m.m_type = rw_flag == READING ? REQ_READ : REQ_WRITE;
853   m.m_vfs_fs_readwrite.inode = inode_nr;
854   m.m_vfs_fs_readwrite.grant = grant_id;
855   m.m_vfs_fs_readwrite.seek_pos = pos;
856   if ((!(vmp->m_fs_flags & RES_64BIT)) && (pos > INT_MAX)) {
857 	return EINVAL;
858   }
859   m.m_vfs_fs_readwrite.nbytes = num_of_bytes;
860 
861   /* Send/rec request */
862   r = fs_sendrec(fs_e, &m);
863 
864   if (cpf_revoke(grant_id) == GRANT_FAULTED) return(ERESTART);
865 
866   if (r == OK) {
867 	/* Fill in response structure */
868 	*new_posp = m.m_fs_vfs_readwrite.seek_pos;
869 	*cum_iop = m.m_fs_vfs_readwrite.nbytes;
870   }
871 
872   return(r);
873 }
874 
875 /*===========================================================================*
876  *				req_readwrite				     *
877  *===========================================================================*/
878 int req_readwrite(endpoint_t fs_e, ino_t inode_nr, off_t pos,
879 	int rw_flag, endpoint_t user_e, vir_bytes user_addr,
880 	unsigned int num_of_bytes, off_t *new_posp, size_t *cum_iop)
881 {
882 	int r;
883 
884 	r = req_readwrite_actual(fs_e, inode_nr, pos, rw_flag, user_e,
885 		user_addr, num_of_bytes, new_posp, cum_iop, CPF_TRY);
886 
887 	if (r == ERESTART) {
888 		if ((r=vm_vfs_procctl_handlemem(user_e, (vir_bytes) user_addr,
889 		    num_of_bytes, rw_flag == READING)) != OK) {
890 			return r;
891 		}
892 
893 		r = req_readwrite_actual(fs_e, inode_nr, pos, rw_flag, user_e,
894 			user_addr, num_of_bytes, new_posp, cum_iop, 0);
895 	}
896 
897 	return r;
898 }
899 
900 /*===========================================================================*
901  *				req_peek				     *
902  *===========================================================================*/
903 int req_peek(endpoint_t fs_e, ino_t inode_nr, off_t pos, unsigned int bytes)
904 {
905   message m;
906 
907   memset(&m, 0, sizeof(m));
908 
909   if (ex64hi(pos) != 0)
910 	  panic("req_peek: pos too large");
911 
912   /* Fill in request message */
913   m.m_type = REQ_PEEK;
914   m.m_vfs_fs_readwrite.inode = inode_nr;
915   m.m_vfs_fs_readwrite.grant = -1;
916   m.m_vfs_fs_readwrite.seek_pos = pos;
917   m.m_vfs_fs_readwrite.nbytes = bytes;
918 
919   /* Send/rec request */
920   return fs_sendrec(fs_e, &m);
921 }
922 
923 /*===========================================================================*
924  *				req_rename	     			     *
925  *===========================================================================*/
926 int
927 req_rename(endpoint_t fs_e, ino_t old_dir, char *old_name, ino_t new_dir, char *new_name)
928 {
929   int r;
930   cp_grant_id_t gid_old, gid_new;
931   size_t len_old, len_new;
932   message m;
933 
934   len_old = strlen(old_name) + 1;
935   gid_old = cpf_grant_direct(fs_e, (vir_bytes) old_name, len_old, CPF_READ);
936   if(gid_old == -1)
937 	  panic("req_rename: cpf_grant_direct failed");
938 
939   len_new = strlen(new_name) + 1;
940   gid_new = cpf_grant_direct(fs_e, (vir_bytes) new_name, len_new, CPF_READ);
941   if(gid_new == -1)
942 	  panic("req_rename: cpf_grant_direct failed");
943 
944   /* Fill in request message */
945   m.m_type = REQ_RENAME;
946   m.m_vfs_fs_rename.dir_old = old_dir;
947   m.m_vfs_fs_rename.grant_old = gid_old;
948   m.m_vfs_fs_rename.len_old = len_old;
949 
950   m.m_vfs_fs_rename.dir_new = new_dir;
951   m.m_vfs_fs_rename.grant_new = gid_new;
952   m.m_vfs_fs_rename.len_new = len_new;
953 
954   /* Send/rec request */
955   r = fs_sendrec(fs_e, &m);
956   cpf_revoke(gid_old);
957   cpf_revoke(gid_new);
958 
959   return(r);
960 }
961 
962 
963 /*===========================================================================*
964  *				req_rmdir	      			     *
965  *===========================================================================*/
966 int
967 req_rmdir(endpoint_t fs_e, ino_t inode_nr, char *lastc)
968 {
969   int r;
970   cp_grant_id_t grant_id;
971   size_t len;
972   message m;
973 
974   len = strlen(lastc) + 1;
975   grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
976   if(grant_id == -1)
977 	  panic("req_rmdir: cpf_grant_direct failed");
978 
979   /* Fill in request message */
980   m.m_type = REQ_RMDIR;
981   m.m_vfs_fs_unlink.inode = inode_nr;
982   m.m_vfs_fs_unlink.grant = grant_id;
983   m.m_vfs_fs_unlink.path_len = len;
984 
985   /* Send/rec request */
986   r = fs_sendrec(fs_e, &m);
987   cpf_revoke(grant_id);
988 
989   return(r);
990 }
991 
992 
993 /*===========================================================================*
994  *				req_slink_actual      			     *
995  *===========================================================================*/
996 static int req_slink_actual(
997   endpoint_t fs_e,
998   ino_t inode_nr,
999   char *lastc,
1000   endpoint_t proc_e,
1001   vir_bytes path_addr,
1002   size_t path_length,
1003   uid_t uid,
1004   gid_t gid,
1005   int cpflag
1006 )
1007 {
1008   int r;
1009   size_t len;
1010   cp_grant_id_t gid_name, gid_buf;
1011   message m;
1012 
1013   len = strlen(lastc) + 1;
1014   gid_name = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
1015   if (gid_name == GRANT_INVALID)
1016 	  panic("req_slink: cpf_grant_direct failed");
1017 
1018   gid_buf = cpf_grant_magic(fs_e, proc_e, path_addr, path_length,
1019 	CPF_READ | cpflag);
1020 
1021   if (gid_buf == GRANT_INVALID) {
1022 	  cpf_revoke(gid_name);
1023 	  panic("req_slink: cpf_grant_magic failed");
1024   }
1025 
1026   /* Fill in request message */
1027   m.m_type = REQ_SLINK;
1028   m.m_vfs_fs_slink.inode = inode_nr;
1029   m.m_vfs_fs_slink.uid = uid;
1030   m.m_vfs_fs_slink.gid = gid;
1031   m.m_vfs_fs_slink.grant_path = gid_name;
1032   m.m_vfs_fs_slink.path_len = len;
1033   m.m_vfs_fs_slink.grant_target = gid_buf;
1034   m.m_vfs_fs_slink.mem_size = path_length;
1035 
1036   /* Send/rec request */
1037   r = fs_sendrec(fs_e, &m);
1038 
1039   cpf_revoke(gid_name);
1040   if (cpf_revoke(gid_buf) == GRANT_FAULTED) return(ERESTART);
1041 
1042   return(r);
1043 }
1044 
1045 /*===========================================================================*
1046  *				req_slink	      			     *
1047  *===========================================================================*/
1048 int req_slink(
1049   endpoint_t fs_e,
1050   ino_t inode_nr,
1051   char *lastc,
1052   endpoint_t proc_e,
1053   vir_bytes path_addr,
1054   size_t path_length,
1055   uid_t uid,
1056   gid_t gid
1057 )
1058 {
1059 	int r;
1060 
1061 	r = req_slink_actual(fs_e, inode_nr, lastc, proc_e, path_addr,
1062 		path_length, uid, gid, CPF_TRY);
1063 
1064 	if (r == ERESTART) {
1065 		if((r=vm_vfs_procctl_handlemem(proc_e, (vir_bytes) path_addr,
1066 			path_length, 0)) != OK) {
1067 			return r;
1068 		}
1069 
1070 		r = req_slink_actual(fs_e, inode_nr, lastc, proc_e, path_addr,
1071 			path_length, uid, gid, 0);
1072 	}
1073 
1074 	return r;
1075 }
1076 
1077 /*===========================================================================*
1078  *				req_stat_actual	       			     *
1079  *===========================================================================*/
1080 int req_stat_actual(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e,
1081 	vir_bytes buf, int cpflag)
1082 {
1083   cp_grant_id_t grant_id;
1084   int r;
1085   message m;
1086 
1087   /* Grant FS access to copy straight into user provided buffer */
1088   grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct stat),
1089 	CPF_WRITE | cpflag);
1090 
1091   if (grant_id < 0)
1092 	panic("req_stat: cpf_grant_* failed");
1093 
1094   /* Fill in request message */
1095   m.m_type = REQ_STAT;
1096   m.m_vfs_fs_stat.inode = inode_nr;
1097   m.m_vfs_fs_stat.grant = grant_id;
1098 
1099   /* Send/rec request */
1100   r = fs_sendrec(fs_e, &m);
1101 
1102   if (cpf_revoke(grant_id) == GRANT_FAULTED) return(ERESTART);
1103 
1104   return(r);
1105 }
1106 
1107 
1108 /*===========================================================================*
1109  *				req_stat	       			     *
1110  *===========================================================================*/
1111 int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e,
1112 	vir_bytes buf)
1113 {
1114 	int r;
1115 
1116 	r = req_stat_actual(fs_e, inode_nr, proc_e, buf, CPF_TRY);
1117 
1118 	if (r == ERESTART) {
1119 		if((r=vm_vfs_procctl_handlemem(proc_e, (vir_bytes) buf,
1120 			sizeof(struct stat), 1)) != OK) {
1121 			return r;
1122 		}
1123 
1124 		r = req_stat_actual(fs_e, inode_nr, proc_e, buf, 0);
1125 	}
1126 
1127 	return r;
1128 }
1129 
1130 /*===========================================================================*
1131  *				req_sync	       			     *
1132  *===========================================================================*/
1133 int
1134 req_sync(endpoint_t fs_e)
1135 {
1136   message m;
1137 
1138   /* Fill in request message */
1139   m.m_type = REQ_SYNC;
1140 
1141   /* Send/rec request */
1142   return fs_sendrec(fs_e, &m);
1143 }
1144 
1145 
1146 /*===========================================================================*
1147  *				req_unlink	     			     *
1148  *===========================================================================*/
1149 int
1150 req_unlink(endpoint_t fs_e, ino_t inode_nr, char *lastc)
1151 {
1152   cp_grant_id_t grant_id;
1153   size_t len;
1154   int r;
1155   message m;
1156 
1157   len = strlen(lastc) + 1;
1158   grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
1159   if(grant_id == -1)
1160 	  panic("req_unlink: cpf_grant_direct failed");
1161 
1162   /* Fill in request message */
1163   m.m_type = REQ_UNLINK;
1164   m.m_vfs_fs_unlink.inode = inode_nr;
1165   m.m_vfs_fs_unlink.grant = grant_id;
1166   m.m_vfs_fs_unlink.path_len = len;
1167 
1168   /* Send/rec request */
1169   r = fs_sendrec(fs_e, &m);
1170   cpf_revoke(grant_id);
1171 
1172   return(r);
1173 }
1174 
1175 
1176 /*===========================================================================*
1177  *				req_unmount	    			     *
1178  *===========================================================================*/
1179 int
1180 req_unmount(endpoint_t fs_e)
1181 {
1182   message m;
1183 
1184   /* Fill in request message */
1185   m.m_type = REQ_UNMOUNT;
1186 
1187   /* Send/rec request */
1188   return fs_sendrec(fs_e, &m);
1189 }
1190 
1191 
1192 /*===========================================================================*
1193  *				req_utime	      			     *
1194  *===========================================================================*/
1195 int req_utime(endpoint_t fs_e, ino_t inode_nr, struct timespec * actimespec,
1196 	struct timespec * modtimespec)
1197 {
1198   message m;
1199 
1200   assert(actimespec != NULL);
1201   assert(modtimespec != NULL);
1202 
1203   /* Fill in request message */
1204   m.m_type = REQ_UTIME;
1205   m.m_vfs_fs_utime.inode = inode_nr;
1206   m.m_vfs_fs_utime.actime = actimespec->tv_sec;
1207   m.m_vfs_fs_utime.modtime = modtimespec->tv_sec;
1208   m.m_vfs_fs_utime.acnsec = actimespec->tv_nsec;
1209   m.m_vfs_fs_utime.modnsec = modtimespec->tv_nsec;
1210 
1211   /* Send/rec request */
1212   return fs_sendrec(fs_e, &m);
1213 }
1214