home *** CD-ROM | disk | FTP | other *** search
- PROGRAM GarbageCompactor;
-
- {$I "Include:Utils/Break.i"}
- {$I "Include:Libraries/DOS.i"}
- {$I "Include:Utils/DateTools.i"}
- {$I "Include:Utils/StringLib.i"}
- {$I "Include:Utils/Parameters.i"}
-
- {
- Trash Compactor version 1.11 December 7, 1991
- version 1.1 December 7, 1991
- version 1.0 November 26, 1991
-
- Stephan Zuercher internet: szuerche@jarthur.claremont.edu
- GEnie: S.ZUERCHER
-
- A program that will check the trashcan for file that have been in the
- trashcan for more than a specified number of days, deleting any files
- that meet the requirement of having been there long enough.
-
- This program was inspired by a program on Norton Desktop (an add-on to
- Microsoft's Windows for the IBM PC) that does pretty much the same thing
- as this program.
-
- Forgive me for not having written it in C. I need the practice in Pascal
- and PCQ also happens to be the only compiled programming language available
- to me right now.
-
- Command line parameters:
-
- TrashCompactor [-#] [path1] [path2] ... [path10] [quiet]
-
- Where # is the number of days old a file must be before it gets sent to
- Never-Never Land and path1, path2, ... path10 are up to ten different paths
- to the various trashcans that may or may NOT be floating around your
- system. If the quiet switch is given, the program will NOT tell you that
- it is deleting files. If no parameters are given on the command line, the
- program will default to 5 days old, SYS:Trashcan, and will tell you that it
- is in fact deleting files.
-
- There is a maximum number of days old for -# parameter. It is 28 days.
- There is also a minimum number of days. That's one day. 8)
-
- Version 1.11 We couldn't delete subdirectories of the trashcan. It checked
- the date on the subdir before deletion, however, if _any_
- files had been deleted from the subdir, its date would be
- the current date and the subdir itself wouldn't get deleted.
- Solution: Try to delete all subdirs. If they're empty, then
- they disappear, otherwise they stay. Not pretty,
- but it works.
- Version 1.1 If there was more than one subdirectory in the Trashcan it
- would only find the first. Argh. I knew I shouldn't have
- used the code from Find.p. Well its rewritten now. It should
- work.
-
- Version 1.0 Well, it runs. Doesn't give back 200 bytes of memory, but I
- know where that is.
- }
-
- TYPE
- CLarray1 = ARRAY [1..12] OF String;
- CLarray2 = ARRAY [1..10] OF String;
-
- VAR
- CLstrings : CLarray2;
- BeQuiet : BOOLEAN;
- MaxDaysOld,
- DelYear,
- count,
- numdel,
- totdel : Short;
- DelMonth,DelDay : BYTE;
-
-
- FUNCTION StringToInteger(t : String) : Integer;
-
- { This function takes an integer value from a string and converts it into
- a pascal integer. Please NOT that it has been modified for TrashCompactor
- by stopping before the negative sign that is prepended to each string
- passed. That means if you steal this routine for your own program you'll
- have to modify it for negative numbers, or if you'll only be needing
- positive conversions, change the DOWNTO 1 in the FOR loop to DOWNTO 0.
- }
-
- VAR
- tot,x,count,place,factor,length : Integer;
-
- BEGIN { StringToInteger }
- x := 0; { Initialize variables }
- tot := 0;
- factor := 1;
- length := strlen(t);
- FOR count := length-1 DOWNTO 1 DO { Loop for last digit in number to first }
- BEGIN
- x := (ORD(t[count])-48) * factor;
- { Determine value of a digit }
- { Multiply x by the factor for the place value }
- tot := tot + x; { Add x to the current tot }
- factor := factor * 10; { Multiply factor by 10, to get the value for
- the next multiplication factor }
- END;
- StringToInteger := tot;
- END; { StringToInteger }
-
-
- PROCEDURE GetCL(VAR CLstr : CLarray2;
- VAR DaysBack : Short;
- VAR ShutUp : BOOLEAN);
-
- { This procedure gets the command line parameters, and returns an array
- containing up to ten paths minus the other parameters. The proceudre
- also returns how many days old a file can be before it gets deleted and
- whether output should be suppressed. }
-
- VAR
- allCLstr : CLarray1;
- numparams,
- count,
- returncount : Short;
- temp : String;
-
- BEGIN
- DaysBack := 5;
- ShutUp := False;
- FOR count := 1 TO 12 DO
- allCLstr[count] := AllocString(128);
- count := 0;
- returncount := 0;
- temp := AllocString(128);
- REPEAT
- BEGIN
- count := count + 1;
- GetParam(count,allCLstr[count]);
- END
- UNTIL (strlen(allCLstr[count]) < 1) OR (count = 12);
- IF strlen(allCLstr[count]) < 1 THEN
- numparams := count - 1
- ELSE
- numparams := count;
- FOR count := 1 TO numparams DO
- IF strnieq(allCLstr[count],"-",1) THEN
- BEGIN
- strcpy(temp,allCLstr[count]);
- IF (temp[1] = 'h') OR (temp[1] = 'H') OR (temp[1] = '?') THEN
- DaysBack := -42
- ELSE
- BEGIN
- DaysBack := StringToInteger(temp);
- IF DaysBack > 28 THEN DaysBack := 28;
- END
- END
- ELSE
- IF strnieq(allCLstr[count],"QUIET",5) THEN
- ShutUp := True
- ELSE
- BEGIN
- returncount := returncount + 1;
- CLstr[returncount] := allCLstr[count];
- END;
- IF returncount = 0 THEN
- CLstr[1] := strdup("SYS:Trashcan")
- ELSE
- IF returncount < 10 THEN
- FOR returncount := returncount + 1 TO 10 DO
- CLstr[returncount] := AllocString(1);
- END; { Get CL }
-
-
-
- PROCEDURE GetDeleteDate( DaysBack : SHORT;
- VAR DelMonth,DelDay : BYTE;
- VAR DelYear : SHORT);
-
- VAR
- SysDate,
- DelDate : DateDescription;
-
- BEGIN
- TimeDesc(SysDate); { Get System Date. If this isn't set }
- WITH SysDate DO { before execution, thou art reamed... }
- BEGIN
- IF (Year/4) = (Year DIV 4) THEN { Is this a leap year? If so... make }
- DaysInMonth[1] := 29; { # of days in Feb = 29 instead of 28 }
- IF Day > DaysBack THEN
- BEGIN
- DelDay := Day - DaysBack; { If we are >DaysBack into the month, }
- DelMonth := Month; { just back up the date x days to find }
- DelYear := Year; { what date to delete file before }
- END { Block }
- ELSE
- IF Month > 1 THEN { Otherwise if this isn't Jan, we back }
- BEGIN { into the previous month, keeping the }
- DelDay := (Day-DaysBack) + DaysInMonth[Month-2];
- DelMonth := Month - 1; { year. Note DaysInMonth is zero based}
- DelYear := Year; { but Month isn't. Go figure... }
- END { Block }
- ELSE
- BEGIN { Otherwise we get to back up into the }
- DelDay := (Day-DaysBack) + DaysInMonth[11];
- DelMonth := 12; { previous year! Month *has* to be Dec}
- DelYear := Year - 1 { in case you care to know... }
- END; { Block }
- END; { With Block }
- END;
-
- FUNCTION CheckDateAndDelete( path : String;
- FIBptr : FileInfoBlockPtr) : BOOLEAN;
-
- VAR
- pathname,
- filename : String;
- DOSError,
- datediff : Integer;
- DD : DateDescription;
- DeleteIt : BOOLEAN;
- dirlock : FileLock;
-
- BEGIN
- DeleteIt := FALSE; { set up some stuff... }
- pathname := AllocString(140);
- filename := AllocString(31);
- strcpy(pathname,path); { path is dir file is in }
- strcpy(filename,ADR(FIBptr^.fib_FileName)); { get filename from FIB }
- strcat(pathname,"/"); { put a / on the end of dir }
- strcat(pathname,filename); { put filename on end of dir }
- StampDesc(FIBptr^.fib_Date,DD); { get date from file }
- WITH DD DO
- IF DelYear > Year THEN { check date against global }
- DeleteIt := TRUE { DelDates }
- ELSE
- IF DelYear = Year THEN
- IF DelMonth > Month THEN
- DeleteIt := TRUE
- ELSE
- IF DelMonth = Month THEN
- IF DelDay > Day THEN
- DeleteIt := TRUE;
- IF NOT BeQuiet THEN { Print out the filename if we're allowed }
- Write(pathname,' ');
- IF DeleteIt THEN { Delete file if its old enough. }
- BEGIN
- IF DeleteFile(pathname) THEN
- BEGIN
- IF NOT BeQuiet THEN { Inform user of deletion }
- WriteLn('\e[33;1mdeleted.\e[31;40;0m');
- END
- ELSE
- BEGIN
- DeleteIt := FALSE; { Problem... }
- DOSError := IOErr;
- IF (DOSError = ERROR_DELETE_PROTECTED) THEN
- BEGIN
- IF BeQuiet THEN { We tell the user about deletion }
- Write(pathname,' '); { Protection even if we're supposed }
- { to be quiet... }
- WriteLn('protected from deletion.');
- END
- ELSE
- IF NOT BeQuiet THEN { Inform user of error }
- WriteLn('not deleted. \e[33;1mError #',DOSError,'\e[31;40;0m');
- END;
- END
- ELSE
- IF NOT BeQuiet THEN
- WriteLn('not deleted. File too new.');
- CheckDateAndDelete := DeleteIt;
- END;
-
- PROCEDURE DeleteDir(pathname : String);
-
- { We try to delete the directory. Assuming its empty it works, otherwise,
- it not empty and we don't do anything. In version 1.1, this procedure
- didn't exist. I used a call to CheckDateAndDelete and checked FIBptr within
- that function to see if this was a directory. It it was, the function
- didn't do any string manipulation to get a pathname, because the correct
- one was already in the calling parameters. Only one problem, deleting a
- file within a directory changes its date. That means that subdirectories
- in the trashcan NEVER got deleted unless they were empty to begin with.
- Now we try to delete all subdirs. If they're empty they're gone, if not
- then we leave them. Simple. }
-
- VAR
- DOSError : Integer;
-
- BEGIN
- IF NOT BeQuiet THEN
- Write(pathname,' ');
- IF NOT DeleteFile(pathname) THEN
- BEGIN
- DOSError := IOErr;
- IF DOSError <> ERROR_DIRECTORY_NOT_EMPTY THEN
- BEGIN
- IF NOT BeQuiet THEN
- WriteLn('not deleted. \e[33;1mError #',DOSError,'\e[31;40;0m');
- END
- ELSE
- IF NOT BeQuiet THEN
- WriteLn('not deleted.');
- END
- ELSE
- IF NOT BeQuiet THEN
- WriteLn('\e[33mdeleted.\e[31;40;0m');
- END; { DeleteDir }
-
-
- FUNCTION CleanUpDir(dir : string) : Short;
-
- { This function runs down the dir list using ExNext...If it finds a
- directory, it calls itself recursively. After it goes through a
- directory, it tries to delete it if files were deleted from within it }
-
- VAR
- flock,
- dirlock : FileLock;
- FIBptr : FileInfoBlockPtr;
- DoAnother,
- barf : BOOLEAN;
- DOSError : Integer;
- count,
- subdircount : Short;
- newdir : String;
-
- BEGIN
- count := 0;
- flock := Lock(dir,ACCESS_READ);
- IF flock = NIL THEN { Couldn't get lock: dir doesn't exist! }
- CleanUpDir := -1;
- New(FIBptr);
- IF NOT Examine(flock,FIBptr) THEN { Can't get info on flock!? }
- BEGIN
- Unlock(flock);
- CleanUpDir := 0;
- END;
- IF FIBptr^.fib_DirEntryType < 0 THEN { This isn't a directory, its a file! }
- BEGIN
- Unlock(flock);
- CleanUpDir := -2;
- END;
- REPEAT
- BEGIN
- DoAnother := ExNext(flock, FIBptr);
- IF CheckBreak THEN
- DoAnother := FALSE;
- IF DoAnother THEN
- BEGIN
- IF FIBptr^.fib_DirEntryType < 0 THEN { we've got a file... }
- BEGIN
- IF CheckDateAndDelete(dir,FIBptr) THEN
- count := count + 1;
- END
- ELSE
- BEGIN { Another directory... }
- newdir := AllocString(109);
- strcpy(newdir,dir);
- strcat(newdir,"/");
- strcat(newdir,ADR(FIBptr^.fib_FileName));
- subdircount := CleanUpDir(newdir);
- count := count + subdircount;
- IF subdircount > 0 THEN
- BEGIN
- dirlock := Lock(newdir,ACCESS_READ);
- IF dirlock = NIL THEN
- BEGIN
- WriteLn('Unable to lock ',newdir);
- Exit(25);
- END;
- IF NOT Examine(dirlock,FIBptr) THEN
- BEGIN
- WriteLn('Unable to examine ',newdir);
- Exit(25);
- END;
- Unlock(dirlock);
- DeleteDir(newdir);
- END;
- END
- END
- ELSE
- BEGIN
- DOSError := IOErr; { This might not be bad... }
- IF (DOSError <> ERROR_NO_MORE_ENTRIES) AND NOT CheckBreak THEN
- WriteLn('\nError #',DOSError,' has occurred.');
- END;
- END;
- UNTIL NOT DoAnother;
- Unlock(flock);
- CleanUpDir := count;
- END;
-
-
- BEGIN
- GetCL(CLstrings,MaxDaysOld,BeQuiet);
- IF (MaxDaysOld = -42) OR strieq(CLstrings[1],"H")
- OR strieq(CLstrings[1],"?") THEN
- BEGIN
- WriteLn;
- WriteLn('\e[33;1mTrashCompactor\e[31;40;0m by Stephan Zuercher');
- WriteLn('Version 1.11 on December 7, 1991');
- WriteLn;
- WriteLn('Usage: TrashCompactor -# [path1] [path2] ... [path10] [QUIET]');
- WriteLn;
- WriteLn('Where # = age of files in days before deletion occurs.');
- WriteLn(' The default is 5 days.');
- WriteLn(' path# = one of ten possible directories to treat as');
- WriteLn(' Trashcans. Default is SYS:Trashcan.');
- WriteLn(' QUIET = a switch that controls the whether the program');
- WriteLn(' outputs information about file deletion to the');
- WriteLn(' screen.');
- Exit(20);
- END;
-
- GetDeleteDate(MaxDaysOld,DelMonth,DelDay,DelYear);
-
- count := 1;
- numdel := 0;
- totdel := 0;
- WHILE (StrLen(CLStrings[count]) > 0) AND NOT CheckBreak DO
- BEGIN
- numdel := CleanUpDir(CLStrings[count]);
- IF numdel >= 0 THEN
- totdel := totdel + numdel
- ELSE
- BEGIN
- Write(CLStrings[count]);
- IF numdel = -2 THEN
- WriteLn(' is NOT a directory.')
- ELSE
- WriteLn(' does NOT exist.');
- END;
- count := count + 1;
- END;
- IF NOT BeQuiet THEN WriteLn(totdel,' files deleted.');
-
- END.
-