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