#include <string.h>
#include <fcntl.h>
+#ifdef _WIN32
+ #include "fmemopen.c"
+#endif
+
#include "solv_xfopen.h"
#include "util.h"
+#ifndef WITHOUT_COOKIEOPEN
static FILE *cookieopen(void *cookie, const char *mode,
ssize_t (*cread)(void *, char *, size_t),
#ifdef ENABLE_ZCHUNK_COMPRESSION
+#ifdef WITH_SYSTEM_ZCHUNK
+/* use the system's zchunk library that supports reading and writing of zchunk files */
+
+#include <zck.h>
+
+static ssize_t cookie_zckread(void *cookie, char *buf, size_t nbytes)
+{
+ return zck_read((zckCtx *)cookie, buf, nbytes);
+}
+
+static ssize_t cookie_zckwrite(void *cookie, const char *buf, size_t nbytes)
+{
+ return zck_write((zckCtx *)cookie, buf, nbytes);
+}
+
+static int cookie_zckclose(void *cookie)
+{
+ zckCtx *zck = (zckCtx *)cookie;
+ int fd = zck_get_fd(zck);
+ if (fd != -1)
+ close(fd);
+ zck_free(&zck);
+ return 0;
+}
+
+static void *zchunkopen(const char *path, const char *mode, int fd)
+{
+ zckCtx *f;
+
+ if (!path && fd < 0)
+ return 0;
+ if (fd == -1)
+ {
+ if (*mode != 'w')
+ fd = open(path, O_RDONLY);
+ else
+ fd = open(path, O_WRONLY | O_CREAT, 0666);
+ if (fd == -1)
+ return 0;
+ }
+ f = zck_create();
+ if (!f)
+ {
+ close(fd);
+ return 0;
+ }
+ if (*mode != 'w')
+ {
+ if(!zck_init_read(f, fd))
+ return 0;
+ }
+ else
+ {
+ if(!zck_init_write(f, fd))
+ return 0;
+ }
+ return cookieopen(f, mode, cookie_zckread, cookie_zckwrite, cookie_zckclose);
+}
+
+#else
+
#include "solv_zchunk.h"
+/* use the libsolv's limited zchunk implementation that only supports reading of zchunk files */
static void *zchunkopen(const char *path, const char *mode, int fd)
{
void *f;
if (!path && fd < 0)
return 0;
- if (strcmp(mode, "r") != 0)
- return 0;
if (fd != -1)
fp = fdopen(fd, mode);
else
fp = fopen(path, mode);
if (!fp)
return 0;
+ if (strcmp(mode, "r") != 0)
+ return 0;
f = solv_zchunk_open(fp, 1);
if (!f)
fclose(fp);
return cookieopen(f, mode, (ssize_t (*)(void *, char *, size_t))solv_zchunk_read, 0, (int (*)(void *))solv_zchunk_close);
}
+#endif
+
static inline FILE *myzchunkfopen(const char *fn, const char *mode)
{
return zchunkopen(fn, mode, -1);
return zchunkopen(0, mode, fd);
}
+#endif /* ENABLE_ZCHUNK_COMPRESSION */
+
+#else
+/* no cookies no compression */
+#undef ENABLE_ZLIB_COMPRESSION
+#undef ENABLE_LZMA_COMPRESSION
+#undef ENABLE_BZIP2_COMPRESSION
+#undef ENABLE_ZSTD_COMPRESSION
+#undef ENABLE_ZCHUNK_COMPRESSION
#endif
+
+
FILE *
solv_xfopen(const char *fn, const char *mode)
{
if (suf && !strcmp(suf, ".zck"))
return myzchunkfopen(fn, mode);
#else
- if (suf && !strcmp(suf, ".zst"))
+ if (suf && !strcmp(suf, ".zck"))
return 0;
#endif
return fopen(fn, mode);
suf = fn ? strrchr(fn, '.') : 0;
if (!mode)
{
+ #ifndef _WIN32
int fl = fcntl(fd, F_GETFL, 0);
+ #else
+ HANDLE handle = (HANDLE) _get_osfhandle(fd);
+ BY_HANDLE_FILE_INFORMATION file_info;
+ if (!GetFileInformationByHandle(handle, &file_info))
+ return 0;
+ int fl = file_info.dwFileAttributes;
+ #endif
if (fl == -1)
return 0;
fl &= O_RDONLY|O_WRONLY|O_RDWR;
if (suf && !strcmp(suf, ".zck"))
return myzchunkfdopen(fd, simplemode);
#else
- if (suf && !strcmp(suf, ".zst"))
+ if (suf && !strcmp(suf, ".zck"))
return 0;
#endif
return fdopen(fd, mode);
return 0;
}
+
+#ifndef WITHOUT_COOKIEOPEN
+
struct bufcookie {
char **bufp;
size_t *buflp;
}
return fp;
}
+
+#else
+
+FILE *
+solv_xfopen_buf(const char *fn, char **bufp, size_t *buflp, const char *mode)
+{
+ FILE *fp;
+ size_t l;
+ if (*mode != 'r')
+ return 0;
+ l = buflp ? *buflp : strlen(*bufp);
+ if (!strcmp(mode, "rf"))
+ {
+ if (!(fp = fmemopen(0, l, "r+")))
+ return 0;
+ if (l && fwrite(*bufp, l, 1, fp) != 1)
+ {
+ fclose(fp);
+ return 0;
+ }
+ solv_free(*bufp);
+ rewind(fp);
+ }
+ else
+ fp = fmemopen(*bufp, l, "r");
+ return fp;
+}
+
+#endif
+