MagiC, just as MultiTOS, enables the incorporation of alternative filesystems (so-called XFSs). Firmly integrated in MagiC is only a single XFS, the DOS_XFS. On top of this XFS sit in turn subdrivers, the so-called DFS (DOS filesystem), of which two are integrated in MagiC, namely the FAT filesystem and the U filesystem (that for the drive U:).
A DOS filesystem (DFS) is called by DOS_XFS. This includes only the file functions, while the management of directories is essentially taken over by the DOS_XFS. Further DFSs can be installed. 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). This section deals with the items:
See also: MagiC's XFS-concept
Since the implementation of a DFS can only be performed in Assembler, this description is specified in Assembler syntax:
dfs_name: DS.B 8 /* Subname of the DOS filesystems */ dfs_next: DS.L 1 /* Next driver */ dfs_init: DS.L 1 /* Initialization */ dfs_sync: DS.L 1 /* Synchronises the filesystem */ dfs_drv_open: DS.L 1 /* New drive */ dfs_drv_close: DS.L 1 /* Release drive */ dfs_dfree: DS.L 1 /* For Dfree */ dfs_sfirst: DS.L 1 /* For Fsfirst */ dfs_snext: DS.L 1 /* For Fsnext */ dfs_ext_fd: DS.L 1 /* Extends a directory */ dfs_fcreate: DS.L 1 /* Creates a directory or file */ dfs_fxattr: DS.L 1 /* For Fxattr */ dfs_dir2index: DS.L 1 /* For Dreaddir */ dfs_readlink: DS.L 1 /* For Freadlink */ dfs_dir2FD: DS.L 1 /* for Fopen */ dfs_fdelete: DS.L 1 /* For Fdelete and Ddelete */ dfs_pathconf: DS.L 1 /* For Dpathconf */
See also: Make-up of an XFS MagiC
Name: | »dfs_dfree«
| |||||||||
Parameters: |
| |||||||||
Description: | For Dfree it is generally sufficient to obtain from the DD
the DMD that belongs to it and to specify the free space on the
whole drive.
| |||||||||
Group: | Make-up of a DFS
| |||||||||
See also: | MagiC's DFS-concept
|
Name: | »dfs_dir2FD« - Initialize a prototype FD.
|
Parameters: |
|
Description: | dfs_dir2FD initializes a prototype-FD, namely the fields:
and if necessary:
Other data of the FD may also be changed if necessary. |
Group: | Make-up of a DFS
|
See also: | MagiC's DFS-concept
|
Name: | »dfs_dir2index«
|
Parameters: |
|
Description: | dfs_dir2index simply returns an index (32-bit) to a DIR entry.
For this the FAT_DFS takes the de-Intelled starting cluster.
dd is the directory that contains the file.
|
Group: | Make-up of a DFS
|
See also: | MagiC's DFS-concept
|
Name: | »dfs_drv_close«
| |||||||||
Parameters: |
| |||||||||
Description: | The dfs_drv_close function too 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 were already recognized be the kernel and DOS_XFS, i.e. in that case dfs_drv_close will not be called at all. For this reason, generally no altered sector buffers may exist, even those that are currently being read or written (this is always done via files!). In this case it suffices, therefore, always to return an E_OK. Things become more problematic if one uses a write-back cache. With this it may happen that no file is open any more, but a buffer still holds data that 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 - if they do, then for safety's sake the DFS should return EACCON. 2. mode == 1: The DOS_XFS forces the closing of the drive, the DFS must return E_OK. No caches may be written back, since the drive is already invalid (after a media change has been reported already). With Dlock, dfs_drv_close is first called in mode 0, then - if no error has occurred - with mode 1. This strategy will be carried out also even if at some time a mechanism is built in that monitors the eject button of interchangeable-media drives or CD-ROMs, and bars ejection if necessary. | |||||||||
Group: | Make-up of a DFS
| |||||||||
See also: | MagiC's DFS-concept
|
Name: | »dfs_drv_open«
| ||||||
Parameters: |
| ||||||
Description: | MagiC supports exactly 26 simultaneously active filesystems
that are assigned letters 'A'..'Z'. dfs_drv_open has two tasks:
| ||||||
Group: | Make-up of a DFS
| ||||||
See also: | MagiC's DFS-concept
|
Name: | »dfs_ext_fd«
| ||||||
Parameters: |
| ||||||
Description: | dfs_ext_fd is used when a file is to be created but the
directory is already full. It is also used during the creation of a
folder (Dcreate).
fd is a prototype FD, which is already opened in the exclusive mode. The file has to be extended and the new space initialized with NULLs. | ||||||
Group: | Make-up of a DFS
| ||||||
See also: | MagiC's DFS-concept
|
Name: | »dfs_fcreate«
|
Parameters: |
|
Description: | dfs_fcreate is used for Fcreate, Dcreate and Dcntl. The DOS_XFS
has already found free space in the directory dd, and - at
first in memory - created the new directory entry dir. Those
parts of the DIR not used in every DFS (the cluster number too)
are already initialized with NULLs. The DFS has the opportunity here
still to make corrections and to initialize the reserved DIR areas
according to the file-type before the DOS_XFS writes the whole entry
into the directory.
When the call Dcntl or Fsymlink occurs, d0 and a0 contain the relevant parameters, otherwise d0 == 0. If d0 == SYMLINK_CREATE, a symbolic link must (or at least can, if possible) be created. |
Group: | Make-up of a DFS
|
See also: | MagiC's DFS-concept
|
Name: | »dfs_fdelete«
|
Parameters: |
|
Description: | The file with the directory entry dir in the directory
FD is to be deleted. dfs_fdelete performs the actual deletion
of the file; the deletion of the directory entry and access checks are
performed by the DOS_XFS.
|
Group: | Make-up of a DFS
|
See also: | MagiC's DFS-concept
|
Name: | »dfs_fxattr«
|
Parameters: |
|
Description: | dfs_fxattr is required for Fxattr. The DOS_XFS has already
entered all the information, which is identical for all DFSs, into
the XATTR. xattr_blksize as well as xattr_nblocks both still have to
be initialized by the DFS, xattr_size can be adapted for special
files, say. xattr_index has been initialized by the DOS_XFS, with
dir_stcl converted to the Motorola format. In many cases it will be
necessary to perform a correction here, and to pass a pointer to a
driver or a global data structure, for instance.
With mode d0 == 0 (i.e. follow symbolic links) the DFS must react appropriately and in the case of a link it has to return in d0 ELINK and in a0 the link. If dir == NULL, then the DOS_XFS has not located a directory entry but an FD (e.g. the root, or an open file). |
Group: | Make-up of a DFS
|
See also: | MagiC's DFS-concept
|
Name: | »dfs_init«
|
Parameters: | —
|
Description: | Reserved. In case of MagiC-internal XFSs, dfs_init contains
their initialization. It is not used with loaded-in XFSs.
|
Group: | Make-up of a DFS
|
See also: | MagiC's DFS-concept
|
Name: | »dfs_name«
|
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 spaces). |
Group: | Make-up of a DFS
|
See also: | MagiC's DFS-concept
|
Name: | »dfs_next«
|
Parameters: | —
|
Description: | dfs_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
integrated DOS driver, for instance.
|
Group: | Make-up of a DFS
|
See also: | MagiC's DFS-concept
|
Name: | »dfs_pathconf«
| |||||||||
Parameters: |
| |||||||||
Description: | dfs_pathconf inquires about various restrictions that apply for
a given path dd. Most values for which have been set
by the DOS_XFS already, so only the following values occur:
| |||||||||
Group: | Make-up of a DFS
| |||||||||
See also: | MagiC's DFS-concept
|
Name: | »dfs_readlink«
|
Parameters: |
|
Description: | dfs_readlink is used for Freadlink. d0 is either EACCDN if
dir is not a symlink, or another error-code. If no error has
arisen, a0 must return the link and d0 has to have the value ELINK.
|
Group: | Make-up of a DFS
|
See also: | MagiC's DFS-concept
|
Name: | »dfs_sfirst«
|
Parameters: |
|
Description: | The DOS_XFS has already accessed the file. The DFS only
needs to initialize the reserved entries dta_usr1 and dta_usr2 for the
next Fsnext, so that this position can be found again.
File descriptors (FDs) cannot be used in dta_usrm as releasing them during a 'garbage collection' cannot be avoided. Simply blocking the FDs is not possible either as one cannot predict the end of the Fsfirst/Fsnext operation. An already failed search can be marked by deleting dta_sname, for instance. pos already points to the next entry, i.e. 32 bytes after dir. For symbolic links the DFS has to react appropriately, pass ELINK in d0 and in a0 a pointer to the link. 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 terminating NULL-byte and also be even. The link must lie at an even memory address. The buffer for the link may be static or volatile as the kernel immediately copies the data elsewhere, with no possibility of a context change happening inbetween. |
Group: | Make-up of a DFS
|
See also: | MagiC's DFS-concept
|
Name: | »dfs_snext«
| ||||||||||||
Parameters: |
| ||||||||||||
Description: | The next matching file will be looked for, based on the data
that dfs_sfirst has stored in the reserved area of the DTA. For
this one can fall back on the functions of the DOS_XFS that can be
obtained with Dcntl:
| ||||||||||||
Group: | Make-up of a DFS
| ||||||||||||
See also: | MagiC's DFS-concept
|
Name: | »dfs_sync«
| ||||||
Parameters: |
| ||||||
Description: | The kernel has notified DOS_XFS that all buffers have been
written back on drive d. A pointer to a DMD (drive medium
descriptor) is passed in register a0. The DOS_XFS passes this call on
directly to the DFS.
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. | ||||||
Group: | Make-up of a DFS
| ||||||
See also: | MagiC's DFS-concept
|
When working with a DFS the following data structures are important:
See also: XFS structures
The following fields are identical for every DFS:
dir_name: DS.B 11 /* 0x00: Filename */ dir_attr: DS.B 1 /* 0x0b: Attribute */ dir_usr1: DS.W 1 /* 0x0c: For free user assignment */ dir_usr2: DS.L 1 /* 0x0e: For free user assignment */ dir_usr3: DS.L 1 /* 0x12: For free user assignment */ dir_time: DS.W 1 /* 0x16: Time of last change (Intel format) */ dir_date: DS.W 1 /* 0x18: Date of last change (Intel format) */ dir_stcl: DS.W 1 /* 0x1a: First cluster, or other info */ dir_flen: DS.L 1 /* 0x1c: File length (Intel format) */
Note: Instead of the cluster, other statements are possible as well. However, DOS_XFS treats the entry as a cluster specification at first (for xattr.index and fd_stcl as well as the creation of the entries '.' and '..' for Dcreate). In the case of Fxattr the statements of the DFS can be overwritten with other data.
See also: MagiC's DFS-concept
The sub-device driver (MX_DDEV) is inserted into the file descriptor by the DFS function dfs_dir2FD at the opening of a file and called up by the DOS_XFS. The MX_DDEV device driver has to make the following functions available:
typedef struct _mx_ddev { LONG cdecl (*ddev_open)(struct _mx_dosfd *f); LONG cdecl (*ddev_close)(); LONG cdecl (*ddev_read)(); LONG cdecl (*ddev_write)(); LONG cdecl (*ddev_stat)(); LONG cdecl (*ddev_seek)(); LONG cdecl (*ddev_datime)(); LONG cdecl (*ddev_ioctl)(); LONG cdecl (*ddev_delete)(); LONG cdecl (*ddev_getc)(); LONG cdecl (*ddev_getline)(); LONG cdecl (*ddev_putc)(); } MX_DDEV;
See also: MagiC's DFS-concept MagiC's XFS-concept
Name: | »ddev_open«
| ||||||
Parameters: |
| ||||||
Description: | The file is opened, the FD is already initialized. In open-mode
(fd_mode), bit O_TRUNC has to be evaluated. If appropriate an
error-code has been returned, for devices O_TRUNC can be confidently
ignored.
The field fd_fpos is already initialized to 0L. Should this not suffice (say if the FAT_DFS always memorizes the current cluster), then the appropriate fields of the user area of the FD are to be initialized or other fields of the FD adapted. ddev_open is called both on the first opening of a file (after dfs_dir2FD) as well as on duplication of a file descriptor (say if several programs access a file or a directory simultaneously). The compatibility of the open-modes (perhaps a shared read) is guaranteed by the kernel. The device driver can, for instance, modify the open-mode in such a way that the FD is always opened as 'exclusive', or arrange with the bit OM_NOCHECK that it wants to oversee the open-mode itself. If ddev_open for the prototype FD is called, then fd->fd_multi1 == fd. If ddev_open returns an error-code, then the FD is simply released again by the DOS-XFS. | ||||||
Group: | DOS device driver
| ||||||
See also: | —
|
The file is closed. The handling of fd_refcnt is taken over by the DOS_XFS. The MX_DDEV driver here only needs to write back any buffers that may exist.
Parameters:
a0 | = | FD *file, |
-> d0 | = | long errcode |
See dev_read.
Parameters:
a0 | = | FD *file |
d0 | = | long count |
a1 | = | char *buffer |
-> d0 | = | long amount |
See dev_write. The MX_DDEV does not have to bother with the updating of the directory or the date of last access.
Parameters:
a0 | = | FD *file |
d0 | = | long count |
a1 | = | char *buffer |
-> d0 | = | long amount |
See dev_stat.
Parameters:
a0 | = | FD *file |
a1 | = | MAGX_UNSEL *unselect oder NULL |
d0 | = | int rwflag |
d1 | = | long apcode |
-> d0 | = | long status |
See dev_seek.
Parameters:
a0 | = | FD *file |
d0 | = | long where |
d1 | = | int mode |
-> d0 | = | long position |
See dev_datime. The MX_DDEV can simply insert a NULL-pointer here, then the DOS_XFS performs the standard procedure. The DOS_XFS converts Fcntl(FUTIME, ...) to Fdatime.
Parameters:
a0 | = | FD *file |
a1 | = | int d[2] |
d0 | = | int setflag |
-> d0 | = | long errcode |
See dev_ioctl. There should be support for the functions FTRUNCATE, FIONREAD and FIONWRITE at least. DOS_XFS converts Fcntl(FUTIME, ...) to Fdatime and with that to ddev_datime, i.e. FUTIME does not have to be supported directly by ddev_ioctl.
Parameters:
a0 | = | FD *file |
d0 | = | int cmd |
a1 | = | void *buf |
-> d0 | = | long errcode |
This function is called only by the U_DFS, i.e. the integrated DFS file system for drive U:. So if one installs one's own device driver, this is the time to release its memory and so retire from the system.
Parameters:
a0 | = | FD *directory |
a1 | = | DIR *dir |
-> d0 | = | long errcode |
See dev_getc. The MX_DDEV can simply insert a NULL-pointer here, then the DOS_XFS performs the standard procedure, i.e. calls ddev_read.
Parameters:
a0 | = | FD *file |
d0 | = | int mode |
-> d0 | = | unsigned long c |
See dev_getline. The MX_DDEV can simply insert a NULL-pointer here, then the DOS_XFS performs the standard procedure, i.e. calls ddev_read.
Parameters:
a0 | = | FD *file |
a1 | = | char *buf |
d1 | = | long size |
d0 | = | int mode |
-> d0 | = | long amount |
See dev_putc. The MX_DDEV can simply insert a NULL-pointer here, then the DOS_XFS performs the standard procedure, i.e. calls ddev_write.
Parameters:
a0 | = | FD *file |
d0 | = | int mode |
d1 | = | long value |
-> d0 | = | unsigned long count |
The DTA is used by the old DOS functions Fsfirst and Fsnext, whose clumsy conception by the MSDOS originators still weighs down the system like a curse. The partitioning into res1/res2 has historical reasons, to make the structure at least in DOS_XFS as compatible as possible to old TOSs. For the DOS_XFS and with that for all DFSs the structure looks as follows:
dta_sname: DS.B 12 /* 0x00: Search name (from Fsfirst) */ dta_usr1 : DS.L 1 /* 0x0c: For free user assignment */ dta_usr2 : DS.L 1 /* 0x10: For free user assignment */ 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 */
Note: Here there are two LONGwords for free assignment by the user. dta_sname contains the search name already in the current format. In dta_usr1 and dta_usr2 one must enter the current position of the search, so that a following Fsnext continues the search at the correct position.
See also: MagiC's DFS-concept
A DFS is simply a program that installs the driver and then
terminates itself as resident. The installation takes place with:
dosfunctions = Dcntl(DFS_INSTDFS, "U:\\",
&myxfs);
the path "U:\\" is important, because the Dcntl call is
performed not by the MagiC kernel, but by the DOS-XFS. The return
value will be a pointer to important XFS functions, or an
error-code.
The DOS_XFS functions can also be inquired for independent of
the installation of a DFS by using:
dosfunctions = Dcntl(DFS_GETINFO, "U:\\", NULL);
with kernel = Dcntl (KER_GETINFO, NULL, NULL) one obtains
the kernel functions.
The deinstallation of a DFS is not provided for.