Dem GEMDOS auf der Spur, Teil 4

Diesmal erfahren Sie alles über die leistungsfähigen Datei-, Ordner- und Laufwerks-Funktionen des GEMDOS. Wir erklären, wie Sie Dateien verschieben und Dateiattribute verändern. Außerdem lernen Sie verschiedene Datei-Hilfsfunktionen kennen.

Nachdem der letzte Kursteil Aufschluß über die grundlegenden Funktionen des GEMDOS gab, beginnen wir diesmal mit der Kategorie der Datei-Hilfsfunktionen. Die Funktion »Fdelete« (GEMDOS $41) dient zum Löschen einer Datei. Dabei übergeben Sie lediglich den Dateipfad: Die Anweisung »Fdelete("C:\PFAD\HELLO.C");« löscht etwa die Datei »HELLO.C« im Ordner »PFAD« auf dem Laufwerk C. Als Ergebnis erhalten Sie den Wert 0 (Datei wurde gelöscht) oder eine Fehlernummer zurück. Die Bedeutung der Fehlernummern finden Sie im vorherigen Teil dieser Serie. »Fdelete()« löscht nicht die Daten der Datei, sondern lediglich drei Informationen auf dem Massenspeicher, um den Speicherplatz für neue Dateien nutzbar zu machen. Zum einen überschreibt GEMDOS den ersten Buchstaben des Dateinamens im Inhaltsverzeichnis mit dem Wert $e5. Dieser signalisiert dem Betriebssystem stets einen freien Eintrag im Inhaltsverzeichnis. Zudem setzt GEMDOS die Dateilänge auf Null. Außerdem löscht diese Funktion in der FAT die Clusterverkettung der angegebenen Datei. Beim Zurückholen einer gelöschten Datei stellt das Rekonstruieren dieser Information das größte Problem dar. Dabei rührt GEMDOS die Startcluster-Information der gelöschten Datei im Inhaltsverzeichnis nicht an. Da die Datei-Rekonstruktion mühevoll ist, gibt es einige Programme, die diese Prozedur automatisch durchführen.

GEMDOS kennt drei weitere Datei-Hilfsfunktionen: »Frename()« (GEMDOS $56), »Fattrib()« (GEMDOS $43) und »Fdatime()« (GEMDOS $57). Die erste Funktion dient zum Umbennen oder Verschieben einer Datei. Sie erwartet dazu drei Parameter: einen Integerwert (reserviert, enthält stets den Wert 0, den ursprünglichen und den neuen Dateipfad). Beim bloßen Umbennen einer Datei geben Sie lediglich die Dateinamen (etwa »MANTA.PRG« in »EY.TOS«) an. Wollen Sie die Datei jedoch in einen anderen Ordner verschieben, so geben Sie im dritten Parameter den neuen Pfad und den neuen Namen an. Der Funktionsaufruf »Frename(0, "MIST.PRG","\TRASH\MUELL2.PRG");« verschiebt die Datei »MIST.PRG« in den Ordner »\TRASH« und benennt sie in »MUELL2.PRG« um. Der Backslash (»\«) vor dem Ordner sagt GEMDOS, daß »TRASH« im Wurzelverzeichnis des aktuellen Laufwerks liegt. Beachten Sie jedoch, daß das Verschieben nur innerhalb des selben logischen Laufwerks - etwa von C: nach C: - funktioniert. Dies liegt daran, daß GEMDOS nicht die Daten der Datei verschiebt, sondern lediglich den entsprechenden Eintrag vom urspünglichen in das neue Inhaltsverzeichnis überträgt.

Die GEMDOS-Funktion »Fattrib()« erlaubt das Lesen und Schreiben der Dateiattribute. Dazu übergeben Sie drei Parameter: Mit dem ersten bestimmen Sie den Dateipfad und -namen. Der zweite Parameter - ein Integer-Wert - gibt den Modus an: 0 für Abfragen und 1 für Setzen der Attribute. Die neuen Dateiattribute übergeben Sie im letzten Parameter, der ebenfalls ein Integer-Wert ist. Eine Übersicht der Bitbelegung der Attribute finden Sie in Tabelle 1.

Das Archivbit unter TOS 1.2 und 1.4

Einer Erklärung bedarf bei den Dateiattributen besonders das Archiv-Bit. Wie auch sein »Pate« MS-DOS verwendet GEMDOS dieses Attribut, um gerade beschriebene Dateien zu markieren. Ein Backup-Programm kann dieses Attribut mit »Fattrib()«, abfragen, um festzustellen, ob es für die entsprechende Datei eine Sicherheitskopie anlegen muß. Bis einschließlich des Blitter-TOS löschte GEMDOS das Archiv-Bit bei jeder Veränderung der Datei - im Gegensatz zu MSDOS, das es setzt. Erst seit TOS 1.4 verhält sich GEMDOS wie MS-DOS, was zu Problemen mit älterer Software führen kann. Sie sollten deshalb mit Ihrem Backup-Programm prüfen, ob es auch die richtigen Dateien kopiert.

Bit Wert Bezeichnung Bedeutung
0 $1 READONLY Datei ist schreibgeschützt
1 $2 HIDDEN Datei ist versteckt
2 $4 SYSTEM Systemdatei
3 $8 VOLUME Datei dient als Diskettenname
4 $10 SUBDIR Eintrag ist Unterverzeichnis
5 $20 ARCHIVE Datei wurde beschrieben

Tabelle 1. In dieser Übersicht finden Sie die Bitbelegung des Dateiattributs

Wenden wir uns der letzten noch nicht behandelten Datei-Hilfsfunktion »Fdatime()« zu: Sie liefert oder setzt das Datum und die Uhrzeit (im folgenden zusammenfassend als Datum bezeichnet) der letzten Veränderung an einer bestimmten Datei. Als Parameter übergeben Sie der Funktion einen Zeiger auf einen Datenpuffer, das Datei-Handle, und einen Integerwert, der als Flag dient. Als Ergebnis erhalten Sie den Wert 0 oder eine Fehlernummer. Das als Parameter benötigte Datei-Handle erhalten Sie mit der »Fopen()«-Funktion; dadurch ist die Datei eindeutig bestimmt. Besitzt das Flag den Wert 0, so liefert die Funktion das Dateidatum, hat es den Wert 1, so setzt sie das Datum. Abhängig davon hat der Datumspuffer zwei verschiedene Aufgaben: Beim Abfragen erhalten Sie dort das in vier Byte codierte Datum im GEMDOS-Format zurück; beim Setzen des Datums erwartet GEMDOS in diesem Puffer das bereits codierte neue Datum. Assembler-Programmierer können statt eines Puffers auch einen Stackbereich angeben, etwa durch:

subq.l	#$4, sp	; Puffer reservieren
move.l	sp, a3	; für nachher merken
clr.w	-(sp)	; Parameter 3: Das Flag
pea	(a3)	; P. 2: Die Pufferadresse
move.w	handle, -(sp)	; P. 3: Das Dateihandle
move.w	#$57, -(sp)	; Funktionsnummer
bsr	GEMDOS	; GEMDOS-Aufruf
addq.w	#$a, sp	; Stack aufräumen
	... auswerten des Datumspuffers (a3) ...
addq.l	#$4, sp	; Puffer wieder freigeben

In Tabelle 2 finden Sie eine Aufschlüsselung der vier Byte. Das folgende C-Listing wertet Datum und Zeit einer Datei aus.

#include <tos.h>
#include <stdio.h>
int main()
{
	DOSTIME timeptr;
	int handle, time, date;
	int Tag, Monat, Jahr, Sec, Minuten, Stunden;
	handle = Fopen ("FDATIME.C",0);	/* Datei öffnen */
	Fdatime (&timeptr, handle, 0);	/*Datum u. Zeit ermitteln */
	time = timeptr.time;
	date = timeptr.date;
	Tag = date & 31;
	Monat = (date >> 5) & 15;
	Jahr = 1980 + ((date >> 9) & 63)
	Sec = (time & 31) *2;
	Minuten = (time >> 5) & 63;
	Stunden = (time >> 11) & 31;
	printf ("\n%d.%d.%d%d : %d.%d", Tag, Monat, Jahr, Stunden, Minuten, Sec);
	getchar();
	Fclose (handle);
	return 0;
}

Listing 1. Decodierung des Datums und der Zeit nach Aufruf von »Fdatime«

Bitnummer 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
Uhrzeit S S S S S M M M M M M s s s s s
Datum J J J J J J J M M M M T T T T T

Wertebereiche
S = Stunden (0-23) M = Minuten (0-59) s = Sekunden (0-59)
J = Jahr (0-119; 0 = 1980) M = Monat (1 - 12) T = Tag (1-31)

Tabelle 2. Aufschlüsselung der vier Byte, die »Fdatime«zurückliefert

Die Ordnerfunktionen

Eine weitere Funktionenkategorie des GEMDOS bezieht sich auf die Verwaltung der Laufwerke, Ordner und Pfade. Wie sämtliche Dateifunktionen mit dem Buchstaben »F« für »File« beginnen, besitzen die folgenden ein »D« für »Directory« oder »Drive« am Anfang ihres Funktionsnamens.

Befassen wir uns zunächst mit der Funktion »Dcreate()« (GEMDOS $39). Sie dient zum Erzeugen eines neuen Ordners. Dazu übergeben Sie lediglich den Pfad. Mit »Dcreate("C:\SUBI\NEUSUB2");« legen Sie auf dem Laufwerk »C:« im Ordner »SUBI « den neuen Unterordner »NEUSUB2« an. Wie bei nahezu allen GEMDOS-Funktionen erhalten Sie auch bei »Dcreate« den Wert 0 (kein Fehler) oder eine Fehlernummer als Ergebnis zurück. Zum Löschen eines Ordners stellt GEMDOS die Funktion »Ddelete()« (GEMDOS $3a) zur Verfügung. Auch sie erwartet lediglich die Pfadangabe als Parameter. Bei der Verwendung von »Ddelete()« sollten Sie jedoch drei Punkte beachten:

Offset Bezeichnung Bedeutung
0 b_free Anzahl freier Cluster auf dem Laufwerk
4 b_total Gesamtzahl der Cluster
8 b_secsize Anzahl Byte pro Sektor
12 b_clsiz Anzahl Sektoren pro Cluster

Tabelle 3. Die Bedeutung der durch die »Dfree«-Funktion erhaltenen vier Langwort-Informationen

Eine besonders nützliche Funktion ist »Dfree()« (GEMDOS $36). Sie informiert Sie über den freien Speicher des angegebenen Laufwerks. Als Parameter übergeben Sie einen Zeiger auf einen Datenpuffer, in den GEMDOS die gewünschten Informationen ablegt, sowie die Nummer des zu überprüfenden Laufwerks. GEMDOS versieht jedes logische Laufwerk mit einer Nummer: Laufwerk A entspricht Nummer 0, Laufwerk B der Nummer 1 etc. Die Nummern der logischen Laufwerke reichen von 0 bis 15 (»A: bis P:«). Die Belegung des Puffers finden Sie in Tabelle 3. Besonderer Erklärung bedarf in diesem Zusammenhang der Ausdruck »Cluster«: GEMDOS speichert Daten nicht in Sektoren, sondern in Clustern. Unter ihnen versteht man zu einer Einheit zusammengefaßte Sektoren - normalerweise zwei. Die Verwendung von Clustern anstatt Sektoren verhindert, daß eine Datei zu sehr auf einem Laufwerk zerstückelt wird - und hebt somit die Zugriffsgeschwindigkeit stark an. Durch die von »Dfree()« erhaltenen Informationen sind Sie auch in der Lage, die Größe eines Clusters in Byte zu berechnen: »b_clsiz * b_secsiz«. Viele C-Implementationen (etwa Turbo-C) besitzen bereits eine vordefinierte Datenstruktur namens »DISKINFO« (in »tos.h« oder »osbind.h«) für die Pufferinformationen.

Mit der Funktion »Dsetdrv()« (GEMDOS $e) wählen Sie das aktuelle Laufwerk aus. Dazu übergeben Sie der Funktion die Laufwerksnummer (0 bis 15). Als Ergebnis erhalten Sie einen Integerwert zurück. Jedes der 16 Bit des Rückgabewertes repräsentiert dabei ein logisches Laufwerk: Bit 0 für A:, Bit 1 für B: etc. Ist das entsprechende Bit gesetzt, so ist das Laufwerk vorhanden, ansonsten hat GEMDOS das Laufwerk nicht erkannt. Besitzer von nur einem Diskettenlaufwerk bemerken, daß GEMDOS dennoch Bit 1 setzt, somit also Laufwerk B: anscheinend vorhanden ist. Tatsächlich emuliert GEMDOS ein Laufwerk B:, falls dieses nicht angeschlossen ist.

Direkt in Verbindung mit »Dsetdrv()« steht die Funktion »Dsetpath()« (GEMDOS $3b), mit der Sie den aktuellen Pfad bestimmen. »Dsetpath()« erwartet als Parameter nur den Pfadnamen. GEMDOS verwaltet für jedes logische Laufwerk einen eigenen aktuellen Pfad. Mit der Befehlskombination

Dsetdrv(2);	/* Wechsel zu Laufwerk C: */
Dsetpath ("\CSUB1");	/* Verzweige in Ordner CSUBI */
Dsetdrv (3);	/* Wechsel zu Laufwerk D: */
Dsetpath ("\DSUB1");	/* Verzweige in Ordner DSUB2 */
Dsetdrv (2);	/* Wechsel zu Laufwerk C: (CSUB1) */

Verwaltet GEMDOS zwei unterschiedliche Pfade für zwei verschiedene Laufwerke. Zum Schluß befinden Sie sich auf dem Laufwerk C: im Ordner »CSUBI«. Zum Abfragen des aktuellen Laufwerks oder Pfads kennt GEMDOS die beiden Funktionen »Dgetdrv()« (GEMDOS $19) und »Dgetpath()« (GEMDOS $47). »Dgetdrv()« benötigt keine Parameter, sondern liefert die Nummer des aktuellen Laufwerks zurück (0 für A:, 1 für B: bis 15 für P:). Die Funktion »Dgetpath()« liefert den aktuellen Pfad des angegebenen Laufwerks zurück. Dazu verlangt sie zwei Parameter: einen Zeiger auf einen Puffer und die Nummer des gewünschten Laufwerks.

Die Laufwerksnumerierung hat sich bei dieser Funktion allerdings um 1 verschoben, da der Wert 0 für das aktuelle Laufwerk steht - Laufwerk A: entspricht nun also dem Wert 1. Die Funktion liefert den Pfadnamen im angegebenen Puffer ab. Dieser muß mindestens 64 Byte - sollte jedoch stets 128 Byte groß sein. Der Pfadname ist mit dem Zeichen CHR$(0) abgeschlossen. (ah)


Martin Backschat
Aus: TOS 10 / 1991, Seite 88

Links

Copyright-Bestimmungen: siehe Über diese Seite