rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

ar.c
Go to the documentation of this file.
1
6 #undef JBJ_WRITEPAD
7
8 #include "system.h"
9
10 #include <rpmio_internal.h> /* XXX fdGetCpioPos writing AR_MAGIC */
11
12 #include <rpmmacro.h>
13 #include <ugid.h>
14 #include <ar.h>
15 #define _IOSM_INTERNAL
16 #include <iosm.h>
17
18 #include "debug.h"
19
20 /*@access IOSM_t @*/
21
22 /*@unchecked@*/
23 int _ar_debug = 0;
24
33 static int strntoul(const char *str, /*@null@*/ /*@out@*/char **endptr,
34 int base, size_t num)
35 /*@modifies *endptr @*/
36 {
37 char * buf, * end;
38 unsigned long ret;
39
40 buf = alloca(num + 1);
41 strncpy(buf, str, num);
42 buf[num] = '\0';
43
44 ret = strtoul(buf, &end, base);
45 if (endptr != NULL) {
46 if (*end != '\0')
47 *endptr = ((char *)str) + (end - buf); /* XXX discards const */
48 else
49 *endptr = ((char *)str) + strlen(buf);
50 }
51
52 return ret;
53 }
54
55 /* Translate archive read/write ssize_t return for iosmStage(). */
56 #define _IOSMRC(_rc) \
57 if ((_rc) <= 0) return ((_rc) ? (int) -rc : IOSMERR_HDR_TRAILER)
58
59 static ssize_t arRead(void * _iosm, void * buf, size_t count)
60 /*@globals fileSystem @*/
61 /*@modifies _iosm, *buf, fileSystem @*/
62 {
63 IOSM_t iosm = _iosm;
64 char * t = buf;
65 size_t nb = 0;
66 size_t rc;
67
68 if (_ar_debug)
69 fprintf(stderr, "\t arRead(%p, %p[%u])\n", iosm, buf, (unsigned)count);
70
71 while (count > 0) {
72
73 /* Read next ar block. */
74 iosm->wrlen = count;
75 rc = _iosmNext(iosm, IOSM_DREAD);
76 if (!rc && iosm->rdnb != iosm->wrlen) {
77 if (iosm->rdnb == 0) return -IOSMERR_HDR_TRAILER; /* EOF */
78 rc = IOSMERR_READ_FAILED;
79 }
80 if (rc) return -rc;
81
82 /* Append to buffer. */
83 rc = (count > iosm->rdnb ? iosm->rdnb : count);
84 if (buf != iosm->wrbuf)
85 memcpy(t + nb, iosm->wrbuf, rc);
86 nb += rc;
87 count -= rc;
88 }
89 return nb;
90 }
91
92 int arHeaderRead(void * _iosm, struct stat * st)
93 /*@modifies _iosm, *st @*/
94 {
95 IOSM_t iosm = _iosm;
96 arHeader hdr = (arHeader) iosm->wrbuf;
97 ssize_t rc = 0;
98
99 if (_ar_debug)
100 fprintf(stderr, " arHeaderRead(%p, %p)\n", iosm, st);
101
102 /* XXX Read AR_MAGIC to beginning of ar(1) archive. */
103 if (fdGetCpioPos(iosm->cfd) == 0) {
104 rc = arRead(iosm, iosm->wrbuf, sizeof(AR_MAGIC)-1);
105 _IOSMRC(rc);
106
107 /* Verify archive magic. */
108 if (strncmp(iosm->wrbuf, AR_MAGIC, sizeof(AR_MAGIC)-1))
109 return IOSMERR_BAD_MAGIC;
110 }
111
112 top:
113 /* Make sure block aligned. */
114 rc = _iosmNext(iosm, IOSM_POS);
115 if (rc) return (int) rc;
116
117 rc = arRead(iosm, hdr, sizeof(*hdr));
118 _IOSMRC(rc);
119 if (_ar_debug)
120 fprintf(stderr, "==> %p[%u] \"%.*s\"\n", hdr, (unsigned)rc, (int)sizeof(*hdr)-2, (char *)hdr);
121
122 /* Verify header marker. */
123 if (strncmp(hdr->marker, AR_MARKER, sizeof(AR_MARKER)-1))
124 return IOSMERR_BAD_MAGIC;
125
126 st->st_size = strntoul(hdr->filesize, NULL, 10, sizeof(hdr->filesize));
127
128 /* Special ar(1) archive members. */
129 if (hdr->name[0] == '/') {
130 /* GNU: on "//": Read long member name string table. */
131 if (hdr->name[1] == '/' && hdr->name[2] == ' ') {
132 char * t;
133 size_t i;
134
135 rc = arRead(iosm, iosm->wrbuf, st->st_size);
136 _IOSMRC(rc);
137
138 iosm->wrbuf[rc] = '\0';
139 iosm->lmtab = t = xstrdup(iosm->wrbuf);
140 iosm->lmtablen = rc;
141 iosm->lmtaboff = 0;
142
143 for (i = 1; i < iosm->lmtablen; i++) {
144 t++;
145 if (t[0] != '\n') continue;
146 t[0] = '\0';
147 /* GNU: trailing '/' to permit file names with trailing ' '. */
148 if (t[-1] == '/') t[-1] = '\0';
149 }
150 goto top;
151 }
152 /* GNU: on "/": Skip symbol table. */
153 if (hdr->name[1] == ' ') {
154 rc = arRead(iosm, iosm->wrbuf, st->st_size);
155 _IOSMRC(rc);
156 goto top;
157 }
158 /* GNU: on "/123": Read "123" offset to substitute long member name. */
159 if (xisdigit((int)hdr->name[1])) {
160 char * te = NULL;
161 int i = strntoul(&hdr->name[1], &te, 10, sizeof(hdr->name)-2);
162 if (*te == ' ' && iosm->lmtab != NULL && i < (int)iosm->lmtablen)
163 iosm->path = xstrdup(iosm->lmtab + i);
164 }
165 } else
166 if (hdr->name[0] != ' ') { /* Short member name. */
167 size_t nb = sizeof(hdr->name);
168 char t[sizeof(hdr->name)+1];
169 memcpy(t, hdr->name, nb);
170 t[nb] = '\0';
171 while (nb > 0 && t[nb-1] == ' ')
172 t[--nb] = '\0';
173 /* GNU: trailing '/' to permit file names with trailing ' '. */
174 if (nb > 0 && t[nb - 1] == '/')
175 t[--nb] = '\0';
176 iosm->path = xstrdup(t);
177 }
178
179 st->st_mtime = strntoul(hdr->mtime, NULL, 10, sizeof(hdr->mtime));
180 st->st_ctime = st->st_atime = st->st_mtime;
181
182 st->st_uid = strntoul(hdr->uid, NULL, 10, sizeof(hdr->uid));
183 st->st_gid = strntoul(hdr->gid, NULL, 10, sizeof(hdr->gid));
184
185 st->st_mode = strntoul(hdr->mode, NULL, 8, sizeof(hdr->mode));
186
187 st->st_nlink = 1;
188 rc = 0;
189
190 if (_ar_debug)
191 fprintf(stderr, "\t %06o%3d (%4d,%4d)%12lu %s\n",
192 (unsigned)st->st_mode, (int)st->st_nlink,
193 (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
194 (iosm->path ? iosm->path : ""));
195
196 return (int) rc;
197 }
198
199 static ssize_t arWrite(void * _iosm, const void *buf, size_t count)
200 /*@globals fileSystem @*/
201 /*@modifies _iosm, fileSystem @*/
202 {
203 IOSM_t iosm = _iosm;
204 const char * s = buf;
205 size_t nb = 0;
206 size_t rc;
207
208 if (_ar_debug)
209 fprintf(stderr, "\tarWrite(%p, %p[%u])\n", iosm, buf, (unsigned)count);
210
211 while (count > 0) {
212
213 /* XXX DWRITE uses rdnb for I/O length. */
214 iosm->rdnb = count;
215 if (s != iosm->rdbuf)
216 memmove(iosm->rdbuf, s + nb, iosm->rdnb);
217
218 rc = _iosmNext(iosm, IOSM_DWRITE);
219 if (!rc && iosm->rdnb != iosm->wrnb)
220 rc = IOSMERR_WRITE_FAILED;
221 if (rc) return -rc;
222
223 nb += iosm->rdnb;
224 count -= iosm->rdnb;
225 }
226
227 #if defined(JBJ_WRITEPAD)
228 /* Pad to next block boundary. */
229 if ((rc = _iosmNext(iosm, IOSM_PAD)) != 0) return -rc;
230 #endif
231
232 return nb;
233 }
234
235 int arHeaderWrite(void * _iosm, struct stat * st)
236 {
237 IOSM_t iosm = _iosm;
238 arHeader hdr = (arHeader) iosm->rdbuf;
239 size_t nb;
240 ssize_t rc = 0;
241
242 if (_ar_debug)
243 fprintf(stderr, " arHeaderWrite(%p, %p)\n", iosm, st);
244
245 /* At beginning of ar(1) archive, write magic and long member table. */
246 if (fdGetCpioPos(iosm->cfd) == 0) {
247 /* Write ar(1) magic. */
248 rc = arWrite(iosm, AR_MAGIC, sizeof(AR_MAGIC)-1);
249 _IOSMRC(rc);
250 /* GNU: on "//": Write long member name string table. */
251 if (iosm->lmtab != NULL) {
252 memset(hdr, (int) ' ', sizeof(*hdr));
253 hdr->name[0] = '/';
254 hdr->name[1] = '/';
255 sprintf(hdr->filesize, "%-10d", (unsigned) (iosm->lmtablen & 037777777777));
256 strncpy(hdr->marker, AR_MARKER, sizeof(AR_MARKER)-1);
257
258 rc = arWrite(iosm, hdr, sizeof(*hdr));
259 _IOSMRC(rc);
260 rc = arWrite(iosm, iosm->lmtab, iosm->lmtablen);
261 _IOSMRC(rc);
262 #if !defined(JBJ_WRITEPAD)
263 rc = _iosmNext(iosm, IOSM_PAD);
264 if (rc) return (int)rc;
265 #endif
266 }
267 }
268
269 memset(hdr, (int)' ', sizeof(*hdr));
270
271 nb = strlen(iosm->path);
272 if (nb >= sizeof(hdr->name)) {
273 const char * t;
274 const char * te;
275 assert(iosm->lmtab != NULL);
276 t = iosm->lmtab + iosm->lmtaboff;
277 te = strchr(t, '\n');
278 /* GNU: on "/123": Write "/123" offset for long member name. */
279 nb = snprintf(hdr->name, sizeof(hdr->name)-1, "/%u", (unsigned)iosm->lmtaboff);
280 hdr->name[nb] = ' ';
281 if (te != NULL)
282 iosm->lmtaboff += (te - t) + 1;
283 } else {
284 strncpy(hdr->name, iosm->path, nb);
285 hdr->name[nb] = '/';
286 }
287
288 sprintf(hdr->mtime, "%-12u", (unsigned) (st->st_mtime & 037777777777));
289 sprintf(hdr->uid, "%-6u", (unsigned int)(st->st_uid & 07777777));
290 sprintf(hdr->gid, "%-6u", (unsigned int)(st->st_gid & 07777777));
291
292 sprintf(hdr->mode, "%-8o", (unsigned int)(st->st_mode & 07777777));
293 sprintf(hdr->filesize, "%-10u", (unsigned) (st->st_size & 037777777777));
294
295 strncpy(hdr->marker, AR_MARKER, sizeof(AR_MARKER)-1);
296
297 rc = (int) sizeof(*hdr);
298 if (_ar_debug)
299 fprintf(stderr, "==> %p[%u] \"%.*s\"\n", hdr, (unsigned)rc, (int)sizeof(*hdr), (char *)hdr);
300
301 rc = arWrite(iosm, hdr, sizeof(*hdr));
302 _IOSMRC(rc);
303 rc = 0;
304
305 return (int) rc;
306 }
307
308 int arTrailerWrite(void * _iosm)
309 {
310 IOSM_t iosm = _iosm;
311 size_t rc = 0;
312
313 if (_ar_debug)
314 fprintf(stderr, " arTrailerWrite(%p)\n", iosm);
315
316 #if defined(JBJ_WRITEPAD)
317 rc = arWrite(iosm, NULL, 0); /* XXX _iosmNext(iosm, IOSM_PAD) */
318 _IOSMRC(rc);
319 #else
320 rc = _iosmNext(iosm, IOSM_PAD); /* XXX likely unnecessary. */
321 #endif
322
323 return (int) rc;
324 }