← ST-Computer 03 / 1990

FILE-INFO

Programmierpraxis

Jeder ST-Besitzer kennt selbstverständlich die Option “zeige Info” im Desktop-Menu. Für eine ausgewählte Datei erscheint beim Aufruf eine Dialogbox, die Informationen über diese anzeigt. Dabei handelt es sich um Angaben über den Dateinamen, Erstellungsdatum und -zeit sowie über das Schreibschutzattribut. Andern lassen sich leider nur dieses Attribut und der Dateiname.

Will man jedoch die Erstellungszeit oder andere Attribute ändern, läßt sich nichts machen.

Dabei ist es manchmal sinnvoll, nachträglich das Erstellungsdatum einer Datei ändern zu können, z.B. dann, wenn sich nach einem Kopiervorgang zeigt, daß man wieder einmal vergessen hat, die Uhr im Kontrollfeld zu stellen. Das Ergebnis: Die Datei weist ein unsinniges Erstellungsdatum auf. Bisher blieb in einem solchen Fall nichts anderes übrig, als den Kopiervorgang zu wiederholen (natürlich nach dem Stellen der Uhr), mit einem Disk-Monitor zu drohen oder sich gar ganz geschlagen zu geben.

Einstellungen

Mit dem Accessory FILEINFO ist dieser Ärger nun vorbei. Für die über den Fileselector angewählte Datei erhält man eine ausführlichere Information als das Desktop sie bietet, wobei alle angezeigten Angaben auch geändert werden können. Neben dem Schreibschutzattribut kann eingestellt werden, ob es sich bei der ausgewählten Datei in Zukunft um eine Systemdatei oder um eine versteckte handeln soll. Zur Auswahl der Attribute genügt es, die dafür vorgesehen Buttons in der Dialogbox anzuklicken. Die Einstellung der Buttons beim Betreten der Box entspricht den Attributen, wie sie die Datei im Augenblick des Aufrufs besitzt. Besonders interessant sind die Dateiattribute System und Versteckt, die vom Desktop aus nicht geändert werden können. Geben Sie einer Datei das Attribut System, wird sie nicht mehr auf dem Desktop angezeigt, und auch für den normalen Fileselector ist sie nicht mehr vorhanden. Dennoch kann der Inhalt dieser Datei gelesen werden, denn sie ist nicht wirklich von der Diskette verschwunden. Wozu das gut sein kann? Nun, wenn Sie Disketten besitzen, die hoffnungslos überfüllt sind, geben Sie allen .RSC-Dateien doch einfach den Systemstatus. Danach sieht der Disketteninhalt schon viel übersichtlicher aus, denn die .RSC-Dateien werden nicht mehr angezeigt. Das Betriebssystem bzw. die Programme, die die .RSC-Dateien lesen sollen, bemerken von der Änderung nichts. Selbstverständlich kann man dieses Verfahren auch auf andere Dateien anwenden, die nur von anderen Programmen nachgeladen werden, also ohnehin nicht über einen Mausklick gestartet werden können. Geben Sie einer Datei das Attribut Versteckt, so ist sie für das TOS so gut wie gar nicht mehr zu finden, es sei denn, man geht mit einem Disk-Monitor auf die Suche.

Kopierschutz

Auf diese Art und Weise kann ein einfacher Kopierschutz für einzelne Dateien realisiert werden, denn wenn man nicht weiß, daß sich eine Datei auf einer Diskette befindet, kommt man auch nicht auf die Idee, sie kopieren zu wollen. (Selbstverständlich hilft dieses Verfahren nur dann, wenn nicht gleich ein Backup der kompletten Disk gemacht wird.) Daraus resultiert jedoch auch folgende Warnung: Merken Sie sich, welche Dateien Sie versteckt haben, denn nur wenn Sie die Dateinamen kennen, können Sie diese Files wieder sichtbar machen! Hierzu rufen Sie erneut das FILEINFO-Accessory auf, geben den Namen der unsichtbaren Datei über die Tastatur ein (der Fileselector zeigt diesen Namen nicht an!), und voilà: Die Information über die anscheinend nicht vorhandene Datei erscheint auf dem Bildschirm. Ändern Sie nun die File-Attribute entsprechend ab, wird die Datei ab sofort wieder für jedermann sichtbar.

Wichtig ist noch der folgende Hinweis: Wird die Datei, deren Namen oder Attribut Sie soeben geändert haben, in einem Window auf dem Desktop angezeigt, muß die ESC-Taste gedrückt werden, damit die vorgenommenen Änderungen auf das Desktop übertragen werden. Welche Routinen des GEMDOS ermöglichen nun das Holen und Ändern der File-Daten? Für das Holen und Setzen der File-Attribute ist die Funktion CHANGE MODE ($31) verantwortlich. Sie ermöglicht das Setzen oder Löschen einzelner Attribute. Erstellungsdatum und -zeit werden mit der Funktion GSDTOF ($57) geholt oder gesetzt. Als Parameter wird unter anderem ein Flag übergeben, das bestimmt, ob die Daten ermittelt oder gesetzt werden sollen. Achtung: In der Literatur zum TOS ist dieses Flag oftmals falsch beschrieben. Der Wert muß 0 sein, wenn die Erstellungsdaten geholt werden sollen. Wird eine 1 übergeben, werden diese Daten gesetzt!

Wie sich der Aufruf der oben beschriebenen GEMDOS-Routinen genau gestaltet, kann dem ausführlich kommentierten Quelltext des Programms entnommen werden, das übrigens mit einem zum AS68 kompatiblen Assembler erstellt wurde. Die Objektdaten für die Dialogbox wurden in den Quelltext integriert, so daß keine externe Resource-Datei vorhanden ist. Die Programmlänge nach dem Assemblieren und Linken sollte 2321 Bytes betragen.

********************************* * Von Uwe Seimet * * Buchenlochstrasse 29 * * 6750 Kaiserslautern * * (c) MAXON Computer GmbH 1990 * ********************************* *GEMDOS-Konstanten GEMDOS = 1 OPEN = $3d CLOSE = $3e CHMOD = $43 RENAME = $56 GSDTOF = $57 *Wichtige Objektindices NAME = 6 OK = 14 text lea stack+400,sp ;Stackpointer initialisieren move.l #"\*.*",inpath ;Pfad für Disk lea intin,a5 ;Pointer auf INTIN-Array lea intout,a6 ;Pointer auf INTOUT-Array moveq #10,d0 ;appl_init move.l #$00010000,d1 bsr aes move (a6),d4 ;apid_nr merken move #18,(a5) ;19 Objekte fix: moveq #114,d0 ;rsrc_obfix move.l #$01010100,d1 bsr aesobj ;Koordinaten auf Aufl. umrechnen subq #1,(a5) bpi fix ;nächstes Objekt moveq #77,d0 ;graf_handle move.l #$00050000,d1 bsr aes move (a6),phys_h ;phys_handle merken moveq #35,d0 ;menu_register move.l #$01010100,d1 move d4,(a5) lea name(pc),a0 ;Accessory-Name bsr aes ;in Menüleiste eintragen move (a6),nr ;Nummer des Eintrags merken *Warteschleife doacc: moveq #23,d0 ;evnt_mesag move.l #$00010100,d1 lea ev_buff,a3 ;Puffer für GEM-Messages move.l a3,a0 bsr aes cmp #40,(a3) ;AC_OPEN? bne doacc ;nein- move nr,d0 cmp 8(a3),d0 ;Programm angeklickt? bne doacc ;nein- bsr.s act ;Dialog ausführen bra doacc ;weiter in Warteschleife *Dialog mit dem Benutzer act: move.l a5,a0 ;Pointer auf INTIN-Array moveq #9,d0 opn: move #1,(a0)+ ;Parameter für OPEN VIRTUAL WORKSTATION dbf d0,opn move #2,(a0) moveq #100,d0 ;v_opnvwk lea contrl+2,a4 clr.l (a4)+ move #11,(a4) move phys_h,vdi_h bsr vdi move 6(a4),vdi_h ;vdi_handle merken moveq #90,d0 ;fsel_input move.l #$00020200,d1 move.l #insel,addrin+4 lea inpath,a0 bsr aes ;Eingabe des Filenamens tst 2{a6) ;Abbruch? beq exit ;ja- moveq #2,d0 ;Biene als Mauscursor bsr mouse lea inpath,a0 ;Pointer auf Pfad lea nam,a1 ;Pointer auf alten Filenamen lea nnam,a2 ;Pointer auf neuen Filenamen tpat: move.b (a0)+,d0 move.b d0,(a1)+ ;Pfadnamen kopieren move.b d0,(a2)+ bne tpat tpat1: cmp.l #nam,a1 bcs exit subq.l #1,a2 cmp.b -(a1) bne tpat1 addq.l #1,a1 addq.l #1,a2 move.l a2,newnam ;Pointer auf Beginn des neuen Namens lea insel,a0 lea filnam(pc),a2 moveq #10,d0 filspc: move.b #" ",(a2)+ ;Bereich für Namen löschen dbf d0,filspc lea filnam(pc),a2 tsel: move.b (a0)+,d0 ;Pfad- und Filenamen zusammensetzen cmp.b #".",d0 bne.s tsell1 lea filnam+8(pc),a2 bra.s tsel2 tsel1: move.b d0,(a2)+ tsel2: move.b d0,(a1)+ bne.s tsel clr.l -(sp) ;Attribut ermitteln pea nam move #CHMOD,-(sp) trap #GEMDOS add #10,sp tst d0 ;alles klar? bmi exit ;dummerweise nicht- lea flg1+3(pc),a0 ;Pointer auf lea flg2+3(pc),a1 ;Radio-Buttons btst #0,d0 ;Read Only? bne.s ro ;ja- exg.l a0,a1 ro: bclr #0,(a0) ;Buttons deselektieren bset #0,(a1) ;bzw. selektieren lea flg3+3(pc),a0 lea flg4+3(pc),a1 btst #1,d0 ;versteckt? bne.s hidden ;ja- exg.1 a0,a1 hidden: bclr #0,(a0) bset #0,(a1) lea flg5+3(pc),a0 lea flg6+3(pc),a1 btst #2,d0 ;System-File? bne.s system ;ja- exg.l a0,a1 system: bclr #0,(a0) bset #0,(a1) clr -(sp) pea nam move #OPEN,-(sp) ;Datei muß vor GSDTOF trap #GEMDOS ;erst geöffnet werden addq.l #8,sp move.l d0,d6 ;Fehler beim Öffnen? bmi exit ;ja- clr -(sp) ;Flag für Datum, Zeit ermitteln move d6,-(sp) pea dati ;Puffer für Datum und Zeit move #GSDTOF,-(sp) trap #GEMDOS add #10,sp clr.l d1 move dati,d1 ;Zeit holen lsr #5,d1 ;Sekundenbits rausschieben move.l d1,d0 and #%111111,d0 ;Minuten isolieren divu #10,d0 add.b #"0”,d0 ;und nach ASCII wandeln lea time(pc),a0 move.b d0,2(a0) swap d0 add.b #"0",d0 move.b d0,3(a0) lsr #6,d1 ;Stunden isolieren divu #10,d1 add.b #"0",d1 move.b d1,(a0)+ swap d1 add.b #"0”,d1 move.b d1,(a0) clr.l d1 move dati+2,d1 ;Datum holen move.l d1,d0 and #%11111,d0 ;Tag divu #10,d0 add.b #"0",d0 lea date(pc),a0 move.b d0,(a0)+ swap d0 add.b #"0",d0 move.b d0,(a0)+ lsr #5,d1 move.l d1,d0 and #%1111,d0 ;Monat divu #10,d0 add.b #"0",d0 move.b d0,(a0)+ swap d0 add.b #"0",d0 move.b d0,(a0)+ lsr #4,d1 ;Jahr add #80,d1 cmp #100,d1 ;falls im Jahr 2000 o. später bcs.s ovr ;(man kann ja nie wissen) sub #100,d1 ovr: divu #10,d1 add.b #"0",d1 move.b d1,(a0)+ swap d1 add.b #"0",d1 move.b d1,(a0) moveq #107,d0 ;wind_update move.l #$01010000,d1 move #1,(a5) bsr aes moveq #54,d0 ;form_center move.l #$00050100,d1 bsr aesobj movem.l 2(a6),a3/a4 ;form_xy und form_wh merken clr d2 ;Bildschirmspeicher reservieren movem.l a3/a4,2(a5) bsr form_dial moveq #42,d0 ;objc_draw move.l #$06010100,d1 move.l #$00000002,(a5) move.l 2(a6),4(a5) move.l 6(a6),8(a5) bsr aesobj ;Dialogbox darstellen clr d0 ;Pfeil als Mauscursor bsr mouse moveq #50,d0 ;form_do move.l #$01010101,d1 move #NAME,(a5) ;Eingabefeld bsr aesobj ;Dialog starten move (a6),d7 bclr #15,d7 ;Bit für Doppelklick löschen cmp #OK,d7 ;OK-Button angewählt? bne break ;nein-keine Änderung vornehmen lea date(pc),a0 clr d0 move.b 4(a0),d0 sub.b #"0",d0 mulu #10,d0 sub.b #"0",d0 add.b 5(a0),d0 sub #80,d0 move d0,d1 asl #4,d1 ;Jahr clr d0 move.b 2(a0),d0 sub.b #"0",d0 mulu #10,d0 sub.b #"0",d0 add.b 3(a0),d0 or d0,d1 asl #5,d1 ;Monat clr d0 move.b (a0)+,d0 sub.b #"0", d0 mulu #10,d0 sub.b #"0",d0 add.b (a0),d0 or d0,d1 ;Tag move d1,dati+2 ;Datum merken lea time(pc),a0 clr d0 move.b (a0)+,d0 sub.b #"0",d0 mulu #10,d0 sub.b #"0",d0 add.b (a0)+,d0 move d0,d1 asl #6,d1 ;Stunden clr d0 move.b (a0)+,d0 sub.b #"0",d0 mulu #10,d0 sub.b #"0",d0 add.b (a0),d0 or d0,d1 ;Minuten asl #5,d1 move d1,dati ;Zeit merken move #1,-(sp) ;Datum und Zeit setzen move d6,-(sp) pea dati move #GSDTOF,-(sp) trap #GEMDOS add #10,sp clr d0 btst #0,flg2+3 ;Read Only? beq.s ro1 ;nein- bset #0,d0 ro1: btst #0,flg4+3 ;versteckt? beq.s hidden1 ;nein- bset #1,d0 hidden1:btst #0,flg6+3 ;System-File? beq.s system1 ;nein- bset #2,d0 system1:move d0,-(sp) move #1,-(sp) pea nam move #CHMOD,-(sp) trap #GEMDOS ;neue Attribute setzen add #10,sp move.l newnam,a1 lea filnam(pc),a0 moveq #7,d0 copnew: move.b (a0)+,d1 cmp.b #" ",d1 beq.s copn2 move.b d1,(a1)+ ;neuen Filenamen zusammensetzen beq.s copn1 dbf d0,copnew bra.s copn3 copn2: add.l d0,a0 copn3: move.b #".",(a1)+ copnew1:move.b (a0)+,(a1)+ bne copnew1 copn1: pea nnam ;neuer Name pea nam ;alter Name clr -(sp) move #RENAME,-(sp) trap #GEMDOS ;Datei umbenennen add #12,sp break: moveq #3,d2 ;Bildschirmspeicher freigeben movem.l a3/a4,2(a5) bsr.s fo_dial moveq #47,d0 ;objc_change move.l #$08010100,d1 move.l a5,a0 move d7,(a0)+ clr (a0)+ movem.l a3/a4,(a0) clr.l 12(a5) bsr.s aesobj ;ausgewählten Button wieder deselektieren move d7,-(sp) move #CLOSE,-(sp) trap #GEMDOS ;das war's addq.l #4,sp moveq #107,d0 ;wind_update move.l #$01010000,d1 clr (a5) bsr.s aes exit: clr d0 ;Pfeil als Mauscursor bsr.s mouse moveq #101,d0 ;v_clsvwk vdi: lea contrl,a0 move vdi_h,12(a0) ;vdi_handle move d0,(a0) ;Funktionsnummer move.l #vdipb,d1 moveq #$73,d0 ;VDI trap #2 ;aufrufen rts *Mausform auswählen mouse: move d0,(a5) ;Mausform festlegen moveq #78,d0 ;graf_mouse move.l #$01010100,d1 bra.s aes fo_dial: movem.l a3/a4,10(a5) form_dial: moveq #51,d0 ;form_dial move.l #$09010100,d1 move d2,(a5) aesobj: lea _objcdat(pc),a0 aes: move.l a0,addrin ;Objekt-Adresse lea contrl,a0 ;Pointer auf CONTRL-Array move d0,(a0) ;Befehlsnummer movep.l d1,3(a0) ;Parameter in Array übertragen move.l #aespb,d1 move #$c8,d0 ;AES trap #2 ;aufrufen rts name: dc.b " Fileinfo",0 ;Name des Menüeintrags even *__________ *Objektdaten für die Dialogbox _objcdat: dc.w $ffff dc.w $0001,$0012 dc.w $0014 dc.w $0000,$0010 dc.l $00021100 dc.w $0006,$0001 dc.w $0028,$0012 dc.w $0002 dc.w $ffff,$ffff dc.w $001c dc.w $0000,$0011 dc.l spec000 dc.w $000c,$0001 dc.w $0010,$0001 dc.w $0003 dc.w $ffff,$ffff dc.w $0015 dc.w $0000,$0000 dc.l spec001 dc.w $000c,$0003 dc.w $0410,$0001 dc.w $0004 dc.w $ffff,$ffff dc.w $0015 dc.w $0000,$0000 dc.l spec002 dc.w $000d,$0004 dc.w $020e,$0001 dc.w $0005 dc.w $ffff,$ffff dc.w $0015 dc.w $0000,$0000 dc.l spec003 dc.w $000d,$0005 dc.w $020e,$0001 dc.w $0006 dc.w $ffff,$ffff dc.w $0015 dc.w $0000,$0000 dc.l spec004 dc.w $000d,$0006 dc.w $020e,$0001 dc.w $0007 dc.w $ffff,$ffff dc.w $001d dc.w $0008,$0000 dc.l spec005 dc.w $000a,$0008 dc.w $0016,$0001 dc.w $0008 dc.w $ffff,$ffff dc.w $001d dc.w $0008,$0000 dc.l spec006 dc.w $0002,$0009 dc.w $001a,$0001 dc.w $0009 dc.w $ffff,$ffff dc.w $001d dc.w $0008,$0000 dc.l spec007 dc.w $0003,$000a dc.w $0016,$0001 dc.w $000a dc.w $ffff,$ffff dc.w $001a flg1: dc.w $0011,$0000 dc.l spec008 dc.w $0002,$000c dc.w $000b,$0001 dc.w $000b dc.w $ffff,$ffff dc.w $001a flg2: dc.w $0011,$0000 dc.l spec009 dc.w $000e,$000c dc.w $000b,$0001 dc.w $000e dc.w $000c,$000d dc.w $0019 dc.w $0000,$0000 dc.l $00001100 dc.w $0002,$000e dc.w $0017,$0001 dc.w $000d dc.w $ffff,$ffff dc.w $001a flg3: dc.w $0011,$0000 dc.l spec010 dc.w $0000,$0000 dc.w $000b,$0001 dc.w $000b dc.w $ffff,$ffff dc.w $001a flg4: dc.w $0011,$0000 dc.l spec011 dc.w $000c,$0000 dc.w $000b,$0001 dc.w $000f dc.w $ffff,$ffff dc.w $001a dc.w $0007,$0000 dc.l spec012 dc.w $001e,$000e dc.w $0008,$0001 dc.w $0012 dc.w $0010,$0011 dc.w $0019 dc.w $0000,$0000 dc.l $00001100 dc.w $0002,$0010 dc.w $0017,$0001 dc.w $0011 dc.w $ffff,$ffff dc.w $001a flg5: dc.w $0011,$0000 dc.l spec013 dc.w $0000,$0000 dc.w $000b,$0001 dc.w $000f dc.w $ffff,$ffff dc.w $001a flg6: dc.w $0011,$0000 dc.l spec014 dc.w $000c,$0000 dc.w $000b,$0001 dc.w $0000 dc.w $ffff,$ffff dc.w $001a dc.w $0025,$0000 dc.l spec015 dc.w $001e,$0010 dc.w $0008,$0001 spec000:dc.b ' FILEINFO V1.00 ',0 spec001:dc.l spec001+$001c,spec001+$0033,spec001+$0034 dc.w $0005 dc.w $0006 dc.w $0000 dc.w $1180 dc.w $0000 dc.w $ffff dc.w $0017,$0001 dc.b ' (C) 1987 by Uwe Seimet',0 dc.b 0 dc.b 0 spec002:dc.l spec002+$001c,spec002+$0030,spec002+$0031 dc.w $0005 dc.w $0006 dc.w $0000 dc.w $1180 dc.w $0000 dc.w $ffff dc.w $0014,$0001 dc.b 'BuchenlochstraPe 29', 0 dc.b 0 dc.b 0 spec003:dc.l spec003+$001c,spec003+$0030,spec003+$0031 dc.w $0005 dc.w $0006 dc.w $0000 dc.w $1180 dc.w $0000 dc.w $ffff dc.w $0014,$0001 dc.b '6750 Kaiserslautern',0 dc.b 0 dc.b 0 spec004:dc.l spec004+$001c,spec004+$0030,spec004+$0031 dc.w $0005 dc.w $0006 dc.w $0000 dc.w $1180 dc.w $0000 dc.w $ffff dc.w $0014,$0001 dc.b 'Telefon: 0631/21...',0 dc.b 0 dc.b 0 spec005:dc.l spec005+$001c,spec005+$0028,spec005+$003f dc.w $0003 dc.w $0006 dc.w $0000 dc.w $1180 dc.w $0000 dc.w $ffff dc.w $000c,$0017 filnam: dc.b 'FILENAMEEXT',0 dc.b 'Filename: _______.___',0 dc.b 'ppppppppppp',0 spec006:dc.l spec006+$001c,spec006+$0023,spec006+$003e dc.w $0003 dc.w $0006 dc.w $0000 dc.w $1180 dc.w $0000 dc.w $ffff dc.w $0007,$001b date: dc.b '000000',0 dc.b 'Erstellungsdatum: __.__.____',0 dc.b '999999',0 spec007:dc.l spec007+$001c,spec007+$0021,spec007+$0038 dc.w $0003 dc.w $0006 dc.w $0000 dc.w $1180 dc.w $0000 dc.w $ffff dc.w $0005,$0017 time: dc.b '0000',0 dc.b 'Erstellungszeit: __:__',0 dc.b '9999',0 spec008:dc.b 'Read/Write',0 spec009:dc.b 'Read Only',0 spec010:dc.b 'Sichtbar',0 spec011:dc.b 'Versteckt',0 spec012:dc.b 'OK',0 spec013:dc.b 'Normal',0 spec014:dc.b 'System',0 spec015:dc.b 'ABBRUCH',0 *__________ data aespb: dc.l contrl,global,intin,intout,addrin,addrout vdipb: dc.l contrl,intin,ptsin,intout,ptsout bss *Speicherbereiche für VDI und AES contrl: ds 11 global: ds 15 intin: ds 64 ptsin: ds 64 intout: ds 64 ptsout: ds 64 addrin: ds 64 addrout:ds 64 phys_h: ds 1 vdi_h: ds 1 nr: ds 1 ;Nummer des Accessory-Eintrags ev_buff:ds 8 ;Puffer für GEM-Mitteilungen dati: ds 2 ;Puffer für Datum und Zeit newnam: ds.l 1 ;Pointer auf neuen Dateinamen even inpath: ds.b 40 ;Pfad für Fileselector insel: ds.b 13 ;Dateiname für Fileselector nam: ds.b 52 ;kompletter alter Name der Datei nnam: ds.b 52 ;kompletter neuer Name der Datei even stack: ds.l 100 ;für Stack
Uwe Seimet