MagiC ermöglicht wie MultiTOS die Einbindung alternativer Dateisysteme (sog. XFSs). Fest in MagiC 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 MagiC integriert sind, und zwar das FAT-Dateisystem und das U-Dateisystem (das für Laufwerk U:).
Ein DOS-Dateisystem (DFS) wird vom DOS_XFS aufgerufen. Hier stehen nur die Dateifunktionen, während die Verzeichnisverwaltung im wesentlichen vom DOS_XFS übernommen wird. Weitere DFSs können eingebunden werden. Der Aufwand für ein DFS ist wesentlich geringer als für ein XFS, da viele Funktionen vom DOS_XFS bereits ausgeführt werden. Die wesentliche Voraussetzung ist eine DOS-konforme Verzeichnisstruktur (mit 32-Byte-Einträgen und Dateinamen des Formats 8+3). Dieses Kapitel behandelt die Punkte:
Querverweis: XFS-Konzept in MagiC
Da die Implementation eines DFS nur in Assembler erfolgen kann, wird dessen Beschreibung in Assembler-Syntax angegeben:
dfs_name: DS.B 8 /* Untername des DOS-Dateisystems */ dfs_next: DS.L 1 /* nächster Treiber */ dfs_init: DS.L 1 /* Initialisierung */ dfs_sync: DS.L 1 /* synchronisiert das Dateisystem */ dfs_drv_open: DS.L 1 /* neues Laufwerk */ dfs_drv_close: DS.L 1 /* Laufwerk freigeben */ dfs_dfree: DS.L 1 /* für Dfree */ dfs_sfirst: DS.L 1 /* für Fsfirst */ dfs_snext: DS.L 1 /* für Fsnext */ dfs_ext_fd: DS.L 1 /* erweitert ein Verzeichnis */ dfs_fcreate: DS.L 1 /* erstellt ein Verzeichnis oder Datei */ dfs_fxattr: DS.L 1 /* für Fxattr */ dfs_dir2index: DS.L 1 /* für Dreaddir */ dfs_readlink: DS.L 1 /* für Freadlink */ dfs_dir2FD: DS.L 1 /* für Fopen */ dfs_fdelete: DS.L 1 /* für Fdelete und Ddelete */ dfs_pathconf: DS.L 1 /* für Dpathconf */
Querverweis: Aufbau eines XFS MagiC
Name: | »dfs_dfree«
| |||||||||
Parameter: |
| |||||||||
Beschreibung: | Für Dfree(). I.a. reicht es, aus dem DD den zugehörigen
DMD zu ermitteln und den freien Platz auf dem ganzen Laufwerk
anzugeben.
| |||||||||
Gruppe: | Aufbau eines DFS
| |||||||||
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_dir2FD«
|
Parameter: |
|
Beschreibung: | Initialisiert einen Prototyp-FD, und zwar die Felder
und ggf.
Ggfs. werden noch andere Daten des FD verändert. |
Gruppe: | Aufbau eines DFS
|
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_dir2index«
|
Parameter: |
|
Beschreibung: | Gibt einfach einen Index (32 Bit) zu einem DIR-Eintrag zurück.
Der FAT_DFS nimmt dazu den ent-intellisierten Startcluster. <dd>
ist das Verzeichnis, in dem die Datei liegt.
|
Gruppe: | Aufbau eines DFS
|
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_drv_close«
| |||||||||
Parameter: |
| |||||||||
Beschreibung: | Auch diese Funktion erfüllt, abhängig 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 (nötig z.B. für Dlock()). Geöffnete 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 dürften i.A. keine veränderten Sektorpuffer existieren, auch keine, die gerade gelesen oder beschrieben werden (dies geschieht immer über Dateien!). In diesem Fall genügt 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 geöffnet ist, aber noch Puffer belegt sind und zurückgeschrieben werden müssen. Der Kernel macht einen Sync-Aufruf (xfs_sync, der weitergegeben wird an dfs_sync), bevor die Anfrage gestellt wird; es dürften also keine veränderten Puffer mehr existieren. Falls doch, sollte das DFS aus Sicherheitsgründen ein EACCDN zurückliefern. 2. mode == 1: Das DOS_XFS erzwingt das Schließen, das DFS muß E_OK liefern. Es dürfen keine Caches zurückgeschrieben werden, da das Laufwerk bereits ungültig ist. (nachdem ein Diskwechsel bereits gemeldet wurde). Beim Dlock() wird dfs_drv_close() zunächst mit Modus 0, dann, wenn es keinen Fehler gegeben hat, mit Modus 1 aufgerufen. Diese Vorgehensweise wird auch dann durchgeführt, wenn einmal ein Mechanismus eingebaut wird, der den Auswurfknopf von Wechselplattenlaufwerken oder CD-ROM abfragt und ggf. den Auswurf verweigert. | |||||||||
Gruppe: | Aufbau eines DFS
| |||||||||
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_drv_open«
| ||||||
Parameter: |
| ||||||
Beschreibung: | MagiC unterstützt genau 26 gleichzeitig aktive Dateisysteme
denen die Buchstaben 'A'..'Z' zugeordnet sind. Dieser Eintrag hat zwei
Aufgaben:
| ||||||
Gruppe: | Aufbau eines DFS
| ||||||
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_ext_fd«
| ||||||
Parameter: |
| ||||||
Beschreibung: | Wird benutzt, wenn eine Datei angelegt werden soll, aber das
Verzeichnis bereits voll ist. Wird außerdem beim Anlegen eines
Ordners (Dcreate) verwendet.
<fd> ist ein Prototyp-FD, der bereits im exklusiven Modus geöffnet ist. Die Datei muß erweitert und der neue Platz mit Nullen initialisiert werden. | ||||||
Gruppe: | Aufbau eines DFS
| ||||||
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_fcreate«
|
Parameter: |
|
Beschreibung: | Wird bei Fcreate, Dcreate und Dcntl benutzt. Der DOS_XFS hat
bereits im Verzeichnis <dd> einen freien Platz gefunden und,
zunächst 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 Verzeichni 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 möglich) ein symbolischer Link erstellt werden. |
Gruppe: | Aufbau eines DFS
|
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_fdelete«
|
Parameter: |
|
Beschreibung: | Die Datei mit dem Verzeichniseintrag <dir> im Verzeichnis
<FD> soll gelöscht werden. Führt das tatsächliche Löschen
der Datei durch, das Löschen des Verzeichniseintrags und
Zugriffsprüfungen werden vom DOS_XFS durchgeführt.
|
Gruppe: | Aufbau eines DFS
|
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_fxattr«
|
Parameter: |
|
Beschreibung: | Für Fxattr. Der DOS_XFS hat bereits alle Informationen, die
für alle DFSs identisch sind, in den XATTR eingetragen.
xattr_blksize und xattr_nblocks müssen vom DFS noch initialisiert
werden, xattr_size kann z.B. bei Sonderdateien angepaßt werden.
xattr_index ist vom DOS_XFS mit dem in Motorola-Format umgewandelten
dir_stcl initialisiert worden. In vielen Fällen wird es nötig 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 zurückgeben. Wenn dir == NULL ist, hat der DOS_XFS keinen Verzeichniseintrag, sondern einen FD ermittelt (z.B. die Root oder eine geöffnete Datei). |
Gruppe: | Aufbau eines DFS
|
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_init«
|
Parameter: | —
|
Beschreibung: | Reserviert. Enthält im Fall MagiC-interner XFSs deren
Initialisierung. Wird bei nachgeladenen XFSs nicht verwendet.
|
Gruppe: | Aufbau eines DFS
|
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_name«
|
Parameter: | —
|
Beschreibung: | Der Name ist bisher nur Kommentar; er soll irgendwann auch
einmal die Möglichkeit bieten, festzustellen, welche Treiber
installiert sind und wie z.B. der für Laufwerk A: zuständige Treiber
heißt (d.h. was für ein Dateisystem die Diskette enthält).
Der Name des integrierten XFS lautet "DOS_XFS " (auf 8 Zeichen per Leerstellen erweitert). |
Gruppe: | Aufbau eines DFS
|
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_next«
|
Parameter: | —
|
Beschreibung: | Ist einfach ein Verkettungszeiger auf den nächsten Treiber.
Ein neuer Treiber wird vorn eingebunden, hat also immer höchste
Priorität. Damit ist es z.B. möglich, den integrierten DOS-Treiber
zu überladen.
|
Gruppe: | Aufbau eines DFS
|
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_pathconf«
| |||||||||
Parameter: |
| |||||||||
Beschreibung: | Verschiedene Beschränkungen werden abgefragt, die für einen
bestimmten Pfad <dd> gelten. Die meisten Werte für
<which> werden bereits vom DOS_XFS eingesetzt, deshalb kommen
nur folgende Werte vor:
| |||||||||
Gruppe: | Aufbau eines DFS
| |||||||||
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_readlink«
|
Parameter: |
|
Beschreibung: | Für Freadlink. d0 ist entweder EACCDN, wenn <dir> kein
Symlink ist, oder ein anderer Fehlercode. Wenn kein Fehler aufgetreten
ist, muß in a0 der Link zurückgegeben werden, und d0 muß den Wert
ELINK haben.
|
Gruppe: | Aufbau eines DFS
|
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_sfirst«
|
Parameter: |
|
Beschreibung: | Der DOS_XFS hat bereits die Datei angesteuert. Das DFS braucht
lediglich für den nächsten Fsnext die reservierten Einträge
dta_usr1 und dta_usr2 zu initialisieren, damit die Stelle
wiedergefunden wird.
Dateideskriptoren (FDs) können 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 möglich, da man das Ende der Fsfirst/Fsnext Operation nicht vorhersagen kann. Eine bereits erfolglose Suche kann z.B. durch Löschen von dta_sname markiert werden. <pos> zeigt bereits auf den nächsten 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) für die Länge des Pfads, gefolgt vom Pfad selbst. Achtung: Die Länge muß INKLUSIVE abschließendes Nullbyte und außerdem gerade sein. Der Link muß auf einer geraden Speicheradresse liegen. Der Puffer für den Link kann statisch oder auch flüchtig sein, da der Kernel die Daten sofort umkopiert, ohne daß zwischendurch ein Kontextwechsel stattfinden kann. |
Gruppe: | Aufbau eines DFS
|
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_snext«
| ||||||||||||
Parameter: |
| ||||||||||||
Beschreibung: | Gestützt auf die Daten, die dfs_sfirst im reservierten Bereich
der DTA abgelegt hat, wird die nächste passende Datei gesucht.
Dabei kann auf Funktionen des DOS_XFS zurückgegriffen werden, die per
Dcntl ermittelt werden können:
| ||||||||||||
Gruppe: | Aufbau eines DFS
| ||||||||||||
Querverweis: | DFS-Konzept in MagiC
|
Name: | »dfs_sync«
| ||||||
Parameter: |
| ||||||
Beschreibung: | Der Kernel hat dem DOS_XFS mitgeteilt, daß auf Laufwerk
<d> alle Puffer zurückzuschreiben 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.
Zurückgeliefert wird ein Fehlercode. Wenn das DFS keine Pufferverwaltung hat (z.B. eine RAMDisk), muß eine 0 geliefert werden. | ||||||
Gruppe: | Aufbau eines DFS
| ||||||
Querverweis: | DFS-Konzept in MagiC
|
Bei der Arbeit mit einem DFS sind die folgenden Datenstrukturen wichtig:
Querverweis: XFS-Strukturen
Die folgenden Felder sind bei jedem DFS identisch:
dir_name: DS.B 11 /* 0x00: Dateinname */ 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: Dateilänge (Intel) */
Hinweis: Statt des Clusters sind auch andere Angaben möglich. Das DOS_XFS behandelt allerdings den Eintrag zunächst wie eine Clusterangabe (für xattr.index und fd_stcl sowie für das Erstellen der Einträge "." und ".." bei Dcreate). Im Fall Fxattr kann die Angabe vom DFS mit anderen Daten überschrieben werden.
Querverweis: DFS-Konzept in MagiC
Der Unter-Gerätetreiber (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-Gerätetreiber muß folgende Funktionen bereitstellen:
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;
Querverweis: DFS-Konzept in MagiC XFS-Konzept in MagiC
Name: | »ddev_open«
| ||||||
Parameter: |
| ||||||
Beschreibung: | Die Datei wird geöffnet, der FD ist bereits initialisiert. Im
Open-Modus (fd_mode) muß das Bit O_TRUNC ausgewertet werden. Ggf. ist
ein Fehlercode zurückzugeben, bei Geräten 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). Die Verträglichkeit der Open-Modi (etwa shared read) wird vom Kernel gewährleistet. Der Gerätetreiber kann z.B. den Openmodus derart modifizieren, daß der FD immer "exklusiv" geöffnet ist, oder per Bit OM_NOCHECK veranlassen, daß er den Openmodus selbst überwachen möchte. Wird ddev_open für den Prototyp-FD aufgerufen, ist fd->fd_multi1 == fd. Gibt ddev_open einen Fehlercode zurück, wird der FD einfach wieder vom DOS-XFS freigegeben. | ||||||
Gruppe: | DOS-Gerätetreiber
| ||||||
Querverweis: | —
|
Die Datei wird geschlossen. Die Behandlung von fd_refcnt wird vom DOS_XFS übernommen. Der MX_DDEV-Treiber braucht hier lediglich eventuelle Puffer zurückzuschreiben.
Parameter-Übergabe:
a0 | = | FD *file, |
-> d0 | = | long errcode |
Siehe dev_read.
Parameter-übergabe:
a0 | = | FD *file |
d0 | = | long count |
a1 | = | char *buffer |
-> d0 | = | long amount |
Siehe dev_write. Der MX_DDEV braucht sich nicht um eine Aktualisierung des Verzeichnisses oder das Datum des letzten Zugriffs zu kümmern.
Parameter-Übergabe:
a0 | = | FD *file |
d0 | = | long count |
a1 | = | char *buffer |
-> d0 | = | long amount |
Siehe dev_stat.
Parameter-übergabe:
a0 | = | FD *file |
a1 | = | MAGX_UNSEL *unselect oder NULL |
d0 | = | int rwflag |
d1 | = | long apcode |
-> d0 | = | long status |
Siehe dev_seek.
Parameter-Übergabe:
a0 | = | FD *file |
d0 | = | long where |
d1 | = | int mode |
-> d0 | = | long position |
Siehe dev_datime. Der MX_DDEV kann hier einfach einen NULL-Zeiger einsetzen, dann führt das DOS_XFS die Standardprozedur durch. Das DOS_XFS setzt Fcntl(FUTIME, ...) auf Fdatime um.
Parameter-Übergabe:
a0 | = | FD *file |
a1 | = | int d[2] |
d0 | = | int setflag |
-> d0 | = | long errcode |
Siehe dev_ioctl. Es sollten zumindest die Funktionen FTRUNCATE, FIONREAD und FIONWRITE unterstützt werden. Das DOS_XFS setzt Fcntl(FUTIME, ...) auf Fdatime() und damit auf ddev_datime um, d.h. FUTIME braucht von ddev_ioctl nicht direkt unterstützt zu werden.
Parameter-Übergabe:
a0 | = | FD *file |
d0 | = | int cmd |
a1 | = | void *buf |
-> d0 | = | long errcode |
Diese Funktion wird nur vom U_DFS, also dem integrierten DFS-Dateisystem für Laufwerk U: aufgerufen. Wenn man also einen eigenen Gerätetreiber installiert, ist genau hier der Zeitpunkt gekommen, seinen Speicher freizugeben und sich damit aus dem System zurückzuziehen.
Parameter-übergabe:
a0 | = | FD *directory |
a1 | = | DIR *dir |
-> d0 | = | long errcode |
Siehe dev_getc. Der MX_DDEV kann hier einfach einen NULL-Zeiger einsetzen, dann führt das DOS_XFS die Standardprozedur durch, d.h. ruft ddev_read auf.
Parameter-übergabe:
a0 | = | FD *file |
d0 | = | int mode |
-> d0 | = | unsigned long c |
Siehe dev_getline. Der MX_DDEV kann hier einfach einen NULL-Zeiger einsetzen, dann führt das DOS_XFS die Standardprozedur durch, d.h. ruft ddev_read auf.
Parameter-Übergabe:
a0 | = | FD *file |
a1 | = | char *buf |
d1 | = | long size |
d0 | = | int mode |
-> d0 | = | long amount |
Siehe dev_putc. Der MX_DDEV kann hier einfach einen NULL-Zeiger einsetzen, dann führt das DOS_XFS die Standardprozedur durch, d.h. ruft ddev_write auf.
Parameter-Übergabe:
a0 | = | FD *file |
d0 | = | int mode |
d1 | = | long value |
-> d0 | = | unsigned long count |
Die DTA wird von den alten DOS-Funktionen Fsfirst und Fsnext verwendet, deren ungeschickte Konzeption durch die MSDOS-Schöpfer immer noch wie ein Fluch auf dem System lastet. Die Aufteilung in res1/res2 hat historische Gründe, um den Aufbau zumindest im DOS_XFS möglichst kompatibel zum alten TOS zu machen. Für das DOS_XFS und damit alle DFSs sieht die Struktur folgendermaßen 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 Verfügung */ 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 Länge */ dta_name : DS.B 14 /* 0x1e: gefundener Dateiname */
Hinweis: Hier stehen 2 Langworte zur freien Verfügung. In dta_sname steht der Suchname bereits im aktuellen Format. In dta_usr1 und dta_usr2 muß die aktuelle Position der Suche eingetragen werden, damit ein nachfolgendes Fsnext an der richtigen Stelle weitersucht.
Querverweis: DFS-Konzept in MagiC
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 ausgeführt wird. Man
erhält einen Zeiger auf wichtige XFS-Funktionen zurück, oder einen
Fehlercode.
Die DOS_XFS-Funktionen kann man auch unabhängig von der
Installation eines DFS erfragen über:
dosfunctions = Dcntl(DFS_GETINFO, "U:\\", NULL);
Per kernel = Dcntl (KER_GETINFO, NULL, NULL) erhält man
die Kernelfunktionen.
Die Deinstallation eines DFS ist nicht vorgesehen.