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