rpm  4.5
cpio.c
Go to the documentation of this file.
1 
10 #include "system.h"
11 
12 #include <rpmio_internal.h>
13 #include <rpmlib.h>
14 
15 #include "cpio.h"
16 #include "fsm.h"
17 
18 #include "rpmerr.h"
19 #include "debug.h"
20 
21 /*@access FSM_t @*/
22 
23 /*@unchecked@*/
24 int _cpio_debug = 0;
25 
34 static int strntoul(const char *str, /*@out@*/char **endptr, int base, int num)
35  /*@modifies *endptr @*/
36  /*@requires maxSet(endptr) >= 0 @*/
37 {
38  char * buf, * end;
39  unsigned long ret;
40 
41  buf = alloca(num + 1);
42  strncpy(buf, str, num);
43  buf[num] = '\0';
44 
45  ret = strtoul(buf, &end, base);
46 /*@-boundsread@*/ /* LCL: strtoul annotations */
47  if (*end != '\0')
48  *endptr = ((char *)str) + (end - buf); /* XXX discards const */
49  else
50  *endptr = ((char *)str) + strlen(buf);
51 /*@=boundsread@*/
52 
53  return ret;
54 }
55 
56 #define GET_NUM_FIELD(phys, log) \
57  /*@-boundswrite@*/ \
58  log = strntoul(phys, &end, 16, sizeof(phys)); \
59  /*@=boundswrite@*/ \
60  if ( (end - phys) != sizeof(phys) ) return CPIOERR_BAD_HEADER;
61 #define SET_NUM_FIELD(phys, val, space) \
62  sprintf(space, "%8.8lx", (unsigned long) (val)); \
63  /*@-boundsread@*/ \
64  memcpy(phys, space, 8) \
65  /*@=boundsread@*/
66 
68 {
69  struct cpioCrcPhysicalHeader * hdr =
70  (struct cpioCrcPhysicalHeader *)fsm->rdbuf;
71  int rc;
72 
73 /*@-boundswrite@*/
74  memset(hdr, '0', PHYS_HDR_SIZE);
75  memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
76  memcpy(hdr->nlink, "00000001", 8);
77  memcpy(hdr->namesize, "0000000b", 8);
78  memcpy(fsm->rdbuf + PHYS_HDR_SIZE, CPIO_TRAILER, sizeof(CPIO_TRAILER));
79 /*@=boundswrite@*/
80 
81  /* XXX DWRITE uses rdnb for I/O length. */
82  fsm->rdnb = PHYS_HDR_SIZE + sizeof(CPIO_TRAILER);
83  rc = fsmNext(fsm, FSM_DWRITE);
84 
85  /*
86  * GNU cpio pads to 512 bytes here, but we don't. This may matter for
87  * tape device(s) and/or concatenated cpio archives. <shrug>
88  */
89  if (!rc)
90  rc = fsmNext(fsm, FSM_PAD);
91 
92  return rc;
93 }
94 
95 int cpioHeaderWrite(FSM_t fsm, struct stat * st)
96 {
97  struct cpioCrcPhysicalHeader * hdr = (struct cpioCrcPhysicalHeader *)fsm->rdbuf;
98  char field[64];
99  size_t len;
100  dev_t dev;
101  int rc = 0;
102 
103 if (_cpio_debug)
104 fprintf(stderr, " %s(%p, %p)\n", __FUNCTION__, fsm, st);
105 
106  memcpy(hdr->magic, CPIO_NEWC_MAGIC, sizeof(hdr->magic));
107  SET_NUM_FIELD(hdr->inode, st->st_ino, field);
108  SET_NUM_FIELD(hdr->mode, st->st_mode, field);
109  SET_NUM_FIELD(hdr->uid, st->st_uid, field);
110  SET_NUM_FIELD(hdr->gid, st->st_gid, field);
111  SET_NUM_FIELD(hdr->nlink, st->st_nlink, field);
112  SET_NUM_FIELD(hdr->mtime, st->st_mtime, field);
113  SET_NUM_FIELD(hdr->filesize, st->st_size, field);
114 
115  dev = major((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMajor, dev, field);
116  dev = minor((unsigned)st->st_dev); SET_NUM_FIELD(hdr->devMinor, dev, field);
117  dev = major((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMajor, dev, field);
118  dev = minor((unsigned)st->st_rdev); SET_NUM_FIELD(hdr->rdevMinor, dev, field);
119 
120  len = strlen(fsm->path) + 1; SET_NUM_FIELD(hdr->namesize, len, field);
121  memcpy(hdr->checksum, "00000000", 8);
122 /*@-boundswrite@*/
123  memcpy(fsm->rdbuf + PHYS_HDR_SIZE, fsm->path, len);
124 /*@=boundswrite@*/
125 
126  /* XXX DWRITE uses rdnb for I/O length. */
127  fsm->rdnb = PHYS_HDR_SIZE + len;
128  rc = fsmNext(fsm, FSM_DWRITE);
129  if (!rc && fsm->rdnb != fsm->wrnb)
131  if (!rc)
132  rc = fsmNext(fsm, FSM_PAD);
133 
134  if (!rc && S_ISLNK(st->st_mode)) {
135 assert(fsm->lpath != NULL);
136  fsm->rdnb = strlen(fsm->lpath);
137  memcpy(fsm->rdbuf, fsm->lpath, fsm->rdnb);
138  rc = fsmNext(fsm, FSM_DWRITE);
139  if (!rc && fsm->rdnb != fsm->wrnb)
141  if (!rc)
142  rc = fsmNext(fsm, FSM_PAD);
143  }
144 
145  return rc;
146 }
147 
148 int cpioHeaderRead(FSM_t fsm, struct stat * st)
149  /*@modifies fsm, *st @*/
150 {
151  struct cpioCrcPhysicalHeader hdr;
152  int nameSize;
153  char * end;
154  int major, minor;
155  int rc = 0;
156 
157 if (_cpio_debug)
158 fprintf(stderr, " %s(%p, %p)\n", __FUNCTION__, fsm, st);
159 
160  fsm->wrlen = PHYS_HDR_SIZE;
161  rc = fsmNext(fsm, FSM_DREAD);
162  if (!rc && fsm->rdnb != fsm->wrlen)
163  rc = CPIOERR_READ_FAILED;
164  if (rc) return rc;
165 /*@-boundswrite@*/
166  memcpy(&hdr, fsm->wrbuf, fsm->rdnb);
167 /*@=boundswrite@*/
168 
169  if (strncmp(CPIO_CRC_MAGIC, hdr.magic, sizeof(CPIO_CRC_MAGIC)-1) &&
170  strncmp(CPIO_NEWC_MAGIC, hdr.magic, sizeof(CPIO_NEWC_MAGIC)-1))
171  return CPIOERR_BAD_MAGIC;
172 
173  GET_NUM_FIELD(hdr.inode, st->st_ino);
174  GET_NUM_FIELD(hdr.mode, st->st_mode);
175  GET_NUM_FIELD(hdr.uid, st->st_uid);
176  GET_NUM_FIELD(hdr.gid, st->st_gid);
177  GET_NUM_FIELD(hdr.nlink, st->st_nlink);
178  GET_NUM_FIELD(hdr.mtime, st->st_mtime);
179  GET_NUM_FIELD(hdr.filesize, st->st_size);
180 
181  GET_NUM_FIELD(hdr.devMajor, major);
182  GET_NUM_FIELD(hdr.devMinor, minor);
183  /*@-shiftimplementation@*/
184  st->st_dev = makedev(major, minor);
185  /*@=shiftimplementation@*/
186 
187  GET_NUM_FIELD(hdr.rdevMajor, major);
188  GET_NUM_FIELD(hdr.rdevMinor, minor);
189  /*@-shiftimplementation@*/
190  st->st_rdev = makedev(major, minor);
191  /*@=shiftimplementation@*/
192 
193  GET_NUM_FIELD(hdr.namesize, nameSize);
194  if (nameSize >= fsm->wrsize)
195  return CPIOERR_BAD_HEADER;
196 
197  { char * t = xmalloc(nameSize + 1);
198  fsm->wrlen = nameSize;
199  rc = fsmNext(fsm, FSM_DREAD);
200  if (!rc && fsm->rdnb != fsm->wrlen)
201  rc = CPIOERR_BAD_HEADER;
202  if (rc) {
203  t = _free(t);
204  fsm->path = NULL;
205  return rc;
206  }
207 /*@-boundswrite@*/
208  memcpy(t, fsm->wrbuf, fsm->rdnb);
209  t[nameSize] = '\0';
210 /*@=boundswrite@*/
211  fsm->path = t;
212  }
213 
214  if (S_ISLNK(st->st_mode)) {
215  rc = fsmNext(fsm, FSM_POS);
216  if (rc) return rc;
217  fsm->wrlen = st->st_size;
218  rc = fsmNext(fsm, FSM_DREAD);
219  if (!rc && fsm->rdnb != fsm->wrlen)
220  rc = CPIOERR_READ_FAILED;
221  if (rc) return rc;
222 /*@-boundswrite@*/
223  fsm->wrbuf[st->st_size] = '\0';
224 /*@=boundswrite@*/
225  fsm->lpath = xstrdup(fsm->wrbuf);
226  }
227 
228 if (_cpio_debug)
229 fprintf(stderr, "\t %06o%3d (%4d,%4d)%10d %s\n\t-> %s\n",
230  (unsigned)st->st_mode, (int)st->st_nlink,
231  (int)st->st_uid, (int)st->st_gid, (int)st->st_size,
232  (fsm->path ? fsm->path : ""), (fsm->lpath ? fsm->lpath : ""));
233 
234  return rc;
235 }
236 
237 const char * cpioStrerror(int rc)
238 {
239  static char msg[256];
240  char *s;
241  int l, myerrno = errno;
242 
243  strcpy(msg, "cpio: ");
244  /*@-branchstate@*/
245  switch (rc) {
246  default:
247  s = msg + strlen(msg);
248  sprintf(s, _("(error 0x%x)"), (unsigned)rc);
249  s = NULL;
250  break;
251  case CPIOERR_BAD_MAGIC: s = _("Bad magic"); break;
252  case CPIOERR_BAD_HEADER: s = _("Bad/unreadable header");break;
253 
254  case CPIOERR_OPEN_FAILED: s = "open"; break;
255  case CPIOERR_CHMOD_FAILED: s = "chmod"; break;
256  case CPIOERR_CHOWN_FAILED: s = "chown"; break;
257  case CPIOERR_WRITE_FAILED: s = "write"; break;
258  case CPIOERR_UTIME_FAILED: s = "utime"; break;
259  case CPIOERR_UNLINK_FAILED: s = "unlink"; break;
260  case CPIOERR_RENAME_FAILED: s = "rename"; break;
261  case CPIOERR_SYMLINK_FAILED: s = "symlink"; break;
262  case CPIOERR_STAT_FAILED: s = "stat"; break;
263  case CPIOERR_LSTAT_FAILED: s = "lstat"; break;
264  case CPIOERR_MKDIR_FAILED: s = "mkdir"; break;
265  case CPIOERR_RMDIR_FAILED: s = "rmdir"; break;
266  case CPIOERR_MKNOD_FAILED: s = "mknod"; break;
267  case CPIOERR_MKFIFO_FAILED: s = "mkfifo"; break;
268  case CPIOERR_LINK_FAILED: s = "link"; break;
269  case CPIOERR_READLINK_FAILED: s = "readlink"; break;
270  case CPIOERR_READ_FAILED: s = "read"; break;
271  case CPIOERR_COPY_FAILED: s = "copy"; break;
272  case CPIOERR_LSETFCON_FAILED: s = "lsetfilecon"; break;
273 
274  case CPIOERR_HDR_SIZE: s = _("Header size too big"); break;
275  case CPIOERR_UNKNOWN_FILETYPE: s = _("Unknown file type"); break;
276  case CPIOERR_MISSING_HARDLINK: s = _("Missing hard link(s)"); break;
277  case CPIOERR_DIGEST_MISMATCH: s = _("File digest mismatch"); break;
278  case CPIOERR_INTERNAL: s = _("Internal error"); break;
279  case CPIOERR_UNMAPPED_FILE: s = _("Archive file not in header"); break;
280  case CPIOERR_ENOENT: s = strerror(ENOENT); break;
281  case CPIOERR_ENOTEMPTY: s = strerror(ENOTEMPTY); break;
282  }
283  /*@=branchstate@*/
284 
285  l = sizeof(msg) - strlen(msg) - 1;
286  if (s != NULL) {
287  if (l > 0) strncat(msg, s, l);
288  l -= strlen(s);
289  }
290  /*@-branchstate@*/
291  if ((rc & CPIOERR_CHECK_ERRNO) && myerrno) {
292  s = _(" failed - ");
293  if (l > 0) strncat(msg, s, l);
294  l -= strlen(s);
295  if (l > 0) strncat(msg, strerror(myerrno), l);
296  }
297  /*@=branchstate@*/
298  return msg;
299 }