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