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