Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/pax/pax-saveset.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 vmsbackup format
24
*/
25
26
#include "format.h"
27
28
#define BLKHDR_SIZE 256
29
#define BLKHDR_hdrsiz 0
30
#define BLKHDR_blksiz 40
31
32
#define FILHDR_SIZE 4
33
#define FILHDR_MAGIC 257
34
#define FILHDR_namelen 128
35
#define FILHDR_size 0
36
#define FILHDR_type 2
37
#define FILHDR_data 4
38
39
#define FILATT_blocks 10
40
#define FILATT_frag 12
41
#define FILATT_recatt 1
42
#define FILATT_recfmt 0
43
#define FILATT_reclen 2
44
#define FILATT_recvfc 15
45
46
#define RECHDR_SIZE 16
47
#define RECHDR_size 0
48
#define RECHDR_type 2
49
50
#define REC_file 3
51
#define REC_vbn 4
52
53
typedef struct Saveset_s
54
{
55
char* block; /* current block */
56
long blocksize; /* max block size */
57
char* bp; /* block pointer */
58
int recatt; /* record attributes */
59
int recfmt; /* record format */
60
int reclen; /* record length */
61
int recvfc; /* record fixed control length */
62
int lastsize; /* size of last record */
63
time_t time; /* backup time */
64
char id[17]; /* name id */
65
} Saveset_t;
66
67
/*
68
* get next saveset record
69
* if header!=0 then all records skipped until REC_file found
70
* otherwise REC_vbn cause non-zero return
71
* 0 returned for no record match
72
*/
73
74
static int
75
getsaveset(Pax_t* pax, register Archive_t* ap, register File_t* f, register Saveset_t* ss, int header)
76
{
77
register char* p;
78
register char* s;
79
char* t;
80
int i;
81
long n;
82
83
for (;;)
84
{
85
ss->bp += ss->lastsize;
86
while (ss->bp >= ss->block + state.blocksize)
87
{
88
ss->bp = ss->block;
89
ss->lastsize = 0;
90
if (paxread(pax, ap, ss->bp, (off_t)0, (off_t)state.blocksize, 0) <= 0)
91
{
92
ap->format = getformat("slt", 1);
93
if (header)
94
gettrailer(ap, f);
95
return 0;
96
}
97
if (swapget(1, ss->bp + BLKHDR_hdrsiz, 2) != BLKHDR_SIZE)
98
error(3, "invalid %s format block header", ap->format->name);
99
if (!(n = swapget(3, ss->bp + BLKHDR_blksiz, 4)))
100
ss->bp += state.blocksize;
101
else if (n != state.blocksize)
102
error(3, "invalid %s format blocksize=%ld", ap->format->name, n);
103
ss->bp += BLKHDR_SIZE;
104
}
105
ss->lastsize = swapget(1, ss->bp + RECHDR_size, 2);
106
i = swapget(1, ss->bp + RECHDR_type, 2);
107
ss->bp += RECHDR_SIZE;
108
message((-2, "record: type=%d size=%d", i, ss->lastsize));
109
if (i == REC_file)
110
{
111
if (header)
112
{
113
p = ss->bp;
114
if (swapget(1, p, 2) != FILHDR_MAGIC)
115
error(3, "invalid %s format file header", ap->format->name);
116
p += 2;
117
i = swapget(1, p + FILHDR_size, 2);
118
if (p + FILHDR_data + i > ss->block + state.blocksize)
119
error(3, "invalid %s format file attribute", ap->format->name);
120
t = f->name = paxstash(pax, &ap->stash.head, NiL, i);
121
n = 0;
122
for (s = p + FILHDR_data + 1; s < p + FILHDR_data + i; s++)
123
{
124
if (isupper(*s))
125
*t++ = tolower(*s);
126
else if (n)
127
{
128
if (*s == ';')
129
break;
130
*t++ = *s;
131
}
132
else if (*s == ']')
133
{
134
n = 1;
135
*t++ = '/';
136
}
137
else if (*s == '.')
138
*t++ = '/';
139
else
140
*t++ = *s;
141
}
142
*t = 0;
143
for (i = 0; i < 5; i++)
144
{
145
s = p + FILHDR_size;
146
if ((p += FILHDR_SIZE + (long)swapget(1, s, 2)) > ss->block + state.blocksize)
147
error(3, "invalid %s format file attribute", ap->format->name);
148
}
149
ss->recatt = *(p + FILHDR_data + FILATT_recfmt);
150
ss->recfmt = *(p + FILHDR_data + FILATT_recfmt);
151
ss->reclen = swapget(1, p + FILHDR_data + FILATT_reclen, 2);
152
ss->recvfc = swapget(1, p + FILHDR_data + FILATT_recvfc, 2);
153
f->st->st_size = (long)(swapget(1, p + FILHDR_data + FILATT_blocks, 2) - 1) * BLOCKSIZE + (long)swapget(1, p + FILHDR_data + FILATT_frag, 2);
154
for (; i < 15; i++)
155
{
156
s = p + FILHDR_size;
157
if ((p += FILHDR_SIZE + (long)swapget(1, s, 2)) > ss->block + state.blocksize)
158
error(3, "invalid %s format file attribute", ap->format->name);
159
}
160
161
/*
162
* pure guesswork based on 100 nsec epoch
163
* 17-NOV-1858 00:00:00 GMT
164
*/
165
166
if ((n = swapget(3, p + FILHDR_data + 4, 4) - 7355000) < 0)
167
n = 1;
168
else
169
n = (n << 8) + *(p + FILHDR_data + 3);
170
f->st->st_mtime = (time_t)n;
171
return 1;
172
}
173
ss->bp -= RECHDR_SIZE;
174
ss->lastsize = 0;
175
return 0;
176
}
177
else if (i == REC_vbn && !header)
178
return 1;
179
}
180
}
181
182
static int
183
vmsbackup_done(Pax_t* pax, register Archive_t* ap)
184
{
185
if (ap->data)
186
{
187
free(ap->data);
188
ap->data = 0;
189
}
190
return 0;
191
}
192
193
static int
194
vmsbackup_getdata(Pax_t* pax, register Archive_t* ap, register File_t* f, int wfd)
195
{
196
register Saveset_t* ss = (Saveset_t*)ap->data;
197
register off_t c;
198
int i;
199
int j;
200
int k;
201
Sfio_t* wfp;
202
203
if (wfd < 0)
204
wfp = 0;
205
else if (!(wfp = sfnew(NiL, NiL, SF_UNBOUND, wfd, SF_WRITE)))
206
{
207
error(2, "%s: cannot write", f->name);
208
return -1;
209
}
210
j = 0;
211
k = 0;
212
c = 0;
213
while (getsaveset(pax, ap, f, ss, 0))
214
{
215
/*
216
* this part transcribed from vmsbackup
217
*/
218
219
i = 0;
220
if (wfp) while ((c + i) < f->st->st_size && i < ss->lastsize) switch (ss->recfmt)
221
{
222
case 1: /* fixed length */
223
if (j <= 0) j = ss->reclen;
224
sfputc(wfp, ss->bp[i]);
225
i++;
226
j--;
227
break;
228
case 2: /* variable length */
229
case 3: /* with fixed control */
230
if (j <= 0)
231
{
232
j = k = swapget(1, &ss->bp[i], 2);
233
i += 2;
234
if (ss->recfmt == 3)
235
{
236
i += ss->recvfc;
237
j -= ss->recvfc;
238
}
239
}
240
else
241
{
242
if (j == k && ss->recatt == 1)
243
{
244
if (ss->bp[i] == '0') ss->bp[i] = '\n';
245
else if (ss->bp[i] == '1') ss->bp[i] = '\f';
246
}
247
sfputc(wfp, ss->bp[i]);
248
i++;
249
j--;
250
}
251
if (j <= 0)
252
{
253
sfputc(wfp, '\n');
254
if (i & 1) i++;
255
}
256
break;
257
case 4: /* seq stream */
258
case 5: /* seq LF stream */
259
if (j <= 0) j = 512;
260
if (ss->bp[i] == '\n') j = 0;
261
else j--;
262
sfputc(wfp, ss->bp[i]);
263
i++;
264
break;
265
case 6: /* seq CR stream */
266
if (ss->bp[i] == '\r') ss->bp[i] = '\n';
267
sfputc(wfp, ss->bp[i]);
268
i++;
269
break;
270
default:
271
error(state.keepgoing ? 1 : 3, "%s: invalid %s format data record format=%d", f->name, ap->format->name, ss->recfmt);
272
goto next;
273
}
274
next:
275
c += i;
276
}
277
if (wfp)
278
{
279
sfclose(wfp);
280
setfile(ap, f);
281
}
282
return 1;
283
}
284
285
static int
286
vmsbackup_getepilogue(Pax_t* pax, Archive_t* ap)
287
{
288
return 1;
289
}
290
291
static int
292
vmsbackup_validate(Pax_t* pax, Archive_t* ap, register File_t* f)
293
{
294
register Saveset_t* ss = (Saveset_t*)ap->data;
295
register char* s;
296
297
if (f->type != X_IFREG)
298
{
299
error(2, "%s: only regular files copied in %s format", f->path, ap->format->name);
300
return 0;
301
}
302
if (s = strrchr(f->name, '/'))
303
{
304
s++;
305
error(1, "%s: file name stripped to %s", f->name, s);
306
}
307
else
308
s = f->name;
309
if (strlen(s) > sizeof(ss->id) - 1)
310
{
311
error(2, "%s: file name too long", f->name);
312
return 0;
313
}
314
f->id = strupper(strcpy(ss->id, s));
315
return 1;
316
}
317
318
Format_t pax_vmsbackup_format =
319
{
320
"vmsbackup",
321
0,
322
"VMS backup savset; for tape devices only",
323
0,
324
ARCHIVE|NOHARDLINKS|IN,
325
0,
326
0,
327
0,
328
PAXNEXT(vmsbackup),
329
0,
330
vmsbackup_done,
331
0,
332
0,
333
vmsbackup_getdata,
334
0,
335
vmsbackup_getepilogue,
336
0,
337
0,
338
0,
339
0,
340
0,
341
0,
342
0,
343
0,
344
vmsbackup_validate
345
};
346
347
PAXLIB(vmsbackup)
348
349