1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
|
#include <stdio.h>
#include <string.h>
/* --------------------------------------------------------------------
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
|