Bug Summary

File:rpmio/rpmio.c
Warning:line 97, column 5
Use of memory after it is freed

Annotated Source Code

1/** \ingroup rpmio
2 * \file rpmio/rpmio.c
3 */
4
5#include "system.h"
6#include <stdarg.h>
7#include <errno(*__errno_location ()).h>
8#include <ctype.h>
9#if defined(__linux__1)
10#include <sys/personality.h>
11#endif
12#include <sys/utsname.h>
13
14#include <rpm/rpmlog.h>
15#include <rpm/rpmmacro.h>
16#include <rpm/rpmfileutil.h>
17#include <rpm/rpmsw.h>
18#include <rpm/rpmurl.h>
19
20#include "rpmio/rpmio_internal.h"
21
22#include "debug.h"
23
24typedef struct FDSTACK_s * FDSTACK_t;
25
26struct FDSTACK_s {
27 FDIO_t io;
28 void * fp;
29 int fdno;
30 int syserrno; /* last system errno encountered */
31 const char *errcookie; /* pointer to custom error string */
32
33 FDSTACK_t prev;
34};
35
36/** \ingroup rpmio
37 * Cumulative statistics for a descriptor.
38 */
39typedef struct {
40 struct rpmop_s ops[FDSTAT_MAX]; /*!< Cumulative statistics. */
41} * FDSTAT_t;
42
43/** \ingroup rpmio
44 * The FD_t File Handle data structure.
45 */
46struct _FD_s {
47 int nrefs;
48 int flags;
49#define RPMIO_DEBUG_IO0x40000000 0x40000000
50 int magic;
51#define FDMAGIC0x04463138 0x04463138
52 FDSTACK_t fps;
53 int urlType; /* ufdio: */
54
55 char *descr; /* file name (or other description) */
56 FDSTAT_t stats; /* I/O statistics */
57
58 rpmDigestBundle digests;
59};
60
61#define DBG(_f, _m, _x)if ((_rpmio_debug | ((_f) ? ((FD_t)(_f))->flags : 0)) &
(_m)) fprintf _x
\
62 \
63 if ((_rpmio_debug | ((_f) ? ((FD_t)(_f))->flags : 0)) & (_m)) fprintf _x \
64
65#define DBGIO(_f, _x)if ((_rpmio_debug | (((_f)) ? ((FD_t)((_f)))->flags : 0)) &
(0x40000000)) fprintf _x
DBG((_f), RPMIO_DEBUG_IO, _x)if ((_rpmio_debug | (((_f)) ? ((FD_t)((_f)))->flags : 0)) &
(0x40000000)) fprintf _x
66
67static FDSTACK_t fdGetFps(FD_t fd)
68{
69 return (fd != NULL((void*)0)) ? fd->fps : NULL((void*)0);
70}
71
72static void fdSetFdno(FD_t fd, int fdno)
73{
74 if (fd)
75 fd->fps->fdno = fdno;
76}
77
78static void fdPush(FD_t fd, FDIO_t io, void * fp, int fdno)
79{
80 FDSTACK_t fps = xcalloc(1, sizeof(*fps))rcalloc((1), (sizeof(*fps)));
81 fps->io = io;
82 fps->fp = fp;
83 fps->fdno = fdno;
84 fps->prev = fd->fps;
85
86 fd->fps = fps;
87 fdLink(fd);
88}
89
90static FDSTACK_t fdPop(FD_t fd)
91{
92 FDSTACK_t fps = fd->fps;
93 fd->fps = fps->prev;
94 free(fps);
95 fps = fd->fps;
96 fdFree(fd);
16
Calling 'fdFree'
23
Returning; memory was released
97 return fps;
24
Use of memory after it is freed
98}
99
100void fdSetBundle(FD_t fd, rpmDigestBundle bundle)
101{
102 if (fd)
103 fd->digests = bundle;
104}
105
106rpmDigestBundle fdGetBundle(FD_t fd, int create)
107{
108 rpmDigestBundle bundle = NULL((void*)0);
109 if (fd) {
110 if (fd->digests == NULL((void*)0) && create)
111 fd->digests = rpmDigestBundleNew();
112 bundle = fd->digests;
113 }
114 return bundle;
115}
116
117/** \ingroup rpmio
118 * \name RPMIO Vectors.
119 */
120typedef ssize_t (*fdio_read_function_t) (FDSTACK_t fps, void *buf, size_t nbytes);
121typedef ssize_t (*fdio_write_function_t) (FDSTACK_t fps, const void *buf, size_t nbytes);
122typedef int (*fdio_seek_function_t) (FDSTACK_t fps, off_t pos, int whence);
123typedef int (*fdio_close_function_t) (FDSTACK_t fps);
124typedef FD_t (*fdio_open_function_t) (const char * path, int flags, mode_t mode);
125typedef FD_t (*fdio_fdopen_function_t) (FD_t fd, int fdno, const char * fmode);
126typedef int (*fdio_fflush_function_t) (FDSTACK_t fps);
127typedef long (*fdio_ftell_function_t) (FDSTACK_t fps);
128typedef int (*fdio_ferror_function_t) (FDSTACK_t fps);
129typedef const char * (*fdio_fstrerr_function_t)(FDSTACK_t fps);
130
131struct FDIO_s {
132 const char * ioname;
133 const char * name;
134 fdio_read_function_t read;
135 fdio_write_function_t write;
136 fdio_seek_function_t seek;
137 fdio_close_function_t close;
138
139 fdio_open_function_t _open;
140 fdio_fdopen_function_t _fdopen;
141 fdio_fflush_function_t _fflush;
142 fdio_ftell_function_t _ftell;
143 fdio_ferror_function_t _ferror;
144 fdio_fstrerr_function_t _fstrerr;
145};
146
147/* forward refs */
148static const FDIO_t fdio;
149static const FDIO_t ufdio;
150static const FDIO_t gzdio;
151static const FDIO_t bzdio;
152static const FDIO_t xzdio;
153static const FDIO_t lzdio;
154
155/** \ingroup rpmio
156 * Update digest(s) attached to fd.
157 */
158static void fdUpdateDigests(FD_t fd, const void * buf, size_t buflen);
159static FD_t fdNew(int fdno, const char *descr);
160/**
161 */
162int _rpmio_debug = 0;
163
164/* =============================================================== */
165
166static const char * fdbg(FD_t fd)
167{
168 static char buf[BUFSIZ8192];
169 char *be = buf;
170
171 buf[0] = '\0';
172 if (fd == NULL((void*)0))
173 return buf;
174
175 *be++ = '\t';
176 for (FDSTACK_t fps = fd->fps; fps != NULL((void*)0); fps = fps->prev) {
177 FDIO_t iot = fps->io;
178 if (fps != fd->fps)
179 *be++ = ' ';
180 *be++ = '|';
181 *be++ = ' ';
182 /* plain fd io types dont have _fopen() method */
183 if (iot->_fdopen == NULL((void*)0)) {
184 sprintf(be, "%s %d fp %p", iot->ioname, fps->fdno, fps->fp);
185 } else {
186 sprintf(be, "%s %p fp %d", iot->ioname, fps->fp, fps->fdno);
187 }
188 be += strlen(be);
189 *be = '\0';
190 }
191 return buf;
192}
193
194static void fdstat_enter(FD_t fd, fdOpX opx)
195{
196 if (fd->stats != NULL((void*)0))
197 (void) rpmswEnter(fdOp(fd, opx), (ssize_t) 0);
198}
199
200static void fdstat_exit(FD_t fd, fdOpX opx, ssize_t rc)
201{
202 if (rc == -1) {
203 FDSTACK_t fps = fdGetFps(fd);
204 fps->syserrno = errno(*__errno_location ());
205 }
206 if (fd->stats != NULL((void*)0))
207 (void) rpmswExit(fdOp(fd, opx), rc);
208}
209
210static void fdstat_print(FD_t fd, const char * msg, FILE * fp)
211{
212 static const int usec_scale = (1000*1000);
213 int opx;
214
215 if (fd == NULL((void*)0) || fd->stats == NULL((void*)0)) return;
216 for (opx = 0; opx < 4; opx++) {
217 rpmop op = &fd->stats->ops[opx];
218 if (op->count <= 0) continue;
219 switch (opx) {
220 case FDSTAT_READ:
221 if (msg) fprintf(fp, "%s:", msg);
222 fprintf(fp, "%8d reads, %8ld total bytes in %d.%06d secs\n",
223 op->count, (long)op->bytes,
224 (int)(op->usecs/usec_scale), (int)(op->usecs%usec_scale));
225 break;
226 case FDSTAT_WRITE:
227 if (msg) fprintf(fp, "%s:", msg);
228 fprintf(fp, "%8d writes, %8ld total bytes in %d.%06d secs\n",
229 op->count, (long)op->bytes,
230 (int)(op->usecs/usec_scale), (int)(op->usecs%usec_scale));
231 break;
232 case FDSTAT_SEEK:
233 break;
234 case FDSTAT_CLOSE:
235 break;
236 }
237 }
238}
239
240off_t fdSize(FD_t fd)
241{
242 struct stat sb;
243 off_t rc = -1;
244
245 if (fd != NULL((void*)0) && fstat(Fileno(fd), &sb) == 0)
246 rc = sb.st_size;
247 return rc;
248}
249
250FD_t fdDup(int fdno)
251{
252 FD_t fd;
253 int nfdno;
254
255 if ((nfdno = dup(fdno)) < 0)
256 return NULL((void*)0);
257 fd = fdNew(nfdno, NULL((void*)0));
258DBGIO(fd, (stderr, "==> fdDup(%d) fd %p %s\n", fdno, (fd ? fd : NULL), fdbg(fd)))if ((_rpmio_debug | (((fd)) ? ((FD_t)((fd)))->flags : 0)) &
(0x40000000)) fprintf (stderr, "==> fdDup(%d) fd %p %s\n"
, fdno, (fd ? fd : ((void*)0)), fdbg(fd))
;
259 return fd;
260}
261
262/* Regular fd doesn't have fflush() equivalent but its not an error either */
263static int fdFlush(FDSTACK_t fps)
264{
265 return 0;
266}
267
268static int fdError(FDSTACK_t fps)
269{
270 return fps->syserrno;
271}
272
273static int zfdError(FDSTACK_t fps)
274{
275 return (fps->syserrno || fps->errcookie != NULL((void*)0)) ? -1 : 0;
276}
277
278static const char * fdStrerr(FDSTACK_t fps)
279{
280 return (fps->syserrno != 0) ? strerror(fps->syserrno) : "";
281}
282
283static const char * zfdStrerr(FDSTACK_t fps)
284{
285 return (fps->errcookie != NULL((void*)0)) ? fps->errcookie : "";
286}
287
288const char * Fdescr(FD_t fd)
289{
290 if (fd == NULL((void*)0))
291 return _("[none]")dcgettext ("rpm", "[none]", 5);
292
293 /* Lazy lookup if description is not set (eg dupped fd) */
294 if (fd->descr == NULL((void*)0)) {
295 int fdno = fd->fps->fdno;
296#if defined(__linux__1)
297 /* Grab the path from /proc if we can */
298 char *procpath = NULL((void*)0);
299 char buf[PATH_MAX4096];
300 ssize_t llen;
301
302 rasprintf(&procpath, "/proc/self/fd/%d", fdno);
303 llen = readlink(procpath, buf, sizeof(buf)-1);
304 free(procpath);
305
306 if (llen >= 1) {
307 buf[llen] = '\0';
308 /* Real paths in /proc are always absolute */
309 if (buf[0] == '/')
310 fd->descr = xstrdup(buf)rstrdup((buf));
311 else
312 fd->descr = rstrscat(NULL((void*)0), "[", buf, "]", NULL((void*)0));
313 }
314#endif
315 /* Still no description, base it on fdno which is always there */
316 if (fd->descr == NULL((void*)0))
317 rasprintf(&(fd->descr), "[fd %d]", fdno);
318 }
319 return fd->descr;
320}
321
322FD_t fdLink(FD_t fd)
323{
324 if (fd)
325 fd->nrefs++;
326 return fd;
327}
328
329FD_t fdFree( FD_t fd)
330{
331 if (fd) {
17
Taking true branch
332 if (--fd->nrefs > 0)
18
Assuming the condition is false
19
Taking false branch
333 return fd;
334 fd->stats = _free(fd->stats)rfree((fd->stats));
335 if (fd->digests) {
20
Assuming the condition is false
21
Taking false branch
336 fd->digests = rpmDigestBundleFree(fd->digests);
337 }
338 free(fd->fps);
22
Memory is released
339 free(fd->descr);
340 free(fd);
341 }
342 return NULL((void*)0);
343}
344
345static FD_t fdNew(int fdno, const char *descr)
346{
347 FD_t fd = xcalloc(1, sizeof(*fd))rcalloc((1), (sizeof(*fd)));
348 fd->nrefs = 0;
349 fd->flags = 0;
350 fd->magic = FDMAGIC0x04463138;
351 fd->urlType = URL_IS_UNKNOWN;
352 fd->stats = xcalloc(1, sizeof(*fd->stats))rcalloc((1), (sizeof(*fd->stats)));
353 fd->digests = NULL((void*)0);
354 fd->descr = descr ? xstrdup(descr)rstrdup((descr)) : NULL((void*)0);
355
356 fdPush(fd, fdio, NULL((void*)0), fdno);
357 return fd;
358}
359
360static ssize_t fdRead(FDSTACK_t fps, void * buf, size_t count)
361{
362 return read(fps->fdno, buf, count);
363}
364
365static ssize_t fdWrite(FDSTACK_t fps, const void * buf, size_t count)
366{
367 if (count == 0)
368 return 0;
369
370 return write(fps->fdno, buf, count);
371}
372
373static int fdSeek(FDSTACK_t fps, off_t pos, int whence)
374{
375 return lseek(fps->fdno, pos, whence);
376}
377
378static int fdClose(FDSTACK_t fps)
379{
380 int fdno = fps->fdno;
381 int rc;
382
383 fps->fdno = -1;
384
385 rc = ((fdno >= 0) ? close(fdno) : -2);
386
387 return rc;
388}
389
390static FD_t fdOpen(const char *path, int flags, mode_t mode)
391{
392 FD_t fd;
393 int fdno;
394
395 fdno = open(path, flags, mode);
396 if (fdno < 0) return NULL((void*)0);
397 if (fcntl(fdno, F_SETFD2, FD_CLOEXEC1)) {
398 (void) close(fdno);
399 return NULL((void*)0);
400 }
401 fd = fdNew(fdno, path);
402 fd->flags = flags;
403 return fd;
404}
405
406static long fdTell(FDSTACK_t fps)
407{
408 return lseek(fps->fdno, 0, SEEK_CUR1);
409}
410
411static const struct FDIO_s fdio_s = {
412 "fdio", NULL((void*)0),
413 fdRead, fdWrite, fdSeek, fdClose,
414 fdOpen, NULL((void*)0), fdFlush, fdTell, fdError, fdStrerr,
415};
416static const FDIO_t fdio = &fdio_s ;
417
418off_t ufdCopy(FD_t sfd, FD_t tfd)
419{
420 char buf[BUFSIZ8192];
421 ssize_t rdbytes, wrbytes;
422 off_t total = 0;
423
424 while (1) {
425 rdbytes = Fread(buf, sizeof(buf[0]), sizeof(buf), sfd);
426
427 if (rdbytes > 0) {
428 wrbytes = Fwrite(buf, sizeof(buf[0]), rdbytes, tfd);
429 if (wrbytes != rdbytes) {
430 total = -1;
431 break;
432 }
433 total += wrbytes;
434 } else {
435 if (rdbytes < 0)
436 total = -1;
437 break;
438 }
439 }
440
441 return total;
442}
443
444/*
445 * Deal with remote url's by fetching them with a helper application
446 * and treat as local file afterwards.
447 * TODO:
448 * - better error checking + reporting
449 * - curl & friends don't know about hkp://, transform to http?
450 */
451
452static FD_t urlOpen(const char * url, int flags, mode_t mode)
453{
454 FD_t fd;
455 char *dest = NULL((void*)0);
456 int rc = 1; /* assume failure */
457
458 fd = rpmMkTempFile(NULL((void*)0), &dest);
459 if (fd == NULL((void*)0)) {
460 return NULL((void*)0);
461 }
462 Fclose(fd);
463
464 rc = urlGetFile(url, dest);
465 if (rc == 0) {
466 fd = fdOpen(dest, flags, mode);
467 unlink(dest);
468 } else {
469 fd = NULL((void*)0);
470 }
471 dest = _free(dest)rfree((dest));
472
473 return fd;
474
475}
476static FD_t ufdOpen(const char * url, int flags, mode_t mode)
477{
478 FD_t fd = NULL((void*)0);
479 const char * path;
480 urltype urlType = urlPath(url, &path);
481
482if (_rpmio_debug)
483fprintf(stderrstderr, "*** ufdOpen(%s,0x%x,0%o)\n", url, (unsigned)flags, (unsigned)mode);
484
485 switch (urlType) {
486 case URL_IS_FTP:
487 case URL_IS_HTTPS:
488 case URL_IS_HTTP:
489 case URL_IS_HKP:
490 fd = urlOpen(url, flags, mode);
491 /* we're dealing with local file when urlOpen() returns */
492 urlType = URL_IS_UNKNOWN;
493 break;
494 case URL_IS_DASH:
495 if ((flags & O_ACCMODE0003) == O_RDWR02) {
496 fd = NULL((void*)0);
497 } else {
498 fd = fdDup((flags & O_ACCMODE0003) == O_WRONLY01 ?
499 STDOUT_FILENO1 : STDIN_FILENO0);
500 }
501 break;
502 case URL_IS_PATH:
503 case URL_IS_UNKNOWN:
504 default:
505 fd = fdOpen(path, flags, mode);
506 break;
507 }
508
509 if (fd != NULL((void*)0)) {
510 fd->fps->io = ufdio;
511 fd->urlType = urlType;
512 }
513 return fd;
514}
515
516static const struct FDIO_s ufdio_s = {
517 "ufdio", NULL((void*)0),
518 fdRead, fdWrite, fdSeek, fdClose,
519 ufdOpen, NULL((void*)0), fdFlush, fdTell, fdError, fdStrerr
520};
521static const FDIO_t ufdio = &ufdio_s ;
522
523/* =============================================================== */
524/* Support for GZIP library. */
525#include <zlib.h>
526
527static FD_t gzdFdopen(FD_t fd, int fdno, const char *fmode)
528{
529 gzFile gzfile = gzdopen(fdno, fmode);
530
531 if (gzfile == NULL((void*)0))
532 return NULL((void*)0);
533
534 fdSetFdno(fd, -1); /* XXX skip the fdio close */
535 fdPush(fd, gzdio, gzfile, fdno); /* Push gzdio onto stack */
536 return fd;
537}
538
539static int gzdFlush(FDSTACK_t fps)
540{
541 gzFile gzfile = fps->fp;
542 if (gzfile == NULL((void*)0)) return -2;
543 return gzflush(gzfile, Z_SYNC_FLUSH2); /* XXX W2DO? */
544}
545
546static void gzdSetError(FDSTACK_t fps)
547{
548 gzFile gzfile = fps->fp;
549 int zerror = 0;
550 fps->errcookie = gzerror(gzfile, &zerror);
551 if (zerror == Z_ERRNO(-1)) {
552 fps->syserrno = errno(*__errno_location ());
553 fps->errcookie = strerror(fps->syserrno);
554 }
555}
556
557static ssize_t gzdRead(FDSTACK_t fps, void * buf, size_t count)
558{
559 gzFile gzfile = fps->fp;
560 ssize_t rc;
561
562 if (gzfile == NULL((void*)0)) return -2; /* XXX can't happen */
563
564 rc = gzread(gzfile, buf, count);
565 if (rc < 0)
566 gzdSetError(fps);
567 return rc;
568}
569
570static ssize_t gzdWrite(FDSTACK_t fps, const void * buf, size_t count)
571{
572 gzFile gzfile;
573 ssize_t rc;
574
575 gzfile = fps->fp;
576 if (gzfile == NULL((void*)0)) return -2; /* XXX can't happen */
577
578 rc = gzwrite(gzfile, (void *)buf, count);
579 if (rc < 0)
580 gzdSetError(fps);
581 return rc;
582}
583
584/* XXX zlib-1.0.4 has not */
585static int gzdSeek(FDSTACK_t fps, off_t pos, int whence)
586{
587 off_t p = pos;
588 int rc;
589#if HAVE_GZSEEK1
590 gzFile gzfile = fps->fp;
591
592 if (gzfile == NULL((void*)0)) return -2; /* XXX can't happen */
593
594 rc = gzseek(gzfile, p, whence);
595 if (rc < 0)
596 gzdSetError(fps);
597#else
598 rc = -2;
599#endif
600 return rc;
601}
602
603static int gzdClose(FDSTACK_t fps)
604{
605 gzFile gzfile = fps->fp;
606 int rc;
607
608 if (gzfile == NULL((void*)0)) return -2; /* XXX can't happen */
609
610 rc = gzclose(gzfile);
611
612 return (rc != 0) ? -1 : 0;
613}
614
615static long gzdTell(FDSTACK_t fps)
616{
617 off_t pos = -1;
618 gzFile gzfile = fps->fp;
619
620 if (gzfile != NULL((void*)0)) {
621#if HAVE_GZSEEK1
622 pos = gztell(gzfile);
623 if (pos < 0)
624 gzdSetError(fps);
625#else
626 pos = -2;
627#endif
628 }
629 return pos;
630}
631static const struct FDIO_s gzdio_s = {
632 "gzdio", "gzip",
633 gzdRead, gzdWrite, gzdSeek, gzdClose,
634 NULL((void*)0), gzdFdopen, gzdFlush, gzdTell, zfdError, zfdStrerr
635};
636static const FDIO_t gzdio = &gzdio_s ;
637
638/* =============================================================== */
639/* Support for BZIP2 library. */
640#if HAVE_BZLIB_H1
641
642#include <bzlib.h>
643
644static FD_t bzdFdopen(FD_t fd, int fdno, const char * fmode)
645{
646 BZFILE *bzfile = BZ2_bzdopen(fdno, fmode);
647
648 if (bzfile == NULL((void*)0))
649 return NULL((void*)0);
650
651 fdSetFdno(fd, -1); /* XXX skip the fdio close */
652 fdPush(fd, bzdio, bzfile, fdno); /* Push bzdio onto stack */
653 return fd;
654}
655
656static int bzdFlush(FDSTACK_t fps)
657{
658 return BZ2_bzflush(fps->fp);
659}
660
661static ssize_t bzdRead(FDSTACK_t fps, void * buf, size_t count)
662{
663 BZFILE *bzfile = fps->fp;
664 ssize_t rc = 0;
665
666 if (bzfile)
667 rc = BZ2_bzread(bzfile, buf, count);
668 if (rc == -1) {
669 int zerror = 0;
670 if (bzfile) {
671 fps->errcookie = BZ2_bzerror(bzfile, &zerror);
672 }
673 }
674 return rc;
675}
676
677static ssize_t bzdWrite(FDSTACK_t fps, const void * buf, size_t count)
678{
679 BZFILE *bzfile = fps->fp;
680 ssize_t rc;
681
682 rc = BZ2_bzwrite(bzfile, (void *)buf, count);
683 if (rc == -1) {
684 int zerror = 0;
685 fps->errcookie = BZ2_bzerror(bzfile, &zerror);
686 }
687 return rc;
688}
689
690static int bzdClose(FDSTACK_t fps)
691{
692 BZFILE *bzfile = fps->fp;
693
694 if (bzfile == NULL((void*)0)) return -2;
695
696 /* bzclose() doesn't return errors */
697 BZ2_bzclose(bzfile);
698
699 return 0;
700}
701
702static const struct FDIO_s bzdio_s = {
703 "bzdio", "bzip2",
704 bzdRead, bzdWrite, NULL((void*)0), bzdClose,
705 NULL((void*)0), bzdFdopen, bzdFlush, NULL((void*)0), zfdError, zfdStrerr
706};
707static const FDIO_t bzdio = &bzdio_s ;
708
709#endif /* HAVE_BZLIB_H */
710
711/* =============================================================== */
712/* Support for LZMA library. */
713
714#ifdef HAVE_LZMA_H1
715
716#include <sys/types.h>
717#include <inttypes.h>
718#include <lzma.h>
719/* Multithreading support in stable API since xz 5.2.0 */
720#if LZMA_VERSION(5 * 10000000U + 2 * 10000U + 3 * 10U + 2) >= 50020002
721#define HAVE_LZMA_MT
722#endif
723
724#define kBufferSize(1 << 15) (1 << 15)
725
726typedef struct lzfile {
727 /* IO buffer */
728 uint8_t buf[kBufferSize(1 << 15)];
729
730 lzma_stream strm;
731
732 FILE *file;
733
734 int encoding;
735 int eof;
736
737} LZFILE;
738
739static LZFILE *lzopen_internal(const char *mode, int fd, int xz)
740{
741 int level = LZMA_PRESET_DEFAULT6U;
742 int encoding = 0;
743 FILE *fp;
744 LZFILE *lzfile;
745 lzma_ret ret;
746 lzma_stream init_strm = LZMA_STREAM_INIT{ ((void*)0), 0, 0, ((void*)0), 0, 0, ((void*)0), ((void*)0),
((void*)0), ((void*)0), ((void*)0), ((void*)0), 0, 0, 0, 0, LZMA_RESERVED_ENUM
, LZMA_RESERVED_ENUM }
;
747 uint64_t mem_limit = rpmExpandNumeric("%{_xz_memlimit}");
748#ifdef HAVE_LZMA_MT
749 int threads = 0;
750#endif
751 for (; *mode; mode++) {
752 if (*mode == 'w')
753 encoding = 1;
754 else if (*mode == 'r')
755 encoding = 0;
756 else if (*mode >= '0' && *mode <= '9')
757 level = *mode - '0';
758 else if (*mode == 'T') {
759 if (isdigit(*(mode+1))((*__ctype_b_loc ())[(int) ((*(mode+1)))] & (unsigned short
int) _ISdigit)
) {
760#ifdef HAVE_LZMA_MT
761 threads = atoi(++mode);
762#endif
763 /* skip past rest of digits in string that atoi()
764 * should've processed
765 * */
766 while (isdigit(*++mode)((*__ctype_b_loc ())[(int) ((*++mode))] & (unsigned short
int) _ISdigit)
);
767 }
768#ifdef HAVE_LZMA_MT
769 else
770 threads = -1;
771#endif
772 }
773 }
774 fp = fdopen(fd, encoding ? "w" : "r");
775 if (!fp)
776 return NULL((void*)0);
777 lzfile = calloc(1, sizeof(*lzfile));
778 lzfile->file = fp;
779 lzfile->encoding = encoding;
780 lzfile->eof = 0;
781 lzfile->strm = init_strm;
782 if (encoding) {
783 if (xz) {
784#ifdef HAVE_LZMA_MT
785 if (!threads) {
786#endif
787 ret = lzma_easy_encoder(&lzfile->strm, level, LZMA_CHECK_SHA256);
788#ifdef HAVE_LZMA_MT
789 } else {
790 if (threads == -1)
791 threads = sysconf(_SC_NPROCESSORS_ONLN_SC_NPROCESSORS_ONLN);
792 lzma_mt mt_options = {
793 .flags = 0,
794 .threads = threads,
795 .block_size = 0,
796 .timeout = 0,
797 .preset = level,
798 .filters = NULL((void*)0),
799 .check = LZMA_CHECK_SHA256 };
800
801#if __WORDSIZE64 == 32
802 /* In 32 bit environment, required memory easily exceeds memory address
803 * space limit if compressing using multiple threads.
804 * By setting a memory limit, liblzma will automatically adjust number
805 * of threads to avoid exceeding memory.
806 */
807 if (threads > 1) {
808 struct utsname u;
809 uint32_t memlimit = (SIZE_MAX(18446744073709551615UL)>>1) + (SIZE_MAX(18446744073709551615UL)>>3);
810 uint64_t memory_usage;
811 /* While a 32 bit linux kernel will have an address limit of 3GiB
812 * for processes (which is why set the memory limit to 2.5GiB as a safety
813 * margin), 64 bit kernels will have a limit of 4GiB for 32 bit binaries.
814 * Therefore the memory limit should be higher if running on a 64 bit
815 * kernel, so we increase it to 3,5GiB.
816 */
817 uname(&u);
818 if (strstr(u.machine, "64") || strstr(u.machine, "s390x")
819#if defined(__linux__1)
820 || ((personality(0xffffffff) & PER_MASK) == PER_LINUX32)
821#endif
822 )
823 memlimit += (SIZE_MAX(18446744073709551615UL)>>2);
824
825 /* keep reducing the number of threads until memory usage gets below limit */
826 while ((memory_usage = lzma_stream_encoder_mt_memusage(&mt_options)) > memlimit) {
827 /* number of threads shouldn't be able to hit zero with compression
828 * settings aailable to set through rpm... */
829 assert(--mt_options.threads != 0)({ if (--mt_options.threads != 0) ; else __assert_fail ("--mt_options.threads != 0"
, "rpmio.c", 829, __PRETTY_FUNCTION__); })
;
830 }
831 lzma_memlimit_set(&lzfile->strm, memlimit);
832
833 if (threads != (int)mt_options.threads)
834 rpmlog(RPMLOG_NOTICE,
835 "XZ: Adjusted the number of threads from %d to %d to not exceed the memory usage limit of %lu bytes",
836 threads, mt_options.threads, memlimit);
837 }
838#endif
839
840 ret = lzma_stream_encoder_mt(&lzfile->strm, &mt_options);
841 }
842#endif
843 } else {
844 lzma_options_lzma options;
845 lzma_lzma_preset(&options, level);
846 ret = lzma_alone_encoder(&lzfile->strm, &options);
847 }
848 } else { /* lzma_easy_decoder_memusage(level) is not ready yet, use hardcoded limit for now */
849 ret = lzma_auto_decoder(&lzfile->strm, mem_limit ? mem_limit : 100<<20, 0);
850 }
851 if (ret != LZMA_OK) {
852 switch (ret) {
853 case LZMA_MEM_ERROR:
854 rpmlog(RPMLOG_ERR, "liblzma: Memory allocation failed");
855 break;
856
857 case LZMA_DATA_ERROR:
858 rpmlog(RPMLOG_ERR, "liblzma: File size limits exceeded");
859 break;
860
861 default:
862 rpmlog(RPMLOG_ERR, "liblzma: <Unknown error (%d), possibly a bug", ret);
863 break;
864 }
865 fclose(fp);
866 free(lzfile);
867 return NULL((void*)0);
868 }
869 return lzfile;
870}
871
872static int lzclose(LZFILE *lzfile)
873{
874 lzma_ret ret;
875 size_t n;
876 int rc;
877
878 if (!lzfile)
879 return -1;
880 if (lzfile->encoding) {
881 for (;;) {
882 lzfile->strm.avail_out = kBufferSize(1 << 15);
883 lzfile->strm.next_out = lzfile->buf;
884 ret = lzma_code(&lzfile->strm, LZMA_FINISH);
885 if (ret != LZMA_OK && ret != LZMA_STREAM_END)
886 return -1;
887 n = kBufferSize(1 << 15) - lzfile->strm.avail_out;
888 if (n && fwrite(lzfile->buf, 1, n, lzfile->file) != n)
889 return -1;
890 if (ret == LZMA_STREAM_END)
891 break;
892 }
893 }
894 lzma_end(&lzfile->strm);
895 rc = fclose(lzfile->file);
896 free(lzfile);
897 return rc;
898}
899
900static ssize_t lzread(LZFILE *lzfile, void *buf, size_t len)
901{
902 lzma_ret ret;
903 int eof = 0;
904
905 if (!lzfile || lzfile->encoding)
906 return -1;
907 if (lzfile->eof)
908 return 0;
909 lzfile->strm.next_out = buf;
910 lzfile->strm.avail_out = len;
911 for (;;) {
912 if (!lzfile->strm.avail_in) {
913 lzfile->strm.next_in = lzfile->buf;
914 lzfile->strm.avail_in = fread(lzfile->buf, 1, kBufferSize(1 << 15), lzfile->file);
915 if (!lzfile->strm.avail_in)
916 eof = 1;
917 }
918 ret = lzma_code(&lzfile->strm, LZMA_RUN);
919 if (ret == LZMA_STREAM_END) {
920 lzfile->eof = 1;
921 return len - lzfile->strm.avail_out;
922 }
923 if (ret != LZMA_OK)
924 return -1;
925 if (!lzfile->strm.avail_out)
926 return len;
927 if (eof)
928 return -1;
929 }
930}
931
932static ssize_t lzwrite(LZFILE *lzfile, void *buf, size_t len)
933{
934 lzma_ret ret;
935 size_t n;
936 if (!lzfile || !lzfile->encoding)
937 return -1;
938 if (!len)
939 return 0;
940 lzfile->strm.next_in = buf;
941 lzfile->strm.avail_in = len;
942 for (;;) {
943 lzfile->strm.next_out = lzfile->buf;
944 lzfile->strm.avail_out = kBufferSize(1 << 15);
945 ret = lzma_code(&lzfile->strm, LZMA_RUN);
946 if (ret != LZMA_OK)
947 return -1;
948 n = kBufferSize(1 << 15) - lzfile->strm.avail_out;
949 if (n && fwrite(lzfile->buf, 1, n, lzfile->file) != n)
950 return -1;
951 if (!lzfile->strm.avail_in)
952 return len;
953 }
954}
955
956static FD_t xzdFdopen(FD_t fd, int fdno, const char * fmode)
957{
958 LZFILE *lzfile = lzopen_internal(fmode, fdno, 1);
959
960 if (lzfile == NULL((void*)0))
961 return NULL((void*)0);
962
963 fdSetFdno(fd, -1); /* XXX skip the fdio close */
964 fdPush(fd, xzdio, lzfile, fdno);
965 return fd;
966}
967
968static FD_t lzdFdopen(FD_t fd, int fdno, const char * fmode)
969{
970 LZFILE *lzfile = lzopen_internal(fmode, fdno, 0);
971
972 if (lzfile == NULL((void*)0))
973 return NULL((void*)0);
974
975 fdSetFdno(fd, -1); /* XXX skip the fdio close */
976 fdPush(fd, lzdio, lzfile, fdno);
977 return fd;
978}
979
980static int lzdFlush(FDSTACK_t fps)
981{
982 LZFILE *lzfile = fps->fp;
983 return fflush(lzfile->file);
984}
985
986static ssize_t lzdRead(FDSTACK_t fps, void * buf, size_t count)
987{
988 LZFILE *lzfile = fps->fp;
989 ssize_t rc = 0;
990
991 if (lzfile)
992 rc = lzread(lzfile, buf, count);
993 if (rc == -1) {
994 fps->errcookie = "Lzma: decoding error";
995 }
996 return rc;
997}
998
999static ssize_t lzdWrite(FDSTACK_t fps, const void * buf, size_t count)
1000{
1001 LZFILE *lzfile = fps->fp;
1002 ssize_t rc = 0;
1003
1004 rc = lzwrite(lzfile, (void *)buf, count);
1005 if (rc < 0) {
1006 fps->errcookie = "Lzma: encoding error";
1007 }
1008 return rc;
1009}
1010
1011static int lzdClose(FDSTACK_t fps)
1012{
1013 LZFILE *lzfile = fps->fp;
1014 int rc;
1015
1016 if (lzfile == NULL((void*)0)) return -2;
1017 rc = lzclose(lzfile);
1018
1019 return rc;
1020}
1021
1022static struct FDIO_s xzdio_s = {
1023 "xzdio", "xz",
1024 lzdRead, lzdWrite, NULL((void*)0), lzdClose,
1025 NULL((void*)0), xzdFdopen, lzdFlush, NULL((void*)0), zfdError, zfdStrerr
1026};
1027static const FDIO_t xzdio = &xzdio_s;
1028
1029static struct FDIO_s lzdio_s = {
1030 "lzdio", "lzma",
1031 lzdRead, lzdWrite, NULL((void*)0), lzdClose,
1032 NULL((void*)0), lzdFdopen, lzdFlush, NULL((void*)0), zfdError, zfdStrerr
1033};
1034static const FDIO_t lzdio = &lzdio_s;
1035
1036#endif /* HAVE_LZMA_H */
1037
1038/* =============================================================== */
1039
1040#define FDIOVEC(_fps, _vec)((_fps) && (_fps)->io) ? (_fps)->io->_vec : (
(void*)0)
\
1041 ((_fps) && (_fps)->io) ? (_fps)->io->_vec : NULL((void*)0)
1042
1043const char *Fstrerror(FD_t fd)
1044{
1045 const char *err = "";
1046
1047 if (fd != NULL((void*)0)) {
1048 FDSTACK_t fps = fdGetFps(fd);
1049 fdio_fstrerr_function_t _fstrerr = FDIOVEC(fps, _fstrerr)((fps) && (fps)->io) ? (fps)->io->_fstrerr :
((void*)0)
;
1050 if (_fstrerr)
1051 err = _fstrerr(fps);
1052 } else if (errno(*__errno_location ())){
1053 err = strerror(errno(*__errno_location ()));
1054 }
1055 return err;
1056}
1057
1058ssize_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd)
1059{
1060 ssize_t rc = -1;
1061
1062 if (fd != NULL((void*)0)) {
1063 FDSTACK_t fps = fdGetFps(fd);
1064 fdio_read_function_t _read = FDIOVEC(fps, read)((fps) && (fps)->io) ? (fps)->io->read : ((void
*)0)
;
1065
1066 fdstat_enter(fd, FDSTAT_READ);
1067 do {
1068 rc = (_read ? (*_read) (fps, buf, size * nmemb) : -2);
1069 } while (rc == -1 && errno(*__errno_location ()) == EINTR4);
1070 fdstat_exit(fd, FDSTAT_READ, rc);
1071
1072 if (fd->digests && rc > 0)
1073 fdUpdateDigests(fd, buf, rc);
1074 }
1075
1076 DBGIO(fd, (stderr, "==>\tFread(%p,%p,%ld) rc %ld %s\n",if ((_rpmio_debug | (((fd)) ? ((FD_t)((fd)))->flags : 0)) &
(0x40000000)) fprintf (stderr, "==>\tFread(%p,%p,%ld) rc %ld %s\n"
, fd, buf, (long)size * nmemb, (long)rc, fdbg(fd))
1077 fd, buf, (long)size * nmemb, (long)rc, fdbg(fd)))if ((_rpmio_debug | (((fd)) ? ((FD_t)((fd)))->flags : 0)) &
(0x40000000)) fprintf (stderr, "==>\tFread(%p,%p,%ld) rc %ld %s\n"
, fd, buf, (long)size * nmemb, (long)rc, fdbg(fd))
;
1078
1079 return rc;
1080}
1081
1082ssize_t Fwrite(const void *buf, size_t size, size_t nmemb, FD_t fd)
1083{
1084 ssize_t rc = -1;
1085
1086 if (fd != NULL((void*)0)) {
1087 FDSTACK_t fps = fdGetFps(fd);
1088 fdio_write_function_t _write = FDIOVEC(fps, write)((fps) && (fps)->io) ? (fps)->io->write : ((
void*)0)
;
1089
1090 fdstat_enter(fd, FDSTAT_WRITE);
1091 do {
1092 rc = (_write ? _write(fps, buf, size * nmemb) : -2);
1093 } while (rc == -1 && errno(*__errno_location ()) == EINTR4);
1094 fdstat_exit(fd, FDSTAT_WRITE, rc);
1095
1096 if (fd->digests && rc > 0)
1097 fdUpdateDigests(fd, buf, rc);
1098 }
1099
1100 DBGIO(fd, (stderr, "==>\tFwrite(%p,%p,%ld) rc %ld %s\n",if ((_rpmio_debug | (((fd)) ? ((FD_t)((fd)))->flags : 0)) &
(0x40000000)) fprintf (stderr, "==>\tFwrite(%p,%p,%ld) rc %ld %s\n"
, fd, buf, (long)size * nmemb, (long)rc, fdbg(fd))
1101 fd, buf, (long)size * nmemb, (long)rc, fdbg(fd)))if ((_rpmio_debug | (((fd)) ? ((FD_t)((fd)))->flags : 0)) &
(0x40000000)) fprintf (stderr, "==>\tFwrite(%p,%p,%ld) rc %ld %s\n"
, fd, buf, (long)size * nmemb, (long)rc, fdbg(fd))
;
1102
1103 return rc;
1104}
1105
1106int Fseek(FD_t fd, off_t offset, int whence)
1107{
1108 int rc = -1;
1109
1110 if (fd != NULL((void*)0)) {
1111 FDSTACK_t fps = fdGetFps(fd);
1112 fdio_seek_function_t _seek = FDIOVEC(fps, seek)((fps) && (fps)->io) ? (fps)->io->seek : ((void
*)0)
;
1113
1114 fdstat_enter(fd, FDSTAT_SEEK);
1115 rc = (_seek ? _seek(fps, offset, whence) : -2);
1116 fdstat_exit(fd, FDSTAT_SEEK, rc);
1117 }
1118
1119 DBGIO(fd, (stderr, "==>\tFseek(%p,%ld,%d) rc %lx %s\n",if ((_rpmio_debug | (((fd)) ? ((FD_t)((fd)))->flags : 0)) &
(0x40000000)) fprintf (stderr, "==>\tFseek(%p,%ld,%d) rc %lx %s\n"
, fd, (long)offset, whence, (unsigned long)rc, fdbg(fd))
1120 fd, (long)offset, whence, (unsigned long)rc, fdbg(fd)))if ((_rpmio_debug | (((fd)) ? ((FD_t)((fd)))->flags : 0)) &
(0x40000000)) fprintf (stderr, "==>\tFseek(%p,%ld,%d) rc %lx %s\n"
, fd, (long)offset, whence, (unsigned long)rc, fdbg(fd))
;
1121
1122 return rc;
1123}
1124
1125int Fclose(FD_t fd)
1126{
1127 int rc = 0, ec = 0;
1128
1129 if (fd == NULL((void*)0))
7
Taking false branch
1130 return -1;
1131
1132 fd = fdLink(fd);
1133 fdstat_enter(fd, FDSTAT_CLOSE);
1134 for (FDSTACK_t fps = fd->fps; fps != NULL((void*)0); fps = fdPop(fd)) {
8
Assuming 'fps' is not equal to NULL
9
Loop condition is true. Entering loop body
15
Calling 'fdPop'
1135 if (fps->fdno >= 0) {
10
Assuming the condition is false
11
Taking false branch
1136 fdio_close_function_t _close = FDIOVEC(fps, close)((fps) && (fps)->io) ? (fps)->io->close : ((
void*)0)
;
1137 rc = _close ? _close(fps) : -2;
1138
1139 if (ec == 0 && rc)
1140 ec = rc;
1141 }
1142
1143 /* Debugging stats for compresed types */
1144 if ((_rpmio_debug || rpmIsDebug()(rpmlogSetMask(0) >= (1 << ((unsigned)(RPMLOG_DEBUG)
)))
) && fps->fdno == -1)
12
Assuming '_rpmio_debug' is 0
1145 fdstat_print(fd, fps->io->ioname, stderrstderr);
1146
1147 /* Leave freeing the last one after stats */
1148 if (fps->prev == NULL((void*)0))
13
Assuming the condition is false
14
Taking false branch
1149 break;
1150 }
1151 fdstat_exit(fd, FDSTAT_CLOSE, rc);
1152 DBGIO(fd, (stderr, "==>\tFclose(%p) rc %lx %s\n",if ((_rpmio_debug | (((fd)) ? ((FD_t)((fd)))->flags : 0)) &
(0x40000000)) fprintf (stderr, "==>\tFclose(%p) rc %lx %s\n"
, (fd ? fd : ((void*)0)), (unsigned long)rc, fdbg(fd))
1153 (fd ? fd : NULL), (unsigned long)rc, fdbg(fd)))if ((_rpmio_debug | (((fd)) ? ((FD_t)((fd)))->flags : 0)) &
(0x40000000)) fprintf (stderr, "==>\tFclose(%p) rc %lx %s\n"
, (fd ? fd : ((void*)0)), (unsigned long)rc, fdbg(fd))
;
1154 fdPop(fd);
1155
1156 fdFree(fd);
1157 return ec;
1158}
1159
1160/**
1161 * Convert stdio fmode to open(2) mode, filtering out zlib/bzlib flags.
1162 * returns stdio[0] = NUL on error.
1163 *
1164 * - gzopen: [0-9] is compression level
1165 * - gzopen: 'f' is filtered (Z_FILTERED)
1166 * - gzopen: 'h' is Huffman encoding (Z_HUFFMAN_ONLY)
1167 * - bzopen: [1-9] is block size (modulo 100K)
1168 * - bzopen: 's' is smallmode
1169 * - HACK: '.' terminates, rest is type of I/O
1170 */
1171static void cvtfmode (const char *m,
1172 char *stdio, size_t nstdio,
1173 char *other, size_t nother,
1174 const char **end, int * f)
1175{
1176 int flags = 0;
1177 char c;
1178
1179 switch (*m) {
1180 case 'a':
1181 flags |= O_WRONLY01 | O_CREAT0100 | O_APPEND02000;
1182 if (--nstdio > 0) *stdio++ = *m;
1183 break;
1184 case 'w':
1185 flags |= O_WRONLY01 | O_CREAT0100 | O_TRUNC01000;
1186 if (--nstdio > 0) *stdio++ = *m;
1187 break;
1188 case 'r':
1189 flags |= O_RDONLY00;
1190 if (--nstdio > 0) *stdio++ = *m;
1191 break;
1192 default:
1193 *stdio = '\0';
1194 return;
1195 break;
1196 }
1197 m++;
1198
1199 while ((c = *m++) != '\0') {
1200 switch (c) {
1201 case '.':
1202 break;
1203 case '+':
1204 flags &= ~(O_RDONLY00|O_WRONLY01);
1205 flags |= O_RDWR02;
1206 if (--nstdio > 0) *stdio++ = c;
1207 continue;
1208 break;
1209 case 'b':
1210 if (--nstdio > 0) *stdio++ = c;
1211 continue;
1212 break;
1213 case 'x':
1214 flags |= O_EXCL0200;
1215 if (--nstdio > 0) *stdio++ = c;
1216 continue;
1217 break;
1218 default:
1219 if (--nother > 0) *other++ = c;
1220 continue;
1221 break;
1222 }
1223 break;
1224 }
1225
1226 *stdio = *other = '\0';
1227 if (end != NULL((void*)0))
1228 *end = (*m != '\0' ? m : NULL((void*)0));
1229 if (f != NULL((void*)0))
1230 *f = flags;
1231}
1232
1233static FDIO_t findIOT(const char *name)
1234{
1235 static FDIO_t fdio_types[] = {
1236 &fdio_s,
1237 &ufdio_s,
1238 &gzdio_s,
1239#if HAVE_BZLIB_H1
1240 &bzdio_s,
1241#endif
1242#if HAVE_LZMA_H1
1243 &xzdio_s,
1244 &lzdio_s,
1245#endif
1246 NULL((void*)0)
1247 };
1248 FDIO_t iot = NULL((void*)0);
1249
1250 for (FDIO_t *t = fdio_types; t && *t; t++) {
1251 if (rstreq(name, (*t)->ioname) ||
1252 ((*t)->name && rstreq(name, (*t)->name))) {
1253 iot = (*t);
1254 break;
1255 }
1256 }
1257
1258 return iot;
1259}
1260
1261FD_t Fdopen(FD_t ofd, const char *fmode)
1262{
1263 char stdio[20], other[20], zstdio[40];
1264 const char *end = NULL((void*)0);
1265 FDIO_t iot = NULL((void*)0);
1266 FD_t fd = ofd;
1267 int fdno = Fileno(ofd);
1268
1269if (_rpmio_debug)
1270fprintf(stderrstderr, "*** Fdopen(%p,%s) %s\n", fd, fmode, fdbg(fd));
1271
1272 if (fd == NULL((void*)0) || fmode == NULL((void*)0) || fdno < 0)
1273 return NULL((void*)0);
1274
1275 cvtfmode(fmode, stdio, sizeof(stdio), other, sizeof(other), &end, NULL((void*)0));
1276 if (stdio[0] == '\0')
1277 return NULL((void*)0);
1278 zstdio[0] = '\0';
1279 strncat(zstdio, stdio, sizeof(zstdio) - strlen(zstdio) - 1);
1280 strncat(zstdio, other, sizeof(zstdio) - strlen(zstdio) - 1);
1281
1282 if (end == NULL((void*)0) && other[0] == '\0')
1283 return fd;
1284
1285 if (end && *end) {
1286 iot = findIOT(end);
1287 } else if (other[0] != '\0') {
1288 for (end = other; *end && strchr("0123456789fh", *end); end++)
1289 {};
1290 if (*end == '\0')
1291 iot = findIOT("gzdio");
1292 }
1293
1294 if (iot && iot->_fdopen)
1295 fd = iot->_fdopen(fd, fdno, zstdio);
1296
1297DBGIO(fd, (stderr, "==> Fdopen(%p,\"%s\") returns fd %p %s\n", ofd, fmode, (fd ? fd : NULL), fdbg(fd)))if ((_rpmio_debug | (((fd)) ? ((FD_t)((fd)))->flags : 0)) &
(0x40000000)) fprintf (stderr, "==> Fdopen(%p,\"%s\") returns fd %p %s\n"
, ofd, fmode, (fd ? fd : ((void*)0)), fdbg(fd))
;
1298 return fd;
1299}
1300
1301FD_t Fopen(const char *path, const char *fmode)
1302{
1303 char stdio[20], other[20];
1304 const char *end = NULL((void*)0);
1305 mode_t perms = 0666;
1306 int flags = 0;
1307 FD_t fd = NULL((void*)0);
1308
1309 if (path == NULL((void*)0) || fmode == NULL((void*)0))
1310 return NULL((void*)0);
1311
1312 stdio[0] = '\0';
1313 cvtfmode(fmode, stdio, sizeof(stdio), other, sizeof(other), &end, &flags);
1314 if (stdio[0] == '\0')
1315 return NULL((void*)0);
1316
1317 if (end == NULL((void*)0) || rstreq(end, "fdio")) {
1318 if (_rpmio_debug)
1319 fprintf(stderrstderr, "*** Fopen fdio path %s fmode %s\n", path, fmode);
1320 fd = fdOpen(path, flags, perms);
1321 } else {
1322 if (_rpmio_debug)
1323 fprintf(stderrstderr, "*** Fopen ufdio path %s fmode %s\n", path, fmode);
1324 fd = ufdOpen(path, flags, perms);
1325 }
1326
1327 /* Open compressed stream if necessary */
1328 if (fd)
1329 fd = Fdopen(fd, fmode);
1330
1331 DBGIO(fd, (stderr, "==>\tFopen(\"%s\",%x,0%o) %s\n",if ((_rpmio_debug | (((fd)) ? ((FD_t)((fd)))->flags : 0)) &
(0x40000000)) fprintf (stderr, "==>\tFopen(\"%s\",%x,0%o) %s\n"
, path, (unsigned)flags, (unsigned)perms, fdbg(fd))
1332 path, (unsigned)flags, (unsigned)perms, fdbg(fd)))if ((_rpmio_debug | (((fd)) ? ((FD_t)((fd)))->flags : 0)) &
(0x40000000)) fprintf (stderr, "==>\tFopen(\"%s\",%x,0%o) %s\n"
, path, (unsigned)flags, (unsigned)perms, fdbg(fd))
;
1333
1334 return fd;
1335}
1336
1337int Fflush(FD_t fd)
1338{
1339 int rc = -1;
1340 if (fd != NULL((void*)0)) {
1341 FDSTACK_t fps = fdGetFps(fd);
1342 fdio_fflush_function_t _fflush = FDIOVEC(fps, _fflush)((fps) && (fps)->io) ? (fps)->io->_fflush : (
(void*)0)
;
1343
1344 rc = (_fflush ? _fflush(fps) : -2);
1345 }
1346 return rc;
1347}
1348
1349off_t Ftell(FD_t fd)
1350{
1351 off_t pos = -1;
1352 if (fd != NULL((void*)0)) {
1353 FDSTACK_t fps = fdGetFps(fd);
1354 fdio_ftell_function_t _ftell = FDIOVEC(fps, _ftell)((fps) && (fps)->io) ? (fps)->io->_ftell : (
(void*)0)
;
1355
1356 pos = (_ftell ? _ftell(fps) : -2);
1357 }
1358 return pos;
1359}
1360
1361int Ferror(FD_t fd)
1362{
1363 int rc = 0;
1364
1365 if (fd == NULL((void*)0)) return -1;
1366 for (FDSTACK_t fps = fd->fps; fps != NULL((void*)0); fps = fps->prev) {
1367 fdio_ferror_function_t _ferror = FDIOVEC(fps, _ferror)((fps) && (fps)->io) ? (fps)->io->_ferror : (
(void*)0)
;
1368 rc = _ferror(fps);
1369
1370 if (rc)
1371 break;
1372 }
1373DBGIO(fd, (stderr, "==> Ferror(%p) rc %d %s\n", fd, rc, fdbg(fd)))if ((_rpmio_debug | (((fd)) ? ((FD_t)((fd)))->flags : 0)) &
(0x40000000)) fprintf (stderr, "==> Ferror(%p) rc %d %s\n"
, fd, rc, fdbg(fd))
;
1374 return rc;
1375}
1376
1377int Fileno(FD_t fd)
1378{
1379 int rc = -1;
1380
1381 if (fd == NULL((void*)0)) return -1;
1382 for (FDSTACK_t fps = fd->fps; fps != NULL((void*)0); fps = fps->prev) {
1383 rc = fps->fdno;
1384 if (rc != -1)
1385 break;
1386 }
1387
1388DBGIO(fd, (stderr, "==> Fileno(%p) rc %d %s\n", (fd ? fd : NULL), rc, fdbg(fd)))if ((_rpmio_debug | (((fd)) ? ((FD_t)((fd)))->flags : 0)) &
(0x40000000)) fprintf (stderr, "==> Fileno(%p) rc %d %s\n"
, (fd ? fd : ((void*)0)), rc, fdbg(fd))
;
1389 return rc;
1390}
1391
1392/* XXX this is naive */
1393int Fcntl(FD_t fd, int op, void *lip)
1394{
1395 return fcntl(Fileno(fd), op, lip);
1396}
1397
1398rpmop fdOp(FD_t fd, fdOpX opx)
1399{
1400 rpmop op = NULL((void*)0);
1401
1402 if (fd != NULL((void*)0) && fd->stats != NULL((void*)0) && opx >= 0 && opx < FDSTAT_MAX)
1403 op = fd->stats->ops + opx;
1404 return op;
1405}
1406
1407int rpmioSlurp(const char * fn, uint8_t ** bp, ssize_t * blenp)
1408{
1409 static const ssize_t blenmax = (32 * BUFSIZ8192);
1410 ssize_t blen = 0;
1411 uint8_t * b = NULL((void*)0);
1412 ssize_t size;
1413 FD_t fd;
1414 int rc = 0;
1415
1416 fd = Fopen(fn, "r.ufdio");
1417 if (fd == NULL((void*)0) || Ferror(fd)) {
1
Taking false branch
1418 rc = 2;
1419 goto exit;
1420 }
1421
1422 size = fdSize(fd);
1423 blen = (size >= 0 ? size : blenmax);
2
'?' condition is false
1424 if (blen) {
3
Taking true branch
1425 int nb;
1426 b = xmalloc(blen+1)rmalloc((blen+1));
1427 b[0] = '\0';
1428 nb = Fread(b, sizeof(*b), blen, fd);
1429 if (Ferror(fd) || (size > 0 && nb != blen)) {
1430 rc = 1;
1431 goto exit;
1432 }
1433 if (blen == blenmax && nb < blen) {
4
Taking true branch
1434 blen = nb;
1435 b = xrealloc(b, blen+1)rrealloc((b), (blen+1));
1436 }
1437 b[blen] = '\0';
1438 }
1439
1440exit:
1441 if (fd) (void) Fclose(fd);
5
Taking true branch
6
Calling 'Fclose'
1442
1443 if (rc) {
1444 if (b) free(b);
1445 b = NULL((void*)0);
1446 blen = 0;
1447 }
1448
1449 if (bp) *bp = b;
1450 else if (b) free(b);
1451
1452 if (blenp) *blenp = blen;
1453
1454 return rc;
1455}
1456
1457void fdInitDigest(FD_t fd, int hashalgo, rpmDigestFlags flags)
1458{
1459 return fdInitDigestID(fd, hashalgo, hashalgo, flags);
1460}
1461
1462void fdInitDigestID(FD_t fd, int hashalgo, int id, rpmDigestFlags flags)
1463{
1464 if (fd->digests == NULL((void*)0)) {
1465 fd->digests = rpmDigestBundleNew();
1466 }
1467 fdstat_enter(fd, FDSTAT_DIGEST);
1468 rpmDigestBundleAddID(fd->digests, hashalgo, id, flags);
1469 fdstat_exit(fd, FDSTAT_DIGEST, (ssize_t) 0);
1470}
1471
1472static void fdUpdateDigests(FD_t fd, const void * buf, size_t buflen)
1473{
1474 if (fd && fd->digests) {
1475 fdstat_enter(fd, FDSTAT_DIGEST);
1476 rpmDigestBundleUpdate(fd->digests, buf, buflen);
1477 fdstat_exit(fd, FDSTAT_DIGEST, (ssize_t) buflen);
1478 }
1479}
1480
1481void fdFiniDigest(FD_t fd, int id,
1482 void ** datap, size_t * lenp, int asAscii)
1483{
1484 if (fd && fd->digests) {
1485 fdstat_enter(fd, FDSTAT_DIGEST);
1486 rpmDigestBundleFinal(fd->digests, id, datap, lenp, asAscii);
1487 fdstat_exit(fd, FDSTAT_DIGEST, (ssize_t) 0);
1488 }
1489}
1490
1491DIGEST_CTX fdDupDigest(FD_t fd, int id)
1492{
1493 DIGEST_CTX ctx = NULL((void*)0);
1494
1495 if (fd && fd->digests)
1496 ctx = rpmDigestBundleDupCtx(fd->digests, id);
1497
1498 return ctx;
1499}