Description of the DFS concept of MagiC V3.00 onwards
#####################################################

Andreas Kromke
Hannover, 6.4.95
English translation: Peter West, May 99


I Concepts
==========

The document MGX_XFS.TXT (also in the FILESYS folder) describes the 
construction of a MagiC file system driver (XFS). Only a single XFS, the 
DOS_XFS, is integrated into MagiC.
On top of this XFS sit a number of sub-drivers, so-called DFSs (DOS file 
system), of which two are integrated into MagiC, namely the FAT file 
system and the U file system (that for drive U:).
A DOS file system (DFS) is called by the DOS_XFS. It includes only the 
file functions, while the directory management is undertaken in effect
by the DOS_XFS.
Further DFSs can be installed. Less work has to be done by a programmer 
to create a DFS than an XFS, as many functions will have been performed 
already by the DOS_XFS. The essential prerequisite is a DOS-conform 
directory structure (with 32-byte entries and filenames in the format 8+3).


II Structure of a DFS
=====================

As the implementation can only take place in assembler, here is the 
structure of a DFS in assembler syntax:

     OFFSET

dfs_name:      DS.B      8    /* Sub-name of the DOS file system          */
dfs_next:      DS.L      1    /* Next driver                              */
dfs_init:      DS.L      1    /* Initialisation                           */

     These entries have the same meaning as for a XFS.

dfs_sync:      DS.L      1    /* Synchronises the file system             */
                              /* a0 = DMD *d                              */
                              /* -> d0 = long errcode                     */

     The kernel has informed the DOS_XFS that all buffers are to be 
     written back on drive <d>. In register a0 a pointer is passed to a
     DMD (drive media descriptor). The DOS_XFS passes on this call 
     directly to the DFS.
     The return is an error code. If the DFS does not perform any buffer 
     management (e.g. a RAMdisk) then a 0 must be returned.

dfs_drv_open:  DS.L      1    /* New drive                                */
                              /* a0 = DMD *d                              */
                              /* -> d0 = long errcode                     */

     MagiC supports exactly 26 simultaenously active file systems, which 
     are assigned the letters 'A'..'Z'. This entry has two tasks:

     1. At the first access to a drive (say D:) the kernel creates a 
        DMD (drive media descriptor) and "offers" this to the XFSs. The 
        DOS_XFS in turn offers this to all DFS drivers one after the other.
        The entry d_dfs is still a null-pointer, d_drive is initialised 
        (between 0 and 25, corresponding to 'A'..'Z').
        The DFS drivers then attempt to recognise "their" file system on 
        the drive. If this succeeds then d_dfs and d_root have to be 
        initialised and the return value is then E_OK.
        Else EDRIVE is reported and the DOS_XFS tries the next DFS.

     2. At a repeated access d_dfs is already initialised, and the DFS 
        has the opportunity to test for a media change. If everything 
        is in order then E_OK has to be returned, else the disk change 
        routine of the kernel must be called and E_CHNG returned.
        The pointer to the disk change routine of the kernel is 
        obtained by that for Dcntl (see below).

dfs_drv_close: DS.L      1    /* Close drive                              */
                              /* d0 = int mode                            */
                              /* a0 = DMD *d                              */
                              /* -> d0 = long errcode                     */

     This function also fulfills two tasks, depending on <mode>:

     1. mode == 0:
        The DOS_XFS asks the DFS whether the drive may be closed. If 
        this is not permitted then EACCDN must be returned, else E_OK
        (required e.g. for Dlock()).
        Opened files will already have been recognised by the kernel and 
        the DOS_XFS, i.e. in such cases dfs_drv_close will not even be 
        called.

        For this reason in general no altered sector buffers ought to 
        exist, even those that are currently being read or written to 
        (this is always done via files!). So in this case it suffices to 
        always return an E_OK.
        Things become more difficult when using a write-back cache. With 
        this it is possible that, though no file is open any more, some 
        buffers are still occupied and have to be written back. The 
        kernel makes a sync call (xfs_sync, which is passed on to 
        dfs_sync) before the inquiry is made; thus no altered buffers 
        ought to exist any more. But if they do then the DFS should 
        return an EACCDN for safety reasons.

     2. mode == 1:
        The DOS_XFS forces closing, and the DFS must return E_OK. No 
        caches may be written back, as the drive is already invalid
        (after a media change has already been reported).

     With Dlock(), dfs_drv_close() is called first with mode 0, and then 
     if there is no error with mode 1.
     This procedure will also be executed if sometime in the future a 
     mechanism is built in that interrogates the "Eject" button of 
     interchangeable hard drives or CD-ROMs and refuses ejection if 
     appropriate (my Sun always says in such cases: "device busy").

dfs_dfree:     DS.L      1    /* For Dfree()                              */
                              /* a0 = FD *                                */
                              /* a1 = long df[4]                          */
                              /* -> d0 = long errcode                     */

     For Dfree(). In general it suffices to establish from the DD the 
     appropriate DMD and to quote the free space on the whole drive.

dfs_sfirst:    DS.L      1    /* For Fsfirst                              */
                              /* a0 = FD * d                              */
                              /* a1 = DIR *dir                            */
                              /* d0 = long pos                            */
                              /* d1 = DTA *dta                            */
                              /* -> d0 = long errcode                     */
                              /*    If appropriate                        */
                              /*    a0 = LINK *l                          */

     The DOS_XFS has already positioned the file pointer. The DFS only 
     needs to initialise the reserved entries dta_usr1 and dta_usr2 for 
     the next Fsnext so that one can find the position again.

     File descriptors (FDs) can not be used in dta_usr, because one can 
     not prevent them from being cleared during a "garbage collection".
     It is also not possible just to block the FDs, as one can not 
     predict the end of the Fsfirst/-next operation. A previous 
     unsuccessful search can be marked by clearing dta_sname, for instance.

     <pos> already points to the next entry, i.e. 32 bytes after <dir>. 
     With symbolic links the DFS must react correspondingly, pass ELINK  
     in d0 and a pointer to the link in a0. A  link starts with a word
     (16 bit) for the length of the path, followed by the path itself.

     Warning: The length must INCLUDE the closing null-byte 
              and also be even. The link must be positioned at
              an even memory address.

     The buffer for the link may be static or fugitive, as the kernel 
     immediately copies the data, without the possibility of a context 
     change in between.

dfs_snext:     DS.L      1    /* For Fsnext                               */
                              /* a0 = DTA *dta                            */
                              /* a1 = DMD *dmd                            */
                              /* -> d0 = long errcode                     */
                              /*    If appropriate                        */
                              /*    a0 = LINK *l                          */

     Based on the data that dfs_sfirst has stored in the reserved area 
     of the DTA, the next matching file will be searched for. For this 
     one can resort to functions of the DOS_XFS that can be established
     via Dcntl:

          _dir_srch           Searches through a directory by FD
          reopen_FD           Opens an FD
          close_DD            Closes an FD
          filename_match      Compares filenames
          conv_path_elem      Converts filenames
          init_DTA            Copies data from DIR to the DTA

dfs_ext_fd:    DS.L      1    /* Extends a directory                      */
                              /* a0 = FD *fd                              */
                              /* -> d0 = long errcode                     */

     This is used if a file is to be created but the directory is 
     already full. It is also used when creating a folder (Dcreate).

     <fd> is a prototype-FD that is already opened in exclusive mode.
     The file has to be extended and the new space initialised with zeros.

dfs_fcreate:   DS.L      1    /* Created file or directory                */
                              /* a0 = FD *dd                              */
                              /* a1 = DIR *dir                            */
                              /* d0 = int cmd                             */
                              /* d1 = long arg                            */
                              /* -> d0 = long errcode                     */

     This is used with Fcreate, Dcreate and Dcntl. The DOS_XFS has 
     already found a free space in directory <dd> and created the new 
     directory entry <dir>, at first in memory. The parts of the DIR not 
     used by every DFS (including cluster number) are already initialised
     with zeros. The DFS still has the opportunity to perform corrections 
     here and to initialise the reserved DIR areas according to the file 
     type, before the DOS_XFS writes the whole entry to the directory.
     If the call comes from Dcntl or Fsymlink then d0 and a0 contain the 
     corresponding parameters, else d0 == 0. If d0 == SYMLINK_CREATE then 
     a symbolic link must (or at least can, if possible) be created.

dfs_fxattr:    DS.L      1    /* For Fxattr                               */
                              /* a0 = FD *dd                              */
                              /* a1 = DIR *dir or NULL                    */
                              /* d0 = int mode                            */
                              /* d1 = XATTR *xattr                        */
                              /* -> d0 = long errcode                     */
                              /*    If appropriate                        */
                              /*    a0 = LINK *l                          */

     For Fxattr. The DOS_XFS has already entered all the information, 
     which is identical for all DFSs, in the XATTR. xattr_blksize and
     xattr_nblocks still has to be initialised by the DFS, xattr_size can
     be adapted, for instance for pseudo-files such as PROC, PIPE or DEV.
     xattr_index has been initialised by the DOS_XFS with the Motorola-
     format converted dir_stcl. In many cases it will be necessary to 
     perform a correction here, for instance to pass a pointer to a driver 
     or a global data structure.
     For mode d0 == 0 (i.e. follow symbolic links) the DFS has to react 
     correspondingly, and in the case of a link return ELINK in d0 and the 
     link in a0.
     If <dir> == NULL then the DOS_XFS has not read a directory entry but 
     an FD (e.g. the root or an opened file).

dfs_dir2index: DS.L      1    /* For Dreaddir                             */
                              /* a0 = FD *dd                              */
                              /* a1 = DIR *dir                            */
                              /* -> d0 = long index or errcode            */

      This simply returns an index (32 bit) to a DIR entry. The FAT_DFS 
      uses the de-Intelised start cluster for this.
     <dd> is the directory that contains the file.

dfs_readlink:  DS.L      1    /* For Freadlink                            */
                              /* a0 = FD *dd                              */
                              /* a1 = DIR *dir                            */
                              /* -> d0 = long errcode                     */
                              /*    If appropriate                        */
                              /*    a0 = LINK *l                          */

     For Freadlink. d0 is either EACCDN when <dir> is not a symlink, or
     another error code.
     If no error has arisen then the link must be returned in a0, and 
     d0 must have the value ELINK.

dfs_dir2FD:    DS.L      1    /* For Fopen                                */
                              /* a0 = FD *dd                              */
                              /* a1 = DIR *dir                            */
                              /* -> d0 = long errcode                     */
                              /*    If appropriate                        */
                              /*    a0 = LINK *l                          */

     Initialises a prototype-FD, namely the fields:

          fd_len
          fd_stcl
          fd_attr
          fd_ddev

     and if appropriate:

          fd_name
          fd_xftype
          fd_xdata usw.

     and may alter some other data of the FD if required.

dfs_fdelete:   DS.L      1    /* For Fdelete and Ddelete                  */
                              /* a0 = FD *dd                              */
                              /* a1 = DIR *dir                            */
                              /* d0 = long dirpos                         */
                              /* -> d0 = long errcode                     */

     The file in the directory entry <dir> in the directory <FD> is to
     be deleted.
     Performs the actual removal of the file; the deletion of the 
     directory entry and the check of the access permissions are 
     performed by the DOS_XFS.

dfs_pathconf:  DS.L      1    /* For Dpathconf                            */
                              /* a0 = FD *dd                              */
                              /* d0 = int which                           */
                              /* -> d0 = long val or error code           */

     Various limits and capabilities that apply to a given path <dd> are 
     interrogated. Most of the values for <which> are already inserted by 
     the DOS_XFS, so that only the following values occur:

          DP_IOPEN (0)     Maximum number of simultaneously opened files
          DP_ATOMIC (4)    Internal block size (sector size?, cluster size?)
         From 21.5.95 onwards:
          DP_MODEATTR (7)  Permitted file types

III Data structures
===================

1. The DOS device driver (MX_DDEV)
----------------------------------

At the opening of a file the sub device driver (MX_DDEV) is inserted by 
the DFS function dfs_dir2FD into the file descriptor and called by the 
DOS_XFS. The MX_DDEV device driver must make the following functions 
available:

     OFFSET

ddev_open:     DS.L      1         /* a0 = FD *file                       */
                                   /* -> d0 = long errcode                */

     The file is opened, the FD is already initialised. In Open mode
     (fd_mode) the bit O_TRUNC has to be evaluated. If appropriate an 
     error code is to be returned. With devices one can safely ignore
     O_TRUNC.
     The field fd_fpos is already initialised to 0L. Should this be 
     insufficient (e.g. if the FAT_DFS always remembers the current 
     cluster) then the corresponding fields of the user area of the FD 
     have to be initialised, or other fields of the FD adapted.

     ddev_open is called both at the first opening of a file (after 
     dfs_dir2FD), as well as when duplicating a file descriptor (when, 
     for instance, several programs access a file or a directory 
     simultaneously). Not, however, when Fdup() is called or when a 
     program calls another one and opened files are inherited (!) during 
     this. The reason for this is that no new file descriptors (FDs) are 
     created during these operations, but merely several handles or 
     processes access the same FD.

     The compatibility of the Open modes (perhaps "shared read") is 
     guaranteed by the DOS-XFS. The device driver can, for instance, 
     modify the Open mode in such a way that the FD is always opened 
     "exclusive", or with the bit OM_NOCHECK cause it to supervise the 
     Open mode itself.
     If ddev_open() is called for the prototype-FD, then
     fd->fd_multi1 == fd.
     If ddev_open() returns an error code then the FD is simply released 
     again by the DOS-XFS.

ddev_close:    DS.L      1         /* a0 = FD *file                       */
                                   /* -> d0 = long errcode                */

     The file is closed. The management of fd_refcnt will be taken over 
     by the DOS_XFS. The MX_DDEV driver here may merely need to write 
     back any buffers.

     One should note that the ddev_open/ddev_close calls need not occur 
     in pairs. The reason for this is that Fdup() or the inheritance of 
     handles do not cause a ddev_open but merely increment the fd_refcnt.
     In contrast to this a ddev_close is called for the closing of the 
     handle, so that any buffers that exist are written back.

ddev_read:     DS.L      1    /* a0 = FD *file                            */
                              /* d0 = long count                          */
                              /* a1 = char *buffer                        */
                              /* -> d0 = long amount                      */

     See dev_read in MGX_XFS.TXT (also in this FILESYS folder)

ddev_write:    DS.L      1    /* a0 = FD *file                            */
                              /* d0 = long count                          */
                              /* a1 = char *buffer                        */
                              /* -> d0 = long amount                      */

     See dev_write in MGX_XFS.TXT.
     The MX_DDEV need not bother with updating the directories or the 
     date of last access.

ddev_stat:     DS.L      1    /* a0 = FD *file                            */
                              /* a1 = MAGX_UNSEL *unselect   or NULL      */
                              /* d0 = int rwflag                          */
                              /* d1 = long apcode                         */
                              /* -> d0 = long status                      */

     See dev_stat in MGX_XFS.TXT

ddev_seek:     DS.L      1    /* a0 = FD *file                            */
                              /* d0 = long where                          */
                              /* d1 = int mode                            */
                              /* -> d0 = long position                    */

     See dev_seek in MGX_XFS.TXT

ddev_datime:   DS.L      1    /* a0 = FD *file                            */
                              /* a1 = int d[2]                            */
                              /* d0 = int setflag                         */
                              /* -> d0 = long errcode                     */

     See dev_datime in MGX_XFS.TXT.
     The MX_DDEV can simply insert a NULL-pointer here, then the DOS_XFS 
     executes the standard procedure.
     The DOS_XFS converts Fcntl(FUTIME, ...) to Fdatime.

ddev_ioctl:    DS.L      1    /* a0 = FD *file                            */
                              /* d0 = int cmd                             */
                              /* a1 = void *buf                           */
                              /* -> d0 = long errcode                     */

     See dev_ioctl in MGX_XFS.TXT.
     At least the functions FTRUNCATE, FIONREAD and FIONWRITE should be 
     supported.
     The DOS_XFS converts Fcntl(FUTIME, ...) to Fdatime() and hence to 
     ddev_datime, i.e. FUTIME does not have to be supported directly by 
     ddev_ioctl.

ddev_delete:   DS.L      1    /* a0 = FD *directory                       */
                              /* a1 = DIR *dir                            */
                              /* -> d0 = long errcode                     */

     This function is called only by the U-DFS, i.e. the integrated DFS 
     file system for drive U:. Thus if one installs one's own device 
     driver, this is just the right time to release the memory it 
     occupies and so withdraw from the system.
     More details are given in MGX_UDFS.TXT (also in the FILESYS folder).

ddev_getc:     DS.L      1    /* a0 = FD *file                            */
                              /* d0 = int mode                            */
                              /* -> d0 = unsigned long c                  */

     See dev_getc in MGX_XFS.TXT.
     The MX_DDEV can simply insert a NULL-pointer here, then the DOS_XFS 
     executes the standard procedure, i.e. calls ddev_read.

ddev_getline:  DS.L      1    /* a0 = FD *file                            */
                              /* a1 = char *buf                           */
                              /* d1 = long size                           */
                              /* d0 = int mode                            */
                              /* -> d0 = long amount                      */

     See dev_getline in MGX_XFS.TXT.
     The MX_DDEV can simply insert a NULL-pointer here, then the DOS_XFS 
     executes the standard procedure, i.e. calls ddev_read.

ddev_putc:     DS.L      1    /* a0 = FD *file                            */
                              /* d0 = int mode                            */
                              /* d1 = long value                          */
                              /* -> d0 = unsigned long count              */

     See dev_putc in MGX_XFS.TXT.
     The MX_DDEV can simply insert a NULL-pointer here, then the DOS_XFS 
     executes the standard procedure, i.e. calls ddev_write.


2. The file descriptor (FD) or directory descriptor (DD)
--------------------------------------------------------

The file descriptors are created and managed by the DOS_XFS. The DOS_XFS
manages files and folders (subdirectories) with the help of an identical 
data structure. Within a DFS an FD looks like the following (it is an 
object class derived from the parent class with further entries (compare 
with MGX_XFS.TXT)):

     OFFSET

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

     The first entries correspond to the parent class, i.e. they are
     identical for all XFSs as they are used by the kernel.

; For all DFS
; fd_name/attr/next/children
; fd_dirch/time/date/stcl/len are invalid for clones
; fd_parent/dirpos/dmd are identical with the prototype-FD

fd_ddev:       DS.L      1    /* 0x0c: Pointer to MX_DDEV                 */

     Here the DFS must enter the MX_DDEV, i.e. the device driver, at the
     "dir2FD" call.

fd_name:       DS.B      11   /* 0x10: DD_FD: Name in internal format     */
fd_attr:       DS.B      1    /* 0x1b: Attribute                          */

     Here the name (8+3) in internal format as well as the file attribute 
     is stored. The name is only valid when it applies to a subdirectory.
     Name and attribute are only valid in the "prototype-FD", i.e. in 
     fd->multi1. One can recognise from the attribute whether the entry 
     represents a directory. The name of the root is an empty character 
     string.

fd_owner:      DS.L      1    /* 0x1c: DD_FD: Owner of an FD or NULL      */

     Here a pointer to the owner of an FD is stored (i.e. a pointer to 
     the basepage). A value of NULL indicates that the FD is currently 
     unused.

fd_parent:     DS.L      1    /* 0x20: Pointer to the parent-DD_FD        */

     Chaining pointer to the parent, i.e. to the directory that contains 
     the file, or the parent directory of a subdirectory if appropriate.
     fd_parent is only valid for the prototype-FD.

fd_children:   DS.L      1    /* 0x24: DD_FD: List of all children        */

     List of all opened files and opened subdirectories. 
     fd_children is only valid for the prototype-FD.

fd_next:       DS.L      1    /* 0x28: Pointer to FDs in same directory   */

     Pointer to the next FD in the same directory, i.e. to the next 
     sibling, which can be an opened file or a subdirectory; in principle 
     no distinction is made between these.
     fd_next is only valid for the prototype-FD.

fd_multi:      DS.L      1    /* 0x2c: Pointer to FD of the same file     */

     If a file is opened several times then a "clone" of the prototype-FD
     is created. Most of the fields of the FD are invalid for this clone; 
     essentially only drivers, mode and file position are valid.
     fd_multi is a chained list that is NULL-terminated.

fd_multi1:     DS.L      1    /* 0x30: Pointer to first list element      */

     The associated prototype-FD, which contains the valid file 
     specifications. If a file has only been opened once, then
     fd->fd_multi1 == fd applies.

fd_fpos:       DS.L      1    /* 0x34: Position of the file pointer       */

     The position of the file pointer, is 0L for a device.

fd_dirch:      DS.B      1    /* 0x38: Bit0: "dirty"                      */

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

fd_unused:     DS.B      1    /* 0x39: */

     Unused and reserved.

fd_time:       DS.W      1    /* 0x3a: Time  (8086)                       */
fd_date:       DS.W      1    /* 0x3c: Date  (8086)                       */
fd_stcl:       DS.W      1    /* 0x3e: Start cluster (68000)              */
fd_len:        DS.L      1    /* 0x40: File length in bytes (68000)       */

     Data from the directory entry, date and time unaltered, thus in 
     Intel format (sdrawkcab).

fd_dirpos:     DS.L      1    /* 0x44: Pos.of associated entry in directory */

     Position of the associated entry in the parent. Is only valid for 
     the prototype-FD.

fd_user1:      DS.L      1    /* 0x48: */
fd_user2:      DS.L      1    /* 0x4c: */

     2 longwords available for free use. The FAT_DFS saves additional 
     information for fd_fpos here, namely the current cluster. Other DFSs 
     can store other data here.
     These fields are at first also only valid for the prototype-FD, 
     unless during opening (ddev_open) the data is copied explicitly 
     from the prototype-FD to the clone.


3. The medium descriptor (DMD)
------------------------------

d_xfs:         DS.L      1    /* 0x00: The file system 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 & drive           */

     As in parent object. See MGX_XFS.TXT (also in FILESYS folder).

d_dfs:         DS.L      1    /* 0x14: DOS-specific file system driver    */

In contrast to the parent object class only the d_dfs entry has been 
added, which contains the associated DFS driver.


4. The DTA
----------

The DTA is used by the old DOS functions Fsfirst and Fsnext, whose clumsy 
conception by the MS-DOS creators still burdens us like a curse. The 
division into res1/res2 has historical reasons, to make the structure 
as compatible as possible to the old TOS at least in the DOS_XFS.
For the DOS_XFS, and with this all DFSs, the structure looks like this:

dta_sname:     DS.B      12   /* 0x00: Search name (from Fsfirst)         */
dta_usr1:      DS.L      1    /* 0x0c: Available for free use             */
dta_usr2:      DS.L      1    /* 0x10: Available for free use             */
dta_drive:     DS.B      1    /* 0x14: Logical drive (0..25)              */
dta_attr:      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                     */

     Here there are 2 longwords free for use. <dta_sname> already 
     contains the search name in the current format.
     In usr1 und usr2 one must enter the current position of the search 
     so that a following Fsnext continues searching from the correct 
     position.


5. The directory entry (DIR)
----------------------------

The following fields are identical for all DFSs:

     OFFSET

dir_name:      DS.B     11    /* 0x00: Filename                           */
dir_attr:      DS.B      1    /* 0x0b: Attribute                          */
dir_usr1:      DS.W      1    /* 0x0c: Available for free use             */
dir_usr2:      DS.L      1    /* 0x0e: Available for free use             */
dir_usr3:      DS.L      1    /* 0x12: Available for free use             */
dir_time:      DS.W      1    /* 0x16: Time of last modification (Intel)  */
dir_date:      DS.W      1    /* 0x18: Date of last modification (Intel)  */
dir_stcl:      DS.W      1    /* 0x1a: First cluster or other information */
dir_flen:      DS.L      1    /* 0x1c: File length (Intel)                */

     Other data is also possible in place of the first cluster. The 
     DOS_XFS however handles the entry at first as a cluster specification
     (for xattr.index and fd_stcl as well as for creating the entries "." 
     and ".." during Dcreate). In the case of Fxattr the data can be 
     overwritten by the DFS with other data.


IV Installation
===============

A DFS is simply a program that installs the driver, then terminates and 
stays resident.
The installation is effected with:

     dosfunctions = Dcntl(DFS_INSTDFS, "U:\\", &myxfs);

The path "U:\\" is important because the Dcntl call is not executed by 
the MagiC kernel but by the DOS-XFS. If one specifies a path to a 
Mac-volume, for instance, then this Dcntl will not be serviced because 
the Mac-XFS does not know this code.

The return is a pointer to important DOS_XFS functions (or an error 
code). The DOS_XFS functions can also be queried independently of the
installation of a DFS with:

     dosfunctions = Dcntl(DFS_GETINFO, "U:\\", NULL);

One obtains the kernel functions with:

     kernel = Dcntl(KER_GETINFO, NULL, NULL);

No provision is made for the deinstallation of a DFS.
