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