1 2 #include "fsdriver.h" 3 #include <minix/ds.h> 4 5 /* 6 * Process a READSUPER request from VFS. 7 */ 8 int 9 fsdriver_readsuper(const struct fsdriver * __restrict fdp, 10 const message * __restrict m_in, message * __restrict m_out) 11 { 12 struct fsdriver_node root_node; 13 char label[DS_MAX_KEYLEN]; 14 cp_grant_id_t label_grant; 15 size_t label_len; 16 unsigned int flags, res_flags; 17 dev_t dev; 18 int r; 19 20 dev = m_in->m_vfs_fs_readsuper.device; 21 label_grant = m_in->m_vfs_fs_readsuper.grant; 22 label_len = m_in->m_vfs_fs_readsuper.path_len; 23 flags = m_in->m_vfs_fs_readsuper.flags; 24 25 if (fdp->fdr_mount == NULL) 26 return ENOSYS; 27 28 if (fsdriver_mounted) { 29 printf("fsdriver: attempt to mount multiple times\n"); 30 return EBUSY; 31 } 32 33 if ((r = fsdriver_getname(m_in->m_source, label_grant, label_len, 34 label, sizeof(label), FALSE /*not_empty*/)) != OK) 35 return r; 36 37 if (fdp->fdr_driver != NULL) 38 fdp->fdr_driver(dev, label); 39 40 res_flags = RES_NOFLAGS; 41 42 r = fdp->fdr_mount(dev, flags, &root_node, &res_flags); 43 44 if (r == OK) { 45 /* This one we can set on the file system's behalf. */ 46 if (fdp->fdr_peek != NULL && fdp->fdr_bpeek != NULL) 47 res_flags |= RES_HASPEEK; 48 49 m_out->m_fs_vfs_readsuper.inode = root_node.fn_ino_nr; 50 m_out->m_fs_vfs_readsuper.mode = root_node.fn_mode; 51 m_out->m_fs_vfs_readsuper.file_size = root_node.fn_size; 52 m_out->m_fs_vfs_readsuper.uid = root_node.fn_uid; 53 m_out->m_fs_vfs_readsuper.gid = root_node.fn_gid; 54 m_out->m_fs_vfs_readsuper.flags = res_flags; 55 56 /* Update library-local state. */ 57 fsdriver_mounted = TRUE; 58 fsdriver_root = root_node.fn_ino_nr; 59 } 60 61 return r; 62 } 63 64 /* 65 * Process an UNMOUNT request from VFS. 66 */ 67 int 68 fsdriver_unmount(const struct fsdriver * __restrict fdp, 69 const message * __restrict __unused m_in, 70 message * __restrict __unused m_out) 71 { 72 73 if (fdp->fdr_unmount != NULL) 74 fdp->fdr_unmount(); 75 76 /* Update library-local state. */ 77 fsdriver_mounted = FALSE; 78 79 return OK; 80 } 81 82 /* 83 * Process a PUTNODE request from VFS. 84 */ 85 int 86 fsdriver_putnode(const struct fsdriver * __restrict fdp, 87 const message * __restrict m_in, message * __restrict __unused m_out) 88 { 89 ino_t ino_nr; 90 unsigned int count; 91 92 ino_nr = m_in->m_vfs_fs_putnode.inode; 93 count = m_in->m_vfs_fs_putnode.count; 94 95 if (fdp->fdr_putnode == NULL) 96 return ENOSYS; 97 98 if (count == 0 || count > INT_MAX) { 99 printf("fsdriver: invalid reference count\n"); 100 return EINVAL; 101 } 102 103 return fdp->fdr_putnode(ino_nr, count); 104 } 105 106 /* 107 * Process a NEWNODE request from VFS. 108 */ 109 int 110 fsdriver_newnode(const struct fsdriver * __restrict fdp, 111 const message * __restrict m_in, message * __restrict m_out) 112 { 113 struct fsdriver_node node; 114 mode_t mode; 115 uid_t uid; 116 gid_t gid; 117 dev_t dev; 118 int r; 119 120 mode = m_in->m_vfs_fs_newnode.mode; 121 uid = m_in->m_vfs_fs_newnode.uid; 122 gid = m_in->m_vfs_fs_newnode.gid; 123 dev = m_in->m_vfs_fs_newnode.device; 124 125 if (fdp->fdr_newnode == NULL) 126 return ENOSYS; 127 128 if ((r = fdp->fdr_newnode(mode, uid, gid, dev, &node)) == OK) { 129 m_out->m_fs_vfs_newnode.inode = node.fn_ino_nr; 130 m_out->m_fs_vfs_newnode.mode = node.fn_mode; 131 m_out->m_fs_vfs_newnode.file_size = node.fn_size; 132 m_out->m_fs_vfs_newnode.uid = node.fn_uid; 133 m_out->m_fs_vfs_newnode.gid = node.fn_gid; 134 m_out->m_fs_vfs_newnode.device = node.fn_dev; 135 } 136 137 return r; 138 } 139 140 /* 141 * Process a read or write request from VFS. 142 */ 143 static int 144 read_write(const struct fsdriver * __restrict fdp, 145 const message * __restrict m_in, message * __restrict m_out, int call) 146 { 147 struct fsdriver_data data; 148 ino_t ino_nr; 149 off_t pos; 150 size_t nbytes; 151 ssize_t r; 152 153 ino_nr = m_in->m_vfs_fs_readwrite.inode; 154 pos = m_in->m_vfs_fs_readwrite.seek_pos; 155 nbytes = m_in->m_vfs_fs_readwrite.nbytes; 156 157 if (pos < 0 || nbytes > SSIZE_MAX) 158 return EINVAL; 159 160 data.endpt = m_in->m_source; 161 data.grant = m_in->m_vfs_fs_readwrite.grant; 162 data.size = nbytes; 163 164 if (call == FSC_WRITE) 165 r = fdp->fdr_write(ino_nr, &data, nbytes, pos, call); 166 else 167 r = fdp->fdr_read(ino_nr, &data, nbytes, pos, call); 168 169 if (r >= 0) { 170 pos += r; 171 172 m_out->m_fs_vfs_readwrite.seek_pos = pos; 173 m_out->m_fs_vfs_readwrite.nbytes = r; 174 r = OK; 175 } 176 177 return r; 178 } 179 180 /* 181 * Process a READ request from VFS. 182 */ 183 int 184 fsdriver_read(const struct fsdriver * __restrict fdp, 185 const message * __restrict m_in, message * __restrict m_out) 186 { 187 188 if (fdp->fdr_read == NULL) 189 return ENOSYS; 190 191 return read_write(fdp, m_in, m_out, FSC_READ); 192 } 193 194 /* 195 * Process a WRITE request from VFS. 196 */ 197 int 198 fsdriver_write(const struct fsdriver * __restrict fdp, 199 const message * __restrict m_in, message * __restrict m_out) 200 { 201 202 if (fdp->fdr_write == NULL) 203 return ENOSYS; 204 205 return read_write(fdp, m_in, m_out, FSC_WRITE); 206 } 207 208 /* 209 * Process a PEEK request from VFS. 210 */ 211 int 212 fsdriver_peek(const struct fsdriver * __restrict fdp, 213 const message * __restrict m_in, message * __restrict __unused m_out) 214 { 215 ino_t ino_nr; 216 off_t pos; 217 size_t nbytes; 218 ssize_t r; 219 220 ino_nr = m_in->m_vfs_fs_readwrite.inode; 221 pos = m_in->m_vfs_fs_readwrite.seek_pos; 222 nbytes = m_in->m_vfs_fs_readwrite.nbytes; 223 224 if (fdp->fdr_peek == NULL) 225 return ENOSYS; 226 227 if (pos < 0 || nbytes > SSIZE_MAX) 228 return EINVAL; 229 230 r = fdp->fdr_peek(ino_nr, NULL /*data*/, nbytes, pos, FSC_PEEK); 231 232 /* Do not return a new position. */ 233 if (r >= 0) { 234 m_out->m_fs_vfs_readwrite.nbytes = r; 235 r = OK; 236 } 237 238 return r; 239 } 240 241 /* 242 * Process a GETDENTS request from VFS. 243 */ 244 int 245 fsdriver_getdents(const struct fsdriver * __restrict fdp, 246 const message * __restrict m_in, message * __restrict m_out) 247 { 248 struct fsdriver_data data; 249 ino_t ino_nr; 250 off_t pos; 251 size_t nbytes; 252 ssize_t r; 253 254 ino_nr = m_in->m_vfs_fs_getdents.inode; 255 pos = m_in->m_vfs_fs_getdents.seek_pos; 256 nbytes = m_in->m_vfs_fs_getdents.mem_size; 257 258 if (fdp->fdr_getdents == NULL) 259 return ENOSYS; 260 261 if (pos < 0 || nbytes > SSIZE_MAX) 262 return EINVAL; 263 264 data.endpt = m_in->m_source; 265 data.grant = m_in->m_vfs_fs_getdents.grant; 266 data.size = nbytes; 267 268 r = fdp->fdr_getdents(ino_nr, &data, nbytes, &pos); 269 270 if (r >= 0) { 271 m_out->m_fs_vfs_getdents.seek_pos = pos; 272 m_out->m_fs_vfs_getdents.nbytes = r; 273 r = OK; 274 } 275 276 return r; 277 } 278 279 /* 280 * Process a FTRUNC request from VFS. 281 */ 282 int 283 fsdriver_trunc(const struct fsdriver * __restrict fdp, 284 const message * __restrict m_in, message * __restrict __unused m_out) 285 { 286 ino_t ino_nr; 287 off_t start_pos, end_pos; 288 289 ino_nr = m_in->m_vfs_fs_ftrunc.inode; 290 start_pos = m_in->m_vfs_fs_ftrunc.trc_start; 291 end_pos = m_in->m_vfs_fs_ftrunc.trc_end; 292 293 if (start_pos < 0 || end_pos < 0) 294 return EINVAL; 295 296 if (fdp->fdr_trunc == NULL) 297 return ENOSYS; 298 299 return fdp->fdr_trunc(ino_nr, start_pos, end_pos); 300 } 301 302 /* 303 * Process a INHIBREAD request from VFS. 304 */ 305 int 306 fsdriver_inhibread(const struct fsdriver * __restrict fdp, 307 const message * __restrict m_in, message * __restrict __unused m_out) 308 { 309 ino_t ino_nr; 310 311 ino_nr = m_in->m_vfs_fs_inhibread.inode; 312 313 if (fdp->fdr_seek != NULL) 314 fdp->fdr_seek(ino_nr); 315 316 return OK; 317 } 318 319 /* 320 * Process a CREATE request from VFS. 321 */ 322 int 323 fsdriver_create(const struct fsdriver * __restrict fdp, 324 const message * __restrict m_in, message * __restrict m_out) 325 { 326 struct fsdriver_node node; 327 char name[NAME_MAX+1]; 328 cp_grant_id_t grant; 329 size_t len; 330 ino_t dir_nr; 331 mode_t mode; 332 uid_t uid; 333 gid_t gid; 334 int r; 335 336 grant = m_in->m_vfs_fs_create.grant; 337 len = m_in->m_vfs_fs_create.path_len; 338 dir_nr = m_in->m_vfs_fs_create.inode; 339 mode = m_in->m_vfs_fs_create.mode; 340 uid = m_in->m_vfs_fs_create.uid; 341 gid = m_in->m_vfs_fs_create.gid; 342 343 if (fdp->fdr_create == NULL) 344 return ENOSYS; 345 346 if ((r = fsdriver_getname(m_in->m_source, grant, len, name, 347 sizeof(name), TRUE /*not_empty*/)) != OK) 348 return r; 349 350 if (!strcmp(name, ".") || !strcmp(name, "..")) 351 return EEXIST; 352 353 if ((r = fdp->fdr_create(dir_nr, name, mode, uid, gid, &node)) == OK) { 354 m_out->m_fs_vfs_create.inode = node.fn_ino_nr; 355 m_out->m_fs_vfs_create.mode = node.fn_mode; 356 m_out->m_fs_vfs_create.file_size = node.fn_size; 357 m_out->m_fs_vfs_create.uid = node.fn_uid; 358 m_out->m_fs_vfs_create.gid = node.fn_gid; 359 } 360 361 return r; 362 } 363 364 /* 365 * Process a MKDIR request from VFS. 366 */ 367 int 368 fsdriver_mkdir(const struct fsdriver * __restrict fdp, 369 const message * __restrict m_in, message * __restrict __unused m_out) 370 { 371 char name[NAME_MAX+1]; 372 cp_grant_id_t grant; 373 size_t path_len; 374 ino_t dir_nr; 375 mode_t mode; 376 uid_t uid; 377 gid_t gid; 378 int r; 379 380 grant = m_in->m_vfs_fs_mkdir.grant; 381 path_len = m_in->m_vfs_fs_mkdir.path_len; 382 dir_nr = m_in->m_vfs_fs_mkdir.inode; 383 mode = m_in->m_vfs_fs_mkdir.mode; 384 uid = m_in->m_vfs_fs_mkdir.uid; 385 gid = m_in->m_vfs_fs_mkdir.gid; 386 387 if (fdp->fdr_mkdir == NULL) 388 return ENOSYS; 389 390 if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name, 391 sizeof(name), TRUE /*not_empty*/)) != OK) 392 return r; 393 394 if (!strcmp(name, ".") || !strcmp(name, "..")) 395 return EEXIST; 396 397 return fdp->fdr_mkdir(dir_nr, name, mode, uid, gid); 398 } 399 400 /* 401 * Process a MKNOD request from VFS. 402 */ 403 int 404 fsdriver_mknod(const struct fsdriver * __restrict fdp, 405 const message * __restrict m_in, message * __restrict __unused m_out) 406 { 407 char name[NAME_MAX+1]; 408 cp_grant_id_t grant; 409 size_t path_len; 410 ino_t dir_nr; 411 mode_t mode; 412 uid_t uid; 413 gid_t gid; 414 dev_t dev; 415 int r; 416 417 grant = m_in->m_vfs_fs_mknod.grant; 418 path_len = m_in->m_vfs_fs_mknod.path_len; 419 dir_nr = m_in->m_vfs_fs_mknod.inode; 420 mode = m_in->m_vfs_fs_mknod.mode; 421 uid = m_in->m_vfs_fs_mknod.uid; 422 gid = m_in->m_vfs_fs_mknod.gid; 423 dev = m_in->m_vfs_fs_mknod.device; 424 425 if (fdp->fdr_mknod == NULL) 426 return ENOSYS; 427 428 if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name, 429 sizeof(name), TRUE /*not_empty*/)) != OK) 430 return r; 431 432 if (!strcmp(name, ".") || !strcmp(name, "..")) 433 return EEXIST; 434 435 return fdp->fdr_mknod(dir_nr, name, mode, uid, gid, dev); 436 } 437 438 /* 439 * Process a LINK request from VFS. 440 */ 441 int 442 fsdriver_link(const struct fsdriver * __restrict fdp, 443 const message * __restrict m_in, message * __restrict __unused m_out) 444 { 445 char name[NAME_MAX+1]; 446 cp_grant_id_t grant; 447 size_t path_len; 448 ino_t dir_nr, ino_nr; 449 int r; 450 451 grant = m_in->m_vfs_fs_link.grant; 452 path_len = m_in->m_vfs_fs_link.path_len; 453 dir_nr = m_in->m_vfs_fs_link.dir_ino; 454 ino_nr = m_in->m_vfs_fs_link.inode; 455 456 if (fdp->fdr_link == NULL) 457 return ENOSYS; 458 459 if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name, 460 sizeof(name), TRUE /*not_empty*/)) != OK) 461 return r; 462 463 if (!strcmp(name, ".") || !strcmp(name, "..")) 464 return EEXIST; 465 466 return fdp->fdr_link(dir_nr, name, ino_nr); 467 } 468 469 /* 470 * Process an UNLINK request from VFS. 471 */ 472 int 473 fsdriver_unlink(const struct fsdriver * __restrict fdp, 474 const message * __restrict m_in, message * __restrict __unused m_out) 475 { 476 char name[NAME_MAX+1]; 477 cp_grant_id_t grant; 478 size_t path_len; 479 ino_t dir_nr; 480 int r; 481 482 grant = m_in->m_vfs_fs_unlink.grant; 483 path_len = m_in->m_vfs_fs_unlink.path_len; 484 dir_nr = m_in->m_vfs_fs_unlink.inode; 485 486 if (fdp->fdr_unlink == NULL) 487 return ENOSYS; 488 489 if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name, 490 sizeof(name), TRUE /*not_empty*/)) != OK) 491 return r; 492 493 if (!strcmp(name, ".") || !strcmp(name, "..")) 494 return EPERM; 495 496 return fdp->fdr_unlink(dir_nr, name, FSC_UNLINK); 497 } 498 499 /* 500 * Process a RMDIR request from VFS. 501 */ 502 int 503 fsdriver_rmdir(const struct fsdriver * __restrict fdp, 504 const message * __restrict m_in, message * __restrict __unused m_out) 505 { 506 char name[NAME_MAX+1]; 507 cp_grant_id_t grant; 508 size_t path_len; 509 ino_t dir_nr; 510 int r; 511 512 grant = m_in->m_vfs_fs_unlink.grant; 513 path_len = m_in->m_vfs_fs_unlink.path_len; 514 dir_nr = m_in->m_vfs_fs_unlink.inode; 515 516 if (fdp->fdr_rmdir == NULL) 517 return ENOSYS; 518 519 if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name, 520 sizeof(name), TRUE /*not_empty*/)) != OK) 521 return r; 522 523 if (!strcmp(name, ".")) 524 return EINVAL; 525 526 if (!strcmp(name, "..")) 527 return ENOTEMPTY; 528 529 return fdp->fdr_rmdir(dir_nr, name, FSC_RMDIR); 530 } 531 532 /* 533 * Process a RENAME request from VFS. 534 */ 535 int 536 fsdriver_rename(const struct fsdriver * __restrict fdp, 537 const message * __restrict m_in, message * __restrict __unused m_out) 538 { 539 char old_name[NAME_MAX+1], new_name[NAME_MAX+1]; 540 cp_grant_id_t old_grant, new_grant; 541 size_t old_len, new_len; 542 ino_t old_dir_nr, new_dir_nr; 543 int r; 544 545 old_grant = m_in->m_vfs_fs_rename.grant_old; 546 old_len = m_in->m_vfs_fs_rename.len_old; 547 old_dir_nr = m_in->m_vfs_fs_rename.dir_old; 548 new_grant = m_in->m_vfs_fs_rename.grant_new; 549 new_len = m_in->m_vfs_fs_rename.len_new; 550 new_dir_nr = m_in->m_vfs_fs_rename.dir_new; 551 552 if (fdp->fdr_rename == NULL) 553 return ENOSYS; 554 555 if ((r = fsdriver_getname(m_in->m_source, old_grant, old_len, old_name, 556 sizeof(old_name), TRUE /*not_empty*/)) != OK) 557 return r; 558 559 if (!strcmp(old_name, ".") || !strcmp(old_name, "..")) 560 return EINVAL; 561 562 if ((r = fsdriver_getname(m_in->m_source, new_grant, new_len, new_name, 563 sizeof(new_name), TRUE /*not_empty*/)) != OK) 564 return r; 565 566 if (!strcmp(new_name, ".") || !strcmp(new_name, "..")) 567 return EINVAL; 568 569 return fdp->fdr_rename(old_dir_nr, old_name, new_dir_nr, new_name); 570 } 571 572 /* 573 * Process a SLINK request from VFS. 574 */ 575 int 576 fsdriver_slink(const struct fsdriver * __restrict fdp, 577 const message * __restrict m_in, message * __restrict __unused m_out) 578 { 579 struct fsdriver_data data; 580 char name[NAME_MAX+1]; 581 cp_grant_id_t grant; 582 size_t path_len; 583 ino_t dir_nr; 584 uid_t uid; 585 gid_t gid; 586 int r; 587 588 grant = m_in->m_vfs_fs_slink.grant_path; 589 path_len = m_in->m_vfs_fs_slink.path_len; 590 dir_nr = m_in->m_vfs_fs_slink.inode; 591 uid = m_in->m_vfs_fs_slink.uid; 592 gid = m_in->m_vfs_fs_slink.gid; 593 594 if (fdp->fdr_slink == NULL) 595 return ENOSYS; 596 597 if ((r = fsdriver_getname(m_in->m_source, grant, path_len, name, 598 sizeof(name), TRUE /*not_empty*/)) != OK) 599 return r; 600 601 if (!strcmp(name, ".") || !strcmp(name, "..")) 602 return EEXIST; 603 604 data.endpt = m_in->m_source; 605 data.grant = m_in->m_vfs_fs_slink.grant_target; 606 data.size = m_in->m_vfs_fs_slink.mem_size; 607 608 return fdp->fdr_slink(dir_nr, name, uid, gid, &data, data.size); 609 } 610 611 /* 612 * Process a RDLINK request from VFS. 613 */ 614 int 615 fsdriver_rdlink(const struct fsdriver * __restrict fdp, 616 const message * __restrict m_in, message * __restrict m_out) 617 { 618 struct fsdriver_data data; 619 ssize_t r; 620 621 if (fdp->fdr_rdlink == NULL) 622 return ENOSYS; 623 624 data.endpt = m_in->m_source; 625 data.grant = m_in->m_vfs_fs_rdlink.grant; 626 data.size = m_in->m_vfs_fs_rdlink.mem_size; 627 628 r = fdp->fdr_rdlink(m_in->m_vfs_fs_rdlink.inode, &data, data.size); 629 630 if (r >= 0) { 631 m_out->m_fs_vfs_rdlink.nbytes = r; 632 r = OK; 633 } 634 635 return r; 636 } 637 638 /* 639 * Process a STAT request from VFS. 640 */ 641 int 642 fsdriver_stat(const struct fsdriver * __restrict fdp, 643 const message * __restrict m_in, message * __restrict __unused m_out) 644 { 645 struct stat buf; 646 cp_grant_id_t grant; 647 ino_t ino_nr; 648 int r; 649 650 ino_nr = m_in->m_vfs_fs_stat.inode; 651 grant = m_in->m_vfs_fs_stat.grant; 652 653 if (fdp->fdr_stat == NULL) 654 return ENOSYS; 655 656 memset(&buf, 0, sizeof(buf)); 657 658 if ((r = fdp->fdr_stat(ino_nr, &buf)) == OK) 659 r = sys_safecopyto(m_in->m_source, grant, 0, (vir_bytes)&buf, 660 (phys_bytes)sizeof(buf)); 661 662 return r; 663 } 664 665 /* 666 * Process a CHOWN request from VFS. 667 */ 668 int 669 fsdriver_chown(const struct fsdriver * __restrict fdp, 670 const message * __restrict m_in, message * __restrict m_out) 671 { 672 ino_t ino_nr; 673 uid_t uid; 674 gid_t gid; 675 mode_t mode; 676 int r; 677 678 ino_nr = m_in->m_vfs_fs_chown.inode; 679 uid = m_in->m_vfs_fs_chown.uid; 680 gid = m_in->m_vfs_fs_chown.gid; 681 682 if (fdp->fdr_chown == NULL) 683 return ENOSYS; 684 685 if ((r = fdp->fdr_chown(ino_nr, uid, gid, &mode)) == OK) 686 m_out->m_fs_vfs_chown.mode = mode; 687 688 return r; 689 } 690 691 /* 692 * Process a CHMOD request from VFS. 693 */ 694 int 695 fsdriver_chmod(const struct fsdriver * __restrict fdp, 696 const message * __restrict m_in, message * __restrict m_out) 697 { 698 ino_t ino_nr; 699 mode_t mode; 700 int r; 701 702 ino_nr = m_in->m_vfs_fs_chmod.inode; 703 mode = m_in->m_vfs_fs_chmod.mode; 704 705 if (fdp->fdr_chmod == NULL) 706 return ENOSYS; 707 708 if ((r = fdp->fdr_chmod(ino_nr, &mode)) == OK) 709 m_out->m_fs_vfs_chmod.mode = mode; 710 711 return r; 712 } 713 714 /* 715 * Process a UTIME request from VFS. 716 */ 717 int 718 fsdriver_utime(const struct fsdriver * __restrict fdp, 719 const message * __restrict m_in, message * __restrict __unused m_out) 720 { 721 ino_t ino_nr; 722 struct timespec atime, mtime; 723 724 ino_nr = m_in->m_vfs_fs_utime.inode; 725 atime.tv_sec = m_in->m_vfs_fs_utime.actime; 726 atime.tv_nsec = m_in->m_vfs_fs_utime.acnsec; 727 mtime.tv_sec = m_in->m_vfs_fs_utime.modtime; 728 mtime.tv_nsec = m_in->m_vfs_fs_utime.modnsec; 729 730 if (fdp->fdr_utime == NULL) 731 return ENOSYS; 732 733 return fdp->fdr_utime(ino_nr, &atime, &mtime); 734 } 735 736 /* 737 * Process a MOUNTPOINT request from VFS. 738 */ 739 int 740 fsdriver_mountpoint(const struct fsdriver * __restrict fdp, 741 const message * __restrict m_in, message * __restrict __unused m_out) 742 { 743 ino_t ino_nr; 744 745 ino_nr = m_in->m_vfs_fs_mountpoint.inode; 746 747 if (fdp->fdr_mountpt == NULL) 748 return ENOSYS; 749 750 return fdp->fdr_mountpt(ino_nr); 751 } 752 753 /* 754 * Process a STATVFS request from VFS. 755 */ 756 int 757 fsdriver_statvfs(const struct fsdriver * __restrict fdp, 758 const message * __restrict m_in, message * __restrict __unused m_out) 759 { 760 struct statvfs buf; 761 int r; 762 763 if (fdp->fdr_statvfs == NULL) 764 return ENOSYS; 765 766 memset(&buf, 0, sizeof(buf)); 767 768 if ((r = fdp->fdr_statvfs(&buf)) != OK) 769 return r; 770 771 return sys_safecopyto(m_in->m_source, m_in->m_vfs_fs_statvfs.grant, 0, 772 (vir_bytes)&buf, (phys_bytes)sizeof(buf)); 773 } 774 775 /* 776 * Process a SYNC request from VFS. 777 */ 778 int 779 fsdriver_sync(const struct fsdriver * __restrict fdp, 780 const message * __restrict __unused m_in, 781 message * __restrict __unused m_out) 782 { 783 784 if (fdp->fdr_sync != NULL) 785 fdp->fdr_sync(); 786 787 return OK; 788 } 789 790 /* 791 * Process a NEW_DRIVER request from VFS. 792 */ 793 int 794 fsdriver_newdriver(const struct fsdriver * __restrict fdp, 795 const message * __restrict m_in, message * __restrict __unused m_out) 796 { 797 char label[DS_MAX_KEYLEN]; 798 cp_grant_id_t grant; 799 size_t path_len; 800 dev_t dev; 801 int r; 802 803 dev = m_in->m_vfs_fs_new_driver.device; 804 grant = m_in->m_vfs_fs_new_driver.grant; 805 path_len = m_in->m_vfs_fs_new_driver.path_len; 806 807 if (fdp->fdr_driver == NULL) 808 return OK; 809 810 if ((r = fsdriver_getname(m_in->m_source, grant, path_len, label, 811 sizeof(label), FALSE /*not_empty*/)) != OK) 812 return r; 813 814 fdp->fdr_driver(dev, label); 815 816 return OK; 817 } 818 819 /* 820 * Process a block read or write request from VFS. 821 */ 822 static ssize_t 823 bread_bwrite(const struct fsdriver * __restrict fdp, 824 const message * __restrict m_in, message * __restrict m_out, int call) 825 { 826 struct fsdriver_data data; 827 dev_t dev; 828 off_t pos; 829 size_t nbytes; 830 ssize_t r; 831 832 dev = m_in->m_vfs_fs_breadwrite.device; 833 pos = m_in->m_vfs_fs_breadwrite.seek_pos; 834 nbytes = m_in->m_vfs_fs_breadwrite.nbytes; 835 836 if (pos < 0 || nbytes > SSIZE_MAX) 837 return EINVAL; 838 839 data.endpt = m_in->m_source; 840 data.grant = m_in->m_vfs_fs_breadwrite.grant; 841 data.size = nbytes; 842 843 if (call == FSC_WRITE) 844 r = fdp->fdr_bwrite(dev, &data, nbytes, pos, call); 845 else 846 r = fdp->fdr_bread(dev, &data, nbytes, pos, call); 847 848 if (r >= 0) { 849 pos += r; 850 851 m_out->m_fs_vfs_breadwrite.seek_pos = pos; 852 m_out->m_fs_vfs_breadwrite.nbytes = r; 853 r = OK; 854 } 855 856 return r; 857 } 858 859 /* 860 * Process a BREAD request from VFS. 861 */ 862 ssize_t 863 fsdriver_bread(const struct fsdriver * __restrict fdp, 864 const message * __restrict m_in, message * __restrict m_out) 865 { 866 867 if (fdp->fdr_bread == NULL) 868 return ENOSYS; 869 870 return bread_bwrite(fdp, m_in, m_out, FSC_READ); 871 } 872 873 /* 874 * Process a BWRITE request from VFS. 875 */ 876 ssize_t 877 fsdriver_bwrite(const struct fsdriver * __restrict fdp, 878 const message * __restrict m_in, message * __restrict m_out) 879 { 880 881 if (fdp->fdr_bwrite == NULL) 882 return ENOSYS; 883 884 return bread_bwrite(fdp, m_in, m_out, FSC_WRITE); 885 } 886 887 /* 888 * Process a BPEEK request from VFS. 889 */ 890 int 891 fsdriver_bpeek(const struct fsdriver * __restrict fdp, 892 const message * __restrict m_in, message * __restrict __unused m_out) 893 { 894 dev_t dev; 895 off_t pos; 896 size_t nbytes; 897 ssize_t r; 898 899 dev = m_in->m_vfs_fs_breadwrite.device; 900 pos = m_in->m_vfs_fs_breadwrite.seek_pos; 901 nbytes = m_in->m_vfs_fs_breadwrite.nbytes; 902 903 if (fdp->fdr_bpeek == NULL) 904 return ENOSYS; 905 906 if (pos < 0 || nbytes > SSIZE_MAX) 907 return EINVAL; 908 909 r = fdp->fdr_bpeek(dev, NULL /*data*/, nbytes, pos, FSC_PEEK); 910 911 /* Do not return a new position. */ 912 if (r >= 0) { 913 m_out->m_fs_vfs_breadwrite.nbytes = r; 914 r = OK; 915 } 916 917 return r; 918 } 919 920 /* 921 * Process a FLUSH request from VFS. 922 */ 923 int 924 fsdriver_flush(const struct fsdriver * __restrict fdp, 925 const message * __restrict m_in, message * __restrict __unused m_out) 926 { 927 dev_t dev; 928 929 dev = m_in->m_vfs_fs_flush.device; 930 931 if (fdp->fdr_bflush != NULL) 932 fdp->fdr_bflush(dev); 933 934 return OK; 935 } 936