|
|
1.1 root 1: /*
2:
1.1.1.3 root 3: Copyright 1991,1992 Eric R. Smith.
4:
1.1.1.4 ! root 5: Copyright 1992,1993 Atari Corporation.
1.1.1.3 root 6:
7: All rights reserved.
1.1 root 8:
9: */
10:
11:
12:
13: /* a simple unified file system */
14:
15:
16:
17: #include "mint.h"
18:
19:
20:
21:
22:
23: extern FILESYS bios_filesys, proc_filesys, pipe_filesys, shm_filesys;
24:
25:
26:
1.1.1.2 root 27: static long ARGS_ON_STACK uni_root P_((int drv, fcookie *fc));
1.1 root 28:
1.1.1.2 root 29: static long ARGS_ON_STACK uni_lookup P_((fcookie *dir, const char *name, fcookie *fc));
1.1 root 30:
1.1.1.2 root 31: static long ARGS_ON_STACK uni_getxattr P_((fcookie *fc, XATTR *xattr));
1.1 root 32:
1.1.1.2 root 33: static long ARGS_ON_STACK uni_chattr P_((fcookie *fc, int attrib));
1.1 root 34:
1.1.1.2 root 35: static long ARGS_ON_STACK uni_chown P_((fcookie *fc, int uid, int gid));
1.1 root 36:
1.1.1.2 root 37: static long ARGS_ON_STACK uni_chmode P_((fcookie *fc, unsigned mode));
1.1 root 38:
1.1.1.2 root 39: static long ARGS_ON_STACK uni_rmdir P_((fcookie *dir, const char *name));
1.1 root 40:
1.1.1.2 root 41: static long ARGS_ON_STACK uni_remove P_((fcookie *dir, const char *name));
1.1 root 42:
1.1.1.3 root 43: static long ARGS_ON_STACK uni_getname P_((fcookie *root, fcookie *dir,
44:
45: char *pathname, int size));
1.1 root 46:
1.1.1.2 root 47: static long ARGS_ON_STACK uni_rename P_((fcookie *olddir, char *oldname,
1.1 root 48:
49: fcookie *newdir, const char *newname));
50:
1.1.1.2 root 51: static long ARGS_ON_STACK uni_opendir P_((DIR *dirh, int flags));
1.1 root 52:
1.1.1.2 root 53: static long ARGS_ON_STACK uni_readdir P_((DIR *dirh, char *nm, int nmlen, fcookie *));
1.1 root 54:
1.1.1.2 root 55: static long ARGS_ON_STACK uni_rewinddir P_((DIR *dirh));
1.1 root 56:
1.1.1.2 root 57: static long ARGS_ON_STACK uni_closedir P_((DIR *dirh));
1.1 root 58:
1.1.1.2 root 59: static long ARGS_ON_STACK uni_pathconf P_((fcookie *dir, int which));
1.1 root 60:
1.1.1.2 root 61: static long ARGS_ON_STACK uni_dfree P_((fcookie *dir, long *buf));
1.1 root 62:
1.1.1.2 root 63: static DEVDRV * ARGS_ON_STACK uni_getdev P_((fcookie *fc, long *devsp));
1.1 root 64:
1.1.1.2 root 65: static long ARGS_ON_STACK uni_symlink P_((fcookie *dir, const char *name, const char *to));
1.1 root 66:
1.1.1.2 root 67: static long ARGS_ON_STACK uni_readlink P_((fcookie *fc, char *buf, int buflen));
1.1 root 68:
1.1.1.4 ! root 69: static long ARGS_ON_STACK uni_fscntl P_((fcookie *dir, const char *name, int cmd, long arg));
! 70:
1.1 root 71:
72:
73: FILESYS uni_filesys = {
74:
75: (FILESYS *)0,
76:
1.1.1.3 root 77: FS_LONGPATH,
1.1 root 78:
79: uni_root,
80:
81: uni_lookup, nocreat, uni_getdev, uni_getxattr,
82:
83: uni_chattr, uni_chown, uni_chmode,
84:
85: nomkdir, uni_rmdir, uni_remove, uni_getname, uni_rename,
86:
87: uni_opendir, uni_readdir, uni_rewinddir, uni_closedir,
88:
89: uni_pathconf, uni_dfree, nowritelabel, noreadlabel,
90:
1.1.1.4 ! root 91: uni_symlink, uni_readlink, nohardlink, uni_fscntl, nodskchng
1.1 root 92:
93: };
94:
95:
96:
97: /*
98:
99: * structure that holds files
100:
101: * if (mode & S_IFMT == S_IFDIR), then this is an alias for a drive:
102:
103: * "dev" holds the appropriate BIOS device number, and
104:
105: * "data" is meaningless
106:
107: * if (mode & S_IFMT == S_IFLNK), then this is a symbolic link:
108:
109: * "dev" holds the user id of the owner, and
110:
111: * "data" points to the actual link data
112:
113: */
114:
115:
116:
117: typedef struct unifile {
118:
119: char name[NAME_MAX+1];
120:
1.1.1.2 root 121: ushort mode;
1.1 root 122:
123: ushort dev;
124:
125: FILESYS *fs;
126:
127: void *data;
128:
129: struct unifile *next;
130:
131: } UNIFILE;
132:
133:
134:
1.1.1.2 root 135: static UNIFILE u_drvs[UNI_NUM_DRVS];
1.1 root 136:
137: static UNIFILE *u_root = 0;
138:
139:
140:
141: void
142:
143: unifs_init()
144:
145: {
146:
147: UNIFILE *u = u_drvs;
148:
149: int i;
150:
151:
152:
153: u_root = u;
154:
1.1.1.2 root 155: for (i = 0; i < UNI_NUM_DRVS; i++,u++) {
1.1 root 156:
157: u->next = u+1;
158:
159: u->mode = S_IFDIR|DEFAULT_DIRMODE;
160:
161: u->dev = i;
162:
1.1.1.2 root 163: if (i == PROCDRV) {
1.1 root 164:
165: strcpy(u->name, "proc");
166:
1.1.1.2 root 167: u->fs = &proc_filesys;
168:
169: } else if (i == PIPEDRV) {
1.1 root 170:
171: strcpy(u->name, "pipe");
172:
1.1.1.2 root 173: u->fs = &pipe_filesys;
174:
175: } else if (i == BIOSDRV) {
1.1 root 176:
177: strcpy(u->name, "dev");
178:
1.1.1.2 root 179: u->fs = &bios_filesys;
180:
181: } else if (i == UNIDRV) {
1.1 root 182:
183: (u-1)->next = u->next; /* skip this drive */
184:
1.1.1.2 root 185: } else if (i == SHMDRV) {
186:
187: strcpy(u->name, "shm");
188:
189: u->fs = &shm_filesys;
190:
1.1 root 191: } else {
192:
193: u->name[0] = i + 'a';
194:
195: u->name[1] = 0;
196:
1.1.1.2 root 197: u->fs = 0;
198:
1.1 root 199: }
200:
201: }
202:
1.1.1.2 root 203: --u; /* oops, we went too far */
1.1 root 204:
1.1.1.2 root 205: u->next = 0;
1.1 root 206:
207: }
208:
209:
210:
1.1.1.2 root 211: static long ARGS_ON_STACK
1.1 root 212:
213: uni_root(drv, fc)
214:
215: int drv;
216:
217: fcookie *fc;
218:
219: {
220:
221: if (drv == UNIDRV) {
222:
223: fc->fs = &uni_filesys;
224:
225: fc->dev = drv;
226:
227: fc->index = 0L;
228:
229: return 0;
230:
231: }
232:
233: fc->fs = 0;
234:
235: return EINTRN;
236:
237: }
238:
239:
240:
1.1.1.2 root 241: static long ARGS_ON_STACK
1.1 root 242:
243: uni_lookup(dir, name, fc)
244:
245: fcookie *dir;
246:
247: const char *name;
248:
249: fcookie *fc;
250:
251: {
252:
253: UNIFILE *u;
254:
255: long drvs;
256:
257: FILESYS *fs;
258:
1.1.1.3 root 259: fcookie *tmp;
260:
1.1 root 261: extern long dosdrvs;
262:
263:
264:
1.1.1.2 root 265: TRACE(("uni_lookup(%s)", name));
1.1 root 266:
267:
268:
269: if (dir->index != 0) {
270:
1.1.1.2 root 271: DEBUG(("uni_lookup: bad directory"));
1.1 root 272:
273: return EPTHNF;
274:
275: }
276:
277: /* special case: an empty name in a directory means that directory */
278:
279: /* so do "." and ".." */
280:
281:
282:
283: if (!*name || !strcmp(name, ".") || !strcmp(name, "..")) {
284:
1.1.1.3 root 285: dup_cookie(fc, dir);
1.1 root 286:
287: return 0;
288:
289: }
290:
291: drvs = drvmap() | dosdrvs | PSEUDODRVS;
292:
293: /*
294:
295: * OK, check the list of aliases and special directories
296:
297: */
298:
299: for (u = u_root; u; u = u->next) {
300:
301: if (!stricmp(name, u->name)) {
302:
303: if ( (u->mode & S_IFMT) == S_IFDIR ) {
304:
305: if (u->dev >= NUM_DRIVES) {
306:
307: fs = u->fs;
308:
309: return (*fs->root)(u->dev,fc);
310:
311: }
312:
313: if ((drvs & (1L << u->dev)) == 0)
314:
315: return EPTHNF;
316:
1.1.1.3 root 317: tmp = &curproc->root[u->dev];
1.1 root 318:
1.1.1.3 root 319: if (!tmp->fs) { /* drive changed? */
1.1 root 320:
1.1.1.3 root 321: changedrv(tmp->dev);
1.1 root 322:
1.1.1.3 root 323: tmp = &curproc->root[u->dev];
1.1 root 324:
1.1.1.3 root 325: if (!tmp->fs)
1.1 root 326:
327: return EPTHNF;
328:
329: }
330:
1.1.1.3 root 331: dup_cookie(fc, tmp);
332:
1.1 root 333: } else { /* a symbolic link */
334:
335: fc->fs = &uni_filesys;
336:
337: fc->dev = UNIDRV;
338:
339: fc->index = (long)u;
340:
341: }
342:
343: return 0;
344:
345: }
346:
347: }
348:
1.1.1.2 root 349: DEBUG(("uni_lookup: name (%s) not found", name));
1.1 root 350:
351: return EFILNF;
352:
353: }
354:
355:
356:
1.1.1.2 root 357: static long ARGS_ON_STACK
1.1 root 358:
359: uni_getxattr(fc, xattr)
360:
361: fcookie *fc;
362:
363: XATTR *xattr;
364:
365: {
366:
367: UNIFILE *u = (UNIFILE *)fc->index;
368:
369:
370:
371: if (fc->fs != &uni_filesys) {
372:
373: ALERT("ERROR: wrong file system getxattr called");
374:
375: return EINTRN;
376:
377: }
378:
379:
380:
381: xattr->index = fc->index;
382:
383: xattr->dev = fc->dev;
384:
385: xattr->nlink = 1;
386:
387: xattr->blksize = 1;
388:
389:
390:
391: /* If "u" is null, then we have the root directory, otherwise
392:
393: * we use the UNIFILE structure to get the info about it
394:
395: */
396:
397: if (!u || ( (u->mode & S_IFMT) == S_IFDIR )) {
398:
399: xattr->uid = xattr->gid = 0;
400:
401: xattr->size = xattr->nblocks = 0;
402:
403: xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
404:
405: xattr->attr = FA_DIR;
406:
407: } else {
408:
409: xattr->uid = u->dev;
410:
411: xattr->gid = 0;
412:
413: xattr->size = xattr->nblocks = strlen(u->data) + 1;
414:
415: xattr->mode = u->mode;
416:
417: xattr->attr = 0;
418:
419: }
420:
421: xattr->mtime = xattr->atime = xattr->ctime = 0;
422:
423: xattr->mdate = xattr->adate = xattr->cdate = 0;
424:
425: return 0;
426:
427: }
428:
429:
430:
1.1.1.2 root 431: static long ARGS_ON_STACK
1.1 root 432:
433: uni_chattr(dir, attrib)
434:
435: fcookie *dir;
436:
437: int attrib;
438:
439: {
440:
1.1.1.2 root 441: UNUSED(dir); UNUSED(attrib);
442:
1.1 root 443: return EACCDN;
444:
445: }
446:
447:
448:
1.1.1.2 root 449: static long ARGS_ON_STACK
1.1 root 450:
451: uni_chown(dir, uid, gid)
452:
453: fcookie *dir;
454:
455: int uid, gid;
456:
457: {
458:
1.1.1.2 root 459: UNUSED(dir); UNUSED(uid);
460:
461: UNUSED(gid);
462:
1.1 root 463: return EINVFN;
464:
465: }
466:
467:
468:
1.1.1.2 root 469: static long ARGS_ON_STACK
1.1 root 470:
471: uni_chmode(dir, mode)
472:
473: fcookie *dir;
474:
475: unsigned mode;
476:
477: {
478:
1.1.1.2 root 479: UNUSED(dir);
480:
481: UNUSED(mode);
482:
1.1 root 483: return EINVFN;
484:
485: }
486:
487:
488:
1.1.1.2 root 489: static long ARGS_ON_STACK
1.1 root 490:
491: uni_rmdir(dir, name)
492:
493: fcookie *dir;
494:
495: const char *name;
496:
497: {
498:
499: long r;
500:
501:
502:
503: r = uni_remove(dir, name);
504:
505: if (r == EFILNF) r = EPTHNF;
506:
507: return r;
508:
509: }
510:
511:
512:
1.1.1.2 root 513: static long ARGS_ON_STACK
1.1 root 514:
515: uni_remove(dir, name)
516:
517: fcookie *dir;
518:
519: const char *name;
520:
521: {
522:
523: UNIFILE *u, *lastu;
524:
525:
526:
1.1.1.2 root 527: UNUSED(dir);
528:
529:
530:
1.1 root 531: lastu = 0;
532:
533: u = u_root;
534:
535: while (u) {
536:
537: if (!strncmp(u->name, name, NAME_MAX)) {
538:
539: if ( (u->mode & S_IFMT) != S_IFLNK ) return EFILNF;
540:
541: kfree(u->data);
542:
543: if (lastu)
544:
545: lastu->next = u->next;
546:
547: else
548:
549: u_root = u->next;
550:
551: kfree(u);
552:
553: return 0;
554:
555: }
556:
557: lastu = u;
558:
559: u = u->next;
560:
561: }
562:
563: return EFILNF;
564:
565: }
566:
567:
568:
1.1.1.2 root 569: static long ARGS_ON_STACK
1.1 root 570:
1.1.1.3 root 571: uni_getname(root, dir, pathname, size)
1.1 root 572:
573: fcookie *root, *dir; char *pathname;
574:
1.1.1.3 root 575: int size;
576:
1.1 root 577: {
578:
579: FILESYS *fs;
580:
581: UNIFILE *u;
582:
583: char *n;
584:
585: fcookie relto;
586:
1.1.1.3 root 587: char tmppath[PATH_MAX];
588:
589: long r;
590:
1.1 root 591:
592:
1.1.1.2 root 593: UNUSED(root);
594:
595:
596:
1.1.1.3 root 597: if (size <= 0) return ERANGE;
598:
599:
600:
1.1 root 601: fs = dir->fs;
602:
603: if (dir->dev == UNIDRV) {
604:
605: *pathname = 0;
606:
607: return 0;
608:
609: }
610:
611:
612:
613: for (u = u_root; u; u = u->next) {
614:
615: if (dir->dev == u->dev && (u->mode & S_IFMT) == S_IFDIR) {
616:
617: *pathname++ = '\\';
618:
1.1.1.3 root 619: if (--size <= 0) return ERANGE;
620:
621: for (n = u->name; *n; ) {
1.1 root 622:
623: *pathname++ = *n++;
624:
1.1.1.3 root 625: if (--size <= 0) return ERANGE;
626:
627: }
628:
1.1 root 629: break;
630:
631: }
632:
633: }
634:
635:
636:
637: if (!u) {
638:
639: ALERT("unifs: couldn't match a drive with a directory");
640:
641: return EPTHNF;
642:
643: }
644:
645:
646:
647: if (dir->dev >= NUM_DRIVES) {
648:
649: if ((*fs->root)(dir->dev, &relto) == 0) {
650:
1.1.1.3 root 651: if (!(fs->fsflags & FS_LONGPATH)) {
652:
653: r = (*fs->getname)(&relto, dir, tmppath, PATH_MAX);
654:
655: release_cookie(&relto);
656:
657: if (r) {
658:
659: return r;
660:
661: }
662:
663: if (strlen(tmppath) < size) {
664:
665: strcpy(pathname, tmppath);
666:
667: return 0;
668:
669: } else {
670:
671: return ERANGE;
672:
673: }
674:
675: }
676:
677: r = (*fs->getname)(&relto, dir, pathname, size);
678:
679: release_cookie(&relto);
680:
681: return r;
1.1 root 682:
683: } else {
684:
1.1.1.2 root 685: *pathname = 0;
1.1 root 686:
687: return EINTRN;
688:
689: }
690:
691: }
692:
693:
694:
695: if (curproc->root[dir->dev].fs != fs) {
696:
697: ALERT("unifs: drive's file system doesn't match directory's");
698:
699: return EINTRN;
700:
701: }
702:
703:
704:
1.1.1.3 root 705: if (!(fs->fsflags & FS_LONGPATH)) {
706:
707: r = (*fs->getname)(&curproc->root[dir->dev], dir, tmppath, PATH_MAX);
708:
709: if (r) return r;
710:
711: if (strlen(tmppath) < size) {
712:
713: strcpy(pathname, tmppath);
714:
715: return 0;
716:
717: } else {
718:
719: return ERANGE;
720:
721: }
722:
723: }
724:
725: return (*fs->getname)(&curproc->root[dir->dev], dir, pathname, size);
1.1 root 726:
727: }
728:
729:
730:
1.1.1.2 root 731: static long ARGS_ON_STACK
1.1 root 732:
733: uni_rename(olddir, oldname, newdir, newname)
734:
735: fcookie *olddir;
736:
737: char *oldname;
738:
739: fcookie *newdir;
740:
741: const char *newname;
742:
743: {
744:
1.1.1.2 root 745: UNIFILE *u;
1.1 root 746:
747: fcookie fc;
748:
749: long r;
750:
751:
752:
1.1.1.2 root 753: UNUSED(olddir);
754:
755:
756:
1.1 root 757: for (u = u_root; u; u = u->next) {
758:
759: if (!stricmp(u->name, oldname))
760:
761: break;
762:
763: }
764:
765:
766:
767: if (!u) {
768:
1.1.1.2 root 769: DEBUG(("uni_rename: old file not found"));
1.1 root 770:
771: return EFILNF;
772:
773: }
774:
775:
776:
777: /* the new name is not allowed to exist! */
778:
779: r = uni_lookup(newdir, newname, &fc);
780:
1.1.1.3 root 781: if (r == 0)
782:
783: release_cookie(&fc);
784:
785:
786:
1.1 root 787: if (r != EFILNF) {
788:
1.1.1.2 root 789: DEBUG(("uni_rename: error %ld", r));
1.1 root 790:
791: return (r == 0) ? EACCDN : r;
792:
793: }
794:
795:
796:
797: (void)strncpy(u->name, newname, NAME_MAX);
798:
799: return 0;
800:
801: }
802:
803:
804:
1.1.1.2 root 805: static long ARGS_ON_STACK
1.1 root 806:
807: uni_opendir(dirh, flags)
808:
809: DIR *dirh;
810:
811: int flags;
812:
813: {
814:
1.1.1.2 root 815: UNUSED(flags);
816:
817:
818:
1.1 root 819: if (dirh->fc.index != 0) {
820:
1.1.1.2 root 821: DEBUG(("uni_opendir: bad directory"));
1.1 root 822:
823: return EPTHNF;
824:
825: }
826:
827: dirh->index = 0;
828:
829: return 0;
830:
831: }
832:
833:
834:
835:
836:
1.1.1.2 root 837: static long ARGS_ON_STACK
1.1 root 838:
839: uni_readdir(dirh, name, namelen, fc)
840:
841: DIR *dirh;
842:
843: char *name;
844:
845: int namelen;
846:
847: fcookie *fc;
848:
849: {
850:
851: long map;
852:
853: char *dirname;
854:
855: int i;
856:
857: int giveindex = (dirh->flags == 0);
858:
859: UNIFILE *u;
860:
861: long index;
862:
863: extern long dosdrvs;
864:
865: long r;
866:
867:
868:
869: map = dosdrvs | drvmap() | PSEUDODRVS;
870:
871: i = dirh->index++;
872:
873: u = u_root;
874:
875: while (i > 0) {
876:
877: --i;
878:
879: u = u->next;
880:
881: if (!u)
882:
883: break;
884:
885: }
886:
887: tryagain:
888:
889: if (!u) return ENMFIL;
890:
891:
892:
893: dirname = u->name;
894:
895: index = (long)u;
896:
897: if ( (u->mode & S_IFMT) == S_IFDIR ) {
898:
899: /* make sure the drive really exists */
900:
901: if ( u->dev >= NUM_DRIVES) {
902:
903: r = (*u->fs->root)(u->dev,fc);
904:
905: if (r) {
906:
907: fc->fs = &uni_filesys;
908:
909: fc->index = 0;
910:
911: fc->dev = u->dev;
912:
913: }
914:
915: } else {
916:
917: if ((map & (1L << u->dev)) == 0 ) {
918:
919: dirh->index++;
920:
921: u = u->next;
922:
923: goto tryagain;
924:
925: }
926:
1.1.1.3 root 927: dup_cookie(fc, &curproc->root[u->dev]);
1.1 root 928:
929: if (!fc->fs) { /* drive not yet initialized */
930:
931: /* use default attributes */
932:
933: fc->fs = &uni_filesys;
934:
935: fc->index = 0;
936:
937: fc->dev = u->dev;
938:
939: }
940:
941: }
942:
943: } else { /* a symbolic link */
944:
945: fc->fs = &uni_filesys;
946:
947: fc->dev = UNIDRV;
948:
949: fc->index = (long)u;
950:
951: }
952:
953:
954:
955: if (giveindex) {
956:
1.1.1.2 root 957: namelen -= (int)sizeof(long);
1.1 root 958:
1.1.1.3 root 959: if (namelen <= 0) {
960:
961: release_cookie(fc);
962:
963: return ERANGE;
964:
965: }
1.1 root 966:
967: *((long *)name) = index;
968:
969: name += sizeof(long);
970:
971: }
972:
973: strncpy(name, dirname, namelen-1);
974:
1.1.1.3 root 975: if (strlen(name) < strlen(dirname)) {
976:
977: release_cookie(fc);
1.1 root 978:
979: return ENAMETOOLONG;
980:
1.1.1.3 root 981: }
982:
1.1 root 983: return 0;
984:
985: }
986:
987:
988:
1.1.1.2 root 989: static long ARGS_ON_STACK
1.1 root 990:
991: uni_rewinddir(dirh)
992:
993: DIR *dirh;
994:
995: {
996:
997: dirh->index = 0;
998:
999: return 0;
1000:
1001: }
1002:
1003:
1004:
1.1.1.2 root 1005: static long ARGS_ON_STACK
1.1 root 1006:
1007: uni_closedir(dirh)
1008:
1009: DIR *dirh;
1010:
1011: {
1012:
1.1.1.2 root 1013: UNUSED(dirh);
1014:
1.1 root 1015: return 0;
1016:
1017: }
1018:
1019:
1020:
1.1.1.2 root 1021: static long ARGS_ON_STACK
1.1 root 1022:
1023: uni_pathconf(dir, which)
1024:
1025: fcookie *dir;
1026:
1027: int which;
1028:
1029: {
1030:
1.1.1.2 root 1031: UNUSED(dir);
1032:
1033:
1034:
1.1 root 1035: switch(which) {
1036:
1037: case -1:
1038:
1039: return DP_MAXREQ;
1040:
1041: case DP_IOPEN:
1042:
1043: return 0; /* no files to open */
1044:
1045: case DP_MAXLINKS:
1046:
1047: return 1; /* no hard links available */
1048:
1049: case DP_PATHMAX:
1050:
1051: return PATH_MAX;
1052:
1053: case DP_NAMEMAX:
1054:
1055: return NAME_MAX;
1056:
1057: case DP_ATOMIC:
1058:
1059: return 1; /* no atomic writes */
1060:
1061: case DP_TRUNC:
1062:
1063: return DP_AUTOTRUNC;
1064:
1065: case DP_CASE:
1066:
1067: return DP_CASEINSENS;
1068:
1069: default:
1070:
1071: return EINVFN;
1072:
1073: }
1074:
1075: }
1076:
1077:
1078:
1.1.1.2 root 1079: static long ARGS_ON_STACK
1.1 root 1080:
1081: uni_dfree(dir, buf)
1082:
1083: fcookie *dir;
1084:
1085: long *buf;
1086:
1087: {
1088:
1.1.1.2 root 1089: UNUSED(dir);
1090:
1091:
1092:
1.1 root 1093: buf[0] = 0; /* number of free clusters */
1094:
1095: buf[1] = 0; /* total number of clusters */
1096:
1097: buf[2] = 1; /* sector size (bytes) */
1098:
1099: buf[3] = 1; /* cluster size (sectors) */
1100:
1101: return 0;
1102:
1103: }
1104:
1105:
1106:
1.1.1.2 root 1107: static DEVDRV * ARGS_ON_STACK
1.1 root 1108:
1109: uni_getdev(fc, devsp)
1110:
1111: fcookie *fc;
1112:
1113: long *devsp;
1114:
1115: {
1116:
1.1.1.2 root 1117: UNUSED(fc);
1118:
1119:
1120:
1.1 root 1121: *devsp = EACCDN;
1122:
1123: return 0;
1124:
1125: }
1126:
1127:
1128:
1.1.1.2 root 1129: static long ARGS_ON_STACK
1.1 root 1130:
1131: uni_symlink(dir, name, to)
1132:
1133: fcookie *dir;
1134:
1135: const char *name;
1136:
1137: const char *to;
1138:
1139: {
1140:
1141: UNIFILE *u;
1142:
1143: fcookie fc;
1144:
1145: long r;
1146:
1147:
1148:
1149: r = uni_lookup(dir, name, &fc);
1150:
1.1.1.3 root 1151: if (r == 0) {
1152:
1153: release_cookie(&fc);
1154:
1155: return EACCDN; /* file already exists */
1156:
1157: }
1.1 root 1158:
1159: if (r != EFILNF) return r; /* some other error */
1160:
1161:
1162:
1163: u = kmalloc(SIZEOF(UNIFILE));
1164:
1165: if (!u) return EACCDN;
1166:
1167:
1168:
1169: strncpy(u->name, name, NAME_MAX);
1170:
1171: u->name[NAME_MAX] = 0;
1172:
1173:
1174:
1175: u->data = kmalloc((long)strlen(to)+1);
1176:
1177: if (!u->data) {
1178:
1179: kfree(u);
1180:
1181: return EACCDN;
1182:
1183: }
1184:
1185: strcpy(u->data, to);
1186:
1187: u->mode = S_IFLNK | DEFAULT_DIRMODE;
1188:
1189: u->dev = curproc->ruid;
1190:
1191: u->next = u_root;
1192:
1193: u->fs = &uni_filesys;
1194:
1195: u_root = u;
1196:
1197: return 0;
1198:
1199: }
1200:
1201:
1202:
1.1.1.2 root 1203: static long ARGS_ON_STACK
1.1 root 1204:
1205: uni_readlink(fc, buf, buflen)
1206:
1207: fcookie *fc;
1208:
1209: char *buf;
1210:
1211: int buflen;
1212:
1213: {
1214:
1215: UNIFILE *u;
1216:
1217:
1218:
1219: u = (UNIFILE *)fc->index;
1220:
1221: assert(u);
1222:
1223: assert((u->mode & S_IFMT) == S_IFLNK);
1224:
1225: assert(u->data);
1226:
1227: strncpy(buf, u->data, buflen);
1228:
1229: if (strlen(u->data) >= buflen)
1230:
1231: return ENAMETOOLONG;
1232:
1233: return 0;
1234:
1235: }
1236:
1.1.1.4 ! root 1237:
! 1238:
! 1239:
! 1240:
! 1241:
! 1242:
! 1243:
! 1244:
! 1245: /* uk: use these Dcntl's to install a new filesystem which is only visible
! 1246:
! 1247: * on drive u:
! 1248:
! 1249: *
! 1250:
! 1251: * FS_INSTALL: let the kernel know about the file system; it does NOT
! 1252:
! 1253: * get a device number.
! 1254:
! 1255: * FS_MOUNT: use Dcntl(FS_MOUNT, "u:\\foo", &descr) to make a directory
! 1256:
! 1257: * foo where the filesytem resides in; the file system now
! 1258:
! 1259: * gets its device number which is also written into the
! 1260:
! 1261: * dev_no field of the fs_descr structure.
! 1262:
! 1263: * FS_UNMOUNT: remove a file system's directory; this call closes all
! 1264:
! 1265: * open files, directory searches and directories on this
! 1266:
! 1267: * device. Make sure that the FS will not recognise any
! 1268:
! 1269: * accesses to this device, as fs->root will be called
! 1270:
! 1271: * during the reinitalisation!
! 1272:
! 1273: * FS_UNINSTALL: remove a file system completely from the kernel list,
! 1274:
! 1275: * but that will only be possible if there is no directory
! 1276:
! 1277: * associated with this file system.
! 1278:
! 1279: * This function allows it to write file systems as demons
! 1280:
! 1281: * which stay in memory only as long as needed.
! 1282:
! 1283: *
! 1284:
! 1285: * BUG: it is not possible yet to lock such a filesystem.
! 1286:
! 1287: */
! 1288:
! 1289:
! 1290:
! 1291: /* here we start with gemdos only file system device numbers */
! 1292:
! 1293: static curr_dev_no = 0x100;
! 1294:
! 1295:
! 1296:
! 1297:
! 1298:
! 1299:
! 1300:
! 1301: static long ARGS_ON_STACK
! 1302:
! 1303: uni_fscntl(dir, name, cmd, arg)
! 1304:
! 1305: fcookie *dir;
! 1306:
! 1307: const char *name;
! 1308:
! 1309: int cmd;
! 1310:
! 1311: long arg;
! 1312:
! 1313: {
! 1314:
! 1315: fcookie fc;
! 1316:
! 1317: long r;
! 1318:
! 1319:
! 1320:
! 1321: extern struct kerinfo kernelinfo;
! 1322:
! 1323: extern FILESYS *active_fs;
! 1324:
! 1325:
! 1326:
! 1327: if (cmd == FS_INSTALL) { /* install a new filesystem */
! 1328:
! 1329: struct fs_descr *d = (struct fs_descr*)arg;
! 1330:
! 1331: FILESYS *fs;
! 1332:
! 1333:
! 1334:
! 1335: /* check if FS is installed already */
! 1336:
! 1337: for (fs = active_fs; fs; fs = fs->next)
! 1338:
! 1339: if (d->file_system == fs) return 0L;
! 1340:
! 1341: /* include new file system into chain of file systems */
! 1342:
! 1343: d->file_system->next = active_fs;
! 1344:
! 1345: active_fs = d->file_system;
! 1346:
! 1347: return (long)&kernelinfo; /* return pointer to kernel info as OK */
! 1348:
! 1349: } else if (cmd == FS_MOUNT) { /* install a new gemdos-only device for this FS */
! 1350:
! 1351: struct fs_descr *d = (struct fs_descr*)arg;
! 1352:
! 1353: FILESYS *fs;
! 1354:
! 1355: UNIFILE *u;
! 1356:
! 1357:
! 1358:
! 1359: /* first check for existing names */
! 1360:
! 1361: r = uni_lookup(dir, name, &fc);
! 1362:
! 1363: if (r == 0) {
! 1364:
! 1365: release_cookie(&fc);
! 1366:
! 1367: return EACCDN; /* name exists already */
! 1368:
! 1369: }
! 1370:
! 1371: if (r != EFILNF) return r; /* some other error */
! 1372:
! 1373: if (!d) return EACCDN;
! 1374:
! 1375: if (!d->file_system) return EACCDN;
! 1376:
! 1377: /* check if FS is installed */
! 1378:
! 1379: for (fs = active_fs; fs; fs = fs->next)
! 1380:
! 1381: if (d->file_system == fs) break;
! 1382:
! 1383: if (!fs) return EACCDN; /* not installed, so return an error */
! 1384:
! 1385: u = kmalloc(SIZEOF(UNIFILE));
! 1386:
! 1387: if (!u) return EACCDN;
! 1388:
! 1389: strncpy(u->name, name, NAME_MAX);
! 1390:
! 1391: u->name[NAME_MAX] = 0;
! 1392:
! 1393: u->mode = S_IFDIR|DEFAULT_DIRMODE;
! 1394:
! 1395: u->data = 0;
! 1396:
! 1397: u->fs = d->file_system;
! 1398:
! 1399: /* now get the file system its own device number */
! 1400:
! 1401: u->dev = d->dev_no = curr_dev_no++;
! 1402:
! 1403: /* chain new entry into unifile list */
! 1404:
! 1405: u->next = u_root;
! 1406:
! 1407: u_root = u;
! 1408:
! 1409: return (long)u->dev;
! 1410:
! 1411: } else if (cmd == FS_UNMOUNT) { /* remove a file system's directory */
! 1412:
! 1413: struct fs_descr *d = (struct fs_descr*)arg;
! 1414:
! 1415: FILESYS *fs;
! 1416:
! 1417: UNIFILE *u;
! 1418:
! 1419:
! 1420:
! 1421: /* first check that directory exists */
! 1422:
! 1423: r = uni_lookup(dir, name, &fc);
! 1424:
! 1425: if (r != 0) return EFILNF; /* name does not exist */
! 1426:
! 1427: if (!d) return EFILNF;
! 1428:
! 1429: if (!d->file_system) return EFILNF;
! 1430:
! 1431: if (d->file_system != fc.fs)
! 1432:
! 1433: return EFILNF; /* not the right name! */
! 1434:
! 1435: u = (UNIFILE*)fc.index;
! 1436:
! 1437: release_cookie(&fc);
! 1438:
! 1439: if (!u || (u->fs != d->file_system))
! 1440:
! 1441: return EFILNF;
! 1442:
! 1443: /* check if FS is installed */
! 1444:
! 1445: for (fs = active_fs; fs; fs = fs->next)
! 1446:
! 1447: if (d->file_system == fs) break;
! 1448:
! 1449: if (!fs) return EACCDN; /* not installed, so return an error */
! 1450:
! 1451:
! 1452:
! 1453: /* here comes the difficult part: we have to close all files on that
! 1454:
! 1455: * device, so we have to call changedrv(). The file system driver
! 1456:
! 1457: * has to make sure that further calls to fs.root() with this device
! 1458:
! 1459: * number will fail!
! 1460:
! 1461: *
! 1462:
! 1463: * Kludge: mark the directory as a link, so uni_remove will remove it.
! 1464:
! 1465: */
! 1466:
! 1467: changedrv(u->dev);
! 1468:
! 1469: u->mode &= ~S_IFMT;
! 1470:
! 1471: u->mode |= S_IFLNK;
! 1472:
! 1473: return uni_remove(dir, name);
! 1474:
! 1475: } else if (cmd == FS_UNINSTALL) { /* remove file system from kernel list */
! 1476:
! 1477: struct fs_descr *d = (struct fs_descr*)arg;
! 1478:
! 1479: FILESYS *fs, *last_fs;
! 1480:
! 1481: UNIFILE *u;
! 1482:
! 1483:
! 1484:
! 1485: /* first check if there are any files or directories associated with
! 1486:
! 1487: * this file system
! 1488:
! 1489: */
! 1490:
! 1491: for (u = u_root; u; u = u->next)
! 1492:
! 1493: if (u->fs == d->file_system)
! 1494:
! 1495: return EACCDN; /* we cannot remove it before unmount */
! 1496:
! 1497: last_fs = 0;
! 1498:
! 1499: fs = active_fs;
! 1500:
! 1501: while (fs) { /* go through the list and remove the file system */
! 1502:
! 1503: if (fs == d->file_system) {
! 1504:
! 1505: if (last_fs)
! 1506:
! 1507: last_fs->next = fs->next;
! 1508:
! 1509: else
! 1510:
! 1511: active_fs = fs->next;
! 1512:
! 1513: d->file_system->next = 0;
! 1514:
! 1515: return 0;
! 1516:
! 1517: }
! 1518:
! 1519: last_fs = fs;
! 1520:
! 1521: fs = fs->next;
! 1522:
! 1523: }
! 1524:
! 1525: return EFILNF;
! 1526:
! 1527: } else {
! 1528:
! 1529: /* see if we should just pass this along to another file system */
! 1530:
! 1531: r = uni_lookup(dir, name, &fc);
! 1532:
! 1533: if (r == 0) {
! 1534:
! 1535: if (fc.fs != &uni_filesys) {
! 1536:
! 1537: r = (*fc.fs->fscntl)(&fc, ".", cmd, arg);
! 1538:
! 1539: release_cookie(&fc);
! 1540:
! 1541: return r;
! 1542:
! 1543: }
! 1544:
! 1545: release_cookie(&fc);
! 1546:
! 1547: }
! 1548:
! 1549: }
! 1550:
! 1551: return EINVFN;
! 1552:
! 1553: }
! 1554:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.