|
|
1.1 root 1: /*
2:
3: Copyright 1991,1992 Eric R. Smith. All rights reserved.
4:
5: */
6:
7:
8:
9: /* a simple unified file system */
10:
11:
12:
13: #include "mint.h"
14:
15:
16:
17:
18:
19: extern FILESYS bios_filesys, proc_filesys, pipe_filesys, shm_filesys;
20:
21:
22:
23: static long uni_root P_((int drv, fcookie *fc));
24:
25: static long uni_lookup P_((fcookie *dir, const char *name, fcookie *fc));
26:
27: static long uni_getxattr P_((fcookie *fc, XATTR *xattr));
28:
29: static long uni_chattr P_((fcookie *fc, int attrib));
30:
31: static long uni_chown P_((fcookie *fc, int uid, int gid));
32:
33: static long uni_chmode P_((fcookie *fc, unsigned mode));
34:
35: static long uni_rmdir P_((fcookie *dir, const char *name));
36:
37: static long uni_remove P_((fcookie *dir, const char *name));
38:
39: static long uni_getname P_((fcookie *root, fcookie *dir, char *pathname));
40:
41: static long uni_rename P_((fcookie *olddir, char *oldname,
42:
43: fcookie *newdir, const char *newname));
44:
45: static long uni_opendir P_((DIR *dirh, int flags));
46:
47: static long uni_readdir P_((DIR *dirh, char *nm, int nmlen, fcookie *));
48:
49: static long uni_rewinddir P_((DIR *dirh));
50:
51: static long uni_closedir P_((DIR *dirh));
52:
53: static long uni_pathconf P_((fcookie *dir, int which));
54:
55: static long uni_dfree P_((fcookie *dir, long *buf));
56:
57: static DEVDRV * uni_getdev P_((fcookie *fc, long *devsp));
58:
59: static long uni_symlink P_((fcookie *dir, const char *name, const char *to));
60:
61: static long uni_readlink P_((fcookie *fc, char *buf, int buflen));
62:
63:
64:
65: FILESYS uni_filesys = {
66:
67: (FILESYS *)0,
68:
69: 0,
70:
71: uni_root,
72:
73: uni_lookup, nocreat, uni_getdev, uni_getxattr,
74:
75: uni_chattr, uni_chown, uni_chmode,
76:
77: nomkdir, uni_rmdir, uni_remove, uni_getname, uni_rename,
78:
79: uni_opendir, uni_readdir, uni_rewinddir, uni_closedir,
80:
81: uni_pathconf, uni_dfree, nowritelabel, noreadlabel,
82:
83: uni_symlink, uni_readlink, nohardlink, nofscntl, nodskchng
84:
85: };
86:
87:
88:
89: /*
90:
91: * structure that holds files
92:
93: * if (mode & S_IFMT == S_IFDIR), then this is an alias for a drive:
94:
95: * "dev" holds the appropriate BIOS device number, and
96:
97: * "data" is meaningless
98:
99: * if (mode & S_IFMT == S_IFLNK), then this is a symbolic link:
100:
101: * "dev" holds the user id of the owner, and
102:
103: * "data" points to the actual link data
104:
105: */
106:
107:
108:
109: typedef struct unifile {
110:
111: char name[NAME_MAX+1];
112:
113: short mode;
114:
115: ushort dev;
116:
117: FILESYS *fs;
118:
119: void *data;
120:
121: struct unifile *next;
122:
123: } UNIFILE;
124:
125:
126:
127: /* the "+1" is for shared memory, which has no BIOS drive */
128:
129: #define UNI_DIRS NUM_DRIVES+1
130:
131: static UNIFILE u_drvs[UNI_DIRS];
132:
133: static UNIFILE *u_root = 0;
134:
135:
136:
137: void
138:
139: unifs_init()
140:
141: {
142:
143: UNIFILE *u = u_drvs;
144:
145: int i;
146:
147:
148:
149: u_root = u;
150:
151: for (i = 0; i < NUM_DRIVES; i++,u++) {
152:
153: u->next = u+1;
154:
155: u->mode = S_IFDIR|DEFAULT_DIRMODE;
156:
157: u->dev = i;
158:
159: u->fs = 0;
160:
161: if (i == PROCDRV)
162:
163: strcpy(u->name, "proc");
164:
165: else if (i == PIPEDRV)
166:
167: strcpy(u->name, "pipe");
168:
169: else if (i == BIOSDRV)
170:
171: strcpy(u->name, "dev");
172:
173: else if (i == UNIDRV) {
174:
175: (u-1)->next = u->next; /* skip this drive */
176:
177: } else {
178:
179: u->name[0] = i + 'a';
180:
181: u->name[1] = 0;
182:
183: }
184:
185: }
186:
187: u->next = 0;
188:
189: u->mode = S_IFDIR|DEFAULT_DIRMODE;
190:
191: u->dev = SHMDEVICE;
192:
193: u->fs = &shm_filesys;
194:
195: strcpy(u->name, "shm");
196:
197: }
198:
199:
200:
201: static long
202:
203: uni_root(drv, fc)
204:
205: int drv;
206:
207: fcookie *fc;
208:
209: {
210:
211: if (drv == UNIDRV) {
212:
213: fc->fs = &uni_filesys;
214:
215: fc->dev = drv;
216:
217: fc->index = 0L;
218:
219: return 0;
220:
221: }
222:
223: fc->fs = 0;
224:
225: return EINTRN;
226:
227: }
228:
229:
230:
231: static long
232:
233: uni_lookup(dir, name, fc)
234:
235: fcookie *dir;
236:
237: const char *name;
238:
239: fcookie *fc;
240:
241: {
242:
243: UNIFILE *u;
244:
245: long drvs;
246:
247: FILESYS *fs;
248:
249: extern long dosdrvs;
250:
251:
252:
253: TRACE("uni_lookup(%s)", name);
254:
255:
256:
257: if (dir->index != 0) {
258:
259: DEBUG("uni_lookup: bad directory");
260:
261: return EPTHNF;
262:
263: }
264:
265: /* special case: an empty name in a directory means that directory */
266:
267: /* so do "." and ".." */
268:
269:
270:
271: if (!*name || !strcmp(name, ".") || !strcmp(name, "..")) {
272:
273: *fc = *dir;
274:
275: return 0;
276:
277: }
278:
279: drvs = drvmap() | dosdrvs | PSEUDODRVS;
280:
281: /*
282:
283: * OK, check the list of aliases and special directories
284:
285: */
286:
287: for (u = u_root; u; u = u->next) {
288:
289: if (!stricmp(name, u->name)) {
290:
291: if ( (u->mode & S_IFMT) == S_IFDIR ) {
292:
293: if (u->dev >= NUM_DRIVES) {
294:
295: fs = u->fs;
296:
297: return (*fs->root)(u->dev,fc);
298:
299: }
300:
301: if ((drvs & (1L << u->dev)) == 0)
302:
303: return EPTHNF;
304:
305: *fc = curproc->root[u->dev];
306:
307: if (!fc->fs) { /* drive changed? */
308:
309: changedrv(fc->dev);
310:
311: *fc = curproc->root[u->dev];
312:
313: if (!fc->fs)
314:
315: return EPTHNF;
316:
317: }
318:
319: } else { /* a symbolic link */
320:
321: fc->fs = &uni_filesys;
322:
323: fc->dev = UNIDRV;
324:
325: fc->index = (long)u;
326:
327: }
328:
329: return 0;
330:
331: }
332:
333: }
334:
335: DEBUG("uni_lookup: name (%s) not found", name);
336:
337: return EFILNF;
338:
339: }
340:
341:
342:
343: static long
344:
345: uni_getxattr(fc, xattr)
346:
347: fcookie *fc;
348:
349: XATTR *xattr;
350:
351: {
352:
353: UNIFILE *u = (UNIFILE *)fc->index;
354:
355:
356:
357: if (fc->fs != &uni_filesys) {
358:
359: ALERT("ERROR: wrong file system getxattr called");
360:
361: return EINTRN;
362:
363: }
364:
365:
366:
367: xattr->index = fc->index;
368:
369: xattr->dev = fc->dev;
370:
371: xattr->nlink = 1;
372:
373: xattr->blksize = 1;
374:
375:
376:
377: /* If "u" is null, then we have the root directory, otherwise
378:
379: * we use the UNIFILE structure to get the info about it
380:
381: */
382:
383: if (!u || ( (u->mode & S_IFMT) == S_IFDIR )) {
384:
385: xattr->uid = xattr->gid = 0;
386:
387: xattr->size = xattr->nblocks = 0;
388:
389: xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
390:
391: xattr->attr = FA_DIR;
392:
393: } else {
394:
395: xattr->uid = u->dev;
396:
397: xattr->gid = 0;
398:
399: xattr->size = xattr->nblocks = strlen(u->data) + 1;
400:
401: xattr->mode = u->mode;
402:
403: xattr->attr = 0;
404:
405: }
406:
407: xattr->mtime = xattr->atime = xattr->ctime = 0;
408:
409: xattr->mdate = xattr->adate = xattr->cdate = 0;
410:
411: return 0;
412:
413: }
414:
415:
416:
417: static long
418:
419: uni_chattr(dir, attrib)
420:
421: fcookie *dir;
422:
423: int attrib;
424:
425: {
426:
427: return EACCDN;
428:
429: }
430:
431:
432:
433: static long
434:
435: uni_chown(dir, uid, gid)
436:
437: fcookie *dir;
438:
439: int uid, gid;
440:
441: {
442:
443: return EINVFN;
444:
445: }
446:
447:
448:
449: static long
450:
451: uni_chmode(dir, mode)
452:
453: fcookie *dir;
454:
455: unsigned mode;
456:
457: {
458:
459: return EINVFN;
460:
461: }
462:
463:
464:
465: static long
466:
467: uni_rmdir(dir, name)
468:
469: fcookie *dir;
470:
471: const char *name;
472:
473: {
474:
475: long r;
476:
477:
478:
479: r = uni_remove(dir, name);
480:
481: if (r == EFILNF) r = EPTHNF;
482:
483: return r;
484:
485: }
486:
487:
488:
489: static long
490:
491: uni_remove(dir, name)
492:
493: fcookie *dir;
494:
495: const char *name;
496:
497: {
498:
499: UNIFILE *u, *lastu;
500:
501:
502:
503: lastu = 0;
504:
505: u = u_root;
506:
507: while (u) {
508:
509: if (!strncmp(u->name, name, NAME_MAX)) {
510:
511: if ( (u->mode & S_IFMT) != S_IFLNK ) return EFILNF;
512:
513: kfree(u->data);
514:
515: if (lastu)
516:
517: lastu->next = u->next;
518:
519: else
520:
521: u_root = u->next;
522:
523: kfree(u);
524:
525: return 0;
526:
527: }
528:
529: lastu = u;
530:
531: u = u->next;
532:
533: }
534:
535: return EFILNF;
536:
537: }
538:
539:
540:
541: static long
542:
543: uni_getname(root, dir, pathname)
544:
545: fcookie *root, *dir; char *pathname;
546:
547: {
548:
549: FILESYS *fs;
550:
551: UNIFILE *u;
552:
553: char *n;
554:
555: fcookie relto;
556:
557:
558:
559: fs = dir->fs;
560:
561: if (dir->dev == UNIDRV) {
562:
563: *pathname = 0;
564:
565: return 0;
566:
567: }
568:
569:
570:
571: for (u = u_root; u; u = u->next) {
572:
573: if (dir->dev == u->dev && (u->mode & S_IFMT) == S_IFDIR) {
574:
575: *pathname++ = '\\';
576:
577: for (n = u->name; *n; )
578:
579: *pathname++ = *n++;
580:
581: break;
582:
583: }
584:
585: }
586:
587:
588:
589: if (!u) {
590:
591: ALERT("unifs: couldn't match a drive with a directory");
592:
593: return EPTHNF;
594:
595: }
596:
597:
598:
599: if (dir->dev >= NUM_DRIVES) {
600:
601: if ((*fs->root)(dir->dev, &relto) == 0) {
602:
603: return (*fs->getname)(&relto, dir, pathname);
604:
605: } else {
606:
607: *pathname++ = 0;
608:
609: return EINTRN;
610:
611: }
612:
613: }
614:
615:
616:
617: if (curproc->root[dir->dev].fs != fs) {
618:
619: ALERT("unifs: drive's file system doesn't match directory's");
620:
621: return EINTRN;
622:
623: }
624:
625:
626:
627: return (*fs->getname)(&curproc->root[dir->dev], dir, pathname);
628:
629: }
630:
631:
632:
633: static long
634:
635: uni_rename(olddir, oldname, newdir, newname)
636:
637: fcookie *olddir;
638:
639: char *oldname;
640:
641: fcookie *newdir;
642:
643: const char *newname;
644:
645: {
646:
647: UNIFILE *u = 0;
648:
649: fcookie fc;
650:
651: long r;
652:
653:
654:
655: for (u = u_root; u; u = u->next) {
656:
657: if (!stricmp(u->name, oldname))
658:
659: break;
660:
661: }
662:
663:
664:
665: if (!u) {
666:
667: DEBUG("uni_rename: old file not found");
668:
669: return EFILNF;
670:
671: }
672:
673:
674:
675: /* the new name is not allowed to exist! */
676:
677: r = uni_lookup(newdir, newname, &fc);
678:
679: if (r != EFILNF) {
680:
681: DEBUG("uni_rename: error %ld", r);
682:
683: return (r == 0) ? EACCDN : r;
684:
685: }
686:
687:
688:
689: (void)strncpy(u->name, newname, NAME_MAX);
690:
691: return 0;
692:
693: }
694:
695:
696:
697: static long
698:
699: uni_opendir(dirh, flags)
700:
701: DIR *dirh;
702:
703: int flags;
704:
705: {
706:
707: if (dirh->fc.index != 0) {
708:
709: DEBUG("uni_opendir: bad directory");
710:
711: return EPTHNF;
712:
713: }
714:
715: dirh->index = 0;
716:
717: return 0;
718:
719: }
720:
721:
722:
723:
724:
725: static long
726:
727: uni_readdir(dirh, name, namelen, fc)
728:
729: DIR *dirh;
730:
731: char *name;
732:
733: int namelen;
734:
735: fcookie *fc;
736:
737: {
738:
739: long map;
740:
741: char *dirname;
742:
743: int i;
744:
745: int giveindex = (dirh->flags == 0);
746:
747: UNIFILE *u;
748:
749: long index;
750:
751: extern long dosdrvs;
752:
753: long r;
754:
755:
756:
757: map = dosdrvs | drvmap() | PSEUDODRVS;
758:
759: i = dirh->index++;
760:
761: u = u_root;
762:
763: while (i > 0) {
764:
765: --i;
766:
767: u = u->next;
768:
769: if (!u)
770:
771: break;
772:
773: }
774:
775: tryagain:
776:
777: if (!u) return ENMFIL;
778:
779:
780:
781: dirname = u->name;
782:
783: index = (long)u;
784:
785: if ( (u->mode & S_IFMT) == S_IFDIR ) {
786:
787: /* make sure the drive really exists */
788:
789: if ( u->dev >= NUM_DRIVES) {
790:
791: r = (*u->fs->root)(u->dev,fc);
792:
793: if (r) {
794:
795: fc->fs = &uni_filesys;
796:
797: fc->index = 0;
798:
799: fc->dev = u->dev;
800:
801: }
802:
803: } else {
804:
805: if ((map & (1L << u->dev)) == 0 ) {
806:
807: dirh->index++;
808:
809: u = u->next;
810:
811: goto tryagain;
812:
813: }
814:
815: *fc = curproc->root[u->dev];
816:
817: if (!fc->fs) { /* drive not yet initialized */
818:
819: /* use default attributes */
820:
821: fc->fs = &uni_filesys;
822:
823: fc->index = 0;
824:
825: fc->dev = u->dev;
826:
827: }
828:
829: }
830:
831: } else { /* a symbolic link */
832:
833: fc->fs = &uni_filesys;
834:
835: fc->dev = UNIDRV;
836:
837: fc->index = (long)u;
838:
839: }
840:
841:
842:
843: if (giveindex) {
844:
845: namelen -= sizeof(long);
846:
847: if (namelen <= 0) return ERANGE;
848:
849: *((long *)name) = index;
850:
851: name += sizeof(long);
852:
853: }
854:
855: strncpy(name, dirname, namelen-1);
856:
857: if (strlen(name) < strlen(dirname))
858:
859: return ENAMETOOLONG;
860:
861: return 0;
862:
863: }
864:
865:
866:
867: static long
868:
869: uni_rewinddir(dirh)
870:
871: DIR *dirh;
872:
873: {
874:
875: dirh->index = 0;
876:
877: return 0;
878:
879: }
880:
881:
882:
883: static long
884:
885: uni_closedir(dirh)
886:
887: DIR *dirh;
888:
889: {
890:
891: return 0;
892:
893: }
894:
895:
896:
897: static long
898:
899: uni_pathconf(dir, which)
900:
901: fcookie *dir;
902:
903: int which;
904:
905: {
906:
907: switch(which) {
908:
909: case -1:
910:
911: return DP_MAXREQ;
912:
913: case DP_IOPEN:
914:
915: return 0; /* no files to open */
916:
917: case DP_MAXLINKS:
918:
919: return 1; /* no hard links available */
920:
921: case DP_PATHMAX:
922:
923: return PATH_MAX;
924:
925: case DP_NAMEMAX:
926:
927: return NAME_MAX;
928:
929: case DP_ATOMIC:
930:
931: return 1; /* no atomic writes */
932:
933: case DP_TRUNC:
934:
935: return DP_AUTOTRUNC;
936:
937: case DP_CASE:
938:
939: return DP_CASEINSENS;
940:
941: default:
942:
943: return EINVFN;
944:
945: }
946:
947: }
948:
949:
950:
951: static long
952:
953: uni_dfree(dir, buf)
954:
955: fcookie *dir;
956:
957: long *buf;
958:
959: {
960:
961: buf[0] = 0; /* number of free clusters */
962:
963: buf[1] = 0; /* total number of clusters */
964:
965: buf[2] = 1; /* sector size (bytes) */
966:
967: buf[3] = 1; /* cluster size (sectors) */
968:
969: return 0;
970:
971: }
972:
973:
974:
975: static DEVDRV *
976:
977: uni_getdev(fc, devsp)
978:
979: fcookie *fc;
980:
981: long *devsp;
982:
983: {
984:
985: *devsp = EACCDN;
986:
987: return 0;
988:
989: }
990:
991:
992:
993: static long
994:
995: uni_symlink(dir, name, to)
996:
997: fcookie *dir;
998:
999: const char *name;
1000:
1001: const char *to;
1002:
1003: {
1004:
1005: UNIFILE *u;
1006:
1007: fcookie fc;
1008:
1009: long r;
1010:
1011:
1012:
1013: r = uni_lookup(dir, name, &fc);
1014:
1015: if (r == 0) return EACCDN; /* file already exists */
1016:
1017: if (r != EFILNF) return r; /* some other error */
1018:
1019:
1020:
1021: u = kmalloc(SIZEOF(UNIFILE));
1022:
1023: if (!u) return EACCDN;
1024:
1025:
1026:
1027: strncpy(u->name, name, NAME_MAX);
1028:
1029: u->name[NAME_MAX] = 0;
1030:
1031:
1032:
1033: u->data = kmalloc((long)strlen(to)+1);
1034:
1035: if (!u->data) {
1036:
1037: kfree(u);
1038:
1039: return EACCDN;
1040:
1041: }
1042:
1043: strcpy(u->data, to);
1044:
1045: u->mode = S_IFLNK | DEFAULT_DIRMODE;
1046:
1047: u->dev = curproc->ruid;
1048:
1049: u->next = u_root;
1050:
1051: u->fs = &uni_filesys;
1052:
1053: u_root = u;
1054:
1055: return 0;
1056:
1057: }
1058:
1059:
1060:
1061: static long
1062:
1063: uni_readlink(fc, buf, buflen)
1064:
1065: fcookie *fc;
1066:
1067: char *buf;
1068:
1069: int buflen;
1070:
1071: {
1072:
1073: UNIFILE *u;
1074:
1075:
1076:
1077: u = (UNIFILE *)fc->index;
1078:
1079: assert(u);
1080:
1081: assert((u->mode & S_IFMT) == S_IFLNK);
1082:
1083: assert(u->data);
1084:
1085: strncpy(buf, u->data, buflen);
1086:
1087: if (strlen(u->data) >= buflen)
1088:
1089: return ENAMETOOLONG;
1090:
1091: return 0;
1092:
1093: }
1094:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.