rpm  5.4.14
ar.c
Go to the documentation of this file.
1 
6 #undef JBJ_WRITEPAD
7 
8 #include "system.h"
9 
10 #include <rpmio_internal.h> /* XXX fdGetCpioPos writing AR_MAGIC */
11 
12 #include <rpmmacro.h>
13 #include <ugid.h>
14 #include <ar.h>
15 #define _IOSM_INTERNAL
16 #include <iosm.h>
17 
18 #include "debug.h"
19 
20 /*@access IOSM_t @*/
21 
22 /*@unchecked@*/
23 int _ar_debug = 0;
24 
33 static int strntoul(const char *str, /*@null@*/ /*@out@*/char **endptr,
34  int base, size_t num)
35  /*@modifies *endptr @*/
36 {
37  char * buf, * end;
38  unsigned long ret;
39 
40  buf = (char *) alloca(num + 1);
41  strncpy(buf, str, num);
42  buf[num] = '\0';
43 
44  ret = strtoul(buf, &end, base);
45  if (endptr != NULL) {
46  if (*end != '\0')
47  *endptr = ((char *)str) + (end - buf); /* XXX discards const */
48  else
49  *endptr = ((char *)str) + strlen(buf);
50  }
51 
52  return ret;
53 }
54 
55 /* Translate archive read/write ssize_t return for iosmStage(). */
56 #define _IOSMRC(_rc) \
57  if ((_rc) <= 0) return ((_rc) ? (int) -rc : IOSMERR_HDR_TRAILER)
58 
59 static ssize_t arRead(void * _iosm, void * buf, size_t count)
60  /*@globals fileSystem @*/
61  /*@modifies _iosm, *buf, fileSystem @*/
62 {
63  IOSM_t iosm = (IOSM_t) _iosm;
64  char * t = (char *) buf;
65  size_t nb = 0;
66  size_t rc;
67 
68 if (_ar_debug)
69 fprintf(stderr, "\t arRead(%p, %p[%u])\n", iosm, buf, (unsigned)count);
70 
71  while (count > 0) {
72 
73  /* Read next ar block. */
74  iosm->wrlen = count;
75  rc = _iosmNext(iosm, IOSM_DREAD);
76  if (!rc && iosm->rdnb != iosm->wrlen) {
77  if (iosm->rdnb == 0) return -IOSMERR_HDR_TRAILER; /* EOF */
79  }
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 
92 int arHeaderRead(void * _iosm, struct stat * st)
93  /*@modifies _iosm, *st @*/
94 {
95  IOSM_t iosm = (IOSM_t) _iosm;
96  arHeader hdr = (arHeader) iosm->wrbuf;
97  ssize_t rc = 0;
98 
99 if (_ar_debug)
100 fprintf(stderr, " arHeaderRead(%p, %p)\n", iosm, st);
101 
102  /* XXX Read AR_MAGIC to beginning of ar(1) archive. */
103  if (fdGetCpioPos(iosm->cfd) == 0) {
104  rc = arRead(iosm, iosm->wrbuf, sizeof(AR_MAGIC)-1);
105  _IOSMRC(rc);
106 
107  /* Verify archive magic. */
108  if (strncmp(iosm->wrbuf, AR_MAGIC, sizeof(AR_MAGIC)-1))
109  return IOSMERR_BAD_MAGIC;
110  }
111 
112 top:
113  /* Make sure block aligned. */
114  rc = _iosmNext(iosm, IOSM_POS);
115  if (rc) return (int) rc;
116 
117  rc = arRead(iosm, hdr, sizeof(*hdr));
118  _IOSMRC(rc);
119 if (_ar_debug)
120 fprintf(stderr, "==> %p[%u] \"%.*s\"\n", hdr, (unsigned)rc, (int)sizeof(*hdr)-2, (char *)hdr);
121 
122  /* Verify header marker. */
123  if (strncmp(hdr->marker, AR_MARKER, sizeof(AR_MARKER)-1))
124  return IOSMERR_BAD_MAGIC;
125 
126  st->st_size = strntoul(hdr->filesize, NULL, 10, sizeof(hdr->filesize));
127 
128  /* Special ar(1) archive members. */
129  if (hdr->name[0] == '/') {
130  /* GNU: on "//": Read long member name string table. */
131  if (hdr->name[1] == '/' && hdr->name[2] == ' ') {
132  char * t;
133  size_t i;
134 
135  rc = arRead(iosm, iosm->wrbuf, st->st_size);
136  _IOSMRC(rc);
137 
138  iosm->wrbuf[rc] = '\0';
139  iosm->lmtab = t = xstrdup(iosm->wrbuf);
140  iosm->lmtablen = rc;
141  iosm->lmtaboff = 0;
142 
143  for (i = 1; i < iosm->lmtablen; i++) {
144  t++;
145  if (t[0] != '\n') continue;
146  t[0] = '\0';
147  /* GNU: trailing '/' to permit file names with trailing ' '. */
148  if (t[-1] == '/') t[-1] = '\0';
149  }
150  goto top;
151  }
152  /* GNU: on "/": Skip symbol table. */
153  if (hdr->name[1] == ' ') {
154  rc = arRead(iosm, iosm->wrbuf, st->st_size);
155  _IOSMRC(rc);
156  goto top;
157  }
158  /* GNU: on "/123": Read "123" offset to substitute long member name. */
159  if (xisdigit((int)hdr->name[1])) {
160  char * te = NULL;
161  int i = strntoul(&hdr->name[1], &te, 10, sizeof(hdr->name)-2);
162  if (*te == ' ' && iosm->lmtab != NULL && i < (int)iosm->lmtablen)
163  iosm->path = xstrdup(iosm->lmtab + i);
164  }
165  } else
166  if (hdr->name[0] != ' ') { /* Short member name. */
167  size_t nb = sizeof(hdr->name);
168  char t[sizeof(hdr->name)+1];
169  memcpy(t, hdr->name, nb);
170  t[nb] = '\0';
171  while (nb > 0 && t[nb-1] == ' ')
172  t[--nb] = '\0';
173  /* GNU: trailing '/' to permit file names with trailing ' '. */
174  if (nb > 0 && t[nb - 1] == '/')
175  t[--nb] = '\0';
176  iosm->path = xstrdup(t);
177  }
178 
179  st->st_mtime = strntoul(hdr->mtime, NULL, 10, sizeof(hdr->mtime));
180  st->st_ctime = st->st_atime = st->st_mtime;
181 
182  st->st_uid = strntoul(hdr->uid, NULL, 10, sizeof(hdr->uid));
183  st->st_gid = strntoul(hdr->gid, NULL, 10, sizeof(hdr->gid));
184 
185  st->st_mode = strntoul(hdr->mode, NULL, 8, sizeof(hdr->mode));
186 
187  st->st_nlink = 1;
188  rc = 0;
189 
190 if (_ar_debug)
191 fprintf(stderr, "\t %06o%3d (%4d,%4d)%12lu %s\n",
192  (unsigned)st->st_mode, (int)st->st_nlink,
193  (int)st->st_uid, (int)st->st_gid, (unsigned long)st->st_size,
194  (iosm->path ? iosm->path : ""));
195 
196  return (int) rc;
197 }
198 
199 static ssize_t arWrite(void * _iosm, const void *buf, size_t count)
200  /*@globals fileSystem @*/
201  /*@modifies _iosm, fileSystem @*/
202 {
203  IOSM_t iosm =(IOSM_t) _iosm;
204  const char * s = (const char *) buf;
205  size_t nb = 0;
206  size_t rc;
207 
208 if (_ar_debug)
209 fprintf(stderr, "\tarWrite(%p, %p[%u])\n", iosm, buf, (unsigned)count);
210 
211  while (count > 0) {
212 
213  /* XXX DWRITE uses rdnb for I/O length. */
214  iosm->rdnb = count;
215  if (s != iosm->rdbuf)
216  memmove(iosm->rdbuf, s + nb, iosm->rdnb);
217 
218  rc = _iosmNext(iosm, IOSM_DWRITE);
219  if (!rc && iosm->rdnb != iosm->wrnb)
221  if (rc) return -rc;
222 
223  nb += iosm->rdnb;
224  count -= iosm->rdnb;
225  }
226 
227 #if defined(JBJ_WRITEPAD)
228  /* Pad to next block boundary. */
229  if ((rc = _iosmNext(iosm, IOSM_PAD)) != 0) return -rc;
230 #endif
231 
232  return nb;
233 }
234 
235 int arHeaderWrite(void * _iosm, struct stat * st)
236 {
237  IOSM_t iosm = (IOSM_t) _iosm;
238  arHeader hdr = (arHeader) iosm->rdbuf;
239  const char * path = (iosm && iosm->path ? iosm->path : "");
240  size_t nb;
241  ssize_t rc = 0;
242 
243 if (_ar_debug)
244 fprintf(stderr, " arHeaderWrite(%p, %p)\n", iosm, st);
245 
246  /* At beginning of ar(1) archive, write magic and long member table. */
247  if (fdGetCpioPos(iosm->cfd) == 0) {
248  /* Write ar(1) magic. */
249  rc = arWrite(iosm, AR_MAGIC, sizeof(AR_MAGIC)-1);
250  _IOSMRC(rc);
251  /* GNU: on "//": Write long member name string table. */
252  if (iosm->lmtab != NULL) {
253  memset(hdr, (int) ' ', sizeof(*hdr));
254  hdr->name[0] = '/';
255  hdr->name[1] = '/';
256  sprintf(hdr->filesize, "%-10d", (unsigned) (iosm->lmtablen & 037777777777));
257  strncpy(hdr->marker, AR_MARKER, sizeof(AR_MARKER)-1);
258 
259  rc = arWrite(iosm, hdr, sizeof(*hdr));
260  _IOSMRC(rc);
261  rc = arWrite(iosm, iosm->lmtab, iosm->lmtablen);
262  _IOSMRC(rc);
263 #if !defined(JBJ_WRITEPAD)
264  rc = _iosmNext(iosm, IOSM_PAD);
265  if (rc) return (int)rc;
266 #endif
267  }
268  }
269 
270  memset(hdr, (int)' ', sizeof(*hdr));
271 
272  nb = strlen(path);
273  if (nb >= sizeof(hdr->name)) {
274  const char * t;
275  const char * te;
276 assert(iosm->lmtab != NULL);
277  t = iosm->lmtab + iosm->lmtaboff;
278  te = strchr(t, '\n');
279  /* GNU: on "/123": Write "/123" offset for long member name. */
280  nb = snprintf(hdr->name, sizeof(hdr->name)-1, "/%u", (unsigned)iosm->lmtaboff);
281  hdr->name[nb] = ' ';
282  if (te != NULL)
283  iosm->lmtaboff += (te - t) + 1;
284  } else {
285  strncpy(hdr->name, path, nb);
286  hdr->name[nb] = '/';
287  }
288 
289  sprintf(hdr->mtime, "%-12u", (unsigned) (st->st_mtime & 037777777777));
290  sprintf(hdr->uid, "%-6u", (unsigned int)(st->st_uid & 07777777));
291  sprintf(hdr->gid, "%-6u", (unsigned int)(st->st_gid & 07777777));
292 
293  sprintf(hdr->mode, "%-8o", (unsigned int)(st->st_mode & 07777777));
294  sprintf(hdr->filesize, "%-10u", (unsigned) (st->st_size & 037777777777));
295 
296  strncpy(hdr->marker, AR_MARKER, sizeof(AR_MARKER)-1);
297 
298 rc = (int) sizeof(*hdr);
299 if (_ar_debug)
300 fprintf(stderr, "==> %p[%u] \"%.*s\"\n", hdr, (unsigned)rc, (int)sizeof(*hdr), (char *)hdr);
301 
302  rc = arWrite(iosm, hdr, sizeof(*hdr));
303  _IOSMRC(rc);
304  rc = 0;
305 
306  return (int) rc;
307 }
308 
309 int arTrailerWrite(void * _iosm)
310 {
311  IOSM_t iosm = (IOSM_t) _iosm;
312  size_t rc = 0;
313 
314 if (_ar_debug)
315 fprintf(stderr, " arTrailerWrite(%p)\n", iosm);
316 
317 #if defined(JBJ_WRITEPAD)
318  rc = arWrite(iosm, NULL, 0); /* XXX _iosmNext(iosm, IOSM_PAD) */
319  _IOSMRC(rc);
320 #else
321  rc = _iosmNext(iosm, IOSM_PAD); /* XXX likely unnecessary. */
322 #endif
323 
324  return (int) rc;
325 }
int arHeaderRead(void *_iosm, struct stat *st)
Read ar(1) header.
Definition: ar.c:92
static unsigned long long fdGetCpioPos(FD_t fd)
char name[16]
Definition: ar.h:21
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
static char *size_t nb
fgets(3) analogue that reads \ continuations.
Definition: macro.c:409
int rc
Definition: poptALL.c:670
const char * path
Definition: iosm.h:220
static ssize_t arRead(void *_iosm, void *buf, size_t count)
Definition: ar.c:59
char filesize[10]
Definition: ar.h:26
size_t lmtaboff
Definition: iosm.h:319
Structures used for ar(1) archives.
char uid[6]
Definition: ar.h:23
sprintf(t," (%u)",(unsigned) dig->nbytes)
ret
Definition: macro.c:387
size_t wrnb
Definition: iosm.h:243
char * alloca()
FD_t cfd
Definition: iosm.h:226
memset(_r, 0, sizeof(*_r))
int count
Definition: rpmdb-py.c:157
assert(key->size==sizeof(hdrNum))
char * lmtab
Definition: iosm.h:317
size_t rdnb
Definition: iosm.h:235
char mtime[12]
Definition: ar.h:22
fprintf(stderr,"--> %s(%p,%p,%p) sig %p sigp %p\n", __FUNCTION__, dig, t, rsactx, sig, sigp)
int(* _iosmNext)(IOSM_t iosm, iosmFileStage nstage)
Vector to iosmNext.
Definition: iosm.c:83
Definition: iosm.h:160
#define AR_MARKER
Definition: ar.h:15
ar(1) archive header.
Definition: ar.h:20
spectags st
Definition: spec.c:741
struct arHeader_s * arHeader
Definition: ar.h:11
char * wrbuf
Definition: iosm.h:238
size_t wrlen
Definition: iosm.h:242
char marker[2]
Definition: ar.h:27
static int strntoul(const char *str, char **endptr, int base, size_t num)
Convert string to unsigned integer (with buffer size check).
Definition: ar.c:33
const char * s
Definition: poptALL.c:734
static int xisdigit(int c)
Definition: rpmiotypes.h:437
char * t
Definition: rpmds.c:2716
static int snprintf(char *buf, int nb, const char *fmt,...)
Definition: rpmps.c:220
char gid[6]
Definition: ar.h:24
Definition: iosm.h:161
char * path
Definition: poptALL.c:744
int arHeaderWrite(void *_iosm, struct stat *st)
Write ar(1) header.
Definition: ar.c:235
if(__progname==NULL)
Definition: poptALL.c:683
te
Definition: macro.c:552
size_t lmtablen
Definition: iosm.h:318
struct iosm_s * IOSM_t
File state machine data.
Definition: iosm.h:17
int arTrailerWrite(void *_iosm)
Write ar(1) trailer.
Definition: ar.c:309
char * rdbuf
Definition: iosm.h:230
int _ar_debug
Definition: ar.c:23
static ssize_t arWrite(void *_iosm, const void *buf, size_t count)
Definition: ar.c:199
return NULL
Definition: poptALL.c:613
char * buf
Parse (and execute) macro undefinition.
Definition: macro.c:703
File state machine to handle archive I/O and system call&#39;s.
int
Save source and expand field into target.
Definition: rpmds.c:2709
char mode[8]
Definition: ar.h:25
#define _IOSMRC(_rc)
Definition: ar.c:56
int i
Definition: spec.c:743
strncpy(sbuf, f, flen)
File name and stat information.
Definition: iosm.h:218
#define AR_MAGIC
Definition: ar.h:14