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 <nenolod@dereferenced.org>
+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 <stdlib.h>
++#include <sys/ioctl.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <string.h>
++
++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 <dalias@aerifal.cx>
+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;