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