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