Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/paxlib/zoo/zoo.c
1811 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2003-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
/*
23
* pax zoo format
24
*
25
* header layout snarfed from the public domain unzoo.c
26
*/
27
28
#include <paxlib.h>
29
#include <codex.h>
30
#include <sum.h>
31
#include <swap.h>
32
#include <tm.h>
33
34
#define MAGIC 0xfdc4a7dc
35
#define SUM "sum-crc-0xa001"
36
37
typedef struct Ar_s
38
{
39
Codexdisc_t codexdisc;
40
Pax_t* pax;
41
Paxarchive_t* ap;
42
char method[64];
43
unsigned int index;
44
unsigned long checksum;
45
46
unsigned long head; /* next member header offset */
47
unsigned long data; /* current member data offset */
48
unsigned char majver; /* major version */
49
unsigned char minver; /* minor version */
50
} Ar_t;
51
52
static int
53
zoo_done(Pax_t* pax, register Paxarchive_t* ap)
54
{
55
register Ar_t* ar = (Ar_t*)ap->data;
56
57
if (!ar)
58
return -1;
59
free(ar);
60
ap->data = 0;
61
return 0;
62
}
63
64
static int
65
zoo_getprologue(Pax_t* pax, Paxformat_t* fp, register Paxarchive_t* ap, Paxfile_t* f, unsigned char* buf, size_t size)
66
{
67
register Ar_t* ar;
68
69
if (size < 34 || swapget(3, buf + 20, 4) != MAGIC)
70
return 0;
71
if (!(ar = newof(0, Ar_t, 1, 0)))
72
{
73
if (ar)
74
free(ar);
75
return paxnospace(pax);
76
}
77
ar->pax = pax;
78
ar->ap = ap;
79
ar->head = swapget(3, buf + 24, 4);
80
ar->majver = buf[32];
81
ar->minver = buf[33];
82
ap->data = ar;
83
if (ar->head > 34 && size < 42)
84
{
85
zoo_done(pax, ap);
86
return paxcorrupt(pax, ap, NiL, "unexpected EOF");
87
}
88
codexinit(&ar->codexdisc, pax->errorf);
89
return 1;
90
}
91
92
static int
93
zoo_getheader(Pax_t* pax, register Paxarchive_t* ap, register Paxfile_t* f)
94
{
95
register Ar_t* ar = (Ar_t*)ap->data;
96
register unsigned char* buf;
97
register char* s;
98
Tm_t tm;
99
long n;
100
int i;
101
int mode;
102
int dosdate;
103
int dostime;
104
int doszone;
105
int ext;
106
int extdir;
107
int extname;
108
int system;
109
char name[14];
110
111
for (;;)
112
{
113
if (paxseek(pax, ap, ar->head, SEEK_SET, 1) != ar->head ||
114
!(buf = paxget(pax, ap, 38, NiL)) ||
115
swapget(3, buf, 4) != MAGIC)
116
break;
117
if (!(ar->head = swapget(3, buf+6, 4)))
118
return 0;
119
if (buf[30])
120
continue;
121
ar->data = swapget(3, buf+10, 4);
122
dosdate = swapget(3, buf+14, 2);
123
dostime = swapget(3, buf+16, 2);
124
ar->checksum = swapget(3, buf+18, 2);
125
f->uncompressed = swapget(3, buf+20, 4);
126
f->st->st_size = swapget(3, buf+24, 4);
127
ar->majver = buf[28];
128
ar->minver = buf[29];
129
switch (ar->index = buf[5])
130
{
131
case 0:
132
sfsprintf(ar->method, sizeof(ar->method), "copy|%s", SUM);
133
break;
134
case 1:
135
sfsprintf(ar->method, sizeof(ar->method), "lzd+SIZE=%I*u|%s", sizeof(f->uncompressed), f->uncompressed, SUM);
136
s = "lzd";
137
break;
138
case 2:
139
sfsprintf(ar->method, sizeof(ar->method), "lzh-8k-s1+SIZE=%I*u|%s", sizeof(f->uncompressed), f->uncompressed, SUM);
140
break;
141
default:
142
*ar->method = 0;
143
break;
144
}
145
if (paxread(pax, ap, name, sizeof(name) - 1, 0, 1) != (sizeof(name) - 1))
146
break;
147
name[sizeof(name) - 1] = 0;
148
if (buf[4] == 2)
149
{
150
if (!(buf = paxget(pax, ap, 5, NiL)))
151
break;
152
ext = swapget(3, buf+0, 2);
153
doszone = buf[2];
154
}
155
else
156
{
157
ext = 0;
158
doszone = 127;
159
}
160
if (ext > 0)
161
{
162
if (!(buf = paxget(pax, ap, 1, NiL)))
163
break;
164
extname = buf[0];
165
}
166
else
167
extname = 0;
168
if (ext > 1)
169
{
170
if (!(buf = paxget(pax, ap, 1, NiL)))
171
break;
172
extdir = buf[0];
173
}
174
else
175
extdir = 0;
176
if (n = extdir + extname)
177
{
178
if (!extname)
179
n += (i = strlen(name));
180
f->name = paxstash(pax, &ap->stash.head, NiL, n + 1);
181
if (!extname)
182
{
183
memcpy(f->name + extdir, name, i);
184
f->name[extdir + i] = 0;
185
}
186
else if (paxread(pax, ap, f->name + extdir, extname, 0, 1) != extname)
187
break;
188
else
189
f->name[extdir + extname + 1] = 0;
190
if (extdir)
191
{
192
if (paxread(pax, ap, f->name, extdir, 0, 1) != extdir)
193
break;
194
f->name[extdir - 1] = '/';
195
}
196
}
197
else
198
f->name = paxstash(pax, &ap->stash.head, name, 0);
199
if (ext > n+2)
200
{
201
if (!(buf = paxget(pax, ap, 2, NiL)))
202
break;
203
system = swapget(3, buf, 2);
204
}
205
else
206
system = 0;
207
if (ext > n+4)
208
{
209
if (!(buf = paxget(pax, ap, 3, NiL)))
210
break;
211
mode = (buf[2] << 16) | (buf[1] << 8) | buf[0];
212
}
213
else
214
mode = 0;
215
if (ext > n+7 && !(buf = paxget(pax, ap, 3, NiL)))
216
break;
217
f->linkpath = 0;
218
f->st->st_dev = 0;
219
f->st->st_ino = 0;
220
if (system == 0 || system == 2)
221
{
222
if (mode & 0x10)
223
mode = X_IFDIR|X_IRUSR|X_IWUSR|X_IXUSR|X_IRGRP|X_IWGRP|X_IXGRP|X_IROTH|X_IWOTH|X_IXOTH;
224
else if (mode & 0x01)
225
mode = X_IFREG|X_IRUSR|X_IRGRP|X_IROTH;
226
else
227
{
228
mode = X_IFREG|X_IRUSR|X_IWUSR|X_IRGRP|X_IWGRP|X_IROTH|X_IWOTH;
229
if ((s = strrchr(f->name, '.')) && (s[1]=='e' || s[1]=='E') && (s[1]=='x' || s[1]=='X') && (s[1]=='e' || s[1]=='E'))
230
mode |= X_IXUSR|X_IXGRP|X_IXOTH;
231
}
232
}
233
f->st->st_mode = mode & pax->modemask;
234
f->st->st_uid = pax->uid;
235
f->st->st_gid = pax->gid;
236
f->st->st_nlink = 1;
237
IDEVICE(f->st, 0);
238
memset(&tm, 0, sizeof(tm));
239
tm.tm_year = ((dosdate >> 9) & 0x7f) + 80;
240
tm.tm_mon = ((dosdate >> 5) & 0x0f) - 1;
241
tm.tm_mday = ((dosdate ) & 0x1f);
242
tm.tm_hour = ((dostime >> 11) & 0x1f);
243
tm.tm_min = ((dostime >> 5) & 0x3f);
244
tm.tm_sec = ((dostime ) & 0x1f) * 2;
245
if (doszone < 127)
246
tm.tm_sec += 15 * 60 * doszone;
247
else if (doszone > 127)
248
tm.tm_sec += 15 * 60 * (doszone - 256);
249
f->st->st_mtime = f->st->st_ctime = f->st->st_atime = tmtime(&tm, TM_LOCALZONE);
250
return 1;
251
}
252
return paxcorrupt(pax, ap, f, NiL);
253
}
254
255
static int
256
zoo_getdata(Pax_t* pax, register Paxarchive_t* ap, register Paxfile_t* f, int fd)
257
{
258
register Ar_t* ar = (Ar_t*)ap->data;
259
Sfio_t* sp;
260
ssize_t n;
261
int r;
262
int pop;
263
Codexdata_t sum;
264
265
if (fd < 0 || !f->st->st_size)
266
return 1;
267
if (paxseek(pax, ap, ar->data, SEEK_SET, 0) != ar->data)
268
return paxcorrupt(pax, ap, f, "cannot seek to data");
269
if (!*ar->method || ar->majver > 2 || ar->majver == 2 && ar->minver > 1)
270
{
271
(*pax->errorf)(NiL, pax, 2, "%s: %s: cannot extract %s method=%d version=%d.%d data", ap->name, f->name, ap->format->name, ar->index, ar->majver, ar->minver);
272
return -1;
273
}
274
r = -1;
275
if (sp = paxpart(pax, ap, f->st->st_size))
276
{
277
if ((pop = codex(sp, NiL, ar->method, 0, &ar->codexdisc, NiL)) < 0)
278
(*pax->errorf)(NiL, pax, 2, "%s: %s: cannot decode method %s", ap->name, f->name, ar->method);
279
else
280
{
281
for (;;)
282
{
283
if ((n = sfread(sp, pax->buf, sizeof(pax->buf))) < 0)
284
{
285
(*pax->errorf)(NiL, pax, 2, "%s: %s: unexpected EOF", ap->name, f->name);
286
break;
287
}
288
else if (n == 0)
289
{
290
if (codexdata(sp, &sum) <= 0)
291
(*pax->errorf)(NiL, pax, 2, "%s: %s: checksum discipline error", ap->name, f->name);
292
else if (!paxchecksum(pax, ap, f, ar->checksum, sum.num))
293
r = 1;
294
break;
295
}
296
if (paxdata(pax, ap, f, fd, pax->buf, n))
297
break;
298
}
299
codexpop(sp, NiL, pop);
300
}
301
}
302
return r;
303
}
304
305
Paxformat_t pax_zoo_format =
306
{
307
"zoo",
308
0,
309
"zoo archive",
310
0,
311
PAX_ARCHIVE|PAX_DOS|PAX_NOHARDLINKS|PAX_IN,
312
PAX_DEFBUFFER,
313
PAX_DEFBLOCKS,
314
0,
315
PAXNEXT(zoo),
316
0,
317
zoo_done,
318
zoo_getprologue,
319
zoo_getheader,
320
zoo_getdata,
321
};
322
323
PAXLIB(zoo)
324
325