rpm  5.2.1
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);
127  /*@-shiftimplementation@*/
128  st->st_dev = Makedev(major, minor);
129  /*@=shiftimplementation@*/
130 
131  GET_NUM_FIELD(hdr->rdevMajor, major);
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