Suche:

Sie sind hier: Home > Helpdesk > Ratgeber > Zum Archiv > Alles ueber lange Dateinamen

Hintergrundartikel:

DOS-Programme und lange Dateinamen? Kein Problem!

Der Umgang mit langen Dateinamen ist nicht nur Windows-Applikationen vorbehalten. Auch ganz normale DOS-Programme können hervorragend damit arbeiten.

Welches ist das unbeliebteste Zeichen des PC-Zeichensatzes? Die Tilde, was sonst! Dabei wusste vor ein paar Jahren kaum jemand, dass es ein solches "Schnörkel" überhaupt gibt. Dank MS ist das nun aber anders und die Anwendergemeinde darf sehen, wie sie mit ihrer 16-Bit-Software und den abgewürgten langen Dateinamen zurecht kommt. Was kommerzielle Applikationen und Tools anbelangt, so wird man wohl an der Tilde bzw. einer Neuanschaffung nicht vorbeikommen. Handelt es sich bei der "veralteten" Software jedoch um Eigenentwicklungen, so kann man deren Methusalem-Syndrom sofort abstellen. Denn alles was man hierzu benötigt, steckt bereits im in Windows 9x enthaltenen MS-DOS 7.x


Daß auch DOS-Programme locker mit langen Dateinamen umgehen können, zeigt beispielsweise der DOS-Editor von Windows 95

Auch DOS kennt lange Dateinamen
Für den Umgang mit den langen Dateinamen von Windows 95 bietet das API von MS-DOS 7 rund zwei Dutzend neue Funktionen. Dabei ist die Bezeichning "neu" fast schon zu weit gegriffen, denn eigentlich handelt es sich größtenteils um Frischzellenkuren alter Bekannter wie beispielsweise "Verzeichnis anlegen/wechseln/löschen" oder "Verzeichnissuche starten/fortsetzen". Das spiegelt sich sogar in der jeweiligen Funktionsnummer der Neuen wieder: Ermittelte man bisher das aktuelle Verzeichnis mit AH=47h, so ist jetzt AX=7147h zu verwenden. Analog dazu wurde aus AH=41h zum Löschen einer Datei AX=7141h. Kurz - jeder, der schon einmal mit Interrupt 21h gespielt hat, wird sich sofort wie zuhause fühlen.

Neben den abgewandelten Funktionsnummern gibt es aber noch ein weitere wichtige Änderung: Zum Speichern der Verzeichnis- und Dateinamen benötigt man natürlich mehr Platz. Mußten bislang lediglich 13 Zeichen hierfür reserviert werden (Name + Punkt + Erweiterung + Null), so sind es jetzt 255 Byte für Dateinamen und 260 Byte für Verzeichnisse (Beliebiger Name + Null). Das sind die offiziellen Werte. In der Praxis liegt die Grenze dagegen bei genau 250 nutzbaren Zeichen - selbst wenn die Datei bzw. das Verzeichnis direkt im Hauptverzeichnis angelegt wird.

Die LFN-Funktionen im Detail - Verzeichnissuche
Der Unterschied zwischen Programmen, die mit langen Dateinamen umgehen können und solchen, die es nicht können, zeigt sich wohl am deutlichsten beim Einlesen eines Verzeichnisses. Zur Erinnerung: In 16-Bit-Zeiten benutzte man hierfür die DOS-Funktion "Find first" mit AH=4Eh zum Beginnen einer Verzeichnissuche. Jedes weitere Element wurde über "Find next" mit AH=4Fh ermittelt. Das gleiche gilt auch im großen und ganzen für die Anwendung der entsprechenden LFN-Funktionen - allerdings gibt es jetzt etwas mehr Komfort.

Die Verzeichnissuche wird mit AX=714Eh des Interrupt 21h gestartet. Wie zuvor zeigt DS:DX auf eine nullterminierte Zeichenkette (ASCIZ-String) mit der Suchmaske, beispielsweise "*.TXT". Neu ist allerdings, daß man nicht nur alle möglichen Dateiattribute (Register CL) wie "versteckt" oder "Verzeichnis" angeben kann, sondern auch alle erforderlichen (Register CH). Dieser Schritt war längst überfällig, denn somit hat man endlich die Möglichkeit, eine Suche nach einer bestimmten Eintragsgattung auch in einem einzigen Durchgang durchführen zu können: Möchte man beispielsweise alle Ordnernamen eines Verzeichnisses ermitteln, so gibt man als mögliche Attribute "versteckt", "systembezogen" und "Verzeichnis" an und als erforderliches Attribut nur "Verzeichnis". Dadurch werden nur die Einträge geliefert, die auch tatsächlich Verzeichnisnamen darstellen, egal ob sie normal, versteckt oder systembezogen sind (In der alten Funktionsweise erhielt man im gezeigten Beispiel nicht nur Verzeichnisnamen, sondern auch die Namen aller Dateien geliefert). Die ermittelten Eintragsdaten werden in einem speziellen Record abgelegt (siehe Tabelle 1). Dieser landet aber nicht mehr zwangsweise in der Disk Transfer Area (DTA), sondern in einem durch das Registerpaar ES:DI festlegbaren Bereich.

Im Gegensatz zu DOS kennt Windows 95 nicht nur den letzten Änderungszeitpunkt eines Objekts, sondern auch den Zeitpunkt der Erstellung und des letzten Lesezugriffs. Außerdem wurde ordentlich an der Auflösung gedreht: In einem normalen FAT-Eintrag ist der Änderungszeitpunkt auf zwei Sekunden genau eingetragen. Unter Windows 95s VFAT dagegen liegt die Auflösung bei 100 Nanosekunden und ist damit also 20.000.000 mal feiner. Da jeder der neuen Zeiteinträgen jetzt insgesamt 8 Byte groß ist, hat man aber trotz aller Genauigkeit für die nächsten 58.000 Jahre Platz - der Umstieg auf das Jahr 3.000 dürfte sich somit etwas unproblematischer als in 3 Jahren darstellen (Hoffentlich erinnert man sich dann noch an Windows 95). Als Datumsbasis wird zudem nicht länger der 1.1.1980 benutzt, sondern der 1.1.1601 - hier wollte man wohl in die Nähe des Anbeginns des gregorianischen Kalenders rücken. Da die wenigsten 16-Bit-Programme auf ein solch bombastisches Kalendarium vorbereitet sind, gibt es aber noch ein Hintertürchen: Wird die Suche mit SI=0 begonnen, so stehen im Such-Record zwar die neuen 64-Bit-Zeitwerte, doch mit SI=1 erhält man das ganze - wie gehabt - auf dieses Jahrhundert heruntergebrochen. Dabei landet die (DOS-kompatible) letzte Änderungszeit in den niedrigsten beiden Bytes des 8-Byte-Zeiteintrags, gefolgt vom 16-Bit-Datum.

Neben den in Tabelle 1 gezeigten Daten erhält man aber noch weitere Daten von der Suchstartfunktion zurück, die es in deren 16-Bit-Fassung bislang nicht gab: In Register AX wird jetzt ein Such-Handle übergeben und über CX wird man über den Umgang mit nicht umwandelbaren Unicode-Zeichen unterrichtet. Durch das Such-Handle hat man (nun endlich) die Möglichkeit, mehrere Suchen gleichzeitig auführen zu können - es wird an die Folgefunktion "Find next" übergeben. Damit das Handle und die damit zusammenhängenden Datenstrukturen nach Gebrauch auch wieder freigegeben werden können, wurde allerdings eine weitere, wirklich neue Funktion nötig: "Find close" (AX=71A1h).
Vom Format der Unicode-Umwandlung (Register CX) sind bislang nur die ersten beiden Bits belegt - Bit 0 steht dabei für lange Dateinamen, Bit 1 für kurze: Ist ein solches Bit gesetzt, so werden nicht konvertierbare Zeichen im entsprechenden Namen als Unterstriche ("_") dargestellt. Die genaue Registerbelegung dieser drei und aller anderen neuen LFN-Funktionen ist in Tabelle 2 noch einmal detailliert aufgeführt.

Verzeichnisse - erstellen, wechseln, löschen und abfragen
Die Anwendung der vier genannten Funktionen unterscheiden sich von Ihren Vettern, die nur mit kurzen Dateinamen umgehen können, lediglich in der Funktionsnummer:

  • Erstellen AH=39h AX=7139h
  • Wechseln AH=3Ah AX=713Ah
  • Löschen AH=3Bh AX=713Bh
  • Abfragen AH=47h AX=7147h

Für die ersten drei Funktionen wird der betreffende Pfad wie gewohnt als nullterminierte Zeichenkette über den Zeiger DS:DX übergeben. Beim Abfragen des aktuellen Verzeichnisses landet er dagegen an der Position DS:DI. Dabei ist zu beachten, daß die maximale Länge eines Pfades nicht mehr auf 64 Zeichen begrenzt ist. Es sind hierfür (laut offizieller Darstellung) 260 Byte zu reservieren.

Dateien - erstellen/öffnen, schließen, umbenennen und löschen
Zum Öffnen bzw. Erstellen von Dateien bietet MS-DOS aufgrund seiner Geschichte einen ganzen Satz an unterschiedlich leistungsfähigen Funktionen. Zum Glück hat man sich aber darauf beschränkt, nur die neueste auf LFN-Niveau zu bringen. "Create/open file" wurde bislang mit AH=6C00h aufgerufen. Analog zu den vorangegangenen Beispielen reagiert deren LFN-Version auf AX=7C6Ch. Der nullterminierte Name der anzulegenden bzw. zu öffnenden Datei wird wie zuvor über den Zeiger DS:SI übergeben. Ebenfalls unverändert ist die Belegung von BX mit dem Zugriffsmodus und den Flags für gemeinsamen Zugriff, CX mit den Dateiattributen (Tabelle 1) und DX mit der vorzunehmenden Aktion. Neu hinzugekommen sind diverse Flags in den soeben genannten Registern sowie ein Wert in DI für die gewünschte numerischen Erweiterung des betreffenden kurzen Dateinamens.

Die Belegung der einzelnen Zugriffs/Sharing-Bits in BX sind in Tabelle 3 aufgeführt. Die in DX zu übergebende Aktion wird wie folgt definiert:

Aktion, falls Datei nicht existiert (Bits 7-4):
0000 mit Fehler abbrechen
0001 Datei erstellen

Aktion, falls Datei existiert (Bits 3-0):
0000 mit Fehler abbrechen
0001 Datei erstellen
0010 Datei ersetzen bzw. erstellen

Als Ergebnis erhält man in AX ein Handle auf die geöffnete Datei zurück und anhand des Wertes in CX kann man erkennen, welche Aktion schließlich ausgeführt wurde:

1 Datei wurde geöffnet
2 Datei wurde erstellt
3 Datei wurde ersetzt

Zum Schließen einer Datei - auch mit langem Dateinamen - gibt es kein spezielles LFN-Pendant. Man benutzt hierfür einfach die altbekannte Funktion "Close file" mit AH=3Eh und dem Handle der Datei in BX.

Zum Umbenennen von langen Datei- bzw. Verzeichnisnamen dient die Funktion AX=7156h des Interrupt 21h. Sie wird exakt genauso wie ihre 16-Bit-Vorgängerin (AH=56h) angewendet: DS:DX zeigt auf den nullterminierten aktuellen Pfadnamen und ES:DI auf den neuen (ebenfalls ASCIZ). Auch hier ist darauf zu achten, daß man mit dieser Funktion zwar Einträge von einem Verzeichnis in ein anderes legen kann, jedoch nur auf ein und dem selben Datenträger.

Gegenüber ihrer Vorgängerversion deutlich zugelegt hat die Funktion zum Löschen von langen Verzeichniseinträgen (AX=7141h). Enthält SI den Wert 0, so benimmt sich der Aufruf so, wie mit AH=41h. Wird dagegen SI mit 1 geladen, so kann der Name des Löschkandidaten auch Jokerzeichen (* und ?) enthalten und über die Register CL und CH können zusätzlich mögliche und erforderliche Dateiattribute festgelegt werden - ganz wie bei der Verzeichnissuche.

Ortsbestimmung - Funktionen um SUBST
Für alle, die es wirklich nicht glauben wollen: Ja, es ist wahr, SUBST ist auch unter Windows 95 noch immer ein Thema. Man kann damit inzwischen sogar aus einer temporären DOS-Sitzung heraus einem Pfad eine Laufwerkskennung zuweisen, die dann systemweit gilt. Im Zeichen langer Verzeichnisnamen ist dies sicherlich eine praktische Sache, vor allem, wenn man sich ohne Norton Commander oder ähnlichem an der nackten Kommandozeile befindet.

Substitutionen lassen sich selbstverständlich aber nicht nur über das gleichnamige DOS-Tool ausführen, sondern auch über drei entsprechende Interrupt 21h-Funktionen. Dazu kommen dann auch noch die TRUENAME-Funktionen zum Auflösen von Pfaden, die eventuelle Substitutionen enthalten.

Die drei SUBST-Funktionen "Create subst", "Terminate subst" und "Query subst" sind unter einer Aufrufnummer (AX=71AA) zusammengefaßt. Auseinandergehalten werden sie hier über Unterfunktionsnummern in BH (0h, 1h und 2h).
Um eine Substitutionen durchzuführen (Create subst) ruft man also Interrupt 21h mit AX=71AAh und BH=0h auf. DS:DX muß auf eine nullterminierte Zeichenkette zeigen, die einen gültigen (Teil-)Pfad enthält. Dieser wird ersetzt durch die Laufwerkskennung in BL. Dabei steht 0 für das aktuelle Laufwerk, 1 für A:, 2 für B: usw.

Zum Aufheben einer Substitutionen (Terminate subst) ruft man Unterfunktion 1 (BH=1) mit der betreffenden Laufwerkskennung in BL auf. Wichtig: Ist das aktuelle Laufwerk (BL=0) das zu beendende SUBST-Laufwerk, so schlägt der Aufruf fehl.

Auch der Bezug eines Substitutionslaufwerks läßt sich abfragen (Query subst). Dazu ruft man die Funktion mit BH=2 und BL mit der zu befragenden Laufwerkskennung auf (Aktuelles Laufwerk, also 0, ist nicht erlaubt). DS:DX muß auf einen ausreichend großen Puffer zeigen, der den substituierten Pfad als ASCIZ-String aufnimmt.

Auch die drei in MS-DOS 7 enthaltenem Truename-Funktionen sind unter einer Hauptnummer (AX=7160h) zusammengefaßt. Die Unterscheidung läuft hierbei über den Wert in Register CL:

0: Canonicalize path/file name (as is)
1: Canonicalize path/file name (all short)
2: Canonicalize path/file name (all long)

Im Grunde machen alle drei Unterfunktionen das gleiche: Sie liefern den komplett aufgelösten Pfad eines Verzeichnis- bzw. Dateinamens. Unterfunktion 0 übergibt den Ergebnisstring dabei aber so, wie sie ihn vorfindet - alles in kurzen oder langen Namen oder auch gemischt. Unterfunktion 1 dagegen liefert den kompletten Pfad in Kurzschreibweise und Nummer 2 entsprechend alles in langen Namen. DS:SI zeigt dabei auf den aufzulösenden ASCIZ-(Teil-)String (das kann beispielsweise auch "...\..\." sein) und ES:DI auf den Ergebnispuffer, indem der Truename-Pfad als nullterminierte Zeichenkette landet.

Über den Wert in CH (0 oder 1) kann man zudem noch festlegen, ob bei dem aufzulösenden Pfad ein eventuell substituiertes Laufwerk ebenfalls aufgelöst oder beibehalten werden soll.

Die übrigen LFN-Funktionen
Jetzt bleiben nur noch ein paar allgemeine Funktionen zur Informationsermittlung und Zeitformat-Konvertierung zu beschreiben. Am interessantesten dürfte hierbei "Get volume information" sein, die einiges über die Fähigkeiten eines Laufwerks verät. DS:DX muß dabei auf einen nullterminierten String mit zumindest dem Laufwerksbuchstaben des zu befragenden Volumes zeigen. ES:DI zeigt auf einen Ergebnispuffer, dessen Größe in CX übermittelt wird - 32 Byte sind hierbei ausreichend. Die Funktion wird mit AX=71A0h aufgerufen. Als Ergebnis erhält man im oben genannten Puffer den Namen des Dateisystems, beispielsweise "FAT", "CDFS" oder "NTFS". In Register CX findet man die (offizielle) Maximallänge für Dateinamen und in DX den Maximalwert für Verzeichnisnamen. In BX sind die verschiedene bit-codierte Informationen enthalten:

Bit - Bedeutung
0 Verzeichnissuche berücksichtigt Groß-/Kleinschreibung
1 Groß-/Kleinschreibung wird in Verzeichniseinträgen beibehalten
2 Unicode-Zeichen werden für Datei- und Verzeichnisnamen verwendet
3-13 0 (reserviert)
14 DOS-LFN-Funktionen werden unterstützt
15 Laufwerk ist komprimiert

Um an genauere LFN-Informationen über eine Datei zu gelangen, benutzt man die Funktion "Get file information by handle" (AX=71A6h). Wie der Name schon sagt, muß es sich um eine bereits geöffnete Datei handeln. Das betreffende Datei-Handle ist in Register BX zu übergeben und DS:DX muß auf einen ausreichend großen Ergebnispuffer zeigen. Der Aufbau und Inhalt des Puffers ist in Tabelle 4 beschrieben.

Für die Umrechnungen des neuen 64-Bit-Zeitformats muß man keineswegs eigene Routinen schreiben - MS-DOS 7 bietet hierfür bereits zwei fertige Funktionen: "File time to DOS time" und " DOS time to File time". Sie werden über AX=71A7h und BL=0 bzw BL=1 aufgerufen.

Bei der Umwandlung des 64-Bit-Zeitformats (BL=0) muß DS:SI auf die betreffenden 8 Byte mit der Zeitinformation zeigen. Nach dem Aufruf enthält CX die Zeit und DX das Datum im DOS-Format. Register BH enthält zusätzlich noch die Anzahl der auf CX zuzurechnenden 1/100 Sekunden.

Um Zeitangaben aus dem DOS- ins 64-Bit-Format von Windows 95 zu konvertieren (BL=1), muß ES:DI auf einen Ergebnispuffer von 8 Byte zeigen. CX und DX müssen analog zur vorigen Funktion mit der Zeit und dem Datum im DOS-Format geladen werden - BH nimmt wiederum die 1/100 Sekunden auf.

Schließlich wäre noch die Funktion zum Lesen und Ändern der Dateiattribute zu nennen (AX=7143h). DS:DX zeigt wiederum auf den Dateinamen (ASCIZ) und die gewünschte Aktion wird über einen entsprechenden Wert im Register BL ausgewählt:

BL - Aktion
0 Lade CX mit Dateiattributen
1 Schreibe Dateiattribute in CX auf Datenträger
2 Lade AX:DX mit der physikalischen Größe der komprimierten Datei
3 Schreibe neues Änderungsdatum
4 Lies letztes Änderungsdatum
5 Schreibe neues Zugriffsdatum
6 Lies letztes Zugriffsdatum
7 Schreibe neues Erstellungsdatum
8 Lies Erstellungsdatum

Bei den Aktionen 3 bis 8 wird das betreffende Datum im DOS-Datumsformat über die Register CX (Zeit) und DI (Datum) übergeben.

DOS-Programme mit LFN-Funktionen ausstatten.
Anhand der vorliegenden Informationen sollte es jetzt für jeden Entwickler möglich sein, seine 16-Bit-Software LFN-fähig zu machen. Wer seine Tools in Assembler geschrieben hat, dürfte dabei wohl die wenigsten Probleme haben. Bei der Anwendung ist aber darauf zu achten, daß die LFN-Funktionen trotz MS-DOS 7 möglicherweise nicht zur Verfügung stehen. Das ist nämlich nur dann der Fall, wenn auch der Treiber IfsMgr geladen wurde - nicht aber, wenn das System nackt da steht, beispielsweise nach einem abgesicherten Start oder einem Booten von Diskette. Auch könnte jemand auf die Idee kommen LFN-fähige Programme auf einer früheren Version von MS-DOS auszuführen. In diesem Fall würden ein Aufruf der LFN-Funktionen einfach durchrutschen und AX würde in jedem Fall mit 7100h zurückgegeben werden. Damit dies aber überhaupt als Fehlerkondition erkannt wird (Carry=1), muß vor(!) dem Interrupt 21h-Aufruf das Carry-Flag vom Entwickler gesetzt werden.

Auch die Anpassung in C- oder Pascal-Dialekten ist recht einfach, da die gängigsten Compiler ohnehin über einen integrierten Assembler verfügen. Unter BASIC sieht es dagegen etwas flau aus, da hier zunächst entsprechende Zusatzbibliotheken entwickelt werden müssen. Für MS-Basic ab Version 6 bietet Ihnen Tools&More eine entsprechende Implementierung mit ein paar Beispielprogrammen zur Erläuterung - jeweils als EXE-Format sowie Quelldateien:

Download: ZIP-kompatibles Archiv (86,06 KByte)
für Windows 98/ME/2000/XP/Vista
Hilfe und Infos zur Installation finden Sie hier.

Alle Tools und Artikel komplett auf der Tools&More-CD.

Unterstützen Sie Tools&More: Lassen Sie sich registrieren.

Dieses Programm weiterempfehlen.

Weitere Quellen
Wer weitere Informationen zu dem Thema lange Dateinamen unter MS-DOS sucht, wird bei Microsoft kaum schlau werden, da das meiste hier gezeigte - wie so oft - unter die Rubrik "undocumented" fällt. Glücklicherweise gibt es da aber noch die mittlerweile legendäre Interruptliste von Ralph Brown, in der so ziemlich alle Aufrufe klar dokumentiert sind - schon allein im Standard-ASCII-Format hat diese Liste eine Größe von fast 8 MByte. Diese Liste gehört zur kostenlosen Bonus-Software auf der Tools&More-CD.

Top
© 2010 Wirth IT-Design
Druckversion