diff --git a/patches/musl/musl-0001-fopencookie.patch b/patches/musl/musl-0001-fopencookie.patch new file mode 100644 index 0000000..6c9f32c --- /dev/null +++ b/patches/musl/musl-0001-fopencookie.patch @@ -0,0 +1,204 @@ +From 061843340fbf2493bb615e20e66f60c5d1ef0455 Mon Sep 17 00:00:00 2001 +From: William Pitcock +Date: Tue, 5 Dec 2017 16:04:43 -0500 +Subject: implement the fopencookie extension to stdio + +notes added by maintainer: + +this function is a GNU extension. it was chosen over the similar BSD +function funopen because the latter depends on fpos_t being an +arithmetic type as part of its public API, conflicting with our +definition of fpos_t and with the intent that it be an opaque type. it +was accepted for inclusion because, despite not being widely used, it +is usually very difficult to extricate software using it from the +dependency on it. + +calling pattern for the read and write callbacks is not likely to +match glibc or other implementations, but should work with any +reasonable callbacks. in particular the read function is never called +without at least one byte being needed to satisfy its caller, so that +spurious blocking is not introduced. + +contracts for what callbacks called from inside libc/stdio can do are +always complicated, and at some point still need to be specified +explicitly. at the very least, the callbacks must return or block +indefinitely (they cannot perform nonlocal exits) and they should not +make calls to stdio using their own FILE as an argument. +--- + include/stdio.h | 14 +++++ + src/stdio/fopencookie.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 152 insertions(+) + create mode 100644 src/stdio/fopencookie.c + +diff --git a/include/stdio.h b/include/stdio.h +index 884d2e6..2932c76 100644 +--- a/include/stdio.h ++++ b/include/stdio.h +@@ -182,6 +182,20 @@ int vasprintf(char **, const char *, __isoc_va_list); + #ifdef _GNU_SOURCE + char *fgets_unlocked(char *, int, FILE *); + int fputs_unlocked(const char *, FILE *); ++ ++typedef ssize_t (cookie_read_function_t)(void *, char *, size_t); ++typedef ssize_t (cookie_write_function_t)(void *, const char *, size_t); ++typedef int (cookie_seek_function_t)(void *, off_t *, int); ++typedef int (cookie_close_function_t)(void *); ++ ++typedef struct { ++ cookie_read_function_t *read; ++ cookie_write_function_t *write; ++ cookie_seek_function_t *seek; ++ cookie_close_function_t *close; ++} cookie_io_functions_t; ++ ++FILE *fopencookie(void *, const char *, cookie_io_functions_t); + #endif + + #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +diff --git a/src/stdio/fopencookie.c b/src/stdio/fopencookie.c +new file mode 100644 +index 0000000..2f46dd5 +--- /dev/null ++++ b/src/stdio/fopencookie.c +@@ -0,0 +1,138 @@ ++#define _GNU_SOURCE ++#include "stdio_impl.h" ++#include ++#include ++#include ++#include ++#include ++ ++struct fcookie { ++ void *cookie; ++ cookie_io_functions_t iofuncs; ++}; ++ ++struct cookie_FILE { ++ FILE f; ++ struct fcookie fc; ++ unsigned char buf[UNGET+BUFSIZ]; ++}; ++ ++static size_t cookieread(FILE *f, unsigned char *buf, size_t len) ++{ ++ struct fcookie *fc = f->cookie; ++ ssize_t ret = -1; ++ size_t remain = len, readlen = 0; ++ size_t len2 = len - !!f->buf_size; ++ ++ if (!fc->iofuncs.read) goto bail; ++ ++ if (len2) { ++ ret = fc->iofuncs.read(fc->cookie, (char *) buf, len2); ++ if (ret <= 0) goto bail; ++ ++ readlen += ret; ++ remain -= ret; ++ } ++ ++ if (!f->buf_size || remain > !!f->buf_size) return readlen; ++ ++ f->rpos = f->buf; ++ ret = fc->iofuncs.read(fc->cookie, (char *) f->rpos, f->buf_size); ++ if (ret <= 0) goto bail; ++ f->rend = f->rpos + ret; ++ ++ buf[readlen++] = *f->rpos++; ++ ++ return readlen; ++ ++bail: ++ f->flags |= ret == 0 ? F_EOF : F_ERR; ++ f->rpos = f->rend = f->buf; ++ return readlen; ++} ++ ++static size_t cookiewrite(FILE *f, const unsigned char *buf, size_t len) ++{ ++ struct fcookie *fc = f->cookie; ++ ssize_t ret; ++ size_t len2 = f->wpos - f->wbase; ++ if (!fc->iofuncs.write) return len; ++ if (len2) { ++ f->wpos = f->wbase; ++ if (cookiewrite(f, f->wpos, len2) < len2) return 0; ++ } ++ ret = fc->iofuncs.write(fc->cookie, (const char *) buf, len); ++ if (ret < 0) { ++ f->wpos = f->wbase = f->wend = 0; ++ f->flags |= F_ERR; ++ return 0; ++ } ++ return ret; ++} ++ ++static off_t cookieseek(FILE *f, off_t off, int whence) ++{ ++ struct fcookie *fc = f->cookie; ++ int res; ++ if (whence > 2U) { ++ errno = EINVAL; ++ return -1; ++ } ++ if (!fc->iofuncs.seek) { ++ errno = ENOTSUP; ++ return -1; ++ } ++ res = fc->iofuncs.seek(fc->cookie, &off, whence); ++ if (res < 0) ++ return res; ++ return off; ++} ++ ++static int cookieclose(FILE *f) ++{ ++ struct fcookie *fc = f->cookie; ++ if (fc->iofuncs.close) return fc->iofuncs.close(fc->cookie); ++ return 0; ++} ++ ++FILE *fopencookie(void *cookie, const char *mode, cookie_io_functions_t iofuncs) ++{ ++ struct cookie_FILE *f; ++ ++ /* Check for valid initial mode character */ ++ if (!strchr("rwa", *mode)) { ++ errno = EINVAL; ++ return 0; ++ } ++ ++ /* Allocate FILE+fcookie+buffer or fail */ ++ if (!(f=malloc(sizeof *f))) return 0; ++ ++ /* Zero-fill only the struct, not the buffer */ ++ memset(&f->f, 0, sizeof f->f); ++ ++ /* Impose mode restrictions */ ++ if (!strchr(mode, '+')) f->f.flags = (*mode == 'r') ? F_NOWR : F_NORD; ++ ++ /* Set up our fcookie */ ++ f->fc.cookie = cookie; ++ f->fc.iofuncs.read = iofuncs.read; ++ f->fc.iofuncs.write = iofuncs.write; ++ f->fc.iofuncs.seek = iofuncs.seek; ++ f->fc.iofuncs.close = iofuncs.close; ++ ++ f->f.fd = -1; ++ f->f.cookie = &f->fc; ++ f->f.buf = f->buf + UNGET; ++ f->f.buf_size = BUFSIZ; ++ f->f.lbf = EOF; ++ ++ /* Initialize op ptrs. No problem if some are unneeded. */ ++ f->f.read = cookieread; ++ f->f.write = cookiewrite; ++ f->f.seek = cookieseek; ++ f->f.close = cookieclose; ++ ++ /* Add new FILE to open file list */ ++ return __ofl_add(&f->f); ++} +-- +cgit v0.11.2 + diff --git a/patches/musl/musl-0002-fopencookie+abi-compat.patch b/patches/musl/musl-0002-fopencookie+abi-compat.patch new file mode 100644 index 0000000..772994d --- /dev/null +++ b/patches/musl/musl-0002-fopencookie+abi-compat.patch @@ -0,0 +1,27 @@ +From 2488d31f5a946e63e40058baf29fd2991343ea6f Mon Sep 17 00:00:00 2001 +From: Rich Felker +Date: Wed, 6 Dec 2017 13:14:22 -0500 +Subject: adjust fopencookie structure tag for ABI-compat + +stdio types use the struct tag names from glibc libio to match C++ +ABI. +--- + include/stdio.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/stdio.h b/include/stdio.h +index 2932c76..7c4f9ee 100644 +--- a/include/stdio.h ++++ b/include/stdio.h +@@ -188,7 +188,7 @@ typedef ssize_t (cookie_write_function_t)(void *, const char *, size_t); + typedef int (cookie_seek_function_t)(void *, off_t *, int); + typedef int (cookie_close_function_t)(void *); + +-typedef struct { ++typedef struct _IO_cookie_io_functions_t { + cookie_read_function_t *read; + cookie_write_function_t *write; + cookie_seek_function_t *seek; +-- +cgit v0.11.2 + diff --git a/vars/musl.vars b/vars/musl.vars index 9f8473d..77c3603 100644 --- a/vars/musl.vars +++ b/vars/musl.vars @@ -46,7 +46,16 @@ pkg_musl_no_complex_host_all() { set +o noglob; ex_rtl_fileop cp ${PKG_BASE_DIR}/mmglue/* "${PKG_BASE_DIR}/musl-${PKG_VERSION}/"; set -o noglob; - ex_pkg_state_set "${PKG_NAME}" extract -configure; + ex_pkg_state_set "${PKG_NAME}" extract -patch; + fi; + if ! ex_pkg_state_test "${PKG_NAME}" patch "${_restart_at}"; then + set +o noglob; for _patch_fname in \ + "${MIDIPIX_BUILD_PWD}/patches/musl/"*.patch; do + if [ -r "${_patch_fname}" ]; then + patch -b -d "${PKG_BASE_DIR}/musl-${PKG_VERSION}" -p1 < "${_patch_fname}"; + fi; + done; set -o noglob; + ex_pkg_state_set "${PKG_NAME}" patch -configure; fi; if ! ex_pkg_state_test "${PKG_NAME}" configure "${_restart_at}"; then pkgp_musl_configure; @@ -90,7 +99,16 @@ pkg_musl_full_host_all() { set +o noglob; ex_rtl_fileop cp ${PKG_BASE_DIR}/mmglue/* "${PKG_BASE_DIR}/musl-${PKG_VERSION}/"; set -o noglob; - ex_pkg_state_set "${PKG_NAME}" extract -configure; + ex_pkg_state_set "${PKG_NAME}" extract -patch; + fi; + if ! ex_pkg_state_test "${PKG_NAME}" patch "${_restart_at}"; then + set +o noglob; for _patch_fname in \ + "${MIDIPIX_BUILD_PWD}/patches/musl/"*.patch; do + if [ -r "${_patch_fname}" ]; then + patch -b -d "${PKG_BASE_DIR}/musl-${PKG_VERSION}" -p1 < "${_patch_fname}"; + fi; + done; set -o noglob; + ex_pkg_state_set "${PKG_NAME}" patch -configure; fi; if ! ex_pkg_state_test "${PKG_NAME}" configure "${_restart_at}"; then pkgp_musl_configure; @@ -134,7 +152,16 @@ pkg_musl_full_all() { set +o noglob; ex_rtl_fileop cp ${PKG_BASE_DIR}/mmglue/* "${PKG_BASE_DIR}/musl-${PKG_VERSION}/"; set -o noglob; - ex_pkg_state_set "${PKG_NAME}" extract -configure; + ex_pkg_state_set "${PKG_NAME}" extract -patch; + fi; + if ! ex_pkg_state_test "${PKG_NAME}" patch "${_restart_at}"; then + set +o noglob; for _patch_fname in \ + "${MIDIPIX_BUILD_PWD}/patches/musl/"*.patch; do + if [ -r "${_patch_fname}" ]; then + patch -b -d "${PKG_BASE_DIR}/musl-${PKG_VERSION}" -p1 < "${_patch_fname}"; + fi; + done; set -o noglob; + ex_pkg_state_set "${PKG_NAME}" patch -configure; fi; if ! ex_pkg_state_test "${PKG_NAME}" configure "${_restart_at}"; then pkgp_musl_configure;