|
|
1.1 root 1: /*
2:
3: Copyright 1991,1992 Eric R. Smith. All rights reserved.
4:
5: */
6:
7:
8:
9: /* a VERY simple tosfs.c
10:
11: * this one is extremely brain-damaged, but will serve OK for a
12:
13: * skeleton in which to put a "real" tosfs.c
14:
15: */
16:
17:
18:
19: #include "mint.h"
20:
21:
22:
23: /* search mask for anything OTHER THAN a volume label */
24:
25: #define FILEORDIR 0x37
26:
27:
28:
29: #ifndef Flock
30:
31: /* this may need to be adjusted for your compiler/library */
32:
33: extern long gemdos();
34:
35: #define Flock(handle, mode, start, len) gemdos(0x5c, handle, mode, start, len)
36:
37: #endif
38:
39:
40:
41: char tmpbuf[PATH_MAX+1];
42:
43:
44:
45: static long tos_root P_((int drv, fcookie *fc));
46:
47: static long tos_lookup P_((fcookie *dir, const char *name, fcookie *fc));
48:
49: static long tos_getxattr P_((fcookie *fc, XATTR *xattr));
50:
51: static long tos_chattr P_((fcookie *fc, int attrib));
52:
53: static long tos_chown P_((fcookie *fc, int uid, int gid));
54:
55: static long tos_chmode P_((fcookie *fc, unsigned mode));
56:
57: static long tos_mkdir P_((fcookie *dir, const char *name, unsigned mode));
58:
59: static long tos_rmdir P_((fcookie *dir, const char *name));
60:
61: static long tos_remove P_((fcookie *dir, const char *name));
62:
63: static long tos_getname P_((fcookie *root, fcookie *dir, char *pathname));
64:
65: static long tos_rename P_((fcookie *olddir, char *oldname,
66:
67: fcookie *newdir, const char *newname));
68:
69: static long tos_opendir P_((DIR *dirh, int flags));
70:
71: static long tos_readdir P_((DIR *dirh, char *nm, int nmlen, fcookie *));
72:
73: static long tos_rewinddir P_((DIR *dirh));
74:
75: static long tos_closedir P_((DIR *dirh));
76:
77: static long tos_pathconf P_((fcookie *dir, int which));
78:
79: static long tos_dfree P_((fcookie *dir, long *buf));
80:
81: static long tos_writelabel P_((fcookie *dir, const char *name));
82:
83: static long tos_readlabel P_((fcookie *dir, char *name, int namelen));
84:
85:
86:
87: static long tos_creat P_((fcookie *dir, const char *name, unsigned mode,
88:
89: int attrib, fcookie *fc));
90:
91: static DEVDRV * tos_getdev P_((fcookie *fc, long *devsp));
92:
93: static long tos_open P_((FILEPTR *f));
94:
95: static long tos_write P_((FILEPTR *f, const char *buf, long bytes));
96:
97: static long tos_read P_((FILEPTR *f, char *buf, long bytes));
98:
99: static long tos_lseek P_((FILEPTR *f, long where, int whence));
100:
101: static long tos_ioctl P_((FILEPTR *f, int mode, void *buf));
102:
103: static long tos_datime P_((FILEPTR *f, short *time, int rwflag));
104:
105: static long tos_close P_((FILEPTR *f, int pid));
106:
107: static long tos_dskchng P_((int drv));
108:
109:
110:
111: /* some routines from biosfs.c */
112:
113: extern long null_select P_((FILEPTR *f, long p, int mode));
114:
115: extern void null_unselect P_((FILEPTR *f, long p, int mode));
116:
117:
118:
119: DEVDRV tos_device = {
120:
121: tos_open, tos_write, tos_read, tos_lseek, tos_ioctl, tos_datime,
122:
123: tos_close, null_select, null_unselect
124:
125: };
126:
127:
128:
129: FILESYS tos_filesys = {
130:
131: (FILESYS *)0,
132:
133: FS_KNOPARSE | FS_NOXBIT,
134:
135: tos_root,
136:
137: tos_lookup, tos_creat, tos_getdev, tos_getxattr,
138:
139: tos_chattr, tos_chown, tos_chmode,
140:
141: tos_mkdir, tos_rmdir, tos_remove, tos_getname, tos_rename,
142:
143: tos_opendir, tos_readdir, tos_rewinddir, tos_closedir,
144:
145: tos_pathconf, tos_dfree, tos_writelabel, tos_readlabel,
146:
147: nosymlink, noreadlink, nohardlink, nofscntl, tos_dskchng
148:
149: };
150:
151:
152:
153: /* some utility functions and variables: see end of file */
154:
155: static DTABUF *lastdta; /* last DTA buffer we asked TOS about */
156:
157: static DTABUF foo;
158:
159: static void do_setdta P_((DTABUF *dta));
160:
161: static int executable_extension P_((char *));
162:
163:
164:
165: /* this array keeps track of which drives have been changed */
166:
167: /* a nonzero entry means that the corresponding drive has been changed,
168:
169: * but GEMDOS doesn't know it yet
170:
171: */
172:
173: static char drvchanged[NUM_DRIVES];
174:
175:
176:
177: /* force TOS to see a media change */
178:
179: static void force_mediach P_((int drv));
180:
181: static long Newgetbpb P_((int));
182:
183: static long Newmediach P_((int));
184:
185: static long Newrwabs P_((int, void *, int, int, int, long));
186:
187:
188:
189: #define NUM_INDICES 128
190:
191: #define MIN_AGE 8
192:
193:
194:
195: struct tindex {
196:
197: char *name; /* full path name */
198:
199: FILEPTR *open; /* fileptrs for this file; OR
200:
201: * count of number of open directories
202:
203: */
204:
205: LOCK *locks; /* locks on this file */
206:
207: /* file status */
208:
209: long size;
210:
211: short time;
212:
213: short date;
214:
215: short attr;
216:
217: short valid; /* 1 if the above status is still valid */
218:
219: short stamp; /* age of this index, for garbage collection */
220:
221: } gl_ti[NUM_INDICES];
222:
223:
224:
225: /* temporary index for files found by readdir */
226:
227: static struct tindex tmpindex;
228:
229: static char tmpiname[PATH_MAX];
230:
231:
232:
233: static struct tindex *tstrindex P_((char *s));
234:
235: static int tfullpath P_((char *result, struct tindex *base, const char *name));
236:
237: static struct tindex *garbage_collect P_((void));
238:
239:
240:
241: static short tclock; /* #calls to tfullpath since last garbage
242:
243: collection */
244:
245:
246:
247: /* some extra flags for the attr field */
248:
249:
250:
251: /*
252:
253: * is a string the name of a file with executable extension?
254:
255: */
256:
257: #define FA_EXEC 0x4000
258:
259: /*
260:
261: * should the file be deleted when it is closed?
262:
263: */
264:
265: #define FA_DELETE 0x2000
266:
267:
268:
269: /*
270:
271: * NOTE: call executable_extension only on a DTA name returned from
272:
273: * Fsfirst(), not on an arbitrary path
274:
275: */
276:
277:
278:
279: static int
280:
281: executable_extension(s)
282:
283: char *s;
284:
285: {
286:
287: while (*s && *s != '.') s++;
288:
289: if (!*s) return 0;
290:
291: s++;
292:
293: if (s[0] == 'T') {
294:
295: return (s[1] == 'T' && s[2] == 'P') ||
296:
297: (s[1] == 'O' && s[2] == 'S');
298:
299: }
300:
301: if (s[0] == 'P')
302:
303: return s[1] == 'R' && s[2] == 'G';
304:
305: if (s[0] == 'A')
306:
307: return s[1] == 'P' && s[2] == 'P';
308:
309: if (s[0] == 'G')
310:
311: return s[1] == 'T' && s[2] == 'P';
312:
313: return 0;
314:
315: }
316:
317:
318:
319: /*
320:
321: * Look in the table of tos indices to see if an index corresponding
322:
323: * to this file name already exists. If so, mark it as being used
324:
325: * and return it. If not, find an empty slot and make an index for
326:
327: * this string. If no empty slots exist, garbage collect and
328:
329: * try again.
330:
331: *
332:
333: * This routine is pretty dumb; we really should use a hash table
334:
335: * of some sort
336:
337: */
338:
339:
340:
341: static struct tindex *tstrindex(s)
342:
343: char *s;
344:
345: {
346:
347: int i;
348:
349: char *r;
350:
351: struct tindex *t, *free = 0;
352:
353:
354:
355: assert(s != 0);
356:
357: t = gl_ti;
358:
359: for (i = 0; i < NUM_INDICES; i++, t++) {
360:
361: if (t->name && !stricmp(t->name, s)) {
362:
363: t->stamp = tclock; /* update use time */
364:
365: return t;
366:
367: }
368:
369: else if (!t->name && !free)
370:
371: free = t;
372:
373: }
374:
375: if (!free) {
376:
377: free = garbage_collect();
378:
379: }
380:
381: if (!free) {
382:
383: FATAL("tosfs: unable to get a file name index");
384:
385: }
386:
387: r = kmalloc((long)strlen(s)+1);
388:
389: if (!r) {
390:
391: FATAL("tosfs: unable to allocate space for a file name");
392:
393: }
394:
395: strcpy(r, s);
396:
397: free->name = r;
398:
399: free->stamp = tclock;
400:
401: free->open = 0;
402:
403: free->locks = 0;
404:
405:
406:
407: /* check to see if this file was recently returned by opendir() */
408:
409: if (tmpindex.valid && tclock - tmpindex.stamp < MIN_AGE &&
410:
411: !stricmp(free->name, tmpindex.name)) {
412:
413: free->size = tmpindex.size;
414:
415: free->time = tmpindex.time;
416:
417: free->date = tmpindex.date;
418:
419: free->attr = tmpindex.attr;
420:
421: free->valid = 1;
422:
423: tmpindex.valid = 0;
424:
425: } else
426:
427: free->valid = 0;
428:
429: return free;
430:
431: }
432:
433:
434:
435: /*
436:
437: * garbage collection routine: for any TOS index older than MIN_AGE,
438:
439: * check through all current processes to see if it's in use. If
440:
441: * not, free the corresponding string.
442:
443: * Returns: a pointer to a newly freed index, or NULL.
444:
445: */
446:
447:
448:
449: /* it's unlikely that the kernel would need to hold onto a file cookie
450:
451: for longer than this many calls to tstrindex() without first
452:
453: saving the cookie in a directory or file pointer
454:
455: */
456:
457:
458:
459: static struct tindex *
460:
461: garbage_collect()
462:
463: {
464:
465: struct tindex *free, *t;
466:
467: fcookie *fc, *gc;
468:
469: PROC *p;
470:
471: int i, j;
472:
473: int age;
474:
475:
476:
477: free = 0;
478:
479: t = gl_ti;
480:
481: for (i = 0; i < NUM_INDICES; i++,t++) {
482:
483: if (!t->name) continue;
484:
485: age = tclock - t->stamp;
486:
487: t->stamp = 0;
488:
489: assert(age >= 0);
490:
491: if (age > MIN_AGE) {
492:
493: /* see if any process is using this index */
494:
495: if (t->open)
496:
497: goto found_index;
498:
499: for (p = proclist; p; p = p->gl_next) {
500:
501: fc = p->curdir;
502:
503: gc = p->root;
504:
505: for (j = 0; j < NUM_DRIVES; j++,fc++,gc++) {
506:
507: if (( fc->fs == &tos_filesys &&
508:
509: fc->index == (long)t ) ||
510:
511: ( gc->fs == &tos_filesys &&
512:
513: gc->index == (long)t ) )
514:
515: goto found_index;
516:
517: }
518:
519: }
520:
521: /* here, we couldn't find the index in use by any proc. */
522:
523: kfree(t->name);
524:
525: t->name = 0;
526:
527: if (!free)
528:
529: free = t;
530:
531: found_index:
532:
533: ;
534:
535: } else {
536:
537: /* make sure that future garbage collections might look at this file */
538:
539: t->stamp = -age;
540:
541: }
542:
543: }
544:
545:
546:
547: tclock = 0; /* reset the clock */
548:
549: tmpindex.valid = 0; /* expire the temporary Fsfirst buffer */
550:
551: return free;
552:
553: }
554:
555:
556:
557: #define DIRSEP(c) ((c) == '\\')
558:
559:
560:
561: static int
562:
563: tfullpath(result, basei, path)
564:
565: char *result;
566:
567: struct tindex *basei;
568:
569: const char *path;
570:
571: {
572:
573: #define TNMTEMP 32
574:
575: char *n, name[TNMTEMP+1];
576:
577: int dom;
578:
579: int namelen, pathlen;
580:
581: char *base = basei->name;
582:
583: int r = 0;
584:
585:
586:
587: basei->stamp = ++tclock;
588:
589: if (tclock > 10000) {
590:
591: /* garbage collect every so often whether we need it or not */
592:
593: (void)garbage_collect();
594:
595: }
596:
597: if (!*path) {
598:
599: strncpy(result, base, PATH_MAX-1);
600:
601: return r;
602:
603: }
604:
605:
606:
607: dom = curproc->domain;
608:
609:
610:
611: strncpy(result, base, PATH_MAX-1);
612:
613:
614:
615: pathlen = strlen(result);
616:
617:
618:
619: /* now path is relative to what's currently in "result" */
620:
621:
622:
623: while(*path) {
624:
625: /* get next name in path */
626:
627: n = name; namelen = 0;
628:
629: while (*path && !DIRSEP(*path)) {
630:
631: /* BUG: we really should to the translation to DOS 8.3
632:
633: * format *here*, so that really long names are truncated
634:
635: * correctly.
636:
637: */
638:
639: if (namelen < TNMTEMP) {
640:
641: *n++ = toupper(*path); path++; namelen++;
642:
643: }
644:
645: else
646:
647: path++;
648:
649: }
650:
651: *n++ = 0;
652:
653: while (DIRSEP(*path)) path++;
654:
655: /* check for "." and ".." */
656:
657: if (!strcmp(name, ".")) continue;
658:
659: if (!strcmp(name, "..")) {
660:
661: n = strrchr(result, '\\');
662:
663: if (n) {
664:
665: *n = 0;
666:
667: pathlen = n - result;
668:
669: }
670:
671: else r = EMOUNT;
672:
673: continue;
674:
675: }
676:
677: if (pathlen + namelen < PATH_MAX - 1) {
678:
679: strcat(result, "\\");
680:
681: pathlen++;
682:
683:
684:
685: /* make sure the name is restricted to DOS 8.3 format */
686:
687: for (base = result; *base; base++)
688:
689: ;
690:
691: n = name;
692:
693: namelen = 0;
694:
695: while (*n && *n != '.' && namelen++ < 8) {
696:
697: *base++ = *n++;
698:
699: pathlen++;
700:
701: }
702:
703: while (*n && *n != '.') n++;
704:
705: if (*n == '.' && *(n+1) != 0) {
706:
707: *base++ = *n++;
708:
709: pathlen++;
710:
711: namelen = 0;
712:
713: while (*n && namelen++ < 3) {
714:
715: *base++ = *n++;
716:
717: pathlen++;
718:
719: }
720:
721: }
722:
723: *base = 0;
724:
725: }
726:
727: }
728:
729: return r;
730:
731: }
732:
733:
734:
735: static long
736:
737: tos_root(drv, fc)
738:
739: int drv;
740:
741: fcookie *fc;
742:
743: {
744:
745: struct tindex *ti;
746:
747:
748:
749: ksprintf(tmpbuf, "%c:", drv+'A');
750:
751: fc->fs = &tos_filesys;
752:
753: fc->dev = drv;
754:
755: ti = tstrindex(tmpbuf);
756:
757: ti->size = ti->date = ti->time = 0;
758:
759: ti->attr = FA_DIR;
760:
761: ti->valid = 1;
762:
763: fc->index = (long)ti;
764:
765:
766:
767: /* if the drive has changed, make sure GEMDOS knows it! */
768:
769: if (drvchanged[drv]) {
770:
771: force_mediach(drv);
772:
773: }
774:
775: return 0;
776:
777: }
778:
779:
780:
781: static long
782:
783: tos_lookup(dir, name, fc)
784:
785: fcookie *dir;
786:
787: const char *name;
788:
789: fcookie *fc;
790:
791: {
792:
793: long r;
794:
795: struct tindex *ti = (struct tindex *)dir->index;
796:
797:
798:
799: r = tfullpath(tmpbuf, ti, name);
800:
801:
802:
803: /* if the name is empty or otherwise trivial, just return the directory */
804:
805: if (!strcmp(ti->name, tmpbuf)) {
806:
807: *fc = *dir;
808:
809: return r;
810:
811: }
812:
813:
814:
815: /* is there already an index for this file?? If so, is it up to date?? */
816:
817: ti = tstrindex(tmpbuf);
818:
819: if (!ti->valid) {
820:
821: if (tmpbuf[1] == ':' && tmpbuf[2] == 0) {
822:
823: /* a root directory -- lookup always succeeds */
824:
825: foo.dta_size = 0;
826:
827: foo.dta_date = foo.dta_time = 0;
828:
829: foo.dta_attrib = FA_DIR;
830:
831: foo.dta_name[0] = 0;
832:
833: } else {
834:
835: do_setdta(&foo);
836:
837: r = Fsfirst(tmpbuf, FILEORDIR);
838:
839: if (r) {
840:
841: DEBUG("tos_lookup: Fsfirst(%s) returned %ld", tmpbuf, r);
842:
843: return r;
844:
845: }
846:
847: }
848:
849: ti->size = foo.dta_size;
850:
851: ti->date = foo.dta_date;
852:
853: ti->time = foo.dta_time;
854:
855: ti->attr = foo.dta_attrib;
856:
857: if (executable_extension(foo.dta_name))
858:
859: ti->attr |= FA_EXEC;
860:
861: ti->valid = 1;
862:
863: }
864:
865: fc->fs = &tos_filesys;
866:
867: fc->index = (long)ti;
868:
869: fc->dev = dir->dev;
870:
871: return r;
872:
873: }
874:
875:
876:
877: static long
878:
879: tos_getxattr(fc, xattr)
880:
881: fcookie *fc;
882:
883: XATTR *xattr;
884:
885: {
886:
887: struct tindex *ti = (struct tindex *)fc->index;
888:
889: long r;
890:
891: static long junkindex = 0;
892:
893:
894:
895: xattr->index = junkindex++;
896:
897: xattr->dev = fc->dev;
898:
899: xattr->nlink = 1;
900:
901: xattr->uid = xattr->gid = 0;
902:
903:
904:
905: ti->stamp = ++tclock;
906:
907: if (!ti->valid) {
908:
909: do_setdta(&foo);
910:
911: if (ti->name[2] == 0) { /* a root directory */
912:
913: /* actually, this can also happen if a program tries to open a file
914:
915: * with an empty name... so we should fail gracefully
916:
917: */
918:
919: TRACE("tosfs: a root directory became invalid??");
920:
921: goto around;
922:
923: }
924:
925:
926:
927: r = Fsfirst(ti->name, FILEORDIR);
928:
929: if (r < 0)
930:
931: FATAL("tosfs: search error on [%s]", ti->name);
932:
933: ti->size = foo.dta_size;
934:
935: ti->date = foo.dta_date;
936:
937: ti->time = foo.dta_time;
938:
939: ti->attr = foo.dta_attrib;
940:
941: if (executable_extension(foo.dta_name))
942:
943: ti->attr |= FA_EXEC;
944:
945: around:
946:
947: ti->valid = 1;
948:
949: }
950:
951: xattr->size = ti->size;
952:
953:
954:
955: /* BUG: blksize isn't accurate if the sector size is not 512 */
956:
957: xattr->blksize = 1024;
958:
959: xattr->nblocks = (xattr->size + 1023) / 1024;
960:
961: xattr->mdate = xattr->cdate = xattr->adate = ti->date;
962:
963: xattr->mtime = xattr->ctime = xattr->atime = ti->time;
964:
965: xattr->mode = (ti->attr & FA_DIR) ? (S_IFDIR | DEFAULT_DIRMODE) :
966:
967: (S_IFREG | DEFAULT_MODE);
968:
969:
970:
971: if (ti->attr & FA_RDONLY) {
972:
973: xattr->mode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
974:
975: }
976:
977:
978:
979: if (ti->attr & FA_EXEC) {
980:
981: xattr->mode |= (S_IXUSR|S_IXGRP|S_IXOTH);
982:
983: }
984:
985: xattr->attr = ti->attr & 0xff;
986:
987: return 0;
988:
989: }
990:
991:
992:
993: static long
994:
995: tos_chattr(fc, attrib)
996:
997: fcookie *fc;
998:
999: int attrib;
1000:
1001: {
1002:
1003: struct tindex *ti = (struct tindex *)fc->index;
1004:
1005:
1006:
1007: if (ti->attr & FA_DIR) {
1008:
1009: DEBUG("error: attempt to change attributes of a directory");
1010:
1011: return EACCDN;
1012:
1013: }
1014:
1015: ti->valid = 0;
1016:
1017: (void)tfullpath(tmpbuf, ti, "");
1018:
1019: return Fattrib(tmpbuf, 1, attrib);
1020:
1021: }
1022:
1023:
1024:
1025: static long
1026:
1027: tos_chown(dir, uid, gid)
1028:
1029: fcookie *dir;
1030:
1031: int uid, gid;
1032:
1033: {
1034:
1035: return EINVFN;
1036:
1037: }
1038:
1039:
1040:
1041: static long
1042:
1043: tos_chmode(fc, mode)
1044:
1045: fcookie *fc;
1046:
1047: unsigned mode;
1048:
1049: {
1050:
1051: int oldattr, newattr;
1052:
1053: long r;
1054:
1055: struct tindex *ti = (struct tindex *)fc->index;
1056:
1057:
1058:
1059: oldattr = Fattrib(ti->name, 0, 0);
1060:
1061: if (oldattr < 0)
1062:
1063: return oldattr;
1064:
1065:
1066:
1067: ti->valid = 0;
1068:
1069:
1070:
1071: if (!(mode & S_IWUSR))
1072:
1073: newattr = oldattr | FA_RDONLY;
1074:
1075: else
1076:
1077: newattr = oldattr & ~FA_RDONLY;
1078:
1079: if (newattr != oldattr)
1080:
1081: r = Fattrib(ti->name, 1, newattr);
1082:
1083: else
1084:
1085: r = 0;
1086:
1087: return (r < 0) ? r : 0;
1088:
1089: }
1090:
1091:
1092:
1093: static long
1094:
1095: tos_mkdir(dir, name, mode)
1096:
1097: fcookie *dir;
1098:
1099: const char *name;
1100:
1101: unsigned mode; /* ignored under TOS */
1102:
1103: {
1104:
1105: (void)tfullpath(tmpbuf, (struct tindex *)dir->index, name);
1106:
1107: tmpindex.valid = 0;
1108:
1109:
1110:
1111: return Dcreate(tmpbuf);
1112:
1113: }
1114:
1115:
1116:
1117: static long
1118:
1119: tos_rmdir(dir, name)
1120:
1121: fcookie *dir;
1122:
1123: const char *name;
1124:
1125: {
1126:
1127: struct tindex *ti;
1128:
1129:
1130:
1131: (void)tfullpath(tmpbuf, (struct tindex *)dir->index, name);
1132:
1133: ti = tstrindex(tmpbuf);
1134:
1135: ti->valid = 0;
1136:
1137:
1138:
1139: return Ddelete(tmpbuf);
1140:
1141: }
1142:
1143:
1144:
1145: static long
1146:
1147: tos_remove(dir, name)
1148:
1149: fcookie *dir;
1150:
1151: const char *name;
1152:
1153: {
1154:
1155: struct tindex *ti;
1156:
1157:
1158:
1159: (void)tfullpath(tmpbuf, (struct tindex *)dir->index, name);
1160:
1161:
1162:
1163: ti = tstrindex(tmpbuf);
1164:
1165: if (ti->open) {
1166:
1167: DEBUG("tos_remove: file is open, will be deleted later");
1168:
1169: if (ti->attr & FA_RDONLY)
1170:
1171: return EACCDN;
1172:
1173: ti->attr |= FA_DELETE;
1174:
1175: return 0;
1176:
1177: }
1178:
1179: ti->valid = 0;
1180:
1181: return Fdelete(tmpbuf);
1182:
1183: }
1184:
1185:
1186:
1187: static long
1188:
1189: tos_getname(root, dir, pathname)
1190:
1191: fcookie *root, *dir;
1192:
1193: char *pathname;
1194:
1195: {
1196:
1197: ksprintf(pathname, "%s", ((struct tindex *)dir->index)->name +
1198:
1199: strlen(((struct tindex*)root->index)->name) );
1200:
1201: if (curproc->domain == DOM_MINT)
1202:
1203: strlwr(pathname);
1204:
1205:
1206:
1207: return 0;
1208:
1209: }
1210:
1211:
1212:
1213: static long
1214:
1215: tos_rename(olddir, oldname, newdir, newname)
1216:
1217: fcookie *olddir;
1218:
1219: char *oldname;
1220:
1221: fcookie *newdir;
1222:
1223: const char *newname;
1224:
1225: {
1226:
1227: char newbuf[128];
1228:
1229: struct tindex *ti;
1230:
1231: long r;
1232:
1233:
1234:
1235: (void)tfullpath(tmpbuf, (struct tindex *)olddir->index, oldname);
1236:
1237: (void)tfullpath(newbuf, (struct tindex *)newdir->index, newname);
1238:
1239: r = Frename(0, tmpbuf, newbuf);
1240:
1241: if (r == 0) {
1242:
1243: ti = tstrindex(tmpbuf);
1244:
1245: kfree(ti->name);
1246:
1247: ti->name = kmalloc((long)strlen(newbuf)+1);
1248:
1249: if (!ti->name) {
1250:
1251: FATAL("tosfs: unable to allocate space for a name");
1252:
1253: }
1254:
1255: strcpy(ti->name, newbuf);
1256:
1257: ti->valid = 0;
1258:
1259: }
1260:
1261: return r;
1262:
1263: }
1264:
1265:
1266:
1267: #define DIR_FLAG(x) (x->fsstuff[0])
1268:
1269: #define STARTSEARCH 0 /* opendir() was just called */
1270:
1271: #define INSEARCH 1 /* readdir() has been called at least once */
1272:
1273: #define NMFILE 2 /* no more files to read */
1274:
1275:
1276:
1277: #define DIR_DTA(x) ((DTABUF *)(x->fsstuff + 2))
1278:
1279: #define DIR_NAME(x) (x->fsstuff + 32)
1280:
1281:
1282:
1283: /*
1284:
1285: * The directory functions are a bit tricky. What we do is have
1286:
1287: * opendir() do Fsfirst; the first readdir() picks up this name,
1288:
1289: * subsequent readdir()'s have to do Fsnext
1290:
1291: */
1292:
1293:
1294:
1295: static long
1296:
1297: tos_opendir(dirh, flags)
1298:
1299: DIR *dirh;
1300:
1301: int flags;
1302:
1303: {
1304:
1305: long r;
1306:
1307: struct tindex *t = (struct tindex *)dirh->fc.index;
1308:
1309:
1310:
1311: (void)tfullpath(tmpbuf, t, "*.*");
1312:
1313:
1314:
1315: do_setdta(DIR_DTA(dirh));
1316:
1317:
1318:
1319: r = Fsfirst(tmpbuf, FILEORDIR);
1320:
1321:
1322:
1323: if (r == 0) {
1324:
1325: t->open++;
1326:
1327: DIR_FLAG(dirh) = STARTSEARCH;
1328:
1329: return 0;
1330:
1331: } else if (r == EFILNF) {
1332:
1333: t->open++;
1334:
1335: DIR_FLAG(dirh) = NMFILE;
1336:
1337: return 0;
1338:
1339: }
1340:
1341: return r;
1342:
1343: }
1344:
1345:
1346:
1347: static long
1348:
1349: tos_readdir(dirh, name, namelen, fc)
1350:
1351: DIR *dirh;
1352:
1353: char *name;
1354:
1355: int namelen;
1356:
1357: fcookie *fc;
1358:
1359: {
1360:
1361: static long index = 0;
1362:
1363: long ret;
1364:
1365: int giveindex = dirh->flags == 0;
1366:
1367: struct tindex *ti;
1368:
1369: DTABUF *dta = DIR_DTA(dirh);
1370:
1371:
1372:
1373: again:
1374:
1375: if (DIR_FLAG(dirh) == NMFILE)
1376:
1377: return ENMFIL;
1378:
1379:
1380:
1381: if (DIR_FLAG(dirh) == STARTSEARCH) {
1382:
1383: DIR_FLAG(dirh) = INSEARCH;
1384:
1385: } else {
1386:
1387: assert(DIR_FLAG(dirh) == INSEARCH);
1388:
1389: do_setdta(dta);
1390:
1391: ret = Fsnext();
1392:
1393: if (ret) {
1394:
1395: DIR_FLAG(dirh) = NMFILE;
1396:
1397: return ret;
1398:
1399: }
1400:
1401: }
1402:
1403:
1404:
1405: /* don't return volume labels from readdir */
1406:
1407: if (dta->dta_attrib == FA_LABEL) goto again;
1408:
1409:
1410:
1411: fc->fs = &tos_filesys;
1412:
1413: fc->dev = dirh->fc.dev;
1414:
1415:
1416:
1417: (void)tfullpath(tmpiname, (struct tindex *)dirh->fc.index, DIR_NAME(dirh));
1418:
1419:
1420:
1421: ti = &tmpindex;
1422:
1423: ti->name = tmpiname;
1424:
1425: ti->valid = 1;
1426:
1427: ti->size = dta->dta_size;
1428:
1429: ti->date = dta->dta_date;
1430:
1431: ti->time = dta->dta_time;
1432:
1433: ti->attr = dta->dta_attrib;
1434:
1435: ti->stamp = tclock;
1436:
1437: if (executable_extension(dta->dta_name))
1438:
1439: ti->attr |= FA_EXEC;
1440:
1441: fc->index = (long)ti;
1442:
1443:
1444:
1445: if (giveindex) {
1446:
1447: namelen -= sizeof(long);
1448:
1449: if (namelen <= 0) return ERANGE;
1450:
1451: *((long *)name) = index++;
1452:
1453: name += sizeof(long);
1454:
1455: }
1456:
1457: strncpy(name, DIR_NAME(dirh), namelen-1);
1458:
1459: name[namelen-1] = 0;
1460:
1461: if (curproc->domain == DOM_MINT) {
1462:
1463: strlwr(name);
1464:
1465: }
1466:
1467: if (strlen(DIR_NAME(dirh)) >= namelen)
1468:
1469: return ENAMETOOLONG;
1470:
1471: else
1472:
1473: return 0;
1474:
1475: }
1476:
1477:
1478:
1479: static long
1480:
1481: tos_rewinddir(dirh)
1482:
1483: DIR *dirh;
1484:
1485: {
1486:
1487: struct tindex *ti = (struct tindex *)dirh->fc.index;
1488:
1489: long r;
1490:
1491:
1492:
1493: (void)tfullpath(tmpbuf, ti, "*.*");
1494:
1495: do_setdta(DIR_DTA(dirh));
1496:
1497: r = Fsfirst(tmpbuf, FILEORDIR);
1498:
1499: if (r == 0) {
1500:
1501: DIR_FLAG(dirh) = STARTSEARCH;
1502:
1503: } else {
1504:
1505: DIR_FLAG(dirh) = NMFILE;
1506:
1507: }
1508:
1509: return r;
1510:
1511: }
1512:
1513:
1514:
1515: static long
1516:
1517: tos_closedir(dirh)
1518:
1519: DIR *dirh;
1520:
1521: {
1522:
1523: struct tindex *t = (struct tindex *)dirh->fc.index;
1524:
1525:
1526:
1527: assert(t->open);
1528:
1529: --t->open;
1530:
1531: DIR_FLAG(dirh) = NMFILE;
1532:
1533: return 0;
1534:
1535: }
1536:
1537:
1538:
1539: static long
1540:
1541: tos_pathconf(dir, which)
1542:
1543: fcookie *dir;
1544:
1545: int which;
1546:
1547: {
1548:
1549: switch(which) {
1550:
1551: case -1:
1552:
1553: return DP_MAXREQ;
1554:
1555: case DP_IOPEN:
1556:
1557: return 60; /* we can only keep about this many open */
1558:
1559: case DP_MAXLINKS:
1560:
1561: return 1; /* no hard links */
1562:
1563: case DP_PATHMAX:
1564:
1565: return PATH_MAX;
1566:
1567: case DP_NAMEMAX:
1568:
1569: return 8+3+1;
1570:
1571: case DP_ATOMIC:
1572:
1573: return 512; /* we can write at least a sector atomically */
1574:
1575: case DP_TRUNC:
1576:
1577: return DP_DOSTRUNC; /* DOS style file names */
1578:
1579: case DP_CASE:
1580:
1581: return DP_CASECONV; /* names converted to upper case */
1582:
1583: default:
1584:
1585: return EINVFN;
1586:
1587: }
1588:
1589: }
1590:
1591:
1592:
1593: long
1594:
1595: tos_dfree(dir, buf)
1596:
1597: fcookie *dir;
1598:
1599: long *buf;
1600:
1601: {
1602:
1603: return Dfree(buf, (dir->dev)+1);
1604:
1605: }
1606:
1607:
1608:
1609: /*
1610:
1611: * writelabel: creates a volume label
1612:
1613: * readlabel: reads a volume label
1614:
1615: * both of these are only guaranteed to work in the root directory
1616:
1617: */
1618:
1619:
1620:
1621: /*
1622:
1623: * BUG: this should first delete any old labels, so that it will
1624:
1625: * work with TOS <1.4
1626:
1627: */
1628:
1629:
1630:
1631: long
1632:
1633: tos_writelabel(dir, name)
1634:
1635: fcookie *dir;
1636:
1637: const char *name;
1638:
1639: {
1640:
1641: long r;
1642:
1643: struct tindex *ti;
1644:
1645:
1646:
1647: (void)tfullpath(tmpbuf, (struct tindex *)dir->index, name);
1648:
1649: r = Fcreate(tmpbuf, FA_LABEL);
1650:
1651: if (r < 0) return r;
1652:
1653: (void)Fclose(r);
1654:
1655: ti = tstrindex(tmpbuf);
1656:
1657: ti->valid = 0;
1658:
1659: return 0;
1660:
1661: }
1662:
1663:
1664:
1665: long
1666:
1667: tos_readlabel(dir, name, namelen)
1668:
1669: fcookie *dir;
1670:
1671: char *name;
1672:
1673: int namelen;
1674:
1675: {
1676:
1677: long r;
1678:
1679: struct tindex *ti = (struct tindex *)dir->index;
1680:
1681:
1682:
1683: if (ti->name[2] != 0) /* not a root directory? */
1684:
1685: return EFILNF;
1686:
1687:
1688:
1689: (void)tfullpath(tmpbuf, ti, "*.*");
1690:
1691: do_setdta(&foo);
1692:
1693: r = Fsfirst(tmpbuf, FA_LABEL);
1694:
1695: if (r)
1696:
1697: return r;
1698:
1699: strncpy(name, foo.dta_name, namelen-1);
1700:
1701: return (strlen(foo.dta_name) < namelen) ? 0 : ENAMETOOLONG;
1702:
1703: }
1704:
1705:
1706:
1707: /*
1708:
1709: * TOS creat: this doesn't actually create the file, rather it
1710:
1711: * sets up a (fake) index for the file that will be used by
1712:
1713: * the later tos_open call.
1714:
1715: */
1716:
1717:
1718:
1719: static long
1720:
1721: tos_creat(dir, name, mode, attrib, fc)
1722:
1723: fcookie *dir;
1724:
1725: const char *name;
1726:
1727: unsigned mode;
1728:
1729: int attrib;
1730:
1731: fcookie *fc;
1732:
1733: {
1734:
1735: struct tindex *ti;
1736:
1737:
1738:
1739: (void)tfullpath(tmpbuf, (struct tindex *)dir->index, name);
1740:
1741:
1742:
1743: ti = tstrindex(tmpbuf);
1744:
1745: ti->size = 0;
1746:
1747: ti->date = datestamp;
1748:
1749: ti->time = timestamp;
1750:
1751: ti->attr = attrib;
1752:
1753: ti->valid = 1;
1754:
1755:
1756:
1757: fc->fs = &tos_filesys;
1758:
1759: fc->index = (long)ti;
1760:
1761: fc->dev = dir->dev;
1762:
1763: return 0;
1764:
1765: }
1766:
1767:
1768:
1769: /*
1770:
1771: * TOS device driver
1772:
1773: */
1774:
1775:
1776:
1777: static DEVDRV *
1778:
1779: tos_getdev(fc, devsp)
1780:
1781: fcookie *fc;
1782:
1783: long *devsp;
1784:
1785: {
1786:
1787: return &tos_device;
1788:
1789: }
1790:
1791:
1792:
1793: static long
1794:
1795: tos_open(f)
1796:
1797: FILEPTR *f;
1798:
1799: {
1800:
1801: struct tindex *ti;
1802:
1803: int mode = f->flags;
1804:
1805: int tosmode;
1806:
1807: long r;
1808:
1809: extern int flk; /* in main.c, set if _FLK cookie already present */
1810:
1811:
1812:
1813: ti = (struct tindex *)(f->fc.index);
1814:
1815: assert(ti != 0);
1816:
1817:
1818:
1819: ti->stamp = ++tclock;
1820:
1821: ti->valid = 0;
1822:
1823:
1824:
1825: /* TEMPORARY HACK: change all modes to O_RDWR for files opened in
1826:
1827: * compatibility sharing mode. This is silly, but
1828:
1829: * allows broken TOS programs that write to read-only handles to continue
1830:
1831: * to work (it also helps file sharing, by making the realistic assumption
1832:
1833: * that any open TOS file can be written to). Eventually,
1834:
1835: * this should be tuneable by the user somehow.
1836:
1837: * ALSO: change O_COMPAT opens into O_DENYNONE; again, this may be temporary.
1838:
1839: */
1840:
1841: if ( (mode & O_SHMODE) == O_COMPAT ) {
1842:
1843: f->flags = (mode & ~(O_RWMODE|O_SHMODE)) | O_RDWR | O_DENYNONE;
1844:
1845: }
1846:
1847:
1848:
1849: /* check to see that nobody has opened this file already in an
1850:
1851: * incompatible mode
1852:
1853: */
1854:
1855: if (denyshare(ti->open, f)) {
1856:
1857: TRACE("tos_open: file sharing denied");
1858:
1859: return EACCDN;
1860:
1861: }
1862:
1863:
1864:
1865: /*
1866:
1867: * now open the file; if O_TRUNC was specified, actually
1868:
1869: * create the file anew.
1870:
1871: * BUG: O_TRUNC without O_CREAT doesn't work right. The kernel doesn't
1872:
1873: * use this mode, anyways
1874:
1875: */
1876:
1877:
1878:
1879: if (mode & O_TRUNC) {
1880:
1881: if (ti->open) {
1882:
1883: DEBUG("tos_open: attempt to truncate an open file");
1884:
1885: return EACCDN;
1886:
1887: }
1888:
1889: r = Fcreate(ti->name, ti->attr);
1890:
1891: } else {
1892:
1893: if (flk)
1894:
1895: tosmode = mode & (O_RWMODE|O_SHMODE);
1896:
1897: else
1898:
1899: tosmode = (mode & O_RWMODE);
1900:
1901: if (tosmode == O_EXEC) tosmode = O_RDONLY;
1902:
1903:
1904:
1905: r = Fopen(ti->name, tosmode );
1906:
1907: if (r == EFILNF && (mode & O_CREAT))
1908:
1909: r = Fcreate(ti->name, ti->attr);
1910:
1911: }
1912:
1913:
1914:
1915: if (r < 0) {
1916:
1917: /* get rid of the index for the file, since it doesn't exist */
1918:
1919: kfree(ti->name);
1920:
1921: ti->name = 0;
1922:
1923: ti->valid = 0;
1924:
1925: return r;
1926:
1927: }
1928:
1929:
1930:
1931: f->devinfo = r;
1932:
1933:
1934:
1935: f->next = ti->open;
1936:
1937: ti->open = f;
1938:
1939: return 0;
1940:
1941: }
1942:
1943:
1944:
1945: static long
1946:
1947: tos_write(f, buf, bytes)
1948:
1949: FILEPTR *f; const char *buf; long bytes;
1950:
1951: {
1952:
1953: struct tindex *ti = (struct tindex *)f->fc.index;
1954:
1955:
1956:
1957: ti->valid = 0;
1958:
1959: return Fwrite((int)f->devinfo, bytes, buf);
1960:
1961: }
1962:
1963:
1964:
1965: static long
1966:
1967: tos_read(f, buf, bytes)
1968:
1969: FILEPTR *f; char *buf; long bytes;
1970:
1971: {
1972:
1973: return Fread((int)f->devinfo, bytes, buf);
1974:
1975: }
1976:
1977:
1978:
1979: static long
1980:
1981: tos_lseek(f, where, whence)
1982:
1983: FILEPTR *f; long where; int whence;
1984:
1985: {
1986:
1987: long r;
1988:
1989:
1990:
1991: r = Fseek(where, (int)f->devinfo, whence);
1992:
1993: return r;
1994:
1995: }
1996:
1997:
1998:
1999: static long
2000:
2001: tos_ioctl(f, mode, buf)
2002:
2003: FILEPTR *f; int mode; void *buf;
2004:
2005: {
2006:
2007: LOCK t, *lck, **old;
2008:
2009: struct flock *fl;
2010:
2011: long r;
2012:
2013: struct tindex *ti;
2014:
2015: extern int flk; /* set in main.c if _FLK already installed */
2016:
2017:
2018:
2019: if (mode == FIONREAD || mode == FIONWRITE) {
2020:
2021: *((long *)buf) = 1;
2022:
2023: return 0;
2024:
2025: }
2026:
2027: else if (mode == F_SETLK || mode == F_GETLK) {
2028:
2029: fl = ((struct flock *)buf);
2030:
2031: t.l = *fl;
2032:
2033: switch(t.l.l_whence) {
2034:
2035: case 0:
2036:
2037: break;
2038:
2039: case 1: /* SEEK_CUR */
2040:
2041: r = Fseek(0L, (int)f->devinfo, 1);
2042:
2043: t.l.l_start += r;
2044:
2045: break;
2046:
2047: case 2:
2048:
2049: r = Fseek(0L, (int)f->devinfo, 1);
2050:
2051: t.l.l_start = Fseek(t.l.l_start, (int)f->devinfo, 2);
2052:
2053: (void)Fseek(r, (int)f->devinfo, 0);
2054:
2055: break;
2056:
2057: default:
2058:
2059: DEBUG("Invalid value for l_whence");
2060:
2061: return EINVFN;
2062:
2063: }
2064:
2065: /* BUG: can't lock a file starting at >2gigabytes from the beginning */
2066:
2067: if (t.l.l_start < 0) t.l.l_start = 0;
2068:
2069: t.l.l_whence = 0;
2070:
2071: ti = (struct tindex *)f->fc.index;
2072:
2073:
2074:
2075: if (mode == F_GETLK) {
2076:
2077: lck = denylock(ti->locks, &t);
2078:
2079: if (lck)
2080:
2081: *fl = lck->l;
2082:
2083: else
2084:
2085: fl->l_type = F_UNLCK;
2086:
2087: return 0;
2088:
2089: }
2090:
2091:
2092:
2093: if (t.l.l_type == F_UNLCK) {
2094:
2095: /* try to find the lock */
2096:
2097: old = &ti->locks;
2098:
2099: lck = *old;
2100:
2101: while (lck) {
2102:
2103: if (lck->l.l_pid == curproc->pid &&
2104:
2105: lck->l.l_start == t.l.l_start &&
2106:
2107: lck->l.l_len == t.l.l_len) {
2108:
2109: /* found it -- remove the lock */
2110:
2111: *old = lck->next;
2112:
2113: TRACE("tosfs: unlocked %s: %ld + %ld",
2114:
2115: ti->name, t.l.l_start, t.l.l_len);
2116:
2117: kfree(lck);
2118:
2119: if (flk)
2120:
2121: (void)Flock((int)f->devinfo, 1,
2122:
2123: t.l.l_start, t.l.l_len);
2124:
2125: break;
2126:
2127: }
2128:
2129: old = &lck->next;
2130:
2131: lck = lck->next;
2132:
2133: }
2134:
2135: return lck ? 0 : ENSLOCK;
2136:
2137: }
2138:
2139: TRACE("tosfs: lock %s: %ld + %ld", ti->name,
2140:
2141: t.l.l_start, t.l.l_len);
2142:
2143: /* see if there's a conflicting lock */
2144:
2145: lck = denylock(ti->locks, &t);
2146:
2147: if (lck) {
2148:
2149: DEBUG("tosfs: lock conflicts with one held by %d",
2150:
2151: lck->l.l_pid);
2152:
2153: return ELOCKED;
2154:
2155: }
2156:
2157: /* if not, add this lock to the list */
2158:
2159: lck = kmalloc(SIZEOF(LOCK));
2160:
2161: if (!lck) return ENSMEM;
2162:
2163: /* see if other _FLK code might object */
2164:
2165: if (flk) {
2166:
2167: r = Flock((int)f->devinfo, 0, t.l.l_start, t.l.l_len);
2168:
2169: if (r) {
2170:
2171: kfree(lck);
2172:
2173: return r;
2174:
2175: }
2176:
2177: }
2178:
2179: lck->l = t.l;
2180:
2181: lck->l.l_pid = curproc->pid;
2182:
2183: lck->next = ti->locks;
2184:
2185: ti->locks = lck;
2186:
2187: /* mark the file as being locked */
2188:
2189: f->flags |= O_LOCK;
2190:
2191: return 0;
2192:
2193: }
2194:
2195: return EINVFN;
2196:
2197: }
2198:
2199:
2200:
2201: static long
2202:
2203: tos_datime(f, timeptr, rwflag)
2204:
2205: FILEPTR *f;
2206:
2207: short *timeptr;
2208:
2209: int rwflag;
2210:
2211: {
2212:
2213: if (rwflag) {
2214:
2215: struct tindex *ti = (struct tindex *)f->fc.index;
2216:
2217: ti->valid = 0;
2218:
2219: }
2220:
2221: return Fdatime(timeptr, (int)f->devinfo, rwflag);
2222:
2223: }
2224:
2225:
2226:
2227: static long
2228:
2229: tos_close(f, pid)
2230:
2231: FILEPTR *f;
2232:
2233: int pid;
2234:
2235: {
2236:
2237: LOCK *lck, **oldl;
2238:
2239: struct tindex *t;
2240:
2241: FILEPTR **old, *p;
2242:
2243: long r = 0;
2244:
2245: extern int flk; /* set in main.c */
2246:
2247:
2248:
2249: t = (struct tindex *)(f->fc.index);
2250:
2251: /* if this handle was locked, remove any locks held by the process
2252:
2253: */
2254:
2255: if (f->flags & O_LOCK) {
2256:
2257: TRACE("tos_close: releasing locks (file mode: %x)", f->flags);
2258:
2259: oldl = &t->locks;
2260:
2261: lck = *oldl;
2262:
2263: while (lck) {
2264:
2265: if (lck->l.l_pid == pid) {
2266:
2267: *oldl = lck->next;
2268:
2269: if (flk)
2270:
2271: (void)Flock((int)f->devinfo, 1,
2272:
2273: lck->l.l_start, lck->l.l_len);
2274:
2275: kfree(lck);
2276:
2277: } else {
2278:
2279: oldl = &lck->next;
2280:
2281: }
2282:
2283: lck = *oldl;
2284:
2285: }
2286:
2287: }
2288:
2289:
2290:
2291: if (f->links <= 0) {
2292:
2293: /* remove f from the list of open file pointers on this index */
2294:
2295: t->valid = 0;
2296:
2297: old = &t->open;
2298:
2299: p = t->open;
2300:
2301: while (p && p != f) {
2302:
2303: old = &p->next;
2304:
2305: p = p->next;
2306:
2307: }
2308:
2309: assert(p);
2310:
2311: *old = f->next;
2312:
2313: f->next = 0;
2314:
2315: r = Fclose((int)f->devinfo);
2316:
2317:
2318:
2319: /* if the file was marked for deletion, delete it */
2320:
2321: if (!t->open) {
2322:
2323: if (t->attr & FA_DELETE) {
2324:
2325: (void)Fdelete(t->name);
2326:
2327: t->name = 0;
2328:
2329: }
2330:
2331: }
2332:
2333: }
2334:
2335: return r;
2336:
2337: }
2338:
2339:
2340:
2341: /*
2342:
2343: * check for disk change: called by the kernel if Mediach returns a
2344:
2345: * non-zero value
2346:
2347: */
2348:
2349:
2350:
2351: long
2352:
2353: tos_dskchng(drv)
2354:
2355: int drv;
2356:
2357: {
2358:
2359: char dlet;
2360:
2361: int i;
2362:
2363: struct tindex *ti;
2364:
2365:
2366:
2367: dlet = 'A' + drv;
2368:
2369: ti = gl_ti;
2370:
2371: for (i = 0; i < NUM_INDICES; i++, ti++) {
2372:
2373: if (ti->name[0] == dlet) {
2374:
2375: kfree(ti->name);
2376:
2377: ti->name = 0;
2378:
2379: }
2380:
2381: }
2382:
2383: /*
2384:
2385: * OK, make sure that GEMDOS knows to look for a change if we
2386:
2387: * ever use this drive again.
2388:
2389: */
2390:
2391: drvchanged[drv] = 1;
2392:
2393: return 1;
2394:
2395: }
2396:
2397:
2398:
2399: /*
2400:
2401: * utility function: sets the TOS DTA, and also records what directory
2402:
2403: * this was in. This is just to save us a call into the kernel if the
2404:
2405: * correct DTA has already been set.
2406:
2407: */
2408:
2409:
2410:
2411: static void
2412:
2413: do_setdta(dta)
2414:
2415: DTABUF *dta;
2416:
2417: {
2418:
2419: if (dta != lastdta) {
2420:
2421: Fsetdta(dta);
2422:
2423: lastdta = dta;
2424:
2425: }
2426:
2427: }
2428:
2429:
2430:
2431: /*
2432:
2433: * routines for forcing a media change on drive "drv"
2434:
2435: */
2436:
2437:
2438:
2439: static int chdrv;
2440:
2441:
2442:
2443: /* new Getbpb function: when this is called, all the other
2444:
2445: * vectors can be un-installed
2446:
2447: */
2448:
2449:
2450:
2451: static long (*Oldgetbpb) P_((int));
2452:
2453: static long (*Oldmediach) P_((int));
2454:
2455: static long (*Oldrwabs) P_((int, void *, int, int, int, long));
2456:
2457:
2458:
2459: static long
2460:
2461: Newgetbpb(d)
2462:
2463: int d;
2464:
2465: {
2466:
2467: if (d == chdrv) {
2468:
2469: *((Func *)0x472L) = Oldgetbpb;
2470:
2471: *((Func *)0x476L) = Oldrwabs;
2472:
2473: *((Func *)0x47eL) = Oldmediach;
2474:
2475: }
2476:
2477: return (*Oldgetbpb)(d);
2478:
2479: }
2480:
2481:
2482:
2483: static long
2484:
2485: Newmediach(d)
2486:
2487: int d;
2488:
2489: {
2490:
2491: if (d == chdrv)
2492:
2493: return 2;
2494:
2495: return (*Oldmediach)(d);
2496:
2497: }
2498:
2499:
2500:
2501: static long
2502:
2503: Newrwabs(d, buf, a, b, c, l)
2504:
2505: int d;
2506:
2507: void *buf;
2508:
2509: int a, b, c;
2510:
2511: long l;
2512:
2513: {
2514:
2515: if (d == chdrv)
2516:
2517: return E_CHNG;
2518:
2519: return (*Oldrwabs)(d, buf, a, b, c, l);
2520:
2521: }
2522:
2523:
2524:
2525: static void
2526:
2527: force_mediach(d)
2528:
2529: int d;
2530:
2531: {
2532:
2533: long r;
2534:
2535: static char fname[] = "X:\\.INF";
2536:
2537:
2538:
2539: TRACE("tosfs: disk change drive %c", d+'A');
2540:
2541:
2542:
2543: chdrv = d;
2544:
2545: Oldrwabs = *((Func *)0x476L);
2546:
2547: if (Oldrwabs == Newrwabs) {
2548:
2549: ALERT("tosfs: error in media change code");
2550:
2551: } else {
2552:
2553: *((Func *)0x476L) = Newrwabs;
2554:
2555: Oldmediach = *((Func *)0x47eL);
2556:
2557: *((Func *)0x47eL) = Newmediach;
2558:
2559: Oldgetbpb = *((Func *)0x472L);
2560:
2561: *((Func *)0x472L) = Newgetbpb;
2562:
2563: }
2564:
2565:
2566:
2567: fname[0] = d + 'A';
2568:
2569: r = Fopen(fname, 0);
2570:
2571: if (r >= 0) (void)Fclose(r);
2572:
2573:
2574:
2575: drvchanged[d] = 0;
2576:
2577: }
2578:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.