|
|
1.1 ! root 1: /* ! 2: ! 3: Copyright 1990,1991,1992 Eric R. Smith. All rights reserved. ! 4: ! 5: */ ! 6: ! 7: ! 8: ! 9: /* DOS directory functions */ ! 10: ! 11: ! 12: ! 13: #include "mint.h" ! 14: ! 15: ! 16: ! 17: /* change to a new drive: should always return a map of valid drives */ ! 18: ! 19: ! 20: ! 21: long ! 22: ! 23: d_setdrv(d) ! 24: ! 25: int d; ! 26: ! 27: { ! 28: ! 29: long r; ! 30: ! 31: extern long dosdrvs; /* in filesys.c */ ! 32: ! 33: ! 34: ! 35: r = drvmap() | dosdrvs | PSEUDODRVS; ! 36: ! 37: ! 38: ! 39: TRACE("Dsetdrv(%d)", d); ! 40: ! 41: if (d < 0 || d >= NUM_DRIVES || (r & (1L << d)) == 0) { ! 42: ! 43: DEBUG("Dsetdrv: invalid drive %d", d); ! 44: ! 45: return r; ! 46: ! 47: } ! 48: ! 49: ! 50: ! 51: curproc->base->p_defdrv = curproc->curdrv = d; ! 52: ! 53: return r; ! 54: ! 55: } ! 56: ! 57: ! 58: ! 59: long ! 60: ! 61: d_getdrv() ! 62: ! 63: { ! 64: ! 65: TRACE("Dgetdrv"); ! 66: ! 67: return curproc->curdrv; ! 68: ! 69: } ! 70: ! 71: ! 72: ! 73: long ! 74: ! 75: d_free(buf, d) ! 76: ! 77: long *buf; ! 78: ! 79: int d; ! 80: ! 81: { ! 82: ! 83: fcookie *dir; ! 84: ! 85: ! 86: ! 87: TRACE("Dfree(%d)", d); ! 88: ! 89: ! 90: ! 91: /* drive 0 means current drive, otherwise it's d-1 */ ! 92: ! 93: if (d) ! 94: ! 95: d = d-1; ! 96: ! 97: else ! 98: ! 99: d = curproc->curdrv; ! 100: ! 101: ! 102: ! 103: if (d < 0 || d >= NUM_DRIVES) ! 104: ! 105: return EDRIVE; ! 106: ! 107: ! 108: ! 109: /* check for a media change -- we don't care much either way, but it ! 110: ! 111: * does keep the results more accurate ! 112: ! 113: */ ! 114: ! 115: (void)disk_changed(d); ! 116: ! 117: ! 118: ! 119: /* use current directory, not root, since it's more likely that ! 120: ! 121: * programs are interested in the latter (this makes U: work much ! 122: ! 123: * better) ! 124: ! 125: */ ! 126: ! 127: dir = &curproc->curdir[d]; ! 128: ! 129: if (!dir->fs) { ! 130: ! 131: DEBUG("Dfree: bad drive"); ! 132: ! 133: return EDRIVE; ! 134: ! 135: } ! 136: ! 137: ! 138: ! 139: return (*dir->fs->dfree)(dir, buf); ! 140: ! 141: } ! 142: ! 143: ! 144: ! 145: /* temp1 is a convenient place for path2fs puts the last component of ! 146: ! 147: * the path name ! 148: ! 149: */ ! 150: ! 151: ! 152: ! 153: extern char temp1[PATH_MAX]; /* in filesys.c */ ! 154: ! 155: ! 156: ! 157: long ! 158: ! 159: d_create(path) ! 160: ! 161: const char *path; ! 162: ! 163: { ! 164: ! 165: fcookie dir; ! 166: ! 167: long r; ! 168: ! 169: ! 170: ! 171: TRACE("Dcreate(%s)", path); ! 172: ! 173: ! 174: ! 175: r = path2cookie(path, temp1, &dir); ! 176: ! 177: if (r) { ! 178: ! 179: DEBUG("Dcreate(%s): returning %ld", path, r); ! 180: ! 181: return r; /* an error occured */ ! 182: ! 183: } ! 184: ! 185: /* check for write permission on the directory */ ! 186: ! 187: r = dir_access(&dir, S_IWOTH); ! 188: ! 189: if (r) { ! 190: ! 191: DEBUG("Dcreate(%s): access to directory denied",path); ! 192: ! 193: return r; ! 194: ! 195: } ! 196: ! 197: return (*dir.fs->mkdir)(&dir, temp1, DEFAULT_DIRMODE & ~curproc->umask); ! 198: ! 199: } ! 200: ! 201: ! 202: ! 203: long ! 204: ! 205: d_delete(path) ! 206: ! 207: const char *path; ! 208: ! 209: { ! 210: ! 211: fcookie parentdir, targdir; ! 212: ! 213: long r; ! 214: ! 215: PROC *p; ! 216: ! 217: int i; ! 218: ! 219: XATTR xattr; ! 220: ! 221: ! 222: ! 223: TRACE("Ddelete(%s)", path); ! 224: ! 225: ! 226: ! 227: r = path2cookie(path, temp1, &parentdir); ! 228: ! 229: ! 230: ! 231: if (r) { ! 232: ! 233: DEBUG("Ddelete(%s): error %lx", path, r); ! 234: ! 235: return r; ! 236: ! 237: } ! 238: ! 239: /* check for write permission on the directory which the target ! 240: ! 241: * is located ! 242: ! 243: */ ! 244: ! 245: if (r = dir_access(&parentdir, S_IWOTH)) { ! 246: ! 247: DEBUG("Ddelete(%s): access to directory denied", path); ! 248: ! 249: return r; ! 250: ! 251: } ! 252: ! 253: ! 254: ! 255: /* now get the info on the file itself */ ! 256: ! 257: ! 258: ! 259: r = relpath2cookie(&parentdir, temp1, NULL, &targdir, 0); ! 260: ! 261: if (r || (r = (*targdir.fs->getxattr)(&targdir, &xattr))) { ! 262: ! 263: DEBUG("Ddelete: error %ld on %s", r, path); ! 264: ! 265: return r; ! 266: ! 267: } ! 268: ! 269: ! 270: ! 271: /* if the "directory" is a symbolic link, really unlink it */ ! 272: ! 273: if ( (xattr.mode & S_IFMT) == S_IFLNK ) { ! 274: ! 275: return (*parentdir.fs->remove)(&parentdir, temp1); ! 276: ! 277: } ! 278: ! 279: if ( (xattr.mode & S_IFMT) != S_IFDIR ) { ! 280: ! 281: DEBUG("Ddelete: %s is not a directory", path); ! 282: ! 283: return EPTHNF; ! 284: ! 285: } ! 286: ! 287: ! 288: ! 289: /* don't delete anyone else's root or current directory */ ! 290: ! 291: for (p = proclist; p; p = p->gl_next) { ! 292: ! 293: if (p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q) ! 294: ! 295: continue; ! 296: ! 297: for (i = 0; i < NUM_DRIVES; i++) { ! 298: ! 299: if (samefile(&targdir, &p->root[i])) { ! 300: ! 301: DEBUG("Ddelete: directory %s is a root directory", ! 302: ! 303: path); ! 304: ! 305: return EACCDN; ! 306: ! 307: } else if (samefile(&targdir, &p->curdir[i])) { ! 308: ! 309: if (i == p->curdrv && p != curproc) ! 310: ! 311: DEBUG("Ddelete: directory %s is in use", ! 312: ! 313: path); ! 314: ! 315: else { ! 316: ! 317: p->curdir[i] = p->root[i]; ! 318: ! 319: } ! 320: ! 321: } ! 322: ! 323: } ! 324: ! 325: } ! 326: ! 327: ! 328: ! 329: return (*parentdir.fs->rmdir)(&parentdir, temp1); ! 330: ! 331: } ! 332: ! 333: ! 334: ! 335: long ! 336: ! 337: d_setpath(path) ! 338: ! 339: const char *path; ! 340: ! 341: { ! 342: ! 343: fcookie dir; ! 344: ! 345: int drv = curproc->curdrv; ! 346: ! 347: int i; ! 348: ! 349: char c; ! 350: ! 351: long r; ! 352: ! 353: XATTR xattr; ! 354: ! 355: ! 356: ! 357: TRACE("Dsetpath(%s)", path); ! 358: ! 359: ! 360: ! 361: r = path2cookie(path, follow_links, &dir); ! 362: ! 363: ! 364: ! 365: if (r) { ! 366: ! 367: DEBUG("Dsetpath(%s): returning %ld", path, r); ! 368: ! 369: return r; ! 370: ! 371: } ! 372: ! 373: ! 374: ! 375: if (path[0] && path[1] == ':') { ! 376: ! 377: c = *path; ! 378: ! 379: if (c >= 'a' && c <= 'z') ! 380: ! 381: drv = c-'a'; ! 382: ! 383: else if (c >= 'A' && c <= 'Z') ! 384: ! 385: drv = c-'A'; ! 386: ! 387: } ! 388: ! 389: ! 390: ! 391: r = (*dir.fs->getxattr)(&dir, &xattr); ! 392: ! 393: ! 394: ! 395: if (r < 0) { ! 396: ! 397: DEBUG("Dsetpath: file '%s': attributes not found", path); ! 398: ! 399: return r; ! 400: ! 401: } ! 402: ! 403: ! 404: ! 405: if (!(xattr.attr & FA_DIR)) { ! 406: ! 407: DEBUG("Dsetpath(%s): not a directory",path); ! 408: ! 409: return EPTHNF; ! 410: ! 411: } ! 412: ! 413: ! 414: ! 415: /* ! 416: ! 417: * watch out for symbolic links; if c:\foo is a link to d:\bar, then ! 418: ! 419: * "cd c:\foo" should also change the drive to d: ! 420: ! 421: */ ! 422: ! 423: if (drv != UNIDRV && dir.dev != curproc->root[drv].dev) { ! 424: ! 425: for (i = 0; i < NUM_DRIVES; i++) { ! 426: ! 427: if (curproc->root[i].dev == dir.dev && ! 428: ! 429: curproc->root[i].fs == dir.fs) { ! 430: ! 431: if (drv == curproc->curdrv) ! 432: ! 433: curproc->curdrv = i; ! 434: ! 435: drv = i; ! 436: ! 437: break; ! 438: ! 439: } ! 440: ! 441: } ! 442: ! 443: } ! 444: ! 445: curproc->curdir[drv] = dir; ! 446: ! 447: return 0; ! 448: ! 449: } ! 450: ! 451: ! 452: ! 453: long ! 454: ! 455: d_getpath(path, drv) ! 456: ! 457: char *path; ! 458: ! 459: int drv; ! 460: ! 461: { ! 462: ! 463: fcookie *dir, *root; ! 464: ! 465: ! 466: ! 467: TRACE("Dgetpath(%c)", drv + '@'); ! 468: ! 469: if (drv < 0 || drv > NUM_DRIVES) ! 470: ! 471: return EDRIVE; ! 472: ! 473: ! 474: ! 475: drv = (drv == 0) ? curproc->curdrv : drv-1; ! 476: ! 477: ! 478: ! 479: root = &curproc->root[drv]; ! 480: ! 481: ! 482: ! 483: if (!root->fs) { /* maybe not initialized yet? */ ! 484: ! 485: changedrv(drv); ! 486: ! 487: root = &curproc->curdir[drv]; ! 488: ! 489: if (!root->fs) ! 490: ! 491: return EDRIVE; ! 492: ! 493: } ! 494: ! 495: dir = &curproc->curdir[drv]; ! 496: ! 497: ! 498: ! 499: return (*root->fs->getname)(root, dir, path); ! 500: ! 501: } ! 502: ! 503: ! 504: ! 505: long ! 506: ! 507: f_setdta(dta) ! 508: ! 509: DTABUF *dta; ! 510: ! 511: { ! 512: ! 513: ! 514: ! 515: TRACE("Fsetdta: %lx", dta); ! 516: ! 517: curproc->dta = dta; ! 518: ! 519: curproc->base->p_dta = (char *)dta; ! 520: ! 521: return 0; ! 522: ! 523: } ! 524: ! 525: ! 526: ! 527: long ! 528: ! 529: f_getdta() ! 530: ! 531: { ! 532: ! 533: long r; ! 534: ! 535: ! 536: ! 537: r = (long)curproc->dta; ! 538: ! 539: TRACE("Fgetdta: returning %lx", r); ! 540: ! 541: return r; ! 542: ! 543: } ! 544: ! 545: ! 546: ! 547: /* ! 548: ! 549: * Fsfirst/next are actually implemented in terms of opendir/readdir/closedir. ! 550: ! 551: */ ! 552: ! 553: ! 554: ! 555: long ! 556: ! 557: f_sfirst(path, attrib) ! 558: ! 559: const char *path; ! 560: ! 561: int attrib; ! 562: ! 563: { ! 564: ! 565: char *s, *slash; ! 566: ! 567: FILESYS *fs; ! 568: ! 569: fcookie dir, newdir; ! 570: ! 571: DTABUF *dta; ! 572: ! 573: DIR *dirh; ! 574: ! 575: XATTR xattr; ! 576: ! 577: long r; ! 578: ! 579: int i, havelabel; ! 580: ! 581: ! 582: ! 583: /* a special hack just for ksh0.4 -- it uses '/' in a search where ! 584: ! 585: * '\' was better. Note that normally we shouldn't go around changing ! 586: ! 587: * the strings that people send us! ! 588: ! 589: */ ! 590: ! 591: if (curproc->domain == DOM_MINT && !strncmp(path, "x:/*.", 5)) ! 592: ! 593: ((char *)path)[2] = '\\'; ! 594: ! 595: ! 596: ! 597: TRACE("Fsfirst(%s, %x)", path, attrib); ! 598: ! 599: ! 600: ! 601: r = path2cookie(path, temp1, &dir); ! 602: ! 603: ! 604: ! 605: if (r) { ! 606: ! 607: DEBUG("Fsfirst(%s): path2cookie returned %ld", path, r); ! 608: ! 609: return r; ! 610: ! 611: } ! 612: ! 613: ! 614: ! 615: /* ! 616: ! 617: * we need to split the last name (which may be a pattern) off from ! 618: ! 619: * the rest of the path, even if FS_KNOPARSE is true ! 620: ! 621: */ ! 622: ! 623: slash = 0; ! 624: ! 625: s = temp1; ! 626: ! 627: while (*s) { ! 628: ! 629: if (*s == '\\') ! 630: ! 631: slash = s; ! 632: ! 633: s++; ! 634: ! 635: } ! 636: ! 637: ! 638: ! 639: if (slash) { ! 640: ! 641: *slash++ = 0; /* slash now points to a name or pattern */ ! 642: ! 643: r = relpath2cookie(&dir, temp1, follow_links, &newdir, 0); ! 644: ! 645: if (r) { ! 646: ! 647: DEBUG("Fsfirst(%s): lookup returned %ld", path, r); ! 648: ! 649: return r; ! 650: ! 651: } ! 652: ! 653: dir = newdir; ! 654: ! 655: } else { ! 656: ! 657: slash = temp1; ! 658: ! 659: } ! 660: ! 661: ! 662: ! 663: /* BUG? what if there really is an empty file name? */ ! 664: ! 665: if (!*slash) { ! 666: ! 667: DEBUG("Fsfirst: empty pattern"); ! 668: ! 669: return EFILNF; ! 670: ! 671: } ! 672: ! 673: ! 674: ! 675: fs = dir.fs; ! 676: ! 677: dta = curproc->dta; ! 678: ! 679: ! 680: ! 681: /* Now, see if we can find a DIR slot for the search. We use the following ! 682: ! 683: * heuristics to try to avoid destroying a slot: ! 684: ! 685: * (1) if the search doesn't use wildcards, don't bother with a slot ! 686: ! 687: * (2) if an existing slot was for the same DTA address, re-use it ! 688: ! 689: * (3) if there's a free slot, re-use it. Slots are freed when the ! 690: ! 691: * corresponding search is terminated. ! 692: ! 693: */ ! 694: ! 695: ! 696: ! 697: for (i = 0; i < NUM_SEARCH; i++) { ! 698: ! 699: if (curproc->srchdta[i] == dta) { ! 700: ! 701: dirh = &curproc->srchdir[i]; ! 702: ! 703: if (dirh->fc.fs) { ! 704: ! 705: (*dirh->fc.fs->closedir)(dirh); ! 706: ! 707: dirh->fc.fs = 0; ! 708: ! 709: } ! 710: ! 711: curproc->srchdta[i] = 0; /* slot is now free */ ! 712: ! 713: } ! 714: ! 715: } ! 716: ! 717: ! 718: ! 719: /* copy the pattern over into dta_pat into TOS 8.3 form */ ! 720: ! 721: /* remember that "slash" now points at the pattern (it follows the last \, ! 722: ! 723: if any) ! 724: ! 725: */ ! 726: ! 727: copy8_3(dta->dta_pat, slash); ! 728: ! 729: ! 730: ! 731: /* if attrib & FA_LABEL, read the volume label */ ! 732: ! 733: /* BUG: the label date and time are wrong. Does it matter? ! 734: ! 735: */ ! 736: ! 737: havelabel = 0; ! 738: ! 739: if (attrib & FA_LABEL) { ! 740: ! 741: r = (*fs->readlabel)(&dir, dta->dta_name, TOS_NAMELEN); ! 742: ! 743: dta->dta_attrib = FA_LABEL; ! 744: ! 745: dta->dta_time = dta->dta_date = 0; ! 746: ! 747: dta->dta_size = 0; ! 748: ! 749: dta->magic = EVALID; ! 750: ! 751: if (r == 0 && !pat_match(dta->dta_name, dta->dta_pat)) ! 752: ! 753: r = EFILNF; ! 754: ! 755: if (attrib == FA_LABEL) ! 756: ! 757: return r; ! 758: ! 759: else if (r == 0) ! 760: ! 761: havelabel = 1; ! 762: ! 763: } ! 764: ! 765: ! 766: ! 767: if (!havelabel && has_wild(slash) == 0) { /* no wild cards in pattern */ ! 768: ! 769: r = relpath2cookie(&dir, slash, follow_links, &newdir, 0); ! 770: ! 771: if (r == 0) { ! 772: ! 773: r = (*newdir.fs->getxattr)(&newdir, &xattr); ! 774: ! 775: } ! 776: ! 777: if (r) { ! 778: ! 779: DEBUG("Fsfirst(%s): couldn't get file attributes",path); ! 780: ! 781: return r; ! 782: ! 783: } ! 784: ! 785: dta->magic = EVALID; ! 786: ! 787: dta->dta_attrib = xattr.attr; ! 788: ! 789: dta->dta_time = xattr.mtime; ! 790: ! 791: dta->dta_date = xattr.mdate; ! 792: ! 793: dta->dta_size = xattr.size; ! 794: ! 795: strncpy(dta->dta_name, slash, TOS_NAMELEN-1); ! 796: ! 797: dta->dta_name[TOS_NAMELEN-1] = 0; ! 798: ! 799: if (curproc->domain == DOM_TOS && ! 800: ! 801: !(fs->fsflags & FS_CASESENSITIVE)) ! 802: ! 803: strupr(dta->dta_name); ! 804: ! 805: ! 806: ! 807: return 0; ! 808: ! 809: } ! 810: ! 811: ! 812: ! 813: /* There is a wild card. Try to find a slot for an opendir/readdir ! 814: ! 815: * search. NOTE: we also come here if we were asked to search for ! 816: ! 817: * volume labels and found one. ! 818: ! 819: */ ! 820: ! 821: for (i = 0; i < NUM_SEARCH; i++) { ! 822: ! 823: if (curproc->srchdta[i] == 0) ! 824: ! 825: break; ! 826: ! 827: } ! 828: ! 829: if (i == NUM_SEARCH) { ! 830: ! 831: int oldest = 0; int oldtime = curproc->srchtim[0]; ! 832: ! 833: ! 834: ! 835: DEBUG("Fsfirst(%s): having to re-use a directory slot!",path); ! 836: ! 837: for (i = 1; i < NUM_SEARCH; i++) { ! 838: ! 839: if (curproc->srchtim[i] < oldtime) { ! 840: ! 841: oldest = i; ! 842: ! 843: oldtime = curproc->srchtim[i]; ! 844: ! 845: } ! 846: ! 847: } ! 848: ! 849: /* OK, close this directory for re-use */ ! 850: ! 851: i = oldest; ! 852: ! 853: dirh = &curproc->srchdir[i]; ! 854: ! 855: if (dirh->fc.fs) { ! 856: ! 857: (*dirh->fc.fs->closedir)(dirh); ! 858: ! 859: dirh->fc.fs = 0; ! 860: ! 861: } ! 862: ! 863: curproc->srchdta[i] = 0; ! 864: ! 865: } ! 866: ! 867: ! 868: ! 869: /* check to see if we have read permission on the directory (and make ! 870: ! 871: * sure that it really is a directory! ! 872: ! 873: */ ! 874: ! 875: r = dir_access(&dir, S_IROTH); ! 876: ! 877: if (r) { ! 878: ! 879: DEBUG("Fsfirst(%s): access to directory denied",path); ! 880: ! 881: return r; ! 882: ! 883: } ! 884: ! 885: ! 886: ! 887: /* set up the directory for a search */ ! 888: ! 889: dirh = &curproc->srchdir[i]; ! 890: ! 891: dirh->fc = dir; ! 892: ! 893: dirh->index = 0; ! 894: ! 895: dirh->flags = TOS_SEARCH; ! 896: ! 897: r = (*dir.fs->opendir)(dirh, dirh->flags); ! 898: ! 899: if (r != 0) { ! 900: ! 901: DEBUG("Fsfirst(%s): couldn't open directory (error %ld)", ! 902: ! 903: path, r); ! 904: ! 905: return r; ! 906: ! 907: } ! 908: ! 909: ! 910: ! 911: /* mark the slot as in-use */ ! 912: ! 913: curproc->srchdta[i] = dta; ! 914: ! 915: ! 916: ! 917: /* set up the DTA for Fsnext */ ! 918: ! 919: dta->index = i; ! 920: ! 921: dta->magic = SVALID; ! 922: ! 923: dta->dta_sattrib = attrib; ! 924: ! 925: ! 926: ! 927: /* OK, now basically just do Fsnext, except that instead of ENMFIL we ! 928: ! 929: * return EFILNF. ! 930: ! 931: * NOTE: If we already have found a volume label from the search above, ! 932: ! 933: * then we skip the f_snext and just return that. ! 934: ! 935: */ ! 936: ! 937: if (havelabel) ! 938: ! 939: return 0; ! 940: ! 941: ! 942: ! 943: r = f_snext(); ! 944: ! 945: if (r == ENMFIL) r = EFILNF; ! 946: ! 947: if (r) ! 948: ! 949: TRACE("Fsfirst: returning %ld", r); ! 950: ! 951: return r; ! 952: ! 953: } ! 954: ! 955: ! 956: ! 957: /* ! 958: ! 959: * Counter for Fsfirst/Fsnext, so that we know which search slots are ! 960: ! 961: * least recently used. This is updated once per second by the code ! 962: ! 963: * in timeout.c. ! 964: ! 965: * BUG: 1/second is pretty low granularity ! 966: ! 967: */ ! 968: ! 969: ! 970: ! 971: long searchtime; ! 972: ! 973: ! 974: ! 975: long ! 976: ! 977: f_snext() ! 978: ! 979: { ! 980: ! 981: static char buf[TOS_NAMELEN+1]; ! 982: ! 983: DTABUF *dta = curproc->dta; ! 984: ! 985: FILESYS *fs; ! 986: ! 987: fcookie fc; ! 988: ! 989: int i; ! 990: ! 991: DIR *dirh; ! 992: ! 993: long r; ! 994: ! 995: XATTR xattr; ! 996: ! 997: ! 998: ! 999: TRACE("Fsnext"); ! 1000: ! 1001: ! 1002: ! 1003: if (dta->magic == EVALID) { ! 1004: ! 1005: DEBUG("Fsnext: DTA marked a failing search"); ! 1006: ! 1007: return ENMFIL; ! 1008: ! 1009: } ! 1010: ! 1011: if (dta->magic != SVALID) { ! 1012: ! 1013: DEBUG("Fsnext: dta incorrectly set up"); ! 1014: ! 1015: return EINVFN; ! 1016: ! 1017: } ! 1018: ! 1019: ! 1020: ! 1021: i = dta->index; ! 1022: ! 1023: dirh = &curproc->srchdir[i]; ! 1024: ! 1025: curproc->srchtim[i] = searchtime; ! 1026: ! 1027: ! 1028: ! 1029: fs = dirh->fc.fs; ! 1030: ! 1031: if (!fs) /* oops -- the directory got closed somehow */ ! 1032: ! 1033: return EINTRN; ! 1034: ! 1035: ! 1036: ! 1037: /* BUG: f_snext and readdir should check for disk media changes */ ! 1038: ! 1039: ! 1040: ! 1041: for(;;) { ! 1042: ! 1043: r = (*fs->readdir)(dirh, buf, TOS_NAMELEN+1, &fc); ! 1044: ! 1045: ! 1046: ! 1047: if (r == ENAMETOOLONG) { ! 1048: ! 1049: DEBUG("Fsnext: name too long"); ! 1050: ! 1051: continue; /* TOS programs never see these names */ ! 1052: ! 1053: } ! 1054: ! 1055: if (r != 0) { ! 1056: ! 1057: baderror: ! 1058: ! 1059: (void)(*fs->closedir)(dirh); ! 1060: ! 1061: dirh->fc.fs = 0; ! 1062: ! 1063: curproc->srchdta[i] = 0; ! 1064: ! 1065: dta->magic = EVALID; ! 1066: ! 1067: if (r != ENMFIL) ! 1068: ! 1069: DEBUG("Fsnext: returning %ld", r); ! 1070: ! 1071: return r; ! 1072: ! 1073: } ! 1074: ! 1075: ! 1076: ! 1077: if (!pat_match(buf, dta->dta_pat)) ! 1078: ! 1079: continue; /* different patterns */ ! 1080: ! 1081: ! 1082: ! 1083: /* check for search attributes */ ! 1084: ! 1085: r = (*fc.fs->getxattr)(&fc, &xattr); ! 1086: ! 1087: if (r) { ! 1088: ! 1089: DEBUG("Fsnext: couldn't get file attributes"); ! 1090: ! 1091: goto baderror; ! 1092: ! 1093: } ! 1094: ! 1095: /* if the file is a symbolic link, try to find what it's linked to */ ! 1096: ! 1097: if ( (xattr.mode & S_IFMT) == S_IFLNK ) { ! 1098: ! 1099: char linkedto[PATH_MAX]; ! 1100: ! 1101: r = (*fc.fs->readlink)(&fc, linkedto, PATH_MAX); ! 1102: ! 1103: if (r == 0) { ! 1104: ! 1105: /* the "1" tells relpath2cookie that we read a link */ ! 1106: ! 1107: r = relpath2cookie(&dirh->fc, linkedto, ! 1108: ! 1109: follow_links, &fc, 1); ! 1110: ! 1111: if (r == 0) ! 1112: ! 1113: r = (*fc.fs->getxattr)(&fc, &xattr); ! 1114: ! 1115: } ! 1116: ! 1117: if (r) { ! 1118: ! 1119: DEBUG("Fsnext: couldn't follow link: error %ld", ! 1120: ! 1121: r); ! 1122: ! 1123: } ! 1124: ! 1125: } ! 1126: ! 1127: ! 1128: ! 1129: /* silly TOS rules for matching attributes */ ! 1130: ! 1131: if (xattr.attr == 0) break; ! 1132: ! 1133: if (xattr.attr & 0x21) break; ! 1134: ! 1135: if (dta->dta_sattrib & xattr.attr) ! 1136: ! 1137: break; ! 1138: ! 1139: } ! 1140: ! 1141: ! 1142: ! 1143: /* here, we have a match */ ! 1144: ! 1145: dta->dta_attrib = xattr.attr; ! 1146: ! 1147: dta->dta_time = xattr.mtime; ! 1148: ! 1149: dta->dta_date = xattr.mdate; ! 1150: ! 1151: dta->dta_size = xattr.size; ! 1152: ! 1153: strcpy(dta->dta_name, buf); ! 1154: ! 1155: ! 1156: ! 1157: if (curproc->domain == DOM_TOS && !(fs->fsflags & FS_CASESENSITIVE)) { ! 1158: ! 1159: strupr(dta->dta_name); ! 1160: ! 1161: } ! 1162: ! 1163: return 0; ! 1164: ! 1165: } ! 1166: ! 1167: ! 1168: ! 1169: long ! 1170: ! 1171: f_attrib(name, rwflag, attr) ! 1172: ! 1173: const char *name; ! 1174: ! 1175: int rwflag; ! 1176: ! 1177: int attr; ! 1178: ! 1179: { ! 1180: ! 1181: fcookie fc; ! 1182: ! 1183: XATTR xattr; ! 1184: ! 1185: long r; ! 1186: ! 1187: ! 1188: ! 1189: TRACE("Fattrib(%s, %d)", name, attr); ! 1190: ! 1191: ! 1192: ! 1193: r = path2cookie(name, (char *)0, &fc); ! 1194: ! 1195: ! 1196: ! 1197: if (r) { ! 1198: ! 1199: DEBUG("Fattrib(%s): error %ld", name, r); ! 1200: ! 1201: return r; ! 1202: ! 1203: } ! 1204: ! 1205: ! 1206: ! 1207: r = (*fc.fs->getxattr)(&fc, &xattr); ! 1208: ! 1209: ! 1210: ! 1211: if (r) { ! 1212: ! 1213: DEBUG("Fattrib(%s): getxattr returned %ld", name, r); ! 1214: ! 1215: return r; ! 1216: ! 1217: } ! 1218: ! 1219: ! 1220: ! 1221: if (rwflag) { ! 1222: ! 1223: if (attr & (FA_LABEL|FA_DIR)) { ! 1224: ! 1225: DEBUG("Fattrib(%s): illegal attributes specified",name); ! 1226: ! 1227: return EACCDN; ! 1228: ! 1229: } else if (curproc->euid && curproc->euid != xattr.uid) { ! 1230: ! 1231: DEBUG("Fattrib(%s): not the file's owner",name); ! 1232: ! 1233: return EACCDN; ! 1234: ! 1235: } else if (xattr.attr & (FA_LABEL|FA_DIR)) { ! 1236: ! 1237: DEBUG("Fattrib(%s): file is a volume label " ! 1238: ! 1239: "or directory",name); ! 1240: ! 1241: return EACCDN; ! 1242: ! 1243: } ! 1244: ! 1245: return (*fc.fs->chattr)(&fc, attr); ! 1246: ! 1247: } else { ! 1248: ! 1249: return xattr.attr; ! 1250: ! 1251: } ! 1252: ! 1253: } ! 1254: ! 1255: ! 1256: ! 1257: long ! 1258: ! 1259: f_delete(name) ! 1260: ! 1261: const char *name; ! 1262: ! 1263: { ! 1264: ! 1265: fcookie dir; ! 1266: ! 1267: long r; ! 1268: ! 1269: ! 1270: ! 1271: TRACE("Fdelete(%s)", name); ! 1272: ! 1273: ! 1274: ! 1275: r = path2cookie(name, temp1, &dir); ! 1276: ! 1277: ! 1278: ! 1279: if (r) { ! 1280: ! 1281: DEBUG("Fdelete: error %ld", r); ! 1282: ! 1283: return r; ! 1284: ! 1285: } ! 1286: ! 1287: ! 1288: ! 1289: /* check for write permission on directory */ ! 1290: ! 1291: r = dir_access(&dir, S_IWOTH); ! 1292: ! 1293: if (r) { ! 1294: ! 1295: DEBUG("Fdelete(%s): write access to directory denied",name); ! 1296: ! 1297: return r; ! 1298: ! 1299: } ! 1300: ! 1301: /* BUG: we should check here for a read-only file */ ! 1302: ! 1303: return (*dir.fs->remove)(&dir,temp1); ! 1304: ! 1305: } ! 1306: ! 1307: ! 1308: ! 1309: long ! 1310: ! 1311: f_rename(junk, old, new) ! 1312: ! 1313: int junk; /* ignored, for TOS compatibility */ ! 1314: ! 1315: const char *old, *new; ! 1316: ! 1317: { ! 1318: ! 1319: fcookie olddir, newdir, oldfil; ! 1320: ! 1321: XATTR xattr; ! 1322: ! 1323: char temp2[PATH_MAX]; ! 1324: ! 1325: long r; ! 1326: ! 1327: ! 1328: ! 1329: TRACE("Frename(%s, %s)", old, new); ! 1330: ! 1331: ! 1332: ! 1333: r = path2cookie(old, temp2, &olddir); ! 1334: ! 1335: if (r) { ! 1336: ! 1337: DEBUG("Frename(%s,%s): error parsing old name",old,new); ! 1338: ! 1339: return r; ! 1340: ! 1341: } ! 1342: ! 1343: /* check for permissions on the old file ! 1344: ! 1345: * GEMDOS doesn't allow rename if the file is FA_RDONLY ! 1346: ! 1347: * we enforce this restriction only on regular files; processes, ! 1348: ! 1349: * directories, and character special files can be renamed at will ! 1350: ! 1351: */ ! 1352: ! 1353: r = relpath2cookie(&olddir, temp2, follow_links, &oldfil, 0); ! 1354: ! 1355: if (r) { ! 1356: ! 1357: DEBUG("Frename(%s,%s): old file not found",old,new); ! 1358: ! 1359: return r; ! 1360: ! 1361: } ! 1362: ! 1363: r = (*oldfil.fs->getxattr)(&oldfil, &xattr); ! 1364: ! 1365: if (r || ! 1366: ! 1367: ((xattr.mode & S_IFMT) == S_IFREG && (xattr.attr & FA_RDONLY)) ) ! 1368: ! 1369: { ! 1370: ! 1371: DEBUG("Frename(%s,%s): access to old file not granted",old,new); ! 1372: ! 1373: return EACCDN; ! 1374: ! 1375: } ! 1376: ! 1377: r = path2cookie(new, temp1, &newdir); ! 1378: ! 1379: if (r) { ! 1380: ! 1381: DEBUG("Frename(%s,%s): error parsing new name",old,new); ! 1382: ! 1383: return r; ! 1384: ! 1385: } ! 1386: ! 1387: ! 1388: ! 1389: if (newdir.fs != olddir.fs) { ! 1390: ! 1391: DEBUG("Frename(%s,%s): different file systems",old,new); ! 1392: ! 1393: return EXDEV; /* cross device rename */ ! 1394: ! 1395: } ! 1396: ! 1397: ! 1398: ! 1399: /* check for write permission on both directories */ ! 1400: ! 1401: r = dir_access(&olddir, S_IWOTH); ! 1402: ! 1403: if (!r) r = dir_access(&newdir, S_IWOTH); ! 1404: ! 1405: if (r) { ! 1406: ! 1407: DEBUG("Frename(%s,%s): access to a directory denied",old,new); ! 1408: ! 1409: return r; ! 1410: ! 1411: } ! 1412: ! 1413: return (*newdir.fs->rename)(&olddir, temp2, &newdir, temp1); ! 1414: ! 1415: } ! 1416: ! 1417: ! 1418: ! 1419: /* ! 1420: ! 1421: * GEMDOS extension: Dpathconf(name, which) ! 1422: ! 1423: * returns information about filesystem-imposed limits; "name" is the name ! 1424: ! 1425: * of a file or directory about which the limit information is requested; ! 1426: ! 1427: * "which" is the limit requested, as follows: ! 1428: ! 1429: * -1 max. value of "which" allowed ! 1430: ! 1431: * 0 internal limit on open files, if any ! 1432: ! 1433: * 1 max. number of links to a file {LINK_MAX} ! 1434: ! 1435: * 2 max. path name length {PATH_MAX} ! 1436: ! 1437: * 3 max. file name length {NAME_MAX} ! 1438: ! 1439: * 4 no. of bytes in atomic write to FIFO {PIPE_BUF} ! 1440: ! 1441: * 5 file name truncation rules ! 1442: ! 1443: * 6 file name case translation rules ! 1444: ! 1445: * ! 1446: ! 1447: * unlimited values are returned as 0x7fffffffL ! 1448: ! 1449: * ! 1450: ! 1451: * see also Sysconf() in dos.c ! 1452: ! 1453: */ ! 1454: ! 1455: ! 1456: ! 1457: long ! 1458: ! 1459: d_pathconf(name, which) ! 1460: ! 1461: const char *name; ! 1462: ! 1463: int which; ! 1464: ! 1465: { ! 1466: ! 1467: fcookie dir; ! 1468: ! 1469: long r; ! 1470: ! 1471: ! 1472: ! 1473: r = path2cookie(name, (char *)0, &dir); ! 1474: ! 1475: if (r) { ! 1476: ! 1477: DEBUG("Dpathconf(%s): bad path",name); ! 1478: ! 1479: return r; ! 1480: ! 1481: } ! 1482: ! 1483: r = (*dir.fs->pathconf)(&dir, which); ! 1484: ! 1485: if (which == DP_CASE && r == EINVFN) { ! 1486: ! 1487: /* backward compatibility with old .XFS files */ ! 1488: ! 1489: return (dir.fs->fsflags & FS_CASESENSITIVE) ? DP_CASESENS : ! 1490: ! 1491: DP_CASEINSENS; ! 1492: ! 1493: } ! 1494: ! 1495: return r; ! 1496: ! 1497: } ! 1498: ! 1499: ! 1500: ! 1501: /* ! 1502: ! 1503: * GEMDOS extension: Opendir/Readdir/Rewinddir/Closedir offer a new, ! 1504: ! 1505: * POSIX-like alternative to Fsfirst/Fsnext, and as a bonus allow for ! 1506: ! 1507: * arbitrary length file names ! 1508: ! 1509: */ ! 1510: ! 1511: ! 1512: ! 1513: long ! 1514: ! 1515: d_opendir(name, flag) ! 1516: ! 1517: const char *name; ! 1518: ! 1519: int flag; ! 1520: ! 1521: { ! 1522: ! 1523: DIR *dirh; ! 1524: ! 1525: fcookie dir; ! 1526: ! 1527: long r; ! 1528: ! 1529: ! 1530: ! 1531: r = path2cookie(name, follow_links, &dir); ! 1532: ! 1533: if (r) { ! 1534: ! 1535: DEBUG("Dopendir(%s): error %ld", name, r); ! 1536: ! 1537: return r; ! 1538: ! 1539: } ! 1540: ! 1541: r = dir_access(&dir, S_IROTH); ! 1542: ! 1543: if (r) { ! 1544: ! 1545: DEBUG("Dopendir(%s): read permission denied", name); ! 1546: ! 1547: return r; ! 1548: ! 1549: } ! 1550: ! 1551: ! 1552: ! 1553: dirh = (DIR *)umalloc(SIZEOF(DIR)); ! 1554: ! 1555: if (!dirh) return ENSMEM; ! 1556: ! 1557: ! 1558: ! 1559: dirh->fc = dir; ! 1560: ! 1561: dirh->index = 0; ! 1562: ! 1563: dirh->flags = flag; ! 1564: ! 1565: r = (*dir.fs->opendir)(dirh, flag); ! 1566: ! 1567: if (r) { ! 1568: ! 1569: DEBUG("d_opendir(%s): opendir returned %ld", name, r); ! 1570: ! 1571: ufree(dirh); ! 1572: ! 1573: return r; ! 1574: ! 1575: } ! 1576: ! 1577: return (long)dirh; ! 1578: ! 1579: } ! 1580: ! 1581: ! 1582: ! 1583: long ! 1584: ! 1585: d_readdir(len, handle, buf) ! 1586: ! 1587: int len; ! 1588: ! 1589: long handle; ! 1590: ! 1591: char *buf; ! 1592: ! 1593: { ! 1594: ! 1595: DIR *dirh = (DIR *)handle; ! 1596: ! 1597: fcookie fc; ! 1598: ! 1599: ! 1600: ! 1601: if (!dirh->fc.fs) ! 1602: ! 1603: return EIHNDL; ! 1604: ! 1605: return (*dirh->fc.fs->readdir)(dirh, buf, len, &fc); ! 1606: ! 1607: } ! 1608: ! 1609: ! 1610: ! 1611: long ! 1612: ! 1613: d_rewind(handle) ! 1614: ! 1615: long handle; ! 1616: ! 1617: { ! 1618: ! 1619: DIR *dirh = (DIR *)handle; ! 1620: ! 1621: ! 1622: ! 1623: if (!dirh->fc.fs) ! 1624: ! 1625: return EIHNDL; ! 1626: ! 1627: return (*dirh->fc.fs->rewinddir)(dirh); ! 1628: ! 1629: } ! 1630: ! 1631: ! 1632: ! 1633: long ! 1634: ! 1635: d_closedir(handle) ! 1636: ! 1637: long handle; ! 1638: ! 1639: { ! 1640: ! 1641: long r; ! 1642: ! 1643: DIR *dirh = (DIR *)handle; ! 1644: ! 1645: ! 1646: ! 1647: if (!dirh->fc.fs) ! 1648: ! 1649: return EIHNDL; ! 1650: ! 1651: r = (*dirh->fc.fs->closedir)(dirh); ! 1652: ! 1653: dirh->fc.fs = 0; ! 1654: ! 1655: ! 1656: ! 1657: if (r) { ! 1658: ! 1659: DEBUG("Dclosedir: error %ld", r); ! 1660: ! 1661: } ! 1662: ! 1663: ufree(dirh); ! 1664: ! 1665: return r; ! 1666: ! 1667: } ! 1668: ! 1669: ! 1670: ! 1671: /* ! 1672: ! 1673: * GEMDOS extension: Fxattr gets extended attributes for a file. "flag" ! 1674: ! 1675: * is 0 if symbolic links are to be followed (like stat), 1 if not (like ! 1676: ! 1677: * lstat). ! 1678: ! 1679: */ ! 1680: ! 1681: ! 1682: ! 1683: long ! 1684: ! 1685: f_xattr(flag, name, xattr) ! 1686: ! 1687: int flag; ! 1688: ! 1689: const char *name; ! 1690: ! 1691: XATTR *xattr; ! 1692: ! 1693: { ! 1694: ! 1695: fcookie fc; ! 1696: ! 1697: long r; ! 1698: ! 1699: ! 1700: ! 1701: TRACE("Fxattr(%d, %s)", flag, name); ! 1702: ! 1703: ! 1704: ! 1705: r = path2cookie(name, flag ? (char *)0 : follow_links, &fc); ! 1706: ! 1707: if (r) { ! 1708: ! 1709: DEBUG("Fxattr(%s): path2cookie returned %ld", name, r); ! 1710: ! 1711: return r; ! 1712: ! 1713: } ! 1714: ! 1715: r = (*fc.fs->getxattr)(&fc, xattr); ! 1716: ! 1717: if (r) { ! 1718: ! 1719: DEBUG("Fxattr(%s): returning %ld", name, r); ! 1720: ! 1721: } ! 1722: ! 1723: return r; ! 1724: ! 1725: } ! 1726: ! 1727: ! 1728: ! 1729: /* ! 1730: ! 1731: * GEMDOS extension: Flink(old, new) creates a hard link named "new" ! 1732: ! 1733: * to the file "old". ! 1734: ! 1735: */ ! 1736: ! 1737: ! 1738: ! 1739: long ! 1740: ! 1741: f_link(old, new) ! 1742: ! 1743: const char *old, *new; ! 1744: ! 1745: { ! 1746: ! 1747: fcookie olddir, newdir; ! 1748: ! 1749: char temp2[PATH_MAX]; ! 1750: ! 1751: long r; ! 1752: ! 1753: ! 1754: ! 1755: TRACE("Flink(%s, %s)", old, new); ! 1756: ! 1757: ! 1758: ! 1759: r = path2cookie(old, temp2, &olddir); ! 1760: ! 1761: if (r) { ! 1762: ! 1763: DEBUG("Flink(%s,%s): error parsing old name",old,new); ! 1764: ! 1765: return r; ! 1766: ! 1767: } ! 1768: ! 1769: r = path2cookie(new, temp1, &newdir); ! 1770: ! 1771: if (r) { ! 1772: ! 1773: DEBUG("Flink(%s,%s): error parsing new name",old,new); ! 1774: ! 1775: return r; ! 1776: ! 1777: } ! 1778: ! 1779: ! 1780: ! 1781: if (newdir.fs != olddir.fs) { ! 1782: ! 1783: DEBUG("Flink(%s,%s): different file systems",old,new); ! 1784: ! 1785: return EXDEV; /* cross device link */ ! 1786: ! 1787: } ! 1788: ! 1789: ! 1790: ! 1791: /* check for write permission on the destination directory */ ! 1792: ! 1793: ! 1794: ! 1795: r = dir_access(&newdir, S_IWOTH); ! 1796: ! 1797: if (r) { ! 1798: ! 1799: DEBUG("Flink(%s,%s): access to directory denied",old,new); ! 1800: ! 1801: return r; ! 1802: ! 1803: } ! 1804: ! 1805: return (*newdir.fs->hardlink)(&olddir, temp2, &newdir, temp1); ! 1806: ! 1807: } ! 1808: ! 1809: ! 1810: ! 1811: /* ! 1812: ! 1813: * GEMDOS extension: Fsymlink(old, new): create a symbolic link named ! 1814: ! 1815: * "new" that contains the path "old". ! 1816: ! 1817: */ ! 1818: ! 1819: ! 1820: ! 1821: long ! 1822: ! 1823: f_symlink(old, new) ! 1824: ! 1825: const char *old, *new; ! 1826: ! 1827: { ! 1828: ! 1829: fcookie newdir; ! 1830: ! 1831: long r; ! 1832: ! 1833: ! 1834: ! 1835: TRACE("Fsymlink(%s, %s)", old, new); ! 1836: ! 1837: ! 1838: ! 1839: r = path2cookie(new, temp1, &newdir); ! 1840: ! 1841: if (r) { ! 1842: ! 1843: DEBUG("Fsymlink(%s,%s): error parsing %s", old,new,new); ! 1844: ! 1845: return r; ! 1846: ! 1847: } ! 1848: ! 1849: r = dir_access(&newdir, S_IWOTH); ! 1850: ! 1851: if (r) { ! 1852: ! 1853: DEBUG("Fsymlink(%s,%s): access to directory denied",old,new); ! 1854: ! 1855: return r; ! 1856: ! 1857: } ! 1858: ! 1859: return (*newdir.fs->symlink)(&newdir, temp1, old); ! 1860: ! 1861: } ! 1862: ! 1863: ! 1864: ! 1865: /* ! 1866: ! 1867: * GEMDOS extension: Freadlink(buflen, buf, linkfile): ! 1868: ! 1869: * read the contents of the symbolic link "linkfile" into the buffer ! 1870: ! 1871: * "buf", which has length "buflen". ! 1872: ! 1873: */ ! 1874: ! 1875: ! 1876: ! 1877: long ! 1878: ! 1879: f_readlink(buflen, buf, linkfile) ! 1880: ! 1881: int buflen; ! 1882: ! 1883: char *buf; ! 1884: ! 1885: const char *linkfile; ! 1886: ! 1887: { ! 1888: ! 1889: fcookie file; ! 1890: ! 1891: long r; ! 1892: ! 1893: XATTR xattr; ! 1894: ! 1895: ! 1896: ! 1897: TRACE("Freadlink(%s)", linkfile); ! 1898: ! 1899: ! 1900: ! 1901: r = path2cookie(linkfile, (char *)0, &file); ! 1902: ! 1903: if (r) { ! 1904: ! 1905: DEBUG("Freadlink: unable to find %s", linkfile); ! 1906: ! 1907: return r; ! 1908: ! 1909: } ! 1910: ! 1911: r = (*file.fs->getxattr)(&file, &xattr); ! 1912: ! 1913: if (r) { ! 1914: ! 1915: DEBUG("Freadlink: unable to get attributes for %s", linkfile); ! 1916: ! 1917: return r; ! 1918: ! 1919: } ! 1920: ! 1921: if ( (xattr.mode & S_IFMT) == S_IFLNK ) ! 1922: ! 1923: return (*file.fs->readlink)(&file, buf, buflen); ! 1924: ! 1925: ! 1926: ! 1927: DEBUG("Freadlink: %s is not a link", linkfile); ! 1928: ! 1929: return EACCDN; ! 1930: ! 1931: } ! 1932: ! 1933: ! 1934: ! 1935: /* ! 1936: ! 1937: * GEMDOS extension: Dcntl(): do file system specific functions ! 1938: ! 1939: */ ! 1940: ! 1941: ! 1942: ! 1943: long ! 1944: ! 1945: d_cntl(cmd, name, arg) ! 1946: ! 1947: int cmd; ! 1948: ! 1949: const char *name; ! 1950: ! 1951: long arg; ! 1952: ! 1953: { ! 1954: ! 1955: fcookie dir; ! 1956: ! 1957: long r; ! 1958: ! 1959: ! 1960: ! 1961: TRACE("Dcntl(cmd=%x, file=%s, arg=%lx)", cmd, name, arg); ! 1962: ! 1963: ! 1964: ! 1965: r = path2cookie(name, temp1, &dir); ! 1966: ! 1967: if (r) { ! 1968: ! 1969: DEBUG("Dcntl: couldn't find %s", name); ! 1970: ! 1971: return r; ! 1972: ! 1973: } ! 1974: ! 1975: return (*dir.fs->fscntl)(&dir, temp1, cmd, arg); ! 1976: ! 1977: } ! 1978: ! 1979: ! 1980: ! 1981: /* ! 1982: ! 1983: * GEMDOS extension: Fchown(name, uid, gid) changes the user and group ! 1984: ! 1985: * ownerships of a file to "uid" and "gid" respectively. ! 1986: ! 1987: */ ! 1988: ! 1989: ! 1990: ! 1991: long ! 1992: ! 1993: f_chown(name, uid, gid) ! 1994: ! 1995: const char *name; ! 1996: ! 1997: int uid, gid; ! 1998: ! 1999: { ! 2000: ! 2001: fcookie fc; ! 2002: ! 2003: XATTR xattr; ! 2004: ! 2005: long r; ! 2006: ! 2007: ! 2008: ! 2009: TRACE("Fchown(%s, %d, %d)", name, uid, gid); ! 2010: ! 2011: ! 2012: ! 2013: r = path2cookie(name, follow_links, &fc); ! 2014: ! 2015: if (r) { ! 2016: ! 2017: DEBUG("Fchown(%s): error %ld", name, r); ! 2018: ! 2019: return r; ! 2020: ! 2021: } ! 2022: ! 2023: ! 2024: ! 2025: /* MiNT acts like _POSIX_CHOWN_RESTRICTED: a non-privileged process can ! 2026: ! 2027: * only change the ownership of a file that is owned by this user, to ! 2028: ! 2029: * the effective group id of the process ! 2030: ! 2031: */ ! 2032: ! 2033: if (curproc->euid) { ! 2034: ! 2035: if (curproc->egid != gid) return EACCDN; ! 2036: ! 2037: r = (*fc.fs->getxattr)(&fc, &xattr); ! 2038: ! 2039: if (r) { ! 2040: ! 2041: DEBUG("Fchown(%s): unable to get file attributes",name); ! 2042: ! 2043: return r; ! 2044: ! 2045: } ! 2046: ! 2047: if (xattr.uid != curproc->euid || xattr.uid != uid) { ! 2048: ! 2049: DEBUG("Fchown(%s): not the file's owner",name); ! 2050: ! 2051: return EACCDN; ! 2052: ! 2053: } ! 2054: ! 2055: } ! 2056: ! 2057: return (*fc.fs->chown)(&fc, uid, gid); ! 2058: ! 2059: } ! 2060: ! 2061: ! 2062: ! 2063: /* ! 2064: ! 2065: * GEMDOS extension: Fchmod(file, mode) changes a file's access ! 2066: ! 2067: * permissions. ! 2068: ! 2069: */ ! 2070: ! 2071: ! 2072: ! 2073: long ! 2074: ! 2075: f_chmod(name, mode) ! 2076: ! 2077: const char *name; ! 2078: ! 2079: unsigned mode; ! 2080: ! 2081: { ! 2082: ! 2083: fcookie fc; ! 2084: ! 2085: long r; ! 2086: ! 2087: XATTR xattr; ! 2088: ! 2089: ! 2090: ! 2091: TRACE("Fchmod(%s, %o)", name, mode); ! 2092: ! 2093: r = path2cookie(name, follow_links, &fc); ! 2094: ! 2095: if (r) { ! 2096: ! 2097: DEBUG("Fchmod(%s): error %ld", name, r); ! 2098: ! 2099: return r; ! 2100: ! 2101: } ! 2102: ! 2103: r = (*fc.fs->getxattr)(&fc, &xattr); ! 2104: ! 2105: if (r) { ! 2106: ! 2107: DEBUG("Fchmod(%s): couldn't get file attributes",name); ! 2108: ! 2109: return r; ! 2110: ! 2111: } ! 2112: ! 2113: if (curproc->euid && curproc->euid != xattr.uid) { ! 2114: ! 2115: DEBUG("Fchmod(%s): not the file's owner",name); ! 2116: ! 2117: return EACCDN; ! 2118: ! 2119: } ! 2120: ! 2121: r = (*fc.fs->chmode)(&fc, mode & ~S_IFMT); ! 2122: ! 2123: if (r) DEBUG("Fchmod: error %ld", r); ! 2124: ! 2125: return r; ! 2126: ! 2127: } ! 2128: ! 2129: ! 2130: ! 2131: /* ! 2132: ! 2133: * GEMDOS extension: Dlock(mode, dev): locks or unlocks access to ! 2134: ! 2135: * a BIOS device. "mode" is 0 for unlock, 1 for lock; "dev" is a ! 2136: ! 2137: * BIOS device (0 for A:, 1 for B:, etc.). ! 2138: ! 2139: * Returns: 0 if the operation was successful ! 2140: ! 2141: * EACCDN if a lock attempt is made on a drive that is being ! 2142: ! 2143: * used ! 2144: ! 2145: * ELOCKED if the drive is locked by another process ! 2146: ! 2147: * ENSLOCK if a program attempts to unlock a drive it ! 2148: ! 2149: * hasn't locked. ! 2150: ! 2151: */ ! 2152: ! 2153: ! 2154: ! 2155: PROC *dlockproc[NUM_DRIVES]; ! 2156: ! 2157: ! 2158: ! 2159: long ! 2160: ! 2161: d_lock(mode, dev) ! 2162: ! 2163: int mode, dev; ! 2164: ! 2165: { ! 2166: ! 2167: PROC *p; ! 2168: ! 2169: FILEPTR *f; ! 2170: ! 2171: int i; ! 2172: ! 2173: DIR *dirh; ! 2174: ! 2175: ! 2176: ! 2177: TRACE("Dlock(%x,%c:)", mode, dev+'A'); ! 2178: ! 2179: if (dev < 0 || dev >= NUM_DRIVES) return EDRIVE; ! 2180: ! 2181: ! 2182: ! 2183: if ( (mode&1) == 0) { /* unlock */ ! 2184: ! 2185: if (dlockproc[dev] == curproc) { ! 2186: ! 2187: dlockproc[dev] = 0; ! 2188: ! 2189: changedrv(dev); ! 2190: ! 2191: return 0; ! 2192: ! 2193: } ! 2194: ! 2195: DEBUG("Dlock: no such lock"); ! 2196: ! 2197: return ENSLOCK; ! 2198: ! 2199: } ! 2200: ! 2201: ! 2202: ! 2203: /* code for locking */ ! 2204: ! 2205: /* is the drive already locked? */ ! 2206: ! 2207: if (dlockproc[dev]) { ! 2208: ! 2209: DEBUG("Dlock: drive already locked"); ! 2210: ! 2211: return (dlockproc[dev] == curproc) ? 0 : ELOCKED; ! 2212: ! 2213: } ! 2214: ! 2215: /* see if the drive is in use */ ! 2216: ! 2217: for (p = proclist; p; p = p->gl_next) { ! 2218: ! 2219: if (p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q) ! 2220: ! 2221: continue; ! 2222: ! 2223: for (i = MIN_HANDLE; i < MAX_OPEN; i++) { ! 2224: ! 2225: if ( ((f = p->handle[i]) != 0) && (f->fc.dev == dev) ) { ! 2226: ! 2227: DEBUG("Dlock: process %d has an open handle on the drive", p->pid); ! 2228: ! 2229: return EACCDN; ! 2230: ! 2231: } ! 2232: ! 2233: } ! 2234: ! 2235: for (i = 0; i < NUM_SEARCH; i++) { ! 2236: ! 2237: dirh = &curproc->srchdir[i]; ! 2238: ! 2239: if (dirh && dirh->fc.fs && dirh->fc.dev == dev) { ! 2240: ! 2241: DEBUG("Dlock: process %d has an open directory on the drive",p->pid); ! 2242: ! 2243: return EACCDN; ! 2244: ! 2245: } ! 2246: ! 2247: } ! 2248: ! 2249: } ! 2250: ! 2251: ! 2252: ! 2253: /* if we reach here, the drive is not in use */ ! 2254: ! 2255: /* we lock it by setting dlockproc and by setting all root and current ! 2256: ! 2257: * directories referring to the device to a null file system ! 2258: ! 2259: */ ! 2260: ! 2261: for (p = proclist; p; p = p->gl_next) { ! 2262: ! 2263: for (i = 0; i < NUM_DRIVES; i++) { ! 2264: ! 2265: if (p->root[i].dev == dev) ! 2266: ! 2267: p->root[i].fs = 0; ! 2268: ! 2269: if (p->curdir[i].dev == dev) ! 2270: ! 2271: p->curdir[i].fs = 0; ! 2272: ! 2273: } ! 2274: ! 2275: } ! 2276: ! 2277: ! 2278: ! 2279: dlockproc[dev] = curproc; ! 2280: ! 2281: return 0; ! 2282: ! 2283: } ! 2284:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.