rpm 5.2.1

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

- File List
- Globals

cpio.c
Go to the documentation of this file.
1
5 #undef JBJ_WRITEPAD
6
7 #include "system.h"
8
9 #include <rpmio.h>
10 #include <ugid.h>
11 #include <cpio.h>
12 #define _IOSM_INTERNAL
13 #include <iosm.h>
14
15 #include "debug.h"
16
17 /*@access IOSM_t @*/
18
19 /*@unchecked@*/
20 int _cpio_debug = 0;
21
30 static int strntoul(const char *str, /*@null@*/ /*@out@*/char **endptr,
31 int base, size_t num)
32 /*@modifies *endptr @*/
33 /*@requires maxSet(endptr) >= 0 @*/
34 {
35 char * buf, * end;
36 unsigned long ret;
37
38 buf = alloca(num + 1);
39 strncpy(buf, str, num);
40 buf[num] = '\0';
41
42 ret = strtoul(buf, &end, base);
43 if (endptr != NULL) {
44 if (*end != '\0')
45 *endptr = ((char *)str) + (end - buf); /* XXX discards const */
46 else
47 *endptr = ((char *)str) + strlen(buf);
48 }
49
50 return ret;
51 }
52
53 /* Translate archive read/write ssize_t return for iosmStage(). */
54 #define _IOSMRC(_rc) \
55 if ((_rc) <= 0) return ((_rc) ? (int) -rc : IOSMERR_HDR_TRAILER)
56
57 static ssize_t cpioRead(void * _iosm, void * buf, size_t count)
58 /*@globals fileSystem @*/
59 /*@modifies _iosm, *buf, fileSystem @*/
60 {
61 IOSM_t iosm = _iosm;
62 char * t = buf;
63 size_t nb = 0;
64 size_t rc;
65
66 if (_cpio_debug)
67 fprintf(stderr, " cpioRead(%p, %p[%u])\n", iosm, buf, (unsigned)count);
68
69 while (count > 0) {
70
71 /* Read next cpio block. */
72 iosm->wrlen = count;
73 rc = _iosmNext(iosm, IOSM_DREAD);
74 if (!rc && iosm->rdnb != iosm->wrlen)
75 rc = IOSMERR_READ_FAILED;
76 if (rc) return -rc;
77
78 /* Append to buffer. */
79 rc = (count > iosm->rdnb ? iosm->rdnb : count);
80 if (buf != iosm->wrbuf)
81 memcpy(t + nb, iosm->wrbuf, rc);
82 nb += rc;
83 count -= rc;
84 }
85 return nb;
86 }
87
88 #define GET_NUM_FIELD(phys, log) \
89 log = strntoul(phys, &end, 16, sizeof(phys)); \
90 if ( (end - phys) != sizeof(phys) ) return IOSMERR_BAD_HEADER;
91 #define SET_NUM_FIELD(phys, val, space) \
92 sprintf(space, "%8.8lx", (unsigned long) (val)); \
93 memcpy(phys, space, 8)
94
95 int cpioHeaderRead(void * _iosm, struct stat * st)
96 {
97 IOSM_t iosm = _iosm;
98 cpioHeader hdr = (cpioHeader) iosm->wrbuf;
99 size_t nb;
100 char * end;
101 int major, minor;
102 ssize_t rc = 0;
103
104 if (_cpio_debug)
105 fprintf(stderr, " cpioHeaderRead(%p, %p)\n", iosm, st);
106
107 /* Read next header. */
108 rc = cpioRead(iosm, hdr, PHYS_HDR_SIZE);
109 _IOSMRC(rc);
110
111 /* Verify header magic. */
112 if (strncmp(CPIO_CRC_MAGIC, hdr->magic, sizeof(CPIO_CRC_MAGIC)-1) &&
113 strncmp(CPIO_NEWC_MAGIC, hdr->magic, sizeof(CPIO_NEWC_MAGIC)-1))
114 return IOSMERR_BAD_MAGIC;
115
116 /* Convert header to stat(2). */
117 GET_NUM_FIELD(hdr->inode, st->st_ino);
118 GET_NUM_FIELD(hdr->mode, st->st_mode);
119 GET_NUM_FIELD(hdr->uid, st->st_uid);
120 GET_NUM_FIELD(hdr->gid, st->st_gid);
121 GET_NUM_FIELD(hdr->nlink, st->st_nlink);
122 GET_NUM_FIELD(hdr->mtime, st->st_mtime);
123 GET_NUM_FIELD(hdr->filesize, st->st_size);
124
125 GET_NUM_FIELD(hdr->devMajor, major);
126 GET_NUM_FIELD(hdr->devMinor, minor);
127 /*@-shiftimplementation@*/
128 st->st_dev = Makedev(major, minor);
129 /*@=shiftimplementation@*/
130
131 GET_NUM_FIELD(hdr->rdevMajor, major);
132 GET_NUM_FIELD(hdr->rdevMinor, minor);
133 /*@-shiftimplementation@*/
134 st->st_rdev = Makedev(major, minor);
135 /*@=shiftimplementation@*/
136
137 GET_NUM_FIELD(hdr->namesize, nb);
138 if (nb >= iosm->wrsize)
139 return IOSMERR_BAD_HEADER;
140
141 /* Read file name. */
142 { char * t = xmalloc(nb + 1);
143 rc = cpioRead(iosm, t, nb);
144 if (rc < 0) {
145 t = _free(t);
146 iosm->path = NULL;
147 } else {
148 _IOSMRC(rc);
149 t[nb] = '\0';
150 iosm->path = t;
151 }
152 }
153
154 /* Read link name. */
155 if (S_ISLNK(st->st_mode)) {
156 char * t;
157
158 /* Make sure block aligned. */
159 rc = _iosmNext(iosm, IOSM_POS);
160 if (rc) return (int) -rc;
161
162 nb = (size_t) st->st_size;
163 t = xmalloc(nb + 1);
164 rc = cpioRead(iosm, t, nb);
165 if (rc < 0) {
166 t = _free(t);
167 iosm->lpath = NULL;
168 } else {
169 _IOSMRC(rc);
170 t[nb] = '\0';
171 iosm->lpath = t;
172 }
173 }
174
175 rc = 0;
176
177 /*@-usereleased@*/
178 if (_cpio_debug)
179 fprintf(stderr, "\t %06o%3d (%4d,%4d)%12lu %s\n\t-> %s\n",
180 (unsigned)st->st_mode, (int)st->st_nlink,
181 (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
182 (iosm->path ? iosm->path : ""), (iosm->lpath ? iosm->lpath : ""));
183 /*@=usereleased@*/
184
185 return (int) rc;
186 }
187
188 static ssize_t cpioWrite(void * _iosm, const void *buf, size_t count)
189 /*@globals fileSystem @*/
190 /*@modifies _iosm, fileSystem @*/
191 {
192 IOSM_t iosm = _iosm;
193 const char * s = buf;
194 size_t nb = 0;
195 size_t rc;
196
197 if (_cpio_debug)
198 fprintf(stderr, "\t cpioWrite(%p, %p[%u])\n", iosm, buf, (unsigned)count);
199
200 while (count > 0) {
201
202 /* XXX DWRITE uses rdnb for I/O length. */
203 iosm->rdnb = count;
204 if (s != iosm->rdbuf)
205 memmove(iosm->rdbuf, s + nb, iosm->rdnb);
206
207 rc = _iosmNext(iosm, IOSM_DWRITE);
208 if (!rc && iosm->rdnb != iosm->wrnb)
209 rc = IOSMERR_WRITE_FAILED;
210 if (rc) return -rc;
211
212 nb += iosm->rdnb;
213 count -= iosm->rdnb;
214 }
215
216 #if defined(JBJ_WRITEPAD)
217 /* Pad to next block boundary. */
218 if ((rc = _iosmNext(iosm, IOSM_PAD)) != 0) return -rc;
219 #endif
220
221 return nb;
222 }
223
224 int cpioHeaderWrite(void * _iosm, struct stat * st)
225 {
226 IOSM_t iosm = _iosm;
227 cpioHeader hdr = (cpioHeader) iosm->rdbuf;
228 char field[64];
229 size_t nb;
230 dev_t dev;
231 ssize_t rc = 0;
232
233 if (_cpio_debug)
234 fprintf(stderr, " cpioHeaderWrite(%p, %p)\n", iosm, st);
235
236 memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
237 SET_NUM_FIELD(hdr->inode, st->st_ino, field);
238 SET_NUM_FIELD(hdr->mode, st->st_mode, field);
239 SET_NUM_FIELD(hdr->uid, st->st_uid, field);
240 SET_NUM_FIELD(hdr->gid, st->st_gid, field);
241 SET_NUM_FIELD(hdr->nlink, st->st_nlink, field);
242 SET_NUM_FIELD(hdr->mtime, st->st_mtime, field);
243 SET_NUM_FIELD(hdr->filesize, st->st_size, field);
244
245 dev = major((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMajor, dev, field);
246 dev = minor((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMinor, dev, field);
247 dev = major((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMajor, dev, field);
248 dev = minor((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMinor, dev, field);
249
250 nb = strlen(iosm->path) + 1; SET_NUM_FIELD(hdr->namesize, nb, field);
251 memcpy(hdr->checksum, "00000000", 8);
252
253 /* XXX Coalesce hdr+name into single I/O. */
254 memcpy(iosm->rdbuf + PHYS_HDR_SIZE, iosm->path, nb);
255 nb += PHYS_HDR_SIZE;
256 rc = cpioWrite(iosm, hdr, nb);
257 _IOSMRC(rc);
258
259 if (S_ISLNK(st->st_mode)) {
260 assert(iosm->lpath != NULL);
261 #if !defined(JBJ_WRITEPAD)
262 rc = _iosmNext(iosm, IOSM_PAD);
263 if (rc) return (int) rc;
264 #endif
265
266 nb = strlen(iosm->lpath);
267 rc = cpioWrite(iosm, iosm->lpath, nb);
268 _IOSMRC(rc);
269 }
270
271 #if !defined(JBJ_WRITEPAD)
272 rc = _iosmNext(iosm, IOSM_PAD);
273 #endif
274
275 return (int) rc;
276 }
277
278 int cpioTrailerWrite(void * _iosm)
279 {
280 IOSM_t iosm = _iosm;
281 cpioHeader hdr = (cpioHeader) iosm->rdbuf;
282 size_t nb;
283 ssize_t rc = 0;
284
285 if (_cpio_debug)
286 fprintf(stderr, " cpioTrailerWrite(%p)\n", iosm);
287
288 memset(hdr, (int)'0', PHYS_HDR_SIZE);
289 memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
290 memcpy(hdr->nlink, "00000001", 8);
291 memcpy(hdr->namesize, "0000000b", 8);
292
293 nb = sizeof(CPIO_TRAILER);
294 /* XXX Coalesce hdr+trailer into single I/O. */
295 memcpy(iosm->rdbuf + PHYS_HDR_SIZE, CPIO_TRAILER, nb);
296 nb += PHYS_HDR_SIZE;
297
298 rc = cpioWrite(iosm, hdr, nb);
299 _IOSMRC(rc);
300
301 /*
302 * GNU cpio pads to 512 bytes here, but we don't. This may matter for
303 * tape device(s) and/or concatenated cpio archives. <shrug>
304 */
305 #if !defined(JBJ_WRITEPAD)
306 rc = _iosmNext(iosm, IOSM_PAD);
307 #endif
308 rc = 0;
309
310 return (int) rc;
311 }
312