Teil 2 Floppy-Kurs 6 Nun wird eine Schleife durchlaufen, die die acht Fileeinträge dieses Directory- blocks in den entsprechenden Feldern ablegt. Zur Information geben ich Ihnen hier nocheinmal den Aufbau eines Direc- toryeintrags an (sh. Floppy-Kurs, Teil 4):
ByteNr. Aufgabe ----------------------------------------
000 Byte für den Filetyp. 001-002 Track und Sektor des ersten Datenblocks dieses Files. 003-018 16 Bytes für den Filenamen. 019-020 Bei relativen Files stehen hier Track und Sektor des ersten Si- Sektor-Blocks (sonst unbenutzt) 021 Bei relativen Files seht hier die Länge eines Datensatzes (sonst unbenutzt). 022-025 unbenutzt 026-027 Zwischenspeicher des Tracks und Sektors beim Öberschreiben mit dem Klammeraffen (" ") vor dem Filenamen. 028-029 Hier steht die Länge des Files in Blocks als 16-Bit-Lo/Hi-Zahl 030-031 unbenutzt In den Zeilen 340-360 werden nun, obiger Liste entsprechend, der Reihe nach das Filetypenbyte, sowie Starttrack und -sektor des Files in die entsprechenden Felder eingelesen. Die anschließenden 16 Zeichen stellen den Filenamen dar und werden als Text, mit Hilfe einer Schleife in das Feld "na$" eingelesen. In Zeile 400 überlesen wir nun 9 Zeichen des Fileeintrags, die für uns nicht von Nutzen sind. In den Zeilen 410 und 420 werden nun noch Low- und High-Byte der Blockanzahl eingelesen und umgerechnet im Feld "bl" abgelegt. Hiernach werden noch die beiden letzten unbenutzten Bytes überlesen, um den Pufferzeiger auf den Anfang des nächsten Eintrags zu positionieren. Nun wird die Laufvariable q um eins erhöht und an den Schleifen- anfang zurück verzweigt. Ist die Schleife 8 Mal durch- laufen worden, so haben wir alle Einträge dieses Directoryblocks eingelesen und können den nächsten Block laden. Da der letzte Directoryblock immer Track 0 als Folge- track beinhaltet können wir mit der IF- THEN-Abfrage in Zeile 450 prüfen, ob der letzte benutzte Directoryblock schon eingelesen wurde, oder nicht. Ist "tr" ungleich null, so muß die Schleife noch- mals wiederholt werden und es wird zu Zeile 300 zurückverzweigt. Im anderen Fall sind wir beim letzten Directory- block angelangt und können die File- kanäle schließen. In Zeile 480 wird nun die Laufvariable "q" um 1 erniedrigt, da dieser Feldindex beim letzten Durchlauf ja noch keine neue Zuweisung erhielt. Zeile 500 dient nun dazu, den effektiv letzten Eintrag in diesem Directoryblock herauszusuchen, da ja nicht unbedingt alle 8 Einträge in diesem Block benutzt sein müssen. Dies geschieht einfach darin, daß wir "q" solange herunerzählen bis in der Variablen na$(q) ein Text steht. Da Leereinträge nur Nullen ent- halten, ist der Filename bei solchen Einträgen 16 Mal der Wert CHR $(0), was einem Leerstring ("") entspricht. Abschließend wird in das aufrufende Pro- gramm zurückverzweigt. In unseren Feld- variablen befinden sich nun alle Infor- mationen des Directorys, sowie der Diskettenname in "dn$" und die ID in "id$". In der Laufvariablen "q" steht die Anzahl der vorhandenen Einträge minus 1 (beachten Sie bitte, daß im Indexfeld 0 ebenfalls ein Eintrag ent- halten ist. "q" bezeichnet lediglich die Nummer des letzten Eintrags). Nun wissen wir also schon, wie wir die Directory- informationen in den Computer bekommen. Die Hauptroutine unseres UN-DEL-Progamms muß jetzt also nur noch die Unterroutine bei Zeile 200 aufrufen um sie zu erhalten. Um jetzt alle DEL-Einträge herauszusuchen, müssen wir lediglich alle Einträge heraussuchen, die in den unteren 3 Bits des Filetypenbytes den Wert 0 stehen haben. Wir müssen uns des- halb auf die unteren 3 Bits beschränken, da in den Bits 7 und 6 ja auch noch In- formationen über das File gespeichert sind. In den Zeilen 1100-1120 des Haupt- programms werden diese Einträge nun he- rausgesucht und deren Feldindizes im Feld "li" abgelegt. Das Hauptprogramm von UNDEL beginnt übrigens bei Zeile 1000. Aus Platzgründen will ich Ihnen ab jetzt nur noch die Zeilen auflisten, die für uns interessant sind. Der Rest dient hauptsächlich der Bildschirmformatierung und soll uns hier deshalb nicht interes- sieren. Das ganze Programm können Sie sich ja einmal auf dieser MD anschauen. Hier nun die Zeilen 1100-1120: 1100 z=0 1105 fori=0toq 1110 if(ty(i)and7)=0thenli(z)=i:z=z+1 1120 next Wie Sie sehen, benutzen wir hier die Laufvariable "z" als Indexvariable für das Feld "li". Mit dem Ausdruck "ty(i) and 7" isolieren wir die unteren drei Bits des Typenbytes und löschen die evtl. gesetzten Bits 7 und 6 für den IF-THEN-Vergleich. Wenn "z" nun größer Null ist, so wurden DEL-Files gefunden. Selbige werden in den Zeilen 1190-1230 auf dem Bildschirm ausgegeben und es wird gefragt, welches davon gerettet werden soll. In den Zeilen 1240 bis 1350 wird nun nach dem Typ des Files gefragt und ob es evtl. auch vor erneutem Löschen geschützt werden soll. Hier wieder ein Programmauszug:
1240 gosub100:print"Zu retten: ";na$(li( 1250 print"0 - DEL" 1260 print"1 - SEQ" 1270 print"2 - PRG" 1280 print"3 - USR" 1290 print"4 - REL" 1300 input"Welchen Filetyp soll ich zuordne ";t1 1310 if(n<0)or(n>4)then1300 1320 print"File auch schuetzen (J/N) ?" 1330 geta$:ifa$=""then1330 1340 ifa$="j"thent1=t1+64 1350 t1=t1+128:ty(li(n))=t1
Wie Sie sehen, wird in die Variable "t1" eine Zahl zwischen 0 und 4 eingelesen. Die Zahlen, die die einzelnen Typen zuordnen, entsprechen den Codes, die auch die Floppy zur Erkennung des File- typs benutzt. In den Zeilen 1320-1340 wird nun gefragt, ob das File auch vor dem Löschen geschützt werden soll. Dies regelt Bit 6 im Filetyp-Byte. Soll das File geschützt werden, so wird zu der Variablen "t1" der Wert 64 hinzuaddiert, was dem Setzen des 6. Bits entspricht. Zusätzlich müssen wir noch Bit 7 setzen, das anzeigt, daß das File ein gültiges File ist. Dies geschieht durch addie- ren des Wertes 128. Nun müssen wir nur noch den neuen Wert für den Filetyp in die Feld- variable "ty" übernehmen. Als nächstes muß der neue Filetyp im Direc- tory eingetragen und die Datenblocks des Files als 'belegt' gekennzeichnet werden. Dies geschieht in den Zeilen 1370-1550. Hier wieder ein Auszug:
1370 gosub100:print"Schreibe neuen Eintrag" 1380 bl=int(li(n)/8):ei=li(n)-bl*8 1390 tr=dt(bl):se=ds(bl) 1400 open1,8,15,"i":open2,8,2,"#" 1410 print#1,"u1 2 0";tr;se 1420 po=2+ei*32 1430 print#1,"b-p 2";po 1440 print#2,chr$(t1); 1450 print#1,"u2 2 0";tr;se 1460 :
In den Zeilen 1380-1390 wird nun zu- nächst den Variablen TR und SE die Werte für den Directoryblock, in dem der Eintrag steht zugewiesen. Als nächstes öffnen wir einen Befehls- und einen Pufferkanal mit den logischen File- nummern 1 und 2 (wie auch schon in der Dir-Lese-Routine). In Zeile 1410 wird der Block des Eintrags eingelesen. Nun muß der Pufferzeiger auf den Anfang des Eintrags positioniert werden. Da jeder Fileeintrag 32 Bytes lang ist, errechnet sich seine Anfangsposition aus seiner Position im Block (steht in der Variablen "ei", die in Zeile 1380 definiert wurde) multipliziert mit 32. Zusätzlich müssen wir noch zwei Bytes aufaddieren, in denen Track- und Sektornummer des Folgeblocks stehen (ganz am Anfang des Directoryblocks). In Zeile 1430 wird nun auf die errechnete Position positioniert. Nun müssen wir an dieser Stelle nur noch das neue Typen- byte eintragen (geschieht in Zeile 1440) und den Directoryblock mittels "U2" wieder auf die Diskette zurückschreiben. Schon ist der Fileeintrag geändert! Zum Schluß müssen wir noch alle vom File belegten Blocks heraussuchen und wieder neu belegen. Den ersten davon finden wir in den Feldern "ft" und "fs". Hier wieder ein Programmauszug:
1465 z=0 1470 print"Belege Blocks neu... " 1480 tr=ft(li(n)):se=fs(li(n)) 1490 print#1,"b-a 0";tr;se 1500 print#1,"u1 2 0";tr;se 1505 z=z+1 1510 gosub600:tr=a 1520 gosub600:se=a 1530 iftr<>0then1490 1540 close1:close2 1550 printz;"Blocks gefunden."
Hier wird die Variable "z" dazu benutzt, die gefundenen Blocks zu zählen. In Zeile 1480 werden nun die Feldeinträge in "ft" und "fs" in TR und SE Übertra- gen. Zeile 1490 benutzt nun den Block- Allocate-Befehl um diesen Block als 'belegt' zu kennzeichnen. In Zeile 1500 wird er dann in den Puffer gelesen, da seine ersten beiden Bytes ja auf den nächsten Block des Files zeigen. Dessen Track- und Sektornummer wird nun in den Zeilen 1510 und 1520 in TR und SE ein- gelesen und für den nächsten Durchlauf der Schleife verwendet. Sollte TR jedoch den Wert 0 aufweisen, so sind wir beim letzten Block angelangt und können die Blockbelegung beenden. Dies regelt die IF-THEN-Anweisung in Zeile 1530. Somit wären alle wichtigen Teile des UN- DEL-Programms besprochen. Um einen Gesamtüberblick zu erhalten, rate ich Ihnen, sich das Programm auf dieser MD einmal auszudrucken und anzuschauen. Öbrigens beinhaltet das Programm noch einen kleinen Schönheitsfehler: Wenn Sie nämlich z.B. 9 Files auf einer Diskette haben, und das letzte davon löschen, so findet es die Directory-Lese-Routine nicht mehr. Das liegt daran, daß nach dem Löschen des Eintrags der zweite Directoryblock ja nicht mehr benötigt wird und deshalb als Folgeblock Track 0, Sektor 255 im ersten Directoryblock eingetragen wird. Um diesen Fehler zu beheben, können Sie ja eine Routine schreiben, die alle Directoryblocks der Reihe nach einliest. Das ist zwar sehr zeitaufwendig, könnte jedoch den Fehler beheben. Sie können dabei davon aus- gehen, daß die Folgetracks und -sektoren beim Directory immer gleich sind. Bei einem vollen Directory (144 Einträge), können Sie so diese Einträge mit Hilfe eines Diskettenmonitors einfach herausfinden. Ich verabschiede mich hiermit von Ihnen bis zur nächsten Ausgabe, wo wir uns an die Floppyprogrammierung in Assembler heranwagen möchten.
(ub)