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