HomeMagiCMagiC's DFS-conceptVFAT-XFS in MagiC

11.21 MagiC's XFS-concept

MagiC, just as MultiTOS, enables the incorporation of alternative filesystems (so-called XFSs) and with that the use of long filenames. However, for several reasons a different approach was chosen in MagiC to Atari's solution. This has the unfortunate consequence that the XFS's available for MultiTOS (Minix-XFS, CD-ROM-XFS, ...) cannot be used under MagiC. This chapter describes the following points:

See also: VFAT-XFS in MagiC   MagiC's DFS-concept

11.21.1 General remarks about MagiC's XFS-concept

GEMDOSwas until now the most conservative part of the MagiC operating system. For network drivers, practically all DOS calls, including Pexec, had to be recreated without being able to intervene at a deeper level. In Mag!X 1.x (as in TOS) the DOS was not even reentrant because a statically constructed stack was used.

In MultiTOS/MiNT the problem is circumvented in such a way that a virtual system is laid over the GEMDOS which takes care of all higher management tasks, can incorporate other filesystems and uses GEMDOS only as a dumb filesystem driver. An advantage of this solution is its great flexibility and extendibility, but a decided drawback is the towering overhead when using the 'normal' DOS filesystem. But this is just the one that is utilized most frequently. In addition, the GEMDOS filesystem can gain no functionality, comfort or speed with the use of MiNT, since the old routines only execute with additional overhead. File-system accesses under MiNT are therefore generally not reentrant, i.e., as under MS-Windows, every floppy disk access paralyses the whole computer.

A further property of MiNT is the attempt to undertake functions that all filesystems have in common in the kernel. Although this leaves the filesystem drivers (MiNT-XFSs) compact, due to the Inode-oriented format of the kernel functions an unfavourable structure is forced on the file drivers in some circumstances; in addition, generally many calls of the filesystem driver are required for one DOS call. Finally the MiNT kernel itself is very long, but to a large extent lies fallow as long as no filesystems other than DOS are in use.

Under MagiC a different approach was chosen, which included rewriting all GEMDOS functions from the ground up, including the low-level ones for the sector buffering, and to carve them up into three, four or five layers in which one can intervene from the outside (with loaded- in drivers). A side-effect resulted in an extension of the DOS file system functionality and an additional filesystem on the logical drive U:.

The whole concept inclusive of accesses to the DOS filesystems is reentrant and runs in the background. Thus it is possible to amend files on drive A: without markedly slowing down the computer during floppy disk accesses. Despite this MagiC has till now grown only by 10kB. Compared to MiNT, more functions were offloaded into the file system drivers, and while this makes them longer, it gives them the possibility of executing the functions much more efficiently. Also, the DOS filesystem has become somewhat faster rather than slower.

Although realized completely in Assembler, we are dealing with an object-oriented operating system with virtual functions and multi- level heredity. A file descriptor (FD), as used by the kernel and made available by the XFS, is an object with special data and functions. But the XFS realizes also a derived object with further data fields and functions. Finally the DFS subdriver of the DOS_XFS must in turn accommodate further functions and data in the FD and extrapolate the class further. Things look exactly the same with the DMD (drive medium descriptor). The kernel requires only a few statements, but the lower layers appreciably more, though always different ones.

The layers in detail:

  1. The DOS kernel. This lies in MagiC itself and is called directly by user programs via TRAP #1. It contains modules for memory management, for process management and for file management. The latter has the following sublayers:
  2. The filesystem (XFS = eXtended File-System). Its construction is basically different from a MiNT-XFS, but fulfills the same purpose. MagiC for Ataris contains only a single XFS, the so- called DOS_XFS; others can be incorporated. The Macintosh version (MagiC Mac) contains a Mac-XFS in addition. Specifically this filesystem again makes use of subdrivers:
    1. A DOS filesystem (DFS) is called up by DOS_XFS. This only contains the file functions, while the directory management is essentially taken on by the DOS_XFS. MagiC contains directly two DFSs. One for drive U:, a second for the FAT filesystems that lie on BIOS drives. More DFSs can be incorporated. The effort for a DFS is appreciably lower than for an XFS, as many functions are performed already by the DOS_XFS. The vital prerequisite is a DOS- conforming directory structure (with 32-bit entries and filenames in the 8+3 format). The kernel itself does not come into contact with the DFS but controls it transparently via the DOS-XFS.
  3. The file drivers (MX_DEV), which essentially take care of file reading and writing operations. They are created and managed by the XFS, but with functions such as Fread and Fwrite called directly by the kernel, which accrues extremely low overheads. The DOS_XFS actually contains only one file driver. This handles the updating of the directory at write accesses, for instance, and in turn calls a subdriver (MX_DDEV).
    1. The subdriver MX_DDEV is only called by the DOS file driver of the DOS_XFS filesystem. The user can incorporate custom MX_DDEVs via the directory U:\\DEV. The kernel itself does not come into contact with the subdrivers.

Notes:

See also: MagiC's XFS-concept   Test for pipes

11.21.2 The make-up of an XFS

Since the implementation of an XFS can only be performed in Assembler, its description is given in Assembler syntax:

xfs_name:       DS.B      8    /* Name of the filesystem              */
xfs_next:       DS.L      1    /* Next driver                         */
xfs_flags:      DS.L      1    /* Flags, analogous to MiNT            */
xfs_init:       DS.L      1    /* Initialization                      */
xfs_sync:       DS.L      1    /* Synchronization of the filesystem   */
xfs_pterm:      DS.L      1    /* Notifies a program termination      */
xfs_garbcoll:   DS.L      1    /* Garbage collection, or NULL         */
xfs_freeDD:     DS.L      1    /* Releases DD                         */
xfs_drv_open:   DS.L      1    /* Tests/initializes DMD (Mediach)     */
xfs_drv_close:  DS.L      1    /* Forces a disk media change          */
xfs_path2DD:    DS.L      1    /* Returns a DD to a pathname          */
xfs_sfirst:     DS.L      1    /* Searches for first matching file    */
xfs_snext:      DS.L      1    /* Searches for next matching file     */
xfs_fopen:      DS.L      1    /* Opens or creates a file             */
xfs_fdelete:    DS.L      1    /* Deletes a file                      */
xfs_link:       DS.L      1    /* Required for Frename and Flink      */
xfs_xattr:      DS.L      1    /* Required for Fxattr                 */
xfs_attrib:     DS.L      1    /* Required for Fattrib                */
xfs_chown:      DS.L      1    /* Required for Fchown                 */
xfs_chmod:      DS.L      1    /* Required for Fchmod                 */
xfs_dcreate:    DS.L      1    /* Creates a directory                 */
xfs_ddelete:    DS.L      1    /* Deletes a directory                 */
xfs_DD2name:    DS.L      1    /* Returns the absolute pathname       */
xfs_dopendir:   DS.L      1    /* Opens a directory                   */
xfs_dreaddir:   DS.L      1    /* Reads the next directory entry      */
xfs_drewinddir: DS.L      1    /* Sets the dirhandle to 1st entry     */
xfs_dclosedir:  DS.L      1    /* Closes the dirhandle                */
xfs_dpathconf:  DS.L      1    /* Obtains various limits              */
xfs_dfree:      DS.L      1    /* Obtains number of free blocks etc.  */
xfs_wlabel:     DS.L      1    /* Writes the disk name                */
xfs_rlabel:     DS.L      1    /* Reads the disk name                 */
xfs_symlink:    DS.L      1    /* Creates a symbolic link             */
xfs_readlink:   DS.L      1    /* Reads a symbolic link               */
xfs_dcntl:      DS.L      1    /* Required for Dcntl                  */

See also: Make-up of a DFS   MagiC's XFS-concept

11.21.2.1 xfs_attrib

Name: »xfs_attrib« - Required for Fattrib.
Parameters:
a0 = DD *
a1 = char *name
d0 = int rwflag
d1 = int attrib
-> d0 = char attr or long errcode
-> a0 = SYMLINK *
Description: Unlike MiNT, MagiC does not implement this function as Fxattr, because this can mean a huge overhead in some circumstances. Here symbolic links must followed, i.e. the return of ELINK is permissible.

The function xfs_attrib is not yet carried out tidily by DOS_XFS, symbolic links are not recognised.
Group: Make-up of an XFS
See also: MagiC's XFS-concept   Fattrib   Fxattr

11.21.2.2 xfs_chmod

Name: »xfs_chmod« - Required for Fchmod.
Parameters:
a0 = DD *
a1 = char *name
d0 = int mode
-> d0 = long errcode
Description: xfs_chmod alters the access rights of a file. The parameters correspond to those of Fchmod. Note that symbolic links are not followed.

It is not supported by DOS_XFS.
Group: Make-up of an XFS
See also: MagiC's XFS-concept   Fchmod

11.21.2.3 xfs_chown

Name: »xfs_chown« - Required for Fchown.
Parameters:
a0 = DD *
a1 = char *name
d0 = uid
d1 = gid
-> d0 = long errcode
Description: xfs_chown alters the owner (user ID and group ID) of a file. The parameters correspond to those of Fchown. Symbolic links are not followed, i.e. owner and group of the symbolic link are modified.

It is not supported by DOS_XFS.
Group: Make-up of an XFS
See also: MagiC's XFS-concept   Fchown

11.21.2.4 xfs_dclosedir

Name: »xfs_dclosedir« - schließt ein Verzeichnis
Parameters:
a0 = DHD *dhd
-> d0 = long errcode
Description: Analogous to MiNT.
Group: Make-up of an XFS
See also: MagiC's XFS-concept   Dclosedir

11.21.2.5 xfs_dcntl

Name: »xfs_dcntl« - Required for Dcntl.
Parameters:
a0 = DD *
a1 = char *name
d0 = int cmd
d1 = long arg
-> d0 = long errcode
Description: xfs_dcntl is required for Dcntl. Every XFS should support FUTIME.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.6 xfs_dcreate

Name: Create a directory.
Parameters:
a0 = DD *
a1 = char *name (without path)
-> d0 = long errcode
Description: xfs_dcreate is required for Dcreate.
Group: Make-up of an XFS
See also: MagiC's XFS-concept   Dcreate

11.21.2.7 xfs_ddelete

Name: »xfs_ddelete« - Delete a directory.
Parameters:
a0 = DD *
-> d0 = long errcode
Description: The call xfs_ddelete had to be altered as of MagiC Version 4.01.

For MagiC < 4.01 (kernel version < 3) the following applies:
During deletion one must ensure that no directory may be referenced by the kernel except by the call itself (i.e. dd_refcnt must == 1). In addition one must ensure that there are no files in the directory. ELINK may not be returned, symbolic links may not be processed. The access rights (if they exist) must be tested by the XFS.

For MagiC < 4.01 (kernel version >= 3) the following applies:
Reentrance problems gave rise to some changes, whereby the kernel takes over access control from the XFS and furthermore the kernel releases the DD, not the XFS: The kernel first of all opens the parent of the directory to be deleted with xfs_path2DD, then it tests with xfs_xattr whether it is dealing with a symlink, and if appropriate deletes it with xfs_fdelete.

If it is dealing with a directory, the kernel opens this again with xfs_path2DD (mode 1) and releases the parent again with xfs_freeDD. The check of dd_refcnt is performed by the kernel, hence the counter can and must be ignored by the XFS. The XFS must now ensure that the directory to be deleted or the DD cannot be opened or used by others (important for reentrant XFSs). The XFS then deletes the directory, but does not (!) release the DD, so that the kernel if successful (return value E_OK) can release its standard paths beforehand. The kernel then calls xfs_freeDD. As usual the XFS must check that the directory is empty, or if access rights exist if appropriate.

Again in context:
  • The kernel ascertains the DD to be deleted, tests the reference counter

  • xfs_ddelete locks the DD. If this does not work then EACCDN is returned

  • xfs_ddelete deletes the directory, provided it is empty; here the DD acts as a lock for parallel-runnning attempts to use the newly deleted directory

  • xfs_ddelete leaves the now invalid (but still serving as a lock) DD still valid (in contrast to the old concept)

  • On success the kernel makes its standard paths invalid

  • The kernel releases the DD

Group: Make-up of an XFS
See also: MagiC's XFS-concept   Ddelete

11.21.2.8 xfs_dfree

Name: »xfs_dfree« - Obtain number of free blocks.
Parameters:
a0 = DD *
a1 = long[4]
-> d0 = long errcode
Description: xfs_dfree is required for Dfree. DOS_XFS calls the appropriate DFS driver directly.
Group: Make-up of an XFS
See also: MagiC's XFS-concept   Dfree

11.21.2.9 xfs_DD2name

Name: »xfs_DD2name« - Return the absolute pathname.
Parameters:
a0 = DD *
a1 = char *name
d0 = int bufsize
-> d0 = long errcode
Description: xfs_DD2name is required for Dgetpath and Dgetcwd. The path that belongs to the passed directory is copied after name. The path must be returned without the trailing '\', i.e. an empty string for the root directory. bufsize, as ever, is to be interpreted as including the terminating NULL-byte. If the buffer is too small (bufsize shorler than the path), then as in MiNT ERANGE must be returned.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.10 xfs_dopendir

Name: »xfs_dopendir« - Open a directory.
Parameters:
a0 = DD *
d0 = int tosflag
-> d0 = DHD *dhd or Fehlercode
Description: xfs_dopendir is required for Dopendir. As tosflag only 0 and 1 are permitted at present. If tosflag == 0, filenames are not trunctated, and the first four bytes returned by D(x)readdir contain the file index.

If tosflag == 1, Dreaddir must truncate the filenames to 8+3 and convert them to upper case, and may not return a file ID.
Group: Make-up of an XFS
See also: MagiC's XFS-concept   Dopendir   Dreaddir   Dxreaddir

11.21.2.11 xfs_dpathconf

Name: »xfs_dpathconf« - Obtain various limits.
Parameters:
a0 = DD *
d0 = int which
-> d0 = long value
Description: Analogous to MiNT. The DOS_XFS directly calls the appropriate DFS driver. which can take the following values:
DP_MAXREQ (-1) Obtain maximum valid value for which
DP_IOPEN (0) Internal limit for number of open files
DP_MAXLINKS (1) Maximum number of links for a file
DP_PATHMAX (2) Maximum length for full pathnames
DP_NAMEMAX (3) Maximum length for filenames
DP_ATOMIC (4) Block size
DP_TRUNC (5) Filename truncation, returns:
DP_NOTRUNC (0) Never truncate ERANGE if nec.
DP_AUTOTRUNC (1) Truncated to max. length
DP_DOSTRUNC (2) Truncated to 8+3
DP_CASE (6) Upper/lower case, returns:
DP_CASESENS (0) Differentiate
DP_CASECONV (1) Converted to upper case
DP_CASEINSENS (2) Not differentiated and not converted


As of the MagiC version of 21.5.95 the following are supported as well:
DP_MODEATTR (7) (as for Dpathconf)
DP_XATTRFIELDS (8) (as for Dpathconf)
Group: Make-up of an XFS
See also: MagiC's XFS-concept   Dpathconf

11.21.2.12 xfs_dreaddir

Name: »xfs_dreaddir« - Read next directory entry.
Parameters:
a0 = DHD *dhd
d0 = int size
a1 = char *buf
d1 = XATTR *xattr or NULL
d2 = long *xr (if xattr != NULL)
-> d0 = long errcode
Description: Analogous to MiNT. Supplants both Dreaddir as well as Dxreaddir.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.13 xfs_drewinddir

Name: »xfs_drewinddir« - Set directory handle to 1st entry.
Parameters:
a0 = DHD * dhd
-> d0 = long errcode
Description: Analogous to MiNT.
Group: Make-up of an XFS
See also: MagiC's XFS-concept   Drewinddir

11.21.2.14 xfs_drv_close

Name: »xfs_drv_close« - Force a disk media change.
Parameters:
a0 = DMD *
d0 = int mode
-> d0 = long errcode
Description: The function xfs_drv_close also performs two tasks, depending on mode:

  1. mode = 0:
    The kernel requests the XFS to close the drive, if possible. If this is not permitted then EACCON must be returned, else all structures are to be released or caches written back and E_OK returned.

    Opened fies are recognized already by the kernel and closing of the drive will be prevented. However only those files that have a handle and are known to the kernel can be recognized here. For the sake of safety the kernel calls xfs_sync before calling this function in case a write-back cache is being used. This strategy will be carried out also even if at some time a mechanism is built in that monitors eject buttons of interchangeablemedia drives or CD-ROMs, and bars ejection if necessary.

  2. mode = 1:
    The kernel forces closing of the drive, the XFS has to return E_OK. No caches may be written back as the drive is already invalid (after a media change has been reported already). DDs and FDs do not have to be released as far as they are still referenced by the kernel, i.e. the kernel still performs xfs_freeDD or dev_close even after a media change.



The internal DOS_XFS passes the call on to the DFS function of the same name, and in addition the XFS structures will be released if necessary.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.15 xfs_drv_open

Name: »xfs_drv_open« - Test/initialize the DMD (Mediach).
Parameters:
a0 = DMD *
-> d0 = long errcode
Description: MagiC supports exactly 26 simultaneously active filesystems that are assigned letters 'A'..'Z'. xfs_drv_open has two tasks:

  1. At the first access to a drive (say D:), the kernel creates a DMD (drive medium descriptor) and 'offers' this to the XFSs. The entry d_dfs is still a NULL-pointer, d_drive is initialized (between 0 and 25, corresponding to 'A'..'Z').

    The DFS drivers now attempt to recognize 'their' filesystem on the drive. If this succeeds, then d_xfs and d_root have to be initialized, in which case the return value is then E_OK. Else EDRIVE is reported, and the DOS_XFS tries the next DFS.

    Warning: The root may not be released during the lifetime of a mounted filesystem. The reference counter of the root should be preloaded with 1 to prevent it being released with xfs_freeDD. In the MagiC versions before 4.01 this was not necessary because the reference counter (in a 'dirty' way) was not incremented before the xfs_path2DD call, nor decremented afterwards.

  2. On subsequent access d_xfs is already initialized, and the DFS has the opportunity to test for a medium change. If everything is in order, E_OK has to be returned. Else the disk medium change routine of the kernel has to be called and E_CHNG returned. For this one obtains the pointer to the medium change routine of the kernel with Dcntl.



The internal DOS_XFS passes on the call to the DFS function of the same name, i.e. all DFS drivers are tried in turn.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.16 xfs_fdelete

Name: »xfs_fdelete« - Delete a file.
Parameters:
a0 = DD *
a1 = char *name (without path)
-> d0 = long errcode
Description: xfs_fdelete is required for Fdelete. When deleting a symlink, only this may be deleted but not a referenced file. This means that a return value of ELINK is not permissible here.

Access right checks are left completely to the XFS. During deletion one should pay attention that no file may be referenced by the kernel (i.e. fd_refcnt != 0).
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.17 xfs_flags

Name: »xfs_flags« -Flags, analogous to MiNT.
Parameters:
Description: Reserved. Should actually contain flags, but it is not used by the MagiC kernel. So please do not use it!
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.18 xfs_fopen

Name: »xfs_fopen« - Open or create a file.
Parameters:
a0 = DD *
a1 = char *name (for opening)
d0 = int omode (fürs Öffnen)
d1 = int attrib (for creating)
-> d0 = FD * or error-code
-> a0 = SYMLINK *
Description: xfs_fopen is used by the functions Fopen and Fcreate. The open-mode in the lower-value byte is different to MiNT, because the MiNT modes are unfavourable for the implementation of inquiries. When calling Fopen via TRAP #1, the MiNT modes are converted by the kernel to the internal modes.

These are the internal modes which have to be handled by the XFS driver (NOINHERIT is not supported, because according to TOS convention only the handles 0..5 are inherited). Otherwise the high byte corresponds to the MiNT conventions:
OM_RPERM   EQU  1   // File is opened for reading
OM_WPERM   EQU  2   // File is opened for writing
OM_EXEC    EQU  4   // File is opened for execution
OM_APPEND  EQU  8   // Write accesses at end (kernel!)
OM_RDENY   EQU  16  // Others may not read at same time
OM_WDENY   EQU  32  // Others may not write at same time
OM_NOCHECK EQU  64  // No check by the kernel


The bit OM_APPEND is taken note of by the kernel at a Fwrite call automatically; the kernel performs an Fseek before every write access.

OM_NOCHECK is set by the kernel if a file is opened or redirected (Fforce) as a device, i.e. as handle -1, -2, -3 or -4. If this bit is set, then the XFS should not perform a check for multiple opening of the file (see also below for fd_mode), but leave this to the device driver.

Here are the bits, which are used as in MiNT:
O_CREAT EQU  $200 // Create file, if it doesn't exist
O_TRUNC EQU  $400 // Clear file, if it exists
O_EXCL  EQU  $800 // Don't open file, if it exists


The kernel performs Fcreate as Fopen (O_CREAT +O_RDWR + O_TRUNC). O_COMPAT (i.e. specify only the TOS mode 0, 1 or 2), is in MagiC always equivalent to O_WDENY.

The checking of the access rights is completely up to the XFS, the kernel does nothing; that would be fairly pointless anyway, since every filesystem has its own mechanisms and rights. The kernel is returned a pointer to an opened FD, i.e. the opening of the file driver must be performed by the XFS. The reference counter of the returned FD is to be incremented by the XFS, or initialized as 1 at the first opening. For symbolic links and disk media changes the same applies as for xfs_sfirst.

Fopen is implemented as follows under MiNT:
  1. With convert pathname->fcookie
  2. With obtain the access rights
  3. Test of access rights by the kernel
  4. With obtain the file driver
  5. With open> open the file


This procedure is very protracted. DOS returns a pointer to the 32-byte directory entry already when searching for a file, which serves directly for the checking of the attributes and with that the access rights, and also for opening the file. Hence MagiC expects direct implementation of the Fopen call with all checks of the access rights. The return is an FD structure, in which the file driver was entered and opened.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.19 xfs_freeDD

Name: »xfs_freeDD« - Release a DD.
Parameters:
a0 = DD *
-> void
Description: The kernel has decremeted the reference counter of a DD to 0, so that the DD is no longer referenced by the kernel. The function xfs_freeDD is called, say, when the kernel after the Fopen no longer requires the path in which the opened file lies and which was passed to xfs_fopen. XFSs that do not perform garbage collection can release their DDs via this function.

One must ensure that the root is never released. Either one builds in a special inquiry here, or (more elegant) already sets the reference counter of the root with xfs_drv_open to 1.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.20 xfs_garbcoll

Name: »xfs_garbcoll« - Garbage collection.
Parameters:
a0 = DMD *d
-> d0 = 1L oder 0L
Description: The kernel urgently requires internal GEMDOS memory and uses xfs_garbcoll to perform a garbage collection. An XFS that does not use the kernel's internal memory management can place a NULL-pointer as a function here.

Warning: As many blocks as possible should be released. The return value is 1 if (at least) one block could be released. During a garbage collection the kernel runs through the whole list of mounted logical drives, so the XFS requests a garbage collection as many times as the number of drives it is managing at the time.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.21 xfs_init

Name: »xfs_init« - Initialization.
Parameters:
Description: Reserved. For MagiC-internal XFSs it contains their initialization. Not used with loaded-in XFSs.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.22 xfs_link

Name: »xfs_link« - Required for Frename and Flink.
Parameters:
a0 = DD *olddir
a1 = DD *newdir
d0 = char *oldname
d1 = char *newname
d2 = int flag_link
-> d0 = long errcode
Description: xfs_link is used both for Frename (d2 = 0) and also for Flink (d2 = 1). In the case of Frename a new directory entry has to be created and the old entry (reference to the file) deleted or overwritten.

In the case of Flink a further reference to the same file is created and the old entry is not deleted. Both DDs always lie in the same filesystem, so have the same DMD. As for Fdelete, in the case of a symbolic link this has to be renamed or a further link created. This means that an ELINK return value is impermissible here (as for xfs_fdelete).

Flinkis not supported by the DOS_XFS.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.23 xfs_name

Name: »xfs_name« - Name of the filesystem.
Parameters:
Description: The name is up till now just a comment; perhaps in the future it may offer the possibility of ascertaining which drivers are installed and what, say, the driver responsible for drive A: is called (i.e. what sort of filesystem the floppy disk contains).

The name of the integrated XFS is 'DOS_XFS ' (extended to 8 characters with a space).
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.24 xfs_next

Name: »xfs_next« - Next driver.
Parameters:
Description: xfs_next is simply a chaining pointer to the next driver. A new driver is always incorporated at the front, so always has the highest priority. This makes it possible to load a driver in place of the intergated DOS driver, for instance.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.25 xfs_path2DD

Name: »xfs_path2DD« - Return a directory descriptor (DD) to a pathname.
Parameters:
mode = 0: The name is a file
= 1: The name is itself a directory
d0 = int mode
a0 = DD *reldir current directory
a1 = char *pathname
-> d0 = DD *
d1 = char *restpfad
oder  
-> d0 = ELINK
d1 = Restpath without leading '\'
a0 = FD of the path in which the symbolic link lies; this is important for relative path specifications in the link
a1 = NULL, the path represents the parent of the root directory
oder  
a1 = Path of the symbolic link
Description: The kernel differentiates between two different types of descriptors, file descriptors (FD) and directory descriptors (DD), which can have an identical structure however. The xfs_path2DD function returns a descriptor for a path.
The reference counter of the DD must be incremented by 1 each time it is returned as a function value, as it is referenced by the kernel. The xfs_path2DD function corresponds to an 'opening' of the path; a kind of 'file handle' is returned to the kernel, which the kernel has to close again. The parsing of the path must always be taken care of by the XFS.

Input parameters:
Determines whether the last path element is itself a directory (mode == 1), or whether the path is to be obtained in which this file lies
Directory from which the search is to start
The pathname, without drive letter and without leading '\'


Output parameters:

1st case: An error has arisen

d0 contains the error-code

2nd case: A directory descriptor (DD) could not be obtained
Pointer to the DD; the XFS has incremented the reference counter of the DD by 1
Pointer to the remaining filenames without leading '\' or '/'; if the end of the path was reached, this pointer points to the terminating NULL-byte


3rd case: The XFS hit on a symbolic link during the )path evaluation
Contains the internal MagiC error-code ELINK
Pointer to the remaining path without the leading '\' or '/'
Contains the DD of the path in which the symbolic link lies; the XFS has incremented the reference counter of the DD by 1
This is the pointer to the link itself; a link starts with a WORD (16 bits) for the length of the path, followed by the path itself


Warning: The length must include the terminating NULL-byte and also be even. The link has to lie at an even memory address.

The buffer for the link may be static or volatile since the kernel immediately copies the data elsewhere, with no possibility of a context change happening inbetween.

If a1 == NULL is passed, a signal is sent to the kernel that the parent of the root directory was selected. If the path resides, say, on U:\A, then the kernel can fall back to U:\. The value of the return register a0 is ignored by the kernel, so no reference counter may be incremented.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.26 xfs_pterm

Name: »xfs_pterm« - Notify a program termination.
Parameters:
a0 = PD *
-> void
Description: The call xfs_pterm is made at every program termination and gives the XFS the opportunity to release internal structures or remove locks. The files visible to the kernel (i.e. those that are assigned a handle) are closed by the kernel beforehand. The reference counter for the standard directories is likewise decremented beforehand by the kernel.

A pointer to a process descriptor is passed in a0.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.27 xfs_readlink

Name: »xfs_readlink« - Read a symbolic link.
Parameters:
a0 = DD *
a1 = char *name
d0 = char *buf
d1 = int size
-> d0 = long errcode
Description: xfs_readlink is used for Freadlink. It is supported by DOS_XFS.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.28 xfs_rlabel

Name: »xfs_rlabel« - liest den Disknamen.
Parameters:
a0 = DD *
a1 = char *name
d0 = char *buf
d1 = int len
-> d0 = long errcode
Description: xfs_rlabel serves for reading the medium name. It is called by the kernel when Fsfirst with attribute == 8 is performed. name is generally "*.*" and can be ignored. len is the length of the buffer buf; on overflow ERANGE must be returned.
xfs_rlabel is also called for Dreadlabel. In this case name == NULL.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.29 xfs_sfirst

Name: »xfs_sfirst« - Search for first matching file.
Parameters:
a0 = DD * srchdir
a1 = char *name (ohne Pfad)
d0 = DTA *
d1 = int attrib
-> d0 = long errcode
-> a0 = SYMLINK * (or Symlink if appropriate)
Description: xfs_sfirst is required for Fsfirst. MiNT uses instead of this function a combination of Dreaddir and Fxattr, which however makes very many calls of the XFS driver necessary. The reserved area of the DTA can be used freely by the XFS; if this is too small, one has to proceed with similar heuristic methods to MiNT, i.e. pointers must be entered in the DTA that point to fixed descriptors.

These descriptors however can be released again only with heuristic methods, because one never knows whether another Fsnext is coming or not. The kernel already gets the complete path with xfs_path2DD, so that only the pure pathname is passed in a1. As with all DOS calls that process a path, the XFS must ensure that the DD is protected for the duration of the processing. This is particularly critical if the filesystem is reentrant.

If a file searched for is a symbolic link, then one has to pass ELINK as error-code in d0 and the pointer to the link in a0. The kernel then simply calls Fxattr} to fill the DTA. If a disk media change has occurred, then E_CHNG is to be returned; the kernel then automatically repeats the function. This also applies for all other functions.

In every case xfs_dta_drive has to be initialized correctly, e.g. with:
dta.dta_drive = srchdir->dd_dmd->d_drive. If E_OK or ELINK is returned without xfs_dta_drive being initialized, then the result is indeterminate.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.30 xfs_snext

Name: »xfs_snext« - Search for the next matching file.
Parameters:
a0 = DTA *
a1 = DMD *
-> d0 = long errcode,
-> a0 = SYMLINK * (Symlink)
Description: xfs_snext is required for Fsnext. The kernel has already obtained from the DTA the relevant filesystem whose DMD is passed in a1. Here too a symbolic link may occur.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.31 xfs_symlink

Name: »xfs_symlink« - Create a symbolic link.
Parameters:
a0 = DD * dir
a1 = char *name
d0 = char *to
-> d0 = long errcode
Description: xfs_symlink is required for Fsymlink. A file has to be created under the new name name in the directory dir that points to the file to. The call is supported by DOS_XFS.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.32 xfs_sync

Name: »xfs_sync« - Synchronize the filesystem.
Parameters:
a0 = DMD *d
-> long errcode
Description: The kernel notifies the XFS that on drive d all the buffers have been written back. Passed in register a0 is a pointer to a DMD (drive medium descriptor). This is created by the kernel.

The return value will be an error-code. If the DFS does not manage the buffer (e.g. a RAMdisk), then a 0 has to be returned. The internal DOS_XFS simply calls the DFS function with the same name.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.33 xfs_wlabel

Name: »xfs_wlabel« - Write the disk name.
Parameters:
a0 = DD *
a1 = char *name
-> d0 = long errcode
Description: xfs_wlabel serves for (re)naming media. It is called by the kernel when Fcreate with attribute 8 is performed. If the disk name is stored as a special file, as for the DOS filesystem, then all other path-based XFS functions have to ignore the disk name.

An empty name, or one consisting of '0xe5' (for TOS compatibility) must delete the disk name (provided that media without names are allowable). xfs_wlabel is also called for Dwritelabel.
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.2.34 xfs_xattr

Name: »xfs_xattr« - Required for Fxattr.
Parameters:
a0 = DD *
a1 = char *name
d0 = XATTR *
d1 = int mode
-> d0 = long errcode
-> a0 = SYMLINK *
Description: xfs_xattr is used for Fxattr. In the case mode == 0 (i.e. follow symbolic links) one can return ELINK in d0 and a link in a0, else ELINK is inadmissible.
mode == 0: Follow symbolic links (or return ELINK if appropriate)
== 1: Do not follow (i.e. creale XATTR for the link)
Group: Make-up of an XFS
See also: MagiC's XFS-concept

11.21.3 Data structures for an XFS

When working with an XFS the following data structures are important:

DD (Directory descriptor)
DHD (Directory handle descriptor)
DMD (Drive medium descriptor)
DTA (Disk transfer area)
FD (File descriptor)
MX_DEV (Device driver)

See also: DFS structures   MagiC's XFS-concept

11.21.3.1 The directory descriptor (DD)

The directory descriptors must be created and managed by the XFS. All descriptors that are known to the kernel (i.e. those that are used as a standard path for a process) have a non-zero reference counter. The only exception is the DD for the root directory of a drive; here the reference counter is always 0, irrespective of whether a process has the root directory as a standard directory or not.

For the kernel a DD looks like the following; these entries have to be created by the XFS:

dd_dmd:      DS.L      1    /* 0x00: Pointer to DMD                  */
dd_refcnt:   DS.W      1    /* 0x04: Ref. counter for standard paths */

See also: MagiC's XFS-concept

11.21.3.1.1 dd_dmd

The associated filesystem is found here.

11.21.3.1.2 dd_refcnt

The reference counter. dd_refcnt is used only by the kernel, has to be initialized to 0 by the XFS on creation of a DD (for the root better to 1, see above for xfs_drv_open) and incremented by 1 at each handing over to the kernel (-> xfs_path2DD).

This means that on returning a new DD (which is thus not otherwise referenced by the kernel) xfs_path2DD must set the reference counter to 1.

If the reference counter is non-zero, the kernel has a pointer to this DD and it may in no way be released by the XFS. The kernel decrements the reference counter by 1 each time it no longer requires a DD. If the counter reaches 0 during this, then xfs_freeDD is called. The XFS can then release the DD, or else only at a call of xfs_garbcoll (the garbage collection) or at xfs_drv_close.

Warning: The root may not be released during the lifetime of the mounted filesystem. The root's reference counter should be preset to 1 to prevent it being released with xfs_freeDD.

See also: MagiC's XFS-concept   Data structures for an XFS

11.21.3.2 The directory handle descriptor (DHD)

The directory handles are required for Dopendir/Dclosedir/Drewinddir. Unlike the file descriptors (FDs) the kernel does not hold a list of opened directory handles (DH). When a process terminates, the XFS is called via the function xfs_pterm and must release all DHs created for the process.

The XFS can obtain the owner of a DH with the kernel pointer act_pd. For the kernel a DH looks like the following; these entries have to be created by the XFS:

dhd_dmd:  DS.L   1   /* 0x00: Pointer to DMD  */

See also: MagiC's XFS-concept   DMD

11.21.3.2.1 dhd_dmd

The associated filesystem is found here.

11.21.3.3 The Drive Medium Descriptor (DMD)

The DMD is created by the kernel (!) for each opened drive and also released again if necessary. The XFS stores all data here that it has to memorize for the drive. The following fields are the ones that the kernel requires (the ancestor object from which the XFS derives its XFS-DMD):

d_xfs:      DS.L   1    /* 0x00: The filesystem driver            */
d_drive:    DS.W   1    /* 0x04: Drive number 0..25               */
d_root:     DS.L   1    /* 0x06: Pointer to DD of the root        */
d_biosdev:  DS.W   1    /* 0x0a: BIOS drive, or -1                */
d_driver:   DS.L   1    /* 0x0c: With devcode, defines the medium */
d_devcode:  DS.L   1    /* 0x10: e.g. SCSI target and drive       */
d_dfs:      DS.L   1    /* 0x14: DOS-specific filesystem driver   */

Other XFSs or DFSs enter further data into the DMD. One can envisage the DMD as an object class. A DMD derived for the DOS_XFS only has the additional entry d_dfs. The FAT enters extra data such as the cluster size and the number of sectors.

See also: MagiC's XFS-concept   DD

11.21.3.3.1 d_xfs

The associated filesystem driver (XFS) is found here. It is entered by xfs_drv_open.

11.21.3.3.2 d_drive

d_drive specifies which logical drive ('A' .. 'Z') the filesystem is assigned to. This does not always have to correspond to a BIOS drive. This value is always(!) entered by the kernel when a drive is opened, before an XFS is entered.

11.21.3.3.3 d_root

A pointer to the DD of the root directory can be found here.

11.21.3.3.4 d_biosdev

If dealing with a partition that is handled by BIOS's Rwabs, then the BIOS device number will be found here. Else -1 must be entered here (e.g. for drive U: or a Macintosh partition).

11.21.3.3.5 d_driver

Together with d_devcode, this determines the medium. That means that if d_driver and d_devcode are identical, both drives lie on the same medium, and if the medium is to be ejected then both filesystems have to be locked. With a hard disk partition, d_biosdev is the BIOS drive, d_driver is arbitrary (e.g. pointer to the XHDI structure), d_devcode is the XHDI code of a medium, i.e. SCSI target and device number (one WORD in each case).

11.21.3.3.6 d_devcode

Together with d_driver, this determines the medium. That means that if d_driver and d_devcode are identical, both drives lie on the same medium, and if the medium is to be ejected then both filesystems have to be locked. With a hard disk partition, d_biosdev is the BIOS drive, d_driver is arbitrary (e.g. pointer to the XHDI structure), d_devcode is the XHDI code of a medium, i.e. SCSI target and device number (one WORD in each case).

11.21.3.3.7 d_dfs

This entry is mandatory only for DOS filesystems (i.e. already for a derived object) and contains a pointer to the DFS subdriver.

11.21.3.4 The Disk Transfer Area (DTA) for XFSs

The DTA is used by the old DOS functions Fsfirst and Fsnext, whose clumsy conception by the MS-DOS originators still weighs down the system like a curse. For the kernel the structure looks as follows:

dta_res1:        DS.B    20    /* 0x00: Not used by the kernel   */
dta_drive:       DS.B     1    /* 0x14: Logical drive            */
dta_attribute:   DS.B     1    /* 0x15: Found attribute          */
dta_time:        DS.W     1    /* 0x16: Found time               */
dta_date:        DS.W     1    /* 0x18: Found date               */
dta_len:         DS.L     1    /* 0x1a: Found length             */
dta_name:        DS.B    14    /* 0x1e: Found filename           */

Note: The components dta_attribute to dta_name represent the documented user area; this has to be handled according to GEMDOS specifications.

See also: MagiC's XFS-concept

11.21.3.4.1 xfs_dta_res1

dta_res1 (from XFS) is not used by the kernel. Here the XFS may muck about.

11.21.3.4.2 xfs_dta_drive

xfs_dta_drive contains the associated logical drive (0 corresponds to drive A: etc). With this information the kernel can decide at Fsnext which XFS has to perform the task.

11.21.3.5 The File Descriptor (FD)

The file descriptors must be created and managed by the XFS. All the descriptors that are known to the kernel have a non-zero reference counter. For the kernel an FD looks exactly like a DD, which is why the same data structure is used in the DOS_XFS.

For the kernel an FD looks like the following; these entries have to be created by the XFS:

fd_dmd:      DS.L    1   /* 0x00: Pointer to DMD                       */
fd_refcnt:   DS.W    1   /* 0x04: Reference counter for closing, or -1 */
fd_mode:     DS.W    1   /* 0x06: Open-mode and flags                  */
fd_dev:      DS.L    1   /* 0x08: Pointer to MX_DEV                    */

The class derived from DOS_XFS (a 'DOS-FD') also has the additional fields:

fd_ddev:     DS.L    1    /* 0x0c: Pointer to MX_DDEV                  */
fd_name:     DS.B   11    /* 0x10: DD_FD: Name in internal format      */
fd_attr:     DS.B    1    /* 0x1b: Attribute                           */
fd_owner:    DS.L    1    /* 0x1c: DD_FD: Owner of an FD, or NULL      */
fd_parent:   DS.L    1    /* 0x20: Pointer to the parent DD_FD         */
fd_children: DS.L    1    /* 0x24: DD_FD: List of all children         */
fd_next:     DS.L    1    /* 0x28: Pointer to FDs im same directory    */
fd_multi:    DS.L    1    /* 0x2c: Pointer to FD of the same file      */
fd_multi1:   DS.L    1    /* 0x30: Pointer to first list element       */
fd_fpos:     DS.L    1    /* 0x34: Position of the file pointer        */
fd_dirch:    DS.B    1    /* 0x38: Bit0: 'dirty'                       */
fd_unused:   DS.B    1    /* 0x39: Not used                            */
fd_time:     DS.W    1    /* 0x3a: Time  (8086)                        */
fd_date:     DS.W    1    /* 0x3c: Date (8086)                         */
fd_stcl:     DS.W    1    /* 0x3e: Starting cluster                    */
fd_len:      DS.L    1    /* 0x40: File length in bytes                */
fd_dirpos:   DS.L    1    /* 0x44: Pos. of matching entry in directory */
fd_user1:    DS.L    1    /* 0x48: Available for user allocation       */
fd_user2:    DS.L    1    /* 0x4c: Available for user allocation       */

See also: MagiC's XFS-concept   DMD   MX_DDEV   MX_DEV

11.21.3.5.1 fd_dmd

fd_dmd contains a pointer to the associated filesystem.

11.21.3.5.2 fd_refcnt

The reference counter. This entry is used only by the kernel, has to be decremented by 1 at each dev_close call and initialized (to 1) by xfs_fopen.

A reference counter of -1 signals that the FD may never be released. This is necessary for, say, the device files U:\DEV\CON, U:\DEV\AUX etc. that are always available.

11.21.3.5.3 fd_mode

fd_mode contains the mode, as described for xfs_fopen. If two FDs point to the same file, then the modes have to be compatible. Thanks to the simple MagiC-internal mode notation, a plain rotation and ANDing of the bits is sufficient, e.g.:

  move.w   fd_mode(a0),d1
  btst     #BOM_NOCHECK,d1  ; No check by the XFS?
  bne.b    _opf_nxt         ; Yes, ddev_open checks
  ror.b    #4,d1
  and.b    d0,d1
  bne      opd_eaccdn       ; Conflict: return(EACCDN)
11.21.3.5.4 fd_dev

fd_dev is the pointer to the device driver.

11.21.3.5.5 fd_ddev

Here the DFS has to enter the MX_DDEV (i.e. the device driver) at a dfs_dir2FD call.

11.21.3.5.6 fd_name

Here the name (8+3) is stored in an internal format. The name is valid only when it refers to a subdirectory, and only in a prototype FD, i.e. in fd_multi1. The name of the root is an empty character string.

11.21.3.5.7 fd_attr

Here the file attribute is stored. This is valid only in a prototype FD, i.e. in fd_multi1. From the attribute one can recognize whether the FD represents a directory.

11.21.3.5.8 fd_owner

Here a pointer to the owner of an FD is stored (i.e. a pointer to the basepage). A value of NULL signifies that the FD is not allocated at present.

11.21.3.5.9 fd_parent

This is a chaining pointer to the parent, i.e. to the directory in which the file lies, or the parent directory of a subdirectory. fd_parent is valid only for the prototype FD.

11.21.3.5.10 fd_children

This is a list of all opened files and opened subdirecories. fd_children is valid only for the prototype FD.

11.21.3.5.11 fd_next

This is a pointer to the next FD in the same directory, i.e. the next sibling; this can be an opened file or a subdirectory - in principle these are not differentiated.
fd_next is valid only for the prototype FD.

11.21.3.5.12 fd_multi

If a file is opened several times, then a 'clone' of the prototype FD is created. Most of the FD fields are invalid for this clone; in essence only driver, mode and file position are valid. fd_multi is a chained list, wich is NULL-terminated.

11.21.3.5.13 fd_multi1

This is the associated prototype FD that contains the valid file data. If a file is only opened once, then: fd->fd_multi1 == fd.

11.21.3.5.14 fd_fpos

fd_fpos is the position of the file pointer; it is 0L for a device.

11.21.3.5.15 fd_dirch

Bit 0 of fd_dirch indicates whether a file has been altered and hence on closing the file the directory (fd_parent) has to be updated (does not happen when dealing with a folder). The other bits are reserved and are used in part by the DOS_XFS.

11.21.3.5.16 fd_unused

Unused and reserved.

11.21.3.5.17 fd_time

fd_time is the time of day from the directory entry in Intel format.

11.21.3.5.18 fd_date

fd_date is the date from the directory entry in Intel format.

11.21.3.5.19 fd_stcl

fd_stcl is the starting cluster in Motorola format.

11.21.3.5.20 fd_len

fd_len is the file length in bytes in Motorola format.

11.21.3.5.21 fd_dirpos

fd_dirpos is the position of the associated entry in the parent. It is valid only for the prototype FD.

11.21.3.5.22 fd_user1

Together with fd_user2, 2 LONGwords available for free allocation by the user. The FAT_DFS stores here additional information for fd_fpos, namely the current cluster. Other DFSs can store other data. These fields are valid initially only for the prototype FD, except that on opening (ddev_open) the data are copied explicitly from the prototype FD into the clone.

11.21.3.5.23 fd_user2

Together with fd_user1, 2 LONGwords available for free allocation by the user. The FAT_DFS stores here additional information for fd_fpos, namely the current cluster. Other DFSs can store other data. These fields are valid initially only for the prototype FD, except that on opening (ddev_open) the data are copied explicitly from the prototype FD into the clone.

11.21.3.6 The device driver (MX_DEV)

The device driver is inserted by the XFS into the file descriptor at the opening of a file, and called directly by the kernel. The device driver must make the following functions available:

typedef struct _mx_dev
{
  LONG  (*dev_close)();
  LONG  (*dev_read)();
  LONG  (*dev_write)();
  LONG  (*dev_stat)();
  LONG  (*dev_seek)();
  LONG  (*dev_datime)();
  LONG  (*dev_ioctl)();
  LONG  (*dev_getc)();
  LONG  (*dev_getline)();
  LONG  (*dev_putc)();
} MX_DEV;

See also: MagiC's XFS-concept

11.21.3.6.1 dev_close
Name: »dev_close«
Parameters:
a0 = FD *file
-> d0 = long errcode
Description: If fd_refcnt is not 0 already, fd_refcnt must be decremented (this must be accomplished by the MX_DEV). On this occasion any buffers that may be present should be written back and directory entries updated. If fd_refcnt is 0, the FD can be released. At a disk media change fd_refcnt is already 0 at a dev_close call, i.e. the FD just needs to be released.

The file driver installed by DOS_XFS writes back the directory data and then calls the MX_DDEV subdriver.
Group: Workstation driver
See also:
11.21.3.6.2 dev_datime

For Fdatime. The file driver installed by DOS_XFS passes the call on to the MX_DDEV subdriver, if the function is supported in the MX_DDEV driver (pointer != NULL), otherwise the function will be performed automatically with the help of the FD data.

Parameters:

a0 = FD *file
a1 = int d[2]
d0 = int setflag
-> d0 = long errcode
11.21.3.6.3 dev_getc
Name: »dev_getc«
Parameters:
a0 = FD *file
d0 = int mode
-> d0 = unsigned long c
Description: dev_getc is used by the kernel for Fgetchar and the character-oriented functions (Cconin, Cconout, Cauxin etc.). In the case of a device, the return value may be a LONGword (e.g. for CON having the scancode of the key in the high-WORD), else a byte (always extended to 'unsigned'). At EOF, 0x0000FF1A must be returned.

mode means:
CMODE_COOKED (1) Bit 0 set: Control characters ^C, ^S, ^Q will be processed
CMODE_RAW (0) Bit 0 not set: 'raw' mode
CMODE_ECHO (2) Bit 1 set: Input will be echoed


The file driver installed by DOS_XFS passes the call on to the MX_DDEV subdriver if the function is supported in the MX_DDEV driver (pointer != NULL), otherwise the function is implemented automatically as dev_fread.
Group: Workstation driver
See also:
11.21.3.6.4 dev_getline

For line-oriented input. mode as in dev_getc. The return will be the number of characters input without terminatng characters or similar. The file driver installed by DOS_XFS passes the dev_getline call on to the MX_DDEV subdriver if the function is supported in the MX_DDEV driver (pointer != NULL); otherwise the function is implemented auto matically as dev_fread. The line is then terminated with CR and LF;

Parameters:

a0 = FD *file
a1 = char *buf
d1 = long size
d0 = int mode
-> d0 = long amount
11.21.3.6.5 dev_ioctl

For Fcntl. The file driver installed by DOS_XFS passes the dev_ioctl call directly to the MX_DDEV subdriver. Only the following functions are handled however: FSTAT and FUTIME. These should also be executed by other XFSs. Every file driver should support FIONREAD and FIONWRITE.

Parameters:

a0 = FD *file
d0 = int cmd
a1 = void *buf
-> d0 = long errcode
11.21.3.6.6 dev_putc
Name: »dev_putc«
Parameters:
a0 = FD *file
d0 = int mode
d1 = long value
-> d0 = unsigned long count
Description: dev_putc is used by the kernel for Fgetchar and the character-oriented functions (Cconin, Cconout, Cauxin etc.). In the case of a terminal the return value must be 4L (i.e. 4 bytes written), otherwises 1L if writing was successful.

mode means:
CMODE_COOKED (1) Bit 0 set: Control characters ^C, ^S, ^Q will be processed
CMODE_RAW (0) Bit 0 not set: 'raw' mode


The file driver installed by DOS_XFS passes the call on to the MX_DDEV subdriver if the function is supported in the MX_DDEV driver (pointer != NULL), otherwise the function is automatically implemented as dev_fwrite.
Group: Workstation driver
See also:
11.21.3.6.7 dev_read

From the file file, count bytes are read into the buffer buffer. The return is the number of characters actually read. The file driver installed by DOS_XFS passes the dev_read call directly to the MX_DDEV subdriver.

Parameters:

a0 = FD *file
d0 = long count
a1 = char *buffer
-> d0 = long amount
11.21.3.6.8 dev_seek

For Fseek. mode is, as in TOS, 0, 1 or 2. The return value will be the current position of the write/read pointer; device drivers must always return a 0L here. The file driver installed by DOS_XFS passes the dev_seek call directly to the MX_DDEV subdriver.

Parameters:

a0 = FD *file
d0 = long where
d1 = int mode
-> d0 = long position
11.21.3.6.9 dev_stat
Name: »dev_stat«
Parameters:
a0 = FD *file
a1 = MAGX_UNSEL *unselect oder NULL
d0 = int rwflag
d1 = long apcode
-> d0 = long status
Description: dev_stat specifies the read/write status of the file. It is called for Fselect (or for Cconos/Cconis etc.) for instance. In contrast to MiNT, it is left to the driver here whether it is interrupt-capable or not, i.e. whether it is able to call a waiting application in interrupt again or not. rwflag specifies whether the write or read status is inquired for.

unselect is either NULL or a pointer to the following structure:
typedef struct
{
   union
   {
      void (*unsel) (MAGX_UNSEL *un);
      long status;
   }
   long param;
} MAGX_UNSEL;


Procedure:

Generally the following applies: If unselect is non-0, the return value must be returned not only as the function result (in d0.L) but also in unselect->status. This applies for all kinds of return values. One can optionally store a parameter in unsel->param.

If apcode == NULL, polling will be performed, i.e. the application is not put to sleep. So the return will be:

0 = Not ready, 1 = Ready, <0 = Error.

If apcode ! = NULL (then unselect != NULL as well) then the return will be:
<0 Error
0 Not ready, device can only be polled
1 Ready
>0 Perhaps a pointer to a function that deinstalls the awakening interrupt again (corresonds more or less to unselect in MiNT)


If the device is not ready and is interrupt-capable, then one proceeds as follows:
  1. Initialize unselect with the address of the clean-up routine and an optional parameter; prototype on the lines of:
    void unselect( a0 = MAGX_UNSEL *un,a1 = void *ap_code );
    
  2. Install interrupt for awakening, pass it unselect (and with it also the optional parameter) and appl
  3. Return pointer to the clean-up routine in d0


The interrupt routine does the following:
  1. The interrupt arrives
  2. unselect->status has 1 (OK) or < 0 (not OK) written to it and the interrupt is deactivated! The application is awakened with:
    kernel->appl_IOcomplete( a0 = APPL *ap );
    


The clean-up routine does the following:
  1. The interrupt is deactivated.
  2. If it has not happened already, unsel->status will have a 1 (arrived) or a 0 (not arrived) or < 0 (error) entered into it. One must ensure that no IOcomplete and no write access to unsel can follow subsequently. A value that is not 1 but greater than zero is always interpreted as the address of the clean-up routine; this still has to be called if the interrupt has not arrived. If the interrupt entered a value of 2L, say, the kernel would assume that the interrupt has not arrived and that the address of the clean-up routine is still contained in the MAGX_UNSEL structure. A jump to address 2 however is then deadly rather quickly!


The DOS functions Finstat and Foutstat at first attempt to execute the call as Fcntl} (FIONREAD or FIONWRITE). If this subfunction of dev_ioctl does not exist (the file driver has to return EINVFN!), then dev_stat is called. In that case one can state either that a 'character is available' (value == 1) or 'no character is available' (value == 0).

The file driver installed by DOS_XFS passes on the call directly to the MX_DDEV subdriver.
Group: Workstation driver
See also:
11.21.3.6.10 dev_write

To the file file, count bytes are written from the buffer buffer. The return is the number of characters actually written. The file driver installed by DOS_XFS updates the date/timestamp of the file and then passes the dev_write call to the MX_DDEV subdriver.

Parameters:

a0 = FD *file
d0 = long count
a1 = char *buffer
-> d0 = long amount

11.21.4 Installation of an XFS

An XFS is just a program that installs the driver and then terminates itself resident. The installation is performed with:
kernel = Dcntl(KER_INSTXFS, NULL, &myxfs).

The return is a pointer to important kernel functions, or an error- code. The kernel functions can also be inquired for independently of the installation of an XFS, namely with: kernel = Dcntl(KER_GETINFO, NULL, NULL).

The deinstallation of an XFS is not provided for.

11.21.5 Kernel functions for an XFS

MagiCmakes available to the installed XFSs, DFSs or device drivers some kernel information as well as kernel functions. The same register conventions apply for the kernel functions as for the XFS functions, i.e. d0-d2 and a0-a2 may be destroyed. One can obtain a pointer to the structure that contains the kernel functions with:

     kernel = Dcntl (KER_INSTXFS, NULL, &myxfs);   or
     kernel = Dcntl (KER_GETINFO, NULL, NULL);

In the first case an XFS is installed, in the second case one only gets the kernel structure (perhaps for a DFS or a device driver). The build-up of the kernel structure in detail:

typedef struct
{
  WORD   mxk_version;
  VOID (*mxk_fast_clrmem)      ( void *von, void *bis );
  BYTE (*mxk_toupper)          ( char c );
  VOID (*mxk__sprintf)         ( char *dest, char *source, LONG *p );
  VOID  *mxk_mxk_act_pd;
  APPL  *mxk_act_appl;
  APPL  *mxk_keyb_app;
  WORD  *mxk_pe_slice;
  WORD  *mxk_pe_timer;
  VOID (*mxk_appl_yield)       ( void );
  VOID (*mxk_appl_suspend)     ( void );
  VOID (*mxk_appl_begcritic)   ( void );
  VOID (*mxk_appl_endcritic)   ( void );
  LONG (*mxk_evnt_IO)          ( LONG ticks_50hz, void *unsel );
  VOID (*mxk_evnt_mIO)         ( LONG ticks_50hz, void *unsel, WORD cnt );
  VOID (*mxk_evnt_emIO)        ( APPL *ap );
  VOID (*mxk_appl_IOcomplete)  ( APPL *ap );
  LONG (*mxk_evnt_sem)         ( WORD mode, void *sem, LONG timeout );
  VOID (*mxk_Pfree)            ( void *pd );
  WORD   mxk_int_msize;
  VOID  *mxk_int_malloc        ( void );
  VOID   mxk_int_mfree         ( void *memblk );
  VOID   mxk_resv_intmem       ( void *mem, LONG bytes );
  LONG   mxk_diskchange        ( WORD drv );
  LONG   mxk_DMD_rdevinit      ( DMD *dmd );
  LONG   mxk_proc_info         ( WORD code, PD *pd );
  LONG   mxk_mxalloc           ( d0 = LONG amount, d1 = WORD mode, a0 = PD *pd );
  LONG   mxk_mfree             ( a0 = void *block );
  LONG   mxk_mshrink           ( d0 = LONG newlen, a0 = void *block );
} MX_KERNEL;

See also: MagiC's XFS-concept

11.21.5.1 mxk_version

mxk_version is the version number, which is simply 3 at present. For each change of the kernel structure the version number is increased, so that programs may adapt themselves accordingly.

11.21.5.2 mxk_fast_clrmem

mxk_fast_clrmem is a fast memory clearance routine, which sets the memory block between from and to (exclusive) to 0.

The following apply for this:

a0 = void *from
a1 = void *to

11.21.5.3 mxk_toupper

mxk_toupper converts the character c to upper case, respecting the national special characters (accents, umlauts etc.).

The following apply for this:

d0 = char c

11.21.5.4 mxk__sprintf

mxk__sprintf is a function that expects its arguments on the stack. Items to pass are the destination character string dest, the template source and the values to be entered p[]. Depending on the formatting statement, the LONGwords are interpreted as 'unsigned int' (%W), 'signed long' (%L) or character string (%S).

With %W the WORD lying further down in memory is used, the sequence %% inserts a 'percent' character.

11.21.5.5 mxk_act_pd

mxk_act_pd is the pointer to the current basepage; the address can be obtained also from the system header or the DOS variables.

11.21.5.6 mxk_act_appl

mxk_act_appl is a pointer to the current application (i.e. the running task). The build-up of the structure is not documented. Due to faster access, the pointer is used as the descriptor in place of the ap_id.

11.21.5.7 mxk_keyb_app

mxk_keyb_app is the pointer to the application that currently 'owns' the keyboard. The pointer can be used by device drivers that have to process the keyboard-owning application in a different way, for instance.

11.21.5.8 mxk_pe_slice

mxk_pe_slice is used for preemptive multitasking. If *pe_slice == -1 then preemptive multitasking is switched off, and disk accesses are not interrupted.

11.21.5.9 mxk_pe_timer

mxk_pe_timer is used for preemptive multitasking. If *pe_slice == -1 then preemptive multitasking is switched off, and disk accesses are not interrupted.

11.21.5.10 mxk_appl_yield

mxk_appl_yield allocates CPU time to the system. It is important for drivers that cannot wait for an interrupt and have to prevent that their 'busy waiting' paralyses the system.

11.21.5.11 mxk_appl_suspend

mxk_appl_suspend works like appl_yield, though it allocates a lower priority to the application, perhaps as a background process.

11.21.5.12 mxk_appl_begcritic

mxk_appl_begcritic signals that the current application has entered a critical phase and may not be terminated.

11.21.5.13 mxk_appl_endcritic

mxk_appl_endcritic signals the end of the critical phase for the current application. If a termination command has arrived in the meantime then the program will be terminated.

11.21.5.14 mxk_evnt_IO

Name: »evnt_IO«
Parameters:
d0 = long ticks_50hz
a0 = void *unsel
Description: mxk_evnt_IO makes it possible to wait for one external event. The external event in question is either an interrupt or another application (which perhaps writes to a pipe for awakening). The function is used for the creation of device drivers:

Procedure (see DEV_LPT1 as an example):
  1. Block interrupts.
  2. Inquire whether the event (in the case of DEV_LPT1 the event is called: 'Centronics busy off') has arrived.
  3. If so, free interrupts and perform the action (in the case of DEV_LPT1: print character).
  4. If not, set up interrupt routine (in the case of DEV_LPT1: MFP-I0, i.e. 'Activate Centronics busy interrupt') and make available to it the current application (act_appl) and also a LONGword address into which the interrupt routine can write return messages. This address should have written to it the address of a routine that deinstalls the interrupt again, and can be followed by some user requirements. i.e. some further data. The unselect routine later gets a pointer to all this data and can evaluate the optional parameters for instance. The whole mechanism is required to guarantee a corrrect deinitialization of the interrupt in each case.
  5. Release interrupts.
  6. Call evnt_IO. In d0.w specify the number of 50Hz ticks for the timeout; 0 means 'no timeout'. In a0 give the address of the LONGword containing the address of the clean-up routine that deinstalls the interrupt again (which is followed by optional further parameters, provided the unselect routine understands these). In the case of incorporation of device drivers for Fselect, only one optional LONGword is possible.
    On arrival of the interrupt, the interrupt routine writes a status < 0L (error) or 1L (OK) in place of the deinitialization routine into the status LONGword (which previously contained its own start address). Following this the routine will deinstall itself or make sure that no actions are performed on following interrupts. Finally the interrupt routine awakens the application assigned to the interrupt, using the call appl_IOcomplete with the application as parameter.
  7. evnt_IO returns either the value 0L (timeout, the interrupt has not arrived) or < 0 (the interrupt has written an error-code to the status LONGword) or 1L (the interrupt has written a 1L into the status LONGword). Deinstallation of the interrupt is no longer required as the kernel has taken care of this if the interrupt routine did not do this itself on arrival of the interrupt.
Group: Kernel functions
See also:

11.21.5.15 mxk_evnt_mIO

Name: »evnt_mIO«
Parameters:
d0 = long ticks_50hz
a0 = void *unsel
d1 = int cnt


or
a0 = APPL *ap
Description: mxk_evnt_mIO makes it possible to wait for several external events; this function is used by Fselect (several files!) for instance.

Procedure:
  1. Create a LONGword table for n events with a length of 2*n.
  2. Enter the clean-up routine (unselect routine) for each event (followed by an optional LONGword parameter) and set up the interrupt. The order is important: one must prevent the unselect address overwriting the return value of an already arrived interrupt - if necessary block interrupts.
  3. Call evnt_mIO. The parameters are the same as in evnt_IO: in d1.w the number of events is passed, a0 is the start of the table.
  4. evnt_mIO offers no return value. The table must be searched through and the interrupts deinstalled (e.g. call the unselect routines); during this one can check which interrupts have arrived already.
  5. Call evnt_emIO with the current application. This call ensures that after deinstallation of all the interrupts their now useless messages to the application are deleted.


Applications waiting for evnt_(m)IO events appear in the program manager as waiting for 'io' (input/output) or 'io ti' (input/output with timeout).
Group: Kernel functions
See also:

11.21.5.16 mxk_appl_IOcomplete

mxk_appl_IOcomplete wakes up an application that is waiting for evnt_(m)IO.

The following apply for this:

a0 = APPL *ap

11.21.5.17 mxk_evnt_sem

Name: »evnt_sem«
Parameters:
d0 = int mode
a0 = void *sem
d1 = long timeout
Description: mxk_evnt_sem is used for controlling semaphores. The following subfunctions are possible for mode:
0 SEM_FREE Release semaphore (without task-switching!)
1 SEM_SET Set semaphore, wait if necessary
2 SEM_TEST Obtain owner of semaphore (if necessary NULL)
3 SEM_CSET Set semaphore, if not set already
4 SEM_GET Get semaphore if name is known
5 SEM_CREATE Create semaphore, i.e. establish new one
6 SEM_DEL Remove semaphore


SEM_SET and SEM_CSET are the only subfunctions that can initiate a task-switch.

In contrast to wind_update, the setting and releasing of semaphores can not be nested with these calls. If one attempts to reserve again a semaphore that is already reserved then this results in an error-code.

On releasing the semaphores no task-switching will take place, i.e. though the semaphores may now belong to another application that has a 'ready' status, it has not yet been allocated any CPU time. If the situation is not critical then an appl_yield should be performed subsequently in each case.

The screen semaphore has the name _SCR and may use mxk_evnt_sem only with the subfunction SEM_TEST.

SEM_CREATE does not set the creator automatically as the owner. This is not necessary as no task-switching has taken place, so SEM_SET can be performed afterwards without further ado.

SEM_DEL requires that the deleter is also the owner. On deletion all waiting applications are released; they receive, if waiting via evnt_sem(SEM_SET, ..), a -2 as return value. People deleting system semaphores (those whose names start with a '_') have only themselves to blame!
Group: Kernel functions
See also:

11.21.5.18 SEM_FREE

Parameters:

a0 = Pointer to semaphore
-> 0 OK
-> -1 Semaphore unused, or used by another APP

11.21.5.19 SEM_SET

Parameters:

a0 = Pointer to semaphore
d1 = Timeout in 50Hz ticks
-> 0 OK
-> 1 Timeout
-> -1 Semaphore was already set by me
-> -2 Semaphore has been removed in the meantime

11.21.5.20 SEM_TEST

Parameters:

a0 = Pointer to semaphore
-> >0 Owner
-> 0 Not used

11.21.5.21 SEM_CSET

Parameters:

a0 = Pointer to semaphore
d1 = Timeout in 50Hz ticks
-> 0 OK
-> 1 Semaphore set by another APP
-> -1 Semaphore was already set by me

11.21.5.22 SEM_GET

Parameters:

d1 = Name of semaphore
-> >0 Pointer to semaphore.
-> -1 Semaphore not found

11.21.5.23 SEM_CREATE

Parameters:

a0 = Pointer to semaphore (32 bytes at even address)
d1 = Name void

11.21.5.24 SEM_DEL

Parameters:

a0 = Pointer to semaphore
-> 0 OK
-> -1 Semaphore invalid

11.21.5.25 mxk_Pfree

mxk_Pfree releases the memory for a process that was terminated with Ptermres. This is necessary to remove a device driver correctly.

The following apply for this:

a0 = void *pd

11.21.5.26 mxk_int_msize

mxk_int_msize gives the length of a memory block of the internal (kernel) memory management.

11.21.5.27 mxk_int_malloc

mxk_int_malloc allocates an internal memory block. If there is no free memory any more then first a global 'garbage collection' will be performed (see description of the XFS), and if this fails the system will be halted. Internal memory blocks may be reserved only in small lots, else one soon gets 'Out of internal memory' messages and the system locks up.

11.21.5.28 mxk_int_mfree

mxk_int_mfree releases a memory block once more.

The following apply for this:

a0 = void *memblk

11.21.5.29 mxk_resv_intmem

mxk_resv_intmem extends the kernel memory. There is no possibility foreseen to claim memory back. As the kernel only reserves internal memory sufficient for the FAT drives on booting, it may be necessary for an XFS to reserve further kernel memory with this function at the start.

The following apply for this:

a0 = void *mem
d0 = long bytes

11.21.5.30 mxk_diskchange

mxk_diskchange must be called when an XFS or DFS driver has recognized a disk media change. The XFS driver releases its files and structures and subsequently the kernel.

Return values:

EDRIVE Invalid drive
E_CHNG Valid drive with new disk medium

The following apply for this:

d0 = int drv

11.21.5.31 mxk_DMD_rdevinit

As of kernel version 1.

mxk_DMD_rdevinit initializes the fields d_driver and d_devcode of the DMD and uses the field d_biosdev for this. It is required for interchangeable disk mechanisms.

The following apply for this:

a0 = DMD *dmd

11.21.5.32 mxk_proc_info

As of kernel version 2.

mxk_proc_info obtains data for the current process:

d0 = 0: 0: Highest available subfunction number
  1: Domain
  2: Process ID

The following apply for this:

d0 = WORD code
a0 = PD *pd

11.21.5.33 mxk_mxalloc

As of kernel version 4.

mxk_mxalloc enables fast memory allocation, e.g. for a RAMdisk-XFS, without having to go via a trap.

pd specifies the process that is entered as the owner of the new block, therefore normally the basepage of the XFS driver should be passed.

11.21.5.34 mxk_mfree

As of kernel version 4.

mxk_mfree releases the memory allocated by mxk_mxalloc.

11.21.5.35 mshrink

As of kernel version 4.

mxk_mshrink alters the size of a memory block.

11.21.6 Symbolic links and the XFS-concept

Symbolic links (also called aliases in the user documentation in accordance with Macintosh nomenclature) are files that are specially labelled in some way, and instead of data contain a path which in turn points to another file. Such a path can also point to a no longer or not yet existing file. Paths can be absolute or relative, where the latter have the directory in which the link lies as a reference.

In memory such links are managed as structures:

{
   WORD n;         /* Rounded up to an even number, incl. EOS */
   char path[n];   /* Path with EOS at end  */
}

Note: When some XFS functions come across a symlink they have to dereference it, i.e. they return to the kernel in d0 the error-code ELINK and in a0 a pointer to a structure of the above form. The kernel then looks after the dereferencing and the limiting of the maximum nesting depth (if the symlink points to another one).

XFS functions that may return ELINK are:

xfs_path2DD, xfs_sfirst, xfs_snext, xfs_fopen, xfs_xattr, xfs_attrib.

See also: MagiC's XFS-concept

11.21.7 MX_DOSLIMITS

This structure is defined as follows:

typedef struct
{
    UWORD version;        /* Version number                 */
    UWORD num_drives;     /* Max. number of drives          */
    ULONG max_secsizb;    /* Max. sector size in bytes      */
    UWORD min_nfats;      /* Min. number of FATs            */
    UWORD max_nfats;      /* Max. number of FATs            */
    ULONG min_nclsiz;     /* Min. number of sectors/cluster */
    ULONG max_nclsiz;     /* Max. number of sectors/cluster */
    ULONG max_ncl;        /* Max. number of clusters        */
    ULONG max_nsec;       /* Max. number of sectors         */
} MX_DOSLIMITS;

See also: Dcntl   KER_DOSLIMITS   MagiC's XFS-concept

11.21.8 XFS structures

11.21.8.1 dev_descr

This structure is defined as follows:

struct dev_descr
{
    DEVDRV  *driver;
    SHORT   dinfo;
    SHORT   flags;
    struct tty *tty;
    LONG    devdrvsiz;
    LONG    reserved[4];
};

Note: The component devdrvsiz describes the size of the DEVDRV structure.

See also: Dcntl   MagiC's XFS-concept

11.21.8.2 DEVDRV

This structure is defined as follows:

typedef struct devdrv
{
    LONG (*open)      (FILEPTR *f);
    LONG (*write)     (FILEPTR *f, BYTE *buf, LONG bytes);
    LONG (*read)      (FILEPTR *f, BYTE *buf, LONG bytes);
    LONG (*lseek)     (FILEPTR *f, LONG where, WORD whence);
    LONG (*ioctl)     (FILEPTR *f, WORD mode, VOID *buf);
    LONG (*datime)    (FILEPTR *f, WORD *timeptr, WORD rwflag);
    LONG (*close)     (FILEPTR *f, WORD pid);
    LONG (*select)    (FILEPTR *f, LONG proc, WORD mode);
    VOID (*unselect)  (FILEPTR *f, LONG proc, WORD mode);
    LONG reserved[3];
} DEVDRV;

See also: Dcntl   dev_descr   FILESYS   MagiC's XFS-concept

11.21.8.3 FILESYS

This structure is defined as follows:

typedef struct filesys
{
    struct  filesys *next;
    LONG    fsflags;
    LONG    (*root)       (WORD drv, fcookie *fc);
    LONG    (*lookup)     (fcookie *dir, BYTE *name, fcookie *fc);
    LONG    (*creat)      (fcookie *dir, BYTE *name, UWORD mode,
                           WORD attrib, fcookie *fc);
    DEVDRV *(*getdev)     (fcookie *fc, LONG *devspecial);
    LONG    (*getxattr)   (fcookie *fc, XATTR *xattr);
    LONG    (*chattr)     (fcookie *fc, WORD attr);
    LONG    (*chown)      (fcookie *fc, WORD uid, WORD gid);
    LONG    (*chmode)     (fcookie *fc, UWORD mode);
    LONG    (*mkdir)      (fcookie *dir, BYTE *name, UWORD mode);
    LONG    (*rmdir)      (fcookie *dir, BYTE *name);
    LONG    (*remove)     (fcookie *dir, BYTE *name);
    LONG    (*getname)    (fcookie *relto, fcookie *dir, BYTE *pathname,
                           WORD size);
    LONG    (*rename)     (fcookie *olddir, BYTE *oldname,
                           fcookie *newdir, BYTE *newname);
    LONG    (*opendir)    (DIR *dirh, WORD tosflag);
    LONG    (*readdir)    (DIR *dirh, BYTE *nm, WORD nmlen, fcookie *fc);
    LONG    (*rewinddir)  (DIR *dirh);
    LONG    (*closedir)   (DIR *dirh);
    LONG    (*pathconf)   (fcookie *dir, WORD which);
    LONG    (*dfree)      (fcookie *dir, LONG *buf);
    LONG    (*writelabel) (fcookie *dir, BYTE *name);
    LONG    (*readlabel)  (fcookie *dir, BYTE *name, WORD namelen);
    LONG    (*symlink)    (fcookie *dir, BYTE *name, BYTE *to);
    LONG    (*readlink)   (fcookie *dir, BYTE *buf, WORD len);
    LONG    (*hardlink)   (fcookie *fromdir, BYTE *fromname,
                           fcookie *todir, BYTE *toname);
    LONG    (*fscntl)     (fcookie *dir, BYTE *name, WORD cmd, LONG arg);
    LONG    (*dskchng)    (WORD drv);
    LONG    (*release)    (fcookie *fc);
    LONG    (*dupcookie)  (fcookie *dest, fcookie *src);
} FILESYS;

See also: Dcntl   fs_descr   MagiC's XFS-concept

11.21.8.4 fs_descr

This structure is defined as follows:

struct fs_descr
{
    FILESYS *file_system;
    SHORT   dev_no;
    LONG    flags;
    LONG    reserved[4];
};

See also: Dcntl   MagiC's XFS-concept


HomeMagiCMagiC's DFS-conceptVFAT-XFS in MagiC