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