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