Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/pax/pax-vdb.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1987-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 vdb format
24
*/
25
26
#include "format.h"
27
28
#include <vdb.h>
29
30
typedef struct Vdb_s
31
{
32
unsigned char delimiter; /* header delimiter */
33
unsigned char variant; /* variant header delimiters */
34
Sfio_t* directory; /* directory trailer stream */
35
struct stat st; /* member stat prototype */
36
struct
37
{
38
char* base; /* header buffer base */
39
char* next; /* next header */
40
} header;
41
} Vdb_t;
42
43
static int
44
vdb_getprologue(Pax_t* pax, Format_t* fp, register Archive_t* ap, File_t* f, unsigned char* buf, size_t size)
45
{
46
register Vdb_t* vdb = (Vdb_t*)ap->data;
47
char* s;
48
char* t;
49
struct stat st;
50
size_t i;
51
off_t n;
52
53
if (fstat(ap->io->fd, &st))
54
return 0;
55
s = state.tmp.buffer;
56
n = sizeof(VDB_MAGIC) + sizeof(state.volume) + 1;
57
if (size < n)
58
return 0;
59
s = (char*)buf;
60
if (s[0] != VDB_DELIMITER || !strneq(s + 1, VDB_MAGIC, sizeof(VDB_MAGIC) - 1) || s[sizeof(VDB_MAGIC)] != VDB_DELIMITER)
61
return 0;
62
if (s[sizeof(VDB_MAGIC) + 1] != '\n')
63
{
64
s[n] = 0;
65
if (t = strchr(s, '\n'))
66
*t = 0;
67
strncpy(state.volume, s + sizeof(VDB_MAGIC) + 1, sizeof(state.volume) - 2);
68
}
69
if (lseek(ap->io->fd, (off_t)(-(VDB_LENGTH + 1)), SEEK_END) <= 0)
70
return 0;
71
if (read(ap->io->fd, s, VDB_LENGTH + 1) != (VDB_LENGTH + 1))
72
return 0;
73
if (!vdb)
74
{
75
if (!(vdb = newof(0, Vdb_t, 1, 0)))
76
nospace();
77
ap->data = vdb;
78
}
79
ccmapstr(state.map.a2n, s, VDB_LENGTH + 1);
80
vdb->variant = *s++ != '\n';
81
if (!strneq(s, VDB_DIRECTORY, sizeof(VDB_DIRECTORY) - 1))
82
goto nope;
83
vdb->delimiter = s[VDB_OFFSET - 1];
84
n = strtol(s + VDB_OFFSET, NiL, 10) - sizeof(VDB_DIRECTORY);
85
i = lseek(ap->io->fd, (off_t)0, SEEK_CUR) - n - VDB_LENGTH - vdb->variant;
86
if (!(vdb->header.base = newof(0, char, i, 1)))
87
nospace();
88
if (lseek(ap->io->fd, n, SEEK_SET) != n)
89
goto nope;
90
if (read(ap->io->fd, vdb->header.base, i) != i)
91
goto nope;
92
ccmapstr(state.map.a2n, vdb->header.base, i);
93
*(vdb->header.base + i) = 0;
94
if (!strneq(vdb->header.base, VDB_DIRECTORY, sizeof(VDB_DIRECTORY) - 1))
95
goto nope;
96
if (!(vdb->header.next = strchr(vdb->header.base, '\n')))
97
goto nope;
98
vdb->header.next++;
99
vdb->st.st_mode = modex(vdb->st.st_mode);
100
return 1;
101
nope:
102
free(vdb);
103
return 0;
104
}
105
106
static int
107
vdb_done(Pax_t* pax, register Archive_t* ap)
108
{
109
register Vdb_t* vdb = (Vdb_t*)ap->data;
110
111
if (vdb)
112
{
113
if (vdb->directory)
114
sfclose(vdb->directory);
115
free(vdb);
116
ap->data = 0;
117
}
118
return 0;
119
}
120
121
static int
122
vdb_getheader(Pax_t* pax, Archive_t* ap, register File_t* f)
123
{
124
register Vdb_t* vdb = (Vdb_t*)ap->data;
125
char* s;
126
char* t;
127
off_t n;
128
129
t = vdb->header.next;
130
if (!(vdb->header.next = strchr(t, '\n')))
131
goto eof;
132
*vdb->header.next++ = 0;
133
message((-1, "VDB: next=`%s'", t));
134
if (vdb->variant)
135
vdb->delimiter = *t++;
136
f->name = t;
137
if (!(t = strchr(t, vdb->delimiter)))
138
goto eof;
139
*t++ = 0;
140
n = strtol(t, &t, 10);
141
if (*t++ != vdb->delimiter)
142
goto eof;
143
if (lseek(ap->io->fd, n, SEEK_SET) != n)
144
goto eof;
145
*f->st = vdb->st;
146
f->st->st_size = strtol(t, &t, 10);
147
if (*t++ == vdb->delimiter) do
148
{
149
if (s = strchr(t, vdb->delimiter))
150
*s++ = 0;
151
if (strneq(t, VDB_DATE, sizeof(VDB_DATE) - 1))
152
f->st->st_mtime = strtol(t + sizeof(VDB_DATE), NiL, 10);
153
else if (strneq(t, VDB_MODE, sizeof(VDB_MODE) - 1))
154
f->st->st_mode = (strtol(t + sizeof(VDB_MODE), NiL, 8) & X_IPERM) | X_IFREG;
155
} while (t = s);
156
f->st->st_dev = 0;
157
f->st->st_ino = 0;
158
f->st->st_nlink = 1;
159
IDEVICE(f->st, 0);
160
f->linktype = NOLINK;
161
f->linkpath = 0;
162
f->uidname = 0;
163
f->gidname = 0;
164
paxsync(pax, ap, 0);
165
return 1;
166
eof:
167
paxsync(pax, ap, 0);
168
ap->io->eof = 1;
169
ap->io->offset = 0;
170
ap->io->count = lseek(ap->io->fd, (off_t)0, SEEK_END);
171
return 0;
172
}
173
174
static int
175
vdb_putprologue(Pax_t* pax, register Archive_t* ap, int append)
176
{
177
register Vdb_t* vdb = (Vdb_t*)ap->data;
178
179
if (!vdb)
180
{
181
if (!(vdb = newof(0, Vdb_t, 1, 0)) || !(vdb->directory = sfstropen()))
182
nospace();
183
ap->data = vdb;
184
}
185
if (append)
186
return 0;
187
sfprintf(vdb->directory, "%c%s%c%s\n", VDB_DELIMITER, VDB_MAGIC, VDB_DELIMITER, state.volume);
188
paxwrite(pax, ap, sfstrbase(vdb->directory), sfstrtell(vdb->directory));
189
sfstrseek(vdb->directory, 0, SEEK_SET);
190
sfprintf(vdb->directory, "%s\n", VDB_DIRECTORY);
191
return 1;
192
}
193
194
static int
195
vdb_putheader(Pax_t* pax, Archive_t* ap, File_t* f)
196
{
197
register Vdb_t* vdb = (Vdb_t*)ap->data;
198
register unsigned char* s;
199
register int c;
200
int n;
201
202
if (state.complete)
203
complete(ap, f, state.record.header ? state.record.headerlen : f->namesize);
204
if (state.record.header)
205
paxwrite(pax, ap, state.record.header, state.record.headerlen);
206
else
207
{
208
f->name[f->namesize - 1] = '\n';
209
paxwrite(pax, ap, f->name, f->namesize);
210
f->name[f->namesize - 1] = 0;
211
}
212
if (!(c = state.record.delimiter))
213
{
214
c = VDB_DELIMITER;
215
s = (unsigned char*)state.tmp.buffer;
216
n = 1024;
217
if (f->fd >= 0)
218
{
219
n = read(f->fd, s, n);
220
if (n > 0)
221
{
222
int dp;
223
int ds;
224
int mp = 0;
225
int ms = 0;
226
unsigned char hit[UCHAR_MAX + 1];
227
228
/*
229
* to determine the delimiter, if any
230
*/
231
232
lseek(f->fd, -n, SEEK_CUR);
233
memzero(hit, sizeof(hit));
234
while (--n > 0)
235
hit[*(s + n)]++;
236
for (n = 0; n <= UCHAR_MAX; n++)
237
if (n == '_' || n == '/' || n == '.' || n == '\n' || n == '\\')
238
/* nop */;
239
else if (isspace(n))
240
{
241
if ((int)hit[n] > ms)
242
{
243
ms = hit[n];
244
ds = n;
245
}
246
}
247
else if ((int)hit[n] > mp && isprint(n) && !isalnum(n))
248
{
249
mp = hit[n];
250
dp = n;
251
}
252
if (mp)
253
c = dp;
254
else if (ms)
255
c = ds;
256
}
257
}
258
}
259
n = (c == '=') ? ':' : '=';
260
sfprintf(vdb->directory, "%c%s%c%I*u%c%I*u%c%s%c%I*u%c%s%c0%o\n", c, f->name, c, sizeof(ap->io->offset), ap->io->offset + ap->io->count, c, sizeof(f->st->st_size), f->st->st_size, c, VDB_DATE, n, sizeof(f->st->st_mtime), f->st->st_mtime, c, VDB_MODE, n, modex(f->st->st_mode & X_IPERM));
261
return 1;
262
}
263
264
static int
265
vdb_puttrailer(Pax_t* pax, Archive_t* ap, File_t* f)
266
{
267
if (state.record.trailer)
268
paxwrite(pax, ap, state.record.trailer, state.record.trailerlen);
269
return 0;
270
}
271
272
static off_t
273
vdb_putepilogue(Pax_t* pax, Archive_t* ap)
274
{
275
register Vdb_t* vdb = (Vdb_t*)ap->data;
276
277
if (state.record.header)
278
paxwrite(pax, ap, state.record.header, state.record.headerlen);
279
sfprintf(vdb->directory, "%c%s%c%0*I*d%c%0*I*d\n", VDB_DELIMITER, VDB_DIRECTORY, VDB_DELIMITER, VDB_FIXED, sizeof(ap->io->offset), ap->io->offset + ap->io->count + sizeof(VDB_DIRECTORY), VDB_DELIMITER, VDB_FIXED, sizeof(Sfoff_t), sftell(vdb->directory) - sizeof(VDB_DIRECTORY) + VDB_LENGTH + 1);
280
paxwrite(pax, ap, sfstrbase(vdb->directory), sfstrtell(vdb->directory));
281
sfstrclose(vdb->directory);
282
return ap->io->count;
283
}
284
285
Format_t pax_vdb_format =
286
{
287
"vdb",
288
0,
289
"virtual database",
290
0,
291
ARCHIVE|NOHARDLINKS|IN|OUT,
292
DEFBUFFER,
293
DEFBLOCKS,
294
0,
295
PAXNEXT(vdb),
296
0,
297
vdb_done,
298
vdb_getprologue,
299
vdb_getheader,
300
0,
301
0,
302
0,
303
vdb_putprologue,
304
vdb_putheader,
305
0,
306
vdb_puttrailer,
307
vdb_putepilogue,
308
};
309
310
PAXLIB(vdb)
311
312