|
|
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.