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 *===========================================================================*/
req_breadwrite_actual(endpoint_t fs_e,endpoint_t user_e,dev_t dev,off_t pos,unsigned int num_of_bytes,vir_bytes user_addr,int rw_flag,off_t * new_pos,size_t * cum_iop,int cpflag)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
req_breadwrite(endpoint_t fs_e,endpoint_t user_e,dev_t dev,off_t pos,unsigned int num_of_bytes,vir_bytes user_addr,int rw_flag,off_t * new_pos,size_t * cum_iop)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 *===========================================================================*/
req_bpeek(endpoint_t fs_e,dev_t dev,off_t pos,unsigned int num_of_bytes)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 *===========================================================================*/
req_chmod(endpoint_t fs_e,ino_t inode_nr,mode_t rmode,mode_t * new_modep)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 *===========================================================================*/
req_chown(endpoint_t fs_e,ino_t inode_nr,uid_t newuid,gid_t newgid,mode_t * new_modep)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 *===========================================================================*/
req_create(endpoint_t fs_e,ino_t inode_nr,int omode,uid_t uid,gid_t gid,char * path,node_details_t * res)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 *===========================================================================*/
req_flush(endpoint_t fs_e,dev_t dev)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 *===========================================================================*/
req_statvfs(endpoint_t fs_e,struct statvfs * buf)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 *===========================================================================*/
req_ftrunc(endpoint_t fs_e,ino_t inode_nr,off_t start,off_t end)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 *===========================================================================*/
req_getdents_actual(endpoint_t fs_e,ino_t inode_nr,off_t pos,vir_bytes buf,size_t size,off_t * new_pos,int direct,int cpflag)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 *===========================================================================*/
req_getdents(endpoint_t fs_e,ino_t inode_nr,off_t pos,vir_bytes buf,size_t size,off_t * new_pos,int direct)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 *===========================================================================*/
req_inhibread(endpoint_t fs_e,ino_t inode_nr)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 *===========================================================================*/
req_link(endpoint_t fs_e,ino_t link_parent,char * lastc,ino_t linked_file)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 *===========================================================================*/
req_lookup(endpoint_t fs_e,ino_t dir_ino,ino_t root_ino,uid_t uid,gid_t gid,struct lookup * resolve,lookup_res_t * res,struct fproc * rfp)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 *===========================================================================*/
req_mkdir(endpoint_t fs_e,ino_t inode_nr,char * lastc,uid_t uid,gid_t gid,mode_t dmode)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 *===========================================================================*/
req_mknod(endpoint_t fs_e,ino_t inode_nr,char * lastc,uid_t uid,gid_t gid,mode_t dmode,dev_t dev)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 *===========================================================================*/
req_mountpoint(endpoint_t fs_e,ino_t inode_nr)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 *===========================================================================*/
req_newnode(endpoint_t fs_e,uid_t uid,gid_t gid,mode_t dmode,dev_t dev,struct node_details * res)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 *===========================================================================*/
req_newdriver(endpoint_t fs_e,dev_t dev,char * label)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(int fs_e,ino_t inode_nr,int count)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 *===========================================================================*/
req_rdlink_actual(endpoint_t fs_e,ino_t inode_nr,endpoint_t proc_e,vir_bytes buf,size_t len,int direct,int cpflag)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 *===========================================================================*/
req_rdlink(endpoint_t fs_e,ino_t inode_nr,endpoint_t proc_e,vir_bytes buf,size_t len,int direct)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 *===========================================================================*/
req_readsuper(struct vmnt * vmp,char * label,dev_t dev,int readonly,int isroot,struct node_details * res,unsigned int * fs_flags)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 *===========================================================================*/
req_readwrite_actual(endpoint_t fs_e,ino_t inode_nr,off_t pos,int rw_flag,endpoint_t user_e,vir_bytes user_addr,unsigned int num_of_bytes,off_t * new_posp,size_t * cum_iop,int cpflag)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 *===========================================================================*/
req_readwrite(endpoint_t fs_e,ino_t inode_nr,off_t pos,int rw_flag,endpoint_t user_e,vir_bytes user_addr,unsigned int num_of_bytes,off_t * new_posp,size_t * cum_iop)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 *===========================================================================*/
req_peek(endpoint_t fs_e,ino_t inode_nr,off_t pos,unsigned int bytes)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
req_rename(endpoint_t fs_e,ino_t old_dir,char * old_name,ino_t new_dir,char * new_name)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
req_rmdir(endpoint_t fs_e,ino_t inode_nr,char * lastc)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 *===========================================================================*/
req_slink_actual(endpoint_t fs_e,ino_t inode_nr,char * lastc,endpoint_t proc_e,vir_bytes path_addr,size_t path_length,uid_t uid,gid_t gid,int cpflag)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 *===========================================================================*/
req_slink(endpoint_t fs_e,ino_t inode_nr,char * lastc,endpoint_t proc_e,vir_bytes path_addr,size_t path_length,uid_t uid,gid_t gid)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 *===========================================================================*/
req_stat_actual(endpoint_t fs_e,ino_t inode_nr,endpoint_t proc_e,vir_bytes buf,int cpflag)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 *===========================================================================*/
req_stat(endpoint_t fs_e,ino_t inode_nr,endpoint_t proc_e,vir_bytes buf)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
req_sync(endpoint_t fs_e)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
req_unlink(endpoint_t fs_e,ino_t inode_nr,char * lastc)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
req_unmount(endpoint_t fs_e)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 *===========================================================================*/
req_utime(endpoint_t fs_e,ino_t inode_nr,struct timespec * actimespec,struct timespec * modtimespec)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