rpm  5.4.14
bzdio.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 #include "rpmio_internal.h"
8 #include <rpmmacro.h>
9 #include <rpmcb.h>
10 
11 #if defined(WITH_BZIP2)
12 
13 #define _RPMBZ_INTERNAL
14 #include "rpmbz.h"
15 
16 #include "debug.h"
17 
18 /*@access FD_t @*/
19 
20 #define BZDONLY(fd) assert(fdGetIo(fd) == bzdio)
21 
22 const char * rpmbzStrerror(rpmbz bz)
23  /*@*/
24 {
25  return BZ2_bzerror(bz->bzfile, &bz->bzerr);
26 }
27 
28 /*@-mustmod@*/
29 void rpmbzClose(rpmbz bz, int abort, /*@null@*/ const char ** errmsg)
30  /*@modifies bz, *errmsg @*/
31 {
32  if (bz->bzfile != NULL) {
33  if (bz->omode == O_RDONLY)
34  BZ2_bzReadClose(&bz->bzerr, bz->bzfile);
35  else
36  BZ2_bzWriteClose(&bz->bzerr, bz->bzfile, abort,
37  &bz->nbytes_in, &bz->nbytes_out);
38 /*@-usereleased@*/ /* XXX does bz->bzfile persist after *Close? */
39  if (bz->bzerr != BZ_OK && errmsg)
40  *errmsg = rpmbzStrerror(bz);
41 /*@=usereleased@*/
42  }
43  bz->bzfile = NULL;
44 }
45 /*@=mustmod@*/
46 
47 /*@only@*/ /*@null@*/
48 rpmbz rpmbzFree(/*@only@*/ rpmbz bz, int abort)
49  /*@globals fileSystem @*/
50  /*@modifies bz, fileSystem @*/
51 {
52  rpmbzClose(bz, abort, NULL);
53  if (bz->fp != NULL) {
54  (void) fclose(bz->fp);
55  bz->fp = NULL;
56  }
57  return rpmbzFini(bz);
58 }
59 
60 /*@-mustmod@*/
61 /*@only@*/
62 rpmbz rpmbzNew(const char * path, const char * fmode, int fdno)
63  /*@globals fileSystem @*/
64  /*@modifies fileSystem @*/
65 {
66  rpmbz bz;
67  int level = -1; /* XXX use _bzdB default */
68  mode_t omode = O_RDONLY;
69  int small = -1; /* XXX use _bzdS default */
70  int verbosity = -1; /* XXX use _bzdV default */
71  const char * s = fmode;
72  char stdio[20];
73  char *t = stdio;
74  char *te = t + sizeof(stdio) - 2;
75  int c;
76 
77 assert(fmode != NULL); /* XXX return NULL instead? */
78 
79  switch ((c = *s++)) {
80  case 'a':
81  case 'w':
82  omode = O_WRONLY;
83  *t++ = (char)c;
84  break;
85  case 'r':
86  omode = O_RDONLY;
87  *t++ = (char)c;
88  break;
89  }
90 
91  while ((c = *s++) != 0) {
92  switch (c) {
93  case '.':
94  /*@switchbreak@*/ break;
95  case '+':
96  case 'x':
97  case 'm':
98  case 'c':
99  case 'b':
100  if (t < te) *t++ = c;
101  /*@switchbreak@*/ break;
102  case 's':
103  if (small < 0) small = 0;
104  small++;
105  /*@switchbreak@*/ break;
106  case 'q':
107  verbosity = 0;
108  /*@switchbreak@*/ break;
109  case 'v':
110  if (verbosity < 0) verbosity = 0;
111  if (verbosity < 4) verbosity++;
112  /*@switchbreak@*/ break;
113  default:
114  if (c >= (int)'0' && c <= (int)'9')
115  level = c - (int)'0';
116  /*@switchbreak@*/ break;
117  }}
118  *t = '\0';
119 
120  bz = rpmbzInit(level, small, verbosity, omode);
121 
122  if (fdno >= 0) {
123  if ((bz->fp = fdopen(fdno, stdio)) != NULL)
124  bz->bzfile = (bz->omode == O_RDONLY)
125  ? BZ2_bzReadOpen(&bz->bzerr, bz->fp, bz->V, bz->S, NULL, 0)
126  : BZ2_bzWriteOpen(&bz->bzerr, bz->fp, bz->B, bz->V, bz->W);
127  } else if (path != NULL) {
128  if ((bz->fp = fopen(path, stdio)) != NULL)
129  bz->bzfile = (bz->omode == O_RDONLY)
130  ? BZ2_bzReadOpen(&bz->bzerr, bz->fp, bz->V, bz->S, NULL, 0)
131  : BZ2_bzWriteOpen(&bz->bzerr, bz->fp, bz->B, bz->V, bz->W);
132  }
133 
134 /*@-usereleased@*/
135  return (bz->bzfile != NULL ? bz : rpmbzFree(bz, 0));
136 /*@=usereleased@*/
137 }
138 /*@=mustmod@*/
139 
140 #ifdef NOTYET
141 /*@-mustmod -nullstate@*/
142 static void rpmbzCompress(rpmbz bz, rpmzJob job)
143  /*@globals fileSystem @*/
144  /*@modifies bz, job, fileSystem @*/
145 {
146  bz_stream *bzstrm = &bz->strm;
147  size_t len; /* remaining bytes to compress/check */
148  int ret;
149 
150  /* initialize the deflate stream for this block */
151  bzstrm->bzfree = NULL;
152  bzstrm->bzalloc = NULL;
153  bzstrm->opaque = NULL;
154  if ((ret = BZ2_bzCompressInit(bzstrm, bz->B, bz->V, bz->W)) != BZ_OK)
155  bail("not enough memory", "BZ2_bzCompressInit");
156 
157  bzstrm->next_in = job->in->buf;
158  bzstrm->next_out = job->out->buf;
159  bzstrm->avail_out = job->out->len;
160 
161  /* run _PIGZMAX-sized amounts of input through deflate -- this loop is
162  * needed for those cases where the integer type is smaller than the
163  * size_t type, or when len is close to the limit of the size_t type */
164  len = job->in->len;
165  while (len > _PIGZMAX) {
166  bzstrm->avail_in = _PIGZMAX;
167  if ((ret = BZ2_bzCompress(bzstrm, BZ_RUN)) != BZ_RUN_OK)
168  fprintf(stderr, "*** BZ2_bzCompress(%d): %d\n", BZ_RUN, ret);
169 assert(bzstrm->avail_in == 0 && bzstrm->avail_out != 0);
170  len -= _PIGZMAX;
171  }
172 
173  /* run the last piece through deflate -- terminate with a sync marker,
174  * or finish deflate stream if this is the last block */
175  bzstrm->avail_in = (unsigned)len;
176  ret = BZ2_bzCompress(bzstrm, BZ_FINISH);
177  if (!(ret == BZ_FINISH_OK || ret == BZ_STREAM_END))
178  fprintf(stderr, "*** BZ2_bzCompress(%d): %d\n", BZ_FINISH, ret);
179  if ((ret = BZ2_bzCompressEnd(bzstrm)) != BZ_OK)
180  fprintf(stderr, "*** BZ2_bzCompressEnd: %d\n", ret);
181 #ifdef NOTYET
182 assert(bzstrm->avail_in == 0 && bzstrm->avail_out != 0);
183 #endif
184 
185 }
186 /*@=mustmod =nullstate@*/
187 
188 /*@-mustmod -nullstate@*/
189 static void rpmbzDecompress(rpmbz bz, rpmzJob job)
190  /*@globals fileSystem @*/
191  /*@modifies bz, job, fileSystem @*/
192 {
193  bz_stream *bzstrm = &bz->strm;
194  int ret;
195 
196  /* initialize the inflate stream for this block */
197  bzstrm->bzfree = NULL;
198  bzstrm->bzalloc = NULL;
199  bzstrm->opaque = NULL;
200  if ((ret = BZ2_bzDecompressInit(bzstrm, bz->V, bz->S)) != BZ_OK)
201  bail("not enough memory", "BZ2_bzDecompressInit");
202 
203  bzstrm->next_in = job->in->buf;
204  bzstrm->avail_in = job->in->len;
205  bzstrm->next_out = job->out->buf;
206  bzstrm->avail_out = job->out->len;
207 
208  if ((ret = BZ2_bzDecompress(bzstrm)) != BZ_RUN_OK)
209  fprintf(stderr, "*** BZ2_bzDecompress: %d\n", ret);
210 
211  job->out->len -= bzstrm->avail_out;
212 
213  if ((ret = BZ2_bzDecompressEnd(bzstrm)) != BZ_OK)
214  fprintf(stderr, "*** BZ2_bzDecompressEnd: %d\n", ret);
215 
216 }
217 /*@=mustmod =nullstate@*/
218 #endif /* NOTYET */
219 
220 /*@-mustmod@*/
221 ssize_t rpmbzRead(rpmbz bz, /*@out@*/ char * buf, size_t count,
222  /*@null@*/ const char ** errmsg)
223  /*@globals internalState @*/
224  /*@modifies bz, *buf, *errmsg, internalState @*/
225 {
226  ssize_t rc = 0;
227 
228 #ifdef NOTYET /* XXX hmmm, read after close needs to return EOF. */
229 assert(bz->bzfile != NULL);
230 #else
231  if (bz->bzfile == NULL) return 0;
232 #endif
233  rc = BZ2_bzRead(&bz->bzerr, bz->bzfile, buf, (int)count);
234  switch (bz->bzerr) {
235  case BZ_STREAM_END: {
236  void * unused = NULL;
237  int nUnused = 0;
238 
239  BZ2_bzReadGetUnused(&bz->bzerr, bz->bzfile, &unused, &nUnused);
240  if (unused != NULL && nUnused > 0)
241  unused = memcpy(xmalloc(nUnused), unused, nUnused);
242  else {
243  unused = NULL;
244  nUnused = 0;
245  }
246  rpmbzClose(bz, 0, NULL);
247  bz->bzfile = BZ2_bzReadOpen(&bz->bzerr, bz->fp, bz->V, bz->S,
248  unused, nUnused);
249  unused = _free(unused);
250  } /*@fallthrough@*/
251  case BZ_OK:
252 assert(rc >= 0);
253  break;
254  default:
255  rc = -1;
256  if (errmsg != NULL)
257  *errmsg = rpmbzStrerror(bz);
258  rpmbzClose(bz, 1, NULL);
259  break;
260  }
261  return rc;
262 }
263 /*@=mustmod@*/
264 
265 ssize_t rpmbzWrite(rpmbz bz, const char * buf, size_t count,
266  /*@null@*/ const char ** errmsg)
267  /*@globals internalState @*/
268  /*@modifies bz, *errmsg, internalState @*/
269 {
270  ssize_t rc;
271 
272 assert(bz->bzfile != NULL); /* XXX TODO: lazy open? */
273  BZ2_bzWrite(&bz->bzerr, bz->bzfile, (void *)buf, (int)count);
274  switch (bz->bzerr) {
275  case BZ_OK:
276  rc = count;
277  break;
278  default:
279  if (errmsg != NULL)
280  *errmsg = rpmbzStrerror(bz);
281  rpmbzClose(bz, 1, NULL);
282  rc = -1;
283  break;
284  }
285  return rc;
286 }
287 
288 static int rpmbzSeek(/*@unused@*/ void * _bz, /*@unused@*/ _libio_pos_t pos,
289  /*@unused@*/ int whence)
290  /*@*/
291 {
292  return -2;
293 }
294 
295 static /*@null@*/ rpmbz rpmbzOpen(const char * path, const char * fmode)
296  /*@globals fileSystem, internalState @*/
297  /*@modifies fileSystem, internalState @*/
298 {
299  return rpmbzNew(path, fmode, -1);
300 }
301 
302 static /*@null@*/ rpmbz rpmbzFdopen(void * _fdno, const char * fmode)
303  /*@globals fileSystem, internalState @*/
304  /*@modifies fileSystem, internalState @*/
305 {
306  int fdno = (int)((long)_fdno); /* XXX hack */
307  return rpmbzNew(NULL, fmode, fdno);
308 }
309 
310 static int rpmbzFlush(void * _bz)
311  /*@*/
312 {
313  rpmbz bz = (rpmbz) _bz;
314  return BZ2_bzflush(bz->bzfile);
315 }
316 
317 /* =============================================================== */
318 static inline /*@dependent@*/ /*@null@*/ void * bzdFileno(FD_t fd)
319  /*@*/
320 {
321  void * rc = NULL;
322  int i;
323 
324  FDSANE(fd);
325  for (i = fd->nfps; i >= 0; i--) {
326  FDSTACK_t * fps = &fd->fps[i];
327  if (fps->io != bzdio)
328  continue;
329  rc = fps->fp;
330  break;
331  }
332 
333  return rc;
334 }
335 
336 /*@-globuse@*/
337 static /*@null@*/ FD_t bzdOpen(const char * path, const char * fmode)
338  /*@globals fileSystem, internalState @*/
339  /*@modifies fileSystem, internalState @*/
340 {
341  FD_t fd;
342  rpmbz bz = rpmbzOpen(path, fmode);
343 
344  if (bz == NULL)
345  return NULL;
346  fd = fdNew("open (bzdOpen)");
347 #ifdef NOTYET /* XXX persistent URI cache prevents fileno(bz->fp) */
348  fdPop(fd); fdPush(fd, bzdio, bz, fileno(bz->fp));
349 #else
350  fdPop(fd); fdPush(fd, bzdio, bz, -1);
351 #endif
352  fdSetOpen(fd, path, -1, bz->omode);
353  return fdLink(fd, "bzdOpen");
354 }
355 /*@=globuse@*/
356 
357 /*@-globuse@*/
358 static /*@null@*/ FD_t bzdFdopen(void * cookie, const char * fmode)
359  /*@globals fileSystem, internalState @*/
360  /*@modifies fileSystem, internalState @*/
361 {
362  FD_t fd = c2f(cookie);
363  int fdno = fdFileno(fd);
364  rpmbz bz = rpmbzFdopen((void *)((long)fdno), fmode);
365 
366  if (bz == NULL)
367  return NULL;
368 #ifdef NOTYET /* XXX persistent URI cache prevents pop */
369  fdPop(fd); fdPush(fd, bzdio, bz, fileno(bz->fp));
370 #else
371  fdSetFdno(fd, -1); /* XXX skip the fdio close */
372  fdPush(fd, bzdio, bz, fdno); /* Push bzdio onto stack */
373 #endif
374  return fdLink(fd, "bzdFdopen");
375 }
376 /*@=globuse@*/
377 
378 /*@-globuse@*/
379 static int bzdFlush(void * cookie)
380  /*@globals fileSystem @*/
381  /*@modifies fileSystem @*/
382 {
383  FD_t fd = c2f(cookie);
384  rpmbz bz = (rpmbz) bzdFileno(fd);
385  return rpmbzFlush(bz);
386 }
387 /*@=globuse@*/
388 
389 /*@-globuse@*/
390 /*@-mustmod@*/ /* LCL: *buf is modified */
391 static ssize_t bzdRead(void * cookie, /*@out@*/ char * buf, size_t count)
392  /*@globals fileSystem, internalState @*/
393  /*@modifies *buf, fileSystem, internalState @*/
394 {
395  FD_t fd = c2f(cookie);
396  rpmbz bz = (rpmbz) bzdFileno(fd);
397  ssize_t rc = 0;
398 
399 assert(bz != NULL);
400  if (fd->bytesRemain == 0) return 0; /* XXX simulate EOF */
402 /*@-modobserver@*/ /* FIX: is errcookie an observer? */
403  rc = rpmbzRead(bz, buf, count, (const char **)&fd->errcookie);
404 /*@=modobserver@*/
405  if (rc >= 0) {
406  fdstat_exit(fd, FDSTAT_READ, rc);
407  if (fd->ndigests && rc > 0) fdUpdateDigests(fd, (const unsigned char *)buf, rc);
408  }
409  return rc;
410 }
411 /*@=mustmod@*/
412 /*@=globuse@*/
413 
414 /*@-globuse@*/
415 static ssize_t bzdWrite(void * cookie, const char * buf, size_t count)
416  /*@globals fileSystem, internalState @*/
417  /*@modifies fileSystem, internalState @*/
418 {
419  FD_t fd = c2f(cookie);
420  rpmbz bz = (rpmbz) bzdFileno(fd);
421  ssize_t rc;
422 
423 assert(bz != NULL);
424  if (fd->bytesRemain == 0) return 0; /* XXX simulate EOF */
425 
426  if (fd->ndigests && count > 0) fdUpdateDigests(fd, (const unsigned char *)buf, count);
427 
429 /*@-modobserver@*/ /* FIX: is errcookie an observer? */
430  rc = rpmbzWrite(bz, buf, count, (const char **)&fd->errcookie);
431 /*@=modobserver@*/
432  if (rc >= 0)
433  fdstat_exit(fd, FDSTAT_WRITE, rc);
434  return rc;
435 }
436 /*@=globuse@*/
437 
438 static int bzdSeek(void * cookie, _libio_pos_t pos, int whence)
439  /*@*/
440 {
441  FD_t fd = c2f(cookie);
442  rpmbz bz = (rpmbz) bzdFileno(fd);
443 
444 assert(bz != NULL);
445  BZDONLY(fd);
446  return rpmbzSeek(bz, pos, whence);
447 }
448 
449 static int bzdClose( /*@only@*/ void * cookie)
450  /*@globals fileSystem, internalState @*/
451  /*@modifies fileSystem, internalState @*/
452 {
453  FD_t fd = c2f(cookie);
454  rpmbz bz = (rpmbz) bzdFileno(fd);
455  int rc;
456 
457 assert(bz != NULL);
458 #ifdef DYING
459  if (bz->bzfile == NULL) /* XXX memory leak w errors? */
460  return -2;
461 #endif
462 
464 /*@-modobserver@*/ /* FIX: is errcookie an observer? */
465  rpmbzClose(bz, 0, (const char **)&fd->errcookie);
466 /*@=modobserver@*/
467  rc = 0; /* XXX FIXME */
468 
469  /* XXX TODO: preserve fd if errors */
470 
471  if (fd)
472  if (rc >= 0)
473  fdstat_exit(fd, FDSTAT_CLOSE, rc);
474 
475 DBGIO(fd, (stderr, "==>\tbzdClose(%p) rc %lx %s\n", cookie, (unsigned long)rc, fdbg(fd)));
476 
477  if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "BZDIO", stderr);
478 
479  if (rc == 0) {
480 /*@-dependenttrans@*/
481  bz = rpmbzFree(bz, 0);
482 /*@=dependenttrans@*/
483  fd = fdFree(fd, "open (bzdClose)");
484  }
485  return rc;
486 }
487 
488 /*@-type@*/ /* LCL: function typedefs */
489 static struct FDIO_s bzdio_s = {
490  bzdRead, bzdWrite, bzdSeek, bzdClose, bzdOpen, bzdFdopen, bzdFlush,
491 };
492 /*@=type@*/
493 
494 FDIO_t bzdio = /*@-compmempass@*/ &bzdio_s /*@=compmempass@*/ ;
495 
496 #endif
497 
char * cookie
Definition: rpmts-py.c:1341
static void fdPop(FD_t fd)
static void fdPush(FD_t fd, FDIO_t io, void *fp, int fdno)
ssize_t bytesRemain
static void fdSetOpen(FD_t fd, const char *path, int flags, mode_t mode)
int rc
Definition: poptALL.c:670
#define FDSANE(fd)
const void * errcookie
FD_t fdLink(void *cookie, const char *msg)
Definition: rpmio.h:107
int nfps
FD_t fdNew(const char *msg)
ret
Definition: macro.c:387
int count
Definition: rpmdb-py.c:157
const char * pos
Definition: rpmrpc.c:501
assert(key->size==sizeof(hdrNum))
static void fdSetFdno(FD_t fd, int fdno)
fprintf(stderr,"--> %s(%p,%p,%p) sig %p sigp %p\n", __FUNCTION__, dig, t, rsactx, sig, sigp)
FD_t fdFree(FD_t fd, const char *msg)
off_t _libio_pos_t
Definition: rpmio.h:32
const char * fdbg(FD_t fd)
Definition: rpmio.c:197
The FD_t File Handle data structure.
static int fdFileno(void *cookie)
static void fdstat_enter(FD_t fd, int opx)
static unsigned
Definition: rpmmtree.c:386
FDIO_t bzdio
node fd
Definition: rpmfd-py.c:124
static const char *char c
Return text between pl and matching pr characters.
Definition: macro.c:470
size_t ndigests
static void fdstat_exit(FD_t fd, int opx, ssize_t rc)
const char * s
Definition: poptALL.c:734
char * t
Definition: rpmds.c:2716
int _rpmio_debug
Definition: rpmio.c:178
char * path
Definition: poptALL.c:744
te
Definition: macro.c:552
static void fdUpdateDigests(FD_t fd, const unsigned char *buf, ssize_t buflen)
Update digest(s) attached to fd.
static FD_t c2f(void *cookie)
#define DBGIO(_f, _x)
return NULL
Definition: poptALL.c:613
static void
Print copy of spec file, filling in Group/Description/Summary from specspo.
Definition: spec.c:737
#define rpmIsDebug()
Definition: rpmcb.h:23
char * buf
Parse (and execute) macro undefinition.
Definition: macro.c:703
int
Save source and expand field into target.
Definition: rpmds.c:2709
#define xmalloc
Definition: system.h:32
FDSTACK_t fps[8]
int fdno
Definition: rpmts-py.c:923
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
int i
Definition: spec.c:743
static void fdstat_print(FD_t fd, const char *msg, FILE *fp)
int len
Definition: rpmdb-py.c:119
mode_t omode