|
|
1.1 root 1: MiNT File Systems
2:
3:
4:
5: MiNT allows loadable file systems, which means that it should be quite
6:
7: easy to implement networked file systems, dynamically re-sizable ram
8:
9: disks, or other nifty things (for example, Stephen Henson's minix.xfs
10:
11: file system allows access to Minix partitions from TOS). Writing
12:
13: these is not difficult, but there are a lot of data structures that
14:
15: must be understood first. (These data structures are given in the
16:
17: file "filesys.h".)
18:
19:
20:
21: A note on conventions: a declaration like:
22:
23: short foo P_((char *bar, long baz));
24:
25: means that "foo" is a function that returns a 16 bit integer, and that
26:
27: expects a pointer to a character and a 32 bit integer as its two
28:
29: arguments. "ushort" is an unsigned 16 bit integer; "ulong" is an
30:
31: unsigned 32 bit integer.
32:
33:
34:
35: File Cookies
36:
37:
38:
39: Files and directories are represented in the kernel by "cookies".
40:
41: The contents of the cookie are mostly file system dependent, i.e. the
42:
43: kernel interprets only the "fs" and "dev" field of the cookie, and the
44:
45: contents of the other fields may be used by a file system as it sees fit.
46:
47:
48:
49: A file cookie has the following structure:
50:
51:
52:
53: typedef struct f_cookie {
54:
55: FILESYS *fs; /* file system that knows about this cookie */
56:
57: ushort dev; /* device info (e.g. Rwabs device number) */
58:
59: ushort aux; /* extra data that the file system may want */
60:
61: long index; /* this+dev uniquely identifies a file */
62:
63: } fcookie;
64:
65:
66:
67: (The "FILESYS" data type is defined below.)
68:
69: The interpretation of the "aux" field is entirely file system dependent. The
70:
71: "index" field is not presently used by the kernel, but file systems
72:
73: should (if possible) make this field uniquely identify a file or directory
74:
75: on a device.
76:
77:
78:
79: File System Structure
80:
81:
82:
83: This is the structure that tells the kernel about the file system,
84:
85: and gives the entry points for routines which the kernel can call in order
86:
87: to manipulate files and directories. Note that actual input/output
88:
89: operations are performed by a device driver; most file systems have just
90:
91: one associated device driver, but some may have more. See the section on
92:
93: device drivers for more information on these.
94:
95:
96:
97: Unless otherwise specified, all of the functions should return 0 for
98:
99: success and an appropriate (long negative) error code for failure. Also,
100:
101: note that it is the kernel's responsibility to do all access checking;
102:
103: the file system may assume that the file's permissions have been checked
104:
105: and are compatible with the current process' uid and the operation
106:
107: selected.
108:
109:
110:
111: Parameters are passed to file system driver functions on the stack.
112:
113: The file system drivers should preserve registers d2-d7 and a2-a7,
114:
115: and return any results in register d0. Note that this may differ from
116:
117: your compiler's default conventions (for example, Alcyon C preserves
118:
119: only registers d3-d7 and a3-a7); in this case, an assembly language
120:
121: wrapper will be necessary.
122:
123:
124:
125: typedef struct filesys {
126:
127: struct filesys *next;
128:
129:
130:
131: This is a link to the next file system in the kernel's list. It will be
132:
133: filled in by the kernel; the file system should leave it as NULL.
134:
135:
136:
137: long fsflags;
138:
139: These flags give some information about the file system. Currently, three
140:
141: flags are defined:
142:
143:
144:
145: #define FS_KNOPARSE 0x01 /* kernel shouldn't do parsing */
146:
147: #define FS_CASESENSITIVE 0x02 /* file names are case sensitive */
148:
149: #define FS_NOXBIT 0x04 /* if a file can be read, it can be executed */
150:
151:
152:
153: Other bits may be defined in future releases of MiNT; for now all other
154:
155: bits in this flag should be 0. Most file systems will have only the
156:
157: FS_NOXBIT flag; networked file systems may have FS_KNOPARSE for
158:
159: reasons of efficiency, and file systems that must be compatible with Unix
160:
161: or similar specifications may be case sensitive and hence have FS_CASESENSITIVE
162:
163: set.
164:
165:
166:
167: long (*root) P_((short drv, fcookie *fc));
168:
169: This is the entry point for a routine to find a file cookie for the root
170:
171: directory of BIOS device "drv" (an integer in the range 0-31 inclusive).
172:
173: This function is called by the kernel when initializing a drive; the kernel
174:
175: will query each file system in turn for a file cookie representing the
176:
177: root directory of the drive. If the file system recognizes the data on
178:
179: the drive as being valid for a file system that it recognizes, it should
180:
181: fill in the cookie pointed to by "fc" and return 0. Otherwise, it should
182:
183: return a negative error code (EDRIVE is a good choice) to indicate that the
184:
185: drive must belong to another file system. Note that this function is called
186:
187: at boot up time and also at any time when media change is detected on a drive.
188:
189:
190:
191: long (*lookup) P_((fcookie *dir, char *name, fcookie *fc));
192:
193: Translate a file name into a cookie. "dir" is the cookie for a directory,
194:
195: returned by a previous call to (*lookup) or (*root). "name" is either the
196:
197: name of a file in that directory (if fsflags & FS_KNOPARSE == 0) or a path
198:
199: name relative to that directory (if fsflags & FS_KNOPARSE == FS_KNOPARSE).
200:
201: If the file is not found, an appropriate error code (like EFILNF) should be
202:
203: returned. If the file is found, the cookie "*fc" should be filled in with
204:
205: appropriate data, and either 0 or EMOUNT returned. EMOUNT should be returned
206:
207: only if "name" is ".." and "dir" represents the root directory of a drive;
208:
209: 0 should be returned otherwise. Note that a lookup call with a null name
210:
211: or with "." should always succeed and return a cookie representing the
212:
213: directory itself. Also note that symbolic links should *never* be followed.
214:
215:
216:
217: long (*creat) P_((fcookie *dir, char *name, ushort mode,
218:
219: short attrib, fcookie *fc)
220:
221: Create a new file named "name" in the directory whose cookie is "dir".
222:
223: "mode" gives the file's type and access permissions, as follows:
224:
225: /* file types */
226:
227: #define S_IFMT 0170000 /* mask to select file type */
228:
229: #define S_IFCHR 0020000 /* BIOS special file */
230:
231: #define S_IFDIR 0040000 /* directory file */
232:
233: #define S_IFREG 0100000 /* regular file */
234:
235: #define S_IFIFO 0120000 /* FIFO */
236:
237: #define S_IMEM 0140000 /* memory region or process */
238:
239: #define S_IFLNK 0160000 /* symbolic link */
240:
241:
242:
243: /* special bits: setuid, setgid, sticky bit */
244:
245: #define S_ISUID 04000 /* change euid when executing this file */
246:
247: #define S_ISGID 02000 /* change egid when executing this file */
248:
249: #define S_ISVTX 01000 /* not implemented */
250:
251:
252:
253: /* file access modes for user, group, and other*/
254:
255: #define S_IRUSR 0400 /* read access for user */
256:
257: #define S_IWUSR 0200 /* write access for user */
258:
259: #define S_IXUSR 0100 /* execute access for user */
260:
261: #define S_IRGRP 0040 /* ditto for group... */
262:
263: #define S_IWGRP 0020
264:
265: #define S_IXGRP 0010
266:
267: #define S_IROTH 0004 /* ditto for everyone else */
268:
269: #define S_IWOTH 0002
270:
271: #define S_IXOTH 0001
272:
273:
274:
275: "attrib" gives the standard TOS attribute byte. This is slightly redundant
276:
277: with "mode" (i.e. the FA_RDONLY bit should agree with the settings of
278:
279: S_IWUSR, S_IWGRP, and S_IWOTH, and FA_DIR should be set if and only if
280:
281: the file's format is S_IFDIR) but is provided for convenience for standard
282:
283: DOS compatible file systems.
284:
285:
286:
287: The kernel will make the "creat" call only after using "lookup" in an attempt
288:
289: to find the file. The file system should create the file (if possible) and
290:
291: set the cookie pointed to by "fc" to represent the newly created file.
292:
293: If an error of any sort occurs, an appropriate error number is returned,
294:
295: otherwise 0 is returned. Also note that the kernel will not try to
296:
297: create directories this way; it will use "mkdir" (q.v.) instead.
298:
299:
300:
301: DEVDRV *(*getdev) P_((fcookie *fc, long *devspecial))
302:
303: Get the device driver which should be used to do i/o on the file whose
304:
305: cookie is "fc". If an error occurs, a NULL pointer should be returned
306:
307: and an error code placed in the long pointed to by "devspecial"; otherwise,
308:
309: "devspecial" should be set to a device-driver specific value which will
310:
311: be placed by the kernel in the "devinfo" field of the FILEPTR structure
312:
313: passed to the device driver's open routine. (The interpretation of
314:
315: this value is a matter for the file system and the device driver, the
316:
317: kernel doesn't care.)
318:
319:
320:
321: If the call to (*getdev) succeeds, a pointer to a device driver structure
322:
323: (see below) is returned; if it fails, a NULL pointer should be returned and
324:
325: an appropriate error number placed in *devspecial.
326:
327:
328:
329: long (*getxattr) P_((fcookie *file, XATTR *xattr));
330:
331: Get a file's attributes. The XATTR structure pointed to by "xattr" should
332:
333: be filled in with the data for the file or directory represented by
334:
335: the cookie "*file", and 0 returned. If a fatal error occurs (e.g. media
336:
337: change) an error code is returned instead. The XATTR structure is defined
338:
339: as follows:
340:
341:
342:
343: /* structure for getxattr */
344:
345: typedef struct xattr {
346:
347: ushort mode;
348:
349: file types and permissions; same as the mode passed to (*creat) (see above)
350:
351: long index;
352:
353: file index; this should if possible be a unique number for the file, so that
354:
355: no two files on the same physical drive could have the same index. It is
356:
357: not mandatory that this match the "index" field of the fcookie structure
358:
359: for the file.
360:
361: ushort dev;
362:
363: physical device on which the file is located; normally set to file->dev
364:
365: ushort reserved1;
366:
367: set to 0
368:
369: ushort nlink;
370:
371: number of hard links to the file; normally 1
372:
373: ushort uid;
374:
375: a number representing the user that owns the file
376:
377: ushort gid;
378:
379: the group ownership of the file
380:
381: long size;
382:
383: length of the file, in bytes
384:
385: short mtime, mdate;
386:
387: last modification time and date of the file, in standard GEMDOS format
388:
389: short atime, adate;
390:
391: last access time and date for the file, in standard GEMDOS format; if the
392:
393: file system does not keep separate record of these, they should be the same
394:
395: as mtime and mdate
396:
397: short ctime, cdate;
398:
399: file creation time and date, in standard GEMDOS format; if the file system
400:
401: does not keep separate record of these, they should be the same as mtime
402:
403: and mdate
404:
405: short attr;
406:
407: TOS attribute byte for the file in the lower 8 bits; the upper 8 should
408:
409: be 0
410:
411: short reserved2;
412:
413: reserved, set to 0
414:
415: long reserved3[2];
416:
417: reserved, set both long words to 0
418:
419: } XATTR;
420:
421:
422:
423: long (*chattr) P_((fcookie *file, short attr));
424:
425: Change the TOS attributes of the file whose cookie is "*file" to "attr".
426:
427: Only the lower 8 bits of "attr" should be considered significant, for now.
428:
429: The kernel will not allow changes if the file's current attributes include
430:
431: the FA_DIR bit or the FA_LABEL bit. Not all filesystems will support all
432:
433: TOS attribute bits, but FA_RDONLY should probably be supported if possible;
434:
435: usually setting the FA_RDONLY bit should be equivalent to turning off all
436:
437: write permissions to the file.
438:
439:
440:
441: long (*chown) P_((fcookie *file, short uid, short gid));
442:
443: Change a file's user and group ownership to "uid" and "gid" respectively.
444:
445: The kernel checks access permissions before making this call, so file
446:
447: systems do not have to. If the file system does not support a concept
448:
449: of ownership, or does not allow changes to ownership, it should return
450:
451: EINVFN.
452:
453:
454:
455: long (*chmode) P_((fcookie *file, ushort mode));
456:
457: Change a file's access permissions. "mode" is similar to the field in
458:
459: the XATTR structure or the value passed to creat, except that _only_
460:
461: the permission bits are significant; (mode & S_IFMT) will always be 0.
462:
463: In the event that the file system supports only a subset of permissions
464:
465: (e.g. the TOS file system can only control write access to the file)
466:
467: then it may consider only the relevant bits of "mode".
468:
469:
470:
471: long (*mkdir) P_((fcookie *dir, char *name, ushort mode));
472:
473: Make a new subdirectory called "name" of the directory whose cookie is
474:
475: "*dir". The new directory should have the file permissions given by
476:
477: "mode & ~S_IFMT". Note that the file system should do all appropriate
478:
479: initializations for the new directory, including making entries for
480:
481: "." and "..". Note also that the kernel verifies that "mode & S_IFMT"
482:
483: is S_IFDIR before making this call.
484:
485:
486:
487: long (*rmdir) P_((fcookie *dir, char *name));
488:
489: Delete the subdirectory called "name" of the directory whose cookie is
490:
491: "*dir". It is also a good idea to allow removal of symbolic links via
492:
493: this call, since a symbolic link to a directory looks like a directory
494:
495: to a normal TOS program.
496:
497:
498:
499: long (*remove) P_((fcookie *dir, char *name));
500:
501: Delete the file called "name" in the directory "*dir". This function should
502:
503: act like the Unix "unlink" call, i.e. if the file has more than 1 hard
504:
505: link to it, only this particular link to the file should be removed and
506:
507: the file contents should not be affected. Directories should not be removed
508:
509: by this function. Symbolic links definitely should be removed by this
510:
511: function; whether other types of special files are removed by this function
512:
513: is up to the file system.
514:
515:
516:
517: long (*getname) P_((fcookie *relto, fcookie *dir, char *pathname));
518:
519: This is analogous to the "getcwd()" operation in Unix. It should get the name
520:
521: of the directory whose cookie is "*dir", expressed as a path relative
522:
523: to the directory whose cookie is "*relto"; normally, this is the root
524:
525: directory, but the file system should not assume this. The resulting path
526:
527: is placed in the array pointed to by *pathname, which is PATH_MAX bytes
528:
529: long. If *relto and *dir are the same directory, then an empty string
530:
531: should be placed in *pathname.
532:
533:
534:
535: Example: if "*relto" is the directory "\FOO", and "*dir" is the directory
536:
537: "\FOO\BAR\SUB", then after the call "pathname" should contain "\BAR\SUB".
538:
539:
540:
541: long (*rename) P_((fcookie *olddir, char *oldname,
542:
543: fcookie *newdir, char *newname));
544:
545: Rename the file with name "oldname" contained in the directory whose cookie
546:
547: is "*olddir" to the name "newname" in the directory whose cookie is "*newdir".
548:
549: The file system need not actually support cross-directory renames, or
550:
551: indeed any sort of renames at all; if no renames at all are supported, EINVFN
552:
553: should be returned.
554:
555:
556:
557: long (*opendir) P_((DIR *dirh, short tosflag));
558:
559: Open a directory for reading. "dirh" is a pointer to a structure as defined
560:
561: below; the file cookie for the directory being opened may be found there.
562:
563: "tosflag" is a copy of "dirh->flags" and is in a sense redundant. The
564:
565: file system should initialize the "fsstuff" and "index" fields of "*dirh"
566:
567: to whatever it needs for carrying out a successful search.
568:
569:
570:
571: /* structure for opendir/readdir/closedir */
572:
573: typedef struct dirstruct {
574:
575: fcookie fc; /* cookie for this directory */
576:
577: ushort index; /* index of the current entry */
578:
579: ushort flags; /* flags (e.g. tos or not) */
580:
581: #define TOS_SEARCH 0x01
582:
583: /* if TOS_SEARCH is set, this call originated from a TOS Fsfirst() system
584:
585: * call -- if possible, the returned names should be acceptable to a
586:
587: * "naive" TOS program
588:
589: */
590:
591: char fsstuff[60]; /* anything else the file system wants */
592:
593: } DIR;
594:
595:
596:
597: long (*readdir) P_((DIR *dirh, char *name, short namelen, fcookie *fc));
598:
599: Read the next name from the directory whose DIR structure (see above)
600:
601: is "*dirh". The name should be copied into "name" (if dirh->flags & TOS_SEARCH
602:
603: is nonzero) or "name+4" if dirh->flags & TOS_SEARCH is 0; in the latter case,
604:
605: the first 4 bytes of "name" should be a unique index for the file. "namelen"
606:
607: is the total size of the buffer for "name"; if the next file name (plus index,
608:
609: if appopriate, and including the trailing 0) is too long for the buffer, as
610:
611: much of it as will fit should be copied in and ENAMETOOLONG returned. If no
612:
613: more file names remain unread in the directory, ENMFIL should be returned
614:
615: and "name" left unchanged. Otherwise, 0 should be returned.
616:
617: Note that volume labels should not be read by this function; only
618:
619: "readlabel" (q.v.) should see these.
620:
621:
622:
623: long (*rewinddir) P_((DIR *dirh));
624:
625: Reset the file system specific fields of "*dirh" so that the next call to
626:
627: "readdir" on this directory will return the first file name in the directory.
628:
629:
630:
631: long (*closedir) P_((DIR *dirh));
632:
633: Called by the kernel when the directory "*dirh" is not going to be searched
634:
635: any more; if the file system needs to clean up any structures or free memory
636:
637: allocated for the search it can do so here.
638:
639:
640:
641: long (*pathconf) P_((fcookie *dir, short which));
642:
643: Get path configuration information for the directory whose cookie is
644:
645: "*dir". "which" indicates what kind of information should be returned,
646:
647: as follows:
648:
649:
650:
651: /* The requests for pathconf() */
652:
653: #define DP_IOPEN 0 /* internal limit on # of open files */
654:
655: #define DP_MAXLINKS 1 /* max number of hard links to a file */
656:
657: #define DP_PATHMAX 2 /* max path name length */
658:
659: #define DP_NAMEMAX 3 /* max length of an individual file name */
660:
661: #define DP_ATOMIC 4 /* # of bytes that can be written atomically */
662:
663: #define DP_TRUNC 5 /* file name truncation behavior */
664:
665: /* possible return values for DP_TRUNC */
666:
667: # define DP_NOTRUNC 0 /* long names cause an error */
668:
669: # define DP_AUTOTRUNC 1 /* long names are truncated */
670:
671: # define DP_DOSTRUNC 2 /* DOS 8+3 rules are used */
672:
673: #define DP_CASE 6 /* file name case conversion */
674:
675: /* possible values returned for DP_CASE */
676:
677: # define DP_CASESENS 0 /* case sensitive */
678:
679: # define DP_CASECONV 1 /* case always converted */
680:
681: # define DP_CASEINSENS 2 /* case insensitive, preserved */
682:
683:
684:
685: #define DP_MAXREQ 6 /* highest legal request */
686:
687: /* Dpathconf and Sysconf return this when a value is not limited
688:
689: (or is limited only by available memory) */
690:
691: #define UNLIMITED 0x7fffffffL
692:
693:
694:
695: long (*dfree) P_((fcookie *dir, long *buf));
696:
697: Determine bytes used and free on the disk that the directory whose cookie
698:
699: is "*dir" is contained on. "buf" points to the same kind of buffer that
700:
701: the "Dfree" system call uses; see the documentation for that call.
702:
703:
704:
705: long (*writelabel) P_((fcookie *dir, char *name));
706:
707: Create a volume label with the indicated name on the drive which contains
708:
709: the directory whose cookie is "*dir". If a label already exists, the file
710:
711: system may either fail the call with EACCDN or re-write the label. If the
712:
713: file system doesn't support the notion of labels, it should return EINVFN.
714:
715:
716:
717: long (*readlabel) P_((fcookie *dir, char *name, short namelen));
718:
719: Read the volume label for the disk whose root directory has the cookie
720:
721: "*dir" into the buffer "name", which is "namelen" bytes long. If the
722:
723: volume label (including trailing 0) won't fit, return ENAMETOOLONG. If
724:
725: *dir is not the cookie of a root directory, or if no volume label
726:
727: exists (perhaps because the file system doesn't support them), return
728:
729: EFILNF.
730:
731:
732:
733: long (*symlink) P_((fcookie *dir, char *name, char *to));
734:
735: Create a symbolic link called "name" in the directory whose cookie is
736:
737: "*dir". The link should contain the 0-terminated string "to". If the file
738:
739: system doesn't support symbolic links, it should return EINVFN.
740:
741:
742:
743: long (*readlink) P_((fcookie *file, char *buf, short buflen));
744:
745: Read the contents of the symbolic link whose cookie is "*file" into the
746:
747: buffer "buf", which is "buflen" bytes long. If the contents (including the
748:
749: trailing 0) won't fit, return ENAMETOOLONG; if the file system doesn't
750:
751: do symbolic links, return EINVFN.
752:
753:
754:
755: long (*hardlink) P_((fcookie *fromdir, char *fromname,
756:
757: fcookie *todir, char *toname));
758:
759: Create a hard link called "toname" in the directory whose cookie is
760:
761: "*todir" for the file named "fromname" in the directory whose cookie is
762:
763: "*fromdir". If the file system doesn't do hard links, return EINVFN.
764:
765:
766:
767: long (*fscntl) P_((fcookie *dir, char *name, short cmd, long arg));
768:
769: Perform an operation on the file whose name is "name", in the directory with
770:
771: cookie "*dir". "cmd" and "arg" specify the operation, and are file system
772:
773: specific. See the documentation for Dcntl() for more details. Most file
774:
775: systems will just return EINVFN for any values of "cmd" and "arg"; this call
776:
777: is here so that you can provide users with a way to manipulate various special
778:
779: features of your file system.
780:
781:
782:
783: long (*dskchng) P_((short drv));
784:
785: Check for media change. "drv" is the BIOS device number on which the
786:
787: kernel thinks there has been a change. This function is called only
788:
789: when the kernel detects what the BIOS claims is a definite disk change
790:
791: (i.e. Mediach returning 2 or Mediach returning 1 and Rwabs returning -14).
792:
793: This may be the result of a program trying to force a media change; if the
794:
795: file system agrees that a change has occured, it should perform any
796:
797: appropriate actions (e.g. invalidating buffers) and return 1; the kernel
798:
799: will then invalidate any open files or directories on the device and
800:
801: re-check what file system the device belongs If no change, in fact, occured,
802:
803: a 0 should be returned to tell the kernel not to worry.
804:
805:
806:
807: long zero;
808:
809: A long word present to allow for future expansion; this must always be set
810:
811: to 0 by file systems (for now).
812:
813: } FILESYS;
814:
815:
816:
817: typedef struct fileptr {
818:
819: short links; /* number of copies of this descriptor */
820:
821: ushort flags; /* file open mode and other file flags */
822:
823: #define O_RWMODE 0x03 /* isolates file read/write mode */
824:
825: # define O_RDONLY 0x00
826:
827: # define O_WRONLY 0x01
828:
829: # define O_RDWR 0x02
830:
831: # define O_EXEC 0x03 /* execute file; used by kernel only */
832:
833:
834:
835: #define O_APPEND 0x08 /* all writes go to the end of the file */
836:
837:
838:
839: #define O_SHMODE 0x70 /* isolates file sharing mode */
840:
841: # define O_COMPAT 0x00 /* compatibility mode */
842:
843: # define O_DENYRW 0x10 /* deny both read and write access */
844:
845: # define O_DENYW 0x20 /* deny write access to others */
846:
847: # define O_DENYR 0x30 /* deny read access to others */
848:
849: # define O_DENYNONE 0x40 /* don't deny any access to others */
850:
851:
852:
853: #define O_NOINHERIT 0x80 /* children can't access via this file descriptor */
854:
855: #define O_NDELAY 0x100 /* don't block for i/o on this file */
856:
857: #define O_CREAT 0x200 /* create file if it doesn't exist */
858:
859: #define O_TRUNC 0x400 /* truncate file to 0 bytes if it does exist */
860:
861: #define O_EXCL 0x800 /* fail open if file exists */
862:
863: #define O_TTY 0x2000 /* file is a terminal */
864:
865: #define O_HEAD 0x4000 /* file is a pseudo-terminal "master" */
866:
867: #define O_LOCK 0x8000 /* file has been locked */
868:
869:
870:
871: The "flags" is constructed by or'ing together exactly one read/write mode,
872:
873: one sharing mode, and any number of the other bits. Device drivers can
874:
875: ignore the O_CREAT flag, since file creation is handled by the kernel.
876:
877: The O_TRUNC flag, however, should be respected; the file should be
878:
879: truncated to 0 length if this flag is set.
880:
881:
882:
883: long pos; /* position in file */
884:
885: The kernel doesn't actually use this field, except to initialize it to
886:
887: 0; it is recommended that device drivers that allow seeking should use it
888:
889: to store the current position in the file (relative to the start of
890:
891: the file). Other device drivers may use it for other purposes.
892:
893: long devinfo; /* device driver specific info */
894:
895: This field is passed back to the kernel from the file system from the
896:
897: "getdev" call; its interpretation is file system specific, except that
898:
899: if this is a terminal device (i.e. the O_TTY bit is set in "flags") then
900:
901: this must be a pointer to a struct tty for this terminal.
902:
903: fcookie fc; /* file system cookie for this file */
904:
905: This is the cookie for the file, as returned by the file system "lookup"
906:
907: function during opening of the file.
908:
909: struct devdrv *dev; /* device driver that knows how to deal with this */
910:
911: This is the device driver returned by the "getdev" call.
912:
913: struct fileptr *next; /* link to next fileptr for this file */
914:
915: This field may be used by device drivers to keep a linked list of file
916:
917: pointers that refer to the same physical file, for example, in order to
918:
919: implement file sharing or locking code.
920:
921: } FILEPTR;
922:
923:
924:
925:
926:
927: The Device Driver Structure
928:
929:
930:
931: All of the functions in the device driver structure, like those in the
932:
933: file system structure, are called in supervisor mode and with the
934:
935: GCC calling conventions. They must preserve registers d2-d7 and a2-a7,
936:
937: and results are to be returned in register d0. The BIOS, XBIOS,
938:
939: GEMDOS, AES, and VDI must not be called directly from the device
940:
941: driver; but GEMDOS and BIOS functions may be called indirectly via
942:
943: the tables found in the kerinfo structure.
944:
945:
946:
947: typedef struct devdrv {
948:
949: long (*open) P_((FILEPTR *f));
950:
951: This routine is called by the kernel during a file "open", after it has
952:
953: constructed a FILEPTR for the file being opened and determined the device
954:
955: driver. The device driver should check the contents of the FILEPTR and
956:
957: make any changes or initializations necessary. If for some reason the open
958:
959: call should be failed, an appropriate error code must be returned (in which
960:
961: case the kernel will free the FILEPTR structure automatically). For example,
962:
963: if the file sharing mode in f->flags is not compatible with the sharing
964:
965: mode of another open FILEPTR referring to the same physical file, EACCDN should
966:
967: be returned.
968:
969:
970:
971: long (*write) P_((FILEPTR *f, char *buf, long bytes));
972:
973: Write "bytes" bytes from the buffer pointed to by "buf" to the file with
974:
975: FILEPTR "f". Return the number of bytes actually written. If the file
976:
977: pointer has the O_APPEND bit set, the kernel will automatically perform
978:
979: an "lseek" to the end of the file before calling the "write" function.
980:
981: If the device driver cannot ensure the atomicity of the "lseek" + "write"
982:
983: combination, it should take whatever steps are necessary here to ensure
984:
985: that files with O_APPEND really do have all writes go to the end of the
986:
987: file.
988:
989:
990:
991: long (*read) P_((FILEPTR *f, char *buf, long bytes));
992:
993: Read "bytes" bytes from the file with FILEPTR "f" into the buffer pointed
994:
995: to by "buf". Return the number of bytes actually read.
996:
997:
998:
999: long (*lseek) P_((FILEPTR *f, long where, short whence));
1000:
1001: Seek to a new position in the file. "where" is the new position; "whence"
1002:
1003: says what "where" is relative to, as follows:
1004:
1005: /* lseek() origins */
1006:
1007: #define SEEK_SET 0 /* from beginning of file */
1008:
1009: #define SEEK_CUR 1 /* from current location */
1010:
1011: #define SEEK_END 2 /* from end of file */
1012:
1013:
1014:
1015: long (*ioctl) P_((FILEPTR *f, short mode, void *buf));
1016:
1017: Perform a device specific function. "mode" is the function desired. All devices
1018:
1019: should support the FIONREAD and FIONWRITE functions, and the file locking
1020:
1021: Fcntl functions if appropriate (see the documentation for the GEMDOS
1022:
1023: Fcntl function).
1024:
1025:
1026:
1027: long (*datime) P_((FILEPTR *f, short *timeptr, short rwflag));
1028:
1029: Get or set the date/time of the file. "timeptr" is a pointer to two words,
1030:
1031: the first of which is the time and the second of which is the date.
1032:
1033: If "rwflag" is 0, the time and date of the file should be placed into timeptr.
1034:
1035: If "rwflag" is nonzero, then the time and date of the file should be set to
1036:
1037: agree with the time and date pointed to by timeptr.
1038:
1039:
1040:
1041: long (*close) P_((FILEPTR *f, short pid));
1042:
1043: Called every time an open file is closed. Note that the file is "really"
1044:
1045: being closed if f->links == 0, otherwise, the FILEPTR is still being used
1046:
1047: by some process. However, if the device driver supports file locking
1048:
1049: then all locks held on the file by process pid should be released on
1050:
1051: any close, even if f->links > 0. Some things to watch out for:
1052:
1053: (1) "pid" is not necessarily the current process; some system calls
1054:
1055: (e.g. Fmidipipe, Pexec) can sometimes close files in a process
1056:
1057: other than the current one.
1058:
1059: (2) Device drivers should set the O_LOCK bit on f->flag when the F_SETLK
1060:
1061: or F_SETLKW ioctl is made; they can then test for this bit when the file
1062:
1063: is being closed, and remove locks only if O_LOCK is set. Note that all locks
1064:
1065: held by process pid and referring to the same physical file as "f" may
1066:
1067: be removed if O_LOCK is set, not just the locks that were associated with
1068:
1069: the particular FILEPTR "f". If the FILEPTR has never had any lock Fcntl()
1070:
1071: calls made on it, locks on the associated physical file need not be (and
1072:
1073: should not be) removed when it is closed.
1074:
1075:
1076:
1077: long (*select) P_((FILEPTR *f, long proc, short mode));
1078:
1079: Called by Fselect() when "f" is one of the file handles a user has chosen to
1080:
1081: do a select on. If mode is O_RDONLY, the select is for reading; if
1082:
1083: it is O_WRONLY, it is for writing (if it is for both reading and writing,
1084:
1085: the function will be called twice). The select function should return
1086:
1087: 1 if the device is ready for reading or writing (i.e. if a read or write
1088:
1089: call to the device will not block); otherwise, it should take whatever
1090:
1091: steps are necessary to arrange to wake up the process whose PROC structure is
1092:
1093: pointed to by "proc" when the appropriate I/O on the device becomes possible.
1094:
1095: Normally, this will be done by calling the "wakeselect" function (as passed
1096:
1097: by the kernel in "struct kerinfo") with "proc" as its parameter.
1098:
1099:
1100:
1101: void (*unselect) P_((FILEPTR *f, long proc, short mode));
1102:
1103: Called when the kernel is returning from an Fselect that had previously
1104:
1105: selected this file or device; the device driver should no longer notify
1106:
1107: "proc" when I/O is possible for this file or device. "mode" is the same
1108:
1109: mode as was passed to the select() function (see above), i.e. either
1110:
1111: O_RDONLY or O_WRONLY; as with select(), unselect() will be called twice
1112:
1113: if both input and output were selected for.
1114:
1115:
1116:
1117: long reserved[3];
1118:
1119: Reserved longwords for future expansion. These must be set to 0.
1120:
1121: } DEVDRV;
1122:
1123:
1124:
1125:
1126:
1127:
1128:
1129: How the File System Is Booted
1130:
1131:
1132:
1133: A loadable file system is an ordinary TOS executable file with an
1134:
1135: extension of ".xfs". MiNT searches its current directory (normally the
1136:
1137: root directory of the boot disk) when it is starting for all such
1138:
1139: files, and loads them with Pexec mode 3. It then does a jump to
1140:
1141: subroutine call to the first instruction of the loaded program,
1142:
1143: passing on the stack a pointer to a structure of type "struct kerinfo"
1144:
1145: (see below) which describes the version of MiNT and provides entry points
1146:
1147: for various utility functions.
1148:
1149:
1150:
1151: The file system should *not* set up a stack or shrink its basepage
1152:
1153: (so the ordinary C startup code is not necessary). MiNT has already provided
1154:
1155: a stack of about 8K or so, and has shrunk the basepage to the bare minimum.
1156:
1157: The file system initialization point (like all file system functions) is
1158:
1159: called in supervisor mode; it must never switch back to user mode. It
1160:
1161: may use registers d0, d1, a0, and a1 as scratch registers; all other
1162:
1163: registers must be preserved.
1164:
1165:
1166:
1167: What the file system initialization code *should* do is to check that an
1168:
1169: appropriate version of MiNT is running and to otherwise check the system
1170:
1171: configuration to see if it is appropriate for the file system driver.
1172:
1173: If so, a pointer to a FILESYS structure should be returned; if not, a NULL
1174:
1175: pointer should be returned.
1176:
1177:
1178:
1179: Note that it is not necessary to actually check during initialization for
1180:
1181: the presence of disks with the appropriate file system types; MiNT will
1182:
1183: call the file system "root" function for each drive in the system, and so
1184:
1185: such checks should be done in the "root" function.
1186:
1187:
1188:
1189: If the file system driver wishes to add new drives to the system,
1190:
1191: it should update the drive configuration variable stored at 0x4c2 to
1192:
1193: reflect the presence of these new drives.
1194:
1195:
1196:
1197: File system drivers should *not* make any calls to the BIOS or GEMDOS
1198:
1199: directly; all such calls should be made through the vectors provided by
1200:
1201: the kernel as part of the struct kerinfo. File system drivers should
1202:
1203: never call the AES, VDI, or XBIOS.
1204:
1205:
1206:
1207: All functions made visible to file systems through the kerinfo
1208:
1209: structure should be called using the GCC/Lattice C calling conventions,
1210:
1211: i.e.:
1212:
1213: (1) parameters are passed on the stack, aligned on 16 bit boundaries
1214:
1215: (2) registers d0-d1 and a0-a1 are scratch registers and may be modified
1216:
1217: by the called functions
1218:
1219: (3) if the function returns a value, it will be returned in register
1220:
1221: d0
1222:
1223:
1224:
1225: /*
1226:
1227: * this is the structure passed to loaded file systems to tell them
1228:
1229: * about the kernel
1230:
1231: */
1232:
1233:
1234:
1235: typedef long (*Func)();
1236:
1237:
1238:
1239: struct kerinfo {
1240:
1241: short maj_version; /* kernel version number */
1242:
1243: short min_version; /* minor kernel version number */
1244:
1245: ushort default_mode; /* default file access permissions */
1246:
1247: short reserved1; /* room for expansion */
1248:
1249:
1250:
1251: /* OS functions */
1252:
1253: /* NOTE: these tables are definitely READ ONLY!!!! */
1254:
1255: Func *bios_tab; /* pointer to the BIOS entry points */
1256:
1257: Func *dos_tab; /* pointer to the GEMDOS entry points */
1258:
1259:
1260:
1261: /* media change vector: call this if a device driver detects a disk
1262:
1263: * change during a read or write operation. The parameter is the BIOS device
1264:
1265: * number of the disk that changed.
1266:
1267: */
1268:
1269: void (*drvchng) P_((ushort));
1270:
1271:
1272:
1273: /* Debugging stuff */
1274:
1275: void (*trace) P_((char *, ...)); /* informational messages */
1276:
1277: void (*debug) P_((char *, ...)); /* error messages */
1278:
1279: void (*alert) P_((char *, ...)); /* really serious errors */
1280:
1281: void (*fatal) P_((char *, ...)); /* fatal errors */
1282:
1283:
1284:
1285: /* memory allocation functions */
1286:
1287: /* kmalloc and kfree should be used for most purposes, and act like malloc
1288:
1289: * and free respectively. umalloc and ufree may be used to allocate/free memory
1290:
1291: * that is attached to the current process, and which is freed automatically
1292:
1293: * when the process exits; this is generally not of much use to a file system
1294:
1295: * driver
1296:
1297: */
1298:
1299: void * (*kmalloc) P_((long));
1300:
1301: void (*kfree) P_((void *));
1302:
1303: void * (*umalloc) P_((long));
1304:
1305: void (*ufree) P_((void *));
1306:
1307:
1308:
1309: /* utility functions for string manipulation */
1310:
1311:
1312:
1313: /* strnicmp, stricmp: like strncmp and strcmp, respectively, except
1314:
1315: * that case is ignored
1316:
1317: */
1318:
1319: short (*strnicmp) P_((char *, char *, short));
1320:
1321: short (*stricmp) P_((char *, char *));
1322:
1323:
1324:
1325: /* strlwr: convert a string to lower case. Returns the address of the string */
1326:
1327: char * (*strlwr) P_((char *));
1328:
1329: /* strupr: convert a string to upper case. Returns the address of the string */
1330:
1331: char * (*strupr) P_((char *));
1332:
1333:
1334:
1335: /* sprintf: like the C library sprintf call, but using this one means you
1336:
1337: * can avoid linking another one. Note: floating point formats are not
1338:
1339: * supported! Also: this sprintf will put at most SPRINTF_MAX characters
1340:
1341: * into the output string.
1342:
1343: */
1344:
1345: short (*sprintf) P_((char *, const char *, ...));
1346:
1347:
1348:
1349: /* utility functions for manipulating time */
1350:
1351: /* convert "ms" milliseconds into a DOS time (in td[0]) and date (in td[1]) */
1352:
1353: void (*millis_time) P_((ulong ms, short *td));
1354:
1355:
1356:
1357: /* convert a DOS style time and date into a Unix style time; returns the
1358:
1359: * Unix time
1360:
1361: */
1362:
1363: long (*unixtim) P_((ushort time, ushort date));
1364:
1365:
1366:
1367: /* convert a Unix time into a DOS time (in the high word of the returned
1368:
1369: * value) and date (in the low word)
1370:
1371: */
1372:
1373: long (*dostim) P_((long));
1374:
1375:
1376:
1377: /* utility functions for dealing with pauses */
1378:
1379: /* go to sleep temporarily for about "n" milliseconds (the exact time
1380:
1381: * slept may vary
1382:
1383: */
1384:
1385: void (*nap) P_((ushort n));
1386:
1387:
1388:
1389: /* wait on system queue "que" until a condition occurs */
1390:
1391: void (*sleep) P_((short que, long cond));
1392:
1393: /* wake all processes on queue "que" that are waiting for condition "cond" */
1394:
1395: void (*wake) P_((short que, long cond));
1396:
1397:
1398:
1399: /* wake a process that is doing a select(); "param" should be the process
1400:
1401: * code passed to select()
1402:
1403: */
1404:
1405: void (*wakeselect) P_((long param));
1406:
1407:
1408:
1409: /* file system utility functions */
1410:
1411: /* "list" is a list of open files; "f" is a new file that is being opened.
1412:
1413: * If the file sharing mode of "f" conflicts with any of the FILEPTRs
1414:
1415: * in the list, then this returns 1, otherwise 0.
1416:
1417: */
1418:
1419: short (*denyshare) P_((FILEPTR *list, FILEPTR *f));
1420:
1421:
1422:
1423: /* denylock() checks a list of locks to see if the new lock conflicts
1424:
1425: * with any one in the list. If so, the first conflicting lock
1426:
1427: * is returned; otherwise, a NULL is returned.
1428:
1429: * This function is only available if maj_version > 0 or min_version >= 94.
1430:
1431: * Otherwise, it will be a null pointer.
1432:
1433: */
1434:
1435: LOCK * (*denylock) P_((LOCK *list, LOCK *new));
1436:
1437:
1438:
1439: /* reserved for future use */
1440:
1441: long res2[9];
1442:
1443: };
1444:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.