rpm  5.4.14
tar.c
Go to the documentation of this file.
1 
6 #undef JBJ_WRITEPAD
7 
8 #include "system.h"
9 
10 #include <rpmio.h>
11 #include <ugid.h>
12 #include <tar.h>
13 #define _IOSM_INTERNAL
14 #include <iosm.h>
15 
16 #include "debug.h"
17 
18 /*@access IOSM_t @*/
19 
20 /*@unchecked@*/
21 int _tar_debug = 0;
22 
23 /*@unchecked@*/
24 static int nochksum = 0;
25 
34 static int strntoul(const char *str, /*@null@*/ /*@out@*/char **endptr,
35  int base, size_t num)
36  /*@modifies *endptr @*/
37  /*@requires maxSet(endptr) >= 0 @*/
38 {
39  char * buf, * end;
40  unsigned long ret;
41 
42  buf = (char *) alloca(num + 1);
43  strncpy(buf, str, num);
44  buf[num] = '\0';
45 
46  ret = strtoul(buf, &end, base);
47  if (endptr != NULL) {
48  if (*end != '\0')
49  *endptr = ((char *)str) + (end - buf); /* XXX discards const */
50  else
51  *endptr = ((char *)str) + strlen(buf);
52  }
53 
54  return ret;
55 }
56 
57 /* Translate archive read/write ssize_t return for iosmStage(). */
58 #define _IOSMRC(_rc) \
59  if ((_rc) <= 0) return ((_rc) ? (int) -rc : IOSMERR_HDR_TRAILER)
60 
61 static ssize_t tarRead(void * _iosm, void * buf, size_t count)
62  /*@globals fileSystem @*/
63  /*@modifies _iosm, *buf, fileSystem @*/
64 {
65  IOSM_t iosm = (IOSM_t) _iosm;
66  char * t = (char *) buf;
67  size_t nb = 0;
68 
69 if (_tar_debug)
70 fprintf(stderr, "\ttarRead(%p, %p[%u])\n", iosm, buf, (unsigned)count);
71 
72  while (count > 0) {
73  size_t rc;
74 
75  /* Read next tar block. */
76  iosm->wrlen = count;
77  rc = _iosmNext(iosm, IOSM_DREAD);
78  if (!rc && iosm->rdnb != iosm->wrlen)
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 
99 static ssize_t tarHeaderReadName(void * _iosm, size_t len,
100  /*@out@*/ const char ** fnp)
101  /*@globals fileSystem, internalState @*/
102  /*@modifies _iosm, *fnp, fileSystem, internalState @*/
103 {
104  IOSM_t iosm = (IOSM_t) _iosm;
105  size_t nb = len + 1;
106  char * t = (char *) xmalloc(nb);
107  ssize_t rc = tarRead(iosm, t, nb);
108 
109  if (rc > 0) /* success */
110  t[rc] = '\0';
111  else /* failure or EOF */
112  t = _free(t);
113  if (fnp != NULL)
114  *fnp = t;
115 
116 if (_tar_debug)
117 fprintf(stderr, "\ttarHeaderReadName(%p, %u, %p) rc 0x%x\n", _iosm, (unsigned)len, fnp, (unsigned)rc);
118 
119  return rc;
120 }
121 
122 int tarHeaderRead(void * _iosm, struct stat * st)
123  /*@modifies _iosm, *st @*/
124 {
125  IOSM_t iosm = (IOSM_t) _iosm;
126  tarHeader hdr = (tarHeader) iosm->wrbuf;
127  char * t;
128  size_t nb;
129  int major, minor;
130  ssize_t rc = 0;
131  int zblk = 0;
132 
133 if (_tar_debug)
134 fprintf(stderr, " tarHeaderRead(%p, %p)\n", iosm, st);
135 
136 top:
137  do {
138  /* Read next header. */
139  rc = tarRead(_iosm, hdr, TAR_BLOCK_SIZE);
140  _IOSMRC(rc);
141 
142  /* Look for end-of-archive, i.e. 2 (or more) zero blocks. */
143  if (hdr->name[0] == '\0' && hdr->checksum[0] == '\0') {
144  if (++zblk == 2)
145  return IOSMERR_HDR_TRAILER;
146  }
147  } while (zblk > 0);
148 
149  /* Verify header checksum. */
150  { const unsigned char * hp = (const unsigned char *) hdr;
151  char checksum[8];
152  char hdrchecksum[8];
153  long sum = 0;
154  int i;
155 
156  memcpy(hdrchecksum, hdr->checksum, sizeof(hdrchecksum));
157  memset(hdr->checksum, (int)' ', sizeof(hdr->checksum));
158 
159  for (i = 0; i < TAR_BLOCK_SIZE; i++)
160  sum += (long)*hp++;
161 
162  memset(checksum, (int)' ', sizeof(checksum));
163  sprintf(checksum, "%06o", (unsigned) (sum & 07777777));
164 if (_tar_debug)
165 fprintf(stderr, "\tmemcmp(\"%s\", \"%s\", %u)\n", hdrchecksum, checksum, (unsigned)sizeof(hdrchecksum));
166  if (memcmp(hdrchecksum, checksum, sizeof(hdrchecksum)))
167  if (!nochksum)
168  return IOSMERR_BAD_HEADER;
169 
170  }
171 
172  /* Verify header magic. */
173  if (strncmp(hdr->magic, TAR_MAGIC, sizeof(TAR_MAGIC)-1))
174  return IOSMERR_BAD_MAGIC;
175 
176  /* Convert header to stat(2). */
177  st->st_size = strntoul(hdr->filesize, NULL, 8, sizeof(hdr->filesize));
178 
179  st->st_nlink = 1;
180  st->st_mode = strntoul(hdr->mode, NULL, 8, sizeof(hdr->mode));
181  st->st_mode &= ~S_IFMT;
182  switch (hdr->typeflag) {
183  case 'x': /* Extended header referring to next file in archive. */
184  case 'g': /* Global extended header. */
185  default:
186  break;
187  case '7': /* reserved (contiguous files?) */
188  case '\0': /* (ancient) regular file */
189  case '0': /* regular file */
190  st->st_mode |= S_IFREG;
191  break;
192  case '1': /* hard link */
193  st->st_mode |= S_IFREG;
194 #ifdef DYING
195  st->st_nlink++;
196 #endif
197  break;
198  case '2': /* symbolic link */
199  st->st_mode |= S_IFLNK;
200  break;
201  case '3': /* character special */
202  st->st_mode |= S_IFCHR;
203  break;
204  case '4': /* block special */
205  st->st_mode |= S_IFBLK;
206  break;
207  case '5': /* directory */
208  st->st_mode |= S_IFDIR;
209  st->st_nlink++;
210  break;
211  case '6': /* FIFO special */
212  st->st_mode |= S_IFIFO;
213  break;
214 #ifdef REFERENCE
215  case 'A': /* Solaris ACL */
216  case 'E': /* Solaris XATTR */
217  case 'I': /* Inode only, as in 'star' */
218  case 'X': /* POSIX 1003.1-2001 eXtended (VU version) */
219  case 'D': /* GNU dumpdir (with -G, --incremental) */
220  case 'M': /* GNU multivol (with -M, --multi-volume) */
221  case 'N': /* GNU names */
222  case 'S': /* GNU sparse (with -S, --sparse) */
223  case 'V': /* GNU tape/volume header (with -Vlll, --label=lll) */
224 #endif
225  case 'K': /* GNU long (>100 chars) link name */
226  rc = tarHeaderReadName(iosm, st->st_size, &iosm->lpath);
227  _IOSMRC(rc);
228  goto top;
229  /*@notreached@*/ break;
230  case 'L': /* GNU long (>100 chars) file name */
231  rc = tarHeaderReadName(iosm, st->st_size, &iosm->path);
232  _IOSMRC(rc);
233  goto top;
234  /*@notreached@*/ break;
235  }
236 
237  st->st_uid = strntoul(hdr->uid, NULL, 8, sizeof(hdr->uid));
238  st->st_gid = strntoul(hdr->gid, NULL, 8, sizeof(hdr->gid));
239  st->st_mtime = strntoul(hdr->mtime, NULL, 8, sizeof(hdr->mtime));
240  st->st_ctime = st->st_atime = st->st_mtime; /* XXX compat? */
241 
242  major = strntoul(hdr->devMajor, NULL, 8, sizeof(hdr->devMajor));
243  minor = strntoul(hdr->devMinor, NULL, 8, sizeof(hdr->devMinor));
244  /*@-shiftimplementation@*/
245  st->st_dev = Makedev(major, minor);
246  /*@=shiftimplementation@*/
247  st->st_rdev = st->st_dev; /* XXX compat? */
248 
249  /* char prefix[155]; */
250  /* char padding[12]; */
251 
252  /* Read short file name. */
253  if (iosm->path == NULL && hdr->name[0] != '\0') {
254  nb = strlen(hdr->name);
255  t = (char *) xmalloc(nb + 1);
256  memcpy(t, hdr->name, nb);
257  t[nb] = '\0';
258  iosm->path = t;
259  }
260 
261  /* Read short link name. */
262  if (iosm->lpath == NULL && hdr->linkname[0] != '\0') {
263  nb = strlen(hdr->linkname);
264  t = (char *) xmalloc(nb + 1);
265  memcpy(t, hdr->linkname, nb);
266  t[nb] = '\0';
267  iosm->lpath = t;
268  }
269 
270  rc = 0;
271 
272 if (_tar_debug)
273 fprintf(stderr, "\t %06o%3d (%4d,%4d)%12lu %s\n\t-> %s\n",
274  (unsigned)st->st_mode, (int)st->st_nlink,
275  (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
276  (iosm->path ? iosm->path : ""), (iosm->lpath ? iosm->lpath : ""));
277 
278  return (int) rc;
279 }
280 
281 static ssize_t tarWrite(void * _iosm, const void *buf, size_t count)
282  /*@globals fileSystem @*/
283  /*@modifies _iosm, fileSystem @*/
284 {
285  IOSM_t iosm = (IOSM_t) _iosm;
286  const char * s = (const char *) buf;
287  size_t nb = 0;
288  size_t rc;
289 
290 if (_tar_debug)
291 fprintf(stderr, "\t tarWrite(%p, %p[%u])\n", iosm, buf, (unsigned)count);
292 
293  while (count > 0) {
294 
295  /* XXX DWRITE uses rdnb for I/O length. */
296  iosm->rdnb = count;
297  if (s != iosm->rdbuf)
298  memmove(iosm->rdbuf, s + nb, iosm->rdnb);
299 
300  rc = _iosmNext(iosm, IOSM_DWRITE);
301  if (!rc && iosm->rdnb != iosm->wrnb)
303  if (rc) return -rc;
304 
305  nb += iosm->rdnb;
306  count -= iosm->rdnb;
307  }
308 
309 #if defined(JBJ_WRITEPAD)
310  /* Pad to next block boundary. */
311  if ((rc = _iosmNext(iosm, IOSM_PAD)) != 0) return rc;
312 #endif
313 
314  return nb;
315 }
316 
323 static ssize_t tarHeaderWriteName(void * _iosm, const char * path)
324  /*@globals fileSystem, internalState @*/
325  /*@modifies _iosm, fileSystem, internalState @*/
326 {
327  ssize_t rc = tarWrite(_iosm, path, strlen(path));
328 
329 #if !defined(JBJ_WRITEPAD)
330  if (rc >= 0) {
331  IOSM_t iosm = (IOSM_t) _iosm;
332  rc = _iosmNext(iosm, IOSM_PAD);
333  if (rc) rc = -rc;
334  }
335 #endif
336 
337 if (_tar_debug)
338 fprintf(stderr, "\ttarHeaderWriteName(%p, %s) rc 0x%x\n", _iosm, path, (unsigned)rc);
339 
340  return rc;
341 }
342 
350 static ssize_t tarHeaderWriteBlock(void * _iosm, struct stat * st, tarHeader hdr)
351  /*@globals fileSystem, internalState @*/
352  /*@modifies _iosm, hdr, fileSystem, internalState @*/
353 {
354  IOSM_t iosm = (IOSM_t) _iosm;
355  const char * path = (iosm && iosm->path ? iosm->path : "");
356  ssize_t rc;
357 
358 if (_tar_debug)
359 fprintf(stderr, "\ttarHeaderWriteBlock(%p, %p) type %c\n", iosm, hdr, hdr->typeflag);
360 if (_tar_debug)
361 fprintf(stderr, "\t %06o%3d (%4d,%4d)%12lu %s\n",
362  (unsigned)st->st_mode, (int)st->st_nlink,
363  (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
364  path);
365 
366 
368 
369  /* Calculate header checksum. */
370  { const unsigned char * hp = (const unsigned char *) hdr;
371  long sum = 0;
372  int i;
373 
374  memset(hdr->checksum, (int)' ', sizeof(hdr->checksum));
375  for (i = 0; i < TAR_BLOCK_SIZE; i++)
376  sum += (long) *hp++;
377  sprintf(hdr->checksum, "%06o", (unsigned)(sum & 07777777));
378 if (_tar_debug)
379 fprintf(stderr, "\thdrchksum \"%s\"\n", hdr->checksum);
380  }
381 
382  rc = tarWrite(_iosm, hdr, TAR_BLOCK_SIZE);
383 
384  return rc;
385 }
386 
387 int tarHeaderWrite(void * _iosm, struct stat * st)
388 {
389  IOSM_t iosm = (IOSM_t) _iosm;
390 /*@observer@*/
391  static const char * llname = "././@LongLink";
392  tarHeader hdr = (tarHeader) iosm->rdbuf;
393  const char * path = (iosm && iosm->path ? iosm->path : "");
394  const char * lpath = (iosm && iosm->lpath ? iosm->lpath : "");
395  const char * s;
396  dev_t dev;
397  size_t nb;
398  ssize_t rc = 0;
399 
400 if (_tar_debug)
401 fprintf(stderr, " tarHeaderWrite(%p, %p)\n", iosm, st);
402 
403  nb = strlen(path);
404  if (nb > sizeof(hdr->name)) {
405  memset(hdr, 0, sizeof(*hdr));
406  strcpy(hdr->name, llname);
407  sprintf(hdr->mode, "%07o", 0);
408  sprintf(hdr->uid, "%07o", 0);
409  sprintf(hdr->gid, "%07o", 0);
410  sprintf(hdr->filesize, "%011o", (unsigned) (nb & 037777777777));
411  sprintf(hdr->mtime, "%011o", 0);
412  hdr->typeflag = 'L';
413  strncpy(hdr->uname, "root", sizeof(hdr->uname));
414  strncpy(hdr->gname, "root", sizeof(hdr->gname));
415  rc = tarHeaderWriteBlock(iosm, st, hdr);
416  _IOSMRC(rc);
417  rc = tarHeaderWriteName(iosm, path);
418  _IOSMRC(rc);
419  }
420 
421  if (lpath && lpath[0] != '0') {
422  nb = strlen(lpath);
423  if (nb > sizeof(hdr->name)) {
424  memset(hdr, 0, sizeof(*hdr));
425  strncpy(hdr->linkname, llname, sizeof(hdr->linkname));
426  sprintf(hdr->mode, "%07o", 0);
427  sprintf(hdr->uid, "%07o", 0);
428  sprintf(hdr->gid, "%07o", 0);
429  sprintf(hdr->filesize, "%011o", (unsigned) (nb & 037777777777));
430  sprintf(hdr->mtime, "%011o", 0);
431  hdr->typeflag = 'K';
432  strncpy(hdr->uname, "root", sizeof(hdr->uname));
433  strncpy(hdr->gname, "root", sizeof(hdr->gname));
434  rc = tarHeaderWriteBlock(iosm, st, hdr);
435  _IOSMRC(rc);
436  rc = tarHeaderWriteName(iosm, path);
437  _IOSMRC(rc);
438  }
439  }
440 
441  memset(hdr, 0, sizeof(*hdr));
442 
443  strncpy(hdr->name, path, sizeof(hdr->name));
444 
445  if (lpath && lpath[0] != '\0')
446  strncpy(hdr->linkname, lpath, sizeof(hdr->linkname));
447 
448  sprintf(hdr->mode, "%07o", (unsigned int)(st->st_mode & 00007777));
449  sprintf(hdr->uid, "%07o", (unsigned int)(st->st_uid & 07777777));
450  sprintf(hdr->gid, "%07o", (unsigned int)(st->st_gid & 07777777));
451 
452  sprintf(hdr->filesize, "%011o", (unsigned) (st->st_size & 037777777777));
453  sprintf(hdr->mtime, "%011o", (unsigned) (st->st_mtime & 037777777777));
454 
455  hdr->typeflag = '0'; /* XXX wrong! */
456  if (S_ISLNK(st->st_mode))
457  hdr->typeflag = '2';
458  else if (S_ISCHR(st->st_mode))
459  hdr->typeflag = '3';
460  else if (S_ISBLK(st->st_mode))
461  hdr->typeflag = '4';
462  else if (S_ISDIR(st->st_mode))
463  hdr->typeflag = '5';
464  else if (S_ISFIFO(st->st_mode))
465  hdr->typeflag = '6';
466 #ifdef WHAT2DO
467  else if (S_ISSOCK(st->st_mode))
468  hdr->typeflag = '?';
469 #endif
470  else if (S_ISREG(st->st_mode))
471  hdr->typeflag = (lpath && lpath[0] != '\0' ? '1' : '0');
472 
473  /* XXX FIXME: map uname/gname from uid/gid. */
474  s = uidToUname(st->st_uid);
475  if (s == NULL) s = "root";
476  strncpy(hdr->uname, s, sizeof(hdr->uname));
477  s = gidToGname(st->st_gid);
478  if (s == NULL) s = "root";
479  strncpy(hdr->gname, s, sizeof(hdr->gname));
480 
481  /* XXX W2DO? st_dev or st_rdev? (likely st->st_rdev) */
482  dev = major((unsigned)st->st_dev);
483  sprintf(hdr->devMajor, "%07o", (unsigned) (dev & 07777777));
484  dev = minor((unsigned)st->st_dev);
485  sprintf(hdr->devMinor, "%07o", (unsigned) (dev & 07777777));
486 
487  rc = tarHeaderWriteBlock(iosm, st, hdr);
488  _IOSMRC(rc);
489  rc = 0;
490 
491 #if !defined(JBJ_WRITEPAD)
492  /* XXX Padding is unnecessary but shouldn't hurt. */
493  rc = _iosmNext(iosm, IOSM_PAD);
494 #endif
495 
496  return (int) rc;
497 }
498 
499 int tarTrailerWrite(void * _iosm)
500 {
501  IOSM_t iosm = (IOSM_t) _iosm;
502  ssize_t rc = 0;
503 
504 if (_tar_debug)
505 fprintf(stderr, " tarTrailerWrite(%p)\n", iosm);
506 
507  /* Pad up to 20 blocks (10Kb) of zeroes. */
508  iosm->blksize *= 20;
509 #if defined(JBJ_WRITEPAD)
510  rc = tarWrite(iosm, NULL, 0); /* XXX _iosmNext(iosm, IOSM_PAD) */
511 #else
512  rc = _iosmNext(iosm, IOSM_PAD);
513 #endif
514  iosm->blksize /= 20;
515 #if defined(JBJ_WRITEPAD)
516  _IOSMRC(rc);
517 #endif
518 
519  return (int) -rc;
520 }
#define TAR_VERSION
Definition: tar.h:15
int tarTrailerWrite(void *_iosm)
Write cpio trailer to payload.
Definition: tar.c:499
char devMajor[8]
Definition: tar.h:41
static int nochksum
Definition: tar.c:24
static int strntoul(const char *str, char **endptr, int base, size_t num)
Convert string to unsigned integer (with buffer size check).
Definition: tar.c:34
char uid[8]
Definition: tar.h:30
static ssize_t tarWrite(void *_iosm, const void *buf, size_t count)
Definition: tar.c:281
static ssize_t tarHeaderWriteName(void *_iosm, const char *path)
Write long file/link name into tar archive.
Definition: tar.c:323
const char * lpath
Definition: iosm.h:222
#define TAR_MAGIC
Definition: tar.h:14
static char *size_t nb
fgets(3) analogue that reads \ continuations.
Definition: macro.c:409
static ssize_t tarHeaderReadName(void *_iosm, size_t len, const char **fnp)
Read long file/link name from tar archive.
Definition: tar.c:99
int rc
Definition: poptALL.c:670
const char * path
Definition: iosm.h:220
char * gidToGname(gid_t gid)
Definition: ugid.c:171
#define Makedev(x, y)
makedev() on QNX takes three parameters the additional one (first place) specifies the node for QNET ...
Definition: system.h:758
#define S_ISLNK(mode)
Definition: system.h:651
char mode[8]
Definition: tar.h:29
char filesize[12]
Definition: tar.h:32
#define S_ISSOCK(mode)
Definition: system.h:655
Tar archive header information.
Definition: tar.h:27
sprintf(t," (%u)",(unsigned) dig->nbytes)
ret
Definition: macro.c:387
size_t wrnb
Definition: iosm.h:243
char * alloca()
memset(_r, 0, sizeof(*_r))
int count
Definition: rpmdb-py.c:157
size_t rdnb
Definition: iosm.h:235
char gid[8]
Definition: tar.h:31
char mtime[12]
Definition: tar.h:33
fprintf(stderr,"--> %s(%p,%p,%p) sig %p sigp %p\n", __FUNCTION__, dig, t, rsactx, sig, sigp)
#define _IOSMRC(_rc)
Definition: tar.c:58
char devMinor[8]
Definition: tar.h:42
int(* _iosmNext)(IOSM_t iosm, iosmFileStage nstage)
Vector to iosmNext.
Definition: iosm.c:83
Structures used for tar(1) archives.
struct tarHeader_s * tarHeader
Definition: tar.h:11
spectags st
Definition: spec.c:741
static ssize_t tarRead(void *_iosm, void *buf, size_t count)
Definition: tar.c:61
char * wrbuf
Definition: iosm.h:238
size_t wrlen
Definition: iosm.h:242
char magic[6]
Definition: tar.h:37
const char * s
Definition: poptALL.c:734
char gname[32]
Definition: tar.h:40
char * t
Definition: rpmds.c:2716
Definition: iosm.h:161
char * path
Definition: poptALL.c:744
char * stpcpy(char *dest, const char *src)
if(__progname==NULL)
Definition: poptALL.c:683
struct iosm_s * IOSM_t
File state machine data.
Definition: iosm.h:17
char checksum[8]
Definition: tar.h:34
char * uidToUname(uid_t uid)
Definition: ugid.c:135
#define TAR_BLOCK_SIZE
Definition: tar.h:17
char * rdbuf
Definition: iosm.h:230
unsigned blksize
Definition: iosm.h:308
return NULL
Definition: poptALL.c:613
char linkname[100]
Definition: tar.h:36
int _tar_debug
Definition: tar.c:21
static void
Print copy of spec file, filling in Group/Description/Summary from specspo.
Definition: spec.c:737
#define minor(dev)
Definition: system.h:141
char * buf
Parse (and execute) macro undefinition.
Definition: macro.c:703
File state machine to handle archive I/O and system call&#39;s.
#define xmalloc
Definition: system.h:32
static ssize_t tarHeaderWriteBlock(void *_iosm, struct stat *st, tarHeader hdr)
Write tar header block with checksum into tar archive.
Definition: tar.c:350
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
int tarHeaderRead(void *_iosm, struct stat *st)
Read tar header from payload.
Definition: tar.c:122
int i
Definition: spec.c:743
char typeflag
Definition: tar.h:35
strncpy(sbuf, f, flen)
char uname[32]
Definition: tar.h:39
int tarHeaderWrite(void *_iosm, struct stat *st)
Write tar header to payload.
Definition: tar.c:387
File name and stat information.
Definition: iosm.h:218
#define major(dev)
Definition: system.h:140
char name[100]
Definition: tar.h:28
int len
Definition: rpmdb-py.c:119