|
|
1.1 ! root 1: /* ! 2: ! 3: Copyright 1991,1992 Eric R. Smith. All rights reserved. ! 4: ! 5: */ ! 6: ! 7: ! 8: ! 9: /* a simple unified file system */ ! 10: ! 11: ! 12: ! 13: #include "mint.h" ! 14: ! 15: ! 16: ! 17: ! 18: ! 19: extern FILESYS bios_filesys, proc_filesys, pipe_filesys, shm_filesys; ! 20: ! 21: ! 22: ! 23: static long uni_root P_((int drv, fcookie *fc)); ! 24: ! 25: static long uni_lookup P_((fcookie *dir, const char *name, fcookie *fc)); ! 26: ! 27: static long uni_getxattr P_((fcookie *fc, XATTR *xattr)); ! 28: ! 29: static long uni_chattr P_((fcookie *fc, int attrib)); ! 30: ! 31: static long uni_chown P_((fcookie *fc, int uid, int gid)); ! 32: ! 33: static long uni_chmode P_((fcookie *fc, unsigned mode)); ! 34: ! 35: static long uni_rmdir P_((fcookie *dir, const char *name)); ! 36: ! 37: static long uni_remove P_((fcookie *dir, const char *name)); ! 38: ! 39: static long uni_getname P_((fcookie *root, fcookie *dir, char *pathname)); ! 40: ! 41: static long uni_rename P_((fcookie *olddir, char *oldname, ! 42: ! 43: fcookie *newdir, const char *newname)); ! 44: ! 45: static long uni_opendir P_((DIR *dirh, int flags)); ! 46: ! 47: static long uni_readdir P_((DIR *dirh, char *nm, int nmlen, fcookie *)); ! 48: ! 49: static long uni_rewinddir P_((DIR *dirh)); ! 50: ! 51: static long uni_closedir P_((DIR *dirh)); ! 52: ! 53: static long uni_pathconf P_((fcookie *dir, int which)); ! 54: ! 55: static long uni_dfree P_((fcookie *dir, long *buf)); ! 56: ! 57: static DEVDRV * uni_getdev P_((fcookie *fc, long *devsp)); ! 58: ! 59: static long uni_symlink P_((fcookie *dir, const char *name, const char *to)); ! 60: ! 61: static long uni_readlink P_((fcookie *fc, char *buf, int buflen)); ! 62: ! 63: ! 64: ! 65: FILESYS uni_filesys = { ! 66: ! 67: (FILESYS *)0, ! 68: ! 69: 0, ! 70: ! 71: uni_root, ! 72: ! 73: uni_lookup, nocreat, uni_getdev, uni_getxattr, ! 74: ! 75: uni_chattr, uni_chown, uni_chmode, ! 76: ! 77: nomkdir, uni_rmdir, uni_remove, uni_getname, uni_rename, ! 78: ! 79: uni_opendir, uni_readdir, uni_rewinddir, uni_closedir, ! 80: ! 81: uni_pathconf, uni_dfree, nowritelabel, noreadlabel, ! 82: ! 83: uni_symlink, uni_readlink, nohardlink, nofscntl, nodskchng ! 84: ! 85: }; ! 86: ! 87: ! 88: ! 89: /* ! 90: ! 91: * structure that holds files ! 92: ! 93: * if (mode & S_IFMT == S_IFDIR), then this is an alias for a drive: ! 94: ! 95: * "dev" holds the appropriate BIOS device number, and ! 96: ! 97: * "data" is meaningless ! 98: ! 99: * if (mode & S_IFMT == S_IFLNK), then this is a symbolic link: ! 100: ! 101: * "dev" holds the user id of the owner, and ! 102: ! 103: * "data" points to the actual link data ! 104: ! 105: */ ! 106: ! 107: ! 108: ! 109: typedef struct unifile { ! 110: ! 111: char name[NAME_MAX+1]; ! 112: ! 113: short mode; ! 114: ! 115: ushort dev; ! 116: ! 117: FILESYS *fs; ! 118: ! 119: void *data; ! 120: ! 121: struct unifile *next; ! 122: ! 123: } UNIFILE; ! 124: ! 125: ! 126: ! 127: /* the "+1" is for shared memory, which has no BIOS drive */ ! 128: ! 129: #define UNI_DIRS NUM_DRIVES+1 ! 130: ! 131: static UNIFILE u_drvs[UNI_DIRS]; ! 132: ! 133: static UNIFILE *u_root = 0; ! 134: ! 135: ! 136: ! 137: void ! 138: ! 139: unifs_init() ! 140: ! 141: { ! 142: ! 143: UNIFILE *u = u_drvs; ! 144: ! 145: int i; ! 146: ! 147: ! 148: ! 149: u_root = u; ! 150: ! 151: for (i = 0; i < NUM_DRIVES; i++,u++) { ! 152: ! 153: u->next = u+1; ! 154: ! 155: u->mode = S_IFDIR|DEFAULT_DIRMODE; ! 156: ! 157: u->dev = i; ! 158: ! 159: u->fs = 0; ! 160: ! 161: if (i == PROCDRV) ! 162: ! 163: strcpy(u->name, "proc"); ! 164: ! 165: else if (i == PIPEDRV) ! 166: ! 167: strcpy(u->name, "pipe"); ! 168: ! 169: else if (i == BIOSDRV) ! 170: ! 171: strcpy(u->name, "dev"); ! 172: ! 173: else if (i == UNIDRV) { ! 174: ! 175: (u-1)->next = u->next; /* skip this drive */ ! 176: ! 177: } else { ! 178: ! 179: u->name[0] = i + 'a'; ! 180: ! 181: u->name[1] = 0; ! 182: ! 183: } ! 184: ! 185: } ! 186: ! 187: u->next = 0; ! 188: ! 189: u->mode = S_IFDIR|DEFAULT_DIRMODE; ! 190: ! 191: u->dev = SHMDEVICE; ! 192: ! 193: u->fs = &shm_filesys; ! 194: ! 195: strcpy(u->name, "shm"); ! 196: ! 197: } ! 198: ! 199: ! 200: ! 201: static long ! 202: ! 203: uni_root(drv, fc) ! 204: ! 205: int drv; ! 206: ! 207: fcookie *fc; ! 208: ! 209: { ! 210: ! 211: if (drv == UNIDRV) { ! 212: ! 213: fc->fs = &uni_filesys; ! 214: ! 215: fc->dev = drv; ! 216: ! 217: fc->index = 0L; ! 218: ! 219: return 0; ! 220: ! 221: } ! 222: ! 223: fc->fs = 0; ! 224: ! 225: return EINTRN; ! 226: ! 227: } ! 228: ! 229: ! 230: ! 231: static long ! 232: ! 233: uni_lookup(dir, name, fc) ! 234: ! 235: fcookie *dir; ! 236: ! 237: const char *name; ! 238: ! 239: fcookie *fc; ! 240: ! 241: { ! 242: ! 243: UNIFILE *u; ! 244: ! 245: long drvs; ! 246: ! 247: FILESYS *fs; ! 248: ! 249: extern long dosdrvs; ! 250: ! 251: ! 252: ! 253: TRACE("uni_lookup(%s)", name); ! 254: ! 255: ! 256: ! 257: if (dir->index != 0) { ! 258: ! 259: DEBUG("uni_lookup: bad directory"); ! 260: ! 261: return EPTHNF; ! 262: ! 263: } ! 264: ! 265: /* special case: an empty name in a directory means that directory */ ! 266: ! 267: /* so do "." and ".." */ ! 268: ! 269: ! 270: ! 271: if (!*name || !strcmp(name, ".") || !strcmp(name, "..")) { ! 272: ! 273: *fc = *dir; ! 274: ! 275: return 0; ! 276: ! 277: } ! 278: ! 279: drvs = drvmap() | dosdrvs | PSEUDODRVS; ! 280: ! 281: /* ! 282: ! 283: * OK, check the list of aliases and special directories ! 284: ! 285: */ ! 286: ! 287: for (u = u_root; u; u = u->next) { ! 288: ! 289: if (!stricmp(name, u->name)) { ! 290: ! 291: if ( (u->mode & S_IFMT) == S_IFDIR ) { ! 292: ! 293: if (u->dev >= NUM_DRIVES) { ! 294: ! 295: fs = u->fs; ! 296: ! 297: return (*fs->root)(u->dev,fc); ! 298: ! 299: } ! 300: ! 301: if ((drvs & (1L << u->dev)) == 0) ! 302: ! 303: return EPTHNF; ! 304: ! 305: *fc = curproc->root[u->dev]; ! 306: ! 307: if (!fc->fs) { /* drive changed? */ ! 308: ! 309: changedrv(fc->dev); ! 310: ! 311: *fc = curproc->root[u->dev]; ! 312: ! 313: if (!fc->fs) ! 314: ! 315: return EPTHNF; ! 316: ! 317: } ! 318: ! 319: } else { /* a symbolic link */ ! 320: ! 321: fc->fs = &uni_filesys; ! 322: ! 323: fc->dev = UNIDRV; ! 324: ! 325: fc->index = (long)u; ! 326: ! 327: } ! 328: ! 329: return 0; ! 330: ! 331: } ! 332: ! 333: } ! 334: ! 335: DEBUG("uni_lookup: name (%s) not found", name); ! 336: ! 337: return EFILNF; ! 338: ! 339: } ! 340: ! 341: ! 342: ! 343: static long ! 344: ! 345: uni_getxattr(fc, xattr) ! 346: ! 347: fcookie *fc; ! 348: ! 349: XATTR *xattr; ! 350: ! 351: { ! 352: ! 353: UNIFILE *u = (UNIFILE *)fc->index; ! 354: ! 355: ! 356: ! 357: if (fc->fs != &uni_filesys) { ! 358: ! 359: ALERT("ERROR: wrong file system getxattr called"); ! 360: ! 361: return EINTRN; ! 362: ! 363: } ! 364: ! 365: ! 366: ! 367: xattr->index = fc->index; ! 368: ! 369: xattr->dev = fc->dev; ! 370: ! 371: xattr->nlink = 1; ! 372: ! 373: xattr->blksize = 1; ! 374: ! 375: ! 376: ! 377: /* If "u" is null, then we have the root directory, otherwise ! 378: ! 379: * we use the UNIFILE structure to get the info about it ! 380: ! 381: */ ! 382: ! 383: if (!u || ( (u->mode & S_IFMT) == S_IFDIR )) { ! 384: ! 385: xattr->uid = xattr->gid = 0; ! 386: ! 387: xattr->size = xattr->nblocks = 0; ! 388: ! 389: xattr->mode = S_IFDIR | DEFAULT_DIRMODE; ! 390: ! 391: xattr->attr = FA_DIR; ! 392: ! 393: } else { ! 394: ! 395: xattr->uid = u->dev; ! 396: ! 397: xattr->gid = 0; ! 398: ! 399: xattr->size = xattr->nblocks = strlen(u->data) + 1; ! 400: ! 401: xattr->mode = u->mode; ! 402: ! 403: xattr->attr = 0; ! 404: ! 405: } ! 406: ! 407: xattr->mtime = xattr->atime = xattr->ctime = 0; ! 408: ! 409: xattr->mdate = xattr->adate = xattr->cdate = 0; ! 410: ! 411: return 0; ! 412: ! 413: } ! 414: ! 415: ! 416: ! 417: static long ! 418: ! 419: uni_chattr(dir, attrib) ! 420: ! 421: fcookie *dir; ! 422: ! 423: int attrib; ! 424: ! 425: { ! 426: ! 427: return EACCDN; ! 428: ! 429: } ! 430: ! 431: ! 432: ! 433: static long ! 434: ! 435: uni_chown(dir, uid, gid) ! 436: ! 437: fcookie *dir; ! 438: ! 439: int uid, gid; ! 440: ! 441: { ! 442: ! 443: return EINVFN; ! 444: ! 445: } ! 446: ! 447: ! 448: ! 449: static long ! 450: ! 451: uni_chmode(dir, mode) ! 452: ! 453: fcookie *dir; ! 454: ! 455: unsigned mode; ! 456: ! 457: { ! 458: ! 459: return EINVFN; ! 460: ! 461: } ! 462: ! 463: ! 464: ! 465: static long ! 466: ! 467: uni_rmdir(dir, name) ! 468: ! 469: fcookie *dir; ! 470: ! 471: const char *name; ! 472: ! 473: { ! 474: ! 475: long r; ! 476: ! 477: ! 478: ! 479: r = uni_remove(dir, name); ! 480: ! 481: if (r == EFILNF) r = EPTHNF; ! 482: ! 483: return r; ! 484: ! 485: } ! 486: ! 487: ! 488: ! 489: static long ! 490: ! 491: uni_remove(dir, name) ! 492: ! 493: fcookie *dir; ! 494: ! 495: const char *name; ! 496: ! 497: { ! 498: ! 499: UNIFILE *u, *lastu; ! 500: ! 501: ! 502: ! 503: lastu = 0; ! 504: ! 505: u = u_root; ! 506: ! 507: while (u) { ! 508: ! 509: if (!strncmp(u->name, name, NAME_MAX)) { ! 510: ! 511: if ( (u->mode & S_IFMT) != S_IFLNK ) return EFILNF; ! 512: ! 513: kfree(u->data); ! 514: ! 515: if (lastu) ! 516: ! 517: lastu->next = u->next; ! 518: ! 519: else ! 520: ! 521: u_root = u->next; ! 522: ! 523: kfree(u); ! 524: ! 525: return 0; ! 526: ! 527: } ! 528: ! 529: lastu = u; ! 530: ! 531: u = u->next; ! 532: ! 533: } ! 534: ! 535: return EFILNF; ! 536: ! 537: } ! 538: ! 539: ! 540: ! 541: static long ! 542: ! 543: uni_getname(root, dir, pathname) ! 544: ! 545: fcookie *root, *dir; char *pathname; ! 546: ! 547: { ! 548: ! 549: FILESYS *fs; ! 550: ! 551: UNIFILE *u; ! 552: ! 553: char *n; ! 554: ! 555: fcookie relto; ! 556: ! 557: ! 558: ! 559: fs = dir->fs; ! 560: ! 561: if (dir->dev == UNIDRV) { ! 562: ! 563: *pathname = 0; ! 564: ! 565: return 0; ! 566: ! 567: } ! 568: ! 569: ! 570: ! 571: for (u = u_root; u; u = u->next) { ! 572: ! 573: if (dir->dev == u->dev && (u->mode & S_IFMT) == S_IFDIR) { ! 574: ! 575: *pathname++ = '\\'; ! 576: ! 577: for (n = u->name; *n; ) ! 578: ! 579: *pathname++ = *n++; ! 580: ! 581: break; ! 582: ! 583: } ! 584: ! 585: } ! 586: ! 587: ! 588: ! 589: if (!u) { ! 590: ! 591: ALERT("unifs: couldn't match a drive with a directory"); ! 592: ! 593: return EPTHNF; ! 594: ! 595: } ! 596: ! 597: ! 598: ! 599: if (dir->dev >= NUM_DRIVES) { ! 600: ! 601: if ((*fs->root)(dir->dev, &relto) == 0) { ! 602: ! 603: return (*fs->getname)(&relto, dir, pathname); ! 604: ! 605: } else { ! 606: ! 607: *pathname++ = 0; ! 608: ! 609: return EINTRN; ! 610: ! 611: } ! 612: ! 613: } ! 614: ! 615: ! 616: ! 617: if (curproc->root[dir->dev].fs != fs) { ! 618: ! 619: ALERT("unifs: drive's file system doesn't match directory's"); ! 620: ! 621: return EINTRN; ! 622: ! 623: } ! 624: ! 625: ! 626: ! 627: return (*fs->getname)(&curproc->root[dir->dev], dir, pathname); ! 628: ! 629: } ! 630: ! 631: ! 632: ! 633: static long ! 634: ! 635: uni_rename(olddir, oldname, newdir, newname) ! 636: ! 637: fcookie *olddir; ! 638: ! 639: char *oldname; ! 640: ! 641: fcookie *newdir; ! 642: ! 643: const char *newname; ! 644: ! 645: { ! 646: ! 647: UNIFILE *u = 0; ! 648: ! 649: fcookie fc; ! 650: ! 651: long r; ! 652: ! 653: ! 654: ! 655: for (u = u_root; u; u = u->next) { ! 656: ! 657: if (!stricmp(u->name, oldname)) ! 658: ! 659: break; ! 660: ! 661: } ! 662: ! 663: ! 664: ! 665: if (!u) { ! 666: ! 667: DEBUG("uni_rename: old file not found"); ! 668: ! 669: return EFILNF; ! 670: ! 671: } ! 672: ! 673: ! 674: ! 675: /* the new name is not allowed to exist! */ ! 676: ! 677: r = uni_lookup(newdir, newname, &fc); ! 678: ! 679: if (r != EFILNF) { ! 680: ! 681: DEBUG("uni_rename: error %ld", r); ! 682: ! 683: return (r == 0) ? EACCDN : r; ! 684: ! 685: } ! 686: ! 687: ! 688: ! 689: (void)strncpy(u->name, newname, NAME_MAX); ! 690: ! 691: return 0; ! 692: ! 693: } ! 694: ! 695: ! 696: ! 697: static long ! 698: ! 699: uni_opendir(dirh, flags) ! 700: ! 701: DIR *dirh; ! 702: ! 703: int flags; ! 704: ! 705: { ! 706: ! 707: if (dirh->fc.index != 0) { ! 708: ! 709: DEBUG("uni_opendir: bad directory"); ! 710: ! 711: return EPTHNF; ! 712: ! 713: } ! 714: ! 715: dirh->index = 0; ! 716: ! 717: return 0; ! 718: ! 719: } ! 720: ! 721: ! 722: ! 723: ! 724: ! 725: static long ! 726: ! 727: uni_readdir(dirh, name, namelen, fc) ! 728: ! 729: DIR *dirh; ! 730: ! 731: char *name; ! 732: ! 733: int namelen; ! 734: ! 735: fcookie *fc; ! 736: ! 737: { ! 738: ! 739: long map; ! 740: ! 741: char *dirname; ! 742: ! 743: int i; ! 744: ! 745: int giveindex = (dirh->flags == 0); ! 746: ! 747: UNIFILE *u; ! 748: ! 749: long index; ! 750: ! 751: extern long dosdrvs; ! 752: ! 753: long r; ! 754: ! 755: ! 756: ! 757: map = dosdrvs | drvmap() | PSEUDODRVS; ! 758: ! 759: i = dirh->index++; ! 760: ! 761: u = u_root; ! 762: ! 763: while (i > 0) { ! 764: ! 765: --i; ! 766: ! 767: u = u->next; ! 768: ! 769: if (!u) ! 770: ! 771: break; ! 772: ! 773: } ! 774: ! 775: tryagain: ! 776: ! 777: if (!u) return ENMFIL; ! 778: ! 779: ! 780: ! 781: dirname = u->name; ! 782: ! 783: index = (long)u; ! 784: ! 785: if ( (u->mode & S_IFMT) == S_IFDIR ) { ! 786: ! 787: /* make sure the drive really exists */ ! 788: ! 789: if ( u->dev >= NUM_DRIVES) { ! 790: ! 791: r = (*u->fs->root)(u->dev,fc); ! 792: ! 793: if (r) { ! 794: ! 795: fc->fs = &uni_filesys; ! 796: ! 797: fc->index = 0; ! 798: ! 799: fc->dev = u->dev; ! 800: ! 801: } ! 802: ! 803: } else { ! 804: ! 805: if ((map & (1L << u->dev)) == 0 ) { ! 806: ! 807: dirh->index++; ! 808: ! 809: u = u->next; ! 810: ! 811: goto tryagain; ! 812: ! 813: } ! 814: ! 815: *fc = curproc->root[u->dev]; ! 816: ! 817: if (!fc->fs) { /* drive not yet initialized */ ! 818: ! 819: /* use default attributes */ ! 820: ! 821: fc->fs = &uni_filesys; ! 822: ! 823: fc->index = 0; ! 824: ! 825: fc->dev = u->dev; ! 826: ! 827: } ! 828: ! 829: } ! 830: ! 831: } else { /* a symbolic link */ ! 832: ! 833: fc->fs = &uni_filesys; ! 834: ! 835: fc->dev = UNIDRV; ! 836: ! 837: fc->index = (long)u; ! 838: ! 839: } ! 840: ! 841: ! 842: ! 843: if (giveindex) { ! 844: ! 845: namelen -= sizeof(long); ! 846: ! 847: if (namelen <= 0) return ERANGE; ! 848: ! 849: *((long *)name) = index; ! 850: ! 851: name += sizeof(long); ! 852: ! 853: } ! 854: ! 855: strncpy(name, dirname, namelen-1); ! 856: ! 857: if (strlen(name) < strlen(dirname)) ! 858: ! 859: return ENAMETOOLONG; ! 860: ! 861: return 0; ! 862: ! 863: } ! 864: ! 865: ! 866: ! 867: static long ! 868: ! 869: uni_rewinddir(dirh) ! 870: ! 871: DIR *dirh; ! 872: ! 873: { ! 874: ! 875: dirh->index = 0; ! 876: ! 877: return 0; ! 878: ! 879: } ! 880: ! 881: ! 882: ! 883: static long ! 884: ! 885: uni_closedir(dirh) ! 886: ! 887: DIR *dirh; ! 888: ! 889: { ! 890: ! 891: return 0; ! 892: ! 893: } ! 894: ! 895: ! 896: ! 897: static long ! 898: ! 899: uni_pathconf(dir, which) ! 900: ! 901: fcookie *dir; ! 902: ! 903: int which; ! 904: ! 905: { ! 906: ! 907: switch(which) { ! 908: ! 909: case -1: ! 910: ! 911: return DP_MAXREQ; ! 912: ! 913: case DP_IOPEN: ! 914: ! 915: return 0; /* no files to open */ ! 916: ! 917: case DP_MAXLINKS: ! 918: ! 919: return 1; /* no hard links available */ ! 920: ! 921: case DP_PATHMAX: ! 922: ! 923: return PATH_MAX; ! 924: ! 925: case DP_NAMEMAX: ! 926: ! 927: return NAME_MAX; ! 928: ! 929: case DP_ATOMIC: ! 930: ! 931: return 1; /* no atomic writes */ ! 932: ! 933: case DP_TRUNC: ! 934: ! 935: return DP_AUTOTRUNC; ! 936: ! 937: case DP_CASE: ! 938: ! 939: return DP_CASEINSENS; ! 940: ! 941: default: ! 942: ! 943: return EINVFN; ! 944: ! 945: } ! 946: ! 947: } ! 948: ! 949: ! 950: ! 951: static long ! 952: ! 953: uni_dfree(dir, buf) ! 954: ! 955: fcookie *dir; ! 956: ! 957: long *buf; ! 958: ! 959: { ! 960: ! 961: buf[0] = 0; /* number of free clusters */ ! 962: ! 963: buf[1] = 0; /* total number of clusters */ ! 964: ! 965: buf[2] = 1; /* sector size (bytes) */ ! 966: ! 967: buf[3] = 1; /* cluster size (sectors) */ ! 968: ! 969: return 0; ! 970: ! 971: } ! 972: ! 973: ! 974: ! 975: static DEVDRV * ! 976: ! 977: uni_getdev(fc, devsp) ! 978: ! 979: fcookie *fc; ! 980: ! 981: long *devsp; ! 982: ! 983: { ! 984: ! 985: *devsp = EACCDN; ! 986: ! 987: return 0; ! 988: ! 989: } ! 990: ! 991: ! 992: ! 993: static long ! 994: ! 995: uni_symlink(dir, name, to) ! 996: ! 997: fcookie *dir; ! 998: ! 999: const char *name; ! 1000: ! 1001: const char *to; ! 1002: ! 1003: { ! 1004: ! 1005: UNIFILE *u; ! 1006: ! 1007: fcookie fc; ! 1008: ! 1009: long r; ! 1010: ! 1011: ! 1012: ! 1013: r = uni_lookup(dir, name, &fc); ! 1014: ! 1015: if (r == 0) return EACCDN; /* file already exists */ ! 1016: ! 1017: if (r != EFILNF) return r; /* some other error */ ! 1018: ! 1019: ! 1020: ! 1021: u = kmalloc(SIZEOF(UNIFILE)); ! 1022: ! 1023: if (!u) return EACCDN; ! 1024: ! 1025: ! 1026: ! 1027: strncpy(u->name, name, NAME_MAX); ! 1028: ! 1029: u->name[NAME_MAX] = 0; ! 1030: ! 1031: ! 1032: ! 1033: u->data = kmalloc((long)strlen(to)+1); ! 1034: ! 1035: if (!u->data) { ! 1036: ! 1037: kfree(u); ! 1038: ! 1039: return EACCDN; ! 1040: ! 1041: } ! 1042: ! 1043: strcpy(u->data, to); ! 1044: ! 1045: u->mode = S_IFLNK | DEFAULT_DIRMODE; ! 1046: ! 1047: u->dev = curproc->ruid; ! 1048: ! 1049: u->next = u_root; ! 1050: ! 1051: u->fs = &uni_filesys; ! 1052: ! 1053: u_root = u; ! 1054: ! 1055: return 0; ! 1056: ! 1057: } ! 1058: ! 1059: ! 1060: ! 1061: static long ! 1062: ! 1063: uni_readlink(fc, buf, buflen) ! 1064: ! 1065: fcookie *fc; ! 1066: ! 1067: char *buf; ! 1068: ! 1069: int buflen; ! 1070: ! 1071: { ! 1072: ! 1073: UNIFILE *u; ! 1074: ! 1075: ! 1076: ! 1077: u = (UNIFILE *)fc->index; ! 1078: ! 1079: assert(u); ! 1080: ! 1081: assert((u->mode & S_IFMT) == S_IFLNK); ! 1082: ! 1083: assert(u->data); ! 1084: ! 1085: strncpy(buf, u->data, buflen); ! 1086: ! 1087: if (strlen(u->data) >= buflen) ! 1088: ! 1089: return ENAMETOOLONG; ! 1090: ! 1091: return 0; ! 1092: ! 1093: } ! 1094:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.