xref: /minix3/minix/servers/vfs/request.c (revision fb4fbf7a0cc5cace6da6a02afab2b621bb394c34)
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 req_putnode(fs_e, inode_nr, count)
700 int fs_e;
701 ino_t inode_nr;
702 int count;
703 {
704   message m;
705 
706   /* Fill in request message */
707   m.m_type = REQ_PUTNODE;
708   m.m_vfs_fs_putnode.inode = inode_nr;
709   m.m_vfs_fs_putnode.count = count;
710 
711   /* Send/rec request */
712   return fs_sendrec(fs_e, &m);
713 }
714 
715 
716 /*===========================================================================*
717  *				req_rdlink_actual     			     *
718  *===========================================================================*/
719 static int req_rdlink_actual(endpoint_t fs_e, ino_t inode_nr,
720 	endpoint_t proc_e, vir_bytes buf, size_t len,
721 	int direct, /* set to 1 to use direct grants instead of magic grants */
722 	int cpflag)
723 {
724   message m;
725   int r;
726   cp_grant_id_t grant_id;
727 
728   if (direct) {
729 	grant_id = cpf_grant_direct(fs_e, buf, len, CPF_WRITE);
730   } else {
731 	grant_id = cpf_grant_magic(fs_e, proc_e, buf, len, CPF_WRITE | cpflag);
732   }
733   if (grant_id == -1)
734 	  panic("req_rdlink: cpf_grant_magic failed");
735 
736   /* Fill in request message */
737   m.m_type = REQ_RDLINK;
738   m.m_vfs_fs_rdlink.inode = inode_nr;
739   m.m_vfs_fs_rdlink.grant = grant_id;
740   m.m_vfs_fs_rdlink.mem_size = len;
741 
742   /* Send/rec request */
743   r = fs_sendrec(fs_e, &m);
744 
745   if (cpf_revoke(grant_id) == GRANT_FAULTED) return(ERESTART);
746 
747   if (r == OK) r = m.m_fs_vfs_rdlink.nbytes;
748 
749   return(r);
750 }
751 
752 /*===========================================================================*
753  *				req_rdlink	     			     *
754  *===========================================================================*/
755 int req_rdlink(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e,
756 	vir_bytes buf, size_t len,
757 	int direct /* set to 1 to use direct grants instead of magic grants */
758 )
759 {
760 	int r;
761 
762 	r = req_rdlink_actual(fs_e, inode_nr, proc_e, buf, len, direct,
763 		CPF_TRY);
764 
765 	if (r == ERESTART) {
766 		assert(!direct);
767 
768 		if((r=vm_vfs_procctl_handlemem(proc_e, buf, len, 1)) != OK) {
769 			return r;
770 		}
771 
772 		r = req_rdlink_actual(fs_e, inode_nr, proc_e, buf, len,
773 			direct, 0);
774 	}
775 
776 	return r;
777 }
778 
779 /*===========================================================================*
780  *				req_readsuper	                  	     *
781  *===========================================================================*/
782 int req_readsuper(
783   struct vmnt *vmp,
784   char *label,
785   dev_t dev,
786   int readonly,
787   int isroot,
788   struct node_details *res,
789   unsigned int *fs_flags
790 )
791 {
792   int r;
793   cp_grant_id_t grant_id;
794   size_t len;
795   message m;
796   endpoint_t fs_e;
797 
798   fs_e = vmp->m_fs_e;
799 
800   len = strlen(label)+1;
801   grant_id = cpf_grant_direct(fs_e, (vir_bytes) label, len, CPF_READ);
802   if (grant_id == -1)
803 	  panic("req_readsuper: cpf_grant_direct failed");
804 
805   /* Fill in request message */
806   m.m_type = REQ_READSUPER;
807   m.m_vfs_fs_readsuper.flags = 0;
808   if(readonly) m.m_vfs_fs_readsuper.flags |= REQ_RDONLY;
809   if(isroot)   m.m_vfs_fs_readsuper.flags |= REQ_ISROOT;
810   m.m_vfs_fs_readsuper.grant = grant_id;
811   m.m_vfs_fs_readsuper.device = dev;
812   m.m_vfs_fs_readsuper.path_len = len;
813 
814   /* Send/rec request */
815   r = fs_sendrec(fs_e, &m);
816   cpf_revoke(grant_id);
817 
818   if(r == OK) {
819 	/* Fill in response structure */
820 	res->fs_e = m.m_source;
821 	res->inode_nr = m.m_fs_vfs_readsuper.inode;
822 	res->fmode = m.m_fs_vfs_readsuper.mode;
823 	res->fsize = m.m_fs_vfs_readsuper.file_size;
824 	res->uid = m.m_fs_vfs_readsuper.uid;
825 	res->gid = m.m_fs_vfs_readsuper.gid;
826 	*fs_flags = m.m_fs_vfs_readsuper.flags;
827   }
828 
829   return(r);
830 }
831 
832 
833 /*===========================================================================*
834  *				req_readwrite_actual			     *
835  *===========================================================================*/
836 static int req_readwrite_actual(endpoint_t fs_e, ino_t inode_nr, off_t pos,
837 	int rw_flag, endpoint_t user_e, vir_bytes user_addr,
838 	unsigned int num_of_bytes, off_t *new_posp, size_t *cum_iop,
839 	int cpflag)
840 {
841   struct vmnt *vmp;
842   int r;
843   cp_grant_id_t grant_id;
844   message m;
845 
846   vmp = find_vmnt(fs_e);
847 
848   grant_id = cpf_grant_magic(fs_e, user_e, user_addr, num_of_bytes,
849 			     (rw_flag==READING ? CPF_WRITE:CPF_READ) | cpflag);
850   if (grant_id == -1)
851 	  panic("req_readwrite: cpf_grant_magic failed");
852 
853   /* Fill in request message */
854   m.m_type = rw_flag == READING ? REQ_READ : REQ_WRITE;
855   m.m_vfs_fs_readwrite.inode = inode_nr;
856   m.m_vfs_fs_readwrite.grant = grant_id;
857   m.m_vfs_fs_readwrite.seek_pos = pos;
858   if ((!(vmp->m_fs_flags & RES_64BIT)) && (pos > INT_MAX)) {
859 	return EINVAL;
860   }
861   m.m_vfs_fs_readwrite.nbytes = num_of_bytes;
862 
863   /* Send/rec request */
864   r = fs_sendrec(fs_e, &m);
865 
866   if (cpf_revoke(grant_id) == GRANT_FAULTED) return(ERESTART);
867 
868   if (r == OK) {
869 	/* Fill in response structure */
870 	*new_posp = m.m_fs_vfs_readwrite.seek_pos;
871 	*cum_iop = m.m_fs_vfs_readwrite.nbytes;
872   }
873 
874   return(r);
875 }
876 
877 /*===========================================================================*
878  *				req_readwrite				     *
879  *===========================================================================*/
880 int req_readwrite(endpoint_t fs_e, ino_t inode_nr, off_t pos,
881 	int rw_flag, endpoint_t user_e, vir_bytes user_addr,
882 	unsigned int num_of_bytes, off_t *new_posp, size_t *cum_iop)
883 {
884 	int r;
885 
886 	r = req_readwrite_actual(fs_e, inode_nr, pos, rw_flag, user_e,
887 		user_addr, num_of_bytes, new_posp, cum_iop, CPF_TRY);
888 
889 	if (r == ERESTART) {
890 		if ((r=vm_vfs_procctl_handlemem(user_e, (vir_bytes) user_addr,
891 		    num_of_bytes, rw_flag == READING)) != OK) {
892 			return r;
893 		}
894 
895 		r = req_readwrite_actual(fs_e, inode_nr, pos, rw_flag, user_e,
896 			user_addr, num_of_bytes, new_posp, cum_iop, 0);
897 	}
898 
899 	return r;
900 }
901 
902 /*===========================================================================*
903  *				req_peek				     *
904  *===========================================================================*/
905 int req_peek(endpoint_t fs_e, ino_t inode_nr, off_t pos, unsigned int bytes)
906 {
907   message m;
908 
909   memset(&m, 0, sizeof(m));
910 
911   if (ex64hi(pos) != 0)
912 	  panic("req_peek: pos too large");
913 
914   /* Fill in request message */
915   m.m_type = REQ_PEEK;
916   m.m_vfs_fs_readwrite.inode = inode_nr;
917   m.m_vfs_fs_readwrite.grant = -1;
918   m.m_vfs_fs_readwrite.seek_pos = pos;
919   m.m_vfs_fs_readwrite.nbytes = bytes;
920 
921   /* Send/rec request */
922   return fs_sendrec(fs_e, &m);
923 }
924 
925 /*===========================================================================*
926  *				req_rename	     			     *
927  *===========================================================================*/
928 int req_rename(fs_e, old_dir, old_name, new_dir, new_name)
929 endpoint_t fs_e;
930 ino_t old_dir;
931 char *old_name;
932 ino_t new_dir;
933 char *new_name;
934 {
935   int r;
936   cp_grant_id_t gid_old, gid_new;
937   size_t len_old, len_new;
938   message m;
939 
940   len_old = strlen(old_name) + 1;
941   gid_old = cpf_grant_direct(fs_e, (vir_bytes) old_name, len_old, CPF_READ);
942   if(gid_old == -1)
943 	  panic("req_rename: cpf_grant_direct failed");
944 
945   len_new = strlen(new_name) + 1;
946   gid_new = cpf_grant_direct(fs_e, (vir_bytes) new_name, len_new, CPF_READ);
947   if(gid_new == -1)
948 	  panic("req_rename: cpf_grant_direct failed");
949 
950   /* Fill in request message */
951   m.m_type = REQ_RENAME;
952   m.m_vfs_fs_rename.dir_old = old_dir;
953   m.m_vfs_fs_rename.grant_old = gid_old;
954   m.m_vfs_fs_rename.len_old = len_old;
955 
956   m.m_vfs_fs_rename.dir_new = new_dir;
957   m.m_vfs_fs_rename.grant_new = gid_new;
958   m.m_vfs_fs_rename.len_new = len_new;
959 
960   /* Send/rec request */
961   r = fs_sendrec(fs_e, &m);
962   cpf_revoke(gid_old);
963   cpf_revoke(gid_new);
964 
965   return(r);
966 }
967 
968 
969 /*===========================================================================*
970  *				req_rmdir	      			     *
971  *===========================================================================*/
972 int req_rmdir(fs_e, inode_nr, lastc)
973 endpoint_t fs_e;
974 ino_t inode_nr;
975 char *lastc;
976 {
977   int r;
978   cp_grant_id_t grant_id;
979   size_t len;
980   message m;
981 
982   len = strlen(lastc) + 1;
983   grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
984   if(grant_id == -1)
985 	  panic("req_rmdir: cpf_grant_direct failed");
986 
987   /* Fill in request message */
988   m.m_type = REQ_RMDIR;
989   m.m_vfs_fs_unlink.inode = inode_nr;
990   m.m_vfs_fs_unlink.grant = grant_id;
991   m.m_vfs_fs_unlink.path_len = len;
992 
993   /* Send/rec request */
994   r = fs_sendrec(fs_e, &m);
995   cpf_revoke(grant_id);
996 
997   return(r);
998 }
999 
1000 
1001 /*===========================================================================*
1002  *				req_slink_actual      			     *
1003  *===========================================================================*/
1004 static int req_slink_actual(
1005   endpoint_t fs_e,
1006   ino_t inode_nr,
1007   char *lastc,
1008   endpoint_t proc_e,
1009   vir_bytes path_addr,
1010   size_t path_length,
1011   uid_t uid,
1012   gid_t gid,
1013   int cpflag
1014 )
1015 {
1016   int r;
1017   size_t len;
1018   cp_grant_id_t gid_name, gid_buf;
1019   message m;
1020 
1021   len = strlen(lastc) + 1;
1022   gid_name = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
1023   if (gid_name == GRANT_INVALID)
1024 	  panic("req_slink: cpf_grant_direct failed");
1025 
1026   gid_buf = cpf_grant_magic(fs_e, proc_e, path_addr, path_length,
1027 	CPF_READ | cpflag);
1028 
1029   if (gid_buf == GRANT_INVALID) {
1030 	  cpf_revoke(gid_name);
1031 	  panic("req_slink: cpf_grant_magic failed");
1032   }
1033 
1034   /* Fill in request message */
1035   m.m_type = REQ_SLINK;
1036   m.m_vfs_fs_slink.inode = inode_nr;
1037   m.m_vfs_fs_slink.uid = uid;
1038   m.m_vfs_fs_slink.gid = gid;
1039   m.m_vfs_fs_slink.grant_path = gid_name;
1040   m.m_vfs_fs_slink.path_len = len;
1041   m.m_vfs_fs_slink.grant_target = gid_buf;
1042   m.m_vfs_fs_slink.mem_size = path_length;
1043 
1044   /* Send/rec request */
1045   r = fs_sendrec(fs_e, &m);
1046 
1047   cpf_revoke(gid_name);
1048   if (cpf_revoke(gid_buf) == GRANT_FAULTED) return(ERESTART);
1049 
1050   return(r);
1051 }
1052 
1053 /*===========================================================================*
1054  *				req_slink	      			     *
1055  *===========================================================================*/
1056 int req_slink(
1057   endpoint_t fs_e,
1058   ino_t inode_nr,
1059   char *lastc,
1060   endpoint_t proc_e,
1061   vir_bytes path_addr,
1062   size_t path_length,
1063   uid_t uid,
1064   gid_t gid
1065 )
1066 {
1067 	int r;
1068 
1069 	r = req_slink_actual(fs_e, inode_nr, lastc, proc_e, path_addr,
1070 		path_length, uid, gid, CPF_TRY);
1071 
1072 	if (r == ERESTART) {
1073 		if((r=vm_vfs_procctl_handlemem(proc_e, (vir_bytes) path_addr,
1074 			path_length, 0)) != OK) {
1075 			return r;
1076 		}
1077 
1078 		r = req_slink_actual(fs_e, inode_nr, lastc, proc_e, path_addr,
1079 			path_length, uid, gid, 0);
1080 	}
1081 
1082 	return r;
1083 }
1084 
1085 /*===========================================================================*
1086  *				req_stat_actual	       			     *
1087  *===========================================================================*/
1088 int req_stat_actual(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e,
1089 	vir_bytes buf, int cpflag)
1090 {
1091   cp_grant_id_t grant_id;
1092   int r;
1093   message m;
1094 
1095   /* Grant FS access to copy straight into user provided buffer */
1096   grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct stat),
1097 	CPF_WRITE | cpflag);
1098 
1099   if (grant_id < 0)
1100 	panic("req_stat: cpf_grant_* failed");
1101 
1102   /* Fill in request message */
1103   m.m_type = REQ_STAT;
1104   m.m_vfs_fs_stat.inode = inode_nr;
1105   m.m_vfs_fs_stat.grant = grant_id;
1106 
1107   /* Send/rec request */
1108   r = fs_sendrec(fs_e, &m);
1109 
1110   if (cpf_revoke(grant_id) == GRANT_FAULTED) return(ERESTART);
1111 
1112   return(r);
1113 }
1114 
1115 
1116 /*===========================================================================*
1117  *				req_stat	       			     *
1118  *===========================================================================*/
1119 int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e,
1120 	vir_bytes buf)
1121 {
1122 	int r;
1123 
1124 	r = req_stat_actual(fs_e, inode_nr, proc_e, buf, CPF_TRY);
1125 
1126 	if (r == ERESTART) {
1127 		if((r=vm_vfs_procctl_handlemem(proc_e, (vir_bytes) buf,
1128 			sizeof(struct stat), 1)) != OK) {
1129 			return r;
1130 		}
1131 
1132 		r = req_stat_actual(fs_e, inode_nr, proc_e, buf, 0);
1133 	}
1134 
1135 	return r;
1136 }
1137 
1138 /*===========================================================================*
1139  *				req_sync	       			     *
1140  *===========================================================================*/
1141 int req_sync(fs_e)
1142 endpoint_t fs_e;
1143 {
1144   message m;
1145 
1146   /* Fill in request message */
1147   m.m_type = REQ_SYNC;
1148 
1149   /* Send/rec request */
1150   return fs_sendrec(fs_e, &m);
1151 }
1152 
1153 
1154 /*===========================================================================*
1155  *				req_unlink	     			     *
1156  *===========================================================================*/
1157 int req_unlink(fs_e, inode_nr, lastc)
1158 endpoint_t fs_e;
1159 ino_t inode_nr;
1160 char *lastc;
1161 {
1162   cp_grant_id_t grant_id;
1163   size_t len;
1164   int r;
1165   message m;
1166 
1167   len = strlen(lastc) + 1;
1168   grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
1169   if(grant_id == -1)
1170 	  panic("req_unlink: cpf_grant_direct failed");
1171 
1172   /* Fill in request message */
1173   m.m_type = REQ_UNLINK;
1174   m.m_vfs_fs_unlink.inode = inode_nr;
1175   m.m_vfs_fs_unlink.grant = grant_id;
1176   m.m_vfs_fs_unlink.path_len = len;
1177 
1178   /* Send/rec request */
1179   r = fs_sendrec(fs_e, &m);
1180   cpf_revoke(grant_id);
1181 
1182   return(r);
1183 }
1184 
1185 
1186 /*===========================================================================*
1187  *				req_unmount	    			     *
1188  *===========================================================================*/
1189 int req_unmount(fs_e)
1190 endpoint_t fs_e;
1191 {
1192   message m;
1193 
1194   /* Fill in request message */
1195   m.m_type = REQ_UNMOUNT;
1196 
1197   /* Send/rec request */
1198   return fs_sendrec(fs_e, &m);
1199 }
1200 
1201 
1202 /*===========================================================================*
1203  *				req_utime	      			     *
1204  *===========================================================================*/
1205 int req_utime(endpoint_t fs_e, ino_t inode_nr, struct timespec * actimespec,
1206 	struct timespec * modtimespec)
1207 {
1208   message m;
1209 
1210   assert(actimespec != NULL);
1211   assert(modtimespec != NULL);
1212 
1213   /* Fill in request message */
1214   m.m_type = REQ_UTIME;
1215   m.m_vfs_fs_utime.inode = inode_nr;
1216   m.m_vfs_fs_utime.actime = actimespec->tv_sec;
1217   m.m_vfs_fs_utime.modtime = modtimespec->tv_sec;
1218   m.m_vfs_fs_utime.acnsec = actimespec->tv_nsec;
1219   m.m_vfs_fs_utime.modnsec = modtimespec->tv_nsec;
1220 
1221   /* Send/rec request */
1222   return fs_sendrec(fs_e, &m);
1223 }
1224