1/* 2 This file contains the vnode layer used by the file system construction 3 kit. It is the file system independent layer and managed hooking up 4 requests from the test program (fsh and tstfs) to the actual file system 5 routines. It provides a rather posix-like interface generally with 6 the routines preceded by a "sys_" prefix. 7 8 THIS CODE COPYRIGHT DOMINIC GIAMPAOLO. NO WARRANTY IS EXPRESSED 9 OR IMPLIED. YOU MAY USE THIS CODE AND FREELY DISTRIBUTE IT FOR 10 NON-COMMERCIAL USE AS LONG AS THIS NOTICE REMAINS ATTACHED. 11 12 FOR COMMERCIAL USE, CONTACT DOMINIC GIAMPAOLO (dbg@be.com). 13 14 Dominic Giampaolo 15 dbg@be.com 16*/ 17#include "compat.h" 18 19#include "skiplist.h" 20#include "lock.h" 21#include "fsproto.h" 22#include "kprotos.h" 23 24#if USED_IN_FS_SHELL 25# include "tracker.h" 26#endif 27 28#define TRACE_KERNEL 0 29#if TRACE_KERNEL 30# define FUNCTION() puts(__FUNCTION__) 31# define TRACE(x...) printf(x) 32#else 33# define FUNCTION() 34# define TRACE(x...) 35#endif 36 37#include <sys/stat.h> 38 39#define OMODE_MASK (MY_O_RDONLY | MY_O_WRONLY | MY_O_RDWR) 40#define SLEEP_TIME (10000.0) 41#define MAX_SYM_LINKS 16 42 43#define FREE_LIST 0 44#define USED_LIST 1 45#define LOCKED_LIST 2 46#define LIST_NUM 3 47 48#define FD_FILE 1 49#define FD_DIR 2 50#define FD_WD 4 51#define FD_ATTR_DIR 8 52 53#define FD_ALL (FD_FILE | FD_DIR | FD_WD | FD_ATTR_DIR) 54 55#define DEFAULT_FD_NUM (128) 56#define VNNUM 256 57 58typedef unsigned long fsystem_id; 59 60typedef struct vnode vnode; 61typedef struct vnlist vnlist; 62typedef struct vnlink vnlink; 63typedef struct fsystem fsystem; 64typedef struct nspace nspace; 65typedef struct ofile ofile; 66typedef struct ioctx ioctx; 67typedef struct fdarray fdarray; 68 69struct vnlist { 70 vnode *head; 71 vnode *tail; 72 int num; 73}; 74 75struct vnlink { 76 vnode *prev; 77 vnode *next; 78}; 79 80struct vnode { 81 vnode_id vnid; 82 nspace * ns; 83 nspace * mounted; 84 char remove; 85 char busy; 86 char inlist; 87 char watched; 88 vnlink nspace; 89 vnlink list; 90 int rcnt; 91 void * data; 92}; 93 94struct fsystem { 95 fsystem_id fsid; 96 int fixed; 97 image_id aid; 98 char name[IDENT_NAME_LENGTH]; 99 int rcnt; 100 vnode_ops ops; 101}; 102 103struct nspace { 104 nspace_id nsid; 105 my_dev_t dev; 106 my_ino_t ino; 107 fsystem *fs; 108 vnlist vnodes; 109 void *data; 110 vnode * root; 111 vnode * mount; 112 nspace * prev; 113 nspace * next; 114 char shutdown; 115}; 116 117struct ofile { 118 short type; 119 ushort flags; 120 vnode * vn; 121 void * cookie; 122 long rcnt; 123 long ocnt; 124 125 fs_off_t pos; 126 int omode; 127}; 128 129 130struct ioctx { 131 lock lock; 132 int kerrno; 133 vnode * cwd; 134 fdarray * fds; 135}; 136 137struct fdarray { 138 long rcnt; 139 lock lock; 140 int num; 141 ulong *alloc; 142 ulong *coes; 143 ofile *fds[1]; 144}; 145 146extern struct { 147 const char * name; 148 vnode_ops * ops; 149} fixed_fs[]; 150 151static vnode_id invalid_vnid = 0; 152static vnode * rootvn; 153static int max_glb_file; 154static fdarray * global_fds; 155static vnlist lists[LIST_NUM]; 156static nspace * nshead; 157static lock vnlock; 158static lock fstablock; 159static nspace ** nstab; 160static fsystem ** fstab; 161static int nns; 162static int nfs; 163static fsystem_id nxfsid; 164static nspace_id nxnsid; 165static SkipList skiplist; 166static int vnnum; 167static int usdvnnum; 168 169 170 171static fsystem * inc_file_system(const char *name); 172static int dec_file_system(fsystem *fs); 173static ioctx * get_cur_ioctx(void); 174 175static int get_dir_fd(int kernel, int fd, const char *path, char *filename, 176 vnode **dvn); 177static int get_file_fd(int kernel, int fd, const char *path, 178 int eatsymlink, vnode **vn); 179static int get_file_vn(nspace_id nsid, vnode_id vnid, const char *path, 180 int eatsymlink, vnode **vn); 181static int parse_path_fd(int kerne, int fd, char **pstart, 182 int eatsymlink, vnode **vn); 183static int parse_path_vn(nspace_id nsid, vnode_id vnid, char **start, 184 int eatsymlink, vnode **vn); 185static int parse_path(vnode *bvn, char **pstart, char *path, 186 int eatsymlink, vnode **vn); 187 188static char * cat_paths(char *a, char *b); 189 190static int load_vnode(nspace_id nsid, vnode_id vnid, char r, vnode **vnp); 191static vnode * lookup_vnode(nspace_id nsid, vnode_id vnid); 192static void move_vnode(vnode *vn, int list); 193static vnode * steal_vnode(int list); 194static void flush_vnode(vnode *vn, char r); 195static int sort_vnode(vnode *vn); 196static void clear_vnode(vnode *vn); 197static void inc_vnode(vnode *vn); 198static void dec_vnode(vnode *vn, char r); 199static int compare_vnode(vnode *vna, vnode *vnb); 200 201static nspace * nsidtons(nspace_id nsid); 202//static int alloc_wd_fd(int kernel, vnode *vn, int coe, int *fdp); 203 204static int is_root(vnode *root, vnode **mount); 205static int is_mount_vnode(vnode *mount, vnode **root); 206static int is_mount_vnid(nspace_id nsid, vnode_id vnid, vnode_id *mount); 207 208static ofile * get_fd(int kernel, int fd, int type); 209static int put_fd(ofile *f); 210static int new_fd(int kernel, int nfd, ofile *f, int fd, int coe); 211static int remove_fd(int kernel, int fd, int type); 212//static int get_coe(int kernel, int fd, int type, int *coe); 213//static int set_coe(int kernel, int fd, int type, int coe); 214//static int get_omode(int kernel, int fd, int type, int *omode); 215static int invoke_close(ofile *f); 216static int invoke_free(ofile *f); 217 218static fdarray * new_fds(int num); 219//static int free_fds(fdarray *fds); 220 221 222#define BITSZ(n) (((n) + 31) & ~31) 223#define SETBIT(a,i,v) *((a)+(i)/32) = (*((a)+(i)/32) & ~(1<<((i)%32))) | (v<<((i)%32)) 224#define GETBIT(a,i) ((*((a)+(i)/32) & (1<<((i)%32))) >> ((i)%32)) 225 226/* ---------------------------------------------------------------- */ 227 228#include <stdio.h> 229 230static void 231PANIC(char *s, ...) 232{ 233 va_list list; 234 235 va_start(list, s); 236 vfprintf(stdout, s, list); 237 va_end(list); 238 239 debugger("fs shell kernel panic!"); 240} 241 242 243#ifndef USER 244#ifdef DEBUG 245int 246dump_fsystem(int argc, char **argv) 247{ 248 struct fsystem *fs; 249 250 if (argv[1] == NULL) { 251 kprintf("%s needs an address argument\n", argv[0]); 252 return 1; 253 } 254 255 fs = (struct fsystem *)strtoul(argv[1], NULL, 0); 256 257 kprintf("fs @ 0x%x name %s rcnt %d ops @ 0x%x\n", fs, fs->name, 258 fs->rcnt, &fs->ops); 259} 260 261int 262dump_ioctx(int argc, char **argv) 263{ 264 struct ioctx *ioctx; 265 266 if (argv[1] == NULL) { 267 kprintf("%s needs an address argument\n", argv[0]); 268 return 1; 269 } 270 271 ioctx = (struct ioctx *)strtoul(argv[1], NULL, 0); 272 273 kprintf("ioctx @ 0x%x, kerrno %d, cwd 0x%x, fdarray 0x%x\n", ioctx, 274 ioctx->kerrno, ioctx->cwd, ioctx->fds); 275} 276 277 278int 279dump_vnode(int argc, char **argv) 280{ 281 struct vnode *vn; 282 283 if (argv[1] == NULL) { 284 kprintf("%s needs an address argument\n", argv[0]); 285 return 1; 286 } 287 288 vn = (vnode *)strtoul(argv[1], NULL, 0); 289 290 kprintf("vnode @ 0x%x vnid 0x%x ns 0x%x mounted 0x%x\n", vn, vn->vnid, 291 vn->ns, vn->mounted); 292 kprintf("remove %d busy %d inlist %d\n", vn->remove, vn->busy, vn->inlist); 293 kprintf("nspace 0x%x list 0x%x rcnt 0x%x data 0x%x\n", &vn->nspace, 294 &vn->list, vn->rcnt, vn->data); 295} 296 297 298int 299dump_fdarray(int argc, char **argv) 300{ 301 int i; 302 struct fdarray *fds; 303 304 if (argv[1] == NULL) { 305 kprintf("%s needs an address argument\n", argv[0]); 306 return 1; 307 } 308 309 fds = (struct fdarray *)strtoul(argv[1], NULL, 0); 310 311 kprintf("fdarray @ 0x%x rcnt %d lock %d num %d\n", fds, fds->rcnt, 312 fds->num); 313 kprintf("alloc 0x%x coes 0x%x\n", fds->alloc, fds->coes); 314 for(i=0; i < fds->num; i++) 315 if (fds->fds[i]) 316 kprintf("fd %3d @ 0x%x\n", i, fds->fds[i]); 317} 318 319 320int 321dump_ofile(int argc, char **argv) 322{ 323 struct ofile *ofile; 324 325 if (argv[1] == NULL) { 326 kprintf("%s needs an address argument\n", argv[0]); 327 return 1; 328 } 329 330 ofile = (struct ofile *)strtoul(argv[1], NULL, 0); 331 332 kprintf("ofile @ 0x%x type %d flags %d vn 0x%x cookie 0x%x\n", 333 ofile, ofile->type, ofile->flags, ofile->vn, ofile->cookie); 334 kprintf("rcnt %d ocnt %d pos 0x%x omode 0x%x\n", ofile->rcnt, ofile->ocnt, 335 ofile->pos, ofile->omode); 336} 337 338int 339dump_nspace(int argc, char **argv) 340{ 341 struct nspace *ns; 342 343 if (argv[1] == NULL) { 344 kprintf("%s needs an address argument\n", argv[0]); 345 return 1; 346 } 347 348 ns = (struct nspace *)strtoul(argv[1], NULL, 0); 349 350 kprintf("ns @ 0x%x nsid %d vnlist @ 0x%x data 0x%x\n", ns, ns->nsid, 351 &ns->vnodes, ns->data); 352 kprintf("root 0x%x mount 0x%x prev 0x%x next 0x%x\n", ns->root, ns->mount, 353 ns->prev, ns->next); 354 kprintf("shutdown %d fs @ 0x%x\n", ns->shutdown, ns->fs); 355} 356 357void 358do_dump_io_info(thread_rec *thr) 359{ 360 int i; 361 struct fdarray *fds; 362 363 if (thr->ioctx == NULL || thr->ioctx->fds == NULL) { 364 kprintf("thread: %d (%s)\n No io info?!?\n", thr->thid, thr->name); 365 return; 366 } 367 368 kprintf("thread: %d (%s)\n", thr->thid, thr->name); 369 fds = thr->ioctx->fds; 370 371 for(i=0; i < fds->num; i++) 372 if (fds->fds[i]) 373 kprintf(" fd %3d vnode @ 0x%.8x (vnid 0x%.8x, data 0x%.8x)\n", i, 374 fds->fds[i]->vn, fds->fds[i]->vn->vnid, 375 fds->fds[i]->vn->data); 376} 377 378 379int 380dump_io_info(int argc, char **argv) 381{ 382 int i; 383 thread_rec *thr; 384 385 if (argv[1] == NULL) { 386 kprintf("%s needs an thread name/address argument\n", argv[0]); 387 return 1; 388 } 389 390 if (strcmp(argv[1], "-n") == 0) { 391 int len; 392 393 /* hunt for the name in argv[2] */ 394 if (argv[2] == NULL) { 395 kprintf("thread: the `-name' option requires an argument\n"); 396 return 0; 397 } 398 399 len = strlen(argv[2]); 400 for(i=0; i < nthreads; i++) { 401 if (thread_tab[i] == NULL) 402 continue; 403 404 if (mystrstr(thread_tab[i]->name, argv[2]) != NULL) { 405 thr = thread_tab[i]; 406 do_dump_io_info(thr); 407 } 408 } 409 } else { 410 ulong num; 411 412 num = strtoul(argv[2], NULL, 0); 413 414 if (num < 0x2ffff && isbadthid(num) == 0) 415 thr = thread_tab[thidtoslot(num)]; 416 else 417 thr = (thread_rec *)num; 418 419 if (thr == 0) 420 return 0; 421 422 do_dump_io_info(thr); 423 } 424 425 return 1; 426} 427 428 429 430int 431find_vn(int argc, char **argv) 432{ 433 nspace *ns; 434 vnode *vn; 435 vnode fakevn; 436 vnode_id vnid; 437 438 if (argv[1] == NULL) { 439 kprintf("%s needs a vnid argument\n", argv[0]); 440 return 1; 441 } 442 443 vnid = (vnode_id)strtoul(argv[1], NULL, 0); 444 445 for(ns=nshead; ns; ns=ns->next) { 446 fakevn.ns = ns; 447 fakevn.vnid = vnid; 448 vn = SearchSL(skiplist, &fakevn); 449 if (vn) 450 kprintf("vn = 0x%x (nsid = %d)\n", vn, vn->ns->nsid); 451 } 452 453 return 0; 454} 455 456#endif /* DEBUG */ 457#endif /* USER*/ 458 459 460/* ---------------------------------------------------------------- */ 461 462#ifdef USER 463int memsize = 8 * 1024 * 1024; 464#endif 465 466int 467init_vnode_layer(void) 468{ 469 int err; 470 vnode *vns; 471 vnode_id vnid; 472 int i; 473 fsystem *fs; 474 nspace *ns; 475 void *data; 476 extern vnode_ops rootfs; /* XXXdbg */ 477 ioctx *io; 478 479 /* 480 compute vnnum based on memsize. 256 vnodes with 8MB. 481 compute usdvnnum based on vnnum. only 1/4 of total vnodes should 482 remain unlocked. 483 */ 484 485 vnnum = memsize >> 15; 486 usdvnnum = vnnum >> 2; 487 488 vns = (vnode *) calloc(sizeof(vnode) * vnnum, 1); 489 for(i=0; i<vnnum; i++) { 490 vns[i].vnid = invalid_vnid; 491 vns[i].ns = NULL; 492 vns[i].mounted = NULL; 493 vns[i].remove = FALSE; 494 vns[i].busy = FALSE; 495 vns[i].inlist = FREE_LIST; 496 vns[i].nspace.next = vns[i].nspace.prev = NULL; 497 vns[i].list.next = (i == vnnum-1 ? NULL : &vns[i+1]); 498 vns[i].list.prev = (i == 0 ? NULL : &vns[i-1]); 499 vns[i].rcnt = 0; 500 vns[i].data = NULL; 501 } 502 lists[FREE_LIST].head = &vns[0]; 503 lists[FREE_LIST].tail = &vns[vnnum-1]; 504 lists[FREE_LIST].num = vnnum; 505 lists[USED_LIST].head = NULL; 506 lists[USED_LIST].tail = NULL; 507 lists[USED_LIST].num = 0; 508 lists[LOCKED_LIST].head = NULL; 509 lists[LOCKED_LIST].tail = NULL; 510 lists[LOCKED_LIST].num = 0; 511 512 skiplist = NewSL(&compare_vnode, NULL, NO_DUPLICATES); 513 514 /* 515 set max # of file systems and mount points. 516 with 8MB, up to 32 fs and 64 mount points. 517 */ 518 519 nns = memsize >> 17; 520 nfs = memsize >> 18; 521 522 nxfsid = 1; 523 nxnsid = 1; 524 nstab = (nspace **) malloc(nns * sizeof(void *)); 525 memset(nstab, 0, nns * sizeof(void *)); 526 fstab = (fsystem **) malloc(nfs * sizeof(void *)); 527 memset(fstab, 0, nfs * sizeof(void *)); 528 529 new_lock(&vnlock, "vnlock"); 530 new_lock(&fstablock, "fstablock"); 531 532 /* 533 determine the max number of files the kernel can open. 534 8MB -> 256 535 */ 536 537 max_glb_file = memsize >> 15; 538 global_fds = new_fds(max_glb_file); 539 540 541 /* 542 install file systems 543 */ 544 install_file_system(&rootfs, "rootfs", TRUE, -1); 545 546 /* 547 mount the root file system 548 */ 549 550 fs = inc_file_system("rootfs"); 551 552 ns = (nspace *) malloc(sizeof(nspace)); 553 ns->fs = fs; 554 ns->nsid = nxnsid++; 555 nstab[ns->nsid % nns] = ns; 556 ns->vnodes.head = ns->vnodes.tail = NULL; 557 ns->data = NULL; 558 ns->root = NULL; 559 ns->mount = NULL; 560 ns->shutdown = FALSE; 561 ns->prev = ns->next = NULL; 562 nshead = ns; 563 564 err = (*fs->ops.mount)(ns->nsid, NULL, 0, NULL, 0, &data, &vnid); 565 ns->data = data; 566 ns->root = lookup_vnode(ns->nsid, vnid); 567 rootvn = ns->root; 568 569 // set cwd to "/" 570 io = get_cur_ioctx(); 571 inc_vnode(rootvn); 572 io->cwd = rootvn; 573 574#ifndef USER 575#ifdef DEBUG 576 577 add_debugger_cmd("ioctx", dump_ioctx, "dump a thread ioctx struct"); 578 add_debugger_cmd("vnode", dump_vnode, "dump a vnode struct"); 579 add_debugger_cmd("fdarray", dump_fdarray, "dump an fd array"); 580 add_debugger_cmd("ofile", dump_ofile, "dump an ofile struct"); 581 add_debugger_cmd("nspace", dump_nspace, "dump a nspace struct"); 582 add_debugger_cmd("fsystem", dump_fsystem, "dump a fsystem struct"); 583 add_debugger_cmd("ioinfo", dump_io_info, "dump io info for a thread"); 584 add_debugger_cmd("findvn", find_vn, "find a vnid (in all threads)"); 585 586#endif /* DEBUG */ 587#endif /* USER*/ 588 589 return 0; 590} 591 592 593/* ---------------------------------------------------------------- */ 594 595int 596sys_sync(void) 597{ 598 nspace *ns; 599 op_sync *op; 600 601 LOCK(vnlock); 602 for(ns = nshead; ns; ns = ns->next) { 603 ns->root->rcnt++; 604 UNLOCK(vnlock); 605 op = ns->fs->ops.sync; 606 if (op) 607 (*op)(ns->data); 608 LOCK(vnlock); 609 ns->root->rcnt--; 610 } 611 UNLOCK(vnlock); 612 return 0; 613} 614 615static ioctx * 616get_cur_ioctx(void) 617{ 618 static int init = 0; 619 static ioctx io; 620 621 if (init == 0) { 622 int error; 623 memset(&io, 0, sizeof(io)); 624 625 error = new_lock(&io.lock, "IO context"); 626 if (error < 0) 627 PANIC("Failed to init IO context lock: %s\n", fs_strerror(error)); 628 629 init = 1; 630 } 631 632 return &io; 633} 634 635 636/* 637 * sys_chdir 638 */ 639 640int 641sys_chdir(int kernel, int fd, const char *path) 642{ 643 int err; 644 ioctx *io; 645 vnode *vn; 646 op_rstat *op; 647 struct my_stat st; 648 649 err = get_file_fd(kernel, fd, path, TRUE, &vn); 650 if (err) 651 goto error1; 652 op = vn->ns->fs->ops.rstat; 653 if (!op) { 654 err = FS_EINVAL; 655 goto error2; 656 } 657 err = (*op)(vn->ns->data, vn->data, &st); 658 if (err) 659 goto error2; 660 if (!MY_S_ISDIR(st.mode)) { 661 err = FS_ENOTDIR; 662 goto error2; 663 } 664 io = get_cur_ioctx(); 665 LOCK(io->lock); 666 dec_vnode(io->cwd, FALSE); 667 io->cwd = vn; 668 UNLOCK(io->lock); 669 670 return 0; 671 672error2: 673 dec_vnode(vn, FALSE); 674error1: 675 return err; 676} 677 678 679/* 680 * sys_access 681 */ 682 683int 684sys_access(int kernel, int fd, const char *path, int mode) 685{ 686 int err; 687 vnode *vn; 688 op_access *op; 689 690 err = get_file_fd(kernel, fd, path, TRUE, &vn); 691 if (err) 692 goto error1; 693 op = vn->ns->fs->ops.access; 694 if (!op) { 695 err = FS_EINVAL; 696 goto error2; 697 } 698 err = (*op)(vn->ns->data, vn->data, mode); 699 if (err) 700 goto error2; 701 dec_vnode(vn, FALSE); 702 return 0; 703 704error2: 705 dec_vnode(vn, FALSE); 706error1: 707 return err; 708} 709 710/* 711 * sys_symlink 712 */ 713 714int 715sys_symlink(int kernel, const char *oldpath, int nfd, const char *newpath) 716{ 717 int err; 718 char filename[FILE_NAME_LENGTH]; 719 char *buf; 720 vnode *dvn; 721 op_symlink *op; 722 723 err = get_dir_fd(kernel, nfd, newpath, filename, &dvn); 724 if (err) 725 goto error1; 726 err = new_path(oldpath, &buf); 727 if (err) 728 goto error2; 729 op = dvn->ns->fs->ops.symlink; 730 if (!op) { 731 err = FS_EINVAL; 732 goto error3; 733 } 734 err = (*op)(dvn->ns->data, dvn->data, filename, buf); 735 if (err) 736 goto error3; 737 738 dec_vnode(dvn, FALSE); 739 free_path(buf); 740 741 return 0; 742 743error3: 744 free_path(buf); 745error2: 746 dec_vnode(dvn, FALSE); 747error1: 748 return err; 749} 750 751/* 752 * sys_readlink 753 */ 754 755ssize_t 756sys_readlink(int kernel, int fd, const char *path, char *buf, size_t bufsize) 757{ 758 int err; 759 vnode *vn; 760 op_readlink *op; 761 size_t sz; 762 763 err = get_file_fd(kernel, fd, path, FALSE, &vn); 764 if (err) 765 goto error1; 766 op = vn->ns->fs->ops.readlink; 767 if (!op) { 768 err = FS_EINVAL; 769 goto error2; 770 } 771 sz = bufsize; 772 err = (*op)(vn->ns->data, vn->data, buf, &sz); 773 if (err) 774 goto error2; 775 dec_vnode(vn, FALSE); 776 777 return sz; 778 779error2: 780 dec_vnode(vn, FALSE); 781error1: 782 return err; 783} 784 785/* 786 * sys_mkdir 787 */ 788 789int 790sys_mkdir(int kernel, int fd, const char *path, int perms) 791{ 792 int err; 793 char filename[FILE_NAME_LENGTH]; 794 vnode *dvn; 795 op_mkdir *op; 796 797 err = get_dir_fd(kernel, fd, path, filename, &dvn); 798 if (err) 799 goto error1; 800 op = dvn->ns->fs->ops.mkdir; 801 if (!op) { 802 err = FS_EINVAL; 803 goto error2; 804 } 805 err = (*op)(dvn->ns->data, dvn->data, filename, perms); 806 if (err) 807 goto error2; 808 809 dec_vnode(dvn, FALSE); 810 811 return 0; 812 813error2: 814 dec_vnode(dvn, FALSE); 815error1: 816 return err; 817} 818 819 820/* 821 * opendir. 822 */ 823 824int 825sys_opendir(int kernel, int fd, const char *path, int coe) 826{ 827 int err; 828 op_opendir *op; 829 op_free_cookie *opf; 830 ofile *f; 831 int nfd; 832 vnode *vn; 833 void *cookie; 834 835 err = get_file_fd(kernel, fd, path, TRUE, &vn); 836 if (err) 837 goto error1; 838 op = vn->ns->fs->ops.opendir; 839 if (!op) { 840 err = FS_EINVAL; 841 goto error2; 842 } 843 err = (*op)(vn->ns->data, vn->data, &cookie); 844 if (err) 845 goto error2; 846 847 /* 848 find a file descriptor 849 */ 850 851 f = (ofile *) calloc(sizeof(ofile), 1); 852 if (!f) { 853 err = FS_ENOMEM; 854 goto error3; 855 } 856 857 f->type = FD_DIR; 858 f->vn = vn; 859 f->cookie = cookie; 860 f->rcnt = 0; 861 f->ocnt = 0; 862 863 nfd = new_fd(kernel, -1, f, -1, coe); 864 if (nfd < 0) { 865 err = FS_EMFILE; 866 goto error4; 867 } 868 869 return nfd; 870 871error4: 872 free(f); 873error3: 874 (*vn->ns->fs->ops.closedir)(vn->ns->data, vn->data, cookie); 875 opf = vn->ns->fs->ops.free_dircookie; 876 if (opf) 877 (*opf)(vn->ns->data, vn->data, cookie); 878error2: 879 dec_vnode(vn, FALSE); 880error1: 881 if (err > 0) /* XXXdbg -- a hack for linux */ 882 err = -err; 883 884 return err; 885} 886 887 888/* 889 * closedir 890 */ 891 892int 893sys_closedir(int kernel, int fd) 894{ 895 return remove_fd(kernel, fd, FD_DIR | FD_ATTR_DIR); 896} 897 898/* 899 * readdir. 900 */ 901 902int 903sys_readdir(int kernel, int fd, struct my_dirent *buf, size_t bufsize, 904 long count) 905{ 906 ofile *f; 907 int err; 908 vnode *vn; 909 struct my_dirent *p; 910 struct my_stat st; 911 long i; 912 nspace_id nsid; 913 vnode_id vnid; 914 long nm; 915 916 f = get_fd(kernel, fd, FD_DIR | FD_ATTR_DIR); 917 if (!f) { 918 err = FS_EBADF; 919 goto error1; 920 } 921 vn = f->vn; 922 nm = count; 923 if (f->type == FD_DIR) { 924 err = (*vn->ns->fs->ops.readdir)(vn->ns->data, vn->data, f->cookie, 925 &nm, buf, bufsize); 926 } else { 927 err = (*vn->ns->fs->ops.read_attrdir)(vn->ns->data, vn->data, f->cookie, 928 &nm, buf, bufsize); 929 } 930 if (err) 931 goto error1; 932 933 934 // set d_pdev and d_pino 935 buf->d_pdev = vn->ns->nsid; 936 buf->d_pino = vn->vnid; 937 938 /* 939 patch the mount points and the root. 940 */ 941 942 if (f->type == FD_DIR) { 943 LOCK(vnlock); 944 nsid = vn->ns->nsid; 945 p = buf; 946 for(i=0; i<nm; i++) { 947 if (is_mount_vnid(nsid, p->d_ino, &vnid)) 948 p->d_ino = vnid; 949 if (vn->ns->mount && !strcmp(p->d_name, "..")) { 950 UNLOCK(vnlock); 951 err = sys_rstat(kernel, fd, "..", &st, FALSE); 952 if (err) 953 goto error2; 954 LOCK(vnlock); 955 p->d_ino = st.ino; 956 } 957 p = (struct my_dirent *) ((char *) p + p->d_reclen); 958 } 959 UNLOCK(vnlock); 960 } 961 962 put_fd(f); 963 return nm; 964 965error2: 966 put_fd(f); 967error1: 968 return err; 969} 970 971 972/* 973 * rewinddir 974 */ 975 976int 977sys_rewinddir(int kernel, int fd) 978{ 979 ofile *f; 980 int err; 981 vnode *vn; 982 983 f = get_fd(kernel, fd, FD_DIR | FD_ATTR_DIR); 984 if (!f) 985 return FS_EBADF; 986 vn = f->vn; 987 if (f->type == FD_DIR) { 988 err = (*vn->ns->fs->ops.rewinddir)(vn->ns->data, vn->data, f->cookie); 989 } else { 990 err = (*vn->ns->fs->ops.rewind_attrdir)(vn->ns->data, vn->data, 991 f->cookie); 992 } 993 put_fd(f); 994 return err; 995} 996 997 998/* 999 * open/create files. 1000 */ 1001 1002int 1003sys_open(int kernel, int fd, const char *path, int omode, int perms, 1004 int coe) 1005{ 1006 int err; 1007 char filename[FILE_NAME_LENGTH]; 1008 vnode *vn, *dvn; 1009 vnode_id vnid; 1010 void *cookie; 1011 ofile *f; 1012 int nfd; 1013 op_create *opc; 1014 op_open *opo; 1015 op_free_cookie *opf; 1016 1017 if (omode & MY_O_CREAT) { 1018 err = get_dir_fd(kernel, fd, path, filename, &dvn); 1019 if (err) 1020 goto errorA; 1021 opc = dvn->ns->fs->ops.create; 1022 if (!opc) { 1023 err = FS_EINVAL; 1024 goto errorB; 1025 } 1026 err = (*opc)(dvn->ns->data, dvn->data, filename, omode, perms, &vnid, 1027 &cookie); 1028 if (err) 1029 goto errorB; 1030 LOCK(vnlock); 1031 vn = lookup_vnode(dvn->ns->nsid, vnid); 1032 UNLOCK(vnlock); 1033 1034 dec_vnode(dvn, FALSE); 1035 } else { 1036 err = get_file_fd(kernel, fd, path, !(omode & MY_O_NOTRAVERSE), &vn); 1037 if (err) 1038 goto error1; 1039 opo = vn->ns->fs->ops.open; 1040 if (!opo) { 1041 err = FS_EINVAL; 1042 goto error2; 1043 } 1044 err = (*opo)(vn->ns->data, vn->data, omode, &cookie); 1045 if (err) 1046 goto error2; 1047 } 1048 1049 /* 1050 find a file descriptor 1051 */ 1052 1053 f = (ofile *) calloc(sizeof(ofile), 1); 1054 if (!f) { 1055 err = FS_ENOMEM; 1056 goto error3; 1057 } 1058 1059 f->type = FD_FILE; 1060 f->vn = vn; 1061 f->cookie = cookie; 1062 f->ocnt = 0; 1063 f->rcnt = 0; 1064 f->pos = 0; 1065 f->omode = omode; 1066 1067 nfd = new_fd(kernel, -1, f, -1, coe); 1068 if (nfd < 0) { 1069 err = FS_EMFILE; 1070 goto error4; 1071 } 1072 1073 return nfd; 1074 1075error4: 1076 free(f); 1077error3: 1078 (*vn->ns->fs->ops.close)(vn->ns->data, vn->data, cookie); 1079 opf = vn->ns->fs->ops.free_cookie; 1080 if (opf) 1081 (*opf)(vn->ns->data, vn->data, cookie); 1082 if (omode & MY_O_CREAT) 1083 goto errorC; 1084error2: 1085 dec_vnode(vn, FALSE); 1086error1: 1087 return err; 1088 1089errorC: 1090 (*vn->ns->fs->ops.unlink)(dvn->ns->data, dvn->data, filename); 1091 dec_vnode(vn, FALSE); 1092errorB: 1093 dec_vnode(dvn, FALSE); 1094errorA: 1095 if (err > 0) /* XXXdbg -- a hack for linux */ 1096 err = -err; 1097 1098 return err; 1099} 1100 1101 1102int 1103sys_open_entry_ref(int kernel, nspace_id device, vnode_id parent, const char *name, 1104 int openMode, int coe) 1105{ 1106 int err; 1107 vnode *vn; 1108 void *cookie; 1109 ofile *f; 1110 int nfd; 1111 op_open *opo; 1112 op_free_cookie *opf; 1113 1114 err = get_file_vn(device, parent, name, TRUE, &vn); 1115 if (err) 1116 return err; 1117 1118 opo = vn->ns->fs->ops.open; 1119 if (!opo) { 1120 err = FS_EINVAL; 1121 goto error1; 1122 } 1123 err = (*opo)(vn->ns->data, vn->data, openMode, &cookie); 1124 if (err) 1125 goto error1; 1126 1127 /* 1128 * find a file descriptor 1129 */ 1130 1131 f = (ofile *)calloc(sizeof(ofile), 1); 1132 if (!f) { 1133 err = FS_ENOMEM; 1134 goto error2; 1135 } 1136 1137 f->type = FD_FILE; 1138 f->vn = vn; 1139 f->cookie = cookie; 1140 f->ocnt = 0; 1141 f->rcnt = 0; 1142 f->pos = 0; 1143 f->omode = openMode; 1144 1145 nfd = new_fd(kernel, -1, f, -1, coe); 1146 if (nfd < 0) { 1147 err = FS_EMFILE; 1148 goto error3; 1149 } 1150 1151 return nfd; 1152 1153error3: 1154 free(f); 1155error2: 1156 (*vn->ns->fs->ops.close)(vn->ns->data, vn->data, cookie); 1157 opf = vn->ns->fs->ops.free_cookie; 1158 if (opf) 1159 (*opf)(vn->ns->data, vn->data, cookie); 1160 1161error1: 1162 dec_vnode(vn, FALSE); 1163 return err; 1164} 1165 1166 1167/* 1168 * sys_close 1169 */ 1170 1171int 1172sys_close(int kernel, int fd) 1173{ 1174 return remove_fd(kernel, fd, FD_FILE); 1175} 1176 1177 1178/* 1179 * sys_lseek 1180 */ 1181 1182fs_off_t 1183sys_lseek(int kernel, int fd, fs_off_t pos, int whence) 1184{ 1185 ofile *f; 1186 int err; 1187 struct my_stat st; 1188 vnode *vn; 1189 op_rstat *op; 1190 1191 f = get_fd(kernel, fd, FD_FILE); 1192 if (!f) { 1193 err = FS_EBADF; 1194 goto error1; 1195 } 1196 switch(whence) { 1197 case MY_SEEK_SET: 1198 f->pos = pos; 1199 break; 1200 case MY_SEEK_CUR: 1201 if ((f->omode & MY_O_APPEND) == 0) 1202 f->pos += pos; 1203 else { /* we're in append mode so ask where the EOF is */ 1204 vn = f->vn; 1205 op = vn->ns->fs->ops.rstat; 1206 if (!op) { 1207 err = FS_EINVAL; 1208 goto error2; 1209 } 1210 err = (*op)(vn->ns->data, vn->data, &st); 1211 if (err) 1212 goto error2; 1213 pos += st.size; 1214 f->pos = pos; 1215 break; 1216 } 1217 break; 1218 case MY_SEEK_END: 1219 vn = f->vn; 1220 op = vn->ns->fs->ops.rstat; 1221 if (!op) { 1222 err = FS_EINVAL; 1223 goto error2; 1224 } 1225 err = (*op)(vn->ns->data, vn->data, &st); 1226 if (err) 1227 goto error2; 1228 pos += st.size; 1229 f->pos = pos; 1230 break; 1231 default: 1232 put_fd(f); 1233 return FS_EINVAL; 1234 } 1235 1236 if (f->pos < 0) { 1237 f->pos = 0; 1238 err = FS_EINVAL; 1239 goto error2; 1240 } 1241 1242 pos = f->pos; 1243 put_fd(f); 1244 return pos; 1245 1246error2: 1247 put_fd(f); 1248error1: 1249 return err; 1250} 1251 1252 1253/* 1254 * sys_read 1255 */ 1256 1257 1258ssize_t 1259sys_read(int kernel, int fd, void *buf, size_t len) 1260{ 1261 ofile *f; 1262 int err; 1263 vnode *vn; 1264 size_t sz; 1265 1266 1267 f = get_fd(kernel, fd, FD_FILE); 1268 if (!f) { 1269 err = FS_EBADF; 1270 goto error1; 1271 } 1272 if ((f->omode & OMODE_MASK) == MY_O_WRONLY) { 1273 err = FS_EBADF; 1274 goto error2; 1275 } 1276 vn = f->vn; 1277 sz = len; 1278 err = (*vn->ns->fs->ops.read)(vn->ns->data, vn->data, f->cookie, f->pos, 1279 buf, &sz); 1280 if (err) 1281 goto error2; 1282 1283 /* 1284 the update of f->pos is not protected. does it matter? 1285 simultaneous I/Os on the same file are unpredictable anyway. 1286 */ 1287 1288 f->pos += sz; 1289 1290 put_fd(f); 1291 1292 return sz; 1293 1294error2: 1295 put_fd(f); 1296error1: 1297 return err; 1298} 1299 1300 1301/* 1302 * sys_write 1303 */ 1304 1305ssize_t 1306sys_write(int kernel, int fd, const void *buf, size_t len) 1307{ 1308 ofile *f; 1309 int err; 1310 vnode *vn; 1311 size_t sz; 1312 1313 f = get_fd(kernel, fd, FD_FILE); 1314 if (!f) { 1315 err = FS_EBADF; 1316 goto error1; 1317 } 1318 if ((f->omode & OMODE_MASK) == MY_O_RDONLY) { 1319 err = FS_EBADF; 1320 goto error2; 1321 } 1322 vn = f->vn; 1323 sz = len; 1324 err = (*vn->ns->fs->ops.write)(vn->ns->data, vn->data, f->cookie, f->pos, 1325 buf, &sz); 1326 if (err) 1327 goto error2; 1328 1329 /* 1330 the update of f->pos is not protected. does it matter? 1331 simultaneous I/Os on the same file are unpredictable anyway. 1332 */ 1333 1334 f->pos += sz; 1335 1336 put_fd(f); 1337 return sz; 1338 1339error2: 1340 put_fd(f); 1341error1: 1342 return err; 1343} 1344 1345 1346/* 1347 * sys_ioctl 1348 */ 1349 1350int 1351sys_ioctl(int kernel, int fd, int cmd, void *arg, size_t sz) 1352{ 1353 ofile *f; 1354 int err; 1355 vnode *vn; 1356 op_ioctl *op; 1357 1358 f = get_fd(kernel, fd, FD_FILE); 1359 if (!f) { 1360 err = FS_EBADF; 1361 goto error1; 1362 } 1363 vn = f->vn; 1364 op = vn->ns->fs->ops.ioctl; 1365 if (op) 1366 err = (*op)(vn->ns->data, vn->data, f->cookie, cmd, arg, sz); 1367 else 1368 err = FS_EINVAL; 1369 if (err) 1370 goto error2; 1371 1372 put_fd(f); 1373 return 0; 1374 1375error2: 1376 put_fd(f); 1377error1: 1378 return err; 1379} 1380 1381 1382/* 1383 * sys_link 1384 */ 1385 1386int 1387sys_link(int kernel, int ofd, const char *oldpath, int nfd, 1388 const char *newpath) 1389{ 1390 int err; 1391 vnode *vn, *dvn; 1392 char filename[FILE_NAME_LENGTH]; 1393 op_link *op; 1394 1395 err = get_file_fd(kernel, ofd, oldpath, TRUE, &vn); 1396 if (err) 1397 goto error1; 1398 err = get_dir_fd(kernel, nfd, newpath, filename, &dvn); 1399 if (err) 1400 goto error2; 1401 1402 if (vn->ns != dvn->ns) { 1403 err = FS_EXDEV; 1404 goto error3; 1405 } 1406 op = dvn->ns->fs->ops.link; 1407 if (!op) { 1408 err = FS_EINVAL; 1409 goto error3; 1410 } 1411 err = (*op)(dvn->ns->data, dvn->data, filename, vn->data); 1412 if (err) 1413 goto error3; 1414 1415 dec_vnode(dvn, FALSE); 1416 dec_vnode(vn, FALSE); 1417 return 0; 1418 1419error3: 1420 dec_vnode(dvn, FALSE); 1421error2: 1422 dec_vnode(vn, FALSE); 1423error1: 1424 return err; 1425} 1426 1427/* 1428 * sys_unlink 1429 */ 1430 1431int 1432sys_unlink(int kernel, int fd, const char *path) 1433{ 1434 int err; 1435 vnode *dvn; 1436 char filename[FILE_NAME_LENGTH]; 1437 op_unlink *op; 1438 1439 err = get_dir_fd(kernel, fd, path, filename, &dvn); 1440 if (err) 1441 goto error1; 1442 1443 op = dvn->ns->fs->ops.unlink; 1444 if (!op) { 1445 err = FS_EINVAL; 1446 goto error2; 1447 } 1448 err = (*op)(dvn->ns->data, dvn->data, filename); 1449 if (err) 1450 goto error2; 1451 1452 dec_vnode(dvn, FALSE); 1453 return 0; 1454 1455error2: 1456 dec_vnode(dvn, FALSE); 1457error1: 1458 return err; 1459} 1460 1461 1462/* 1463 * sys_rmdir 1464 */ 1465 1466int 1467sys_rmdir(int kernel, int fd, const char *path) 1468{ 1469 int err; 1470 vnode *dvn; 1471 char filename[FILE_NAME_LENGTH]; 1472 op_unlink *op; 1473 1474 err = get_dir_fd(kernel, fd, path, filename, &dvn); 1475 if (err) 1476 goto error1; 1477 1478 op = dvn->ns->fs->ops.rmdir; 1479 if (!op) { 1480 err = FS_EINVAL; 1481 goto error2; 1482 } 1483 err = (*op)(dvn->ns->data, dvn->data, filename); 1484 if (err) 1485 goto error2; 1486 1487 dec_vnode(dvn, FALSE); 1488 return 0; 1489 1490error2: 1491 dec_vnode(dvn, FALSE); 1492error1: 1493 return err; 1494} 1495 1496/* 1497 * sys_rename 1498 */ 1499 1500int 1501sys_rename(int kernel, int ofd, const char *oldpath, 1502 int nfd, const char *newpath) 1503{ 1504 int err; 1505 char newname[FILE_NAME_LENGTH], oldname[FILE_NAME_LENGTH]; 1506 vnode *odvn, *ndvn; 1507 op_rename *op; 1508 1509 err = get_dir_fd(kernel, ofd, oldpath, oldname, &odvn); 1510 if (err) 1511 goto error1; 1512 err = get_dir_fd(kernel, nfd, newpath, newname, &ndvn); 1513 if (err) 1514 goto error2; 1515 1516 if (odvn->ns != ndvn->ns) { 1517 err = FS_EXDEV; 1518 goto error2; 1519 } 1520 1521 op = odvn->ns->fs->ops.rename; 1522 if (!op) { 1523 err = FS_EINVAL; 1524 goto error3; 1525 } 1526 err = (*op)(odvn->ns->data, odvn->data, oldname, ndvn->data, newname); 1527 if (err) 1528 goto error3; 1529 1530 dec_vnode(odvn, FALSE); 1531 dec_vnode(ndvn, FALSE); 1532 1533 return 0; 1534 1535error3: 1536 dec_vnode(ndvn, FALSE); 1537error2: 1538 dec_vnode(odvn, FALSE); 1539error1: 1540 return err; 1541} 1542 1543/* 1544 * sys_rstat 1545 */ 1546 1547int 1548sys_rstat(int kernel, int fd, const char *path, struct my_stat *st, int eatlink) 1549{ 1550 int err; 1551 vnode *vn; 1552 op_rstat *op; 1553 1554 FUNCTION(); 1555 1556 err = get_file_fd(kernel, fd, path, eatlink, &vn); 1557 if (err) 1558 goto error1; 1559 op = vn->ns->fs->ops.rstat; 1560 if (!op) { 1561 err = FS_EINVAL; 1562 goto error2; 1563 } 1564 err = (*op)(vn->ns->data, vn->data, st); 1565 if (err) 1566 goto error2; 1567 dec_vnode(vn, FALSE); 1568 1569 return 0; 1570 1571error2: 1572 dec_vnode(vn, FALSE); 1573error1: 1574 return err; 1575} 1576 1577/* 1578 * sys_wstat 1579 */ 1580 1581int 1582sys_wstat(int kernel, int fd, const char *path, struct my_stat *st, long mask, 1583 int eatlink) 1584{ 1585 int err; 1586 vnode *vn; 1587 op_wstat *op; 1588 1589 err = get_file_fd(kernel, fd, path, eatlink, &vn); 1590 if (err) 1591 goto error1; 1592 op = vn->ns->fs->ops.wstat; 1593 if (!op) { 1594 err = FS_EINVAL; 1595 goto error2; 1596 } 1597 err = (*op)(vn->ns->data, vn->data, st, mask); 1598 if (err) 1599 goto error2; 1600 dec_vnode(vn, FALSE); 1601 1602 return 0; 1603 1604error2: 1605 dec_vnode(vn, FALSE); 1606error1: 1607 return err; 1608} 1609 1610 1611void 1612kill_device_vnodes(dev_t id) 1613{ 1614 fsystem *fs; 1615 nspace *ns; 1616 1617 LOCK(vnlock); 1618 1619 ns = nsidtons(id); 1620 1621 if (!ns) { 1622 UNLOCK(vnlock); 1623 return; 1624 } 1625 1626 fs = ns->fs; 1627 1628 while (ns->vnodes.head) { 1629 int err; 1630 1631 struct vnode *vn = ns->vnodes.head; 1632 UNLOCK(vnlock); 1633 err = (*fs->ops.write_vnode)(vn->ns->data, vn->data, FALSE); 1634 LOCK(vnlock); 1635 if (err) 1636 PANIC("ERROR WRITING VNODE!!!\n"); 1637 vn->busy = FALSE; 1638 clear_vnode(vn); 1639 move_vnode(vn, FREE_LIST); 1640 } 1641 1642 UNLOCK(vnlock); 1643} 1644 1645 1646void 1647remove_nspace(nspace *ns) 1648{ 1649 fsystem *fs = ns->fs; 1650 vnode *vn; 1651 1652 ns->shutdown = TRUE; 1653 for (vn = ns->vnodes.head; vn; vn = vn->nspace.next) 1654 vn->busy = TRUE; 1655 1656 while (ns->vnodes.head) { 1657 int err; 1658 1659 vn = ns->vnodes.head; 1660 UNLOCK(vnlock); 1661 err = (*fs->ops.write_vnode)(vn->ns->data, vn->data, FALSE); 1662 LOCK(vnlock); 1663 if (err) 1664 PANIC("ERROR WRITING VNODE!!!\n"); 1665 vn->busy = FALSE; 1666 clear_vnode(vn); 1667 move_vnode(vn, FREE_LIST); 1668 } 1669 1670 nstab[ns->nsid % nns] = NULL; 1671 1672 if (ns->prev) 1673 ns->prev->next = ns->next; 1674 else 1675 nshead = ns->next; 1676 if (ns->next) 1677 ns->next->prev = ns->prev; 1678} 1679 1680 1681status_t 1682add_nspace(nspace *ns, fsystem *fs, const char *fileSystem, dev_t dev, ino_t ino) 1683{ 1684 int i; 1685 1686 if (fileSystem != NULL) 1687 fs = inc_file_system(fileSystem); 1688 if (!fs) 1689 return FS_ENODEV; 1690 1691 for (i = 0; i < nns; i++, nxnsid++) { 1692 if (!nstab[nxnsid % nns]) { 1693 nstab[nxnsid % nns] = ns; 1694 ns->nsid = nxnsid; 1695 nxnsid++; 1696 break; 1697 } 1698 } 1699 if (i == nns) { 1700 dec_file_system(fs); 1701 return FS_EMFILE; 1702 } 1703 1704 nstab[ns->nsid % nns] = ns; 1705 ns->fs = fs; 1706 ns->vnodes.head = ns->vnodes.tail = NULL; 1707 ns->data = NULL; 1708 ns->root = NULL; 1709 ns->mount = NULL; 1710 ns->prev = NULL; 1711 ns->next = nshead; 1712 ns->shutdown = FALSE; 1713 ns->dev = dev; 1714 ns->ino = ino; 1715 1716 if (nshead) 1717 nshead->prev = ns; 1718 nshead = ns; 1719 1720 return FS_OK; 1721} 1722 1723 1724int 1725sys_open_attr_dir(int kernel, int fd, const char *path) 1726{ 1727 int err; 1728 op_open_attrdir *op; 1729 op_free_cookie *opf; 1730 ofile *f; 1731 int nfd; 1732 vnode *vn; 1733 void *cookie; 1734 1735 err = get_file_fd(kernel, fd, path, TRUE, &vn); 1736 if (err) 1737 goto error1; 1738 op = vn->ns->fs->ops.open_attrdir; 1739 if (!op) { 1740 err = FS_EINVAL; 1741 goto error2; 1742 } 1743 err = (*op)(vn->ns->data, vn->data, &cookie); 1744 if (err) 1745 goto error2; 1746 1747 /* 1748 find a file descriptor 1749 */ 1750 1751 f = (ofile *) calloc(sizeof(ofile), 1); 1752 if (!f) { 1753 err = FS_ENOMEM; 1754 goto error3; 1755 } 1756 1757 f->type = FD_ATTR_DIR; 1758 f->vn = vn; 1759 f->cookie = cookie; 1760 f->rcnt = 0; 1761 f->ocnt = 0; 1762 1763 nfd = new_fd(kernel, -1, f, -1, TRUE); 1764 if (nfd < 0) { 1765 err = FS_EMFILE; 1766 goto error4; 1767 } 1768 1769 return nfd; 1770 1771error4: 1772 free(f); 1773error3: 1774 (*vn->ns->fs->ops.close_attrdir)(vn->ns->data, vn->data, cookie); 1775 opf = vn->ns->fs->ops.free_attrdircookie; 1776 if (opf) 1777 (*opf)(vn->ns->data, vn->data, cookie); 1778error2: 1779 dec_vnode(vn, FALSE); 1780error1: 1781 return err; 1782} 1783 1784 1785ssize_t 1786sys_read_attr(int kernel, int fd, const char *name, int type, void *buffer, size_t len, off_t pos) 1787{ 1788 ofile *f; 1789 int err; 1790 vnode *vn; 1791 size_t sz; 1792 1793 f = get_fd(kernel, fd, FD_FILE); 1794 if (!f) { 1795 err = FS_EBADF; 1796 goto error1; 1797 } 1798 1799 vn = f->vn; 1800 sz = len; 1801 err = (*vn->ns->fs->ops.read_attr)(vn->ns->data, vn->data, name, type, buffer, &sz, pos); 1802 if (err) 1803 goto error2; 1804 1805 put_fd(f); 1806 1807 return sz; 1808 1809error2: 1810 put_fd(f); 1811error1: 1812 return err; 1813} 1814 1815 1816ssize_t 1817sys_write_attr(int kernel, int fd, const char *name,int type, 1818 const void *buffer, size_t len, off_t pos) 1819{ 1820 ofile *f; 1821 int err; 1822 vnode *vn; 1823 size_t sz; 1824 1825 f = get_fd(kernel, fd, FD_FILE); 1826 if (!f) { 1827 err = FS_EBADF; 1828 goto error1; 1829 } 1830 1831 vn = f->vn; 1832 sz = len; 1833 err = (*vn->ns->fs->ops.write_attr)(vn->ns->data, vn->data, name, type, buffer, &sz, pos); 1834 if (err) 1835 goto error2; 1836 1837 put_fd(f); 1838 return sz; 1839 1840error2: 1841 put_fd(f); 1842error1: 1843 return err; 1844} 1845 1846 1847ssize_t 1848sys_remove_attr(int kernel, int fd, const char *name) 1849{ 1850 ofile *f; 1851 int err; 1852 vnode *vn; 1853 1854 f = get_fd(kernel, fd, FD_FILE); 1855 if (!f) { 1856 err = FS_EBADF; 1857 goto error1; 1858 } 1859 1860 vn = f->vn; 1861 err = (*vn->ns->fs->ops.remove_attr)(vn->ns->data, vn->data, name); 1862 if (err) 1863 goto error2; 1864 1865 put_fd(f); 1866 1867 return 0; 1868 1869error2: 1870 put_fd(f); 1871error1: 1872 return err; 1873} 1874 1875 1876int 1877sys_stat_attr(int kernel, int fd, const char *path, const char *name, 1878 my_attr_info *info) 1879{ 1880 int err; 1881 vnode *vn; 1882 op_stat_attr *op; 1883 1884 err = get_file_fd(kernel, fd, path, TRUE, &vn); 1885 if (err) 1886 goto error1; 1887 op = vn->ns->fs->ops.stat_attr; 1888 if (!op) { 1889 err = FS_EINVAL; 1890 goto error2; 1891 } 1892 err = (*op)(vn->ns->data, vn->data, name, info); 1893 if (err) 1894 goto error2; 1895 dec_vnode(vn, FALSE); 1896 1897 return 0; 1898 1899error2: 1900 dec_vnode(vn, FALSE); 1901error1: 1902 return err; 1903} 1904 1905 1906/* 1907 * sys_mount 1908 */ 1909 1910void * 1911sys_mount(int kernel, const char *filesystem, int fd, const char *where, 1912 const char *device, ulong flags, void *parms, size_t len) 1913{ 1914 int err; 1915 vnode_id vnid; 1916 vnode *mount; 1917 fsystem *fs; 1918 nspace *ns, *ans; 1919 void *data; 1920 struct stat st; 1921 struct my_stat mst; 1922 my_dev_t dev; 1923 my_ino_t ino; 1924 1925 dev = -1; 1926 ino = -1; 1927 if (device) { 1928 err = stat(device, &st); 1929 if (err) 1930 return NULL; 1931 dev = st.st_dev; 1932 ino = st.st_ino; 1933 } 1934 1935 err = get_file_fd(TRUE, fd, where, TRUE, &mount); 1936 if (err) 1937 goto error1; 1938 1939 err = (*mount->ns->fs->ops.rstat)(mount->ns->data, mount->data, &mst); 1940 if (err) 1941 goto error2; 1942 if (!MY_S_ISDIR(mst.mode)) { 1943 err = FS_ENOTDIR; 1944 goto error2; 1945 } 1946 1947 ns = (nspace *)malloc(sizeof(nspace)); 1948 if (!ns) { 1949 err = FS_ENOMEM; 1950 goto error2; 1951 } 1952 1953 fs = inc_file_system(filesystem); 1954 if (!fs) { 1955 err = FS_ENODEV; 1956 goto error3; 1957 } 1958 1959 LOCK(vnlock); 1960 1961 if (device) { 1962 for(ans=nshead; ans; ans=ans->next) 1963 if ((ans->dev == dev) && (ans->ino == ino)) { 1964 UNLOCK(vnlock); 1965 printf("KERNEL: trying to mount %s twice (already mounted as %s)\n", 1966 device, ans->fs->name); 1967 err = FS_ENODEV; 1968 goto error4; 1969 } 1970 } 1971 1972 err = add_nspace(ns, fs, NULL, dev, ino); 1973 1974 UNLOCK(vnlock); 1975 1976 if (err != FS_OK) 1977 goto error5; 1978 1979 err = (*fs->ops.mount)(ns->nsid, device, flags, parms, len, &data, &vnid); 1980 if (err) 1981 goto error5; 1982 1983 LOCK(vnlock); 1984 ns->root = lookup_vnode(ns->nsid, vnid); 1985 ns->data = data; 1986 1987 if ((mount == rootvn) || (mount->mounted)) { 1988 err = FS_EBUSY; 1989 goto error6; 1990 } 1991 mount->mounted = ns; 1992 ns->mount = mount; 1993 1994 UNLOCK(vnlock); 1995 1996 return data; 1997 1998error6: 1999 dec_vnode(ns->root, FALSE); 2000 (*fs->ops.unmount)(data); 2001error5: 2002 LOCK(vnlock); 2003 remove_nspace(ns); 2004 UNLOCK(vnlock); 2005error4: 2006error3: 2007 free(ns); 2008error2: 2009 dec_vnode(mount, FALSE); 2010error1: 2011 errno = err; 2012 return NULL; 2013} 2014 2015 2016/* 2017 * sys_unmount 2018 */ 2019 2020int 2021sys_unmount(int kernel, int fd, const char *where) 2022{ 2023 int err; 2024 nspace *ns; 2025 fsystem *fs; 2026 vnode *root, *vn, *mount; 2027 2028 err = get_file_fd(TRUE, fd, where, TRUE, &root); 2029 if (err) 2030 goto error1; 2031 2032 LOCK(vnlock); 2033 2034 ns = root->ns; 2035 fs = ns->fs; 2036 if (ns->root != root) { 2037 err = FS_EINVAL; 2038 goto error2; 2039 } 2040 2041 2042 /* 2043 don't allow to unmount the root file system 2044 */ 2045 2046 if (root == rootvn) { 2047 err = FS_EBUSY; 2048 goto error2; 2049 } 2050 2051 /* 2052 decrement twice root: one for the mount, one for the get_file. 2053 */ 2054 2055 root->rcnt -= 2; 2056 2057 for(vn = ns->vnodes.head; vn; vn = vn->nspace.next) 2058 if (vn->busy || (vn->rcnt != 0)) { 2059 err = FS_EBUSY; 2060 goto error3; 2061 } 2062 2063 mount = ns->mount; 2064 mount->mounted = NULL; 2065 2066 remove_nspace(ns); 2067 UNLOCK(vnlock); 2068 2069 (*fs->ops.unmount)(ns->data); 2070 2071 free(ns); 2072 2073 dec_file_system(fs); 2074 dec_vnode(mount, FALSE); 2075 2076 return 0; 2077 2078error3: 2079 root->rcnt++; 2080error2: 2081 UNLOCK(vnlock); 2082error1: 2083 return err; 2084} 2085 2086 2087int 2088sys_write_fs_info(int kernel, dev_t device, struct fs_info *info, int mask) 2089{ 2090 int status = FS_EINVAL; 2091 fsystem *fs = NULL; 2092 vnode *root = NULL; 2093 nspace *ns; 2094 2095 LOCK(vnlock); 2096 ns = nsidtons(device); 2097 if (ns != NULL) { 2098 fs = ns->fs; 2099 if (fs->ops.wfsstat != NULL) { 2100 status = FS_OK; 2101 root = ns->root; 2102 root->rcnt++; 2103 } 2104 } 2105 UNLOCK(vnlock); 2106 2107 if (status == FS_OK) { 2108 status = (*fs->ops.wfsstat)(ns->data, info, mask); 2109 dec_vnode(root, FALSE); 2110 } 2111 2112 return status; 2113} 2114 2115 2116int 2117sys_mkindex(int kernel, dev_t device, const char *index, int type, int flags) 2118{ 2119 int status = FS_EINVAL; 2120 fsystem *fs = NULL; 2121 vnode *root = NULL; 2122 nspace *ns; 2123 2124 LOCK(vnlock); 2125 ns = nsidtons(device); 2126 if (ns != NULL) { 2127 fs = ns->fs; 2128 if (fs->ops.create_index != NULL) { 2129 status = FS_OK; 2130 root = ns->root; 2131 root->rcnt++; 2132 } 2133 } 2134 UNLOCK(vnlock); 2135 2136 if (status == FS_OK) { 2137 status = (*fs->ops.create_index)(ns->data, index, type, flags); 2138 dec_vnode(root, FALSE); 2139 } 2140 2141 TRACE("sys_mkindex() -- end: %d\n", status); 2142 return status; 2143} 2144 2145 2146int 2147sys_open_query(int kernel, int fd, const char *path, const char *query, ulong flags, port_id port, ulong token, void **cookie) 2148{ 2149 int err; 2150 nspace *ns; 2151 fsystem *fs; 2152 vnode *root; 2153 2154 TRACE("sys_open_query() -- start\n"); 2155 err = get_file_fd(TRUE, fd, path, TRUE, &root); 2156 if (err) 2157 return err; 2158 2159 ns = root->ns; 2160 fs = ns->fs; 2161 if (ns->root != root) 2162 return FS_EINVAL; 2163 2164 if (fs->ops.open_query == NULL) { 2165 dec_vnode(root, FALSE); 2166 return FS_EPERM; 2167 } 2168 err = (*fs->ops.open_query)(ns->data, query, flags, port, token, cookie); 2169 TRACE("sys_open_query() -- end: %d\n",err); 2170 dec_vnode(root, FALSE); 2171 2172 return err; 2173} 2174 2175 2176int 2177sys_close_query(int kernel, int fd, const char *path, void *cookie) 2178{ 2179 int err; 2180 nspace *ns; 2181 fsystem *fs; 2182 vnode *root; 2183 2184 err = get_file_fd(TRUE, fd, path, TRUE, &root); 2185 if (err) 2186 return err; 2187 2188 ns = root->ns; 2189 fs = ns->fs; 2190 if (ns->root != root) 2191 return FS_EINVAL; 2192 2193 if (fs->ops.close_query == NULL) { 2194 dec_vnode(root, FALSE); 2195 return FS_EPERM; 2196 } 2197 2198 err = (*fs->ops.close_query)(ns->data, cookie); 2199 (*fs->ops.free_querycookie)(ns->data, NULL, cookie); 2200 2201 dec_vnode(root, FALSE); 2202 2203 return err; 2204} 2205 2206 2207int 2208sys_read_query(int kernel, int fd, const char *path, void *cookie,struct my_dirent *dent,size_t bufferSize,long count) 2209{ 2210 int err; 2211 nspace *ns; 2212 fsystem *fs; 2213 vnode *root; 2214 long num; 2215 2216 err = get_file_fd(TRUE, fd, path, TRUE, &root); 2217 if (err) 2218 return err; 2219 2220 ns = root->ns; 2221 fs = ns->fs; 2222 if (ns->root != root) 2223 return FS_EINVAL; 2224 2225 if (fs->ops.close_query == NULL) { 2226 dec_vnode(root, FALSE); 2227 return FS_EPERM; 2228 } 2229 2230 num = count; 2231 err = (*fs->ops.read_query)(ns->data, cookie, &num, dent, bufferSize); 2232 2233 dec_vnode(root, FALSE); 2234 2235 if (err == 0) 2236 return num; 2237 2238 return err; 2239} 2240 2241/* 2242 * get_dir and get_file: basic functions to parse a path and get the vnode 2243 * for either the parent directory or the file itself. 2244 */ 2245 2246static int 2247get_dir_fd(int kernel, int fd, const char *path, char *filename, vnode **dvn) 2248{ 2249 int err; 2250 char *p, *np; 2251 2252 err = new_path(path, &p); 2253 if (err) 2254 goto error1; 2255 np = strrchr(p, '/'); 2256 if (!np) { 2257 strcpy(filename, p); 2258 strcpy(p, "."); 2259 } else { 2260 strcpy(filename, np+1); 2261 np[1] = '.'; 2262 np[2] = '\0'; 2263 } 2264 err = parse_path_fd(kernel, fd, &p, TRUE, dvn); 2265 if (err) 2266 goto error2; 2267 free_path(p); 2268 return 0; 2269 2270error2: 2271 free_path(p); 2272error1: 2273 return err; 2274} 2275 2276static int 2277get_file_fd(int kernel, int fd, const char *path, int eatsymlink, vnode **vn) 2278{ 2279 int err; 2280 char *p; 2281 2282 err = new_path(path, &p); 2283 if (err) 2284 goto error1; 2285 err = parse_path_fd(kernel, fd, &p, eatsymlink, vn); 2286 if (err) 2287 goto error2; 2288 free_path(p); 2289 return 0; 2290 2291error2: 2292 free_path(p); 2293error1: 2294 return err; 2295} 2296 2297static int 2298get_file_vn(nspace_id nsid, vnode_id vnid, const char *path, int eatsymlink, 2299 vnode **vn) 2300{ 2301 int err; 2302 char *p; 2303 2304 err = new_path(path, &p); 2305 if (err) 2306 goto error1; 2307 err = parse_path_vn(nsid, vnid, &p, eatsymlink, vn); 2308 if (err) 2309 goto error2; 2310 free_path(p); 2311 return 0; 2312 2313error2: 2314 free_path(p); 2315error1: 2316 return err; 2317} 2318 2319static int 2320parse_path_fd(int kernel, int fd, char **pstart, int eatsymlink, vnode **vnp) 2321{ 2322 vnode *bvn; 2323 ofile *f; 2324 ioctx *io; 2325 char *path; 2326 2327 path = *pstart; 2328 if (path && (*path == '/')) { 2329 do 2330 path++; 2331 while (*path == '/'); 2332 bvn = rootvn; 2333 inc_vnode(bvn); 2334 } else 2335 if (fd >= 0) { 2336 f = get_fd(kernel, fd, FD_ALL); 2337 if (!f) 2338 return FS_EBADF; 2339 bvn = f->vn; 2340 inc_vnode(bvn); 2341 put_fd(f); 2342 } else { 2343 io = get_cur_ioctx(); 2344 LOCK(io->lock); 2345 bvn = io->cwd; 2346 inc_vnode(bvn); 2347 UNLOCK(io->lock); 2348 } 2349 return parse_path(bvn, pstart, path, eatsymlink, vnp); 2350} 2351 2352static int 2353parse_path_vn(nspace_id nsid, vnode_id vnid, char **pstart, int eatsymlink, 2354 vnode **vnp) 2355{ 2356 int err; 2357 vnode *bvn; 2358 char *path; 2359 2360 path = *pstart; 2361 if (path && (*path == '/')) { 2362 do 2363 path++; 2364 while (*path == '/'); 2365 bvn = rootvn; 2366 inc_vnode(bvn); 2367 } else { 2368 err = load_vnode(nsid, vnid, FALSE, &bvn); 2369 if (err) 2370 return err; 2371 } 2372 return parse_path(bvn, pstart, path, eatsymlink, vnp); 2373} 2374 2375 2376static int 2377parse_path(vnode *bvn, char **pstart, char *path, int eatsymlink, vnode **vnp) 2378{ 2379 int err; 2380 int iter; 2381 char *p, *np, *newpath, **fred; 2382 vnode_id vnid; 2383 vnode *vn; 2384 2385 TRACE("parse_path(path = %s)\n", path); 2386 2387 if (!path) { 2388 *vnp = bvn; 2389 return 0; 2390 } 2391 2392 iter = 0; 2393 p = path; 2394 vn = NULL; 2395 2396 while(TRUE) { 2397 2398 /* 2399 exit if we're done 2400 */ 2401 2402 if (*p == '\0') { 2403 err = 0; 2404 break; 2405 } 2406 2407 /* 2408 isolate the next component 2409 */ 2410 2411 np = strchr(p+1, '/'); 2412 if (np) { 2413 *np = '\0'; 2414 do 2415 np++; 2416 while (*np == '/'); 2417 } else 2418 np = strchr(p+1, '\0'); 2419 2420 /* 2421 filter '..' if at the root of a namespace 2422 */ 2423 2424 if (!strcmp(p, "..") && is_root(bvn, &vn)) { 2425 dec_vnode(bvn, FALSE); 2426 bvn = vn; 2427 } 2428 2429 /* 2430 ask the file system to eat this component 2431 */ 2432 2433 newpath = NULL; 2434 fred = &newpath; 2435 if (!eatsymlink && (*np == '\0')) 2436 fred = NULL; 2437 2438 err = (*bvn->ns->fs->ops.walk)(bvn->ns->data, bvn->data, p, fred, 2439 &vnid); 2440 p = np; 2441 if (!err) { 2442 if (newpath) 2443 vn = bvn; 2444 else { 2445 LOCK(vnlock); 2446 vn = lookup_vnode(bvn->ns->nsid, vnid); 2447 UNLOCK(vnlock); 2448 dec_vnode(bvn, FALSE); 2449 } 2450 } else { 2451 dec_vnode(bvn, FALSE); 2452 break; 2453 } 2454 2455 /* 2456 deal with symbolic links 2457 */ 2458 2459 if (newpath) { 2460 2461 /* 2462 protection against cyclic graphs (with bad symbolic links). 2463 */ 2464 2465 iter++; 2466 if (iter > MAX_SYM_LINKS) { 2467 dec_vnode(vn, FALSE); 2468 err = FS_ELOOP; 2469 break; 2470 } 2471 2472 p = cat_paths(newpath, np); 2473 if (!p) { 2474 dec_vnode(vn, FALSE); 2475 err = FS_ENOMEM; 2476 break; 2477 } 2478 free_path(*pstart); 2479 *pstart = p; 2480 if (*p == '/') { 2481 do 2482 p++; 2483 while (*p == '/'); 2484 dec_vnode(vn, FALSE); 2485 bvn = rootvn; 2486 inc_vnode(bvn); 2487 } else 2488 bvn = vn; 2489 continue; 2490 } 2491 2492 /* 2493 reached a mounting point 2494 */ 2495 2496 if (is_mount_vnode(vn, &bvn)) { 2497 dec_vnode(vn, FALSE); 2498 continue; 2499 } 2500 2501 bvn = vn; 2502 } 2503 2504 if (!err) { 2505 TRACE("parse_path() got vnode %Ld\n", bvn->vnid); 2506 *vnp = bvn; 2507 } 2508 2509 return err; 2510} 2511 2512 2513 2514/* 2515 * get_vnode 2516 */ 2517 2518status_t 2519get_vnode(nspace_id nsid, vnode_id vnid, void **data) 2520{ 2521 int err; 2522 vnode *vn; 2523 2524 err = load_vnode(nsid, vnid, TRUE, &vn); 2525 if (err) 2526 return err; 2527 *data = vn->data; 2528 return 0; 2529} 2530 2531 2532/* 2533 * put_vnode 2534 */ 2535 2536status_t 2537put_vnode(nspace_id nsid, vnode_id vnid) 2538{ 2539 vnode *vn; 2540 2541 LOCK(vnlock); 2542 vn = lookup_vnode(nsid, vnid); 2543 if (!vn) { 2544 UNLOCK(vnlock); 2545 return FS_ENOENT; 2546 } 2547 UNLOCK(vnlock); 2548 dec_vnode(vn, TRUE); 2549 return 0; 2550} 2551 2552/* 2553 * new_vnode 2554 */ 2555 2556status_t 2557new_vnode(nspace_id nsid, vnode_id vnid, void *data) 2558{ 2559// int retries = 20; 2560 vnode *vn; 2561 int err; 2562 2563 LOCK(vnlock); 2564 2565restart: 2566 if ((vn = lookup_vnode(nsid, vnid)) != NULL) { 2567 // oh, we requested a new vnode although there already 2568 // exist one - compare the private node data and bail 2569 // out if needed. 2570 2571 if (vn->busy) { 2572 TRACE("new_vnode(): vnode exists and is busy!\n"); 2573 UNLOCK(vnlock); 2574 snooze(5000); 2575 LOCK(vnlock); 2576 2577// if (retries-- >= 0) 2578 goto restart; 2579 2580// printf("new_vnode(): still busy, but continue to our doom!\n"); 2581 } 2582 2583 if (vn->data != data) 2584 PANIC("new_vnode(): vnode already exists with different data (vnode id = %Ld)!\n", vnid); 2585 else { 2586 printf("new_vnode(): vnode already exists with the same data (vnode id = %Ld)\n", vnid); 2587 vn->rcnt++; 2588 UNLOCK(vnlock); 2589 return 0; 2590 } 2591 } 2592 2593 vn = steal_vnode(FREE_LIST); 2594 if (!vn) { 2595 vn = steal_vnode(USED_LIST); 2596 if (!vn) { 2597 PANIC("OUT OF VNODE!!!\n"); 2598 UNLOCK(vnlock); 2599 return FS_ENOMEM; 2600 } 2601 flush_vnode(vn, TRUE); 2602 } 2603 2604 vn->ns = nsidtons(nsid); 2605 if (!vn->ns) { 2606 UNLOCK(vnlock); 2607 return FS_ENOENT; 2608 } 2609 vn->vnid = vnid; 2610 vn->data = data; 2611 vn->rcnt = 1; 2612 err = sort_vnode(vn); 2613 UNLOCK(vnlock); 2614 return err; 2615} 2616 2617/* 2618 * remove_vnode 2619 */ 2620 2621status_t 2622remove_vnode(nspace_id nsid, vnode_id vnid) 2623{ 2624 vnode *vn; 2625 2626 LOCK(vnlock); 2627 vn = lookup_vnode(nsid, vnid); 2628 if (!vn || (vn->rcnt == 0)) { 2629 UNLOCK(vnlock); 2630 return FS_ENOENT; 2631 } 2632 vn->remove = TRUE; 2633 UNLOCK(vnlock); 2634 return 0; 2635} 2636 2637/* 2638 * unremove_vnode 2639 */ 2640 2641status_t 2642unremove_vnode(nspace_id nsid, vnode_id vnid) 2643{ 2644 vnode *vn; 2645 2646 LOCK(vnlock); 2647 vn = lookup_vnode(nsid, vnid); 2648 if (!vn || (vn->rcnt == 0)) { 2649 UNLOCK(vnlock); 2650 return FS_ENOENT; 2651 } 2652 vn->remove = FALSE; 2653 UNLOCK(vnlock); 2654 return 0; 2655} 2656 2657/* 2658 * is_vnode_removed 2659 */ 2660 2661status_t 2662is_vnode_removed(nspace_id nsid, vnode_id vnid) 2663{ 2664 vnode *vn; 2665 int res; 2666 2667 LOCK(vnlock); 2668 vn = lookup_vnode(nsid, vnid); 2669 if (!vn) { 2670 UNLOCK(vnlock); 2671 return FS_ENOENT; 2672 } 2673 res = vn->remove; 2674 UNLOCK(vnlock); 2675 return res; 2676} 2677 2678/* 2679 * miscelleanous vnode functions 2680 */ 2681 2682 2683static void 2684inc_vnode(vnode *vn) 2685{ 2686 TRACE("inc_vnode(id = %Ld)\n", vn->vnid); 2687 2688 LOCK(vnlock); 2689 vn->rcnt++; 2690 UNLOCK(vnlock); 2691} 2692 2693static void 2694dec_vnode(vnode *vn, char r) 2695{ 2696 vnode *ovn; 2697 2698 LOCK(vnlock); 2699 vn->rcnt--; 2700 TRACE("dec_vnode(): id = %Ld, rcnt = %d (after decreasing)\n", vn->vnid, vn->rcnt); 2701 if (vn->rcnt == 0) { 2702 if (vn->remove) { 2703 vn->busy = TRUE; 2704 move_vnode(vn, LOCKED_LIST); 2705 UNLOCK(vnlock); 2706 (*vn->ns->fs->ops.remove_vnode)(vn->ns->data, vn->data, r); 2707 LOCK(vnlock); 2708 clear_vnode(vn); 2709 move_vnode(vn, FREE_LIST); 2710 } else { 2711 move_vnode(vn, USED_LIST); 2712 if (lists[USED_LIST].num > usdvnnum) { 2713 ovn = steal_vnode(USED_LIST); 2714 flush_vnode(ovn, r); 2715 move_vnode(ovn, FREE_LIST); 2716 } 2717 } 2718 } 2719 UNLOCK(vnlock); 2720 2721 return; 2722} 2723 2724static void 2725clear_vnode(vnode *vn) 2726{ 2727 DeleteSL(skiplist, vn); 2728 2729 if (vn->nspace.prev) 2730 vn->nspace.prev->nspace.next = vn->nspace.next; 2731 else 2732 vn->ns->vnodes.head = vn->nspace.next; 2733 if (vn->nspace.next) 2734 vn->nspace.next->nspace.prev = vn->nspace.prev; 2735 else 2736 vn->ns->vnodes.tail = vn->nspace.prev; 2737 vn->nspace.next = vn->nspace.prev = NULL; 2738 2739 vn->vnid = invalid_vnid; 2740 vn->ns = NULL; 2741 vn->remove = FALSE; 2742 vn->data = NULL; 2743 vn->rcnt = 0; 2744 vn->busy = FALSE; 2745 vn->mounted = NULL; 2746} 2747 2748static int 2749sort_vnode(vnode *vn) 2750{ 2751 if (!InsertSL(skiplist, vn)) 2752 return FS_ENOMEM; 2753 2754 vn->nspace.next = vn->ns->vnodes.head; 2755 vn->nspace.prev = NULL; 2756 if (vn->ns->vnodes.head) 2757 vn->ns->vnodes.head->nspace.prev = vn; 2758 else 2759 vn->ns->vnodes.tail = vn; 2760 vn->ns->vnodes.head = vn; 2761 return 0; 2762} 2763 2764static void 2765move_vnode(vnode *vn, int list) 2766{ 2767 if (vn->list.prev) 2768 vn->list.prev->list.next = vn->list.next; 2769 else 2770 lists[(int)vn->inlist].head = vn->list.next; 2771 if (vn->list.next) 2772 vn->list.next->list.prev = vn->list.prev; 2773 else 2774 lists[(int)vn->inlist].tail = vn->list.prev; 2775 lists[(int)vn->inlist].num--; 2776 vn->inlist = list; 2777 vn->list.next = NULL; 2778 vn->list.prev = lists[list].tail; 2779 if (vn->list.prev) 2780 vn->list.prev->list.next = vn; 2781 else 2782 lists[list].head = vn; 2783 lists[list].tail = vn; 2784 lists[list].num++; 2785} 2786 2787static vnode * 2788steal_vnode(int list) 2789{ 2790 vnode *vn; 2791 2792 vn = lists[list].head; 2793 if (!vn) 2794 return NULL; 2795 move_vnode(vn, LOCKED_LIST); 2796 return vn; 2797} 2798 2799static void 2800flush_vnode(vnode *vn, char r) 2801{ 2802 int err; 2803 2804 vn->busy = TRUE; 2805 UNLOCK(vnlock); 2806 err = (*vn->ns->fs->ops.write_vnode)(vn->ns->data, vn->data, r); 2807 if (err) 2808 PANIC("ERROR WRITING VNODE!!!\n"); 2809 LOCK(vnlock); 2810 vn->busy = FALSE; 2811 clear_vnode(vn); 2812} 2813 2814static vnode * 2815lookup_vnode(nspace_id nsid, vnode_id vnid) 2816{ 2817 vnode fakevn; 2818 nspace fakens; 2819 2820 fakens.nsid = nsid; 2821 fakevn.ns = &fakens; 2822 fakevn.vnid = vnid; 2823 return SearchSL(skiplist, &fakevn); 2824} 2825 2826static int 2827load_vnode(nspace_id nsid, vnode_id vnid, char r, vnode **vnp) 2828{ 2829 int err; 2830 vnode *vn; 2831 2832 LOCK(vnlock); 2833 while (TRUE) { 2834 vn = lookup_vnode(nsid, vnid); 2835 if (vn) { 2836 if (vn->busy) { 2837 UNLOCK(vnlock); 2838 snooze(SLEEP_TIME); 2839 LOCK(vnlock); 2840 continue; 2841 } else 2842 break; 2843 } 2844 2845 vn = steal_vnode(FREE_LIST); 2846 if (!vn) { 2847 vn = steal_vnode(USED_LIST); 2848 if (!vn) 2849 PANIC("OUT OF VNODE!!!\n"); 2850 } else 2851 break; 2852 2853 flush_vnode(vn, r); 2854 move_vnode(vn, FREE_LIST); 2855 } 2856 2857 if (vn->ns == NULL) { 2858 vn->ns = nsidtons(nsid); 2859 if (!vn->ns) { 2860 err = FS_ENOENT; 2861 goto error1; 2862 } 2863 vn->vnid = vnid; 2864 vn->busy = TRUE; 2865 err = sort_vnode(vn); 2866 if (err) 2867 goto error2; 2868 move_vnode(vn, LOCKED_LIST); 2869 UNLOCK(vnlock); 2870 err = (*vn->ns->fs->ops.read_vnode)(vn->ns->data, vnid, r, &vn->data); 2871 LOCK(vnlock); 2872 vn->busy = FALSE; 2873 if (err) 2874 goto error2; 2875 vn->rcnt = 1; 2876 } else { 2877 vn->rcnt++; 2878 if (vn->rcnt == 1) 2879 move_vnode(vn, LOCKED_LIST); 2880 } 2881 *vnp = vn; 2882 UNLOCK(vnlock); 2883 return 0; 2884 2885error2: 2886 clear_vnode(vn); 2887error1: 2888 move_vnode(vn, FREE_LIST); 2889 UNLOCK(vnlock); 2890 return err; 2891} 2892 2893static int 2894compare_vnode(vnode *vna, vnode *vnb) 2895{ 2896 if (vna->vnid > vnb->vnid) 2897 return 1; 2898 else 2899 if (vna->vnid < vnb->vnid) 2900 return -1; 2901 else 2902 if (vna->ns->nsid > vnb->ns->nsid) 2903 return 1; 2904 else 2905 if (vna->ns->nsid < vnb->ns->nsid) 2906 return -1; 2907 else 2908 return 0; 2909} 2910 2911/* 2912 * path management functions 2913 */ 2914 2915int 2916new_path(const char *path, char **copy) 2917{ 2918 const char *q, *r; 2919 char *p; 2920 int l, s; 2921 2922 if (!path) { 2923 *copy = NULL; 2924 return 0; 2925 } 2926 l = strlen(path); 2927 if (l == 0) 2928 return FS_ENOENT; 2929 s = l; 2930 if (path[l-1] == '/') 2931 s++; 2932 2933 if (l >= MAXPATHLEN) 2934 return FS_ENAMETOOLONG; 2935 2936 q = path; 2937 while (*q != '\0') { 2938 while (*q == '/') 2939 q++; 2940 r = q; 2941 while ((*q != '/') && (*q != '\0')) 2942 q++; 2943 if (q - r >= FILE_NAME_LENGTH) 2944 return FS_ENAMETOOLONG; 2945 } 2946 2947 p = (char *) malloc(s+1); 2948 if (!p) 2949 return FS_ENOMEM; 2950 2951 /* ### do real checking: MAXPATHLEN, max file name len, buffer address... */ 2952 2953 strcpy(p, path); 2954 if (p[l-1] == '/') { 2955 p[l] = '.'; 2956 p[l+1] = '\0'; 2957 } 2958 *copy = p; 2959 return 0; 2960} 2961 2962void 2963free_path(char *p) 2964{ 2965 if (p) { 2966 free(p); 2967 } 2968} 2969 2970static char * 2971cat_paths(char *a, char *b) 2972{ 2973 char *p; 2974 2975 p = (char *) realloc(a, strlen(a) + strlen(b) + 2); 2976 if (!p) 2977 return NULL; 2978 strcat(p, "/"); 2979 strcat(p, b); 2980 return p; 2981} 2982 2983/* 2984 * mount point management functions 2985 */ 2986 2987static int 2988is_mount_vnode(vnode *mount, vnode **root) 2989{ 2990 nspace *ns; 2991 2992 LOCK(vnlock); 2993 ns = mount->mounted; 2994 if (ns) { 2995 *root = ns->root; 2996 ns->root->rcnt++; 2997 } 2998 UNLOCK(vnlock); 2999 return (ns != NULL); 3000} 3001 3002static int 3003is_mount_vnid(nspace_id nsid, vnode_id vnid, vnode_id *mount) 3004{ 3005 nspace *ns; 3006 3007 for(ns = nshead; ns; ns = ns->next) { 3008 if (!ns->mount) 3009 continue; 3010 if (ns->mount->ns->nsid != nsid) 3011 continue; 3012 if (ns->mount->vnid != vnid) 3013 continue; 3014 *mount = ns->root->vnid; 3015 return TRUE; 3016 } 3017 return FALSE; 3018} 3019 3020static int 3021is_root(vnode *root, vnode **mount) 3022{ 3023 if ((root->ns->root == root) && root->ns->mount) { 3024 *mount = root->ns->mount; 3025 inc_vnode(*mount); 3026 return TRUE; 3027 } else 3028 return FALSE; 3029} 3030 3031/* 3032 * file descriptor management functions 3033 */ 3034 3035static ofile * 3036get_fd(int kernel, int fd, int type) 3037{ 3038 ofile *f; 3039 fdarray *fds; 3040 3041 f = NULL; 3042 if (kernel) 3043 fds = global_fds; 3044 else 3045 fds = get_cur_ioctx()->fds; 3046 LOCK(fds->lock); 3047 if ((fd >= 0) && (fd < fds->num) && fds->fds[fd]) { 3048 f = fds->fds[fd]; 3049 if (f->type & type) 3050 atomic_add(&f->rcnt, 1); 3051 else 3052 f = NULL; 3053 } 3054 UNLOCK(fds->lock); 3055 return f; 3056} 3057 3058 3059static int 3060put_fd(ofile *f) 3061{ 3062 long cnt; 3063 3064 cnt = atomic_add(&f->rcnt, -1); 3065 if (cnt == 1) 3066 invoke_free(f); 3067 return 0; 3068} 3069 3070static int 3071new_fd(int kernel, int nfd, ofile *f, int fd, int coe) 3072{ 3073 int i, j, num, end; 3074 fdarray *fds; 3075 ofile *of; 3076 int err; 3077 long cnt; 3078 3079 if (kernel) 3080 fds = global_fds; 3081 else 3082 fds = get_cur_ioctx()->fds; 3083 3084 LOCK(fds->lock); 3085 3086 num = fds->num; 3087 3088 if (!f) { 3089 if ((fd < 0) || (fd >= num)) { 3090 err = FS_EBADF; 3091 goto error1; 3092 } 3093 f = fds->fds[fd]; 3094 if (!f) { 3095 err = FS_EBADF; 3096 goto error1; 3097 } 3098 } 3099 3100 atomic_add(&f->rcnt, 1); 3101 atomic_add(&f->ocnt, 1); 3102 3103 if (nfd >= 0) { 3104 if (nfd >= num) { 3105 err = FS_EBADF; 3106 goto error2; 3107 } 3108 of = fds->fds[nfd]; 3109 fds->fds[nfd] = f; 3110 SETBIT(fds->alloc, nfd, TRUE); 3111 SETBIT(fds->coes, nfd, coe); 3112 3113 UNLOCK(fds->lock); 3114 if (of) { 3115 cnt = atomic_add(&of->ocnt, -1); 3116 if (cnt == 1) 3117 invoke_close(of); 3118 cnt = atomic_add(&of->rcnt, -1); 3119 if (cnt == 1) 3120 invoke_free(of); 3121 } 3122 return nfd; 3123 } 3124 3125 end = num & ~31; 3126 for(j=0; j<end; j+=32) 3127 if (fds->alloc[j/32] != 0xffffffff) 3128 for(i=j; i<j+32; i++) 3129 if (!GETBIT(fds->alloc, i)) 3130 goto found; 3131 for(i=end; i<num; i++) 3132 if (!GETBIT(fds->alloc, i)) 3133 goto found; 3134 3135 err = FS_EMFILE; 3136 goto error2; 3137 3138found: 3139 3140 SETBIT(fds->alloc, i, 1); 3141 fds->fds[i] = f; 3142 SETBIT(fds->coes, i, coe); 3143 UNLOCK(fds->lock); 3144 return i; 3145 3146error2: 3147 atomic_add(&f->rcnt, -1); 3148 atomic_add(&f->ocnt, -1); 3149error1: 3150 UNLOCK(fds->lock); 3151 return err; 3152} 3153 3154static int 3155remove_fd(int kernel, int fd, int type) 3156{ 3157 ofile *f; 3158 fdarray *fds; 3159 long cnt; 3160 int err; 3161 3162 f = NULL; 3163 if (kernel) 3164 fds = global_fds; 3165 else 3166 fds = get_cur_ioctx()->fds; 3167 LOCK(fds->lock); 3168 if ((fd >= 0) && (fd < fds->num) && fds->fds[fd]) { 3169 f = fds->fds[fd]; 3170 if (f->type & type) { 3171 SETBIT(fds->alloc, fd, 0); 3172 fds->fds[fd] = NULL; 3173 } else 3174 f = NULL; 3175 } 3176 UNLOCK(fds->lock); 3177 if (f == NULL) 3178 return FS_EBADF; 3179 3180 err = 0; 3181 cnt = atomic_add(&f->ocnt, -1); 3182 if (cnt == 1) 3183 err = invoke_close(f); 3184 cnt = atomic_add(&f->rcnt, -1); 3185 if (cnt == 1) 3186 invoke_free(f); 3187 return err; 3188} 3189 3190#if 0 3191static int 3192get_coe(int kernel, int fd, int type, int *coe) 3193{ 3194 ofile *f; 3195 fdarray *fds; 3196 3197 f = NULL; 3198 if (kernel) 3199 fds = global_fds; 3200 else 3201 fds = get_cur_ioctx()->fds; 3202 LOCK(fds->lock); 3203 if ((fd >= 0) && (fd < fds->num) && fds->fds[fd]) { 3204 f = fds->fds[fd]; 3205 if (f->type == type) { 3206 *coe = GETBIT(fds->coes, fd); 3207 UNLOCK(fds->lock); 3208 return 0; 3209 } 3210 } 3211 UNLOCK(fds->lock); 3212 return FS_EBADF; 3213} 3214 3215static int 3216set_coe(int kernel, int fd, int type, int coe) 3217{ 3218 ofile *f; 3219 fdarray *fds; 3220 3221 f = NULL; 3222 if (kernel) 3223 fds = global_fds; 3224 else 3225 fds = get_cur_ioctx()->fds; 3226 LOCK(fds->lock); 3227 if ((fd >= 0) && (fd < fds->num) && fds->fds[fd]) { 3228 f = fds->fds[fd]; 3229 if (f->type == type) { 3230 SETBIT(fds->coes, fd, coe); 3231 UNLOCK(fds->lock); 3232 return 0; 3233 } 3234 } 3235 UNLOCK(fds->lock); 3236 return FS_EBADF; 3237} 3238 3239static int 3240get_omode(int kernel, int fd, int type, int *omode) 3241{ 3242 ofile *f; 3243 fdarray *fds; 3244 3245 f = NULL; 3246 if (kernel) 3247 fds = global_fds; 3248 else 3249 fds = get_cur_ioctx()->fds; 3250 LOCK(fds->lock); 3251 if ((fd >= 0) && (fd < fds->num) && fds->fds[fd]) { 3252 f = fds->fds[fd]; 3253 if (f->type == type) { 3254 *omode = f->omode; 3255 UNLOCK(fds->lock); 3256 return 0; 3257 } 3258 } 3259 UNLOCK(fds->lock); 3260 return FS_EBADF; 3261} 3262#endif 3263 3264static int 3265invoke_close(ofile *f) 3266{ 3267 int err; 3268 vnode *vn; 3269 3270 vn = f->vn; 3271 switch (f->type) { 3272 case FD_FILE: 3273 err = (*vn->ns->fs->ops.close)(vn->ns->data, vn->data, f->cookie); 3274 break; 3275 case FD_DIR: 3276 err = (*vn->ns->fs->ops.closedir)(vn->ns->data, vn->data, f->cookie); 3277 break; 3278 case FD_ATTR_DIR: 3279 err = (*vn->ns->fs->ops.close_attrdir)(vn->ns->data, vn->data, 3280 f->cookie); 3281 break; 3282 case FD_WD: 3283 default: 3284 err = 0; 3285 break; 3286 } 3287 return err; 3288} 3289 3290static int 3291invoke_free(ofile *f) 3292{ 3293 vnode *vn; 3294 op_free_cookie *op = NULL; 3295 3296 vn = f->vn; 3297 switch(f->type) { 3298 case FD_FILE: 3299 op = vn->ns->fs->ops.free_cookie; 3300 break; 3301 case FD_DIR: 3302 op = vn->ns->fs->ops.free_dircookie; 3303 break; 3304 case FD_WD: 3305 op = NULL; 3306 break; 3307 case FD_ATTR_DIR: 3308 op = vn->ns->fs->ops.free_attrdircookie; 3309 break; 3310 } 3311 if (op) 3312 (*op)(vn->ns->data, vn->data, f->cookie); 3313 dec_vnode(vn, FALSE); 3314 3315 free(f); 3316 return 0; 3317} 3318 3319/* 3320 * other routines 3321 */ 3322 3323static nspace * 3324nsidtons(nspace_id nsid) 3325{ 3326 nspace *ns; 3327 3328 if (nsid < 0) 3329 return NULL; 3330 3331 ns = nstab[nsid % nns]; 3332 if (!ns || (ns->nsid != nsid) || ns->shutdown) 3333 return NULL; 3334 return ns; 3335} 3336 3337#if 0 3338static int 3339alloc_wd_fd(int kernel, vnode *vn, int coe, int *fdp) 3340{ 3341 int err; 3342 ofile *f; 3343 int nfd; 3344 3345 /* 3346 find a file descriptor 3347 */ 3348 3349 f = (ofile *) calloc(sizeof(ofile), 1); 3350 if (!f) { 3351 err = FS_ENOMEM; 3352 goto error1; 3353 } 3354 3355 f->type = FD_WD; 3356 f->vn = vn; 3357 f->rcnt = 0; 3358 f->ocnt = 0; 3359 3360 nfd = new_fd(kernel, -1, f, -1, coe); 3361 if (nfd < 0) { 3362 err = FS_EMFILE; 3363 goto error2; 3364 } 3365 3366 *fdp = nfd; 3367 return 0; 3368 3369error2: 3370 free(f); 3371error1: 3372 return err; 3373} 3374#endif 3375 3376 3377/* 3378 * file system operations 3379 */ 3380 3381void * 3382install_file_system(vnode_ops *ops, const char *name, int fixed, image_id aid) 3383{ 3384 fsystem *fs; 3385 int i; 3386 3387 fs = (fsystem *) malloc(sizeof(fsystem)); 3388 if (!fs) 3389 return NULL; 3390 3391 memcpy(&fs->ops, ops, sizeof(vnode_ops)); 3392 strcpy(fs->name, name); 3393 fs->rcnt = 1; 3394 fs->fixed = fixed; 3395 fs->aid = aid; 3396 3397 for(i=0; i<nfs; i++, nxfsid++) 3398 if (!fstab[nxfsid % nfs]) { 3399 fstab[nxfsid % nfs] = fs; 3400 fs->fsid = nxfsid; 3401 nxfsid++; 3402 break; 3403 } 3404 3405 if (i == nfs) { 3406 free(fs); 3407 return NULL; 3408 } 3409 return (void *)fs; 3410} 3411 3412status_t 3413initialize_file_system(const char *device, const char *fsName, void *params, 3414 int paramLength) 3415{ 3416 struct nspace *mount; 3417 status_t error; 3418 3419 fsystem *fs = inc_file_system(fsName); 3420 if (fs == NULL || fs->ops.initialize == NULL) 3421 return FS_ERROR; 3422 3423 mount = (nspace *)malloc(sizeof(nspace)); 3424 if (add_nspace(mount, NULL, "myfs", -1, -1) < FS_OK) { 3425 error = FS_ERROR; 3426 } else { 3427 error = (*fs->ops.initialize)(device, params, paramLength); 3428 remove_nspace(mount); 3429 } 3430 3431 dec_file_system(fs); 3432 3433 return error; 3434} 3435 3436static fsystem * 3437load_file_system(const char *name) 3438{ 3439 return NULL; 3440} 3441 3442static int 3443unload_file_system(fsystem *fs) 3444{ 3445 fstab[fs->fsid % nfs] = NULL; 3446 free(fs); 3447 return 0; 3448} 3449 3450 3451static fsystem * 3452inc_file_system(const char *name) 3453{ 3454 fsystem *fs; 3455 int i; 3456 3457 fs = NULL; 3458 LOCK(fstablock); 3459 3460 for(i=0; i<nfs; i++) 3461 if (fstab[i] && !strcmp(fstab[i]->name, name)) { 3462 fs = fstab[i]; 3463 fs->rcnt++; 3464 break; 3465 } 3466 3467 if (!fs) 3468 fs = load_file_system(name); 3469 3470 UNLOCK(fstablock); 3471 3472 return fs; 3473} 3474 3475static int 3476dec_file_system(fsystem *fs) 3477{ 3478 LOCK(fstablock); 3479 3480 fs->rcnt--; 3481 if (!fs->fixed && (fs->rcnt == 0)) 3482 unload_file_system(fs); 3483 3484 UNLOCK(fstablock); 3485 return 0; 3486} 3487 3488 3489static fdarray * 3490new_fds(int num) 3491{ 3492 fdarray *fds; 3493 size_t sz; 3494 3495 sz = sizeof(fdarray) + (num-1) * sizeof(void *) + 2*BITSZ(num); 3496 fds = (fdarray *) malloc(sz); 3497 if (!fds) 3498 return NULL; 3499 memset(fds, 0, sz); 3500 fds->rcnt = 1; 3501 if (new_lock(&fds->lock, "fdlock") < 0) { 3502 free(fds); 3503 return NULL; 3504 } 3505 fds->num = num; 3506 fds->alloc = (ulong *) &fds->fds[num]; 3507 fds->coes = &fds->alloc[BITSZ(num) / sizeof(ulong)]; 3508 return fds; 3509} 3510 3511#if 0 3512static int 3513free_fds(fdarray *fds) 3514{ 3515 long cnt; 3516 int i; 3517 ofile *f; 3518 3519 for(i=0; i<fds->num; i++) 3520 if (fds->fds[i]) { 3521 f = fds->fds[i]; 3522 cnt = atomic_add(&f->ocnt, -1); 3523 if (cnt == 1) 3524 invoke_close(f); 3525 cnt = atomic_add(&f->rcnt, -1); 3526 if (cnt == 1) 3527 invoke_free(f); 3528 } 3529 delete_sem(fds->lock.s); 3530 free(fds); 3531 return 0; 3532} 3533#endif 3534 3535// dummies 3536 3537 3538status_t 3539notify_listener(int op, nspace_id nsid, vnode_id vnida, vnode_id vnidb, vnode_id vnidc, const char *name) 3540{ 3541#ifdef DEBUG 3542 printf("notify_listener: op = %d\n", op); 3543#endif 3544 3545#ifdef USED_IN_FS_SHELL 3546 return send_notification(0, 0, FSH_NOTIFY_LISTENER, op, nsid, -1, vnida, vnidb, vnidc, name); 3547#else 3548 return send_notification(0, 0, 0x666, op, nsid, -1, vnida, vnidb, vnidc, name); 3549#endif 3550} 3551 3552 3553status_t 3554send_notification(port_id port, long token, ulong what, long op, nspace_id nsida, 3555 nspace_id nsidb, vnode_id vnida, vnode_id vnidb, vnode_id vnidc, 3556 const char *name) 3557{ 3558#ifdef USED_IN_FS_SHELL 3559 update_message message; 3560#endif 3561 3562#ifdef DEBUG 3563 char *text; 3564 3565 switch (op) { 3566 case B_ENTRY_CREATED: 3567 text = "B_ENTRY_CREATED"; 3568 break; 3569 case B_ENTRY_REMOVED: 3570 text = "B_ENTRY_REMOVED"; 3571 break; 3572 case B_ENTRY_MOVED: 3573 text = "B_ENTRY_MOVED"; 3574 break; 3575 case B_STAT_CHANGED: 3576 text = "B_STAT_CHANGED"; 3577 break; 3578 case B_ATTR_CHANGED: 3579 text = "B_ATTR_CHANGED"; 3580 break; 3581 case B_DEVICE_MOUNTED: 3582 text = "B_DEVICE_MOUNTED"; 3583 break; 3584 case B_DEVICE_UNMOUNTED: 3585 text = "B_DEVICE_UNMOUNTED"; 3586 break; 3587 default: 3588 text = "unknown operation..."; 3589 break; 3590 } 3591 printf("send_notification... op = %s, name = %s, port = %ld, token = %ld\n", 3592 text, name, port, token); 3593#endif 3594 3595#ifdef USED_IN_FS_SHELL 3596 message.op = op; 3597 message.device = nsida; 3598 message.toDevice = nsidb; 3599 message.parentNode = vnida; 3600 message.targetNode = vnidb; 3601 message.node = vnidc; 3602 3603 if (name != NULL) { 3604 strcpy(message.name, name); 3605 // name is 256 character at maximum 3606 } else 3607 message.name[0] = '\0'; 3608 3609 return write_port(gTrackerPort, what, &message, sizeof(message)); 3610#else 3611 return FS_OK; 3612#endif 3613} 3614 3615#ifdef COMPILE_FOR_R5 3616void 3617notify_select_event(selectsync *sync, uint32 ref) 3618{ 3619} 3620#else 3621status_t 3622notify_select_event(selectsync *sync, uint32 ref, uint8 event) 3623{ 3624 return FS_UNSUPPORTED; 3625} 3626#endif 3627 3628