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