Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/paxlib/tp/tp.c
1811 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2004-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 tp format
24
*/
25
26
#include <paxlib.h>
27
#include <ccode.h>
28
#include <tm.h>
29
30
#define TP_BLOCK 512
31
32
#define DIRDEC 192
33
#define DIRMAG 496
34
35
typedef uint8_t ui1;
36
typedef uint16_t ui2;
37
typedef uint32_t ui4;
38
39
typedef struct Dir_s
40
{
41
char pathname[32];
42
ui1 mode[2];
43
ui1 uid;
44
ui1 gid;
45
ui1 unused1;
46
ui1 size[3];
47
ui1 modtime[4];
48
ui1 tapeaddr[2];
49
ui1 unused2[16];
50
ui1 checksum[2];
51
} Dir_t;
52
53
typedef struct Ar_s
54
{
55
Pax_t* pax;
56
Paxarchive_t* ap;
57
off_t offset;
58
Dir_t* dp;
59
Dir_t* ep;
60
Dir_t dir[1];
61
} Ar_t;
62
63
static int
64
tp_done(Pax_t* pax, register Paxarchive_t* ap)
65
{
66
register Ar_t* ar = (Ar_t*)ap->data;
67
68
if (!ar)
69
return -1;
70
ap->io->eof = 1;
71
free(ar);
72
ap->data = 0;
73
return 0;
74
}
75
76
static int
77
tp_getprologue(Pax_t* pax, Paxformat_t* fp, register Paxarchive_t* ap, Paxfile_t* f, unsigned char* buf, size_t size)
78
{
79
register Ar_t* ar;
80
register ui1* s;
81
register ui1* e;
82
int16_t w;
83
size_t n;
84
85
if (size < 2 * TP_BLOCK)
86
return 0;
87
w = 0;
88
for (e = (s = (ui1*)buf + TP_BLOCK) + TP_BLOCK; s < e; s += 2)
89
w += s[0] + (s[1]<<8);
90
if (w)
91
return 0;
92
w = ((Dir_t*)buf)->checksum[0] + (((Dir_t*)buf)->checksum[1]<<8);
93
if (w < 0 || w > DIRMAG)
94
w = DIRMAG;
95
n = (size_t)w * sizeof(Dir_t);
96
if (!(ar = newof(0, Ar_t, 1, n - sizeof(Dir_t))))
97
return paxnospace(pax);
98
if (paxread(pax, ap, NiL, PAX_BLOCK, 0, 0) != PAX_BLOCK || paxread(pax, ap, ar->dir, n, 0, 0) != n)
99
{
100
error(2, "%s: %s format directory read error", ap->name, fp->name);
101
free(ar);
102
return -1;
103
}
104
ar->dp = ar->dir;
105
ar->ep = ar->dir + w;
106
ar->pax = pax;
107
ar->ap = ap;
108
ap->data = ar;
109
return 1;
110
}
111
112
static int
113
tp_getheader(Pax_t* pax, register Paxarchive_t* ap, register Paxfile_t* f)
114
{
115
register Ar_t* ar = (Ar_t*)ap->data;
116
register Dir_t* dp;
117
register ui1* s;
118
register ui1* e;
119
int16_t w;
120
121
do
122
{
123
if (ar->dp >= ar->ep)
124
return 0;
125
dp = ar->dp++;
126
} while (!*dp->pathname);
127
w = 0;
128
for (e = (s = (ui1*)ar->dir) + sizeof(Dir_t); s < e; s += 2)
129
w += s[0] + (s[1]<<8);
130
if (w)
131
{
132
error(2, "%s: %s format directory entry %d checksum error", ap->name, ap->format->name, ar->dp - ar->dir);
133
return -1;
134
}
135
if (CC_NATIVE != CC_ASCII)
136
ccmaps(dp->pathname, sizeof(dp->pathname), CC_ASCII, CC_NATIVE);
137
f->name = dp->pathname;
138
f->linktype = PAX_NOLINK;
139
f->linkpath = 0;
140
f->st->st_mode = X_IFREG | ((dp->mode[0] + (dp->mode[1]<<8)) & 07777);
141
f->st->st_uid = dp->uid;
142
f->st->st_gid = dp->gid;
143
f->st->st_size = (dp->size[0]<<16) + dp->size[1] + (dp->size[2]<<8);
144
f->st->st_mtime = dp->modtime[2] + (dp->modtime[3]<<8) + (dp->modtime[0]<<16) + (dp->modtime[1]<<24);
145
f->st->st_nlink = 1;
146
ar->offset = (off_t)(dp->tapeaddr[0] + (dp->tapeaddr[1]<<8)) * TP_BLOCK;
147
return 1;
148
}
149
150
static int
151
tp_getdata(Pax_t* pax, register Paxarchive_t* ap, register Paxfile_t* f, int fd)
152
{
153
Sfio_t* sp;
154
off_t skip;
155
ssize_t n;
156
int r;
157
158
if (!(n = f->st->st_size))
159
return 1;
160
skip = roundof(f->st->st_size, TP_BLOCK);
161
r = -1;
162
if (fd < 0)
163
r = 1;
164
else if (sp = paxpart(pax, ap, f->st->st_size))
165
for (;;)
166
{
167
if ((n = sfread(sp, pax->buf, sizeof(pax->buf))) < 0)
168
{
169
(*pax->errorf)(NiL, pax, 2, "%s: %s: unexpected EOF", ap->name, f->name);
170
break;
171
}
172
else if (n == 0)
173
{
174
r = 1;
175
break;
176
}
177
skip -= n;
178
if (paxdata(pax, ap, f, fd, pax->buf, n))
179
break;
180
}
181
if (skip && paxread(pax, ap, NiL, skip, 0, 0) != skip)
182
{
183
(*pax->errorf)(NiL, pax, 2, "%s: %s: cannot skip past %s format data", ap->name, f->name, ap->format->name);
184
r = -1;
185
}
186
return r;
187
}
188
189
Paxformat_t pax_tp_format =
190
{
191
"tp",
192
0,
193
"unix 4th-7th edition PDP-11 tp archive",
194
0,
195
PAX_ARCHIVE|PAX_NOHARDLINKS|PAX_IN,
196
PAX_DEFBUFFER,
197
PAX_DEFBLOCKS,
198
PAX_BLOCK,
199
PAXNEXT(tp),
200
0,
201
tp_done,
202
tp_getprologue,
203
tp_getheader,
204
tp_getdata,
205
};
206
207
PAXLIB(tp)
208
209