Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 1 | From 4d9b6ec30b78d00ead0a22eb5d047dcdba37e99c Mon Sep 17 00:00:00 2001 |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 2 | From: =?UTF-8?q?Neal=20Gompa=20=28=E3=83=8B=E3=83=BC=E3=83=AB=E3=83=BB?= |
| 3 | =?UTF-8?q?=E3=82=B3=E3=82=99=E3=83=B3=E3=83=8F=E3=82=9A=29?= |
| 4 | <ngompa13@gmail.com> |
| 5 | Date: Wed, 11 Nov 2015 20:32:17 -0500 |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 6 | Subject: [PATCH 1/2] Add fallback fopencookie() implementation |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 7 | |
| 8 | In environments where neither fopencookie() nor funopen() |
| 9 | are implemented, we need to provide a suitable implementation |
| 10 | of fopencookie() that we can use. |
| 11 | |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 12 | Alex Kanavin: rebased CMakeLists.txt change to apply to latest upstream code. |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 13 | |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 14 | Upstream-Status: Denied [https://github.com/openSUSE/libsolv/pull/112] |
| 15 | Signed-off-by: Alexander Kanavin <alex.kanavin@gmail.com> |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 16 | --- |
| 17 | ext/CMakeLists.txt | 7 ++ |
| 18 | ext/solv_xfopen.c | 10 +-- |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 19 | ext/solv_xfopen_fallback_fopencookie.c | 123 +++++++++++++++++++++++++++++++++ |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 20 | ext/solv_xfopen_fallback_fopencookie.h | 28 ++++++++ |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 21 | 4 files changed, 164 insertions(+), 4 deletions(-) |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 22 | create mode 100644 ext/solv_xfopen_fallback_fopencookie.c |
| 23 | create mode 100644 ext/solv_xfopen_fallback_fopencookie.h |
| 24 | |
| 25 | diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 26 | index 586eda8..477a2ef 100644 |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 27 | --- a/ext/CMakeLists.txt |
| 28 | +++ b/ext/CMakeLists.txt |
| 29 | @@ -4,6 +4,13 @@ SET (libsolvext_SRCS |
| 30 | SET (libsolvext_HEADERS |
| 31 | tools_util.h solv_xfopen.h testcase.h) |
| 32 | |
| 33 | +IF (NOT HAVE_FOPENCOOKIE AND NOT HAVE_FUNOPEN) |
| 34 | + SET (libsolvext_SRCS ${libsolvext_SRCS} |
| 35 | + solv_xfopen_fallback_fopencookie.c) |
| 36 | + SET (libsolvext_HEADERS ${libsolvext_HEADERS} |
| 37 | + solv_xfopen_fallback_fopencookie.h) |
| 38 | +ENDIF (NOT HAVE_FOPENCOOKIE AND NOT HAVE_FUNOPEN) |
| 39 | + |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 40 | IF (ENABLE_RPMDB OR ENABLE_RPMPKG) |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 41 | SET (libsolvext_SRCS ${libsolvext_SRCS} |
| 42 | pool_fileconflicts.c repo_rpmdb.c) |
| 43 | diff --git a/ext/solv_xfopen.c b/ext/solv_xfopen.c |
| 44 | index b0421bf..31345dd 100644 |
| 45 | --- a/ext/solv_xfopen.c |
| 46 | +++ b/ext/solv_xfopen.c |
| 47 | @@ -13,6 +13,10 @@ |
| 48 | #include <zlib.h> |
| 49 | #include <fcntl.h> |
| 50 | |
| 51 | +#if !defined(HAVE_FUNOPEN) && !defined(HAVE_FOPENCOOKIE) |
| 52 | +#include "solv_xfopen_fallback_fopencookie.h" |
| 53 | +#endif |
| 54 | + |
| 55 | #include "solv_xfopen.h" |
| 56 | #include "util.h" |
| 57 | |
| 58 | @@ -39,7 +43,7 @@ static FILE *cookieopen(void *cookie, const char *mode, |
| 59 | ssize_t (*cwrite)(void *, const char *, size_t), |
| 60 | int (*cclose)(void *)) |
| 61 | { |
| 62 | -#ifdef HAVE_FUNOPEN |
| 63 | +#if defined(HAVE_FUNOPEN) && !defined(HAVE_FOPENCOOKIE) |
| 64 | if (!cookie) |
| 65 | return 0; |
| 66 | return funopen(cookie, |
| 67 | @@ -48,7 +52,7 @@ static FILE *cookieopen(void *cookie, const char *mode, |
| 68 | (fpos_t (*)(void *, fpos_t, int))NULL, /* seekfn */ |
| 69 | cclose |
| 70 | ); |
| 71 | -#elif defined(HAVE_FOPENCOOKIE) |
| 72 | +#else |
| 73 | cookie_io_functions_t cio; |
| 74 | |
| 75 | if (!cookie) |
| 76 | @@ -60,8 +64,6 @@ static FILE *cookieopen(void *cookie, const char *mode, |
| 77 | cio.write = cwrite; |
| 78 | cio.close = cclose; |
| 79 | return fopencookie(cookie, *mode == 'w' ? "w" : "r", cio); |
| 80 | -#else |
| 81 | -# error Need to implement custom I/O |
| 82 | #endif |
| 83 | } |
| 84 | |
| 85 | diff --git a/ext/solv_xfopen_fallback_fopencookie.c b/ext/solv_xfopen_fallback_fopencookie.c |
| 86 | new file mode 100644 |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 87 | index 0000000..0ce2571 |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 88 | --- /dev/null |
| 89 | +++ b/ext/solv_xfopen_fallback_fopencookie.c |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 90 | @@ -0,0 +1,123 @@ |
| 91 | +/* |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 92 | + * Provides a very limited fopencookie() for environments with a libc |
| 93 | + * that lacks it. |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 94 | + * |
| 95 | + * Author: zhasha |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 96 | + * Modified for libsolv by Neal Gompa |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 97 | + * |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 98 | + * This program is licensed under the BSD license, read LICENSE.BSD |
| 99 | + * for further information. |
| 100 | + * |
| 101 | + */ |
| 102 | + |
| 103 | +#define _LARGEFILE64_SOURCE 1 |
| 104 | +#include <pthread.h> |
| 105 | +#include <stdio.h> |
| 106 | +#include <stdlib.h> |
| 107 | +#include <unistd.h> |
| 108 | +#include <fcntl.h> |
| 109 | +#include <sys/types.h> |
| 110 | +#include <errno.h> |
| 111 | +#include "solv_xfopen_fallback_fopencookie.h" |
| 112 | + |
| 113 | +extern int pipe2(int[2], int); |
| 114 | + |
| 115 | +struct ctx { |
| 116 | + int fd; |
| 117 | + void *cookie; |
| 118 | + struct cookie_io_functions_t io; |
| 119 | + char buf[1024]; |
| 120 | +}; |
| 121 | + |
| 122 | +static void *proxy(void *arg) |
| 123 | +{ |
| 124 | + struct ctx *ctx = arg; |
| 125 | + ssize_t r; |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 126 | + size_t n; |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 127 | + |
| 128 | + pthread_detach(pthread_self()); |
| 129 | + |
| 130 | + while (1) { |
| 131 | + r = ctx->io.read ? |
| 132 | + (ctx->io.read)(ctx->cookie, ctx->buf, sizeof(ctx->buf)) : |
| 133 | + read(ctx->fd, ctx->buf, sizeof(ctx->buf)); |
| 134 | + if (r < 0) { |
| 135 | + if (errno != EINTR) { break; } |
| 136 | + continue; |
| 137 | + } |
| 138 | + if (r == 0) { break; } |
| 139 | + |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 140 | + while (n > 0) { |
| 141 | + r = ctx->io.write ? |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 142 | + (ctx->io.write)(ctx->cookie, ctx->buf + ((size_t)r - n), n) : |
| 143 | + write(ctx->fd, ctx->buf + ((size_t)r - n), n); |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 144 | + if (r < 0) { |
| 145 | + if (errno != EINTR) { break; } |
| 146 | + continue; |
| 147 | + } |
| 148 | + if (r == 0) { break; } |
| 149 | + |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 150 | + n -= (size_t)r; |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 151 | + } |
| 152 | + if (n > 0) { break; } |
| 153 | + } |
| 154 | + |
| 155 | + if (ctx->io.close) { (ctx->io.close)(ctx->cookie); } |
| 156 | + close(ctx->fd); |
| 157 | + return NULL; |
| 158 | +} |
| 159 | + |
| 160 | +FILE *fopencookie(void *cookie, const char *mode, struct cookie_io_functions_t io) |
| 161 | +{ |
| 162 | + struct ctx *ctx = NULL; |
| 163 | + int rd = 0, wr = 0; |
| 164 | + int p[2] = { -1, -1 }; |
| 165 | + FILE *f = NULL; |
| 166 | + pthread_t dummy; |
| 167 | + |
| 168 | + switch (mode[0]) { |
| 169 | + case 'a': |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 170 | + case 'r': rd = 1; break; |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 171 | + case 'w': wr = 1; break; |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 172 | + default: |
| 173 | + errno = EINVAL; |
| 174 | + return NULL; |
| 175 | + } |
| 176 | + switch (mode[1]) { |
| 177 | + case '\0': break; |
| 178 | + case '+': |
| 179 | + if (mode[2] == '\0') { |
| 180 | + errno = ENOTSUP; |
| 181 | + return NULL; |
| 182 | + } |
| 183 | + default: |
| 184 | + errno = EINVAL; |
| 185 | + return NULL; |
| 186 | + } |
| 187 | + if (io.seek) { |
| 188 | + errno = ENOTSUP; |
| 189 | + return NULL; |
| 190 | + } |
| 191 | + |
| 192 | + ctx = malloc(sizeof(*ctx)); |
| 193 | + if (!ctx) { return NULL; } |
| 194 | + if (pipe2(p, O_CLOEXEC) != 0) { goto err; } |
| 195 | + if ((f = fdopen(p[wr], mode)) == NULL) { goto err; } |
| 196 | + p[wr] = -1; |
| 197 | + ctx->fd = p[rd]; |
| 198 | + ctx->cookie = cookie; |
| 199 | + ctx->io.read = rd ? io.read : NULL; |
| 200 | + ctx->io.write = wr ? io.write : NULL; |
| 201 | + ctx->io.seek = NULL; |
| 202 | + ctx->io.close = io.close; |
| 203 | + if (pthread_create(&dummy, NULL, proxy, ctx) != 0) { goto err; } |
| 204 | + |
| 205 | + return f; |
| 206 | + |
| 207 | +err: |
| 208 | + if (p[0] >= 0) { close(p[0]); } |
| 209 | + if (p[1] >= 0) { close(p[1]); } |
| 210 | + if (f) { fclose(f); } |
| 211 | + free(ctx); |
| 212 | + return NULL; |
| 213 | +} |
| 214 | diff --git a/ext/solv_xfopen_fallback_fopencookie.h b/ext/solv_xfopen_fallback_fopencookie.h |
| 215 | new file mode 100644 |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 216 | index 0000000..6a7bfee |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 217 | --- /dev/null |
| 218 | +++ b/ext/solv_xfopen_fallback_fopencookie.h |
| 219 | @@ -0,0 +1,28 @@ |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 220 | +/* |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 221 | + * Provides a very limited fopencookie() for environments with a libc |
| 222 | + * that lacks it. |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 223 | + * |
| 224 | + * Author: zhasha |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 225 | + * Modified for libsolv by Neal Gompa |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 226 | + * |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 227 | + * This program is licensed under the BSD license, read LICENSE.BSD |
| 228 | + * for further information. |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 229 | + * |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 230 | + */ |
| 231 | + |
| 232 | +#ifndef SOLV_XFOPEN_FALLBACK_FOPENCOOKIE_H |
| 233 | +#define SOLV_XFOPEN_FALLBACK_FOPENCOOKIE_H |
| 234 | + |
| 235 | +#include <stdio.h> |
| 236 | +#include <stdint.h> |
| 237 | + |
| 238 | +typedef struct cookie_io_functions_t { |
| 239 | + ssize_t (*read)(void *, char *, size_t); |
| 240 | + ssize_t (*write)(void *, const char *, size_t); |
| 241 | + int (*seek)(void *, off64_t, int); |
| 242 | + int (*close)(void *); |
| 243 | +} cookie_io_functions_t; |
| 244 | + |
| 245 | +FILE *fopencookie(void *cookie, const char *mode, struct cookie_io_functions_t io); |
| 246 | + |
| 247 | +#endif |
| 248 | -- |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 249 | 2.11.0 |
Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 250 | |