← ST-Computer 05 / 1989

Was Sie an UTILITIES immer schon brauchten!

Programmierpraxis

Der Computeruser, der ĂŒber sich ewig das Damoklesschwert des Stromausfalls oder des 'Daten auf Disk X defekt?’ sieht, lĂ€sst natĂŒrlich bei jedem Abspeichern das alte File irgendwie umbenennen und ĂŒberschreibt es selbstverstĂ€ndlich nicht. Aber, wenn nach arbeitsreicher Nacht alles geklappt hat und man die diversen BAK-, DUP-, SBK- etc. Files nicht mehr benötigt?

Grund fĂŒr das 1. Utility: ‘DelBak‘. Und dann doch der Frust: Die wichtigste Datei wurde nicht korrekt abgespeichert, das Backup-File natĂŒrlich gelöscht. Aber irgendwo auf der Platte war doch noch eine alte Version! Nur wo? Schon mal durch ‘zig Ordner durchgeklickt? Womit wir beim 2.Utility wĂ€ren: ‘Find’.

DelBak sucht auf einem Laufwerk nach allen Dateien mit den Endungen BAK (1st Word, GFA-BASIC etc.), DUP (Tempus) und SBK (Signum). Diese werden dem Benutzer jeweils auf dem Bildschirm angezeigt, der sie dann mit beliebiger Taste außer n/N löschen kann. Das zu durchsuchende Laufwerk muß beim Programmstart (‘DELBAK.TTP’) als Argument ĂŒbergeben werden.

Beispiel:
delbak d sucht alle Backups auf Laufwerk D

Find sucht, wieder auf einem vorgegebenen Laufwerk, nach Dateien, deren Name den ĂŒbergebenen String enthĂ€lt.

Beispiel:
find d delbak findet (in unserem Fall) die Dateien delbak.m, delbak.mtp und delbak.ttp.

Es werden jeweils alle passenden Dateien zusammen mit dem jeweiligen Suchpfad ausgegeben.

Zur Programmierung

Beide Utilities entstanden nach demselben Muster, was man auch an der Ă€hnlichen Programmstruktur erkennen kann. Sie sind aber doch unterschiedlich genug, um beide abzudrucken, da eine ErklĂ€rung der nötigen Umbauten zuviel Platz einnehmen wĂŒrde.

Kernpunkt der beiden Programme ist die Routine DirQuery. Im Prinzip ist sie eine Zusammenfassung der beiden GEMDOS-Routinen Fsfirst und Fsnext, wobei bei jeder Übereinstimmung eines Directory-Eintrags mit dem vorgegebenen Pattern und den Fileattributen eine vom Programmierer festgelegte Prozedur aufgerufen wird. Diese Prozedur (in unserem Programmen wĂ€re das TestIfBAK bzw. TestIfFound) erhĂ€lt als Parameter den Pfadnamen des gefundenen Eintrags sowie einen Record, der den Eintrag nĂ€her beschreibt. Dieser Record entspricht der Datenstruktur, die von Fsfirst/Fsnext zurĂŒckgeliefert wird.

Die Argumentzeilenauswertung gestaltet sich (dank einem guten Library-Modul) recht einfach: Mit InitArgCV wird die Anzahl der Argumenten+ in die Variable ArgC gelegt, ArgV ist ein Array von Pointern, welche auf die einzelnen Argumentstrings zeigen. ArgV[0] ist dabei immer leer (unter UNIX steht hier der Name des aufgerufenen Programms), DelBak muß daher auf 2 ‘Argumente’ testen, Find auf 3. Finden die beiden Programme nicht die richtige Anzahl Argumente vor, geben sie einen kurzen Text mit der Syntax des Aufrufs aus.

Wenn einem Megamax-Modulisten der Import aus Fast-Strings spanisch vorkommt: Es ist zwar kein Standardmodul (Àtsch), aber auf zwei Arten erhÀltlich:

  1. Über die MAUS-Mailbox [0251/80... (kein Witz!)], im öffentlichen Programmteil nachsehen (MM2FSTRI.ARC).
  2. Auf das nÀchste Update warten.

Das Modul selbst stammt von Thomas Tempelmann (Danke!!) und erfĂŒllt in etwa die gleichen Aufgaben wie das standardmĂ€ĂŸige Stringmodul, allerdings viel schneller (keine Fehlerkontrolle, VAR-Parameter). Wenn man also nicht in der Lage ist, das FastStrings-Modul zu bekommen, kann man auch das normale verwenden.

Beim Linken mĂŒssen außer M2INIT keine Module dazugelinkt werden. Wenn man zu den GlĂŒcklichen gehört, die bereits einen optimierenden Linker besitzen, erhĂ€lt man zwei wirklich kleine (< 5kB) Programme in Modula-2!! Viele mögen sich fragen, ob man das Ende eines solchen Programmes in Modula-2 ĂŒberhaupt erlebt. Nun, man tut es. Das Suchen auf einer 8 MByte-Partition (FĂŒllungsgrad ca. 50%) dauerte etwa 8s! Wenn man da keinen Geschwindigkeitsrausch bekommt ...

(************************************************* * TITEL : DelBak * * ZWECK : Löscht Backup-Dateien * * AUTOREN : (c) 1988 WuSeL-Soft * * Martin Wunderli & Patrick Seemann * * DATUM : 01.09.1988 : Version 1.0 * * SPRACHE : MODULA-2 (MEGAMAX MODULA V1.0) * * Compilerversion 3.6a * ************************************************) (*$E MTP *) MODULE DelBak; FROM ArgCV IMPORT (* TYPES *) ArgStr, PtrArgStr, (* PROCS *) InitArgCV; FROM Directory IMPORT (* TYPES *) FileAttr, FileAttrSet, DirEntry, DirQueryProc, Drive, (* PROCS *) DirQuery, Delete, DefaultDrive, StrToDrive, SetDefaultDrive; FROM FastStrings IMPORT (* PROCS *) Append, Assign, Pos; FROM Terminal IMPORT (* PROCS *) WriteString, WriteLn, Write, Read; TYPE str4 = ARRAY [0..3] OF CHAR; VAR Result : INTEGER; Pattern : ArgStr; NewDrive, BAK, DUP, SBK : str4; James : CHAR; ArgC : CARDINAL; ArgV : ARRAY [0..1] OF PtrArgStr; AktDrive : Drive; (************************************************) PROCEDURE TestIfBAK ( (* in *) Pfad : ARRAY OF CHAR; (* in *) Entry : DirEntry): BOOLEAN; VAR NeuerPfad : ArgStr; BEGIN IF (subdirAttr IN Entry.attr) THEN IF NOT(Entry.name[0] = THEN Assign (Pfad, NeuerPfad); Append (Entry.name,NeuerPfad); Append (Pattern, NeuerPfad); DirQuery (NeuerPfad,FileAttrSet{subdirAttr},TestIfBAK,Result); END (* IF *); ELSE IF (Pos (BAK,Entry.name) >= 0) OR (Pos (DUP,Entry.name) >= 0) OR (Pos (SBK,Entry.name) >= 0) THEN Write (" "); WriteString (Pfad); WriteString (Entry.name); WriteString (" Löschen (_/N)? "); Read (James); IF CAP(James) <> "N" THEN Assign (Pfad, NeuerPfad); Append (Entry.name,NeuerPfad); Delete (NeuerPfad,Result); END (* IF *); WriteLn; END (* IF *); END (* IF *); RETURN TRUE END TestIfBAK; (************************************************) BEGIN Pattern := "\*.*": NewDrive := "X:"; BAK := ".BAK"; DUP := ".DUP"; SBK := ".SBK"; InitArgCV (ArgC, ArgV); IF ArgC = 2 THEN AktDrive := DefaultDrive(); NewDrive[0] := CAP(ArgV[1]^[0]); SetDefaultDrive (StrToDrive (NewDrive)); DirQuery (Pattern, FileAttrSet{subdirAttr}, TestIfBAK, Result); SetDefaultDrive (AktDrive); ELSE WriteString (" Usage: delbak <drive>"); WriteLn; END (* IF *); END DelBak.

DelBak Programm

(************************************************* * TITEL : Find * * ZWECK : Findet eine Datei auf dem ĂŒber- * * gegebenen Laufwerk * * AUTOREN : (c) 1988 WuSeL-Soft * * Martin Wunderli & Patrick Seemann* * DATUM : 01.09.1988 : Version 1.0 * * SPRACHE : MODULA-2 (MEGAMAX MODULA V1.0) * * Compilerversion 3.6a * ************************************************) (*$E MTP *) MODULE Find; FROM ArgCV IMPORT (* TYPES *) ArgStr, PtrArgStr, (* PROCS *) InitArgCV; FROM Directory IMPORT (* TYPES *) FileAttr, FileAttrSet, DirEntry, DirQueryProc, Drive, (* PROCS *) DirQuery, Delete, DefaultDrive, StrToDrive, SetDefaultDrive; FROM FastStrings IMPORT (* PROCS *) Append, Assign, Length, Pos; FROM Terminal IMPORT (* PROCS *) WriteString, WriteLn, Read; TYPE str4 = ARRAY [0..3] OF CHAR; VAR Result : INTEGER; Pattern, File : ArgStr; NewDrive : str4; ArgC, i : CARDINAL; ArgV : ARRAY [0..2] OF PtrArgStr; AktDrive : Drive; James : CHAR; (************************************************* PROCEDURE TestlfFound ( (* in *) Pfad : ARRAY OF CHAR; (* in *) Entry : DirEntry): BOOLEAN; VAR NeuerPfad : ArgStr; BEGIN IF (subdirAttr IN Entry.attr) THEN IF NOT(Entry.name[0] = THEN Assign (Pfad, NeuerPfad); Append (Entry.name,NeuerPfad); Append (Pattern, NeuerPfad); DirQuery (NeuerPfad,FileAttrSet{subdirAttr}, TestIfFound, Result); END (* IF *); ELSE IF (Pos (File, Entry.name) >= 0) THEN WriteString (" Found: ") ; WriteString (Pfad); WriteString (Entry.name); WriteLn; END (* IF *); END (* IF *); RETURN TRUE END TestIfFound; (************************************************) BEGIN NewDrive := "X:"; Pattern := "\*.*"; InitArgCV (ArgC, ArgV); IF ArgC = 3 THEN AktDrive := DefaultDrive(); NewDrive[0] := CAP(ArgV[1]^[0]); SetDefaultDrive (StrToDrive (NewDrive)); FOR i := 0 TO Length (ArgV[2]^) DO File [i] := CAP (ArgV[2]^[i]); END (* FOR i *); DirQuery (Pattern, FileAttrSet{subdirAttr}, TestIfFound, Result); SetDefaultDrive (AktDrive); ELSE WriteString ("Usage: find <drive> <filename>"); WriteLn; END (* IF *); WriteString ("Bitte Taste drĂŒcken!"); Read (James); END Find.

Find Programm

Martin Wunderli