home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
catalog
/
pibcat17.arc
/
PIBCATD.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1989-03-31
|
17KB
|
389 lines
(*----------------------------------------------------------------------*)
(* Display_DWC_Contents --- Display contents of DWC file *)
(*----------------------------------------------------------------------*)
PROCEDURE Display_DWC_Contents( DWCFileName : AnyStr );
(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Display_DWC_Contents *)
(* *)
(* Purpose: Displays contents of a DWC file *)
(* *)
(* Calling sequence: *)
(* *)
(* Display_DWC_Contents( DWCFileName : AnyStr ); *)
(* *)
(* DWCFileName --- name of DWC file whose contents are to be *)
(* listed. *)
(* *)
(* Calls: *)
(* *)
(* Aside from internal subroutines, these routines are required: *)
(* *)
(* Get_Unix_Date --- convert Unix date to string *)
(* Open_File --- open a file *)
(* Close_File --- close a file *)
(* Entry_Matches --- Perform wildcard match *)
(* Display_Page_Titles *)
(* --- Display titles at top of page *)
(* DUPL --- Duplicate a character into a string *)
(* *)
(*----------------------------------------------------------------------*)
(*----------------------------------------------------------------------*)
(* Map of DWC file entry header *)
(*----------------------------------------------------------------------*)
CONST
Max_Entries = 1800 (* Maximum # of files in DWC file *);
TYPE
FNameType = ARRAY[1..13] OF CHAR;
ID_Type = ARRAY[1..3 ] OF CHAR;
(* Header for entire DWC file *)
DWC_Header_Type = RECORD
Size : WORD (* Size of archive structure, future expansion *);
Ent_SZ : BYTE (* Size of directory entry, future expansion *);
Header : FNameType (* Name of Header file to print on listings *);
Time : LONGINT (* Time stamp of last modification to archive *);
Entries : LONGINT (* Number of entries in archive *);
ID_3 : ID_Type (* The string "DWC" to identify archive *);
END;
(* Individual file entry *)
DWC_Entry_Type = RECORD
Filename : FNameType (* File and extension *);
Size : LONGINT (* Original size *);
Time : LONGINT (* Packed date and time *);
New_Size : LONGINT (* Compressed size *);
FPos : LONGINT (* Position in DWC file *);
Method : BYTE (* Compression method *);
SZ_C : BYTE (* Size of comment *);
SZ_D : BYTE (* Size of dir name on add *);
CRC : WORD (* Cyclic Redundancy Check *);
END;
(* Entire DWC directory *)
DWC_Dir_Type = ARRAY[1..Max_Entries] OF DWC_Entry_Type;
DWC_Dir_Ptr = ^DWC_Dir_Type;
(* STRUCTURED *) CONST
DWC_ID : ID_Type = 'DWC';
VAR
DWCFile : FILE (* DWC file to be read *);
DWC_Entry : DWC_Entry_Type (* Entry for one file in DWC lib *);
DWC_Header : DWC_Header_Type (* Main header for DWC file *);
DWC_Pos : LONGINT (* Current byte offset in DWC file *);
Bytes_Read : INTEGER (* # bytes read from DWC file file *);
Ierr : INTEGER (* Error flag *);
Entry_To_Get : INTEGER (* Current entry being worked on *);
Dir_In_Memory : BOOLEAN (* TRUE if entire dir fits in RAM *);
Dir_Ptr : DWC_Dir_Ptr (* Points to RAM-resident DWC dir *);
Dir_Size : WORD (* Size in bytes of directory *);
Long_Name : AnyStr (* Long file name *);
(*----------------------------------------------------------------------*)
(* Get_DWC_Header --- Get initial header entry in DWC file *)
(*----------------------------------------------------------------------*)
FUNCTION Get_DWC_Header( VAR Error : INTEGER ) : BOOLEAN;
(*----------------------------------------------------------------------*)
(* *)
(* Function: Get_DWC_Header *)
(* *)
(* Purpose: Gets initial DWC header *)
(* *)
(* Calling sequence: *)
(* *)
(* OK := Get_DWC_Header( VAR Error : INTEGER ) : BOOLEAN; *)
(* *)
(* Error --- Error flag *)
(* OK --- TRUE if header successfully found, else FALSE *)
(* *)
(*----------------------------------------------------------------------*)
CONST
BufSize = 256;
VAR
I : INTEGER;
J : INTEGER;
Buf : ARRAY[1..BufSize] OF CHAR;
L : LONGINT;
ID_Found : BOOLEAN;
ID_Ptr : ^ID_Type;
BEGIN (* Get_DWC_Header *)
(* Assume no error to start *)
Error := 0;
(* Assume no space to hold entire *)
(* directory in memory. *)
Dir_In_Memory := FALSE;
Dir_Ptr := NIL;
(* Try to find ID = 'DWC' near end *)
(* of file. We will look up to 10 *)
(* 256 byte blocks away from end *)
(* for this info. *)
L := FileSize( DWCFile );
I := 1;
ID_Found := FALSE;
REPEAT
(* Position to next potential block *)
DWC_Pos := L - ( I * BufSize - PRED( I ) * 5 );
IF ( DWC_Pos < 0 ) THEN
DWC_Pos := 0;
SEEK( DWCFile , DWC_Pos );
(* Read in a block of information *)
IF ( IOResult = 0 ) THEN
BEGIN
BlockRead( DWCFile, Buf, BufSize, Bytes_Read );
IF ( IOResult = 0 ) THEN
BEGIN
(* See if we can find "DWC" here *)
J := Bytes_Read - 2;
WHILE ( ( J > 0 ) AND ( NOT ID_Found ) ) DO
BEGIN
ID_Ptr := @Buf[ J ];
IF ( ID_Ptr^ = DWC_ID ) THEN
ID_Found := TRUE
ELSE
DEC( J );
END;
(* In case we need to try next block *)
INC( I );
END
ELSE
Error := Format_Error;
END
ELSE
Error := Format_Error;
UNTIL ( ( I > 10 ) OR ID_Found OR ( Error <> 0 ) );
(* If we didn't find DWC, quit. *)
IF ( NOT ID_Found ) THEN
Error := Format_Error
ELSE
BEGIN (* We found DWC. *)
(* True end of DWC file (we hope). *)
DWC_Pos := DWC_Pos + J + 2;
SEEK( DWCFile , DWC_Pos - SIZEOF( DWC_Header ) );
BlockRead( DWCFile, DWC_Header, SIZEOF( DWC_Header ), Bytes_Read );
(* Check # of entries for reasonableness *)
IF ( ( DWC_Header.Entries < 0 ) OR ( DWC_Header.Entries > Max_Entries ) ) THEN
Error := Format_Error
ELSE
BEGIN
(* # entries looked OK. Pick up offset *)
(* of first directory entry. *)
WITH DWC_Header DO
BEGIN
Dir_Size := Entries * Ent_SZ;
DWC_Pos := DWC_Pos - ( Dir_Size + Size );
END;
SEEK( DWCFile , DWC_Pos );
IF ( IOResult <> 0 ) THEN
Error := Format_Error;
(* See if we can read entire directory *)
(* into memory. If so, do that now. *)
IF ( MaxAvail > Dir_Size ) THEN
BEGIN
GETMEM( Dir_Ptr , Dir_Size );
IF ( Dir_Ptr <> NIL ) THEN
BEGIN
Dir_In_Memory := TRUE;
BlockRead( DWCFile, Dir_Ptr^, Dir_Size, Bytes_Read );
IF ( ( IOResult <> 0 ) OR
( Bytes_Read < Dir_Size ) ) THEN
Error := Format_Error;
END;
END;
END;
END;
(* Report success/failure to calling *)
(* routine. *)
Get_DWC_Header := ( Error = 0 );
END (* Get_DWC_Header *);
(*----------------------------------------------------------------------*)
(* Get_Next_DWC_Entry --- Get next header entry in DWC file *)
(*----------------------------------------------------------------------*)
FUNCTION Get_Next_DWC_Entry( VAR DWC_Entry : DWC_Entry_Type;
Entry_No : INTEGER;
VAR Error : INTEGER ) : BOOLEAN;
(*----------------------------------------------------------------------*)
(* *)
(* Function: Get_Next_DWC_Entry *)
(* *)
(* Purpose: Gets header information for next file in DWC file *)
(* *)
(* Calling sequence: *)
(* *)
(* OK := Get_Next_DWC_Entry( VAR DWC_Entry : DWC_Entry_Type; *)
(* Entry_No : INTEGER; *)
(* VAR Error : INTEGER ) : BOOLEAN; *)
(* *)
(* DWC_Entry --- Header data for next file in DWC file *)
(* Error --- Error flag *)
(* Entry_No --- Entry number to get (if resident dir) *)
(* OK --- TRUE if header successfully found, else FALSE *)
(* *)
(*----------------------------------------------------------------------*)
BEGIN (* Get_Next_DWC_Entry *)
(* Assume no error to start *)
Error := 0;
(* Read in the file header entry. *)
IF Dir_In_Memory THEN
DWC_Entry := Dir_Ptr^[ Entry_No ]
ELSE
BEGIN
BlockRead( DWCFile, DWC_Entry, SIZEOF( DWC_Entry ), Bytes_Read );
(* If wrong size read, or header marker *)
(* byte is incorrect, report DWC file *)
(* format error. *)
IF ( ( IOResult <> 0 ) OR ( Bytes_Read < SIZEOF( DWC_Entry ) ) ) THEN
Error := Format_Error;
END;
(* Report success/failure to calling *)
(* routine. *)
Get_Next_DWC_Entry := ( Error = 0 );
END (* Get_Next_DWC_Entry *);
(*----------------------------------------------------------------------*)
(* Display_DWC_Entry --- Display DWC file file entry info *)
(*----------------------------------------------------------------------*)
PROCEDURE Display_DWC_Entry( DWC_Entry : DWC_Entry_Type );
VAR
FName : AnyStr;
TimeDate : LONGINT;
DTRec : DateTime;
BEGIN (* Display_DWC_Entry *)
WITH DWC_Entry DO
BEGIN
(* Pick up file name *)
FName := COPY( FileName, 1, PRED( POS( #0 , FileName ) ) );
(* See if this file matches the *)
(* entry spec wildcard. Exit if *)
(* not. *)
IF Use_Entry_Spec THEN
IF ( NOT Entry_Matches( FName ) ) THEN
EXIT;
(* Get date and time of creation *)
Get_Unix_Style_Date( Time, DTRec.Year, DTRec.Month, DTRec.Day,
DTRec.Hour, DTRec.Min, DTRec.Sec );
PackTime( DTRec , TimeDate );
Long_Name := '';
(* Display info about this entry *)
Display_One_Entry( FName, Size, TimeDate, DWCFileName,
Current_Subdirectory, Long_Name );
END;
END (* Display_DWC_Entry *);
(*----------------------------------------------------------------------*)
BEGIN (* Display_DWC_Contents *)
(* Open DWC file and initialize *)
(* contents display. *)
IF Start_Contents_Listing( ' DWC file: ',
Current_Subdirectory + DWCFileName, DWCFile,
DWC_Pos, Ierr ) THEN
BEGIN
(* Loop over entries in DWC file *)
(* if DWC file opened OK. *)
IF Get_DWC_Header( Ierr ) THEN
BEGIN
(* Entry to get *)
Entry_To_Get := 1;
(* Loop over entries *)
WHILE ( ( Entry_To_Get <= DWC_Header.Entries ) AND
( Get_Next_DWC_Entry( DWC_Entry , Entry_To_Get , Ierr ) ) ) DO
BEGIN
Display_DWC_Entry( DWC_Entry );
INC( Entry_To_Get );
END;
END
ELSE
IF ( NOT Do_Condensed_Listing ) THEN
WRITELN( Output_File , 'Failed to get DWC header' )
ELSE
WRITELN( Status_File , 'Failed to get DWC header for ', DWCFileName );
(* Dispose of RAM-resident directory *)
IF ( Dir_Ptr <> NIL ) THEN
FREEMEM( Dir_Ptr , Dir_Size );
(* Close DWC file *)
End_Contents_Listing( DWCFile );
END;
END (* Display_DWC_Contents *);