home *** CD-ROM | disk | FTP | other *** search
- program LibraryUtility;
- { written 10/09/84 by Steve Freeman
- This program was written to function as Gary Novosielski's LU. As such it
- will function as a utility to manipulate library members under any operating
- system which will support TURBO Pascal. Minor rewrites may be necessary for
- other versions of Pascal.
- This program is placed into the Public Domain by the author and, as a Public
- Domain program, may NOT be used for commercial purposes.}
- { modified by R.T. Moss 10/12/85 for Turbo Pascal Version 2.0
- original program had fatal I/O errors at runtime.
- changed version number to 1.10
- added 1K buffer for faster Add & Extract }
-
- const ProgramVersion = '1.10';
- BufferSize = 127; { maximum size of data buffer - 1 }
- EntriesPerBuffer = 4; { (BufferSize+1)/32 }
- maxent = 128; { maximum dir entries this program will take }
- BigBuffSize = 1023; { large size for buffer to speedup Add & Extract }
-
- type TimeType = integer;
- FileNameType = array[1..11] of char;
- LibFileType = file;
- EntryType = record
- status: byte;
- name: array[1..8] of char;
- ext: array[1..3] of char;
- index: integer;
- length: integer;
- CRC: integer;
- CreationDate: integer;
- LastChangeDate: integer;
- CreationTime: TimeType;
- LastChangeTime: TimeType;
- filler: array[26..31] of byte;
- end;
- EntryPtr = ^EntryType;
- hexstr = string[4];
- maxstr = string[255];
- filename = string[14];
-
- var buffer: array[0..BufferSize] of byte;
- BigBuff: array[0..BigBuffSize] of byte;
- library, file2: file;
- DirectoryChanged: boolean;
- LibName, fname: filename;
- LibSize, NumEntries: integer;
- LibEntry: EntryType;
- Dir: array[0..maxent] of EntryPtr;
- active, unused, deleted: integer;
-
- procedure WaitKey;
- var c: char;
- begin
- write(^M^J,'Press any key to continue...');
- repeat until keypressed;
- read(kbd,c);
- end;
-
- function Confirm: boolean;
- var c: char;
- begin
- write('Confirm operation (Y/N): ');
- repeat
- read(kbd,c);
- c:=upcase(c);
- until (c in ['Y','N']);
- writeln(c);
- if c = 'Y' then Confirm:=true else Confirm:=false
- end;
-
- function CommandLine: maxstr;
- var len, i: integer;
- str: maxstr;
- begin
- str:='';
- len:=mem[$80];
- if len>1 then for i:=2 to len do str:=str + chr(mem[$80+i]);
- CommandLine:=str;
- end;
-
- function hex(num: integer): hexstr;
- var i, j: integer;
- h: string[16];
- str: hexstr;
- begin
- str:='0000'; h:='0123456789ABCDEF'; j:=num;
- for i:=4 downto 1 do
- begin
- str[i]:=h[(j and 15)+1];
- j:=j shr 4;
- end;
- hex:=str;
- end;
-
- procedure MakeName(f: filename; var name: FileNameType);
- var dotpos, endname, i: integer;
- begin
- for i:=1 to 11 do name[i]:=' ';
- dotpos:=pos('.',f);
- if dotpos > 0 then endname:=dotpos-1 else endname:=length(f);
- for i:=1 to length(f) do f[i]:=upcase(f[i]);
- if dotpos > 0 then
- for i:=1 to 3 do
- if f[dotpos+i]<>' ' then name[8+i]:=f[dotpos+i];
- for i:=1 to endname do name[i]:=f[i];
- end;
-
- procedure PutName(f: filename; n: integer);
- var i: integer;
- name: FileNameType;
- begin
- MakeName(f,name);
- for i:=1 to 8 do Dir[n]^.name[i]:=name[i];
- for i:=1 to 3 do Dir[n]^.ext[i] :=name[i+8];
- end;
-
- function FindMember(f: filename): integer;
- var member, dotpos, endname, i, k: integer;
- lookup: FileNameType;
- found: boolean;
-
- function NamesMatch(entry: integer): boolean;
- var match: boolean;
- begin
- NamesMatch:=true;
- with Dir[entry]^ do
- begin
- if status = $FF then NamesMatch:=false;
- for k:=1 to 8 do if name[k]<>lookup[k] then NamesMatch:=false;
- for k:=1 to 3 do if ext[k]<>lookup[8+k] then NamesMatch:=false;
- end;
- end;
-
- begin
- MakeName(f,lookup);
- found:=false; i:=1;
- if (active = 1) and (deleted = 0)
- then FindMember := 0
- else
- begin
- repeat
- if NamesMatch(i)
- then found := true
- else i := i + 1;
- until found or (i > NumEntries);
- if found
- then FindMember := i
- else FindMember := 0;
- end;
- end;
-
- function Parse(f: filename): filename;
- var i: integer;
- begin
- for i:=1 to length(f) do f[i]:=upcase(f[i]);
- i:=pos('.',f);
- if i>0 then f:=copy(f,1,i-1);
- f:=f + '.LBR';
- Parse:=f;
- end;
-
- procedure WriteDirectoryToDisk(var lib: LibFileType);
- var member, i: integer;
- begin
- reset(lib);
- member:=0;
- while member < NumEntries do
- begin
- for i:=0 to EntriesPerBuffer-1 do move(Dir[member+i]^,buffer[32*i],32);
- blockwrite(lib,buffer,1);
- member:=member + 4
- end;
- DirectoryChanged:=false
- end;
-
- procedure ZeroEntry(n: integer);
- begin
- fillchar(Dir[n]^,32,chr(0)); {clear the record}
- fillchar(Dir[n]^.name[1],11,' '); {clear file name}
- Dir[n]^.status:=-1; {mark unused}
- end;
-
- procedure SortDir;
- var i, j: integer;
-
- function larger(a, b: integer): boolean;
- var ok, x: integer;
- c1, c2: char;
- begin
- ok:=0; x:=1;
- if (Dir[a]^.status <> 0) and (Dir[b]^.status <> 0) then ok:=2;
- if (Dir[a]^.status <> 0) and (ok = 0) then ok:=1;
- if (Dir[b]^.status <> 0) and (ok = 0) then ok:=2;
- while (x < 12) and (ok=0) do
- begin
- c1:=Dir[a]^.name[x]; c2:=Dir[b]^.name[x];
- if c1 > c2 then ok:=1;
- if c1 < c2 then ok:=2;
- x:=x + 1
- end;
- if ok=1 then larger:=true else larger:=false
- end;
-
- procedure swap(x, y: integer);
- var temp: EntryPtr;
- begin
- temp :=Dir[x];
- Dir[x]:=Dir[y];
- Dir[y]:=temp
- end;
-
- begin
- for i:=1 to NumEntries-1 do
- if Dir[i]^.status <> 0 then ZeroEntry(i);
- for i:=1 to NumEntries-2 do
- for j:=i+1 to NumEntries-1 do
- if larger(i,j) then swap(i,j);
- end;
-
- procedure CreateDirectory;
- var i: integer;
- begin
- rewrite(library);
- clrscr; writeln('Creating a new library. Name = ',LibName);
- write('How many entries? '); readln(i);
- NumEntries:=i + 1; {add 1 for Directory entry}
- i:=NumEntries MOD 4;
- if i<>0 then NumEntries:=NumEntries + (4 - i);
- for i:=0 to NumEntries-1 do
- begin
- new(Dir[i]);
- ZeroEntry(i);
- end;
- Dir[0]^.status:=0; {directory entry is always used}
- Dir[0]^.length:=NumEntries DIV 4;
- active:=1; unused:=NumEntries - 1; deleted:=0;
- WriteDirectoryToDisk(library);
- LibSize := NumEntries DIV 32;
- if LibSize < 1 then LibSize := 1;
- end;
-
- procedure GetDirectory;
- var i, offset: integer;
- begin
- offset:=0; DirectoryChanged:=false;
- LibSize:=(1 + filesize(library)) DIV 8; {in kilobytes}
- blockread(library,buffer,1);
- new(Dir[0]); {make space for directory header}
- move(buffer[0],Dir[0]^,32); {move header entry}
- NumEntries:=(128 * Dir[0]^.length) DIV 32;
- for i:=1 to NumEntries-1 do
- begin
- if (i MOD EntriesPerBuffer) = 0 then
- begin {read next block}
- blockread(library,buffer,1);
- offset:=offset + EntriesPerBuffer;
- end;
- new(Dir[i]);
- move(buffer[32*(i-offset)],Dir[i]^,32);
- end;
- active:=1; unused:=0; deleted:=0;
- for i:=1 to NumEntries-1 do
- if Dir[i]^.status=0 then active:=active + 1
- else if Dir[i]^.status=$FE then deleted:=deleted + 1
- else unused:=unused + 1;
- end;
-
- procedure OpenLibrary;
- begin
- assign(library,LibName);
- {$I-} reset(library) {$I+};
- if IOresult=0 then GetDirectory else CreateDirectory;
- end;
-
- procedure Directory;
- var i, j: integer;
- begin
- clrscr;
- writeln('Library ',LibName,' is ',LibSize,'K',^M^J);
- writeln(' name index length CRC');
- writeln('------------------------------------');
- for i:=1 to NumEntries-1 do
- with Dir[i]^ do
- begin
- if status<>$FF then
- begin
- for j:=1 to 8 do write(name[j]);
- write('.');
- for j:=1 to 3 do write(ext[j]);
- write(' ',index:8,length:8,' ',hex(CRC));
- if status=$FE then write(' deleted');
- writeln;
- end;
- end;
- writeln(^M^J,active,' active, ',unused,' unused, ',deleted,' deleted: ',active+unused+deleted,' total entries.');
- WaitKey;
- end;
-
- procedure Extract;
- var fname2: filename;
- i, blocknum, blocksleft: integer;
- begin
- clrscr;
- write('Enter filename to extract: '); readln(fname2);
- if length(fname2)>0 then
- begin
- i:=FindMember(fname2);
- if i>0 then
- begin
- assign(file2,fname2);
- rewrite(file2);
- with Dir[i]^ do
- begin
- seek(library,index);
- blocknum:=1; blocksleft:=length;
- repeat {copy data from library to file2}
- if blocksleft >= 4 then {write 1k blocks if possible}
- begin
- blockread(library,BigBuff,4);
- blockwrite(file2,BigBuff,4);
- blocksleft := blocksleft - 4;
- end
- else {finish with 128 char blocks}
- begin { if necessary }
- blockread(library,buffer,1);
- blockwrite(file2,buffer,1);
- blocksleft := blocksleft - 1;
- end;
- until blocksleft = 0;
- end;
- close(file2);
- end
- else writeln('member was not found!!');
- end;
- WaitKey;
- end;
-
- procedure Delete;
- var fname2: filename;
- i: integer;
- ok: boolean;
- begin
- clrscr;
- write('Enter member to delete: '); readln(fname2);
- if length(fname2)>0 then
- begin
- i:=FindMember(fname2);
- if i>0 then
- begin
- ok:=Confirm;
- write('Member ',fname2);
- if ok then
- begin
- Dir[i]^.status:=$FE;
- deleted:=deleted + 1;
- active:=active - 1;
- writeln(' was deleted.');
- DirectoryChanged:=true;
- end
- else writeln(' was NOT deleted.')
- end
- else writeln(fname2,' does not exist.');
- WaitKey;
- end;
- end;
-
- procedure Undelete;
- var fname2: filename;
- i: integer;
- ok: boolean;
- begin
- clrscr;
- write('Enter member to undelete: '); readln(fname2);
- if length(fname2)>0 then
- begin
- i:=FindMember(fname2);
- if i>0 then
- begin
- Dir[i]^.status:=0;
- deleted:=deleted - 1;
- active:=active + 1;
- writeln(fname2,' was undeleted.');
- DirectoryChanged:=true;
- end
- else writeln(fname2,' does not exist.');
- WaitKey;
- end;
- end;
-
- procedure Add;
- var fname2: filename;
- EntryLength, EntryIndex, SizeOfFile, number, i, blocksleft: integer;
- begin
- number:=0; i:=1;
- while (number = 0) and (i < NumEntries) do
- if (Dir[i]^.status=$FF) and (number=0) then number:=i else i:=i + 1;
- clrscr;
- if number > 0 then
- begin
- write('Enter member to add: '); readln(fname2);
- if length(fname2)>0 then
- begin
- writeln('checking library directory');
- i := FindMember(fname2);
- if i = 0 then
- begin
- assign(file2,fname2);
- {$I-} reset(file2) {$I+};
- if IOresult=0 then
- begin
- SizeOfFile:=filesize(file2);
- EntryIndex :=filesize(library);
- EntryLength:=filesize(file2);
- writeln('Adding ', fname2, ' ', EntryLength);
- seek(library,EntryIndex);
- blocksleft := EntryLength;
- repeat {copy from file2 to library}
- if blocksleft >= 4 then
- begin {use 1k blocks if possible}
- blockread(file2,BigBuff,4);
- blockwrite(library,BigBuff,4);
- blocksleft := blocksleft - 4;
- end
- else
- begin {copy rest with 128 char blocks}
- blockread(file2,buffer,1);
- blockwrite(library,buffer,1);
- blocksleft := blocksleft - 1;
- end;
- until blocksleft = 0;
- close(file2);
- fillchar(Dir[number]^,32,chr(0)); {status:=0}
- Dir[number]^.index :=EntryIndex;
- Dir[number]^.length:=EntryLength;
- PutName(fname2,number);
- unused:=unused - 1;
- active:=active + 1;
- write('Member ',fname2,' was added.');
- DirectoryChanged:=true;
- end
- else writeln('File ',fname2,' was not found.');
- end
- else writeln(fname2,' is already a member.');
- end;
- end
- else writeln('There are no available places to put this entry.');
- WaitKey;
- end;
-
- procedure Reorganize;
- var i, j: integer;
- begin
- SortDir;
- assign(file2,'WORKLBR.$$$');
- reset(library); rewrite(file2);
- WriteDirectoryToDisk(file2);
- for i:=1 to NumEntries-1 do
- with Dir[i]^ do
- begin
- if (status = 0) and (length > 0) then
- begin
- writeln('Copying: ',name,'.',ext,' ',filepos(file2));
- seek(library,index);
- index:=filepos(file2);
- for j:=1 to length do
- begin
- blockread (library,buffer,1);
- blockwrite(file2, buffer,1)
- end
- end
- end;
- WriteDirectoryToDisk(file2);
- close(file2); close(library);
- erase(library); rename(file2,LibName);
- reset(library);
- end;
-
- procedure HelpCmdLine;
- begin
- clrscr;
- writeln(^M^J,'You must enter a file name:');
- writeln(^M^J,'LU <filename>[.LBR]');
- writeln(^M^J,'NOTE: the .LBR suffix is optional.');
- end;
-
- procedure Help;
- begin
- clrscr;
- writeln('Library Utility Commands:',^M^J);
- writeln('Add - add a new member, can''t be duplicate');
- writeln('Directory - gives the listing of this library''s directory');
- writeln('Extract - copy a member out to its own file');
- writeln('Kill - delete a member from the library');
- writeln('Undelete - reverses the effects of a delete');
- writeln('Reorganize- compresses blank space in library');
- writeln('eXit - terminate this program');
- writeln('Help - gives this screen');
- WaitKey;
- end;
-
- procedure Menu;
- var selection: char;
- begin
- OpenLibrary;
- repeat
- clrscr;
- gotoxy(30,2); write('Library Utility Menu');
- gotoxy(35,3); write('version ',ProgramVersion);
- gotoxy(40-length(LibName) DIV 2,5); write(LibName);
- gotoxy(10,07); write('D - directory');
- gotoxy(10,08); write('E - extract member');
- gotoxy(10,09); write('A - add member');
- gotoxy(10,10); write('K - delete member');
- gotoxy(10,11); write('U - undelete member');
- gotoxy(10,12); write('R - reorganize library');
- gotoxy(10,13); write('X - exit');
- gotoxy(10,14); write('? - help');
- gotoxy(20,20); write('choose one: ');
- repeat
- read(kbd,selection);
- selection:=upcase(selection);
- until (selection in ['A','D','E','K','R','U','X','?']);
- writeln(selection);
- case selection of
- 'A': Add;
- 'D': Directory;
- 'E': Extract;
- '?': Help;
- 'K': Delete;
- 'R': Reorganize;
- 'U': Undelete;
- end;
- until selection='X';
- if DirectoryChanged then WriteDirectoryToDisk(library);
- close(library);
- end;
-
- begin
- LibName:=Parse(CommandLine); {CommandLine}
- if LibName = '.LBR' then HelpCmdLine else Menu;
- end.