home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* VIRTEST.PAS *)
- (* Das Programm überprüft Disketten und die Festplatte *)
- (* auf Veränderungen und versucht, Beschädigungen zu *)
- (* reparieren. *)
- (* (c) 1989 Andreas Schuster & TOOLBOX *)
- (* ------------------------------------------------------ *)
- PROGRAM VirTest;
-
- USES Dos,Crt;
-
- CONST
- DefaultName = 'VIRTEST.DTA'; (* Vorgabe Referenzdatei *)
- LogName = 'VIRTEST.LOG'; (* Name Protokolldatei *)
- Titel = 'VirTest ';
- CopyRight = '(c) 1989 A. Schuster & TOOLBOX';
- Version = 'Version 2.1 ';
-
- TYPE
- String12 = STRING[12];
- String8 = STRING[8];
- String3 = STRING[3];
- Zeiger = ^Liste;
- Liste = RECORD
- Name : String12;
- Next : Zeiger;
- END;
- SaveRec = RECORD
- Kopf : ARRAY[1..16] OF BYTE;
- Attr : BYTE;
- Time : LONGINT;
- Size : LONGINT;
- Name : String8;
- Ext : String3;
- Path : STRING[64];
- END;
-
- VAR
- Datei : String12;
- Anzahl : WORD; (* gefundene Programme *)
- Dir : STRING[64]; (* durchsuchtes Directory *)
- Puffer, (* Puffer für Programmdaten *)
- RefRec : SaveRec; (* Referenzdaten *)
- RefFile : FILE OF SaveRec;
- Prot : TEXT; (* Protokolldatei *)
- TestFile : FILE OF BYTE; (* zu testendes Programm *)
- Init : BOOLEAN; (* bei TRUE Daten holen, *)
- (* bei FALSE vergl. *)
- Kommando, (* Option /I oder /T *)
- OptionName, (* Name und *)
- OptionPfad : STRING; (* Pfad der Datendatei *)
- Warnungen, (* Anzahl der Vorwarnungen *)
- Viren : WORD; (* Anzahl der Virenmeldungen*)
- Error, (* Fehler in Datei gefunden *)
- KopfErr, (* erste 16 Bytes geändert! *)
- ExtErr, (* Extension geändert ! *)
- TypErr, (* Extension paßt nicht zu *)
- (* Dateityp ! *)
- SizeErr, (* Dateigröße verändert ! *)
- TimeErr, (* Zeiteintrag verändert ! *)
- AttribErr : BOOLEAN; (* Attribut geändert *)
-
-
- FUNCTION Min(a, b : LONGINT) : LONGINT;
- BEGIN
- IF a < b THEN min := a ELSE Min := b;
- END;
-
-
- FUNCTION ZielGruppe(NameExt : String12) : BOOLEAN;
- VAR (* Programm ? *)
- Ext : STRING[4];
- BEGIN
- Ext := Copy(NameExt, Pos('.', NameExt),4);
- IF Ext = '.COM' THEN ZielGruppe := TRUE
- ELSE
- IF Ext = '.EXE' THEN ZielGruppe := TRUE
- ELSE
- IF Ext = '.SYS' THEN ZielGruppe := TRUE
- ELSE
- IF Ext = '.VIR' THEN ZielGruppe := TRUE
- ELSE ZielGruppe:=FALSE;
- END;
-
-
- FUNCTION GetName(NameExt: String12): String8;
- (* Datei-Name separieren *)
- BEGIN
- GetName := Copy(NameExt, 1, Pos('.', NameExt) - 1);
- END;
-
-
- FUNCTION GetExt(NameExt : String12) : String3;
- (* Datei-Typ separieren *)
- BEGIN
- GetExt := Copy(NameExt, Pos('.', NameExt) + 1, 3);
- END;
-
-
- PROCEDURE ChangeExt(Name : String8;
- ExtAlt, ExtNeu : String3);
- VAR
- RenameFile : FILE OF BYTE;
- AlterName,
- NeuerName : String12;
- BEGIN
- AlterName := Name + '.' + ExtAlt;
- NeuerName := Name + '.' + ExtNeu;
- Assign(RenameFile, AlterName);
- Rename(RenameFile, NeuerName);
- END;
-
-
- PROCEDURE DateiSuche; (* Directory durchsuchen *)
- VAR
- Anfang, Neu, Aktuell : Zeiger;
- Eintrag : SearchRec;
- Fehler : BOOLEAN;
- Datum : DateTime;
- Dir : STRING[64];
-
-
- PROCEDURE DateiDaten;
- (* Daten des akt. Programms holen *)
- VAR
- i : BYTE;
- BEGIN
- Assign(TestFile, Eintrag.Name);
- IF (Eintrag.Attr AND ReadOnly) <>0 THEN
- (* Schreibschutz umgehen *)
- SetFAttr(TestFile, $00);
- Reset(TestFile);
- IF Eintrag.Size > 0 THEN BEGIN
- FOR i := 1 TO Min(16, Eintrag.Size) DO (* 16 Bytes *)
- Read(TestFile, Puffer.Kopf[i]); (* lesen, *)
- IF (Eintrag.Size < 16) THEN
- (* wenn Programm kürzer, *)
- FOR i:=Eintrag.Size TO 16 DO
- (* mit $00 auffüllen *)
- Puffer.Kopf[i] := $00;
- END ELSE
- FillChar(Puffer.Kopf[1], 16, $00);
- Close(TestFile);
- IF (Eintrag.Attr AND ReadOnly) <> 0 THEN
- (* bei Schreibschutz altes *)
- SetFAttr(TestFile, Eintrag.Attr);
- (* Attribut wiederherstellen *)
- Puffer.Attr := Eintrag.Attr;
- (* Daten des Programms in *)
- Puffer.Time := Eintrag.Time;
- (* den Puffer laden ... *)
- Puffer.Size := Eintrag.Size;
- Puffer.Name := GetName(Eintrag.Name);
- Puffer.Ext := GetExt(Eintrag.Name);
- Puffer.Path := Dir;
- IF Init THEN Write(RefFile, Puffer);
- (* ... und sichern *)
- END;
-
-
- FUNCTION KopfFehler: BOOLEAN;
- (* Veränderung i. d. ersten 16 Bytes ? *)
- VAR
- i: BYTE;
- BEGIN
- KopfFehler := TRUE;
- FOR i := 1 TO 16 DO
- IF Puffer.Kopf[i] <> RefRec.Kopf[i] THEN Exit;
- KopfFehler := FALSE;
- END;
-
-
- PROCEDURE Meldung;
- (* Bericht in Protokolldatei schreiben *)
- BEGIN
- WriteLn(Prot, Dir);
- WriteLn(Prot, ' ', Eintrag.Name);
- IF KopfErr THEN BEGIN
- WriteLn(Prot, ' V I R E N B E F A L L !');
- WriteLn(Prot, ' Im Dateikopf wurden Veränderun',
- 'gen festgestellt;');
- WriteLn(Prot, ' Sie sollten dieses Programm ',
- 'nicht mehr verwenden !');
- WriteLn(Prot, ' Die Datei wurde in *.VIR ',
- 'umbenannt.');
- END;
- IF ExtErr THEN BEGIN
- WriteLn(Prot, ' WARNUNG : Extension geändert');
- WriteLn(Prot, ' Wenn Sie die Extension nicht ',
- 'geändert haben, deutet');
- WriteLn(Prot, ' dies auf einen Virus hin.');
- END;
- IF TypErr THEN BEGIN
- WriteLn(Prot, ' WARNUNG : Falscher Dateityp');
- WriteLn(Prot, ' Die Datei trägt die Endung .COM,',
- ' ihr Aufbau ent-');
- WriteLn(Prot, ' spricht dem Typ .EXE. Dies ',
- 'deutet auf Viren hin.');
- WriteLn(Prot, ' Die Datei wurde in *.EXE ',
- 'umbenannt.');
- END;
- IF SizeErr THEN BEGIN
- WriteLn(Prot, ' WARNUNG : Die Größe der Datei ',
- 'hat sich geändert');
- WriteLn(Prot, ' Haben Sie das Programm neu ',
- 'compiliert oder installiert ?');
- WriteLn(Prot, ' Sonst kann dies auf Viren ',
- 'hindeuten.');
- END;
- IF TimeErr THEN BEGIN
- WriteLn(Prot, ' WARNUNG : Das Datei-Datum hat ',
- 'sich geändert');
- WriteLn(Prot, ' Haben Sie das Programm neu ',
- 'compiliert oder installiert ?');
- WriteLn(Prot, ' Sonst kann dies auf Viren ',
- 'hindeuten.');
- END;
- IF AttribErr THEN
- WriteLn(Prot, ' HINWEIS : Dateiattribut ',
- 'verändert !');
- END;
-
-
- PROCEDURE FindeFehler;
- (* aktuelle Daten mit *)
- CONST (* Referenz vergleichen *)
- Abbruch : BOOLEAN = FALSE;
- BEGIN
- Error := FALSE; (* Flags initialisieren *)
- KopfErr := FALSE;
- ExtErr := FALSE;
- TypErr := FALSE;
- SizeErr := FALSE;
- TimeErr := FALSE;
- AttribErr := FALSE;
- IF (Puffer.Path <> RefRec.Path) OR
- (Puffer.Name <> RefRec.Name) THEN BEGIN
- WriteLn(Prot);
- WriteLn(Prot, ' Im Pfad oder Dateinamen wurden ',
- 'Veränderungen');
- WriteLn(Prot, ' festgestellt. VirTest muß neu ',
- 'initialisiert');
- WriteLn(Prot, ' werden.');
- WriteLn(Prot, ' Erwartet : ', RefRec.Path, '\',
- RefRec.Name + '.' + RefRec.Ext);
- WriteLn(Prot, ' Gefunden : ', Puffer.Path, '\',
- Puffer.Name + '.' + Puffer.Ext);
- Close(Prot);
- Close(RefFile);
- GotoXY(1,5);
- WriteLn('Programm abgebrochen - bitte lesen Sie ',
- LogName);
- WriteLn;
- ChDir(OptionPfad);
- Halt(1);
- END;
- IF KopfFehler AND (Puffer.Ext<>'VIR') THEN BEGIN
- (* Veränderung i.d. ersten 16 Bytes ? *)
- Error := TRUE;
- KopfErr := TRUE;
- Viren := Viren + 1; (* Hinweis auf Virus *)
- ChangeExt(Puffer.Name, Puffer.Ext, 'VIR');
- (* Datei umbenennen *)
- Abbruch := TRUE;
- Exit;
- END;
- IF (Puffer.Ext <> RefRec.Ext) AND
- (Puffer.Ext <> 'VIR') THEN BEGIN
- IF (Chr(Puffer.Kopf[1]) + Chr(Puffer.Kopf[2]) = 'MZ')
- (* EXE-Header ? *)
- AND (Puffer.Ext='COM') THEN BEGIN
- (* Extension und Typ inkonsistent *)
- Error := TRUE;
- TypErr := TRUE; (* Typenfehler schwerwiegender *)
- ExtErr := FALSE;(* als Extensionsfehler *)
- Viren := Viren + 1;
- ChangeExt(Puffer.Name, Puffer.Ext, 'EXE');
- (* Fehler korrigieren *)
- Abbruch := TRUE;
- END;
- END;
- IF NOT Abbruch THEN BEGIN
- IF Puffer.Size <> RefRec.Size THEN SizeErr := TRUE;
- IF (Puffer.Time <> RefRec.Time)
- AND (NOT SizeErr) THEN TimeErr := TRUE;
- IF Puffer.Attr <> RefRec.Attr THEN AttribErr := TRUE;
- IF ExtErr OR SizeErr OR TimeErr OR
- AttribErr THEN BEGIN
- Error := TRUE;
- Warnungen := Warnungen + 1;
- END;
- END;
- END;
-
-
- PROCEDURE DateiTest; (* Programm überprüfen *)
- BEGIN
- Read(RefFile, RefRec);
- DateiDaten;
- FindeFehler;
- IF Error THEN Meldung;
- (* wenn Fehler gefunden, Protokoll schreiben *)
- END;
-
-
- BEGIN (* DateiSuche *)
- FindFirst('*.*', AnyFile, Eintrag);
- GetDir(0,Dir); (* Pfad merken *)
- WHILE DosError=0 DO BEGIN
- IF ZielGruppe(Eintrag.Name) THEN BEGIN
- GotoXY(1,5); DelLine;
- WriteLn('Bearbeitet : ', Eintrag.Name);
- IF Init THEN DateiDaten (* Referenzdaten erstellen *)
- ELSE DateiTest; (* Programm testen *)
- Anzahl := Anzahl + 1;
- END;
- FindNext(Eintrag);
- END;
- Anfang := NIL; (* Anfang der Unterver- *)
- Aktuell := NIL; (* zeichnisliste *)
- FindFirst('*.*', Directory, Eintrag);
- WHILE DosError = 0 DO BEGIN
- IF Eintrag.Attr = Directory THEN BEGIN
- New(Neu); (* in Liste aufnehmen ... *)
- Neu^.Name := Eintrag.Name;
- Neu^.Next := NIL;
- IF Anfang = NIL THEN Anfang := Neu
- ELSE Aktuell^.Next := Neu;
- Aktuell := Neu;
- END;
- FindNext(Eintrag); (* und weitersuchen *)
- END;
- Aktuell := Anfang;
- WHILE Aktuell <> NIL DO BEGIN
- IF (Aktuell^.Name <> '..') AND
- (Aktuell^.Name <> '.') THEN BEGIN
- ChDir(Aktuell^.Name); (* ins nächste Verzeichnis *)
- DateiSuche; (* Programme suchen *)
- ChDir('..'); (* und zurück *)
- END;
- Aktuell := Aktuell^.Next;
- END;
- END;
-
-
- PROCEDURE Initialisierung; (* Referenzdatei erstellen *)
- BEGIN
- GetDir(0, Dir); (* Ausgangspunkt merken *)
- ChDir(OptionPfad);
- GotoXY(1, 4);
- WriteLn('Platte/Diskette initialisieren');
- Init := TRUE;
- Assign(RefFile, OptionName);
- Rewrite(RefFile); (* Datei anlegen *)
- Anzahl := 0;
- ChDir('\'); (* ins Hauptverzeichnis *)
- DateiSuche; (* nach Programmen suchen *)
- GotoXY(1, 5);
- DelLine;
- WriteLn('Gesamt gefunden : ', Anzahl, ' Datei(en)');
- ChDir(Dir);
- Close(RefFile);
- END;
-
-
- PROCEDURE Test;
- BEGIN
- Warnungen := 0;
- Viren := 0;
- GetDir(0, Dir);
- GotoXY(1, 4);
- WriteLn('Platte/Diskette testen');
- Init := FALSE;
- ChDir(OptionPfad);
- Assign(RefFile, OptionName); Reset(RefFile);
- Assign(Prot, LogName) ; Rewrite(Prot);
- Anzahl := 0;
- ChDir('\');
- DateiSuche;
- Close(RefFile);
- WriteLn(Prot);
- Write(Prot, 'Report : ', Warnungen:3, ' Warnung(en) ');
- WriteLn(Prot, Viren:3, ' Virenmeldung(en)');
- Close(Prot);
- GotoXY(1, 5);
- Write('VirTest Report : ',Warnungen:3);
- WriteLn(' Warnung(en) ', Viren:3, ' Virenmeldung(en)');
- IF Warnungen + Viren > 0 THEN BEGIN
- WriteLn('Bitte lesen Sie die Logdatei ', LogName);
- ChDir(OptionPfad);
- IF Viren > 0 THEN Halt(20) ELSE
- (* Infornation für ERRORLEVEL *)
- IF Warnungen > 0 THEN Halt(10)
- (* bzw. DosExitCode *)
- END;
- ChDir(Dir);
- Halt(5); (* 20=Viren; 10=Warnung; 5=OK *)
- END;
-
-
- PROCEDURE HilfsText; (* Syntax ausgeben *)
- BEGIN
- WriteLn('Syntax : VIRTEST /I [d:\pfad] [dateiname] ',
- 'Initialisierung');
- WriteLn(' /T [d:\pfad] [dateiname] ',
- 'Test');
- WriteLn;
- WriteLn;
- Halt(1);
- END;
-
-
- BEGIN (* Hauptprogramm *)
- ClrScr;
- WriteLn(Titel, Version, CopyRight);
- IF ParamCount < 1 THEN HilfsText;
- Kommando := ParamStr(1);
- OptionPfad := ParamStr(2);
- OptionName := ParamStr(3);
- IF Kommando = '?' THEN HilfsText;
- IF (Pos('\', OptionPfad) = 0) AND
- (Pos(':', OptionPfad) = 0) THEN BEGIN
- OptionName := OptionPfad;
- GetDir(0, OptionPfad);
- END;
- IF OptionName = '' THEN OptionName := DefaultName;
- IF Pos(':', OptionPfad) = Length(OptionPfad) THEN
- OptionPfad := OptionPfad + '\';
- IF (Kommando = '/I') OR (Kommando='/i') THEN
- Initialisierung
- ELSE
- IF (Kommando = '/T') OR (Kommando = '/t') THEN Test
- ELSE HilfsText;
- END.
- (* ------------------------------------------------------ *)
- (* Ende von VIRTEST.PAS *)