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