|
|
1.1 root 1: /*
2:
1.1.1.3 ! root 3: Copyright 1990,1991,1992 Eric R. Smith.
! 4:
! 5: Copyright 1992 Atari Corp.
! 6:
! 7: All rights reserved.
1.1 root 8:
9: */
10:
11:
12:
13: /*
14:
15: * various file system interface things
16:
17: */
18:
19:
20:
21: #include "mint.h"
22:
23:
24:
1.1.1.3 ! root 25: #define PATH2COOKIE_DB(x) TRACE(x)
! 26:
! 27:
! 28:
1.1 root 29: FILESYS *active_fs;
30:
31: FILESYS *drives[NUM_DRIVES];
32:
1.1.1.3 ! root 33: extern FILESYS tos_filesys; /* declaration needed for debugging only */
! 34:
1.1 root 35:
36:
1.1.1.2 root 37: /* "aliased" drives are different names
38:
39: * for real drives/directories
40:
41: * if drive d is an alias for c:\usr,
42:
43: * then alias_drv[3] == 2 (the real
44:
45: * drive) and aliases has bit (1L << 3)
46:
47: * set.
48:
49: * NOTE: if aliasdrv[d] is 0, then d is not an aliased drive,
50:
51: * otherwise d is aliased to drive aliasdrv[d]-1
52:
53: * (e.g. if drive A: is aliased to B:\FOO, then
54:
55: * aliasdrv[0] == 'B'-'A'+1 == 2). Always remember to
56:
57: * compensate for the extra 1 when dereferencing aliasdrv!
58:
59: */
60:
61: int aliasdrv[NUM_DRIVES];
62:
63:
64:
1.1 root 65: FILEPTR *flist; /* a list of free file pointers */
66:
67:
68:
69: char follow_links[1]; /* dummy "name" used as a parameter to path2cookie */
70:
71:
72:
73: /* vector of valid drives, according to GEMDOS */
74:
75: /* note that this isn't necessarily the same as what the BIOS thinks of
76:
77: * as valid
78:
79: */
80:
81: long dosdrvs;
82:
83:
84:
85: /*
86:
87: * Initialize a specific drive. This is called whenever a new drive
88:
89: * is accessed, or when media change occurs on an old drive.
90:
91: * Assumption: at this point, active_fs is a valid pointer
92:
93: * to a list of file systems.
94:
95: */
96:
97:
98:
99: /* table of processes holding locks on drives */
100:
101: extern PROC *dlockproc[]; /* in dosdir.c */
102:
103:
104:
105: void
106:
107: init_drive(i)
108:
109: int i;
110:
111: {
112:
113: long r;
114:
115: FILESYS *fs;
116:
117: fcookie root_dir;
118:
119:
120:
1.1.1.2 root 121: TRACE(("init_drive(%c)", i+'A'));
1.1 root 122:
123:
124:
125: drives[i] = 0; /* no file system */
126:
127: if (i >= 0 && i < NUM_DRIVES) {
128:
129: if (dlockproc[i]) return;
130:
131: }
132:
133:
134:
135: for (fs = active_fs; fs; fs = fs->next) {
136:
137: r = (*fs->root)(i, &root_dir);
138:
139: if (r == 0) {
140:
141: drives[i] = root_dir.fs;
142:
1.1.1.3 ! root 143: release_cookie(&root_dir);
! 144:
1.1 root 145: break;
146:
147: }
148:
149: }
150:
151: }
152:
153:
154:
155: /*
156:
157: * initialize the file system
158:
159: */
160:
161:
162:
163: #define NUMFPS 40 /* initial number of file pointers */
164:
165:
166:
167: void
168:
169: init_filesys()
170:
171: {
172:
173: static FILEPTR initial[NUMFPS+1];
174:
175: int i;
176:
177: extern FILESYS tos_filesys, bios_filesys, pipe_filesys,
178:
179: proc_filesys, uni_filesys;
180:
181:
182:
183: /* get the vector of connected GEMDOS drives */
184:
185: dosdrvs = Dsetdrv(Dgetdrv()) | drvmap();
186:
187:
188:
189: /* set up some initial file pointers */
190:
191: for (i = 0; i < NUMFPS; i++) {
192:
193: initial[i].devinfo = (ulong) (&initial[i+1]);
194:
195: }
196:
197: initial[NUMFPS].devinfo = 0;
198:
199: flist = initial;
200:
201:
202:
203: /* set up the file systems */
204:
205: tos_filesys.next = 0;
206:
207: bios_filesys.next = &tos_filesys;
208:
209: pipe_filesys.next = &bios_filesys;
210:
211: proc_filesys.next = &pipe_filesys;
212:
213: uni_filesys.next = &proc_filesys;
214:
215:
216:
217: active_fs = &uni_filesys;
218:
219:
220:
221: /* initialize the BIOS file system */
222:
223: biosfs_init();
224:
225:
226:
227: /* initialize the unified file system */
228:
229: unifs_init();
230:
231: }
232:
233:
234:
235: /*
236:
237: * load file systems from disk
238:
239: * this routine is called after process 0 is set up, but before any user
240:
241: * processes are run
242:
243: *
244:
245: * NOTE that a number of directory changes take place here: we look first
246:
247: * in the current directory, then in the directory \mint, and finally
248:
249: * the d_lock() calls force us into the root directory.
250:
251: */
252:
253:
254:
1.1.1.2 root 255: typedef FILESYS * ARGS_ON_STACK (*FSFUNC) P_((struct kerinfo *));
1.1 root 256:
257:
258:
259: void
260:
261: load_filesys()
262:
263: {
264:
265: long r;
266:
267: BASEPAGE *b;
268:
269: FILESYS *fs;
270:
271: FSFUNC initf;
272:
273: static DTABUF dta;
274:
275: int i;
276:
277: extern struct kerinfo kernelinfo; /* in main.c */
278:
1.1.1.2 root 279: char curpath[PATH_MAX];
280:
1.1.1.3 ! root 281: MEMREGION *xfsreg;
! 282:
! 283: #define NPATHS 3
1.1 root 284:
1.1.1.3 ! root 285: static const char *paths[NPATHS] = {"", "\\MINT", "\\MULTITOS"};
1.1 root 286:
287:
288:
289: curproc->dta = &dta;
290:
1.1.1.2 root 291: d_getpath(curpath,0);
292:
1.1 root 293:
294:
295: for (i = 0; i < NPATHS; i++) {
296:
1.1.1.2 root 297: if (*paths[i]) {
298:
299: /* don't bother checking the current directory twice! */
300:
301: if (!stricmp(paths[i],curpath))
302:
303: r = -1;
304:
305: else
306:
307: r = d_setpath(paths[i]);
308:
309: }
310:
311: else
312:
313: r = 0;
314:
315:
316:
317: if (r == 0)
318:
319: r = f_sfirst("*.xfs", 0);
1.1 root 320:
321:
322:
323: while (r == 0) {
324:
325: b = (BASEPAGE *)p_exec(3, dta.dta_name, (char *)"", (char *)0);
326:
327: if ( ((long)b) < 0 ) {
328:
1.1.1.2 root 329: DEBUG(("Error loading file system %s", dta.dta_name));
330:
331: r = f_snext();
1.1 root 332:
333: continue;
334:
335: }
336:
337: /* we leave a little bit of slop at the end of the loaded stuff */
338:
339: m_shrink(0, (virtaddr)b, 512 + b->p_tlen + b->p_dlen + b->p_blen);
340:
341: initf = (FSFUNC)b->p_tbase;
342:
1.1.1.2 root 343: TRACE(("initializing %s", dta.dta_name));
1.1 root 344:
1.1.1.2 root 345: fs = (*initf)(&kernelinfo);
1.1 root 346:
347:
348:
349: if (fs) {
350:
1.1.1.2 root 351: TRACE(("%s loaded OK", dta.dta_name));
1.1 root 352:
1.1.1.3 ! root 353: /* put the loaded XFS into super accesible memory */
! 354:
! 355: xfsreg = addr2region( (long) b );
! 356:
! 357: mark_region(xfsreg, PROT_S);
! 358:
! 359: /* link it into the list of drivers */
! 360:
1.1 root 361: fs->next = active_fs;
362:
363: active_fs = fs;
364:
365: } else {
366:
1.1.1.2 root 367: DEBUG(("%s returned null", dta.dta_name));
1.1 root 368:
1.1.1.3 ! root 369: m_free((virtaddr)b);
! 370:
1.1 root 371: }
372:
373: r = f_snext();
374:
375: }
376:
377: }
378:
379:
380:
381: /* here, we invalidate all old drives EXCEPT for ones we're already using (at
382:
383: * this point, only the bios devices should be open)
384:
385: * this gives newly loaded file systems a chance to replace the
386:
387: * default tosfs.c
388:
389: */
390:
391: for (i = 0; i < NUM_DRIVES; i++) {
392:
393: if (d_lock(1, i) == 0) /* lock if possible */
394:
395: d_lock(0, i); /* and then unlock */
396:
397: }
398:
399: }
400:
401:
402:
403: void
404:
405: close_filesys()
406:
407: {
408:
409: PROC *p;
410:
411: FILEPTR *f;
412:
413: int i;
414:
415:
416:
1.1.1.2 root 417: TRACE(("close_filesys"));
1.1 root 418:
419: /* close every open file */
420:
421: for (p = proclist; p; p = p->gl_next) {
422:
423: for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
424:
425: if ( (f = p->handle[i]) != 0) {
426:
427: if (p->wait_q == TSR_Q || p->wait_q == ZOMBIE_Q)
428:
429: ALERT("Open file for dead process?");
430:
431: do_pclose(p, f);
432:
433: }
434:
435: }
436:
437: }
438:
439: }
440:
441:
442:
443: /*
444:
445: * "media change" routine: called when a media change is detected on device
446:
447: * d, which may or may not be a BIOS device. All handles associated with
448:
449: * the device are closed, and all directories invalidated. This routine
450:
451: * does all the dirty work, and is called automatically when
452:
453: * disk_changed detects a media change.
454:
455: */
456:
457:
458:
1.1.1.2 root 459: void ARGS_ON_STACK
1.1 root 460:
461: changedrv(d)
462:
463: unsigned d;
464:
465: {
466:
467: PROC *p;
468:
469: int i;
470:
471: FILEPTR *f;
472:
473: FILESYS *fs;
474:
1.1.1.3 ! root 475: SHTEXT *stext;
! 476:
! 477: extern SHTEXT *text_reg; /* in mem.c */
! 478:
1.1 root 479: DIR *dirh;
480:
481: fcookie dir;
482:
483: int warned = (d & 0xf000) == PROC_BASE_DEV;
484:
1.1.1.2 root 485: long r;
486:
487:
488:
489: /* if an aliased drive, change the *real* device */
490:
491: if (d < NUM_DRIVES && aliasdrv[d]) {
492:
493: d = aliasdrv[d] - 1; /* see NOTE above */
494:
495: }
1.1 root 496:
497:
498:
499: /* re-initialize the device, if it was a BIOS device */
500:
501: if (d < NUM_DRIVES) {
502:
503: fs = drives[d];
504:
505: if (fs) {
506:
507: (void)(*fs->dskchng)(d);
508:
509: }
510:
511: init_drive(d);
512:
513: }
514:
515:
516:
517: for (p = proclist; p; p = p->gl_next) {
518:
519: /* invalidate all open files on this device */
520:
521: for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
522:
523: if (((f = p->handle[i]) != 0) && (f->fc.dev == d)) {
524:
525: if (!warned) {
526:
527: ALERT(
528:
529: "Files were open on a changed drive (0x%x)!", d);
530:
531: warned++;
532:
533: }
534:
535:
536:
537: /* we set f->dev to NULL to indicate to do_pclose that this is an
538:
539: * emergency close, and that it shouldn't try to make any
540:
541: * calls to the device driver since the file has gone away
542:
543: */
544:
545: f->dev = NULL;
546:
547: (void)do_pclose(p, f);
548:
1.1.1.2 root 549: /* we could just zero the handle, but this could lead to confusion if
550:
551: * a process doesn't realize that there's been a media change, Fopens
552:
553: * a new file, and gets the same handle back. So, we force the
554:
555: * handle to point to /dev/null.
556:
557: */
558:
559: p->handle[i] =
560:
561: do_open("U:\\DEV\\NULL", O_RDWR, 0, (XATTR *)0);
1.1 root 562:
563: }
564:
565: }
566:
567:
568:
569: /* terminate any active directory searches on the drive */
570:
571: /* BUG: This handles only Fsfirst/Fsnext searches! */
572:
573: for (i = 0; i < NUM_SEARCH; i++) {
574:
1.1.1.2 root 575: dirh = &p->srchdir[i];
1.1 root 576:
577: if (dirh->fc.fs && dirh->fc.dev == d) {
578:
1.1.1.2 root 579: TRACE(("closing search for process %d", p->pid));
580:
1.1.1.3 ! root 581: release_cookie(&dirh->fc);
! 582:
1.1 root 583: dirh->fc.fs = 0;
584:
1.1.1.2 root 585: p->srchdta[i] = 0;
1.1 root 586:
587: }
588:
589: }
590:
591:
592:
593: if (d >= NUM_DRIVES) continue;
594:
595:
596:
597: /* change any active directories on the device to the (new) root */
598:
599: fs = drives[d];
600:
601: if (fs) {
602:
603: r = (*fs->root)(d, &dir);
604:
605: if (r != E_OK) dir.fs = 0;
606:
607: } else {
608:
609: dir.fs = 0; dir.dev = d;
610:
611: }
612:
613:
614:
615: for (i = 0; i < NUM_DRIVES; i++) {
616:
1.1.1.3 ! root 617: if (p->root[i].dev == d) {
! 618:
! 619: release_cookie(&p->root[i]);
1.1 root 620:
1.1.1.3 ! root 621: dup_cookie(&p->root[i], &dir);
! 622:
! 623: }
1.1 root 624:
1.1.1.3 ! root 625: if (p->curdir[i].dev == d) {
1.1 root 626:
1.1.1.3 ! root 627: release_cookie(&p->curdir[i]);
! 628:
! 629: dup_cookie(&p->curdir[i], &dir);
! 630:
! 631: }
! 632:
! 633: }
! 634:
! 635: release_cookie(&dir);
! 636:
! 637: }
! 638:
! 639:
! 640:
! 641: /* free any file descriptors associated with shared text regions */
! 642:
! 643: for (stext = text_reg; stext; stext = stext->next) {
! 644:
! 645: f = stext->f;
! 646:
! 647: if (f->fc.dev == d) {
! 648:
! 649: f->dev = NULL;
! 650:
! 651: do_pclose(rootproc, f);
! 652:
! 653: stext->f = 0;
1.1 root 654:
655: }
656:
657: }
658:
659: }
660:
661:
662:
663: /*
664:
665: * check for media change: if the drive has changed, call changedrv to
666:
667: * invalidate any open files and file handles associated with it, and
668:
669: * call the file system's media change routine.
670:
671: * returns: 0 if no change, 1 if change
672:
673: */
674:
675:
676:
677: int
678:
679: disk_changed(d)
680:
681: int d;
682:
683: {
684:
685: short r;
686:
687: FILESYS *fs;
688:
689: static char tmpbuf[8192];
690:
691:
692:
693: /* for now, only check BIOS devices */
694:
695: if (d < 0 || d >= NUM_DRIVES)
696:
697: return 0;
698:
1.1.1.2 root 699: /* watch out for aliased drives */
700:
701: if (aliasdrv[d]) {
702:
703: d = aliasdrv[d] - 1;
704:
705: if (d < 0 || d >= NUM_DRIVES)
706:
707: return 0;
708:
709: }
710:
1.1 root 711:
712:
713: /* has the drive been initialized yet? If not, then initialize it and return
714:
715: * "no change"
716:
717: */
718:
1.1.1.2 root 719: fs = drives[d];
720:
721: if (!fs) {
1.1 root 722:
1.1.1.2 root 723: TRACE(("drive %c not yet initialized", d+'A'));
1.1 root 724:
725: changedrv(d);
726:
727: return 0;
728:
729: }
730:
731:
732:
733: /* We have to do this stuff no matter what, because someone may have installed
734:
735: * vectors to force a media change...
736:
737: * PROBLEM: AHDI may get upset if the drive isn't valid.
738:
739: * SOLUTION: don't change the default PSEUDODRIVES setting!
740:
741: */
742:
743: r = mediach(d);
744:
745: if (r == 1) { /* drive _may_ have changed */
746:
747: r = rwabs(0, tmpbuf, 1, 0, d, 0L); /* check the BIOS */
748:
749: if (r != E_CHNG) { /* nope, no change */
750:
751: return 0;
752:
753: }
754:
755: r = 2; /* drive was definitely changed */
756:
757: }
758:
759: if (r == 2) {
760:
761: fs = drives[d]; /* get filesystem associated with drive */
762:
763: if ((*fs->dskchng)(d)) { /* does the fs agree that it changed? */
764:
1.1.1.2 root 765: drives[d] = 0;
766:
1.1 root 767: changedrv(d); /* yes -- do the change */
768:
769: return 1;
770:
771: }
772:
773: }
774:
775: return 0;
776:
777: }
778:
779:
780:
781: /*
782:
783: * routines for parsing path names
784:
785: */
786:
787:
788:
789: char temp1[PATH_MAX]; /* temporary storage for file names */
790:
791:
792:
793: #define DIRSEP(p) ((p) == '\\')
794:
795:
796:
797: /*
798:
799: * relpath2cookie converts a TOS file name into a file cookie representing
800:
801: * the directory the file resides in, and a character string representing
802:
803: * the name of the file in that directory. The character string is
804:
805: * copied into the "lastname" array. If lastname is NULL, then the cookie
806:
807: * returned actually represents the file, instead of just the directory
808:
809: * the file is in.
810:
811: *
812:
813: * note that lastname, if non-null, should be big enough to contain all the
814:
815: * characters in "path", since if the file system doesn't want the kernel
816:
817: * to do path name parsing we may end up just copying path to lastname
818:
819: * and returning the current or root directory, as appropriate
820:
821: *
822:
823: * "relto" is the directory relative to which the search should start.
824:
825: * if you just want the current directory, use path2cookie instead.
826:
827: *
828:
829: */
830:
831:
832:
833: #define MAX_LINKS 4
834:
835:
836:
837: long
838:
839: relpath2cookie(relto, path, lastname, res, depth)
840:
841: fcookie *relto;
842:
843: const char *path;
844:
845: char *lastname;
846:
847: fcookie *res;
848:
849: int depth;
850:
851: {
852:
1.1.1.3 ! root 853: fcookie dir;
1.1 root 854:
855: int drv;
856:
857: int len;
858:
859: char c, *s;
860:
861: XATTR xattr;
862:
863: static char newpath[16] = "U:\\DEV\\";
864:
865: char temp2[PATH_MAX];
866:
867: char linkstuff[PATH_MAX];
868:
1.1.1.3 ! root 869: long r;
1.1 root 870:
871:
872:
873: /* dolast: 0 == return a cookie for the directory the file is in
874:
875: * 1 == return a cookie for the file itself, don't follow links
876:
877: * 2 == return a cookie for whatever the file points at
878:
879: */
880:
881: int dolast = 0;
882:
883: int i = 0;
884:
885:
886:
887: if (!lastname) {
888:
889: dolast = 1;
890:
891: lastname = temp2;
892:
893: } else if (lastname == follow_links) {
894:
895: dolast = 2;
896:
897: lastname = temp2;
898:
899: }
900:
901:
902:
903: *lastname = 0;
904:
905:
906:
1.1.1.3 ! root 907: PATH2COOKIE_DB(("relpath2cookie(%s, dolast=%d, depth=%d)", path, dolast, depth));
! 908:
! 909:
! 910:
! 911: if (depth > MAX_LINKS) {
! 912:
! 913: DEBUG(("Too many symbolic links"));
! 914:
! 915: return ELOOP;
! 916:
! 917: }
! 918:
1.1 root 919: /* special cases: CON:, AUX:, etc. should be converted to U:\DEV\CON,
920:
921: * U:\DEV\AUX, etc.
922:
923: */
924:
925: if (strlen(path) == 4 && path[3] == ':') {
926:
927: strncpy(newpath+7, path, 3);
928:
929: path = newpath;
930:
931: }
932:
933:
934:
935: /* first, check for a drive letter */
936:
937: /* BUG: a '\' at the start of a symbolic link is relative to the current
938:
939: * drive of the process, not the drive the link is located on
940:
941: */
942:
1.1.1.3 ! root 943: if (path[1] == ':') {
1.1 root 944:
945: c = path[0];
946:
947: if (c >= 'a' && c <= 'z')
948:
949: drv = c - 'a';
950:
951: else if (c >= 'A' && c <= 'Z')
952:
953: drv = c - 'A';
954:
955: else
956:
957: goto nodrive;
958:
959: path += 2;
960:
961: i = 1; /* remember that we saw a drive letter */
962:
963: } else {
964:
965: nodrive:
966:
967: drv = curproc->curdrv;
968:
969: }
970:
971:
972:
973: /* see if the path is rooted from '\\' */
974:
975: if (DIRSEP(*path)) {
976:
977: while(DIRSEP(*path))path++;
978:
1.1.1.3 ! root 979: dup_cookie(&dir, &curproc->root[drv]);
1.1 root 980:
981: } else {
982:
983: if (i) { /* an explicit drive letter was given */
984:
1.1.1.3 ! root 985: dup_cookie(&dir, &curproc->curdir[drv]);
1.1 root 986:
987: }
988:
989: else
990:
1.1.1.3 ! root 991: dup_cookie(&dir, relto);
1.1 root 992:
993: }
994:
995:
996:
997: if (!dir.fs) {
998:
999: changedrv(dir.dev);
1000:
1.1.1.3 ! root 1001: dup_cookie(&dir, &curproc->root[drv]);
1.1 root 1002:
1003: }
1004:
1005:
1006:
1007: if (!dir.fs) {
1008:
1.1.1.3 ! root 1009: DEBUG(("path2cookie: no file system: returning EDRIVE"));
1.1 root 1010:
1011: return EDRIVE;
1012:
1013: }
1014:
1015:
1016:
1.1.1.3 ! root 1017: /* here's where we come when we've gone across a mount point */
1.1 root 1018:
1.1.1.3 ! root 1019:
1.1 root 1020:
1.1.1.3 ! root 1021: restart_mount:
1.1 root 1022:
1023:
1024:
1.1.1.3 ! root 1025: if (!*path) { /* nothing more to do */
1.1 root 1026:
1.1.1.3 ! root 1027: PATH2COOKIE_DB(("relpath2cookie: no more path, returning 0"));
1.1 root 1028:
1.1.1.3 ! root 1029: *res = dir;
1.1 root 1030:
1.1.1.3 ! root 1031: return 0;
! 1032:
! 1033: }
1.1 root 1034:
1035:
1036:
1037: /* see if there has been a disk change; if so, return E_CHNG.
1038:
1039: * path2cookie will restart the search automatically; other functions
1040:
1041: * that call relpath2cookie directly will have to fail gracefully
1042:
1043: */
1044:
1045: if (disk_changed(dir.dev)) {
1046:
1.1.1.3 ! root 1047: release_cookie(&dir);
! 1048:
! 1049: PATH2COOKIE_DB(("relpath2cookie: returning %d", E_CHNG));
! 1050:
1.1 root 1051: return E_CHNG;
1052:
1053: }
1054:
1055:
1056:
1.1.1.3 ! root 1057:
! 1058:
1.1 root 1059: if (dir.fs->fsflags & FS_KNOPARSE) {
1060:
1061: if (!dolast) {
1062:
1.1.1.3 ! root 1063: PATH2COOKIE_DB(("fs is a KNOPARSE, nothing to do"));
! 1064:
1.1 root 1065: strncpy(lastname, path, PATH_MAX-1);
1066:
1067: lastname[PATH_MAX - 1] = 0;
1068:
1069: r = 0;
1070:
1.1.1.3 ! root 1071: *res = dir;
! 1072:
1.1 root 1073: } else {
1074:
1.1.1.3 ! root 1075: PATH2COOKIE_DB(("fs is a KNOPARSE, calling lookup"));
! 1076:
1.1 root 1077: r = (*dir.fs->lookup)(&dir, path, res);
1078:
1.1.1.3 ! root 1079: if (r == EMOUNT) { /* hmmm... a ".." at a mount point, maybe */
1.1 root 1080:
1.1.1.3 ! root 1081: fcookie mounteddir;
1.1 root 1082:
1.1.1.3 ! root 1083: r = (*dir.fs->root)(dir.dev, &mounteddir);
1.1 root 1084:
1.1.1.3 ! root 1085: if (r == 0 && drv == UNIDRV) {
1.1 root 1086:
1.1.1.3 ! root 1087: if (dir.fs == mounteddir.fs &&
1.1 root 1088:
1.1.1.3 ! root 1089: dir.index == mounteddir.index &&
1.1 root 1090:
1.1.1.3 ! root 1091: dir.dev == mounteddir.dev) {
1.1 root 1092:
1.1.1.3 ! root 1093: release_cookie(&dir);
1.1 root 1094:
1.1.1.3 ! root 1095: release_cookie(&mounteddir);
1.1 root 1096:
1.1.1.3 ! root 1097: dup_cookie(&dir, &curproc->root[UNIDRV]);
1.1 root 1098:
1.1.1.3 ! root 1099: TRACE(("path2cookie: restarting from mount point"));
1.1 root 1100:
1.1.1.3 ! root 1101: goto restart_mount;
1.1 root 1102:
1.1.1.3 ! root 1103: }
1.1 root 1104:
1.1.1.3 ! root 1105: } else {
1.1 root 1106:
1.1.1.3 ! root 1107: if (r == 0)
1.1 root 1108:
1.1.1.3 ! root 1109: release_cookie(&mounteddir);
1.1 root 1110:
1.1.1.3 ! root 1111: r = 0;
1.1 root 1112:
1.1.1.3 ! root 1113: }
1.1 root 1114:
1.1.1.3 ! root 1115: }
1.1 root 1116:
1.1.1.3 ! root 1117: release_cookie(&dir);
1.1 root 1118:
1.1.1.3 ! root 1119: }
1.1 root 1120:
1.1.1.3 ! root 1121: PATH2COOKIE_DB(("relpath2cookie: returning %ld", r));
1.1 root 1122:
1.1.1.3 ! root 1123: return r;
1.1 root 1124:
1.1.1.3 ! root 1125: }
1.1 root 1126:
1127:
1128:
1129:
1130:
1.1.1.3 ! root 1131: /* parse all but (possibly) the last component of the path name */
1.1 root 1132:
1.1.1.3 ! root 1133: /* rules here: at the top of the loop, &dir is the cookie of
1.1 root 1134:
1.1.1.3 ! root 1135: * the directory we're in now, xattr is its attributes, and res is unset
1.1 root 1136:
1.1.1.3 ! root 1137: * at the end of the loop, &dir is unset, and either r is nonzero
1.1 root 1138:
1.1.1.3 ! root 1139: * (to indicate an error) or res is set to the final result
1.1 root 1140:
1.1.1.3 ! root 1141: */
1.1 root 1142:
1.1.1.3 ! root 1143: r = (dir.fs->getxattr)(&dir, &xattr);
1.1 root 1144:
1.1.1.3 ! root 1145: if (r) {
1.1 root 1146:
1.1.1.3 ! root 1147: DEBUG(("couldn't get directory attributes"));
1.1 root 1148:
1.1.1.3 ! root 1149: release_cookie(&dir);
1.1 root 1150:
1.1.1.3 ! root 1151: return EINTRN;
1.1 root 1152:
1.1.1.3 ! root 1153: }
1.1 root 1154:
1155:
1156:
1.1.1.3 ! root 1157: while (*path) {
1.1 root 1158:
1159:
1160:
1.1.1.3 ! root 1161: /* now we must have a directory, since there are more things in the path */
1.1 root 1162:
1.1.1.3 ! root 1163: if ((xattr.mode & S_IFMT) != S_IFDIR) {
1.1 root 1164:
1.1.1.3 ! root 1165: PATH2COOKIE_DB(("relpath2cookie: not a directory, returning EPTHNF"));
1.1 root 1166:
1.1.1.3 ! root 1167: release_cookie(&dir);
! 1168:
! 1169: r = EPTHNF;
1.1 root 1170:
1171: break;
1172:
1173: }
1174:
1.1.1.3 ! root 1175: /* we must also have search permission for the directory */
1.1 root 1176:
1.1.1.3 ! root 1177: if (denyaccess(&xattr, S_IXOTH)) {
1.1 root 1178:
1.1.1.3 ! root 1179: DEBUG(("search permission in directory denied"));
1.1 root 1180:
1.1.1.3 ! root 1181: release_cookie(&dir);
1.1 root 1182:
1.1.1.3 ! root 1183: r = EPTHNF;
1.1 root 1184:
1.1.1.3 ! root 1185: break;
1.1 root 1186:
1.1.1.3 ! root 1187: }
1.1 root 1188:
1189:
1190:
1.1.1.3 ! root 1191: /* if there's nothing left in the path, we can break here */
1.1 root 1192:
1.1.1.3 ! root 1193: if (!*path) {
1.1 root 1194:
1.1.1.3 ! root 1195: PATH2COOKIE_DB(("relpath2cookie: no more path, breaking (1)"));
1.1 root 1196:
1.1.1.3 ! root 1197: *res = dir;
1.1 root 1198:
1.1.1.3 ! root 1199: break;
1.1 root 1200:
1.1.1.3 ! root 1201: }
1.1 root 1202:
1203: /* next, peel off the next name in the path */
1204:
1205: len = 0;
1206:
1207: s = lastname;
1208:
1209: c = *path;
1210:
1211: while (c && !DIRSEP(c)) {
1212:
1213: if (len++ < PATH_MAX)
1214:
1215: *s++ = c;
1216:
1217: c = *++path;
1218:
1219: }
1220:
1221: *s = 0;
1222:
1223:
1224:
1.1.1.3 ! root 1225: /* if there are no more names in the path, and we don't want
! 1226:
! 1227: * to actually look up the last name, then we're done
! 1228:
! 1229: */
! 1230:
! 1231: if (dolast == 0 && !*path) {
1.1 root 1232:
1.1.1.3 ! root 1233: *res = dir;
1.1 root 1234:
1.1.1.3 ! root 1235: PATH2COOKIE_DB(("relpath2cookie: no more path, breaking (2)"));
1.1 root 1236:
1237: break;
1238:
1.1.1.3 ! root 1239: }
! 1240:
! 1241:
! 1242:
! 1243:
! 1244:
! 1245: /*
! 1246:
! 1247: * skip trailing slashes
! 1248:
! 1249: */
! 1250:
! 1251: while (DIRSEP(*path)) path++;
! 1252:
! 1253:
! 1254:
! 1255: PATH2COOKIE_DB(("relpath2cookie: looking up [%s]", lastname));
! 1256:
1.1 root 1257:
1258:
1259: r = (*dir.fs->lookup)(&dir, lastname, res);
1260:
1.1.1.3 ! root 1261: if (r == EMOUNT) {
1.1 root 1262:
1.1.1.3 ! root 1263: fcookie mounteddir;
1.1 root 1264:
1.1.1.3 ! root 1265: r = (*dir.fs->root)(dir.dev, &mounteddir);
! 1266:
! 1267: if (r == 0 && drv == UNIDRV) {
! 1268:
! 1269: if (samefile(&dir, &mounteddir)) {
! 1270:
! 1271: release_cookie(&dir);
! 1272:
! 1273: release_cookie(&mounteddir);
! 1274:
! 1275: dup_cookie(&dir, &curproc->root[UNIDRV]);
! 1276:
! 1277: TRACE(("path2cookie: restarting from mount point"));
! 1278:
! 1279: goto restart_mount;
! 1280:
! 1281: } else if (r == 0) {
! 1282:
! 1283: r = EINTRN;
! 1284:
! 1285: release_cookie(&mounteddir);
! 1286:
! 1287: release_cookie(&dir);
! 1288:
! 1289: break;
! 1290:
! 1291: }
! 1292:
! 1293: } else if (r == 0) {
! 1294:
! 1295: release_cookie(&mounteddir);
! 1296:
! 1297: } else {
! 1298:
! 1299: release_cookie(&dir);
! 1300:
! 1301: break;
! 1302:
! 1303: }
! 1304:
! 1305: } else if (r) {
! 1306:
! 1307: release_cookie(&dir);
1.1 root 1308:
1309: break;
1310:
1311: }
1312:
1313:
1314:
1.1.1.3 ! root 1315: /* check for a symbolic link */
! 1316:
! 1317: r = (res->fs->getxattr)(res, &xattr);
! 1318:
! 1319: if (r != 0) {
! 1320:
! 1321: DEBUG(("path2cookie: couldn't get file attributes"));
! 1322:
! 1323: release_cookie(&dir);
! 1324:
! 1325: release_cookie(res);
! 1326:
! 1327: break;
! 1328:
! 1329: }
! 1330:
1.1 root 1331:
1332:
1.1.1.3 ! root 1333: /* if the file is a link, and we're following links, follow it */
1.1 root 1334:
1.1.1.3 ! root 1335: if ( (xattr.mode & S_IFMT) == S_IFLNK && (*path || dolast > 1)) {
1.1 root 1336:
1.1.1.3 ! root 1337: r = (res->fs->readlink)(res, linkstuff, PATH_MAX);
1.1 root 1338:
1.1.1.3 ! root 1339: release_cookie(res);
1.1 root 1340:
1.1.1.3 ! root 1341: if (r) {
1.1 root 1342:
1.1.1.3 ! root 1343: DEBUG(("error reading symbolic link"));
1.1 root 1344:
1.1.1.3 ! root 1345: release_cookie(&dir);
1.1 root 1346:
1.1.1.3 ! root 1347: break;
1.1 root 1348:
1.1.1.3 ! root 1349: }
1.1 root 1350:
1.1.1.3 ! root 1351: r = relpath2cookie(&dir, linkstuff, follow_links, res,
1.1 root 1352:
1.1.1.3 ! root 1353: depth+1);
1.1 root 1354:
1.1.1.3 ! root 1355: release_cookie(&dir);
! 1356:
! 1357: if (r) {
! 1358:
! 1359: DEBUG(("error following symbolic link"));
! 1360:
! 1361: break;
1.1 root 1362:
1363: }
1364:
1.1.1.3 ! root 1365: dir = *res;
1.1 root 1366:
1.1.1.3 ! root 1367: (void)(res->fs->getxattr)(res, &xattr);
! 1368:
! 1369: } else {
! 1370:
! 1371: release_cookie(&dir);
! 1372:
! 1373: dir = *res;
! 1374:
! 1375: }
1.1 root 1376:
1377: }
1378:
1379:
1380:
1.1.1.3 ! root 1381: PATH2COOKIE_DB(("relpath2cookie: returning %ld", r));
! 1382:
1.1 root 1383: return r;
1384:
1385: }
1386:
1387:
1388:
1389: #define MAX_TRYS 8
1390:
1391:
1392:
1393: long
1394:
1395: path2cookie(path, lastname, res)
1396:
1397: const char *path;
1398:
1399: char *lastname;
1400:
1401: fcookie *res;
1402:
1403: {
1404:
1405: fcookie *dir;
1406:
1407: long r;
1408:
1409: /* AHDI sometimes will keep insisting that a media change occured;
1410:
1.1.1.3 ! root 1411: * we limit the number of retrys to avoid hanging the system
1.1 root 1412:
1413: */
1414:
1415: int trycnt = 0;
1416:
1417:
1418:
1419: dir = &curproc->curdir[curproc->curdrv];
1420:
1421:
1422:
1423: do {
1424:
1.1.1.3 ! root 1425: r = relpath2cookie(dir, path, lastname, res, 0);
1.1 root 1426:
1427: if (r == E_CHNG)
1428:
1.1.1.2 root 1429: DEBUG(("path2cookie: restarting due to media change"));
1.1 root 1430:
1431: } while (r == E_CHNG && trycnt++ < MAX_TRYS);
1432:
1433:
1434:
1435: return r;
1436:
1437: }
1438:
1439:
1440:
1441: /*
1442:
1.1.1.3 ! root 1443: * release_cookie: tell the file system owner that a cookie is no
! 1444:
! 1445: * longer in use by the kernel
! 1446:
! 1447: */
! 1448:
! 1449: void
! 1450:
! 1451: release_cookie(fc)
! 1452:
! 1453: fcookie *fc;
! 1454:
! 1455: {
! 1456:
! 1457: FILESYS *fs;
! 1458:
! 1459:
! 1460:
! 1461: if (fc) {
! 1462:
! 1463: fs = fc->fs;
! 1464:
! 1465: if (fs && fs->release) {
! 1466:
! 1467: (void)(*fs->release)(fc);
! 1468:
! 1469: }
! 1470:
! 1471: }
! 1472:
! 1473: }
! 1474:
! 1475:
! 1476:
! 1477: /*
! 1478:
! 1479: * Make a new cookie (newc) which is a duplicate of the old cookie
! 1480:
! 1481: * (oldc). This may be something the file system is interested in,
! 1482:
! 1483: * so we give it a chance to do the duplication; if it doesn't
! 1484:
! 1485: * want to, we just copy.
! 1486:
! 1487: */
! 1488:
! 1489:
! 1490:
! 1491: void
! 1492:
! 1493: dup_cookie(newc, oldc)
! 1494:
! 1495: fcookie *newc, *oldc;
! 1496:
! 1497: {
! 1498:
! 1499: FILESYS *fs = oldc->fs;
! 1500:
! 1501:
! 1502:
! 1503: if (fs && fs->release && fs->dupcookie) {
! 1504:
! 1505: (void)(*fs->dupcookie)(newc, oldc);
! 1506:
! 1507: } else {
! 1508:
! 1509: *newc = *oldc;
! 1510:
! 1511: }
! 1512:
! 1513: }
! 1514:
! 1515:
! 1516:
! 1517: /*
! 1518:
1.1 root 1519: * new_fileptr, dispose_fileptr: allocate (deallocate) a file pointer
1520:
1521: */
1522:
1523:
1524:
1525: FILEPTR *
1526:
1527: new_fileptr()
1528:
1529: {
1530:
1531: FILEPTR *f;
1532:
1533:
1534:
1.1.1.2 root 1535: if ((f = flist) != 0) {
1.1 root 1536:
1537: flist = f->next;
1538:
1539: f->next = 0;
1540:
1541: return f;
1542:
1543: }
1544:
1545: f = kmalloc(SIZEOF(FILEPTR));
1546:
1547: if (!f) {
1548:
1549: FATAL("new_fileptr: out of memory");
1550:
1551: }
1552:
1553: else {
1554:
1555: f->next = 0;
1556:
1557: }
1558:
1559: return f;
1560:
1561: }
1562:
1563:
1564:
1565: void
1566:
1567: dispose_fileptr(f)
1568:
1569: FILEPTR *f;
1570:
1571: {
1572:
1573: if (f->links != 0) {
1574:
1575: FATAL("dispose_fileptr: f->links == %d", f->links);
1576:
1577: }
1578:
1579: f->next = flist;
1580:
1581: flist = f;
1582:
1583: }
1584:
1585:
1586:
1587: /*
1588:
1589: * denyshare(list, f): "list" points at the first FILEPTR in a
1590:
1591: * chained list of open FILEPTRS referring to the same file;
1592:
1593: * f is a newly opened FILEPTR. Every FILEPTR in the given list is
1594:
1595: * checked to see if its "open" mode (in list->flags) is compatible with
1596:
1597: * the open mode in f->flags. If not (for example, if f was opened with
1598:
1599: * a "read" mode and some other file has the O_DENYREAD share mode),
1600:
1601: * then 1 is returned. If all the open FILEPTRs in the list are
1602:
1603: * compatible with f, then 0 is returned.
1604:
1605: * This is not as complicated as it sounds. In practice, just keep a
1606:
1607: * list of open FILEPTRs attached to each file, and put something like
1608:
1609: * if (denyshare(thisfile->openfileptrlist, newfileptr))
1610:
1611: * return EACCDN;
1612:
1613: * in the device open routine.
1614:
1615: */
1616:
1617:
1618:
1.1.1.2 root 1619: int ARGS_ON_STACK
1.1 root 1620:
1621: denyshare(list, f)
1622:
1623: FILEPTR *list, *f;
1624:
1625: {
1626:
1.1.1.3 ! root 1627: int newrm, newsm; /* new read and sharing mode */
1.1 root 1628:
1.1.1.3 ! root 1629: int oldrm, oldsm; /* read and sharing mode of already opened file */
1.1 root 1630:
1631: int i;
1632:
1633:
1634:
1635: newrm = f->flags & O_RWMODE;
1636:
1637: newsm = f->flags & O_SHMODE;
1638:
1639:
1640:
1.1.1.3 ! root 1641: /*
! 1642:
! 1643: * O_EXEC gets treated the same as O_RDONLY for our purposes
! 1644:
! 1645: */
! 1646:
! 1647: if (newrm == O_EXEC) newrm = O_RDONLY;
! 1648:
! 1649:
! 1650:
! 1651: /* New meaning for O_COMPAT: deny write access to all _other_
! 1652:
! 1653: * processes.
! 1654:
! 1655: */
! 1656:
! 1657:
! 1658:
1.1 root 1659: for ( ; list; list = list->next) {
1660:
1661: oldrm = list->flags & O_RWMODE;
1662:
1.1.1.3 ! root 1663: if (oldrm == O_EXEC) oldrm = O_RDONLY;
! 1664:
1.1 root 1665: oldsm = list->flags & O_SHMODE;
1666:
1667: if (oldsm == O_DENYW || oldsm == O_DENYRW) {
1668:
1.1.1.3 ! root 1669: if (newrm != O_RDONLY) {
1.1 root 1670:
1.1.1.2 root 1671: DEBUG(("write access denied"));
1.1 root 1672:
1673: return 1;
1674:
1675: }
1676:
1677: }
1678:
1679: if (oldsm == O_DENYR || oldsm == O_DENYRW) {
1680:
1681: if (newrm != O_WRONLY) {
1682:
1.1.1.2 root 1683: DEBUG(("read access denied"));
1.1 root 1684:
1685: return 1;
1686:
1687: }
1688:
1689: }
1690:
1691: if (newsm == O_DENYW || newsm == O_DENYRW) {
1692:
1.1.1.3 ! root 1693: if (oldrm != O_RDONLY) {
1.1 root 1694:
1.1.1.2 root 1695: DEBUG(("couldn't deny writes"));
1.1 root 1696:
1697: return 1;
1698:
1699: }
1700:
1701: }
1702:
1703: if (newsm == O_DENYR || newsm == O_DENYRW) {
1704:
1705: if (oldrm != O_WRONLY) {
1706:
1.1.1.2 root 1707: DEBUG(("couldn't deny reads"));
1.1 root 1708:
1709: return 1;
1710:
1711: }
1712:
1713: }
1714:
1715: /* If either sm == O_COMPAT, then we check to make sure
1716:
1717: that the file pointers are owned by the same process (O_COMPAT means
1718:
1.1.1.3 ! root 1719: "deny writes to any other processes"). This isn't quite the same
1.1 root 1720:
1.1.1.3 ! root 1721: as the Atari spec, which says O_COMPAT means "deny access to other
1.1 root 1722:
1.1.1.3 ! root 1723: processes." We should fix the spec.
1.1 root 1724:
1.1.1.3 ! root 1725: */
1.1 root 1726:
1.1.1.3 ! root 1727: if ((newsm == O_COMPAT && newrm != O_RDONLY && oldrm != O_RDONLY) ||
1.1 root 1728:
1.1.1.3 ! root 1729: (oldsm == O_COMPAT && newrm != O_RDONLY)) {
1.1 root 1730:
1731: for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
1732:
1733: if (curproc->handle[i] == list)
1734:
1735: goto found;
1736:
1737: }
1738:
1739: /* old file pointer is not open by this process */
1740:
1.1.1.3 ! root 1741: DEBUG(("O_COMPAT file was opened for writing by another process"));
1.1 root 1742:
1743: return 1;
1744:
1745: found:
1746:
1747: ; /* everything is OK */
1748:
1749: }
1750:
1751: }
1752:
1753: return 0;
1754:
1755: }
1756:
1757:
1758:
1759: /*
1760:
1761: * denyaccess(XATTR *xattr, unsigned perm): checks to see if the access
1762:
1763: * specified by perm (which must be some combination of S_IROTH, S_IWOTH,
1764:
1765: * and S_IXOTH) should be granted to the current process
1766:
1767: * on a file with the given extended attributes. Returns 0 if access
1768:
1769: * by the current process is OK, 1 if not.
1770:
1771: */
1772:
1773:
1774:
1775: int
1776:
1777: denyaccess(xattr, perm)
1778:
1779: XATTR *xattr;
1780:
1781: unsigned perm;
1782:
1783: {
1784:
1785: unsigned mode;
1786:
1787:
1788:
1789: /* the super-user can do anything! */
1790:
1791: if (curproc->euid == 0)
1792:
1793: return 0;
1794:
1795:
1796:
1797: mode = xattr->mode;
1798:
1799: if (curproc->euid == xattr->uid)
1800:
1801: perm = perm << 6;
1802:
1803: else if (curproc->egid == xattr->gid)
1804:
1805: perm = perm << 3;
1806:
1807: if ((mode & perm) != perm) return 1; /* access denied */
1808:
1809: return 0;
1810:
1811: }
1812:
1813:
1814:
1815: /*
1816:
1817: * Checks a lock against a list of locks to see if there is a conflict.
1818:
1819: * This is a utility to be used by file systems, somewhat like denyshare
1820:
1821: * above. Returns 0 if there is no conflict, or a pointer to the
1822:
1823: * conflicting LOCK structure if there is.
1824:
1825: *
1826:
1827: * Conflicts occur for overlapping locks if the process id's are
1828:
1829: * different and if at least one of the locks is a write lock.
1830:
1831: *
1832:
1833: * NOTE: we assume before being called that the locks have been converted
1834:
1835: * so that l_start is absolute. not relative to the current position or
1836:
1837: * end of file.
1838:
1839: */
1840:
1841:
1842:
1.1.1.2 root 1843: LOCK * ARGS_ON_STACK
1.1 root 1844:
1845: denylock(list, lck)
1846:
1847: LOCK *list, *lck;
1848:
1849: {
1850:
1851: LOCK *t;
1852:
1853: unsigned long tstart, tend;
1854:
1855: unsigned long lstart, lend;
1856:
1857: int pid = curproc->pid;
1858:
1859: int ltype;
1860:
1861:
1862:
1863: ltype = lck->l.l_type;
1864:
1865: lstart = lck->l.l_start;
1866:
1867:
1868:
1869: if (lck->l.l_len == 0)
1870:
1.1.1.2 root 1871: lend = 0xffffffffL;
1.1 root 1872:
1873: else
1874:
1.1.1.3 ! root 1875: lend = lstart + lck->l.l_len - 1;
1.1 root 1876:
1877:
1878:
1879: for (t = list; t; t = t->next) {
1880:
1881: tstart = t->l.l_start;
1882:
1883: if (t->l.l_len == 0)
1884:
1.1.1.2 root 1885: tend = 0xffffffffL;
1.1 root 1886:
1887: else
1888:
1.1.1.3 ! root 1889: tend = tstart + t->l.l_len - 1;
1.1 root 1890:
1891:
1892:
1893: /* look for overlapping locks */
1894:
1895: if (tstart <= lstart && tend >= lstart && t->l.l_pid != pid &&
1896:
1897: (ltype == F_WRLCK || t->l.l_type == F_WRLCK))
1898:
1899: break;
1900:
1901: if (lstart <= tstart && lend >= tstart && t->l.l_pid != pid &&
1902:
1903: (ltype == F_WRLCK || t->l.l_type == F_WRLCK))
1904:
1905: break;
1906:
1907: }
1908:
1909: return t;
1910:
1911: }
1912:
1913:
1914:
1915: /*
1916:
1917: * check to see that a file is a directory, and that write permission
1918:
1919: * is granted; return an error code, or 0 if everything is ok.
1920:
1921: */
1922:
1923: long
1924:
1925: dir_access(dir, perm)
1926:
1927: fcookie *dir;
1928:
1929: unsigned perm;
1930:
1931: {
1932:
1933: XATTR xattr;
1934:
1935: long r;
1936:
1937:
1938:
1939: r = (*dir->fs->getxattr)(dir, &xattr);
1940:
1.1.1.3 ! root 1941: if (r) {
! 1942:
! 1943: DEBUG(("dir_access: file system returned %ld", r));
! 1944:
! 1945: return r;
! 1946:
! 1947: }
1.1 root 1948:
1949: if ( (xattr.mode & S_IFMT) != S_IFDIR ) {
1950:
1.1.1.2 root 1951: DEBUG(("file is not a directory"));
1.1 root 1952:
1953: return EPTHNF;
1954:
1955: }
1956:
1957: if (denyaccess(&xattr, perm)) {
1958:
1.1.1.2 root 1959: DEBUG(("no permission for directory"));
1.1 root 1960:
1961: return EACCDN;
1962:
1963: }
1964:
1965: return 0;
1966:
1967: }
1968:
1969:
1970:
1971: /*
1972:
1973: * returns 1 if the given name contains a wildcard character
1974:
1975: */
1976:
1977:
1978:
1979: int
1980:
1981: has_wild(name)
1982:
1983: const char *name;
1984:
1985: {
1986:
1987: char c;
1988:
1989:
1990:
1.1.1.2 root 1991: while ((c = *name++) != 0) {
1.1 root 1992:
1993: if (c == '*' || c == '?') return 1;
1994:
1995: }
1996:
1997: return 0;
1998:
1999: }
2000:
2001:
2002:
2003: /*
2004:
2005: * void copy8_3(dest, src): convert a file name (src) into DOS 8.3 format
2006:
2007: * (in dest). Note the following things:
2008:
2009: * if a field has less than the required number of characters, it is
2010:
2011: * padded with blanks
2012:
2013: * a '*' means to pad the rest of the field with '?' characters
2014:
2015: * special things to watch for:
2016:
2017: * "." and ".." are more or less left alone
2018:
2019: * "*.*" is recognized as a special pattern, for which dest is set
2020:
2021: * to just "*"
2022:
2023: * Long names are truncated. Any extensions after the first one are
2024:
2025: * ignored, i.e. foo.bar.c -> foo.bar, foo.c.bar->foo.c.
2026:
2027: */
2028:
2029:
2030:
2031: void
2032:
2033: copy8_3(dest, src)
2034:
2035: char *dest;
2036:
2037: const char *src;
2038:
2039: {
2040:
2041: char fill = ' ', c;
2042:
2043: int i;
2044:
2045:
2046:
2047: if (src[0] == '.') {
2048:
2049: if (src[1] == 0) {
2050:
2051: strcpy(dest, ". . ");
2052:
2053: return;
2054:
2055: }
2056:
2057: if (src[1] == '.' && src[2] == 0) {
2058:
2059: strcpy(dest, ".. . ");
2060:
2061: return;
2062:
2063: }
2064:
2065: }
2066:
2067: if (src[0] == '*' && src[1] == '.' && src[2] == '*' && src[3] == 0) {
2068:
2069: dest[0] = '*';
2070:
2071: dest[1] = 0;
2072:
2073: return;
2074:
2075: }
2076:
2077:
2078:
2079: for (i = 0; i < 8; i++) {
2080:
2081: c = *src++;
2082:
2083: if (!c || c == '.') break;
2084:
2085: if (c == '*') {
2086:
2087: fill = c = '?';
2088:
2089: }
2090:
2091: *dest++ = toupper(c);
2092:
2093: }
2094:
2095: while (i++ < 8) {
2096:
2097: *dest++ = fill;
2098:
2099: }
2100:
2101: *dest++ = '.';
2102:
2103: i = 0;
2104:
2105: fill = ' ';
2106:
2107: while (c && c != '.')
2108:
2109: c = *src++;
2110:
2111:
2112:
2113: if (c) {
2114:
2115: for( ;i < 3; i++) {
2116:
2117: c = *src++;
2118:
2119: if (!c || c == '.') break;
2120:
2121: if (c == '*')
2122:
2123: c = fill = '?';
2124:
2125: *dest++ = toupper(c);
2126:
2127: }
2128:
2129: }
2130:
2131: while (i++ < 3)
2132:
2133: *dest++ = fill;
2134:
1.1.1.2 root 2135: *dest = 0;
1.1 root 2136:
2137: }
2138:
2139:
2140:
2141: /*
2142:
2143: * int pat_match(name, patrn): returns 1 if "name" matches the template in
2144:
2145: * "patrn", 0 if not. "patrn" is assumed to have been expanded in 8.3
2146:
2147: * format by copy8_3; "name" need not be. Any '?' characters in patrn
2148:
2149: * will match any character in name. Note that if "patrn" has a '*' as
2150:
2151: * the first character, it will always match; this will happen only if
2152:
2153: * the original pattern (before copy8_3 was applied) was "*.*".
2154:
2155: *
2156:
2157: * BUGS: acts a lot like the silly TOS pattern matcher.
2158:
2159: */
2160:
2161:
2162:
2163: int
2164:
2165: pat_match(name, template)
2166:
2167: const char *name, *template;
2168:
2169: {
2170:
2171: register char *s, c;
2172:
2173: char expname[TOS_NAMELEN+1];
2174:
2175:
2176:
2177: if (*template == '*') return 1;
2178:
2179: copy8_3(expname, name);
2180:
2181:
2182:
2183: s = expname;
2184:
1.1.1.2 root 2185: while ((c = *template++) != 0) {
1.1 root 2186:
2187: if (c != *s && c != '?')
2188:
2189: return 0;
2190:
2191: s++;
2192:
2193: }
2194:
2195: return 1;
2196:
2197: }
2198:
2199:
2200:
2201: /*
2202:
2203: * int samefile(fcookie *a, fcookie *b): returns 1 if the two cookies
2204:
2205: * refer to the same file or directory, 0 otherwise
2206:
2207: */
2208:
2209:
2210:
2211: int
2212:
2213: samefile(a, b)
2214:
2215: fcookie *a, *b;
2216:
2217: {
2218:
2219: if (a->fs == b->fs && a->dev == b->dev && a->index == b->index)
2220:
2221: return 1;
2222:
2223: return 0;
2224:
2225: }
2226:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.