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