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