/* ** header.c - Routines used to access compressed file header information. ** ** written by DavidDi */ // Headers /////////// #ifndef LZA_DLL #include #include #include #include #include #endif #include "lz_common.h" #include "lz_buffers.h" #include "lz_header.h" /* ** int WriteHdr(PFH pFH, int doshDest); ** ** Write compressed file header to output file. ** ** Arguments: pFH - pointer to source header information structure ** doshDest - DOS file handle of open output file ** ** Returns: int - TRUE if successful. LZERROR_BADOUTHANDLE if ** unsuccessful. ** ** Globals: none ** ** header format: ** 8 bytes --> compressed file signature ** 1 byte --> algorithm label ** 1 byte --> extension char ** 4 bytes --> uncompressed file size (LSB to MSB) ** ** length = 14 bytes */ INT WriteHdr(PFH pFH, INT doshDest, PLZINFO pLZI) { INT i, j; DWORD ucbWritten; BYTE rgbyteHeaderBuf[HEADER_LEN]; // temporary storage for next header byte to write // Sanity check if (!pLZI) { return(LZERROR_GLOBLOCK); } // Copy the compressed file signature. for (i = 0; i < COMP_SIG_LEN; i++) rgbyteHeaderBuf[i] = pFH->rgbyteMagic[i]; // Copy the algorithm label and file name extension character. rgbyteHeaderBuf[i++] = pFH->byteAlgorithm; rgbyteHeaderBuf[i++] = pFH->byteExtensionChar; // Copy input file size (long ==> 4 bytes), // LSB first to MSB last. for (j = 0; j < 4; j++) rgbyteHeaderBuf[i++] = (BYTE)((pFH->cbulUncompSize >> (8 * j)) & (DWORD)BYTE_MASK); // Write header to file. if ((ucbWritten = FWRITE(doshDest, rgbyteHeaderBuf, HEADER_LEN)) != HEADER_LEN) { #ifdef LZA_DLL if (ucbWritten == (DWORD)(-1)) #else if (_error != 0U) #endif // Bad DOS file handle. return(LZERROR_BADOUTHANDLE); else // Insufficient space on destination drive. return(LZERROR_WRITE); } // Keep track of bytes written. pLZI->cblOutSize += (LONG)ucbWritten; // Header written ok. return(TRUE); } /* ** int GetHdr(PFH pFH, int doshSource); ** ** Get compressed file header. ** ** Arguments: pFH - pointer to destination header information structure ** doshSource - DOS file handle of open input file ** ** Returns: int - TRUE if compressed file header read successfully. One ** the LZERROR_ codes if not. ** ** Globals: none */ INT GetHdr(PFH pFH, INT doshSource, LONG *pcblInSize) { DWORD ucbRead; BYTE rgbyteHeaderBuf[HEADER_LEN]; INT i, j; // Get input file length and move back to beginning of input file. if ((*pcblInSize = FSEEK(doshSource, 0L, SEEK_END)) < 0L || FSEEK(doshSource, 0L, SEEK_SET) != 0L) return(LZERROR_BADINHANDLE); if ((ucbRead = FREAD(doshSource, rgbyteHeaderBuf, HEADER_LEN)) != HEADER_LEN) { #ifdef LZA_DLL if (ucbRead == (DWORD)(-1)) #else if (_error != 0U) #endif // We were handed a bad input file handle. return((INT)LZERROR_BADINHANDLE); else // Input file shorter than compressed header size. return(LZERROR_READ); } // Put compressed file signature into rgbyteMagic[] of header info struct. for (i = 0; i < COMP_SIG_LEN; i++) pFH->rgbyteMagic[i] = rgbyteHeaderBuf[i]; // Get algorithm label and file name extension character. pFH->byteAlgorithm = rgbyteHeaderBuf[i++]; pFH->byteExtensionChar = rgbyteHeaderBuf[i++]; // Extract uncompressed file size, LSB --> MSB (4 bytes in long). pFH->cbulUncompSize = 0UL; for (j = 0; j < 4; j++) pFH->cbulUncompSize |= ((DWORD)(rgbyteHeaderBuf[i++]) << (8 * j)); // Stick compressed file size into header info struct. pFH->cbulCompSize = (DWORD)*pcblInSize; // File header read ok. return(TRUE); } /* ** BOOL IsCompressed(PFH pFHIn); ** ** See if a file is in compressed form by comparing its file signature with ** the expected compressed file signature. ** ** Arguments: pFHIn - pointer to header info struct to check ** ** Returns: BOOL - TRUE if file signature matches expected compressed file ** signature. FALSE if not. ** ** Globals: none */ BOOL IsCompressed(PFH pFHIn) { INT i; // storage for FHIn's compressed file signature (used to make it an sz) CHAR rgchBuf[COMP_SIG_LEN + 1]; // Copy file info struct's compressed file signature into rgchBuf[] to // make it an sz. for (i = 0; i < COMP_SIG_LEN; i++) rgchBuf[i] = pFHIn->rgbyteMagic[i]; rgchBuf[i] = '\0'; return((STRCMP(rgchBuf, COMP_SIG) == 0) ? TRUE : FALSE); } /* ** void MakeHeader(PFH pFHBlank, BYTE byteAlgorithm, ** BYTE byteExtensionChar); ** ** Arguments: pFHBlank - pointer to compressed file header struct ** that is to be filled in ** byteAlgorithm - algorithm label ** byteExtensionChar - uncompressed file name extension character ** ** Returns: void ** ** Globals: none ** ** Global cblInSize is used to fill in expanded file length field. ** Compressed file length field is set to 0 since it isn't written. ** */ VOID MakeHeader(PFH pFHBlank, BYTE byteAlgorithm, BYTE byteExtensionChar, PLZINFO pLZI) { INT i; // !!! Assumes pLZI parm is valid. No sanity check (should be done above in caller). // Fill in compressed file signature. for (i = 0; i < COMP_SIG_LEN; i++) pFHBlank->rgbyteMagic[i] = (BYTE)(*(COMP_SIG + i)); // Fill in algorithm and extesion character. pFHBlank->byteAlgorithm = byteAlgorithm; pFHBlank->byteExtensionChar = byteExtensionChar; // Fill in file sizes. (cbulCompSize not written to compressed file // header, so just set it to 0UL.) pFHBlank->cbulUncompSize = (DWORD)pLZI->cblInSize; pFHBlank->cbulCompSize = 0UL; }