9 #include <rpm/rpmlog.h>
10 #include <rpm/rpmmacro.h>
11 #include <rpm/rpmfileutil.h>
12 #include <rpm/rpmsw.h>
13 #include <rpm/rpmurl.h>
15 #include "rpmio/rpmio_internal.h"
19 typedef struct _FDSTACK_s {
26 * Cumulative statistics for a descriptor.
29 struct rpmop_s ops[FDSTAT_MAX]; /*!< Cumulative statistics. */
33 * The FD_t File Handle data structure.
38 #define RPMIO_DEBUG_IO 0x40000000
40 #define FDMAGIC 0x04463138
43 int urlType; /* ufdio: */
45 int syserrno; /* last system errno encountered */
46 const char *errcookie; /* gzdio/bzdio/ufdio/xzdio: */
48 char *descr; /* file name (or other description) */
49 FDSTAT_t stats; /* I/O statistics */
51 rpmDigestBundle digests;
54 #define DBG(_f, _m, _x) \
56 if ((_rpmio_debug | ((_f) ? ((FD_t)(_f))->flags : 0)) & (_m)) fprintf _x \
58 #define DBGIO(_f, _x) DBG((_f), RPMIO_DEBUG_IO, _x)
60 static FDIO_t fdGetIo(FD_t fd)
62 return (fd != NULL) ? fd->fps[fd->nfps].io : NULL;
65 static void fdSetIo(FD_t fd, FDIO_t io)
68 fd->fps[fd->nfps].io = io;
71 static void * fdGetFp(FD_t fd)
73 return (fd != NULL) ? fd->fps[fd->nfps].fp : NULL;
76 static void fdSetFp(FD_t fd, void * fp)
79 fd->fps[fd->nfps].fp = fp;
82 static void fdSetFdno(FD_t fd, int fdno)
85 fd->fps[fd->nfps].fdno = fdno;
88 static void fdPush(FD_t fd, FDIO_t io, void * fp, int fdno)
90 if (fd == NULL || fd->nfps >= (sizeof(fd->fps)/sizeof(fd->fps[0]) - 1))
98 static void fdPop(FD_t fd)
100 if (fd == NULL || fd->nfps < 0) return;
107 void fdSetBundle(FD_t fd, rpmDigestBundle bundle)
110 fd->digests = bundle;
113 rpmDigestBundle fdGetBundle(FD_t fd)
115 return (fd != NULL) ? fd->digests : NULL;
118 static void * iotFileno(FD_t fd, FDIO_t iot)
125 for (int i = fd->nfps; i >= 0; i--) {
126 FDSTACK_t * fps = &fd->fps[i];
137 * \name RPMIO Vectors.
139 typedef ssize_t (*fdio_read_function_t) (FD_t fd, void *buf, size_t nbytes);
140 typedef ssize_t (*fdio_write_function_t) (FD_t fd, const void *buf, size_t nbytes);
141 typedef int (*fdio_seek_function_t) (FD_t fd, off_t pos, int whence);
142 typedef int (*fdio_close_function_t) (FD_t fd);
143 typedef FD_t (*fdio_ref_function_t) (FD_t fd);
144 typedef FD_t (*fdio_deref_function_t) (FD_t fd);
145 typedef FD_t (*fdio_new_function_t) (const char *descr);
146 typedef int (*fdio_fileno_function_t) (FD_t fd);
147 typedef FD_t (*fdio_open_function_t) (const char * path, int flags, mode_t mode);
148 typedef FD_t (*fdio_fopen_function_t) (const char * path, const char * fmode);
149 typedef void * (*fdio_ffileno_function_t) (FD_t fd);
150 typedef int (*fdio_fflush_function_t) (FD_t fd);
151 typedef long (*fdio_ftell_function_t) (FD_t);
154 fdio_read_function_t read;
155 fdio_write_function_t write;
156 fdio_seek_function_t seek;
157 fdio_close_function_t close;
159 fdio_ref_function_t _fdref;
160 fdio_deref_function_t _fdderef;
161 fdio_new_function_t _fdnew;
162 fdio_fileno_function_t _fileno;
164 fdio_open_function_t _open;
165 fdio_fopen_function_t _fopen;
166 fdio_ffileno_function_t _ffileno;
167 fdio_fflush_function_t _fflush;
168 fdio_ftell_function_t _ftell;
172 static const FDIO_t fdio;
173 static const FDIO_t ufdio;
174 static const FDIO_t gzdio;
175 static const FDIO_t bzdio;
176 static const FDIO_t xzdio;
177 static const FDIO_t lzdio;
180 * Update digest(s) attached to fd.
182 static void fdUpdateDigests(FD_t fd, const void * buf, size_t buflen);
183 static FD_t fdNew(const char *descr);
186 int _rpmio_debug = 0;
188 /* =============================================================== */
190 static const char * fdbg(FD_t fd)
192 static char buf[BUFSIZ];
201 for (i = fd->nfps; i >= 0; i--) {
202 FDSTACK_t * fps = &fd->fps[i];
207 if (fps->io == fdio) {
208 sprintf(be, "FD %d fp %p", fps->fdno, fps->fp);
209 } else if (fps->io == ufdio) {
210 sprintf(be, "UFD %d fp %p", fps->fdno, fps->fp);
211 } else if (fps->io == gzdio) {
212 sprintf(be, "GZD %p fdno %d", fps->fp, fps->fdno);
214 } else if (fps->io == bzdio) {
215 sprintf(be, "BZD %p fdno %d", fps->fp, fps->fdno);
218 } else if (fps->io == xzdio) {
219 sprintf(be, "XZD %p fdno %d", fps->fp, fps->fdno);
220 } else if (fps->io == lzdio) {
221 sprintf(be, "LZD %p fdno %d", fps->fp, fps->fdno);
224 sprintf(be, "??? io %p fp %p fdno %d ???",
225 fps->io, fps->fp, fps->fdno);
233 static void fdstat_enter(FD_t fd, fdOpX opx)
235 if (fd->stats != NULL)
236 (void) rpmswEnter(fdOp(fd, opx), (ssize_t) 0);
239 static void fdstat_exit(FD_t fd, fdOpX opx, ssize_t rc)
242 fd->syserrno = errno;
243 if (fd->stats != NULL)
244 (void) rpmswExit(fdOp(fd, opx), rc);
247 static void fdstat_print(FD_t fd, const char * msg, FILE * fp)
249 static const int usec_scale = (1000*1000);
252 if (fd == NULL || fd->stats == NULL) return;
253 for (opx = 0; opx < 4; opx++) {
254 rpmop op = &fd->stats->ops[opx];
255 if (op->count <= 0) continue;
258 if (msg) fprintf(fp, "%s:", msg);
259 fprintf(fp, "%8d reads, %8ld total bytes in %d.%06d secs\n",
260 op->count, (long)op->bytes,
261 (int)(op->usecs/usec_scale), (int)(op->usecs%usec_scale));
264 if (msg) fprintf(fp, "%s:", msg);
265 fprintf(fp, "%8d writes, %8ld total bytes in %d.%06d secs\n",
266 op->count, (long)op->bytes,
267 (int)(op->usecs/usec_scale), (int)(op->usecs%usec_scale));
277 off_t fdSize(FD_t fd)
282 if (fd != NULL && fstat(Fileno(fd), &sb) == 0)
292 if ((nfdno = dup(fdno)) < 0)
295 fdSetFdno(fd, nfdno);
296 DBGIO(fd, (stderr, "==> fdDup(%d) fd %p %s\n", fdno, (fd ? fd : NULL), fdbg(fd)));
300 /* Regular fd doesn't have fflush() equivalent but its not an error either */
301 static int fdFlush(FD_t fd)
306 static int fdFileno(FD_t fd)
308 return (fd != NULL) ? fd->fps[0].fdno : -2;
311 const char * Fdescr(FD_t fd)
316 /* Lazy lookup if description is not set (eg dupped fd) */
317 if (fd->descr == NULL) {
318 int fdno = fd->fps[fd->nfps].fdno;
319 #if defined(__linux__)
320 /* Grab the path from /proc if we can */
321 char *procpath = NULL;
325 rasprintf(&procpath, "/proc/self/fd/%d", fdno);
326 llen = readlink(procpath, buf, sizeof(buf)-1);
331 /* Real paths in /proc are always absolute */
333 fd->descr = xstrdup(buf);
335 fd->descr = rstrscat(NULL, "[", buf, "]", NULL);
338 /* Still no description, base it on fdno which is always there */
339 if (fd->descr == NULL)
340 rasprintf(&(fd->descr), "[fd %d]", fdno);
352 FD_t fdFree( FD_t fd)
357 fd->stats = _free(fd->stats);
359 fd->digests = rpmDigestBundleFree(fd->digests);
367 FD_t fdNew(const char *descr)
369 FD_t fd = xcalloc(1, sizeof(*fd));
370 if (fd == NULL) /* XXX xmalloc never returns NULL */
375 fd->urlType = URL_IS_UNKNOWN;
378 memset(fd->fps, 0, sizeof(fd->fps));
380 fd->fps[0].io = fdio;
381 fd->fps[0].fp = NULL;
382 fd->fps[0].fdno = -1;
385 fd->errcookie = NULL;
386 fd->stats = xcalloc(1, sizeof(*fd->stats));
388 fd->descr = descr ? xstrdup(descr) : NULL;
393 static ssize_t fdRead(FD_t fd, void * buf, size_t count)
395 return read(fdFileno(fd), buf, count);
398 static ssize_t fdWrite(FD_t fd, const void * buf, size_t count)
403 return write(fdFileno(fd), buf, count);
406 static int fdSeek(FD_t fd, off_t pos, int whence)
408 return lseek(fdFileno(fd), pos, whence);
411 static int fdClose(FD_t fd)
416 if (fd == NULL) return -2;
421 rc = ((fdno >= 0) ? close(fdno) : -2);
427 static FD_t fdOpen(const char *path, int flags, mode_t mode)
432 fdno = open(path, flags, mode);
433 if (fdno < 0) return NULL;
434 if (fcntl(fdno, F_SETFD, FD_CLOEXEC)) {
444 static long fdTell(FD_t fd)
446 return lseek(Fileno(fd), 0, SEEK_CUR);
449 static const struct FDIO_s fdio_s = {
450 fdRead, fdWrite, fdSeek, fdClose, fdLink, fdFree, fdNew, fdFileno,
451 fdOpen, NULL, fdGetFp, fdFlush, fdTell
453 static const FDIO_t fdio = &fdio_s ;
455 off_t ufdCopy(FD_t sfd, FD_t tfd)
458 ssize_t rdbytes, wrbytes;
462 rdbytes = Fread(buf, sizeof(buf[0]), sizeof(buf), sfd);
465 wrbytes = Fwrite(buf, sizeof(buf[0]), rdbytes, tfd);
466 if (wrbytes != rdbytes) {
482 * Deal with remote url's by fetching them with a helper application
483 * and treat as local file afterwards.
485 * - better error checking + reporting
486 * - curl & friends don't know about hkp://, transform to http?
489 static FD_t urlOpen(const char * url, int flags, mode_t mode)
493 int rc = 1; /* assume failure */
495 fd = rpmMkTempFile(NULL, &dest);
501 rc = urlGetFile(url, dest);
503 fd = fdOpen(dest, flags, mode);
513 static FD_t ufdOpen(const char * url, int flags, mode_t mode)
517 urltype urlType = urlPath(url, &path);
520 fprintf(stderr, "*** ufdOpen(%s,0x%x,0%o)\n", url, (unsigned)flags, (unsigned)mode);
527 fd = urlOpen(url, flags, mode);
528 /* we're dealing with local file when urlOpen() returns */
529 urlType = URL_IS_UNKNOWN;
532 if ((flags & O_ACCMODE) == O_RDWR) {
535 fd = fdDup((flags & O_ACCMODE) == O_WRONLY ?
536 STDOUT_FILENO : STDIN_FILENO);
542 fd = fdOpen(path, flags, mode);
546 if (fd == NULL) return NULL;
549 fd->urlType = urlType;
551 if (Fileno(fd) < 0) {
558 static const struct FDIO_s ufdio_s = {
559 fdRead, fdWrite, fdSeek, fdClose, fdLink, fdFree, fdNew, fdFileno,
560 ufdOpen, NULL, fdGetFp, fdFlush, fdTell
562 static const FDIO_t ufdio = &ufdio_s ;
564 /* =============================================================== */
565 /* Support for GZIP library. */
568 static void * gzdFileno(FD_t fd)
570 return iotFileno(fd, gzdio);
574 FD_t gzdOpen(const char * path, const char * fmode)
578 if ((gzfile = gzopen(path, fmode)) == NULL)
581 fdPop(fd); fdPush(fd, gzdio, gzfile, -1);
586 static FD_t gzdFdopen(FD_t fd, const char *fmode)
591 if (fd == NULL || fmode == NULL) return NULL;
593 fdSetFdno(fd, -1); /* XXX skip the fdio close */
594 if (fdno < 0) return NULL;
595 gzfile = gzdopen(fdno, fmode);
596 if (gzfile == NULL) return NULL;
598 fdPush(fd, gzdio, gzfile, fdno); /* Push gzdio onto stack */
603 static int gzdFlush(FD_t fd)
606 gzfile = gzdFileno(fd);
607 if (gzfile == NULL) return -2;
608 return gzflush(gzfile, Z_SYNC_FLUSH); /* XXX W2DO? */
611 static ssize_t gzdRead(FD_t fd, void * buf, size_t count)
616 gzfile = gzdFileno(fd);
617 if (gzfile == NULL) return -2; /* XXX can't happen */
619 rc = gzread(gzfile, buf, count);
622 fd->errcookie = gzerror(gzfile, &zerror);
623 if (zerror == Z_ERRNO) {
624 fd->syserrno = errno;
625 fd->errcookie = strerror(fd->syserrno);
631 static ssize_t gzdWrite(FD_t fd, const void * buf, size_t count)
636 gzfile = gzdFileno(fd);
637 if (gzfile == NULL) return -2; /* XXX can't happen */
639 rc = gzwrite(gzfile, (void *)buf, count);
642 fd->errcookie = gzerror(gzfile, &zerror);
643 if (zerror == Z_ERRNO) {
644 fd->syserrno = errno;
645 fd->errcookie = strerror(fd->syserrno);
651 /* XXX zlib-1.0.4 has not */
652 static int gzdSeek(FD_t fd, off_t pos, int whence)
659 if (fd == NULL) return -2;
661 gzfile = gzdFileno(fd);
662 if (gzfile == NULL) return -2; /* XXX can't happen */
664 rc = gzseek(gzfile, p, whence);
667 fd->errcookie = gzerror(gzfile, &zerror);
668 if (zerror == Z_ERRNO) {
669 fd->syserrno = errno;
670 fd->errcookie = strerror(fd->syserrno);
679 static int gzdClose(FD_t fd)
684 gzfile = gzdFileno(fd);
685 if (gzfile == NULL) return -2; /* XXX can't happen */
687 rc = gzclose(gzfile);
689 /* XXX TODO: preserve fd if errors */
693 fd->errcookie = "gzclose error";
695 fd->syserrno = errno;
696 fd->errcookie = strerror(fd->syserrno);
701 if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "GZDIO", stderr);
707 static long gzdTell(FD_t fd)
710 gzFile gzfile = gzdFileno(fd);
712 if (gzfile != NULL) {
714 pos = gztell(gzfile);
717 fd->errcookie = gzerror(gzfile, &zerror);
718 if (zerror == Z_ERRNO) {
719 fd->syserrno = errno;
720 fd->errcookie = strerror(fd->syserrno);
729 static const struct FDIO_s gzdio_s = {
730 gzdRead, gzdWrite, gzdSeek, gzdClose, fdLink, fdFree, fdNew, fdFileno,
731 NULL, gzdOpen, gzdFileno, gzdFlush, gzdTell
733 static const FDIO_t gzdio = &gzdio_s ;
735 /* =============================================================== */
736 /* Support for BZIP2 library. */
741 static void * bzdFileno(FD_t fd)
743 return iotFileno(fd, bzdio);
746 static FD_t bzdOpen(const char * path, const char * mode)
750 if ((bzfile = BZ2_bzopen(path, mode)) == NULL)
753 fdPop(fd); fdPush(fd, bzdio, bzfile, -1);
757 static FD_t bzdFdopen(FD_t fd, const char * fmode)
762 if (fd == NULL || fmode == NULL) return NULL;
764 fdSetFdno(fd, -1); /* XXX skip the fdio close */
765 if (fdno < 0) return NULL;
766 bzfile = BZ2_bzdopen(fdno, fmode);
767 if (bzfile == NULL) return NULL;
769 fdPush(fd, bzdio, bzfile, fdno); /* Push bzdio onto stack */
774 static int bzdFlush(FD_t fd)
776 return BZ2_bzflush(bzdFileno(fd));
779 static ssize_t bzdRead(FD_t fd, void * buf, size_t count)
784 bzfile = bzdFileno(fd);
786 rc = BZ2_bzread(bzfile, buf, count);
790 fd->errcookie = BZ2_bzerror(bzfile, &zerror);
795 static ssize_t bzdWrite(FD_t fd, const void * buf, size_t count)
800 bzfile = bzdFileno(fd);
801 rc = BZ2_bzwrite(bzfile, (void *)buf, count);
804 fd->errcookie = BZ2_bzerror(bzfile, &zerror);
809 static int bzdClose(FD_t fd)
814 bzfile = bzdFileno(fd);
816 if (bzfile == NULL) return -2;
819 rc = 0; /* XXX FIXME */
821 /* XXX TODO: preserve fd if errors */
826 fd->errcookie = BZ2_bzerror(bzfile, &zerror);
830 if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "BZDIO", stderr);
836 static const struct FDIO_s bzdio_s = {
837 bzdRead, bzdWrite, NULL, bzdClose, fdLink, fdFree, fdNew, fdFileno,
838 NULL, bzdOpen, bzdFileno, bzdFlush, NULL
840 static const FDIO_t bzdio = &bzdio_s ;
842 #endif /* HAVE_BZLIB_H */
844 static const char * getFdErrstr (FD_t fd)
846 const char *errstr = NULL;
848 if (fdGetIo(fd) == gzdio) {
849 errstr = fd->errcookie;
852 if (fdGetIo(fd) == bzdio) {
853 errstr = fd->errcookie;
855 #endif /* HAVE_BZLIB_H */
857 if (fdGetIo(fd) == xzdio || fdGetIo(fd) == lzdio) {
858 errstr = fd->errcookie;
860 #endif /* HAVE_LZMA_H */
862 errstr = (fd->syserrno ? strerror(fd->syserrno) : "");
868 /* =============================================================== */
869 /* Support for LZMA library. */
873 #include <sys/types.h>
874 #include <inttypes.h>
877 #define kBufferSize (1 << 15)
879 typedef struct lzfile {
881 uint8_t buf[kBufferSize];
892 static LZFILE *lzopen_internal(const char *path, const char *mode, int fd, int xz)
894 int level = 7; /* Use XZ's default compression level if unspecified */
899 lzma_stream init_strm = LZMA_STREAM_INIT;
901 for (; *mode; mode++) {
904 else if (*mode == 'r')
906 else if (*mode >= '1' && *mode <= '9')
910 fp = fdopen(fd, encoding ? "w" : "r");
912 fp = fopen(path, encoding ? "w" : "r");
915 lzfile = calloc(1, sizeof(*lzfile));
922 lzfile->encoding = encoding;
924 lzfile->strm = init_strm;
927 ret = lzma_easy_encoder(&lzfile->strm, level, LZMA_CHECK_SHA256);
929 lzma_options_lzma options;
930 lzma_lzma_preset(&options, level);
931 ret = lzma_alone_encoder(&lzfile->strm, &options);
933 } else { /* lzma_easy_decoder_memusage(level) is not ready yet, use hardcoded limit for now */
934 ret = lzma_auto_decoder(&lzfile->strm, 100<<20, 0);
936 if (ret != LZMA_OK) {
944 static LZFILE *xzopen(const char *path, const char *mode)
946 return lzopen_internal(path, mode, -1, 1);
949 static LZFILE *xzdopen(int fd, const char *mode)
953 return lzopen_internal(0, mode, fd, 1);
956 static LZFILE *lzopen(const char *path, const char *mode)
958 return lzopen_internal(path, mode, -1, 0);
961 static LZFILE *lzdopen(int fd, const char *mode)
965 return lzopen_internal(0, mode, fd, 0);
968 static int lzflush(LZFILE *lzfile)
970 return fflush(lzfile->file);
973 static int lzclose(LZFILE *lzfile)
981 if (lzfile->encoding) {
983 lzfile->strm.avail_out = kBufferSize;
984 lzfile->strm.next_out = lzfile->buf;
985 ret = lzma_code(&lzfile->strm, LZMA_FINISH);
986 if (ret != LZMA_OK && ret != LZMA_STREAM_END)
988 n = kBufferSize - lzfile->strm.avail_out;
989 if (n && fwrite(lzfile->buf, 1, n, lzfile->file) != n)
991 if (ret == LZMA_STREAM_END)
995 lzma_end(&lzfile->strm);
996 rc = fclose(lzfile->file);
1001 static ssize_t lzread(LZFILE *lzfile, void *buf, size_t len)
1006 if (!lzfile || lzfile->encoding)
1010 lzfile->strm.next_out = buf;
1011 lzfile->strm.avail_out = len;
1013 if (!lzfile->strm.avail_in) {
1014 lzfile->strm.next_in = lzfile->buf;
1015 lzfile->strm.avail_in = fread(lzfile->buf, 1, kBufferSize, lzfile->file);
1016 if (!lzfile->strm.avail_in)
1019 ret = lzma_code(&lzfile->strm, LZMA_RUN);
1020 if (ret == LZMA_STREAM_END) {
1022 return len - lzfile->strm.avail_out;
1026 if (!lzfile->strm.avail_out)
1033 static ssize_t lzwrite(LZFILE *lzfile, void *buf, size_t len)
1037 if (!lzfile || !lzfile->encoding)
1041 lzfile->strm.next_in = buf;
1042 lzfile->strm.avail_in = len;
1044 lzfile->strm.next_out = lzfile->buf;
1045 lzfile->strm.avail_out = kBufferSize;
1046 ret = lzma_code(&lzfile->strm, LZMA_RUN);
1049 n = kBufferSize - lzfile->strm.avail_out;
1050 if (n && fwrite(lzfile->buf, 1, n, lzfile->file) != n)
1052 if (!lzfile->strm.avail_in)
1057 static void * lzdFileno(FD_t fd)
1064 for (int i = fd->nfps; i >= 0; i--) {
1065 FDSTACK_t * fps = &fd->fps[i];
1066 if (fps->io != xzdio && fps->io != lzdio)
1074 static FD_t xzdOpen(const char * path, const char * mode)
1078 if ((lzfile = xzopen(path, mode)) == NULL)
1081 fdPop(fd); fdPush(fd, xzdio, lzfile, -1);
1085 static FD_t xzdFdopen(FD_t fd, const char * fmode)
1090 if (fd == NULL || fmode == NULL) return NULL;
1091 fdno = fdFileno(fd);
1092 fdSetFdno(fd, -1); /* XXX skip the fdio close */
1093 if (fdno < 0) return NULL;
1094 lzfile = xzdopen(fdno, fmode);
1095 if (lzfile == NULL) return NULL;
1096 fdPush(fd, xzdio, lzfile, fdno);
1100 static FD_t lzdOpen(const char * path, const char * mode)
1104 if ((lzfile = lzopen(path, mode)) == NULL)
1107 fdPop(fd); fdPush(fd, xzdio, lzfile, -1);
1111 static FD_t lzdFdopen(FD_t fd, const char * fmode)
1116 if (fd == NULL || fmode == NULL) return NULL;
1117 fdno = fdFileno(fd);
1118 fdSetFdno(fd, -1); /* XXX skip the fdio close */
1119 if (fdno < 0) return NULL;
1120 lzfile = lzdopen(fdno, fmode);
1121 if (lzfile == NULL) return NULL;
1122 fdPush(fd, xzdio, lzfile, fdno);
1126 static int lzdFlush(FD_t fd)
1128 return lzflush(lzdFileno(fd));
1131 static ssize_t lzdRead(FD_t fd, void * buf, size_t count)
1136 lzfile = lzdFileno(fd);
1138 rc = lzread(lzfile, buf, count);
1140 fd->errcookie = "Lzma: decoding error";
1145 static ssize_t lzdWrite(FD_t fd, const void * buf, size_t count)
1150 lzfile = lzdFileno(fd);
1152 rc = lzwrite(lzfile, (void *)buf, count);
1154 fd->errcookie = "Lzma: encoding error";
1159 static int lzdClose(FD_t fd)
1164 lzfile = lzdFileno(fd);
1166 if (lzfile == NULL) return -2;
1167 rc = lzclose(lzfile);
1169 /* XXX TODO: preserve fd if errors */
1173 fd->errcookie = "lzclose error";
1174 fd->syserrno = errno;
1175 fd->errcookie = strerror(fd->syserrno);
1179 if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "XZDIO", stderr);
1185 static struct FDIO_s xzdio_s = {
1186 lzdRead, lzdWrite, NULL, lzdClose, NULL, NULL, NULL, fdFileno,
1187 NULL, xzdOpen, lzdFileno, lzdFlush, NULL
1189 static const FDIO_t xzdio = &xzdio_s;
1191 static struct FDIO_s lzdio_s = {
1192 lzdRead, lzdWrite, NULL, lzdClose, NULL, NULL, NULL, fdFileno,
1193 NULL, lzdOpen, lzdFileno, lzdFlush, NULL
1195 static const FDIO_t lzdio = &lzdio_s;
1197 #endif /* HAVE_LZMA_H */
1199 /* =============================================================== */
1201 const char *Fstrerror(FD_t fd)
1204 return (errno ? strerror(errno) : "");
1205 return getFdErrstr(fd);
1208 #define FDIOVEC(_fd, _vec) \
1209 ((fdGetIo(_fd) && fdGetIo(_fd)->_vec) ? fdGetIo(_fd)->_vec : NULL)
1211 ssize_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd)
1216 fdio_read_function_t _read = FDIOVEC(fd, read);
1218 fdstat_enter(fd, FDSTAT_READ);
1220 rc = (_read ? (*_read) (fd, buf, size * nmemb) : -2);
1221 } while (rc == -1 && errno == EINTR);
1222 fdstat_exit(fd, FDSTAT_READ, rc);
1224 if (fd->digests && rc > 0)
1225 fdUpdateDigests(fd, buf, rc);
1228 DBGIO(fd, (stderr, "==>\tFread(%p,%p,%ld) rc %ld %s\n",
1229 fd, buf, (long)size * nmemb, (long)rc, fdbg(fd)));
1234 ssize_t Fwrite(const void *buf, size_t size, size_t nmemb, FD_t fd)
1239 fdio_write_function_t _write = FDIOVEC(fd, write);
1241 fdstat_enter(fd, FDSTAT_WRITE);
1243 rc = (_write ? _write(fd, buf, size * nmemb) : -2);
1244 } while (rc == -1 && errno == EINTR);
1245 fdstat_exit(fd, FDSTAT_WRITE, rc);
1247 if (fd->digests && rc > 0)
1248 fdUpdateDigests(fd, buf, rc);
1251 DBGIO(fd, (stderr, "==>\tFwrite(%p,%p,%ld) rc %ld %s\n",
1252 fd, buf, (long)size * nmemb, (long)rc, fdbg(fd)));
1257 int Fseek(FD_t fd, off_t offset, int whence)
1262 fdio_seek_function_t _seek = FDIOVEC(fd, seek);
1264 fdstat_enter(fd, FDSTAT_SEEK);
1265 rc = (_seek ? _seek(fd, offset, whence) : -2);
1266 fdstat_exit(fd, FDSTAT_SEEK, rc);
1269 DBGIO(fd, (stderr, "==>\tFseek(%p,%ld,%d) rc %lx %s\n",
1270 fd, (long)offset, whence, (unsigned long)rc, fdbg(fd)));
1283 fdstat_enter(fd, FDSTAT_CLOSE);
1284 while (fd->nfps >= 0) {
1285 fdio_close_function_t _close = FDIOVEC(fd, close);
1286 rc = _close ? _close(fd) : -2;
1294 fdstat_exit(fd, FDSTAT_CLOSE, rc);
1295 DBGIO(fd, (stderr, "==>\tFclose(%p) rc %lx %s\n",
1296 (fd ? fd : NULL), (unsigned long)rc, fdbg(fd)));
1303 * Convert stdio fmode to open(2) mode, filtering out zlib/bzlib flags.
1304 * returns stdio[0] = NUL on error.
1306 * - gzopen: [0-9] is compression level
1307 * - gzopen: 'f' is filtered (Z_FILTERED)
1308 * - gzopen: 'h' is Huffman encoding (Z_HUFFMAN_ONLY)
1309 * - bzopen: [1-9] is block size (modulo 100K)
1310 * - bzopen: 's' is smallmode
1311 * - HACK: '.' terminates, rest is type of I/O
1313 static void cvtfmode (const char *m,
1314 char *stdio, size_t nstdio,
1315 char *other, size_t nother,
1316 const char **end, int * f)
1323 flags |= O_WRONLY | O_CREAT | O_APPEND;
1324 if (--nstdio > 0) *stdio++ = *m;
1327 flags |= O_WRONLY | O_CREAT | O_TRUNC;
1328 if (--nstdio > 0) *stdio++ = *m;
1332 if (--nstdio > 0) *stdio++ = *m;
1341 while ((c = *m++) != '\0') {
1346 flags &= ~(O_RDONLY|O_WRONLY);
1348 if (--nstdio > 0) *stdio++ = c;
1352 if (--nstdio > 0) *stdio++ = c;
1357 if (--nstdio > 0) *stdio++ = c;
1361 if (--nother > 0) *other++ = c;
1368 *stdio = *other = '\0';
1370 *end = (*m != '\0' ? m : NULL);
1375 FD_t Fdopen(FD_t ofd, const char *fmode)
1377 char stdio[20], other[20], zstdio[40];
1378 const char *end = NULL;
1383 fprintf(stderr, "*** Fdopen(%p,%s) %s\n", fd, fmode, fdbg(fd));
1385 if (fd == NULL || fmode == NULL)
1388 cvtfmode(fmode, stdio, sizeof(stdio), other, sizeof(other), &end, NULL);
1389 if (stdio[0] == '\0')
1392 strncat(zstdio, stdio, sizeof(zstdio) - strlen(zstdio) - 1);
1393 strncat(zstdio, other, sizeof(zstdio) - strlen(zstdio) - 1);
1395 if (end == NULL && other[0] == '\0')
1399 if (rstreq(end, "fdio")) {
1401 } else if (rstreq(end, "gzdio") || rstreq(end, "gzip")) {
1403 fd = gzdFdopen(fd, zstdio);
1405 } else if (rstreq(end, "bzdio") || rstreq(end, "bzip2")) {
1407 fd = bzdFdopen(fd, zstdio);
1410 } else if (rstreq(end, "xzdio") || rstreq(end, "xz")) {
1412 fd = xzdFdopen(fd, zstdio);
1413 } else if (rstreq(end, "lzdio") || rstreq(end, "lzma")) {
1415 fd = lzdFdopen(fd, zstdio);
1417 } else if (rstreq(end, "ufdio")) {
1420 } else if (other[0] != '\0') {
1421 for (end = other; *end && strchr("0123456789fh", *end); end++)
1425 fd = gzdFdopen(fd, zstdio);
1431 DBGIO(fd, (stderr, "==> Fdopen(%p,\"%s\") returns fd %p %s\n", ofd, fmode, (fd ? fd : NULL), fdbg(fd)));
1435 FD_t Fopen(const char *path, const char *fmode)
1437 char stdio[20], other[20];
1438 const char *end = NULL;
1439 mode_t perms = 0666;
1443 if (path == NULL || fmode == NULL)
1447 cvtfmode(fmode, stdio, sizeof(stdio), other, sizeof(other), &end, &flags);
1448 if (stdio[0] == '\0')
1451 if (end == NULL || rstreq(end, "fdio")) {
1453 fprintf(stderr, "*** Fopen fdio path %s fmode %s\n", path, fmode);
1454 fd = fdOpen(path, flags, perms);
1455 if (fdFileno(fd) < 0) {
1456 if (fd) (void) fdClose(fd);
1460 /* XXX gzdio and bzdio here too */
1462 switch (urlIsURL(path)) {
1469 case URL_IS_UNKNOWN:
1471 fprintf(stderr, "*** Fopen ufdio path %s fmode %s\n", path, fmode);
1472 fd = ufdOpen(path, flags, perms);
1473 if (fd == NULL || !(fdFileno(fd) >= 0))
1478 fprintf(stderr, "*** Fopen WTFO path %s fmode %s\n", path, fmode);
1486 fd = Fdopen(fd, fmode);
1488 DBGIO(fd, (stderr, "==>\tFopen(\"%s\",%x,0%o) %s\n",
1489 path, (unsigned)flags, (unsigned)perms, fdbg(fd)));
1498 fdio_fflush_function_t _fflush = FDIOVEC(fd, _fflush);
1500 rc = (_fflush ? _fflush(fd) : -2);
1505 off_t Ftell(FD_t fd)
1509 fdio_ftell_function_t _ftell = FDIOVEC(fd, _ftell);
1511 pos = (_ftell ? _ftell(fd) : -2);
1520 if (fd == NULL) return -1;
1521 for (i = fd->nfps; rc == 0 && i >= 0; i--) {
1522 FDSTACK_t * fps = &fd->fps[i];
1525 if (fps->io == gzdio) {
1526 ec = (fd->syserrno || fd->errcookie != NULL) ? -1 : 0;
1527 i--; /* XXX fdio under gzdio always has fdno == -1 */
1529 } else if (fps->io == bzdio) {
1530 ec = (fd->syserrno || fd->errcookie != NULL) ? -1 : 0;
1531 i--; /* XXX fdio under bzdio always has fdno == -1 */
1534 } else if (fps->io == xzdio || fps->io == lzdio) {
1535 ec = (fd->syserrno || fd->errcookie != NULL) ? -1 : 0;
1536 i--; /* XXX fdio under xzdio/lzdio always has fdno == -1 */
1539 /* XXX need to check ufdio/gzdio/bzdio/fdio errors correctly. */
1540 ec = (fdFileno(fd) < 0 ? -1 : 0);
1546 DBGIO(fd, (stderr, "==> Ferror(%p) rc %d %s\n", fd, rc, fdbg(fd)));
1554 if (fd == NULL) return -1;
1555 for (i = fd->nfps ; rc == -1 && i >= 0; i--) {
1556 rc = fd->fps[i].fdno;
1559 DBGIO(fd, (stderr, "==> Fileno(%p) rc %d %s\n", (fd ? fd : NULL), rc, fdbg(fd)));
1563 /* XXX this is naive */
1564 int Fcntl(FD_t fd, int op, void *lip)
1566 return fcntl(Fileno(fd), op, lip);
1569 rpmop fdOp(FD_t fd, fdOpX opx)
1573 if (fd != NULL && fd->stats != NULL && opx >= 0 && opx < FDSTAT_MAX)
1574 op = fd->stats->ops + opx;
1578 int rpmioSlurp(const char * fn, uint8_t ** bp, ssize_t * blenp)
1580 static const ssize_t blenmax = (32 * BUFSIZ);
1587 fd = Fopen(fn, "r.ufdio");
1588 if (fd == NULL || Ferror(fd)) {
1594 blen = (size >= 0 ? size : blenmax);
1597 b = xmalloc(blen+1);
1599 nb = Fread(b, sizeof(*b), blen, fd);
1600 if (Ferror(fd) || (size > 0 && nb != blen)) {
1604 if (blen == blenmax && nb < blen) {
1606 b = xrealloc(b, blen+1);
1612 if (fd) (void) Fclose(fd);
1621 else if (b) free(b);
1623 if (blenp) *blenp = blen;
1628 void fdInitDigest(FD_t fd, int hashalgo, rpmDigestFlags flags)
1630 if (fd->digests == NULL) {
1631 fd->digests = rpmDigestBundleNew();
1633 fdstat_enter(fd, FDSTAT_DIGEST);
1634 rpmDigestBundleAdd(fd->digests, hashalgo, flags);
1635 fdstat_exit(fd, FDSTAT_DIGEST, (ssize_t) 0);
1638 static void fdUpdateDigests(FD_t fd, const void * buf, size_t buflen)
1640 if (fd && fd->digests) {
1641 fdstat_enter(fd, FDSTAT_DIGEST);
1642 rpmDigestBundleUpdate(fd->digests, buf, buflen);
1643 fdstat_exit(fd, FDSTAT_DIGEST, (ssize_t) buflen);
1647 void fdFiniDigest(FD_t fd, int hashalgo,
1648 void ** datap, size_t * lenp, int asAscii)
1650 if (fd && fd->digests) {
1651 fdstat_enter(fd, FDSTAT_DIGEST);
1652 rpmDigestBundleFinal(fd->digests, hashalgo, datap, lenp, asAscii);
1653 fdstat_exit(fd, FDSTAT_DIGEST, (ssize_t) 0);