#include #include /* -------------------------------------------------------------------- Module: WHICHARC.C Subject: tries to determine the archiver used to compress files Author: Heinz Ozwirk & David Gersic modified for SNIPPETS by Bob Stout Status: public domain Started: 28.09.1991 13:35:57 Modified: 13.10.1991 14:15:57 Modified: 5 January, 1992 11:50am by David Gersic Added return codes for self extracting archive files. Modified: 16 January, 1992, 4:15pm by David Gersic Added Pak and ARC ver. 6 with information from Richard Vanhouten @1:272/38. I'm not sure that this code works perfectly for those formats, as his message seems to indicate that the entire archive has to be scanned for headers to check before the type can be perfectly determined. It seems to work for test archives produced here, but may not work for all archives. -------------------------------------------------------------------- Prototype: int WhichArc(char *pName) pName address of full path name of file to examine Result -1: file not found UNKNOWN: unknown packer ARC: ARC or PKARC ARJ: ARJ LHA: LHARC or LHA ZIP: PKZIP ZOO: Zoo PAK: Pak ARC7: ARC later than ver. 6.02 SFXARC: Self Extracting PKARC SFXARJ: Self Extracting ARJ SFXLHARC:Self Extracting LHARC SFXLHA: Self Extracting LHA SFXZIP: Self Extracting ZIP SFXPAK: Self Extracting Pak SFXARC6: Self Extracting ARC later than ver. 6.02 EXE: MS DOS executable of unknown type LHARC/LHA No archive header. WhichArc examines the checksum of the first file header. If the checksum is valid and if the string -lh?- is found, LHA or LHARC is assumed. ARJ If a file starts with 0x60, 0xEA, ARJ is assumed. ZIP If the file begins with "PK", PKZIP is assumed. ZOO Zoo'ed archives always start with "ZOO x.xx Archive". WhichArc only looks for "ZOO". ARC No header. Files starting with 0x1A are assumed to be ARCed. PAK Similar to ARC files, but if the second byte of the header is 0x0a or 0x0b, it was created by Pak. ARC7 Similar to ARC, but if the second byte of the header is 0x14 or higher, it was created by an Arc version later than 6.02. SFX* All of the SFX files start with a small decompressor. Seek past the decompressor and repeat the above checks. -------------------------------------------------------------------- */ typedef unsigned char BYTE; enum ArcType { ArcERR=-1, UNKNOWN, ARC, ZOO, ARJ, LHARC, LHA, ZIP, PAK, ARC7, SFXARC, SFXARJ, SFXLHARC, SFXLHA, SFXZIP, SFXARC7, SFXPAK, EXE }; enum ArcType WhichArc(char *pName) { FILE *fp; BYTE header[128]; int c, i, n; enum ArcType retval = ArcERR; memset(header, 0, sizeof(header)); fp = fopen(pName, "rb"); if (fp == NULL) goto EXIT; /* error opening file */ n = fread(header, sizeof(BYTE), sizeof(header) - sizeof(BYTE), fp); if (n <= 0) /* error reading from file */ goto EXIT; if (n >= 7 && n >= header[0] + 2) { for (c = 0, i = header[0]; i--; c += (header+2)[i]) ; if (((BYTE)(c & 0x00FF)) == header[1] && header[2] == '-' && header[3] == 'l' && header[4] == 'h' && header[6] == '-') { retval = (header[5] > '1') ? LHA : LHARC; goto EXIT; } } if (n >= 2) { if (header[0] == 0x60 && header[1] == 0xEA) { retval = ARJ; goto EXIT; } if (header[0] == 'P' && header[1] == 'K') { retval = ZIP; goto EXIT; } } if (n >= 3 && header[0] == 'Z' && header[1] == 'O' && header[2] == 'O') { retval = ZOO; goto EXIT; } if (n >= 25 && header[0] == 0x1A) { if (header[1]>0x14) retval = ARC7; else if (header[1]==0x0a || header[1]==0x0b) retval = PAK; else retval = ARC; goto EXIT; } if (0 == strncmp(header, "MZ", 2)) /* some sort of .EXE file */ { /* test for SFX ARJ file */ memset(header, 0, sizeof(header)); fseek(fp, 0x39ba, SEEK_SET); n = fread(header, sizeof(BYTE), sizeof(header) - sizeof(BYTE), fp); if (n > 1 && header[0] == 0x60 && header[1] == 0xea) { retval = SFXARJ; goto EXIT; } /* test for SFX LHARC file */ memset(header, 0, sizeof(header)); fseek(fp, 0x653, SEEK_SET); n = fread(header, sizeof(BYTE), sizeof(header) - sizeof(BYTE), fp); for (c = 0, i = header[0]; i--; c += (header+2)[i]) ; if (n >= 7 && n >= header[0] + 2) { if (((BYTE)(c & 0x00FF)) == header[1] && header[2] == '-' && header[3] == 'l' && header[4] == 'h' && header[6] == '-') { retval = SFXLHARC; goto EXIT; } } /* test for SFX LHA file */ memset(header, 0, sizeof(header)); fseek(fp, 0x799, SEEK_SET); n = fread(header, sizeof(BYTE), sizeof(header) - sizeof(BYTE), fp); for (c = 0, i = header[0]; i--; c += (header+2)[i]) ; if (n >= 7 && n >= header[0] + 2) { if (((BYTE)(c & 0x00FF)) == header[1] && header[2] == '-' && header[3] == 'l' && header[4] == 'h' && header[6] == '-') { retval = SFXLHA; goto EXIT; } } /* test for SFX ZIP file */ memset(header, 0, sizeof(header)); fseek(fp, 0x31f0, SEEK_SET); n = fread(header, sizeof(BYTE), sizeof(header) - sizeof(BYTE), fp); if (n > 1 && header[0] == 'P' && header[1] == 'K') { retval = SFXZIP; goto EXIT; } /* test for SFX PKARC file */ memset(header, 0, sizeof(header)); fseek(fp,0x261e,SEEK_SET); n = fread(header, sizeof(BYTE), sizeof(header) - sizeof(BYTE), fp); if (n > 1 && header[0] == 0x1a) { if (header[1]>0x14) retval = SFXARC7; else if (header[1]==0x0a || header[1]==0x0b) retval = SFXPAK; else retval = SFXARC; } else retval = EXE; } retval = UNKNOWN; EXIT: fclose(fp); return retval; } #ifdef TEST int main(int argc,char *argv[]) { char *arc_types[]={"UNKNOWN", "ARC", "ZOO", "ARJ", "LHARC", "LHA", "ZIP", "PAK", "PAK", "ARC7", "SFXARC", "SFXARJ", "SFXLHARC", "SFXLHA", "SFXZIP", "SFXARC7", "SFXPAK", "EXE"}; while (--argc) { enum ArcType which; if (ArcERR == (which = WhichArc(*++argv))) printf("File error accessing %s\n", *argv); else printf("%s archive type is %s\n", *argv, arc_types[which]); } return(0); } #endif