Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/paxlib/lha/lha.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 lha format
24
*/
25
26
#include <paxlib.h>
27
#include <codex.h>
28
#include <ctype.h>
29
#include <swap.h>
30
#include <tm.h>
31
32
#define SUM "sum-crc-0xa001"
33
34
typedef struct Ar_s
35
{
36
Codexdisc_t codexdisc;
37
Pax_t* pax;
38
Paxarchive_t* ap;
39
char method[64];
40
unsigned short checksum;
41
42
unsigned char check;
43
unsigned char system;
44
unsigned char minor_version;
45
} Ar_t;
46
47
static int
48
lha_method(register unsigned char* s)
49
{
50
return (s[0] == '-' && isalnum(s[1]) && isalnum(s[2]) && isalnum(s[3]) && s[4] == '-') ? 0 : -1;
51
}
52
53
static int
54
lha_done(Pax_t* pax, register Paxarchive_t* ap)
55
{
56
register Ar_t* ar = (Ar_t*)ap->data;
57
58
if (!ar)
59
return -1;
60
free(ar);
61
ap->data = 0;
62
return 0;
63
}
64
65
static int
66
lha_getprologue(Pax_t* pax, Paxformat_t* fp, register Paxarchive_t* ap, Paxfile_t* f, unsigned char* buf, size_t size)
67
{
68
register Ar_t* ar;
69
int n;
70
int h;
71
int i;
72
73
if (size < 1 || size < (n = buf[0] + 2) || n < 22 || lha_method(buf+2))
74
return 0;
75
for (h = 0, i = 2; i < n; i++)
76
h += buf[i];
77
if ((h & 0xff) != buf[1])
78
return 0;
79
if (!(ar = newof(0, Ar_t, 1, 0)))
80
{
81
if (ar)
82
free(ar);
83
return paxnospace(pax);
84
}
85
ar->pax = pax;
86
ar->ap = ap;
87
codexinit(&ar->codexdisc, pax->errorf);
88
ar->method[0] = 'l';
89
ar->method[1] = 'z';
90
ar->method[2] = 'h';
91
ar->method[3] = '-';
92
ap->data = ar;
93
return 1;
94
}
95
96
static int
97
lha_getheader(Pax_t* pax, register Paxarchive_t* ap, register Paxfile_t* f)
98
{
99
register Ar_t* ar = (Ar_t*)ap->data;
100
register unsigned char* hdr;
101
char* s;
102
Tm_t tm;
103
unsigned long dostime;
104
long n;
105
int h;
106
int i;
107
int mode;
108
unsigned char ss[2];
109
110
if (paxread(pax, ap, ss, sizeof(ss), 0, 0) != sizeof(ss) || !(hdr = paxget(pax, ap, n = ss[0], NiL)) || lha_method(hdr))
111
return 0;
112
for (h = 0, i = 0; i < n; i++)
113
h += hdr[i];
114
if ((h & 0xff) != ss[1])
115
return paxcorrupt(pax, ap, NiL, "header checksum error");
116
f->st->st_size = swapget(3, hdr+5, 4);
117
f->uncompressed = swapget(3, hdr+9, 4);
118
ar->method[4] = hdr[1];
119
ar->method[5] = hdr[2];
120
ar->method[6] = hdr[3];
121
dostime = swapget(3, hdr+13, 4);
122
mode = swapget(3, hdr+17, 2);
123
i = hdr[19];
124
f->name = paxstash(pax, &ap->stash.head, NiL, i + 1);
125
memcpy(f->name, hdr+20, i);
126
f->name[i] = 0;
127
hdr += i + 20;
128
n -= i;
129
if (n >= 24)
130
{
131
ar->checksum = swapget(3, hdr+0, 2);
132
ar->system = hdr[2];
133
ar->minor_version = hdr[3];
134
ar->check = 1;
135
hdr += 4;
136
}
137
else if (n == 22)
138
{
139
ar->checksum = swapget(3, hdr+0, 2);
140
ar->system = 0;
141
ar->check = 1;
142
hdr += 2;
143
}
144
else if (n == 20)
145
{
146
ar->system = 0;
147
ar->check = 0;
148
}
149
else
150
return paxcorrupt(pax, ap, NiL, NiL);
151
n = 7;
152
n += sfsprintf(ar->method + n, sizeof(ar->method) - n, "+SIZE=%I*u", sizeof(f->uncompressed), f->uncompressed);
153
if (ar->check)
154
n += sfsprintf(ar->method + n, sizeof(ar->method) - n, "|%s", SUM);
155
if (ar->system == 'U')
156
{
157
f->st->st_mtime = swapget(3, hdr+0, 4);
158
f->st->st_mode = swapget(3, hdr+4, 2) & pax->modemask;
159
f->st->st_uid = swapget(3, hdr+6, 2);
160
f->st->st_gid = swapget(3, hdr+8, 2);
161
}
162
else
163
{
164
memset(&tm, 0, sizeof(tm));
165
tm.tm_year = ((dostime >> (16+9)) & 0x7f) + 80;
166
tm.tm_mon = ((dostime >> (16+5)) & 0x0f) - 1;
167
tm.tm_mday = ((dostime >> (16+0)) & 0x1f);
168
tm.tm_hour = ((dostime >> 11) & 0x1f);
169
tm.tm_min = ((dostime >> 5) & 0x3f);
170
tm.tm_sec = ((dostime ) & 0x1f) * 2;
171
f->st->st_mtime = tmtime(&tm, TM_LOCALZONE);
172
if (mode & 0x10)
173
mode = X_IFDIR|X_IRUSR|X_IWUSR|X_IXUSR|X_IRGRP|X_IWGRP|X_IXGRP|X_IROTH|X_IWOTH|X_IXOTH;
174
else if (mode & 0x01)
175
mode = X_IFREG|X_IRUSR|X_IRGRP|X_IROTH;
176
else
177
{
178
mode = X_IFREG|X_IRUSR|X_IWUSR|X_IRGRP|X_IWGRP|X_IROTH|X_IWOTH;
179
if ((s = strrchr(f->name, '.')) && (s[1]=='e' || s[1]=='E') && (s[1]=='x' || s[1]=='X') && (s[1]=='e' || s[1]=='E'))
180
mode |= X_IXUSR|X_IXGRP|X_IXOTH;
181
}
182
f->st->st_mode = mode & pax->modemask;
183
}
184
f->linkpath = 0;
185
f->st->st_dev = 0;
186
f->st->st_ino = 0;
187
f->st->st_uid = pax->uid;
188
f->st->st_gid = pax->gid;
189
f->st->st_nlink = 1;
190
IDEVICE(f->st, 0);
191
f->st->st_ctime = f->st->st_atime = f->st->st_mtime;
192
return 1;
193
}
194
195
static int
196
lha_getdata(Pax_t* pax, register Paxarchive_t* ap, register Paxfile_t* f, int fd)
197
{
198
register Ar_t* ar = (Ar_t*)ap->data;
199
Sfio_t* sp;
200
off_t pos;
201
ssize_t n;
202
int r;
203
int pop;
204
Codexdata_t sum;
205
206
if (!(n = f->st->st_size))
207
return 1;
208
pos = paxseek(pax, ap, 0, SEEK_CUR, 0) + f->st->st_size;
209
r = -1;
210
if (fd < 0)
211
r = 1;
212
else if (sp = paxpart(pax, ap, f->st->st_size))
213
{
214
if ((pop = codex(sp, NiL, ar->method, 0, &ar->codexdisc, NiL)) < 0)
215
(*pax->errorf)(NiL, pax, 2, "%s: %s: cannot decode method %s", ap->name, f->name, ar->method);
216
else
217
{
218
for (;;)
219
{
220
if ((n = sfread(sp, pax->buf, sizeof(pax->buf))) < 0)
221
{
222
(*pax->errorf)(NiL, pax, 2, "%s: %s: unexpected EOF", ap->name, f->name);
223
break;
224
}
225
else if (n == 0)
226
{
227
if (ar->check)
228
{
229
if (codexdata(sp, &sum) <= 0)
230
(*pax->errorf)(NiL, pax, 2, "%s: %s: checksum discipline error", ap->name, f->name);
231
else if (!paxchecksum(pax, ap, f, ar->checksum, sum.num & 0xffff))
232
r = 1;
233
}
234
break;
235
}
236
if (paxdata(pax, ap, f, fd, pax->buf, n))
237
break;
238
}
239
codexpop(sp, NiL, pop);
240
}
241
}
242
if (paxseek(pax, ap, pos, SEEK_SET, 0) != pos)
243
{
244
(*pax->errorf)(NiL, pax, 2, "%s: %s: cannot seek past %s format data", ap->name, f->name, ap->format->name);
245
r = -1;
246
}
247
return r;
248
}
249
250
Paxformat_t pax_lha_format =
251
{
252
"lha",
253
"lharc",
254
"lha archive",
255
0,
256
PAX_ARCHIVE|PAX_DOS|PAX_NOHARDLINKS|PAX_IN,
257
PAX_DEFBUFFER,
258
PAX_DEFBLOCKS,
259
0,
260
PAXNEXT(lha),
261
0,
262
lha_done,
263
lha_getprologue,
264
lha_getheader,
265
lha_getdata,
266
};
267
268
PAXLIB(lha)
269
270