Beschreibung des DFS-Konzepts von Mag!X V3.00
#############################################

Andreas Kromke
Hannover, den 6.4.95


I Konzepte
==========

Im Dokument MGX_XFS.TXT ist der Aufbau eines Mag!X- Dateisystemtreibers (XFS)
beschrieben. Fest in Mag!X integriert ist nur ein einziges XFS, das DOS_XFS.
Auf diesem XFS setzen wiederum Untertreiber, sogenannte DFS (dos file system)
auf, von denen zwei in Mag!X integriert sind, und zwar das FAT- Dateisystem
und das U- Dateisystem (das fr Laufwerk U:).
Ein DOS- Dateisystem (DFS) wird vom DOS_XFS aufgerufen. Hier stehen nur
die Dateifunktionen, whrend die Verzeichnisverwaltung im wesentlichen vom
DOS_XFS bernommen wird.
Weitere DFSs knnen eingebunden werden. Der Aufwand fr ein DFS ist
wesentlich geringer als fr ein XFS, da viele Funktionen vom DOS_XFS
bereits ausgefhrt werden. Die wesentliche Voraussetzung ist eine DOS-
konforme Verzeichnisstruktur (mit 32-Byte-Eintrgen und Dateinamen des
Formats 8+3).


II Aufbau eines DFS
===================

Weil die Implementation nur in Assembler erfolgen kann, hier der Aufbau eines
DFS in Assembler- Syntax.

     OFFSET

dfs_name:      DS.B      8    /* Untername des DOS-Dateisystems            */
dfs_next:      DS.L      1    /* Nchster Treiber                          */
dfs_init:      DS.L      1    /* Initialisierung                           */

     Diese Eintrge haben die gleiche Bedeutung wie bei einem XFS

dfs_sync:      DS.L      1    /* Synchronisiert Dateisystem                */
                              /* a0 = DMD *d                               */
                              /* -> d0 = long errcode                      */

     Der Kernel hat dem DOS_XFS mitgeteilt, da auf Laufwerk <d> alle Puffer
     zurckzuschreiben sind. bergeben wird in Register a0 ein Zeiger auf
     einen DMD (drive media descriptor). Das DOS_XFS gibt diesen Aufruf
     direkt an das DFS weiter.
     Zurckgeliefert wird ein Fehlercode. Wenn das DFS keine Pufferverwaltung
     hat (z.B. eine RAMDisk), mu eine 0 geliefert werden.

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

     Mag!X untersttzt genau 26 gleichzeitig aktive Dateisysteme, denen die
     Buchstaben 'A'..'Z' zugeordnet sind. Dieser Eintrag hat zwei Aufgaben:

     1. Beim ersten Zugriff auf ein Laufwerk (etwa D:) legt der Kernel einen
        DMD (drive media descriptor) an und "bietet" diesen den XFSs an. Der
        DOS_XFS bietet diesen wiederum der Reihe nach allen DFS- Treibern an.
        Der Eintrag d_dfs ist noch ein Nullzeiger, d_drive ist initialisiert
        (zwischen 0 und 25, entsprechend 'A'..'Z').
        Die DFS- Treiber versuchen nun, auf dem Laufwerk "ihr" Dateisystem zu
        erkennen. Falls dies gelingt, mssen d_dfs und d_root initialisiert
        werden, der Rckgabewert ist dann E_OK.
        Andernfalls wird EDRIVE gemeldet, und das DOS_XFS probiert das nchste
        DFS.

     2. Beim wiederholten Zugriff ist d_dfs bereits initialisiert, und das
        DFS hat die Gelegenheit, auf Mediumwechsel zu testen. Ist alles in
        Ordnung, mu E_OK zurckgegeben werden. Ansonsten mu die
        Diskwechselroutine des Kernels aufgerufen und E_CHNG zurckgegeben
        werden.
        Den Zeiger auf die Diskwechselroutine des Kernels erhlt man bei der
        per Dcntl (s.u.).

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

     Auch diese Funktion erfllt, abhngig vom <mode>, zwei Aufgaben:

     1. mode == 0:
        Das DOS_XFS fragt das DFS, ob das Laufwerk geschlossen werden darf.
        Wenn dies nicht erlaubt ist, mu EACCDN geliefert werden, sonst E_OK.
        (ntig z.B. fr Dlock())
        Geffnete Dateien wurden bereits von Kernel und DOS_XFS erkannt,
        d.h. in solch einem Fall wird dfs_drv_close berhaupt nicht
        aufgerufen.

        Aus diesem Grund drften i.A. keine vernderten Sektorpuffer
        existieren, auch keine, die gerade gelesen oder beschrieben werden
        (dies geschieht immer ber Dateien!). In diesem Fall gengt es also,
        immer ein E_OK zu liefern.
        Problematischer wird es, wenn man einen Write-Back-Cache einsetzt.
        Dabei kann es vorkommen, da keine Datei mehr geffnet ist, aber
        noch Puffer belegt sind und zurckgeschrieben werden mssen. Der
        Kernel macht einen Sync- Aufruf (xfs_sync, der weitergegeben
        wird an dfs_sync), bevor die Anfrage gestellt wird; es drften also
        keine vernderten Puffer mehr existieren. Falls doch, sollte das DFS
        aus Sicherheitsgrnden ein EACCDN zurckliefern.

     2. mode == 1:
        Das DOS_XFS erzwingt das Schlieen, das DFS mu E_OK liefern. Es
        drfen keine Caches zurckgeschrieben werden, da das Laufwerk bereits
        ungltig ist.
        (nachdem ein Diskwechsel bereits gemeldet wurde).

     Beim Dlock() wird dfs_drv_close() zunchst mit Modus 0, dann, wenn es
     keinen Fehler gegeben hat, mit Modus 1 aufgerufen.
     Diese Vorgehensweise wird auch dann durchgefhrt, wenn einmal ein
     Mechanismus eingebaut wird, der den Auswurfknopf von
     Wechselplattenlaufwerken oder CD-ROM abfragt und ggf. den Auswurf
     verweigert (meine Sun sagt dann immer: "device busy").

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

     Fr Dfree(). I.A. reicht es, aus dem DD den zugehrigen DMD zu ermitteln
     und den freien Platz auf dem ganzen Laufwerk anzugeben.

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

     Der DOS_XFS hat bereits die Datei angesteuert. Das DFS braucht lediglich
     fr den nchsten Fsnext die reservierten Eintrge dta_usr1 und dta_usr2
     zu initialisieren, damit die Stelle wiedergefunden wird.

     Dateideskriptoren (FDs) knnen in dta_usr nicht verwendet werden, weil
     das Freigeben bei einer "garbage collection" nicht verhindert werden kann.
     Die FDs einfach zu blockieren, ist auch nicht mglich, da man das Ende
     der Fsfirst/-next Operation nicht vorhersagen kann.
     Eine bereits erfolglose Suche kann z.B. durch Lschen von dta_sname
     markiert werden.

     <pos> zeigt bereits auf den nchsten Eintrag, also 32 Bytes hinter
     <dir>. Bei symbolischen Links mu das DFS entsprechend reagieren, in d0
     ELINK bergeben und in a0 einen Zeiger auf den Link. Ein Link beginnt
     mit einem Wort (16 Bit) fr die Lnge des Pfads, gefolgt vom Pfad selbst.

     Achtung: Die Lnge mu INKLUSIVE abschlieendes
              Nullbyte und auerdem gerade sein. Der Link
              mu auf einer geraden Speicheradresse
              liegen.

     Der Puffer fr den Link kann statisch oder auch flchtig sein, da der
     Kernel die Daten sofort umkopiert, ohne da zwischendurch ein
     Kontextwechsel stattfinden kann.

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

     Gesttzt auf die Daten, die dfs_sfirst im reservierten Bereich der DTA
     abgelegt hat, wird die nchste passende Datei gesucht. Dabei kann auf
     Funktionen des DOS_XFS zurckgegriffen werden, die per Dcntl ermittelt
     werden knnen:

          _dir_srch           durchsucht ein Verzeichnis per FD
          reopen_FD           ffnet einen FD
          close_DD            schliet einen FD
          filename_match      vergleicht Dateinamen
          conv_path_elem      wandelt Dateinamen um
          init_DTA            kopiert Daten vom DIR in die DTA

dfs_ext_fd:    DS.L      1    /* erweitere ein Verzeichnis                 */
                              /* a0 = FD *fd                               */
                              /* -> d0 = long errcode                      */

     Wird benutzt, wenn eine Datei angelegt werden soll, aber das Verzeichnis
     bereits voll ist. Wird auerdem beim Anlegen eines Ordners (Dcreate)
     verwendet.

     <fd> ist ein Prototyp-FD, der bereits im exklusiven Modus geffnet ist.
     Die Datei mu erweitert und der neue Platz mit Nullen initialisiert
     werden.

dfs_fcreate:   DS.L      1    /* erstelle Datei oder Verzeichnis           */
                              /* a0 = FD *dd                               */
                              /* a1 = DIR *dir                             */
                              /* d0 = int cmd                              */
                              /* d1 = long arg                             */
                              /* -> d0 = long errcode                      */

     Wird bei Fcreate, Dcreate und Dcntl benutzt. Der DOS_XFS hat bereits im
     Verzeichnis <dd> einen freien Platz gefunden und, zunchst im Speicher,
     den neuen Verzeichniseintrag <dir> erstellt. Die nicht in jedem DFS
     verwendeten Teile des DIR (auch Clusternummer) sind bereits mit Null
     initialisiert. Das DFS hat hier die Gelegenheit, noch Korrekturen
     vorzunehmen und die reservierten DIR- Bereiche je nach Dateityp zu
     initialisieren, bevor der DOS_XFS den ganzen Eintrag in das Verzeichnis
     schreibt.
     Wenn der Aufruf von Dcntl oder Fsymlink kommt, stehen in d0 und a0 die
     entsprechenden Parameter, sonst ist d0 == 0. Wenn d0 == SYMLINK_CREATE
     ist, mu (oder zumindest kann, wenn mglich) ein symbolischer Link
     erstellt werden.

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

     Fr Fxattr. Der DOS_XFS hat bereits alle Informationen, die fr alle
     DFSs identisch sind, in den XATTR eingetragen. xattr_blksize und
     xattr_nblocks mssen vom DFS noch initialisiert werden, xattr_size kann
     z.B. bei Sonderdateien angepat werden.
     xattr_index ist vom DOS_XFS mit dem in Motorola- Format umgewandelten
     dir_stcl initialisiert worden. In vielen Fllen wird es ntig sein, hier
     eine Korrektur vorzunehmen und z.B. einen Zeiger auf einen Treiber oder
     eine globale Datenstruktur zu bergeben.
     Beim Modus d0 == 0 (d.h. folge symbolischen Links) mu der DFS
     entsprechend reagieren und im Fall eines Links in d0 ELINK und in a0 den
     Link zurckgeben.
     Wenn <dir> == NULL ist, hat der DOS_XFS keinen Verzeichniseintrag,
     sondern einen FD ermittelt (z.B. die Root oder eine geffnete Datei).

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

     Gibt einfach einen Index (32 Bit) zu einem DIR- Eintrag zurck. Der
     FAT_DFS nimmt dazu den ent-intellisierten Startcluster.
     <dd> ist das Verzeichnis, in dem die Datei liegt.

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

     Fr Freadlink. d0 ist entweder EACCDN, wenn <dir> kein Symlink ist, oder
     ein anderer Fehlercode.
     Wenn kein Fehler aufgetreten ist, mu in a0 der Link zurckgegeben
     werden, und d0 mu den Wert ELINK haben.

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

     Initialisiert einen Prototyp-FD, und zwar die Felder

          fd_len
          fd_stcl
          fd_attr
          fd_ddev

     und ggf.

          fd_name
          fd_xftype
          fd_xdata usw.

     und ndert ggf. andere Daten des FD.

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

     Die Datei mit dem Verzeichniseintrag <dir> im Verzeichnis <FD> soll
     gelscht werden.
     Fhrt das tatschliche Lschen der Datei durch, das Lschen des
     Verzeichniseintrags und Zugriffsprfungen werden vom DOS_XFS
     durchgefhrt.

dfs_pathconf:  DS.L      1    /* Fr Dpathconf                             */
                              /* a0 = FD *dd                               */
                              /* d0 = int which                            */
                              /* -> d0 = long val oder Fehlercode          */

     Verschiedene Beschrnkungen werden abgefragt, die fr einen bestimmten
     Pfad <dd> gelten. Die meisten Werte fr <which> werden bereits vom
     DOS_XFS eingesetzt, deshalb kommen nur folgende Werte vor:

          DP_IOPEN (0)     maximale Anzahl gleichzeitig offener Dateien
          DP_ATOMIC (4)    interne Blockgre (Sektorgre ?, CLustergre ?)
         ab 21.5.95:
          DP_MODEATTR (7)     zulssige Dateitypen

III Datenstrukturen
===================

1. Der DOS-Gertetreiber (MX_DDEV)
----------------------------------

Der Unter-Gertetreiber (MX_DDEV) wird beim ffnen einer Datei von der DFS-
Funktion dfs_dir2FD in den Dateideskriptor eingesetzt und vom DOS_XFS
aufgerufen. Der MX_DDEV- Gertetreiber mu folgende Funktionen bereitstellen:

     OFFSET

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

     Die Datei wird geffnet, der FD ist bereits initialisiert. Im Open-
     Modus (fd_mode) mu das Bit O_TRUNC ausgewertet werden. Ggf. ist ein
     Fehlercode zurckzugeben, bei Gerten kann O_TRUNC getrost ignoriert
     werden.
     Das Feld fd_fpos ist bereits auf 0L initialisiert. Falls dies nicht
     ausreicht (z.B. merkt sich das FAT_DFS immer den aktuellen Cluster),
     sind die entsprechenden Felder des Benutzerbereichs des FD zu
     initialisieren oder andere Felder des FD anzupassen.

     ddev_open wird sowohl beim ersten ffnen einer Datei aufgerufen (nach
     dfs_dir2FD) als auch beim Duplizieren eines Dateideskriptors (wenn z.B.
     mehrere Programme gleichzeitig auf eine Datei oder ein Verzeichnis
     zugreifen). Nicht jedoch dann, wenn Fdup() aufgerufen wird oder ein
     Programm ein anderes aufruft und dabei geffnete Dateien vererbt
     werden (!). Grund ist, da bei diesen Operationen keine neuen Datei-
     Deskriptoren (FDs) angelegt werden, sondern lediglich mehrere Handles
     bzw. Prozesse auf denselben FD zugreifen.

     Die Vertrglichkeit der Open-Modi (etwa "shared read") wird vom DOS-XFS
     gewhrleistet. Der Gertetreiber kann z.B. den Openmodus derart
     modifizieren, da der FD immer "exklusiv" geffnet ist, oder per Bit
     OM_NOCHECK veranlassen, da er den Openmodus selbst berwachen mchte.
     Wird ddev_open() fr den Prototyp-FD aufgerufen, ist
     fd->fd_multi1 == fd.
     Gibt ddev_open() einen Fehlercode zurck, wird der FD einfach wieder vom
     DOS-XFS freigegeben.

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

     Die Datei wird geschlossen. Die Behandlung von fd_refcnt wird vom
     DOS_XFS bernommen. Der MX_DDEV- Treiber braucht hier lediglich
     eventuelle Puffer zurckzuschreiben.

     Man beachte, da die Aufrufe ddev_open/ddev_close nicht paarweise
     aufzutreten brauchen. Grund ist, da Fdup() oder das Vererben von
     Handles kein ddev_open bewirken, sondern lediglich den fd_refcnt
     inkrementieren. Dagegen wird jedoch fr das Schlieen des Handles
     ein ddev_close aufgerufen, damit eventuelle Puffer zurckgeschrieben
     werden.

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

     siehe dev_read in MGX_XFS.TXT

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

     siehe dev_write in MGX_XFS.TXT.
     Der MX_DDEV braucht sich nicht um eine Aktualisierung des Verzeichnisses
     oder das Datum des letzten Zugriffs zu kmmern.

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

     siehe dev_stat in MGX_XFS.TXT

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

     siehe dev_seek in MGX_XFS.TXT

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

     siehe dev_datime in MGX_XFS.TXT.
     Der MX_DDEV kann hier einfach einen NULL- Zeiger einsetzen, dann fhrt das
     DOS_XFS die Standardprozedur durch.
     Das DOS_XFS setzt Fcntl(FUTIME, ...) auf Fdatime um.

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

     siehe dev_ioctl in MGX_XFS.TXT.
     Es sollten zumindest die Funktionen FTRUNCATE, FIONREAD und FIONWRITE
     untersttzt werden.
     Das DOS_XFS setzt Fcntl(FUTIME, ...) auf Fdatime() und damit auf
     ddev_datime um, d.h. FUTIME braucht von ddev_ioctl nicht direkt
     untersttzt zu werden.

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

     Diese Funktion wird nur vom U_DFS, also dem integrierten DFS-
     Dateisystem fr Laufwerk U: aufgerufen. Wenn man also einen eigenen
     Gertetreiber installiert, ist genau hier der Zeitpunkt gekommen, seinen
     Speicher freizugeben und sich damit aus dem System zurckzuziehen.
     Nheres in MGX_UDFS.TXT.

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

     siehe dev_getc in MGX_XFS.TXT.
     Der MX_DDEV kann hier einfach einen NULL- Zeiger einsetzen, dann fhrt das
     DOS_XFS die Standardprozedur durch, d.h. ruft ddev_read auf.

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

     siehe dev_getline in MGX_XFS.TXT.
     Der MX_DDEV kann hier einfach einen NULL- Zeiger einsetzen, dann fhrt das
     DOS_XFS die Standardprozedur durch, d.h. ruft ddev_read auf.

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

     siehe dev_putc in MGX_XFS.TXT.
     Der MX_DDEV kann hier einfach einen NULL- Zeiger einsetzen, dann fhrt das
     DOS_XFS die Standardprozedur durch, d.h. ruft ddev_write auf.


2. Der Dateideskriptor (FD) bzw. Verzeichnisdeskriptor (DD)
-----------------------------------------------------------

Die Dateideskriptoren werden vom DOS_XFS angelegt und verwaltet. Das DOS_XFS
verwaltet Dateien und Ordner (Unterverzeichnisse) mit Hilfe der gleichen
Datenstruktur. Innerhalb eines DFS siehe ein FD folgendermaen aus (es ist
eine von der Ausgangs- Objektklasse abgeleitete Objektklasse mit weiteren
Eintrgen (vgl. MGX_XFS.TXT).

     OFFSET

fd_dmd:        DS.L      1    /* 0x00: Zeiger auf DMD                      */
fd_refcnt:     DS.W      1    /* 0x04: Ref.zhler frs Schlieen oder -1   */
fd_mode:       DS.W      1    /* 0x06: Open- Modus (0,1,2) und flags       */
fd_dev:        DS.L      1    /* 0x08: Zeiger auf MX_DEV                   */

     die ersten Eintrge entsprechen dem Ur-Objekt, d.h. sind fr alle XFSs
     identisch, weil sie vom Kernel verwendet werden.

; fr alle DFS
; fd_name/attr/next/children
; fd_dirch/time/date/stcl/len sind bei Clones ungltig
; fd_parent/dirpos/dmd sind identisch mit dem Prototyp-FD

fd_ddev:       DS.L      1    /* 0x0c: Zeiger auf MX_DDEV                  */

     Hier mu das DFS beim Aufruf von "dir2FD" den MX_DDEV eintragen, also den
     Gertetreiber.

fd_name:       DS.B      11   /* 0x10: DD_FD: Name im internen Format      */
fd_attr:       DS.B      1    /* 0x1b: Attribut                            */

     Hier wird der Name (8+3) im internen Format sowie das Dateiattribut
     abgelegt. Der Name ist nur gltig, wenn es sich um ein Unterverzeichnis
     handelt.
     Name und Attribut sind nur im "Prototyp-FD", d.h. in fd->multi1 gltig.
     Am Attribut kann man erkennen, ob der FD ein Verzeichnis reprsentiert.
     Der Name der Root (nicht der Rose) ist eine leere Zeichenkette.

fd_owner:      DS.L      1    /* 0x1c: DD_FD: Eigner eines FD oder NULL    */

     Hier wird ein Zeiger auf den Eigner eines FD abgelegt (d.h. ein Zeiger
     auf die Basepage). Ein Wert von NULL bedeutet, da der FD z.Zt. nicht
     belegt ist.

fd_parent:     DS.L      1    /* 0x20: Zeiger auf den Parent-DD_FD         */

     Verkettungszeiger auf den Parent, d.h. auf das Verzeichnis, in dem die
     Datei liegt bzw. das Elterverzeichnis eines Unterverzeichnisses.
     fd_parent ist nur fr den Prototyp- FD gltig.

fd_children:   DS.L      1    /* 0x24: DD_FD: Liste aller Kinder           */

     Liste aller geffneten Dateien und geffneten Unterverzeichnisse.
     fd_children ist nur fr den Prototyp- FD gltig.

fd_next:       DS.L      1    /* 0x28: Zeiger auf FDs im selben Verzeichn. */

     Zeiger auf den nchsten FD im selben Verzeichnis, d.h. auf das nchste
     Geschwist, dieses kann eine geffnete Datei oder ein Unterverzeichnis
     sein, prinzipiell werden keine Unterschiede gemacht.
     fd_next ist nur fr den Prototyp- FD gltig.

fd_multi:      DS.L      1    /* 0x2c: Zeiger auf FD derselben Datei       */

     Wenn eine Datei mehrmals geffnet wird, wird ein "Clone" des Prototyp-
     FD angelegt. Fr diesen Clone sind die meisten Felder des FD ungltig,
     im wesentlichen sind nur Treiber, Modus und Dateiposition gltig.
     fd_multi ist eine verkettete Liste, die mit NULL abgeschlossen ist.

fd_multi1:     DS.L      1    /* 0x30: Zeiger auf erstes Listenelement     */

     Der zugehrige Prototyp-FD, der die gltigen Dateiangaben enthlt. Wenn
     eine Datei nur einmal geffnet ist, gilt: fd->fd_multi1 == fd

fd_fpos:       DS.L      1    /* 0x34: Position des Dateizeigers           */

     Die Position des Dateizeigers, ist 0L bei einem Gert.

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

     Bit 0 zeigt an, ob eine Datei verndert wurde und daher beim Schlieen
     der Datei das Verzeichnis (fd_parent) aktualisiert werden mu (passiert
     nicht, wenn es sich um einen Ordner handelt).
     Die anderen Bits sind reserviert und werden teilweise vom DOS_XFS
     verwendet.

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

     unbenutzt und reserviert.

fd_time:       DS.W      1    /* 0x3a: Zeit  (8086)                        */
fd_date:       DS.W      1    /* 0x3c: Datum (8086)                        */
fd_stcl:       DS.W      1    /* 0x3e: Start- Cluster (68000)              */
fd_len:        DS.L      1    /* 0x40: Dateilnge in Bytes (68000)         */

     Daten aus dem Verzeichniseintrag, Datum und Uhrzeit unverndert, also im
     Intel-Format (strwkcr).

fd_dirpos:     DS.L      1    /* 0x44: Pos. des zug. Eintrags im Directory */

     Position des zugehrigen Eintrags im Parent. Ist nur fr den Prototyp-
     FD gltig.

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

     2 Langworte zur freien Verfgung. Das FAT_DFS speichert hier zustzliche
     Informationen zu fd_fpos ab, und zwar den aktuellen Cluster. Andere DFSs
     knnen andere Daten ablegen.
     Diese Felder sind zunchst auch nur fr den Prototyp- FD gltig, es sei
     denn, beim ffnen (ddev_open) werden die Daten explizit aus dem
     Prototyp- FD in den Clone kopiert.

3. Der Mediumdeskriptor (DMD)
-----------------------------

d_xfs:         DS.L      1    /* 0x00: Der Dateisystemtreiber              */
d_drive:       DS.W      1    /* 0x04: Laufwerknummer 0..25                */
d_root:        DS.L      1    /* 0x06: Zeiger auf DD der Root              */
d_biosdev:     DS.W      1    /* 0x0a: BIOS-Laufwerk oder -1               */
d_driver:      DS.L      1    /* 0x0c: def. zus. mit devcode das Medium    */
d_devcode:     DS.L      1    /* 0x10: z.B. SCSI Target & Laufwerk         */

     wie im Ur-Objekt. Siehe MGX_XFS.TXT.

d_dfs:         DS.L      1    /* 0x14: DOS-spezifischer Dateisystemtreiber */

Gegenber der Ur- Objektklasse ist nur der Eintrag d_dfs hinzugekommen, der
den zugehrigen DFS- Treiber enthlt.

4. Die DTA
----------

Die DTA wird von den alten DOS- Funktionen Fsfirst und Fsnext verwendet,
deren ungeschickte Konzeption durch die MSDOS- Schpfer immer noch wie ein
Fluch auf uns lastet. Die Aufteilung in res1/res2 hat historische Grnde, um
den Aufbau zumindest im DOS_XFS mglichst kompatibel zum alten TOS zu
machen. Fr das DOS_XFS und damit alle DFSs sieht die Struktur folgendermaen
aus:

dta_sname:     DS.B      12   /* 0x00: Suchname     (von Fsfirst)          */
dta_usr1:      DS.L      1    /* 0x0c: zur freien Verwendung               */
dta_usr2:      DS.L      1    /* 0x10: zur freien Verfgung                */
dta_drive:     DS.B      1    /* 0x14: logisches Laufwerk (0..25)          */
dta_attr:      DS.B      1    /* 0x15: gefundenes Attribut                 */
dta_time:      DS.W      1    /* 0x16: gefundene Zeit                      */
dta_date:      DS.W      1    /* 0x18: gefundenes Datum                    */
dta_len:       DS.L      1    /* 0x1a: gefundene Lnge                     */
dta_name:      DS.B      14   /* 0x1e: gefundener Dateiname                */

     Hier stehen 2 Langworte zur freien Verfgung. In <dta_sname> steht der
     Suchname bereits im aktuellen Format.
     In usr1 und usr2 mu die aktuelle Position der Suche eingetragen werden,
     damit ein nachfolgendes Fsnext an der richtigen Stelle weitersucht.

5. Der Verzeichniseintrag (DIR)

Folgende Felder sind bei jedem DFS identisch:

     OFFSET

dir_name:      DS.B     11    /* 0x00: Dateiname                           */
dir_attr:      DS.B      1    /* 0x0b: Attribut                            */
dir_usr1:      DS.W      1    /* 0x0c: zur freien Verwendung               */
dir_usr2:      DS.L      1    /* 0x0e: zur freien Verwendung               */
dir_usr3:      DS.L      1    /* 0x12: zur freien Verwendung               */
dir_time:      DS.W      1    /* 0x16: Zeit  der letzten nderung (Intel)  */
dir_date:      DS.W      1    /* 0x18: Datum der letzten nderung (Intel)  */
dir_stcl:      DS.W      1    /* 0x1a: erster Cluster bzw. andere Info     */
dir_flen:      DS.L      1    /* 0x1c: Dateilnge (Intel)                  */

     Statt des Clusters sind auch andere Angaben mglich. Das DOS_XFS
     behandelt allerdings den Eintrag zunchst wie eine Clusterangabe (fr
     xattr.index und fd_stcl sowie fr das Erstellen der Eintrge "." und
     ".." bei Dcreate). Im Fall Fxattr kann die Angabe vom DFS mit anderen
     Daten berschrieben werden kann.


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

Ein DFS ist einfach ein Programm, das den Treiber installiert und sich
resident beendet.
Die Installation erfolgt durch

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

Der Pfad "U:\\" ist wichtig, weil der Dcntl-Aufruf nicht vom MagiC-Kernel,
sondern vom DOS-XFS ausgefhrt wird. Gibt man z.B. einen Pfad auf einem
Mac-Volume an, wird dieser Dcntl nicht verarbeitet, weil das Mac-XFS
diesen Code nicht kennt.

Man erhlt einen Zeiger auf wichtige DOS_XFS- Funktionen zurck (oder einen
Fehlercode). Die DOS_XFS- Funktionen kann man auch unabhngig von der
Installation eines DFS erfragen ber

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

Die Kernelfunktionen erhlt man ber

     kernel = Dcntl(KER_GETINFO, NULL, NULL);

Die Deinstallation eines DFS ist nicht vorgesehen.
