rpm  5.4.14
xzdio.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_XZ)
12 
13 /* provide necessary defines for inclusion of <lzma.h>
14  similar to LZMAUtils's internal <common.h> and as
15  explicitly stated in the top-level comment of <lzma.h> */
16 #ifndef UINT32_C
17 # define UINT32_C(n) n ## U
18 #endif
19 #ifndef UINT32_MAX
20 # define UINT32_MAX UINT32_C(4294967295)
21 #endif
22 #if SIZEOF_UNSIGNED_LONG == 4
23 # ifndef UINT64_C
24 # define UINT64_C(n) n ## ULL
25 # endif
26 #else
27 # ifndef UINT64_C
28 # define UINT64_C(n) n ## UL
29 # endif
30 #endif
31 #ifndef UINT64_MAX
32 # define UINT64_MAX UINT64_C(18446744073709551615)
33 #endif
34 
35 #include "lzma.h"
36 
37 #ifndef LZMA_PRESET_DEFAULT
38 #define LZMA_PRESET_DEFAULT UINT32_C(6)
39 #endif
40 
41 #include "debug.h"
42 
43 /*@access FD_t @*/
44 
45 #define XZDONLY(fd) assert(fdGetIo(fd) == xzdio)
46 
47 #define kBufferSize (1 << 15)
48 
49 typedef struct xzfile {
50 /*@only@*/
51  rpmuint8_t buf[kBufferSize];
52  lzma_stream strm;
53 /*@dependent@*/
54  FILE * fp;
55  int encoding;
56  int eof;
57 } XZFILE;
58 
59 /*@-globstate@*/
60 /*@null@*/
61 static XZFILE *xzopen_internal(const char *path, const char *mode, int fdno, int xz)
62  /*@globals fileSystem @*/
63  /*@modifies fileSystem @*/
64 {
65  int level = LZMA_PRESET_DEFAULT;
66  int encoding = 0;
67  FILE *fp;
68  XZFILE *xzfile;
69  lzma_stream tmp;
70  lzma_ret ret;
71 
72  for (; *mode != '\0'; mode++) {
73  if (*mode == 'w')
74  encoding = 1;
75  else if (*mode == 'r')
76  encoding = 0;
77  else if (*mode >= '0' && *mode <= '9')
78  level = (int)(*mode - '0');
79  }
80  if (fdno != -1)
81  fp = fdopen(fdno, encoding ? "w" : "r");
82  else
83  fp = fopen(path, encoding ? "w" : "r");
84  if (!fp)
85  return NULL;
86  xzfile = (XZFILE *) calloc(1, sizeof(*xzfile));
87  if (!xzfile) {
88  (void) fclose(fp);
89  return NULL;
90  }
91  xzfile->fp = fp;
92  xzfile->encoding = encoding;
93  xzfile->eof = 0;
94  tmp = (lzma_stream)LZMA_STREAM_INIT;
95  xzfile->strm = tmp;
96  if (encoding) {
97  if (xz) {
98  ret = lzma_easy_encoder(&xzfile->strm, level, LZMA_CHECK_CRC32);
99  } else {
100  lzma_options_lzma options;
101  (void) lzma_lzma_preset(&options, level);
102  ret = lzma_alone_encoder(&xzfile->strm, &options);
103  }
104  } else {
105  /* We set the memlimit for decompression to 100MiB which should be
106  * more than enough to be sufficient for level 9 which requires 65 MiB.
107  */
108  ret = lzma_auto_decoder(&xzfile->strm, 100<<20, 0);
109  }
110  if (ret != LZMA_OK) {
111  (void) fclose(fp);
112  memset(xzfile, 0, sizeof(*xzfile));
113  free(xzfile);
114  return NULL;
115  }
116  return xzfile;
117 }
118 /*@=globstate@*/
119 
120 /*@null@*/
121 static XZFILE *lzopen(const char *path, const char *mode)
122  /*@globals fileSystem @*/
123  /*@modifies fileSystem @*/
124 {
125  return xzopen_internal(path, mode, -1, 0);
126 }
127 
128 /*@null@*/
129 static XZFILE *lzdopen(int fdno, const char *mode)
130  /*@globals fileSystem @*/
131  /*@modifies fileSystem @*/
132 {
133  if (fdno < 0)
134  return NULL;
135  return xzopen_internal(0, mode, fdno, 0);
136 }
137 
138 /*@null@*/
139 static XZFILE *xzopen(const char *path, const char *mode)
140  /*@globals fileSystem @*/
141  /*@modifies fileSystem @*/
142 {
143  return xzopen_internal(path, mode, -1, 1);
144 }
145 
146 /*@null@*/
147 static XZFILE *xzdopen(int fdno, const char *mode)
148  /*@globals fileSystem @*/
149  /*@modifies fileSystem @*/
150 {
151  if (fdno < 0)
152  return NULL;
153  return xzopen_internal(0, mode, fdno, 1);
154 }
155 
156 static int xzflush(XZFILE *xzfile)
157  /*@globals fileSystem @*/
158  /*@modifies xzfile, fileSystem @*/
159 {
160  return fflush(xzfile->fp);
161 }
162 
163 static int xzclose(/*@only@*/ XZFILE *xzfile)
164  /*@globals fileSystem @*/
165  /*@modifies *xzfile, fileSystem @*/
166 {
167  lzma_ret ret;
168  size_t n;
169  int rc;
170 
171  if (!xzfile)
172  return -1;
173  if (xzfile->encoding) {
174  for (;;) {
175  xzfile->strm.avail_out = kBufferSize;
176  xzfile->strm.next_out = (uint8_t *)xzfile->buf;
177  ret = lzma_code(&xzfile->strm, LZMA_FINISH);
178  if (ret != LZMA_OK && ret != LZMA_STREAM_END)
179  return -1;
180  n = kBufferSize - xzfile->strm.avail_out;
181  if (n && fwrite(xzfile->buf, 1, n, xzfile->fp) != n)
182  return -1;
183  if (ret == LZMA_STREAM_END)
184  break;
185  }
186  }
187  lzma_end(&xzfile->strm);
188  rc = fclose(xzfile->fp);
189  memset(xzfile, 0, sizeof(*xzfile));
190  free(xzfile);
191  return rc;
192 }
193 
194 /*@-mustmod@*/
195 static ssize_t xzread(XZFILE *xzfile, void *buf, size_t len)
196  /*@globals fileSystem @*/
197  /*@modifies xzfile, *buf, fileSystem @*/
198 {
199  lzma_ret ret;
200  int eof = 0;
201 
202  if (!xzfile || xzfile->encoding)
203  return -1;
204  if (xzfile->eof)
205  return 0;
206 /*@-temptrans@*/
207  xzfile->strm.next_out = (uint8_t *) buf;
208 /*@=temptrans@*/
209  xzfile->strm.avail_out = len;
210  for (;;) {
211  if (!xzfile->strm.avail_in) {
212  xzfile->strm.next_in = (uint8_t *)xzfile->buf;
213  xzfile->strm.avail_in = fread(xzfile->buf, 1, kBufferSize, xzfile->fp);
214  if (!xzfile->strm.avail_in)
215  eof = 1;
216  }
217  ret = lzma_code(&xzfile->strm, LZMA_RUN);
218  if (ret == LZMA_STREAM_END) {
219  xzfile->eof = 1;
220  return len - xzfile->strm.avail_out;
221  }
222  if (ret != LZMA_OK)
223  return -1;
224  if (!xzfile->strm.avail_out)
225  return len;
226  if (eof)
227  return -1;
228  }
229  /*@notreached@*/
230 }
231 /*@=mustmod@*/
232 
233 static ssize_t xzwrite(XZFILE *xzfile, void *buf, size_t len)
234  /*@globals fileSystem @*/
235  /*@modifies xzfile, fileSystem @*/
236 {
237  lzma_ret ret;
238  size_t n;
239 
240  if (!xzfile || !xzfile->encoding)
241  return -1;
242  if (!len)
243  return 0;
244 /*@-temptrans@*/
245  xzfile->strm.next_in = (const uint8_t *) buf;
246 /*@=temptrans@*/
247  xzfile->strm.avail_in = len;
248  for (;;) {
249  xzfile->strm.next_out = (uint8_t *)xzfile->buf;
250  xzfile->strm.avail_out = kBufferSize;
251  ret = lzma_code(&xzfile->strm, LZMA_RUN);
252  if (ret != LZMA_OK)
253  return -1;
254  n = kBufferSize - xzfile->strm.avail_out;
255  if (n && fwrite(xzfile->buf, 1, n, xzfile->fp) != n)
256  return -1;
257  if (!xzfile->strm.avail_in)
258  return len;
259  }
260  /*@notreached@*/
261 }
262 
263 /* =============================================================== */
264 
265 static inline /*@dependent@*/ /*@null@*/ void * xzdFileno(FD_t fd)
266  /*@*/
267 {
268  void * rc = NULL;
269  int i;
270 
271  FDSANE(fd);
272  for (i = fd->nfps; i >= 0; i--) {
273 /*@-boundsread@*/
274  FDSTACK_t * fps = &fd->fps[i];
275 /*@=boundsread@*/
276  if (fps->io != xzdio && fps->io != lzdio)
277  continue;
278  rc = fps->fp;
279  break;
280  }
281 
282  return rc;
283 }
284 
285 /*@-globuse@*/
286 static /*@null@*/ FD_t lzdOpen(const char * path, const char * fmode)
287  /*@globals fileSystem @*/
288  /*@modifies fileSystem @*/
289 {
290  FD_t fd;
291  mode_t mode = (fmode && fmode[0] == 'w' ? O_WRONLY : O_RDONLY);
292  XZFILE * xzfile = lzopen(path, fmode);
293 
294  if (xzfile == NULL)
295  return NULL;
296  fd = fdNew("open (lzdOpen)");
297  fdPop(fd); fdPush(fd, lzdio, xzfile, -1);
298  fdSetOpen(fd, path, fileno(xzfile->fp), mode);
299  return fdLink(fd, "lzdOpen");
300 }
301 /*@=globuse@*/
302 
303 /*@-globuse@*/
304 static /*@null@*/ FD_t lzdFdopen(void * cookie, const char * fmode)
305  /*@globals fileSystem, internalState @*/
306  /*@modifies fileSystem, internalState @*/
307 {
308  FD_t fd = c2f(cookie);
309  int fdno = fdFileno(fd);
310  XZFILE *xzfile;
311 
312 assert(fmode != NULL);
313  fdSetFdno(fd, -1); /* XXX skip the fdio close */
314  if (fdno < 0) return NULL;
315  xzfile = lzdopen(fdno, fmode);
316  if (xzfile == NULL) return NULL;
317  fdPush(fd, lzdio, xzfile, fdno);
318  return fdLink(fd, "lzdFdopen");
319 }
320 /*@=globuse@*/
321 
322 /*@-globuse@*/
323 static /*@null@*/ FD_t xzdOpen(const char * path, const char * fmode)
324  /*@globals fileSystem @*/
325  /*@modifies fileSystem @*/
326 {
327  FD_t fd;
328  mode_t mode = (fmode && fmode[0] == 'w' ? O_WRONLY : O_RDONLY);
329  XZFILE * xzfile = xzopen(path, fmode);
330 
331  if (xzfile == NULL)
332  return NULL;
333  fd = fdNew("open (xzdOpen)");
334  fdPop(fd); fdPush(fd, xzdio, xzfile, -1);
335  fdSetOpen(fd, path, fileno(xzfile->fp), mode);
336  return fdLink(fd, "xzdOpen");
337 }
338 /*@=globuse@*/
339 
340 /*@-globuse@*/
341 static /*@null@*/ FD_t xzdFdopen(void * cookie, const char * fmode)
342  /*@globals fileSystem, internalState @*/
343  /*@modifies fileSystem, internalState @*/
344 {
345  FD_t fd = c2f(cookie);
346  int fdno = fdFileno(fd);
347  XZFILE *xzfile;
348 
349 assert(fmode != NULL);
350  fdSetFdno(fd, -1); /* XXX skip the fdio close */
351  if (fdno < 0) return NULL;
352  xzfile = xzdopen(fdno, fmode);
353  if (xzfile == NULL) return NULL;
354  fdPush(fd, xzdio, xzfile, fdno);
355  return fdLink(fd, "xzdFdopen");
356 }
357 /*@=globuse@*/
358 
359 /*@-globuse@*/
360 static int xzdFlush(void * cookie)
361  /*@globals fileSystem @*/
362  /*@modifies fileSystem @*/
363 {
364  FD_t fd = c2f(cookie);
365  XZFILE * xzfile = (XZFILE *) xzdFileno(fd);
366  return xzflush(xzfile);
367 }
368 /*@=globuse@*/
369 
370 /* =============================================================== */
371 /*@-globuse@*/
372 /*@-mustmod@*/ /* LCL: *buf is modified */
373 static ssize_t xzdRead(void * cookie, /*@out@*/ char * buf, size_t count)
374  /*@globals fileSystem, internalState @*/
375  /*@modifies *buf, fileSystem, internalState @*/
376 {
377  FD_t fd = c2f(cookie);
378  XZFILE *xzfile;
379  ssize_t rc = -1;
380 
381 assert(fd != NULL);
382  if (fd->bytesRemain == 0) return 0; /* XXX simulate EOF */
383  xzfile = (XZFILE *) xzdFileno(fd);
384 assert(xzfile != NULL);
386 /*@-compdef@*/
387  rc = xzread(xzfile, buf, count);
388 /*@=compdef@*/
389 DBGIO(fd, (stderr, "==>\txzdRead(%p,%p,%u) rc %lx %s\n", cookie, buf, (unsigned)count, (unsigned long)rc, fdbg(fd)));
390  if (rc == -1) {
391  fd->errcookie = "Lzma: decoding error";
392  } else if (rc >= 0) {
393  fdstat_exit(fd, FDSTAT_READ, rc);
394  /*@-compdef@*/
395  if (fd->ndigests > 0 && rc > 0) fdUpdateDigests(fd, (const unsigned char *)buf, rc);
396  /*@=compdef@*/
397  }
398  return rc;
399 }
400 /*@=mustmod@*/
401 /*@=globuse@*/
402 
403 /*@-globuse@*/
404 static ssize_t xzdWrite(void * cookie, const char * buf, size_t count)
405  /*@globals fileSystem, internalState @*/
406  /*@modifies fileSystem, internalState @*/
407 {
408  FD_t fd = c2f(cookie);
409  XZFILE *xzfile;
410  ssize_t rc = 0;
411 
412  if (fd == NULL || fd->bytesRemain == 0) return 0; /* XXX simulate EOF */
413 
414  if (fd->ndigests > 0 && count > 0) fdUpdateDigests(fd, (const unsigned char *)buf, count);
415 
416  xzfile = (XZFILE *) xzdFileno(fd);
417 
419  rc = xzwrite(xzfile, (void *)buf, count);
420 DBGIO(fd, (stderr, "==>\txzdWrite(%p,%p,%u) rc %lx %s\n", cookie, buf, (unsigned)count, (unsigned long)rc, fdbg(fd)));
421  if (rc < 0) {
422  fd->errcookie = "Lzma: encoding error";
423  } else if (rc > 0) {
424  fdstat_exit(fd, FDSTAT_WRITE, rc);
425  }
426  return rc;
427 }
428 
429 static int xzdSeek(void * cookie, /*@unused@*/ _libio_pos_t pos,
430  /*@unused@*/ int whence)
431  /*@*/
432 {
433  FD_t fd = c2f(cookie);
434 
435  XZDONLY(fd);
436  return -2;
437 }
438 
439 static int xzdClose( /*@only@*/ void * cookie)
440  /*@globals fileSystem, internalState @*/
441  /*@modifies fileSystem, internalState @*/
442 {
443  FD_t fd = c2f(cookie);
444  XZFILE *xzfile;
445  const char * errcookie;
446  int rc;
447 
448  xzfile = (XZFILE *) xzdFileno(fd);
449 
450  if (xzfile == NULL) return -2;
451  errcookie = strerror(ferror(xzfile->fp));
452 
454  /*@-dependenttrans@*/
455  rc = xzclose(xzfile);
456  /*@=dependenttrans@*/
457  fdstat_exit(fd, FDSTAT_CLOSE, rc);
458 
459  if (fd && rc == -1)
460  fd->errcookie = errcookie;
461 
462 DBGIO(fd, (stderr, "==>\txzdClose(%p) rc %lx %s\n", cookie, (unsigned long)rc, fdbg(fd)));
463 
464  if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "XZDIO", stderr);
465  /*@-branchstate@*/
466  if (rc == 0)
467  fd = fdFree(fd, "open (xzdClose)");
468  /*@=branchstate@*/
469  return rc;
470 }
471 
472 /*@-type@*/ /* LCL: function typedefs */
473 static struct FDIO_s lzdio_s = {
474  xzdRead, xzdWrite, xzdSeek, xzdClose, lzdOpen, lzdFdopen, xzdFlush,
475 };
476 /*@=type@*/
477 
478 FDIO_t lzdio = /*@-compmempass@*/ &lzdio_s /*@=compmempass@*/ ;
479 
480 /*@-type@*/ /* LCL: function typedefs */
481 static struct FDIO_s xzdio_s = {
482  xzdRead, xzdWrite, xzdSeek, xzdClose, xzdOpen, xzdFdopen, xzdFlush,
483 };
484 /*@=type@*/
485 
486 FDIO_t xzdio = /*@-compmempass@*/ &xzdio_s /*@=compmempass@*/ ;
487 
488 #endif
489 
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)
FDIO_t xzdio
Definition: rpmio.h:107
int nfps
FD_t fdNew(const char *msg)
unsigned char rpmuint8_t
Private int typedefs to avoid C99 portability issues.
Definition: rpmiotypes.h:26
static PyObject *char * mode
Definition: rpmfd-py.c:115
ret
Definition: macro.c:387
memset(_r, 0, sizeof(*_r))
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)
FD_t fdFree(FD_t fd, const char *msg)
FDIO_t lzdio
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)
node fd
Definition: rpmfd-py.c:124
char * n
Definition: macro.c:744
size_t ndigests
static void fdstat_exit(FD_t fd, int opx, ssize_t rc)
int _rpmio_debug
Definition: rpmio.c:178
char * path
Definition: poptALL.c:744
s options
Definition: rpmfts-py.c:94
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
FDSTACK_t fps[8]
int fdno
Definition: rpmts-py.c:923
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