diff --git a/.vscode/settings.json b/.vscode/settings.json index 5814aa12df..eb74f8b3ab 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,7 +16,9 @@ "array": "c", "string": "c", "string_view": "c", - "vector": "c" + "vector": "c", + "php_cli_process_title_arginfo.h": "c", + "php_cli_process_title.h": "c" }, "autoImportFileExcludePatterns": [ "@wp-playground/client" diff --git a/package-lock.json b/package-lock.json index ac2d307a6c..7371bca594 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "file-saver": "^2.0.5", "follow-redirects": "1.15.2", "fs-extra": "11.1.1", + "node-forge": "1.3.1", "octokit": "3.1.1", "octokit-plugin-create-pull-request": "5.1.1", "react": "^18.2.0", @@ -32918,8 +32919,8 @@ }, "node_modules/node-forge": { "version": "1.3.1", - "dev": true, - "license": "(BSD-3-Clause OR GPL-2.0)", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", "engines": { "node": ">= 6.13.0" } diff --git a/package.json b/package.json index 2420479f77..5a91afa438 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "file-saver": "^2.0.5", "follow-redirects": "1.15.2", "fs-extra": "11.1.1", + "node-forge": "1.3.1", "octokit": "3.1.1", "octokit-plugin-create-pull-request": "5.1.1", "react": "^18.2.0", diff --git a/packages/docs/site/docs/11-architecture/18-host-your-own-playground.md b/packages/docs/site/docs/11-architecture/18-host-your-own-playground.md index 2dd5614dd7..fc558a4c4a 100644 --- a/packages/docs/site/docs/11-architecture/18-host-your-own-playground.md +++ b/packages/docs/site/docs/11-architecture/18-host-your-own-playground.md @@ -58,6 +58,7 @@ git clone -b trunk --single-branch --depth 1 git@github.com:WordPress/wordpress- ``` Enter the `wordpress-playground` directory. + ```sh cd wordpress-playground ``` diff --git a/packages/php-wasm/cli/jest.config.ts b/packages/php-wasm/cli/jest.config.ts deleted file mode 100644 index 1fb6ef5671..0000000000 --- a/packages/php-wasm/cli/jest.config.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'nx-extensions', - preset: '../../../jest.preset.js', - transform: { - '^.+\\.[tj]s$': [ - 'ts-jest', - { tsconfig: '/tsconfig.spec.json' }, - ], - }, - moduleFileExtensions: ['ts', 'js', 'html'], - coverageDirectory: '../../../coverage/packages/nx-extensions', -}; diff --git a/packages/php-wasm/compile/Makefile b/packages/php-wasm/compile/Makefile index 63d08d97d2..b372321cd6 100644 --- a/packages/php-wasm/compile/Makefile +++ b/packages/php-wasm/compile/Makefile @@ -88,7 +88,14 @@ oniguruma/dist/root/lib/lib/libonig.a: base-image docker cp $$(docker create playground-php-wasm:oniguruma):/root/lib/lib ./oniguruma/dist/root/lib/ docker cp $$(docker create playground-php-wasm:oniguruma):/root/lib/include ./oniguruma/dist/root/lib -all: libz libzip libpng16 libxml2 libopenssl libsqlite3 libiconv libncurses libedit bison2.7 oniguruma +libcurl: libcurl/dist/root/lib/lib/libcurl.a +libcurl/dist/root/lib/lib/libcurl.a: base-image libz libopenssl + mkdir -p ./libcurl/dist/root/lib + docker build -f ./libcurl/Dockerfile -t playground-php-wasm:libcurl . --progress=plain + docker cp $$(docker create playground-php-wasm:libcurl):/root/curl-7.69.1/lib/.libs ./libcurl/dist/root/lib/lib + docker cp $$(docker create playground-php-wasm:libcurl):/root/curl-7.69.1/include/ ./libcurl/dist/root/lib + +all: libz libzip libpng16 libxml2 libopenssl libsqlite3 libiconv libncurses libedit bison2.7 oniguruma libcurl clean: rm -rf ./libz/dist rm -rf ./libzip/dist diff --git a/packages/php-wasm/compile/build.js b/packages/php-wasm/compile/build.js index 754f1212d1..2c54be4d7f 100644 --- a/packages/php-wasm/compile/build.js +++ b/packages/php-wasm/compile/build.js @@ -123,6 +123,7 @@ const platformDefaults = { }, ['web-light']: {}, ['web-kitchen-sink']: { + WITH_CURL: 'yes', WITH_FILEINFO: 'yes', WITH_ICONV: 'yes', WITH_LIBXML: 'yes', @@ -130,8 +131,10 @@ const platformDefaults = { WITH_MBSTRING: 'yes', WITH_MBREGEX: 'yes', WITH_OPENSSL: 'yes', + WITH_WS_NETWORKING_PROXY: 'yes', }, node: { + WITH_CURL: 'yes', WITH_FILEINFO: 'yes', WITH_ICONV: 'yes', WITH_LIBXML: 'yes', diff --git a/packages/php-wasm/compile/libcurl/Dockerfile b/packages/php-wasm/compile/libcurl/Dockerfile new file mode 100644 index 0000000000..f002d396b1 --- /dev/null +++ b/packages/php-wasm/compile/libcurl/Dockerfile @@ -0,0 +1,38 @@ +FROM playground-php-wasm:base + +RUN mkdir -p /root/lib/include /root/lib/lib +COPY ./libz/dist/root/lib/include /root/lib/include +COPY ./libz/dist/root/lib/lib /root/lib/lib +COPY ./libopenssl/dist/root/lib/include /root/lib/include +COPY ./libopenssl/dist/root/lib/lib /root/lib/lib + +ARG CURL_VERSION="curl-7.69.1" + +RUN /root/copy-lib.sh lib-libz +RUN set -euxo pipefail && \ + source /root/emsdk/emsdk_env.sh && \ + wget https://curl.haxx.se/download/$CURL_VERSION.tar.gz && \ + tar xf $CURL_VERSION.tar.gz + +WORKDIR /root/$CURL_VERSION + +RUN CPPFLAGS="-I/root/lib/include " \ + LDFLAGS="-L/root/lib/lib " \ + PKG_CONFIG_PATH=$PKG_CONFIG_PATH \ + source /root/emsdk/emsdk_env.sh && \ + emconfigure ./configure \ + --build i386-pc-linux-gnu \ + --target wasm32-unknown-emscripten \ + --prefix=/root/install/ \ + --disable-shared \ + --enable-static \ + --with-openssl \ + --enable-https \ + --enable-http \ + --disable-pthreads \ + --disable-threaded-resolver \ + --with-zlib=/root/lib + +RUN source /root/emsdk/emsdk_env.sh && \ + EMCC_SKIP="-lc -lz -lcurl" \ + EMCC_FLAGS="-sSIDE_MODULE -Wl,--wrap=select " emmake make || true \ No newline at end of file diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/Makefile b/packages/php-wasm/compile/libcurl/dist/root/lib/include/Makefile new file mode 100644 index 0000000000..0ee094e28b --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/Makefile @@ -0,0 +1,726 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# include/Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/curl +pkgincludedir = $(includedir)/curl +pkglibdir = $(libdir)/curl +pkglibexecdir = $(libexecdir)/curl +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = i386-pc-linux-gnu +host_triplet = i386-pc-linux-gnu +subdir = include +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compile_check_sizeof.m4 \ + $(top_srcdir)/m4/curl-compilers.m4 \ + $(top_srcdir)/m4/curl-confopts.m4 \ + $(top_srcdir)/m4/curl-functions.m4 \ + $(top_srcdir)/m4/curl-openssl.m4 \ + $(top_srcdir)/m4/curl-override.m4 \ + $(top_srcdir)/m4/curl-reentrant.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/xc-am-iface.m4 \ + $(top_srcdir)/m4/xc-cc-check.m4 \ + $(top_srcdir)/m4/xc-lt-iface.m4 \ + $(top_srcdir)/m4/xc-translit.m4 \ + $(top_srcdir)/m4/xc-val-flgs.m4 \ + $(top_srcdir)/m4/zz40-xc-ovr.m4 \ + $(top_srcdir)/m4/zz50-xc-ovr.m4 \ + $(top_srcdir)/m4/zz60-xc-ovr.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/lib/curl_config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_$(V)) +am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +am__v_at_1 = +depcomp = +am__maybe_remake_depfiles = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = ${SHELL} /root/curl-7.69.1/missing aclocal-1.16 +AMTAR = $${TAR-tar} +AM_DEFAULT_VERBOSITY = 0 +AR = /root/emsdk/upstream/emscripten/emar +AR_FLAGS = cr +AS = as +AUTOCONF = ${SHELL} /root/curl-7.69.1/missing autoconf +AUTOHEADER = ${SHELL} /root/curl-7.69.1/missing autoheader +AUTOMAKE = ${SHELL} /root/curl-7.69.1/missing automake-1.16 +AWK = mawk +BLANK_AT_MAKETIME = +CC = /root/emsdk/upstream/emscripten/emcc +CCDEPMODE = depmode=gcc3 +CFLAGS = -Qunused-arguments -Os +CFLAG_CURL_SYMBOL_HIDING = -fvisibility=hidden +CONFIGURE_OPTIONS = " '--build' 'i386-pc-linux-gnu' '--target' 'wasm32-unknown-emscripten' '--prefix=/root/install/' '--disable-shared' '--enable-static' '--with-openssl' '--enable-https' '--enable-http' '--disable-pthreads' '--disable-threaded-resolver' '--with-zlib=/root/lib' 'build_alias=i386-pc-linux-gnu' 'target_alias=wasm32-unknown-emscripten' 'CC=/root/emsdk/upstream/emscripten/emcc'" +CPP = /root/emsdk/upstream/emscripten/emcc -E +CPPFLAGS = -I/root/lib/include +CPPFLAG_CURL_STATICLIB = -DCURL_STATICLIB +CURLVERSION = 7.69.1 +CURL_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt" +CURL_CFLAG_EXTRAS = +CURL_DISABLE_DICT = +CURL_DISABLE_FILE = +CURL_DISABLE_FTP = +CURL_DISABLE_GOPHER = +CURL_DISABLE_HTTP = +CURL_DISABLE_IMAP = +CURL_DISABLE_LDAP = 1 +CURL_DISABLE_LDAPS = 1 +CURL_DISABLE_POP3 = +CURL_DISABLE_PROXY = +CURL_DISABLE_RTSP = +CURL_DISABLE_SMB = +CURL_DISABLE_SMTP = +CURL_DISABLE_TELNET = +CURL_DISABLE_TFTP = +CURL_LT_SHLIB_VERSIONED_FLAVOUR = +CURL_NETWORK_AND_TIME_LIBS = +CURL_NETWORK_LIBS = +CURL_WITH_MULTI_SSL = +CYGPATH_W = echo +DEFAULT_SSL_BACKEND = no +DEFS = -DHAVE_CONFIG_H +DEPDIR = .deps +DLLTOOL = false +DSYMUTIL = +DUMPBIN = +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = /usr/bin/grep -E +ENABLE_SHARED = no +ENABLE_STATIC = yes +EXEEXT = +FGREP = /usr/bin/grep -F +FISH_FUNCTIONS_DIR = ${prefix}/share/fish/vendor_completions.d +GCOV = +GREP = /usr/bin/grep +HAVE_BROTLI = +HAVE_GNUTLS_SRP = +HAVE_LDAP_SSL = 1 +HAVE_LIBZ = 1 +HAVE_OPENSSL_SRP = 1 +HAVE_PROTO_BSDSOCKET_H = +IDN_ENABLED = +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = $(install_sh) -c -s +IPV6_ENABLED = +LCOV = +LD = /root/emsdk/upstream/emscripten/emcc +LDFLAGS = -L/root/lib/lib +LIBCURL_LIBS = -lssl -lcrypto -lz +LIBMETALINK_CPPFLAGS = +LIBMETALINK_LDFLAGS = +LIBMETALINK_LIBS = +LIBOBJS = +LIBS = -lssl -lcrypto -lz +LIBTOOL = $(SHELL) $(top_builddir)/libtool +LIPO = +LN_S = ln -s +LTLIBOBJS = +LT_SYS_LIBRARY_PATH = +MAINT = # +MAKEINFO = ${SHELL} /root/curl-7.69.1/missing makeinfo +MANIFEST_TOOL = : +MANOPT = +MKDIR_P = /usr/bin/mkdir -p +NM = /root/emsdk/upstream/bin/llvm-nm +NMEDIT = +NROFF = +NSS_LIBS = +OBJDUMP = objdump +OBJEXT = o +OTOOL = +OTOOL64 = +PACKAGE = curl +PACKAGE_BUGREPORT = a suitable curl mailing list: https://curl.haxx.se/mail/ +PACKAGE_NAME = curl +PACKAGE_STRING = curl - +PACKAGE_TARNAME = curl +PACKAGE_URL = +PACKAGE_VERSION = - +PATH_SEPARATOR = : +PERL = /usr/bin/perl +PKGADD_NAME = curl - a client that groks URLs +PKGADD_PKG = HAXXcurl +PKGADD_VENDOR = curl.haxx.se +PKGCONFIG = no +RANDOM_FILE = /dev/urandom +RANLIB = /root/emsdk/upstream/emscripten/emranlib +REQUIRE_LIB_DEPS = yes +SED = /usr/bin/sed +SET_MAKE = +SHELL = /bin/bash +SSL_BACKENDS = OpenSSL +SSL_ENABLED = 1 +SSL_LIBS = +STRIP = strip +SUPPORT_FEATURES = SSL UnixSockets libz NTLM NTLM_WB TLS-SRP HTTPS-proxy +SUPPORT_PROTOCOLS = DICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS POP3 POP3S RTSP SMB SMBS SMTP SMTPS TELNET TFTP +USE_ARES = +USE_BEARSSL = +USE_GNUTLS = +USE_GNUTLS_NETTLE = +USE_LIBRTMP = +USE_LIBSSH = +USE_LIBSSH2 = +USE_MBEDTLS = +USE_MESALINK = +USE_NGHTTP2 = +USE_NGHTTP3 = +USE_NGTCP2 = +USE_NGTCP2_CRYPTO_OPENSSL = +USE_NSS = +USE_OPENLDAP = +USE_QUICHE = +USE_SCHANNEL = +USE_SECTRANSP = +USE_UNIX_SOCKETS = 1 +USE_WINDOWS_SSPI = +USE_WOLFSSH = +USE_WOLFSSL = +VERSION = - +VERSIONNUM = 074501 +ZLIB_LIBS = -lz +ZSH_FUNCTIONS_DIR = ${prefix}/share/zsh/site-functions +abs_builddir = /root/curl-7.69.1/include +abs_srcdir = /root/curl-7.69.1/include +abs_top_builddir = /root/curl-7.69.1 +abs_top_srcdir = /root/curl-7.69.1 +ac_ct_AR = +ac_ct_CC = /root/emsdk/upstream/emscripten/emcc +ac_ct_DUMPBIN = +am__include = include +am__leading_dot = . +am__quote = +am__tar = $${TAR-tar} chof - "$$tardir" +am__untar = $${TAR-tar} xf - +bindir = ${exec_prefix}/bin +build = i386-pc-linux-gnu +build_alias = i386-pc-linux-gnu +build_cpu = i386 +build_os = linux-gnu +build_vendor = pc +builddir = . +datadir = ${datarootdir} +datarootdir = ${prefix}/share +docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} +dvidir = ${docdir} +exec_prefix = ${prefix} +host = i386-pc-linux-gnu +host_alias = +host_cpu = i386 +host_os = linux-gnu +host_vendor = pc +htmldir = ${docdir} +includedir = ${prefix}/include +infodir = ${datarootdir}/info +install_sh = ${SHELL} /root/curl-7.69.1/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +libext = a +localedir = ${datarootdir}/locale +localstatedir = ${prefix}/var +mandir = ${datarootdir}/man +mkdir_p = $(MKDIR_P) +oldincludedir = /usr/include +pdfdir = ${docdir} +prefix = /root/install +program_transform_name = s,x,x, +psdir = ${docdir} +runstatedir = ${localstatedir}/run +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +srcdir = . +subdirs = +sysconfdir = ${prefix}/etc +target_alias = wasm32-unknown-emscripten +top_build_prefix = ../ +top_builddir = .. +top_srcdir = .. +SUBDIRS = curl +EXTRA_DIST = README +AUTOMAKE_OPTIONS = foreign no-dependencies +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: # $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign include/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: # $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): # $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/Makefile.am b/packages/php-wasm/compile/libcurl/dist/root/lib/include/Makefile.am new file mode 100644 index 0000000000..3b24860299 --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/Makefile.am @@ -0,0 +1,5 @@ +SUBDIRS = curl + +EXTRA_DIST = README + +AUTOMAKE_OPTIONS = foreign no-dependencies diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/Makefile.in b/packages/php-wasm/compile/libcurl/dist/root/lib/include/Makefile.in new file mode 100644 index 0000000000..863cac661c --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/Makefile.in @@ -0,0 +1,726 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = include +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compile_check_sizeof.m4 \ + $(top_srcdir)/m4/curl-compilers.m4 \ + $(top_srcdir)/m4/curl-confopts.m4 \ + $(top_srcdir)/m4/curl-functions.m4 \ + $(top_srcdir)/m4/curl-openssl.m4 \ + $(top_srcdir)/m4/curl-override.m4 \ + $(top_srcdir)/m4/curl-reentrant.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/xc-am-iface.m4 \ + $(top_srcdir)/m4/xc-cc-check.m4 \ + $(top_srcdir)/m4/xc-lt-iface.m4 \ + $(top_srcdir)/m4/xc-translit.m4 \ + $(top_srcdir)/m4/xc-val-flgs.m4 \ + $(top_srcdir)/m4/zz40-xc-ovr.m4 \ + $(top_srcdir)/m4/zz50-xc-ovr.m4 \ + $(top_srcdir)/m4/zz60-xc-ovr.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/lib/curl_config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +depcomp = +am__maybe_remake_depfiles = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AR_FLAGS = @AR_FLAGS@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BLANK_AT_MAKETIME = @BLANK_AT_MAKETIME@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_CURL_SYMBOL_HIDING = @CFLAG_CURL_SYMBOL_HIDING@ +CONFIGURE_OPTIONS = @CONFIGURE_OPTIONS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAG_CURL_STATICLIB = @CPPFLAG_CURL_STATICLIB@ +CURLVERSION = @CURLVERSION@ +CURL_CA_BUNDLE = @CURL_CA_BUNDLE@ +CURL_CFLAG_EXTRAS = @CURL_CFLAG_EXTRAS@ +CURL_DISABLE_DICT = @CURL_DISABLE_DICT@ +CURL_DISABLE_FILE = @CURL_DISABLE_FILE@ +CURL_DISABLE_FTP = @CURL_DISABLE_FTP@ +CURL_DISABLE_GOPHER = @CURL_DISABLE_GOPHER@ +CURL_DISABLE_HTTP = @CURL_DISABLE_HTTP@ +CURL_DISABLE_IMAP = @CURL_DISABLE_IMAP@ +CURL_DISABLE_LDAP = @CURL_DISABLE_LDAP@ +CURL_DISABLE_LDAPS = @CURL_DISABLE_LDAPS@ +CURL_DISABLE_POP3 = @CURL_DISABLE_POP3@ +CURL_DISABLE_PROXY = @CURL_DISABLE_PROXY@ +CURL_DISABLE_RTSP = @CURL_DISABLE_RTSP@ +CURL_DISABLE_SMB = @CURL_DISABLE_SMB@ +CURL_DISABLE_SMTP = @CURL_DISABLE_SMTP@ +CURL_DISABLE_TELNET = @CURL_DISABLE_TELNET@ +CURL_DISABLE_TFTP = @CURL_DISABLE_TFTP@ +CURL_LT_SHLIB_VERSIONED_FLAVOUR = @CURL_LT_SHLIB_VERSIONED_FLAVOUR@ +CURL_NETWORK_AND_TIME_LIBS = @CURL_NETWORK_AND_TIME_LIBS@ +CURL_NETWORK_LIBS = @CURL_NETWORK_LIBS@ +CURL_WITH_MULTI_SSL = @CURL_WITH_MULTI_SSL@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_SSL_BACKEND = @DEFAULT_SSL_BACKEND@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SHARED = @ENABLE_SHARED@ +ENABLE_STATIC = @ENABLE_STATIC@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@ +GCOV = @GCOV@ +GREP = @GREP@ +HAVE_BROTLI = @HAVE_BROTLI@ +HAVE_GNUTLS_SRP = @HAVE_GNUTLS_SRP@ +HAVE_LDAP_SSL = @HAVE_LDAP_SSL@ +HAVE_LIBZ = @HAVE_LIBZ@ +HAVE_OPENSSL_SRP = @HAVE_OPENSSL_SRP@ +HAVE_PROTO_BSDSOCKET_H = @HAVE_PROTO_BSDSOCKET_H@ +IDN_ENABLED = @IDN_ENABLED@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPV6_ENABLED = @IPV6_ENABLED@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCURL_LIBS = @LIBCURL_LIBS@ +LIBMETALINK_CPPFLAGS = @LIBMETALINK_CPPFLAGS@ +LIBMETALINK_LDFLAGS = @LIBMETALINK_LDFLAGS@ +LIBMETALINK_LIBS = @LIBMETALINK_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MANOPT = @MANOPT@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NROFF = @NROFF@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGADD_NAME = @PKGADD_NAME@ +PKGADD_PKG = @PKGADD_PKG@ +PKGADD_VENDOR = @PKGADD_VENDOR@ +PKGCONFIG = @PKGCONFIG@ +RANDOM_FILE = @RANDOM_FILE@ +RANLIB = @RANLIB@ +REQUIRE_LIB_DEPS = @REQUIRE_LIB_DEPS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_BACKENDS = @SSL_BACKENDS@ +SSL_ENABLED = @SSL_ENABLED@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +SUPPORT_FEATURES = @SUPPORT_FEATURES@ +SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@ +USE_ARES = @USE_ARES@ +USE_BEARSSL = @USE_BEARSSL@ +USE_GNUTLS = @USE_GNUTLS@ +USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@ +USE_LIBRTMP = @USE_LIBRTMP@ +USE_LIBSSH = @USE_LIBSSH@ +USE_LIBSSH2 = @USE_LIBSSH2@ +USE_MBEDTLS = @USE_MBEDTLS@ +USE_MESALINK = @USE_MESALINK@ +USE_NGHTTP2 = @USE_NGHTTP2@ +USE_NGHTTP3 = @USE_NGHTTP3@ +USE_NGTCP2 = @USE_NGTCP2@ +USE_NGTCP2_CRYPTO_OPENSSL = @USE_NGTCP2_CRYPTO_OPENSSL@ +USE_NSS = @USE_NSS@ +USE_OPENLDAP = @USE_OPENLDAP@ +USE_QUICHE = @USE_QUICHE@ +USE_SCHANNEL = @USE_SCHANNEL@ +USE_SECTRANSP = @USE_SECTRANSP@ +USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@ +USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@ +USE_WOLFSSH = @USE_WOLFSSH@ +USE_WOLFSSL = @USE_WOLFSSL@ +VERSION = @VERSION@ +VERSIONNUM = @VERSIONNUM@ +ZLIB_LIBS = @ZLIB_LIBS@ +ZSH_FUNCTIONS_DIR = @ZSH_FUNCTIONS_DIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libext = @libext@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = curl +EXTRA_DIST = README +AUTOMAKE_OPTIONS = foreign no-dependencies +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign include/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/README b/packages/php-wasm/compile/libcurl/dist/root/lib/include/README new file mode 100644 index 0000000000..091ef76d10 --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/README @@ -0,0 +1,18 @@ + _ _ ____ _ + ___| | | | _ \| | + / __| | | | |_) | | + | (__| |_| | _ <| |___ + \___|\___/|_| \_\_____| + +Include files for libcurl, external users. + +They're all placed in the curl subdirectory here for better fit in any kind +of environment. You must include files from here using... + + #include + +... style and point the compiler's include path to the directory holding the +curl subdirectory. It makes it more likely to survive future modifications. + +The public curl include files can be shared freely between different platforms +and different architectures. diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/Makefile b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/Makefile new file mode 100644 index 0000000000..43beba50e9 --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/Makefile @@ -0,0 +1,699 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# include/curl/Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + + +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/curl +pkglibdir = $(libdir)/curl +pkglibexecdir = $(libexecdir)/curl +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = i386-pc-linux-gnu +host_triplet = i386-pc-linux-gnu +subdir = include/curl +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compile_check_sizeof.m4 \ + $(top_srcdir)/m4/curl-compilers.m4 \ + $(top_srcdir)/m4/curl-confopts.m4 \ + $(top_srcdir)/m4/curl-functions.m4 \ + $(top_srcdir)/m4/curl-openssl.m4 \ + $(top_srcdir)/m4/curl-override.m4 \ + $(top_srcdir)/m4/curl-reentrant.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/xc-am-iface.m4 \ + $(top_srcdir)/m4/xc-cc-check.m4 \ + $(top_srcdir)/m4/xc-lt-iface.m4 \ + $(top_srcdir)/m4/xc-translit.m4 \ + $(top_srcdir)/m4/xc-val-flgs.m4 \ + $(top_srcdir)/m4/zz40-xc-ovr.m4 \ + $(top_srcdir)/m4/zz50-xc-ovr.m4 \ + $(top_srcdir)/m4/zz60-xc-ovr.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(pkginclude_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/lib/curl_config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_$(V)) +am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkgincludedir)" +HEADERS = $(pkginclude_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +pkgincludedir = $(includedir)/curl +ACLOCAL = ${SHELL} /root/curl-7.69.1/missing aclocal-1.16 +AMTAR = $${TAR-tar} +AM_DEFAULT_VERBOSITY = 0 +AR = /root/emsdk/upstream/emscripten/emar +AR_FLAGS = cr +AS = as +AUTOCONF = ${SHELL} /root/curl-7.69.1/missing autoconf +AUTOHEADER = ${SHELL} /root/curl-7.69.1/missing autoheader +AUTOMAKE = ${SHELL} /root/curl-7.69.1/missing automake-1.16 +AWK = mawk +BLANK_AT_MAKETIME = +CC = /root/emsdk/upstream/emscripten/emcc +CCDEPMODE = depmode=gcc3 +CFLAGS = -Qunused-arguments -Os +CFLAG_CURL_SYMBOL_HIDING = -fvisibility=hidden +CONFIGURE_OPTIONS = " '--build' 'i386-pc-linux-gnu' '--target' 'wasm32-unknown-emscripten' '--prefix=/root/install/' '--disable-shared' '--enable-static' '--with-openssl' '--enable-https' '--enable-http' '--disable-pthreads' '--disable-threaded-resolver' '--with-zlib=/root/lib' 'build_alias=i386-pc-linux-gnu' 'target_alias=wasm32-unknown-emscripten' 'CC=/root/emsdk/upstream/emscripten/emcc'" +CPP = /root/emsdk/upstream/emscripten/emcc -E +CPPFLAGS = -I/root/lib/include +CPPFLAG_CURL_STATICLIB = -DCURL_STATICLIB +CURLVERSION = 7.69.1 +CURL_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt" +CURL_CFLAG_EXTRAS = +CURL_DISABLE_DICT = +CURL_DISABLE_FILE = +CURL_DISABLE_FTP = +CURL_DISABLE_GOPHER = +CURL_DISABLE_HTTP = +CURL_DISABLE_IMAP = +CURL_DISABLE_LDAP = 1 +CURL_DISABLE_LDAPS = 1 +CURL_DISABLE_POP3 = +CURL_DISABLE_PROXY = +CURL_DISABLE_RTSP = +CURL_DISABLE_SMB = +CURL_DISABLE_SMTP = +CURL_DISABLE_TELNET = +CURL_DISABLE_TFTP = +CURL_LT_SHLIB_VERSIONED_FLAVOUR = +CURL_NETWORK_AND_TIME_LIBS = +CURL_NETWORK_LIBS = +CURL_WITH_MULTI_SSL = +CYGPATH_W = echo +DEFAULT_SSL_BACKEND = no +DEFS = -DHAVE_CONFIG_H +DEPDIR = .deps +DLLTOOL = false +DSYMUTIL = +DUMPBIN = +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = /usr/bin/grep -E +ENABLE_SHARED = no +ENABLE_STATIC = yes +EXEEXT = +FGREP = /usr/bin/grep -F +FISH_FUNCTIONS_DIR = ${prefix}/share/fish/vendor_completions.d +GCOV = +GREP = /usr/bin/grep +HAVE_BROTLI = +HAVE_GNUTLS_SRP = +HAVE_LDAP_SSL = 1 +HAVE_LIBZ = 1 +HAVE_OPENSSL_SRP = 1 +HAVE_PROTO_BSDSOCKET_H = +IDN_ENABLED = +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = $(install_sh) -c -s +IPV6_ENABLED = +LCOV = +LD = /root/emsdk/upstream/emscripten/emcc +LDFLAGS = -L/root/lib/lib +LIBCURL_LIBS = -lssl -lcrypto -lz +LIBMETALINK_CPPFLAGS = +LIBMETALINK_LDFLAGS = +LIBMETALINK_LIBS = +LIBOBJS = +LIBS = -lssl -lcrypto -lz +LIBTOOL = $(SHELL) $(top_builddir)/libtool +LIPO = +LN_S = ln -s +LTLIBOBJS = +LT_SYS_LIBRARY_PATH = +MAINT = # +MAKEINFO = ${SHELL} /root/curl-7.69.1/missing makeinfo +MANIFEST_TOOL = : +MANOPT = +MKDIR_P = /usr/bin/mkdir -p +NM = /root/emsdk/upstream/bin/llvm-nm +NMEDIT = +NROFF = +NSS_LIBS = +OBJDUMP = objdump +OBJEXT = o +OTOOL = +OTOOL64 = +PACKAGE = curl +PACKAGE_BUGREPORT = a suitable curl mailing list: https://curl.haxx.se/mail/ +PACKAGE_NAME = curl +PACKAGE_STRING = curl - +PACKAGE_TARNAME = curl +PACKAGE_URL = +PACKAGE_VERSION = - +PATH_SEPARATOR = : +PERL = /usr/bin/perl +PKGADD_NAME = curl - a client that groks URLs +PKGADD_PKG = HAXXcurl +PKGADD_VENDOR = curl.haxx.se +PKGCONFIG = no +RANDOM_FILE = /dev/urandom +RANLIB = /root/emsdk/upstream/emscripten/emranlib +REQUIRE_LIB_DEPS = yes +SED = /usr/bin/sed +SET_MAKE = +SHELL = /bin/bash +SSL_BACKENDS = OpenSSL +SSL_ENABLED = 1 +SSL_LIBS = +STRIP = strip +SUPPORT_FEATURES = SSL UnixSockets libz NTLM NTLM_WB TLS-SRP HTTPS-proxy +SUPPORT_PROTOCOLS = DICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS POP3 POP3S RTSP SMB SMBS SMTP SMTPS TELNET TFTP +USE_ARES = +USE_BEARSSL = +USE_GNUTLS = +USE_GNUTLS_NETTLE = +USE_LIBRTMP = +USE_LIBSSH = +USE_LIBSSH2 = +USE_MBEDTLS = +USE_MESALINK = +USE_NGHTTP2 = +USE_NGHTTP3 = +USE_NGTCP2 = +USE_NGTCP2_CRYPTO_OPENSSL = +USE_NSS = +USE_OPENLDAP = +USE_QUICHE = +USE_SCHANNEL = +USE_SECTRANSP = +USE_UNIX_SOCKETS = 1 +USE_WINDOWS_SSPI = +USE_WOLFSSH = +USE_WOLFSSL = +VERSION = - +VERSIONNUM = 074501 +ZLIB_LIBS = -lz +ZSH_FUNCTIONS_DIR = ${prefix}/share/zsh/site-functions +abs_builddir = /root/curl-7.69.1/include/curl +abs_srcdir = /root/curl-7.69.1/include/curl +abs_top_builddir = /root/curl-7.69.1 +abs_top_srcdir = /root/curl-7.69.1 +ac_ct_AR = +ac_ct_CC = /root/emsdk/upstream/emscripten/emcc +ac_ct_DUMPBIN = +am__include = include +am__leading_dot = . +am__quote = +am__tar = $${TAR-tar} chof - "$$tardir" +am__untar = $${TAR-tar} xf - +bindir = ${exec_prefix}/bin +build = i386-pc-linux-gnu +build_alias = i386-pc-linux-gnu +build_cpu = i386 +build_os = linux-gnu +build_vendor = pc +builddir = . +datadir = ${datarootdir} +datarootdir = ${prefix}/share +docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} +dvidir = ${docdir} +exec_prefix = ${prefix} +host = i386-pc-linux-gnu +host_alias = +host_cpu = i386 +host_os = linux-gnu +host_vendor = pc +htmldir = ${docdir} +includedir = ${prefix}/include +infodir = ${datarootdir}/info +install_sh = ${SHELL} /root/curl-7.69.1/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +libext = a +localedir = ${datarootdir}/locale +localstatedir = ${prefix}/var +mandir = ${datarootdir}/man +mkdir_p = $(MKDIR_P) +oldincludedir = /usr/include +pdfdir = ${docdir} +prefix = /root/install +program_transform_name = s,x,x, +psdir = ${docdir} +runstatedir = ${localstatedir}/run +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +srcdir = . +subdirs = +sysconfdir = ${prefix}/etc +target_alias = wasm32-unknown-emscripten +top_build_prefix = ../../ +top_builddir = ../.. +top_srcdir = ../.. + +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### +pkginclude_HEADERS = \ + curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \ + typecheck-gcc.h system.h urlapi.h + +CHECKSRC = $(CS_$(V)) +CS_0 = @echo " RUN " $@; +CS_1 = +CS_ = $(CS_0) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: # $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/curl/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign include/curl/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: # $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): # $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkgincludeHEADERS: $(pkginclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ + done + +uninstall-pkgincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-local: +all-am: Makefile $(HEADERS) all-local +installdirs: + for dir in "$(DESTDIR)$(pkgincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pkgincludeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkgincludeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-am clean \ + clean-generic clean-libtool cscopelist-am ctags ctags-am \ + distclean distclean-generic distclean-libtool distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkgincludeHEADERS \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pkgincludeHEADERS + +.PRECIOUS: Makefile + + +checksrc: + $(CHECKSRC)/usr/bin/perl $(top_srcdir)/lib/checksrc.pl -D$(top_srcdir)/include/curl $(pkginclude_HEADERS) + +# for debug builds, we scan the sources on all regular make invokes +#all-local: checksrc + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/Makefile.am b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/Makefile.am new file mode 100644 index 0000000000..a31f61b101 --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/Makefile.am @@ -0,0 +1,39 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### +pkginclude_HEADERS = \ + curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \ + typecheck-gcc.h system.h urlapi.h + +pkgincludedir= $(includedir)/curl + +CHECKSRC = $(CS_$(V)) +CS_0 = @echo " RUN " $@; +CS_1 = +CS_ = $(CS_0) + +checksrc: + $(CHECKSRC)@PERL@ $(top_srcdir)/lib/checksrc.pl -D$(top_srcdir)/include/curl $(pkginclude_HEADERS) + +if CURLDEBUG +# for debug builds, we scan the sources on all regular make invokes +all-local: checksrc +endif diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/Makefile.in b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/Makefile.in new file mode 100644 index 0000000000..1fef5c5a9f --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/Makefile.in @@ -0,0 +1,699 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = include/curl +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_compile_check_sizeof.m4 \ + $(top_srcdir)/m4/curl-compilers.m4 \ + $(top_srcdir)/m4/curl-confopts.m4 \ + $(top_srcdir)/m4/curl-functions.m4 \ + $(top_srcdir)/m4/curl-openssl.m4 \ + $(top_srcdir)/m4/curl-override.m4 \ + $(top_srcdir)/m4/curl-reentrant.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/xc-am-iface.m4 \ + $(top_srcdir)/m4/xc-cc-check.m4 \ + $(top_srcdir)/m4/xc-lt-iface.m4 \ + $(top_srcdir)/m4/xc-translit.m4 \ + $(top_srcdir)/m4/xc-val-flgs.m4 \ + $(top_srcdir)/m4/zz40-xc-ovr.m4 \ + $(top_srcdir)/m4/zz50-xc-ovr.m4 \ + $(top_srcdir)/m4/zz60-xc-ovr.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(pkginclude_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/lib/curl_config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkgincludedir)" +HEADERS = $(pkginclude_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +pkgincludedir = $(includedir)/curl +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AR_FLAGS = @AR_FLAGS@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BLANK_AT_MAKETIME = @BLANK_AT_MAKETIME@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_CURL_SYMBOL_HIDING = @CFLAG_CURL_SYMBOL_HIDING@ +CONFIGURE_OPTIONS = @CONFIGURE_OPTIONS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAG_CURL_STATICLIB = @CPPFLAG_CURL_STATICLIB@ +CURLVERSION = @CURLVERSION@ +CURL_CA_BUNDLE = @CURL_CA_BUNDLE@ +CURL_CFLAG_EXTRAS = @CURL_CFLAG_EXTRAS@ +CURL_DISABLE_DICT = @CURL_DISABLE_DICT@ +CURL_DISABLE_FILE = @CURL_DISABLE_FILE@ +CURL_DISABLE_FTP = @CURL_DISABLE_FTP@ +CURL_DISABLE_GOPHER = @CURL_DISABLE_GOPHER@ +CURL_DISABLE_HTTP = @CURL_DISABLE_HTTP@ +CURL_DISABLE_IMAP = @CURL_DISABLE_IMAP@ +CURL_DISABLE_LDAP = @CURL_DISABLE_LDAP@ +CURL_DISABLE_LDAPS = @CURL_DISABLE_LDAPS@ +CURL_DISABLE_POP3 = @CURL_DISABLE_POP3@ +CURL_DISABLE_PROXY = @CURL_DISABLE_PROXY@ +CURL_DISABLE_RTSP = @CURL_DISABLE_RTSP@ +CURL_DISABLE_SMB = @CURL_DISABLE_SMB@ +CURL_DISABLE_SMTP = @CURL_DISABLE_SMTP@ +CURL_DISABLE_TELNET = @CURL_DISABLE_TELNET@ +CURL_DISABLE_TFTP = @CURL_DISABLE_TFTP@ +CURL_LT_SHLIB_VERSIONED_FLAVOUR = @CURL_LT_SHLIB_VERSIONED_FLAVOUR@ +CURL_NETWORK_AND_TIME_LIBS = @CURL_NETWORK_AND_TIME_LIBS@ +CURL_NETWORK_LIBS = @CURL_NETWORK_LIBS@ +CURL_WITH_MULTI_SSL = @CURL_WITH_MULTI_SSL@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_SSL_BACKEND = @DEFAULT_SSL_BACKEND@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_SHARED = @ENABLE_SHARED@ +ENABLE_STATIC = @ENABLE_STATIC@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@ +GCOV = @GCOV@ +GREP = @GREP@ +HAVE_BROTLI = @HAVE_BROTLI@ +HAVE_GNUTLS_SRP = @HAVE_GNUTLS_SRP@ +HAVE_LDAP_SSL = @HAVE_LDAP_SSL@ +HAVE_LIBZ = @HAVE_LIBZ@ +HAVE_OPENSSL_SRP = @HAVE_OPENSSL_SRP@ +HAVE_PROTO_BSDSOCKET_H = @HAVE_PROTO_BSDSOCKET_H@ +IDN_ENABLED = @IDN_ENABLED@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IPV6_ENABLED = @IPV6_ENABLED@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCURL_LIBS = @LIBCURL_LIBS@ +LIBMETALINK_CPPFLAGS = @LIBMETALINK_CPPFLAGS@ +LIBMETALINK_LDFLAGS = @LIBMETALINK_LDFLAGS@ +LIBMETALINK_LIBS = @LIBMETALINK_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MANOPT = @MANOPT@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NROFF = @NROFF@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKGADD_NAME = @PKGADD_NAME@ +PKGADD_PKG = @PKGADD_PKG@ +PKGADD_VENDOR = @PKGADD_VENDOR@ +PKGCONFIG = @PKGCONFIG@ +RANDOM_FILE = @RANDOM_FILE@ +RANLIB = @RANLIB@ +REQUIRE_LIB_DEPS = @REQUIRE_LIB_DEPS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SSL_BACKENDS = @SSL_BACKENDS@ +SSL_ENABLED = @SSL_ENABLED@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +SUPPORT_FEATURES = @SUPPORT_FEATURES@ +SUPPORT_PROTOCOLS = @SUPPORT_PROTOCOLS@ +USE_ARES = @USE_ARES@ +USE_BEARSSL = @USE_BEARSSL@ +USE_GNUTLS = @USE_GNUTLS@ +USE_GNUTLS_NETTLE = @USE_GNUTLS_NETTLE@ +USE_LIBRTMP = @USE_LIBRTMP@ +USE_LIBSSH = @USE_LIBSSH@ +USE_LIBSSH2 = @USE_LIBSSH2@ +USE_MBEDTLS = @USE_MBEDTLS@ +USE_MESALINK = @USE_MESALINK@ +USE_NGHTTP2 = @USE_NGHTTP2@ +USE_NGHTTP3 = @USE_NGHTTP3@ +USE_NGTCP2 = @USE_NGTCP2@ +USE_NGTCP2_CRYPTO_OPENSSL = @USE_NGTCP2_CRYPTO_OPENSSL@ +USE_NSS = @USE_NSS@ +USE_OPENLDAP = @USE_OPENLDAP@ +USE_QUICHE = @USE_QUICHE@ +USE_SCHANNEL = @USE_SCHANNEL@ +USE_SECTRANSP = @USE_SECTRANSP@ +USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@ +USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@ +USE_WOLFSSH = @USE_WOLFSSH@ +USE_WOLFSSL = @USE_WOLFSSL@ +VERSION = @VERSION@ +VERSIONNUM = @VERSIONNUM@ +ZLIB_LIBS = @ZLIB_LIBS@ +ZSH_FUNCTIONS_DIR = @ZSH_FUNCTIONS_DIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libext = @libext@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### +pkginclude_HEADERS = \ + curl.h curlver.h easy.h mprintf.h stdcheaders.h multi.h \ + typecheck-gcc.h system.h urlapi.h + +CHECKSRC = $(CS_$(V)) +CS_0 = @echo " RUN " $@; +CS_1 = +CS_ = $(CS_0) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/curl/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign include/curl/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-pkgincludeHEADERS: $(pkginclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ + done + +uninstall-pkgincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +@CURLDEBUG_FALSE@all-local: +all-am: Makefile $(HEADERS) all-local +installdirs: + for dir in "$(DESTDIR)$(pkgincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-pkgincludeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkgincludeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-am clean \ + clean-generic clean-libtool cscopelist-am ctags ctags-am \ + distclean distclean-generic distclean-libtool distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkgincludeHEADERS \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pkgincludeHEADERS + +.PRECIOUS: Makefile + + +checksrc: + $(CHECKSRC)@PERL@ $(top_srcdir)/lib/checksrc.pl -D$(top_srcdir)/include/curl $(pkginclude_HEADERS) + +# for debug builds, we scan the sources on all regular make invokes +@CURLDEBUG_TRUE@all-local: checksrc + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/curl.h b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/curl.h new file mode 100644 index 0000000000..b7cb30a581 --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/curl.h @@ -0,0 +1,2889 @@ +#ifndef CURLINC_CURL_H +#define CURLINC_CURL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * If you have libcurl problems, all docs and details are found here: + * https://curl.haxx.se/libcurl/ + * + * curl-library mailing list subscription and unsubscription web interface: + * https://cool.haxx.se/mailman/listinfo/curl-library/ + */ + +#ifdef CURL_NO_OLDIES +#define CURL_STRICTER +#endif + +#include "curlver.h" /* libcurl version defines */ +#include "system.h" /* determine things run-time */ + +/* + * Define CURL_WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && \ + !defined(__SYMBIAN32__) +#define CURL_WIN32 +#endif + +#include +#include + +#if defined(__FreeBSD__) && (__FreeBSD__ >= 2) +/* Needed for __FreeBSD_version symbol definition */ +#include +#endif + +/* The include stuff here below is mainly for time_t! */ +#include +#include + +#if defined(CURL_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) +#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \ + defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)) +/* The check above prevents the winsock2 inclusion if winsock.h already was + included, since they can't co-exist without problems */ +#include +#include +#endif +#endif + +/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish + libc5-based Linux systems. Only include it on systems that are known to + require it! */ +#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ + defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ + defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ + defined(__CYGWIN__) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) +#include +#endif + +#if !defined(CURL_WIN32) && !defined(_WIN32_WCE) +#include +#endif + +#if !defined(CURL_WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__) +#include +#endif + +#ifdef __BEOS__ +#include +#endif + +/* Compatibility for non-Clang compilers */ +#ifndef __has_declspec_attribute +# define __has_declspec_attribute(x) 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) +typedef struct Curl_easy CURL; +typedef struct Curl_share CURLSH; +#else +typedef void CURL; +typedef void CURLSH; +#endif + +/* + * libcurl external API function linkage decorations. + */ + +#ifdef CURL_STATICLIB +# define CURL_EXTERN +#elif defined(CURL_WIN32) || defined(__SYMBIAN32__) || \ + (__has_declspec_attribute(dllexport) && \ + __has_declspec_attribute(dllimport)) +# if defined(BUILDING_LIBCURL) +# define CURL_EXTERN __declspec(dllexport) +# else +# define CURL_EXTERN __declspec(dllimport) +# endif +#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS) +# define CURL_EXTERN CURL_EXTERN_SYMBOL +#else +# define CURL_EXTERN +#endif + +#ifndef curl_socket_typedef +/* socket typedef */ +#if defined(CURL_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H) +typedef SOCKET curl_socket_t; +#define CURL_SOCKET_BAD INVALID_SOCKET +#else +typedef int curl_socket_t; +#define CURL_SOCKET_BAD -1 +#endif +#define curl_socket_typedef +#endif /* curl_socket_typedef */ + +/* enum for the different supported SSL backends */ +typedef enum { + CURLSSLBACKEND_NONE = 0, + CURLSSLBACKEND_OPENSSL = 1, + CURLSSLBACKEND_GNUTLS = 2, + CURLSSLBACKEND_NSS = 3, + CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */ + CURLSSLBACKEND_GSKIT = 5, + CURLSSLBACKEND_POLARSSL = 6, + CURLSSLBACKEND_WOLFSSL = 7, + CURLSSLBACKEND_SCHANNEL = 8, + CURLSSLBACKEND_SECURETRANSPORT = 9, + CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */ + CURLSSLBACKEND_MBEDTLS = 11, + CURLSSLBACKEND_MESALINK = 12, + CURLSSLBACKEND_BEARSSL = 13 +} curl_sslbackend; + +/* aliases for library clones and renames */ +#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL +#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL + +/* deprecated names: */ +#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL +#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT + +struct curl_httppost { + struct curl_httppost *next; /* next entry in the list */ + char *name; /* pointer to allocated name */ + long namelength; /* length of name length */ + char *contents; /* pointer to allocated data contents */ + long contentslength; /* length of contents field, see also + CURL_HTTPPOST_LARGE */ + char *buffer; /* pointer to allocated buffer contents */ + long bufferlength; /* length of buffer field */ + char *contenttype; /* Content-Type */ + struct curl_slist *contentheader; /* list of extra headers for this form */ + struct curl_httppost *more; /* if one field name has more than one + file, this link should link to following + files */ + long flags; /* as defined below */ + +/* specified content is a file name */ +#define CURL_HTTPPOST_FILENAME (1<<0) +/* specified content is a file name */ +#define CURL_HTTPPOST_READFILE (1<<1) +/* name is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRNAME (1<<2) +/* contents is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRCONTENTS (1<<3) +/* upload file from buffer */ +#define CURL_HTTPPOST_BUFFER (1<<4) +/* upload file from pointer contents */ +#define CURL_HTTPPOST_PTRBUFFER (1<<5) +/* upload file contents by using the regular read callback to get the data and + pass the given pointer as custom pointer */ +#define CURL_HTTPPOST_CALLBACK (1<<6) +/* use size in 'contentlen', added in 7.46.0 */ +#define CURL_HTTPPOST_LARGE (1<<7) + + char *showfilename; /* The file name to show. If not set, the + actual file name will be used (if this + is a file part) */ + void *userp; /* custom pointer used for + HTTPPOST_CALLBACK posts */ + curl_off_t contentlen; /* alternative length of contents + field. Used if CURL_HTTPPOST_LARGE is + set. Added in 7.46.0 */ +}; + + +/* This is a return code for the progress callback that, when returned, will + signal libcurl to continue executing the default progress function */ +#define CURL_PROGRESSFUNC_CONTINUE 0x10000001 + +/* This is the CURLOPT_PROGRESSFUNCTION callback prototype. It is now + considered deprecated but was the only choice up until 7.31.0 */ +typedef int (*curl_progress_callback)(void *clientp, + double dltotal, + double dlnow, + double ultotal, + double ulnow); + +/* This is the CURLOPT_XFERINFOFUNCTION callback prototype. It was introduced + in 7.32.0, avoids the use of floating point numbers and provides more + detailed information. */ +typedef int (*curl_xferinfo_callback)(void *clientp, + curl_off_t dltotal, + curl_off_t dlnow, + curl_off_t ultotal, + curl_off_t ulnow); + +#ifndef CURL_MAX_READ_SIZE + /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */ +#define CURL_MAX_READ_SIZE 524288 +#endif + +#ifndef CURL_MAX_WRITE_SIZE + /* Tests have proven that 20K is a very bad buffer size for uploads on + Windows, while 16K for some odd reason performed a lot better. + We do the ifndef check to allow this value to easier be changed at build + time for those who feel adventurous. The practical minimum is about + 400 bytes since libcurl uses a buffer of this size as a scratch area + (unrelated to network send operations). */ +#define CURL_MAX_WRITE_SIZE 16384 +#endif + +#ifndef CURL_MAX_HTTP_HEADER +/* The only reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause reallocs + infinitely */ +#define CURL_MAX_HTTP_HEADER (100*1024) +#endif + +/* This is a magic return code for the write callback that, when returned, + will signal libcurl to pause receiving on the current transfer. */ +#define CURL_WRITEFUNC_PAUSE 0x10000001 + +typedef size_t (*curl_write_callback)(char *buffer, + size_t size, + size_t nitems, + void *outstream); + +/* This callback will be called when a new resolver request is made */ +typedef int (*curl_resolver_start_callback)(void *resolver_state, + void *reserved, void *userdata); + +/* enumeration of file types */ +typedef enum { + CURLFILETYPE_FILE = 0, + CURLFILETYPE_DIRECTORY, + CURLFILETYPE_SYMLINK, + CURLFILETYPE_DEVICE_BLOCK, + CURLFILETYPE_DEVICE_CHAR, + CURLFILETYPE_NAMEDPIPE, + CURLFILETYPE_SOCKET, + CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */ + + CURLFILETYPE_UNKNOWN /* should never occur */ +} curlfiletype; + +#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0) +#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1) +#define CURLFINFOFLAG_KNOWN_TIME (1<<2) +#define CURLFINFOFLAG_KNOWN_PERM (1<<3) +#define CURLFINFOFLAG_KNOWN_UID (1<<4) +#define CURLFINFOFLAG_KNOWN_GID (1<<5) +#define CURLFINFOFLAG_KNOWN_SIZE (1<<6) +#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7) + +/* Information about a single file, used when doing FTP wildcard matching */ +struct curl_fileinfo { + char *filename; + curlfiletype filetype; + time_t time; /* always zero! */ + unsigned int perm; + int uid; + int gid; + curl_off_t size; + long int hardlinks; + + struct { + /* If some of these fields is not NULL, it is a pointer to b_data. */ + char *time; + char *perm; + char *user; + char *group; + char *target; /* pointer to the target filename of a symlink */ + } strings; + + unsigned int flags; + + /* used internally */ + char *b_data; + size_t b_size; + size_t b_used; +}; + +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */ +#define CURL_CHUNK_BGN_FUNC_OK 0 +#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */ +#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */ + +/* if splitting of data transfer is enabled, this callback is called before + download of an individual chunk started. Note that parameter "remains" works + only for FTP wildcard downloading (for now), otherwise is not used */ +typedef long (*curl_chunk_bgn_callback)(const void *transfer_info, + void *ptr, + int remains); + +/* return codes for CURLOPT_CHUNK_END_FUNCTION */ +#define CURL_CHUNK_END_FUNC_OK 0 +#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */ + +/* If splitting of data transfer is enabled this callback is called after + download of an individual chunk finished. + Note! After this callback was set then it have to be called FOR ALL chunks. + Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC. + This is the reason why we don't need "transfer_info" parameter in this + callback and we are not interested in "remains" parameter too. */ +typedef long (*curl_chunk_end_callback)(void *ptr); + +/* return codes for FNMATCHFUNCTION */ +#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */ +#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */ +#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */ + +/* callback type for wildcard downloading pattern matching. If the + string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */ +typedef int (*curl_fnmatch_callback)(void *ptr, + const char *pattern, + const char *string); + +/* These are the return codes for the seek callbacks */ +#define CURL_SEEKFUNC_OK 0 +#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */ +#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so + libcurl might try other means instead */ +typedef int (*curl_seek_callback)(void *instream, + curl_off_t offset, + int origin); /* 'whence' */ + +/* This is a return code for the read callback that, when returned, will + signal libcurl to immediately abort the current transfer. */ +#define CURL_READFUNC_ABORT 0x10000000 +/* This is a return code for the read callback that, when returned, will + signal libcurl to pause sending data on the current transfer. */ +#define CURL_READFUNC_PAUSE 0x10000001 + +/* Return code for when the trailing headers' callback has terminated + without any errors*/ +#define CURL_TRAILERFUNC_OK 0 +/* Return code for when was an error in the trailing header's list and we + want to abort the request */ +#define CURL_TRAILERFUNC_ABORT 1 + +typedef size_t (*curl_read_callback)(char *buffer, + size_t size, + size_t nitems, + void *instream); + +typedef int (*curl_trailer_callback)(struct curl_slist **list, + void *userdata); + +typedef enum { + CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ + CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */ + CURLSOCKTYPE_LAST /* never use */ +} curlsocktype; + +/* The return code from the sockopt_callback can signal information back + to libcurl: */ +#define CURL_SOCKOPT_OK 0 +#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return + CURLE_ABORTED_BY_CALLBACK */ +#define CURL_SOCKOPT_ALREADY_CONNECTED 2 + +typedef int (*curl_sockopt_callback)(void *clientp, + curl_socket_t curlfd, + curlsocktype purpose); + +struct curl_sockaddr { + int family; + int socktype; + int protocol; + unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it + turned really ugly and painful on the systems that + lack this type */ + struct sockaddr addr; +}; + +typedef curl_socket_t +(*curl_opensocket_callback)(void *clientp, + curlsocktype purpose, + struct curl_sockaddr *address); + +typedef int +(*curl_closesocket_callback)(void *clientp, curl_socket_t item); + +typedef enum { + CURLIOE_OK, /* I/O operation successful */ + CURLIOE_UNKNOWNCMD, /* command was unknown to callback */ + CURLIOE_FAILRESTART, /* failed to restart the read */ + CURLIOE_LAST /* never use */ +} curlioerr; + +typedef enum { + CURLIOCMD_NOP, /* no operation */ + CURLIOCMD_RESTARTREAD, /* restart the read stream from start */ + CURLIOCMD_LAST /* never use */ +} curliocmd; + +typedef curlioerr (*curl_ioctl_callback)(CURL *handle, + int cmd, + void *clientp); + +#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS +/* + * The following typedef's are signatures of malloc, free, realloc, strdup and + * calloc respectively. Function pointers of these types can be passed to the + * curl_global_init_mem() function to set user defined memory management + * callback routines. + */ +typedef void *(*curl_malloc_callback)(size_t size); +typedef void (*curl_free_callback)(void *ptr); +typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +typedef char *(*curl_strdup_callback)(const char *str); +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); + +#define CURL_DID_MEMORY_FUNC_TYPEDEFS +#endif + +/* the kind of data that is passed to information_callback*/ +typedef enum { + CURLINFO_TEXT = 0, + CURLINFO_HEADER_IN, /* 1 */ + CURLINFO_HEADER_OUT, /* 2 */ + CURLINFO_DATA_IN, /* 3 */ + CURLINFO_DATA_OUT, /* 4 */ + CURLINFO_SSL_DATA_IN, /* 5 */ + CURLINFO_SSL_DATA_OUT, /* 6 */ + CURLINFO_END +} curl_infotype; + +typedef int (*curl_debug_callback) + (CURL *handle, /* the handle/transfer this concerns */ + curl_infotype type, /* what kind of data */ + char *data, /* points to the data */ + size_t size, /* size of the data pointed to */ + void *userptr); /* whatever the user please */ + +/* All possible error codes from all sorts of curl functions. Future versions + may return other values, stay prepared. + + Always add new return codes last. Never *EVER* remove any. The return + codes must remain the same! + */ + +typedef enum { + CURLE_OK = 0, + CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ + CURLE_FAILED_INIT, /* 2 */ + CURLE_URL_MALFORMAT, /* 3 */ + CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for + 7.17.0, reused in April 2011 for 7.21.5] */ + CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ + CURLE_COULDNT_RESOLVE_HOST, /* 6 */ + CURLE_COULDNT_CONNECT, /* 7 */ + CURLE_WEIRD_SERVER_REPLY, /* 8 */ + CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server + due to lack of access - when login fails + this is not returned. */ + CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for + 7.15.4, reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ + CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server + [was obsoleted in August 2007 for 7.17.0, + reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ + CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ + CURLE_FTP_CANT_GET_HOST, /* 15 */ + CURLE_HTTP2, /* 16 - A problem in the http2 framing layer. + [was obsoleted in August 2007 for 7.17.0, + reused in July 2014 for 7.38.0] */ + CURLE_FTP_COULDNT_SET_TYPE, /* 17 */ + CURLE_PARTIAL_FILE, /* 18 */ + CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ + CURLE_OBSOLETE20, /* 20 - NOT USED */ + CURLE_QUOTE_ERROR, /* 21 - quote command failure */ + CURLE_HTTP_RETURNED_ERROR, /* 22 */ + CURLE_WRITE_ERROR, /* 23 */ + CURLE_OBSOLETE24, /* 24 - NOT USED */ + CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */ + CURLE_READ_ERROR, /* 26 - couldn't open/read from file */ + CURLE_OUT_OF_MEMORY, /* 27 */ + /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error + instead of a memory allocation error if CURL_DOES_CONVERSIONS + is defined + */ + CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ + CURLE_OBSOLETE29, /* 29 - NOT USED */ + CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ + CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ + CURLE_OBSOLETE32, /* 32 - NOT USED */ + CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */ + CURLE_HTTP_POST_ERROR, /* 34 */ + CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ + CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ + CURLE_FILE_COULDNT_READ_FILE, /* 37 */ + CURLE_LDAP_CANNOT_BIND, /* 38 */ + CURLE_LDAP_SEARCH_FAILED, /* 39 */ + CURLE_OBSOLETE40, /* 40 - NOT USED */ + CURLE_FUNCTION_NOT_FOUND, /* 41 - NOT USED starting with 7.53.0 */ + CURLE_ABORTED_BY_CALLBACK, /* 42 */ + CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ + CURLE_OBSOLETE44, /* 44 - NOT USED */ + CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ + CURLE_OBSOLETE46, /* 46 - NOT USED */ + CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */ + CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ + CURLE_TELNET_OPTION_SYNTAX, /* 49 - Malformed telnet option */ + CURLE_OBSOLETE50, /* 50 - NOT USED */ + CURLE_OBSOLETE51, /* 51 - NOT USED */ + CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ + CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ + CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + CURLE_SEND_ERROR, /* 55 - failed sending network data */ + CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ + CURLE_OBSOLETE57, /* 57 - NOT IN USE */ + CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */ + CURLE_PEER_FAILED_VERIFICATION, /* 60 - peer's certificate or fingerprint + wasn't verified fine */ + CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */ + CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */ + CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ + CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ + CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind + that failed */ + CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ + CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not + accepted and we failed to login */ + CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */ + CURLE_TFTP_PERM, /* 69 - permission problem on server */ + CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ + CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ + CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ + CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */ + CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */ + CURLE_CONV_FAILED, /* 75 - conversion failed */ + CURLE_CONV_REQD, /* 76 - caller must register conversion + callbacks using curl_easy_setopt options + CURLOPT_CONV_FROM_NETWORK_FUNCTION, + CURLOPT_CONV_TO_NETWORK_FUNCTION, and + CURLOPT_CONV_FROM_UTF8_FUNCTION */ + CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing + or wrong format */ + CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ + CURLE_SSH, /* 79 - error from the SSH layer, somewhat + generic so the error message will be of + interest when this has happened */ + + CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL + connection */ + CURLE_AGAIN, /* 81 - socket is not ready for send/recv, + wait till it's ready and try again (Added + in 7.18.2) */ + CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or + wrong format (Added in 7.19.0) */ + CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in + 7.19.0) */ + CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */ + CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */ + CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */ + CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */ + CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */ + CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the + session will be queued */ + CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not + match */ + CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */ + CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer + */ + CURLE_RECURSIVE_API_CALL, /* 93 - an api function was called from + inside a callback */ + CURLE_AUTH_ERROR, /* 94 - an authentication function returned an + error */ + CURLE_HTTP3, /* 95 - An HTTP/3 layer problem */ + CURLE_QUIC_CONNECT_ERROR, /* 96 - QUIC connection error */ + CURL_LAST /* never use! */ +} CURLcode; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Previously obsolete error code re-used in 7.38.0 */ +#define CURLE_OBSOLETE16 CURLE_HTTP2 + +/* Previously obsolete error codes re-used in 7.24.0 */ +#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED +#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT + +/* compatibility with older names */ +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING +#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY + +/* The following were added in 7.62.0 */ +#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.21.5, April 2011 */ +#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION + +/* The following were added in 7.17.1 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.17.0 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */ +#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46 +#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44 +#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10 +#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16 +#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32 +#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29 +#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12 +#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20 +#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40 +#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24 +#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57 +#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN + +#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED +#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE +#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR +#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL +#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS +#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR +#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED + +/* The following were added earlier */ + +#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT + +#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR +#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED +#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED + +#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME + +/* This was the error code 50 in 7.7.3 and a few earlier versions, this + is no longer used by libcurl but is instead #defined here only to not + make programs break */ +#define CURLE_ALREADY_COMPLETE 99999 + +/* Provide defines for really old option names */ +#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */ +#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */ +#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA + +/* Since long deprecated options with no code in the lib that does anything + with them. */ +#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40 +#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72 + +#endif /*!CURL_NO_OLDIES*/ + +/* This prototype applies to all conversion callbacks */ +typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length); + +typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */ + void *ssl_ctx, /* actually an OpenSSL + or WolfSSL SSL_CTX, + or an mbedTLS + mbedtls_ssl_config */ + void *userptr); + +typedef enum { + CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use + CONNECT HTTP/1.1 */ + CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT + HTTP/1.0 */ + CURLPROXY_HTTPS = 2, /* added in 7.52.0 */ + CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already + in 7.10 */ + CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ + CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */ + CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the + host name rather than the IP address. added + in 7.18.0 */ +} curl_proxytype; /* this enum was added in 7.10 */ + +/* + * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options: + * + * CURLAUTH_NONE - No HTTP authentication + * CURLAUTH_BASIC - HTTP Basic authentication (default) + * CURLAUTH_DIGEST - HTTP Digest authentication + * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication + * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated) + * CURLAUTH_NTLM - HTTP NTLM authentication + * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour + * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper + * CURLAUTH_BEARER - HTTP Bearer token authentication + * CURLAUTH_ONLY - Use together with a single other type to force no + * authentication or just that single type + * CURLAUTH_ANY - All fine types set + * CURLAUTH_ANYSAFE - All fine types except Basic + */ + +#define CURLAUTH_NONE ((unsigned long)0) +#define CURLAUTH_BASIC (((unsigned long)1)<<0) +#define CURLAUTH_DIGEST (((unsigned long)1)<<1) +#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2) +/* Deprecated since the advent of CURLAUTH_NEGOTIATE */ +#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE +/* Used for CURLOPT_SOCKS5_AUTH to stay terminologically correct */ +#define CURLAUTH_GSSAPI CURLAUTH_NEGOTIATE +#define CURLAUTH_NTLM (((unsigned long)1)<<3) +#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4) +#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5) +#define CURLAUTH_BEARER (((unsigned long)1)<<6) +#define CURLAUTH_ONLY (((unsigned long)1)<<31) +#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) +#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) + +#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */ +#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */ +#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */ +#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */ +#define CURLSSH_AUTH_HOST (1<<2) /* host key files */ +#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */ +#define CURLSSH_AUTH_AGENT (1<<4) /* agent (ssh-agent, pageant...) */ +#define CURLSSH_AUTH_GSSAPI (1<<5) /* gssapi (kerberos, ...) */ +#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY + +#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */ +#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */ +#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */ + +#define CURL_ERROR_SIZE 256 + +enum curl_khtype { + CURLKHTYPE_UNKNOWN, + CURLKHTYPE_RSA1, + CURLKHTYPE_RSA, + CURLKHTYPE_DSS, + CURLKHTYPE_ECDSA, + CURLKHTYPE_ED25519 +}; + +struct curl_khkey { + const char *key; /* points to a zero-terminated string encoded with base64 + if len is zero, otherwise to the "raw" data */ + size_t len; + enum curl_khtype keytype; +}; + +/* this is the set of return values expected from the curl_sshkeycallback + callback */ +enum curl_khstat { + CURLKHSTAT_FINE_ADD_TO_FILE, + CURLKHSTAT_FINE, + CURLKHSTAT_REJECT, /* reject the connection, return an error */ + CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so + this causes a CURLE_DEFER error but otherwise the + connection will be left intact etc */ + CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ +}; + +/* this is the set of status codes pass in to the callback */ +enum curl_khmatch { + CURLKHMATCH_OK, /* match */ + CURLKHMATCH_MISMATCH, /* host found, key mismatch! */ + CURLKHMATCH_MISSING, /* no matching host/key found */ + CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */ +}; + +typedef int + (*curl_sshkeycallback) (CURL *easy, /* easy handle */ + const struct curl_khkey *knownkey, /* known */ + const struct curl_khkey *foundkey, /* found */ + enum curl_khmatch, /* libcurl's view on the keys */ + void *clientp); /* custom pointer passed from app */ + +/* parameter for the CURLOPT_USE_SSL option */ +typedef enum { + CURLUSESSL_NONE, /* do not attempt to use SSL */ + CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */ + CURLUSESSL_CONTROL, /* SSL for the control connection or fail */ + CURLUSESSL_ALL, /* SSL for all communication or fail */ + CURLUSESSL_LAST /* not an option, never use */ +} curl_usessl; + +/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */ + +/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the + name of improving interoperability with older servers. Some SSL libraries + have introduced work-arounds for this flaw but those work-arounds sometimes + make the SSL communication fail. To regain functionality with those broken + servers, a user can this way allow the vulnerability back. */ +#define CURLSSLOPT_ALLOW_BEAST (1<<0) + +/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those + SSL backends where such behavior is present. */ +#define CURLSSLOPT_NO_REVOKE (1<<1) + +/* - NO_PARTIALCHAIN tells libcurl to *NOT* accept a partial certificate chain + if possible. The OpenSSL backend has this ability. */ +#define CURLSSLOPT_NO_PARTIALCHAIN (1<<2) + +/* The default connection attempt delay in milliseconds for happy eyeballs. + CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document + this value, keep them in sync. */ +#define CURL_HET_DEFAULT 200L + +/* The default connection upkeep interval in milliseconds. */ +#define CURL_UPKEEP_INTERVAL_DEFAULT 60000L + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2009 */ + +#define CURLFTPSSL_NONE CURLUSESSL_NONE +#define CURLFTPSSL_TRY CURLUSESSL_TRY +#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL +#define CURLFTPSSL_ALL CURLUSESSL_ALL +#define CURLFTPSSL_LAST CURLUSESSL_LAST +#define curl_ftpssl curl_usessl +#endif /*!CURL_NO_OLDIES*/ + +/* parameter for the CURLOPT_FTP_SSL_CCC option */ +typedef enum { + CURLFTPSSL_CCC_NONE, /* do not send CCC */ + CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */ + CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */ + CURLFTPSSL_CCC_LAST /* not an option, never use */ +} curl_ftpccc; + +/* parameter for the CURLOPT_FTPSSLAUTH option */ +typedef enum { + CURLFTPAUTH_DEFAULT, /* let libcurl decide */ + CURLFTPAUTH_SSL, /* use "AUTH SSL" */ + CURLFTPAUTH_TLS, /* use "AUTH TLS" */ + CURLFTPAUTH_LAST /* not an option, never use */ +} curl_ftpauth; + +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */ +typedef enum { + CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */ + CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD + again if MKD succeeded, for SFTP this does + similar magic */ + CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD + again even if MKD failed! */ + CURLFTP_CREATE_DIR_LAST /* not an option, never use */ +} curl_ftpcreatedir; + +/* parameter for the CURLOPT_FTP_FILEMETHOD option */ +typedef enum { + CURLFTPMETHOD_DEFAULT, /* let libcurl pick */ + CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */ + CURLFTPMETHOD_NOCWD, /* no CWD at all */ + CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */ + CURLFTPMETHOD_LAST /* not an option, never use */ +} curl_ftpmethod; + +/* bitmask defines for CURLOPT_HEADEROPT */ +#define CURLHEADER_UNIFIED 0 +#define CURLHEADER_SEPARATE (1<<0) + +/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */ +#define CURLALTSVC_IMMEDIATELY (1<<0) + +#define CURLALTSVC_READONLYFILE (1<<2) +#define CURLALTSVC_H1 (1<<3) +#define CURLALTSVC_H2 (1<<4) +#define CURLALTSVC_H3 (1<<5) + +/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */ +#define CURLPROTO_HTTP (1<<0) +#define CURLPROTO_HTTPS (1<<1) +#define CURLPROTO_FTP (1<<2) +#define CURLPROTO_FTPS (1<<3) +#define CURLPROTO_SCP (1<<4) +#define CURLPROTO_SFTP (1<<5) +#define CURLPROTO_TELNET (1<<6) +#define CURLPROTO_LDAP (1<<7) +#define CURLPROTO_LDAPS (1<<8) +#define CURLPROTO_DICT (1<<9) +#define CURLPROTO_FILE (1<<10) +#define CURLPROTO_TFTP (1<<11) +#define CURLPROTO_IMAP (1<<12) +#define CURLPROTO_IMAPS (1<<13) +#define CURLPROTO_POP3 (1<<14) +#define CURLPROTO_POP3S (1<<15) +#define CURLPROTO_SMTP (1<<16) +#define CURLPROTO_SMTPS (1<<17) +#define CURLPROTO_RTSP (1<<18) +#define CURLPROTO_RTMP (1<<19) +#define CURLPROTO_RTMPT (1<<20) +#define CURLPROTO_RTMPE (1<<21) +#define CURLPROTO_RTMPTE (1<<22) +#define CURLPROTO_RTMPS (1<<23) +#define CURLPROTO_RTMPTS (1<<24) +#define CURLPROTO_GOPHER (1<<25) +#define CURLPROTO_SMB (1<<26) +#define CURLPROTO_SMBS (1<<27) +#define CURLPROTO_ALL (~0) /* enable everything */ + +/* long may be 32 or 64 bits, but we should never depend on anything else + but 32 */ +#define CURLOPTTYPE_LONG 0 +#define CURLOPTTYPE_OBJECTPOINT 10000 +#define CURLOPTTYPE_FUNCTIONPOINT 20000 +#define CURLOPTTYPE_OFF_T 30000 + +/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the + string options from the header file */ + + +#define CURLOPT(na,t,nu) na = t + nu + +/* handy aliases that make no run-time difference */ +#define CURLOPTTYPE_STRINGPOINT CURLOPTTYPE_OBJECTPOINT +#define CURLOPTTYPE_SLISTPOINT CURLOPTTYPE_OBJECTPOINT + +/* + * All CURLOPT_* values. + */ + +typedef enum { + /* This is the FILE * or void * the regular output should be written to. */ + CURLOPT(CURLOPT_WRITEDATA, CURLOPTTYPE_OBJECTPOINT, 1), + + /* The full URL to get/put */ + CURLOPT(CURLOPT_URL, CURLOPTTYPE_STRINGPOINT, 2), + + /* Port number to connect to, if other than default. */ + CURLOPT(CURLOPT_PORT, CURLOPTTYPE_LONG, 3), + + /* Name of proxy to use. */ + CURLOPT(CURLOPT_PROXY, CURLOPTTYPE_STRINGPOINT, 4), + + /* "user:password;options" to use when fetching. */ + CURLOPT(CURLOPT_USERPWD, CURLOPTTYPE_STRINGPOINT, 5), + + /* "user:password" to use with proxy. */ + CURLOPT(CURLOPT_PROXYUSERPWD, CURLOPTTYPE_STRINGPOINT, 6), + + /* Range to get, specified as an ASCII string. */ + CURLOPT(CURLOPT_RANGE, CURLOPTTYPE_STRINGPOINT, 7), + + /* not used */ + + /* Specified file stream to upload from (use as input): */ + CURLOPT(CURLOPT_READDATA, CURLOPTTYPE_OBJECTPOINT, 9), + + /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE + * bytes big. */ + CURLOPT(CURLOPT_ERRORBUFFER, CURLOPTTYPE_OBJECTPOINT, 10), + + /* Function that will be called to store the output (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_WRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 11), + + /* Function that will be called to read the input (instead of fread). The + * parameters will use fread() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_READFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 12), + + /* Time-out the read operation after this amount of seconds */ + CURLOPT(CURLOPT_TIMEOUT, CURLOPTTYPE_LONG, 13), + + /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about + * how large the file being sent really is. That allows better error + * checking and better verifies that the upload was successful. -1 means + * unknown size. + * + * For large file support, there is also a _LARGE version of the key + * which takes an off_t type, allowing platforms with larger off_t + * sizes to handle larger files. See below for INFILESIZE_LARGE. + */ + CURLOPT(CURLOPT_INFILESIZE, CURLOPTTYPE_LONG, 14), + + /* POST static input fields. */ + CURLOPT(CURLOPT_POSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 15), + + /* Set the referrer page (needed by some CGIs) */ + CURLOPT(CURLOPT_REFERER, CURLOPTTYPE_STRINGPOINT, 16), + + /* Set the FTP PORT string (interface name, named or numerical IP address) + Use i.e '-' to use default address. */ + CURLOPT(CURLOPT_FTPPORT, CURLOPTTYPE_STRINGPOINT, 17), + + /* Set the User-Agent string (examined by some CGIs) */ + CURLOPT(CURLOPT_USERAGENT, CURLOPTTYPE_STRINGPOINT, 18), + + /* If the download receives less than "low speed limit" bytes/second + * during "low speed time" seconds, the operations is aborted. + * You could i.e if you have a pretty high speed connection, abort if + * it is less than 2000 bytes/sec during 20 seconds. + */ + + /* Set the "low speed limit" */ + CURLOPT(CURLOPT_LOW_SPEED_LIMIT, CURLOPTTYPE_LONG, 19), + + /* Set the "low speed time" */ + CURLOPT(CURLOPT_LOW_SPEED_TIME, CURLOPTTYPE_LONG, 20), + + /* Set the continuation offset. + * + * Note there is also a _LARGE version of this key which uses + * off_t types, allowing for large file offsets on platforms which + * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE. + */ + CURLOPT(CURLOPT_RESUME_FROM, CURLOPTTYPE_LONG, 21), + + /* Set cookie in request: */ + CURLOPT(CURLOPT_COOKIE, CURLOPTTYPE_STRINGPOINT, 22), + + /* This points to a linked list of headers, struct curl_slist kind. This + list is also used for RTSP (in spite of its name) */ + CURLOPT(CURLOPT_HTTPHEADER, CURLOPTTYPE_SLISTPOINT, 23), + + /* This points to a linked list of post entries, struct curl_httppost */ + CURLOPT(CURLOPT_HTTPPOST, CURLOPTTYPE_OBJECTPOINT, 24), + + /* name of the file keeping your private SSL-certificate */ + CURLOPT(CURLOPT_SSLCERT, CURLOPTTYPE_STRINGPOINT, 25), + + /* password for the SSL or SSH private key */ + CURLOPT(CURLOPT_KEYPASSWD, CURLOPTTYPE_STRINGPOINT, 26), + + /* send TYPE parameter? */ + CURLOPT(CURLOPT_CRLF, CURLOPTTYPE_LONG, 27), + + /* send linked-list of QUOTE commands */ + CURLOPT(CURLOPT_QUOTE, CURLOPTTYPE_SLISTPOINT, 28), + + /* send FILE * or void * to store headers to, if you use a callback it + is simply passed to the callback unmodified */ + CURLOPT(CURLOPT_HEADERDATA, CURLOPTTYPE_OBJECTPOINT, 29), + + /* point to a file to read the initial cookies from, also enables + "cookie awareness" */ + CURLOPT(CURLOPT_COOKIEFILE, CURLOPTTYPE_STRINGPOINT, 31), + + /* What version to specifically try to use. + See CURL_SSLVERSION defines below. */ + CURLOPT(CURLOPT_SSLVERSION, CURLOPTTYPE_LONG, 32), + + /* What kind of HTTP time condition to use, see defines */ + CURLOPT(CURLOPT_TIMECONDITION, CURLOPTTYPE_LONG, 33), + + /* Time to use with the above condition. Specified in number of seconds + since 1 Jan 1970 */ + CURLOPT(CURLOPT_TIMEVALUE, CURLOPTTYPE_LONG, 34), + + /* 35 = OBSOLETE */ + + /* Custom request, for customizing the get command like + HTTP: DELETE, TRACE and others + FTP: to use a different list command + */ + CURLOPT(CURLOPT_CUSTOMREQUEST, CURLOPTTYPE_STRINGPOINT, 36), + + /* FILE handle to use instead of stderr */ + CURLOPT(CURLOPT_STDERR, CURLOPTTYPE_OBJECTPOINT, 37), + + /* 38 is not used */ + + /* send linked-list of post-transfer QUOTE commands */ + CURLOPT(CURLOPT_POSTQUOTE, CURLOPTTYPE_SLISTPOINT, 39), + + /* OBSOLETE, do not use! */ + CURLOPT(CURLOPT_OBSOLETE40, CURLOPTTYPE_OBJECTPOINT, 40), + + /* talk a lot */ + CURLOPT(CURLOPT_VERBOSE, CURLOPTTYPE_LONG, 41), + + /* throw the header out too */ + CURLOPT(CURLOPT_HEADER, CURLOPTTYPE_LONG, 42), + + /* shut off the progress meter */ + CURLOPT(CURLOPT_NOPROGRESS, CURLOPTTYPE_LONG, 43), + + /* use HEAD to get http document */ + CURLOPT(CURLOPT_NOBODY, CURLOPTTYPE_LONG, 44), + + /* no output on http error codes >= 400 */ + CURLOPT(CURLOPT_FAILONERROR, CURLOPTTYPE_LONG, 45), + + /* this is an upload */ + CURLOPT(CURLOPT_UPLOAD, CURLOPTTYPE_LONG, 46), + + /* HTTP POST method */ + CURLOPT(CURLOPT_POST, CURLOPTTYPE_LONG, 47), + + /* bare names when listing directories */ + CURLOPT(CURLOPT_DIRLISTONLY, CURLOPTTYPE_LONG, 48), + + /* Append instead of overwrite on upload! */ + CURLOPT(CURLOPT_APPEND, CURLOPTTYPE_LONG, 50), + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + CURLOPT(CURLOPT_NETRC, CURLOPTTYPE_LONG, 51), + + /* use Location: Luke! */ + CURLOPT(CURLOPT_FOLLOWLOCATION, CURLOPTTYPE_LONG, 52), + + /* transfer data in text/ASCII format */ + CURLOPT(CURLOPT_TRANSFERTEXT, CURLOPTTYPE_LONG, 53), + + /* HTTP PUT */ + CURLOPT(CURLOPT_PUT, CURLOPTTYPE_LONG, 54), + + /* 55 = OBSOLETE */ + + /* DEPRECATED + * Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_progress_callback + * prototype defines. */ + CURLOPT(CURLOPT_PROGRESSFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 56), + + /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION + callbacks */ + CURLOPT(CURLOPT_PROGRESSDATA, CURLOPTTYPE_OBJECTPOINT, 57), +#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA + + /* We want the referrer field set automatically when following locations */ + CURLOPT(CURLOPT_AUTOREFERER, CURLOPTTYPE_LONG, 58), + + /* Port of the proxy, can be set in the proxy string as well with: + "[host]:[port]" */ + CURLOPT(CURLOPT_PROXYPORT, CURLOPTTYPE_LONG, 59), + + /* size of the POST input data, if strlen() is not good to use */ + CURLOPT(CURLOPT_POSTFIELDSIZE, CURLOPTTYPE_LONG, 60), + + /* tunnel non-http operations through a HTTP proxy */ + CURLOPT(CURLOPT_HTTPPROXYTUNNEL, CURLOPTTYPE_LONG, 61), + + /* Set the interface string to use as outgoing network interface */ + CURLOPT(CURLOPT_INTERFACE, CURLOPTTYPE_STRINGPOINT, 62), + + /* Set the krb4/5 security level, this also enables krb4/5 awareness. This + * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string + * is set but doesn't match one of these, 'private' will be used. */ + CURLOPT(CURLOPT_KRBLEVEL, CURLOPTTYPE_STRINGPOINT, 63), + + /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ + CURLOPT(CURLOPT_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 64), + + /* The CApath or CAfile used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAINFO, CURLOPTTYPE_STRINGPOINT, 65), + + /* 66 = OBSOLETE */ + /* 67 = OBSOLETE */ + + /* Maximum number of http redirects to follow */ + CURLOPT(CURLOPT_MAXREDIRS, CURLOPTTYPE_LONG, 68), + + /* Pass a long set to 1 to get the date of the requested document (if + possible)! Pass a zero to shut it off. */ + CURLOPT(CURLOPT_FILETIME, CURLOPTTYPE_LONG, 69), + + /* This points to a linked list of telnet options */ + CURLOPT(CURLOPT_TELNETOPTIONS, CURLOPTTYPE_SLISTPOINT, 70), + + /* Max amount of cached alive connections */ + CURLOPT(CURLOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 71), + + /* OBSOLETE, do not use! */ + CURLOPT(CURLOPT_OBSOLETE72, CURLOPTTYPE_LONG, 72), + + /* 73 = OBSOLETE */ + + /* Set to explicitly use a new connection for the upcoming transfer. + Do not use this unless you're absolutely sure of this, as it makes the + operation slower and is less friendly for the network. */ + CURLOPT(CURLOPT_FRESH_CONNECT, CURLOPTTYPE_LONG, 74), + + /* Set to explicitly forbid the upcoming transfer's connection to be re-used + when done. Do not use this unless you're absolutely sure of this, as it + makes the operation slower and is less friendly for the network. */ + CURLOPT(CURLOPT_FORBID_REUSE, CURLOPTTYPE_LONG, 75), + + /* Set to a file name that contains random data for libcurl to use to + seed the random engine when doing SSL connects. */ + CURLOPT(CURLOPT_RANDOM_FILE, CURLOPTTYPE_STRINGPOINT, 76), + + /* Set to the Entropy Gathering Daemon socket pathname */ + CURLOPT(CURLOPT_EGDSOCKET, CURLOPTTYPE_STRINGPOINT, 77), + + /* Time-out connect operations after this amount of seconds, if connects are + OK within this time, then fine... This only aborts the connect phase. */ + CURLOPT(CURLOPT_CONNECTTIMEOUT, CURLOPTTYPE_LONG, 78), + + /* Function that will be called to store headers (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CURLOPT(CURLOPT_HEADERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 79), + + /* Set this to force the HTTP request to get back to GET. Only really usable + if POST, PUT or a custom request have been used first. + */ + CURLOPT(CURLOPT_HTTPGET, CURLOPTTYPE_LONG, 80), + + /* Set if we should verify the Common name from the peer certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches the + * provided hostname. */ + CURLOPT(CURLOPT_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 81), + + /* Specify which file name to write all known cookies in after completed + operation. Set file name to "-" (dash) to make it go to stdout. */ + CURLOPT(CURLOPT_COOKIEJAR, CURLOPTTYPE_STRINGPOINT, 82), + + /* Specify which SSL ciphers to use */ + CURLOPT(CURLOPT_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 83), + + /* Specify which HTTP version to use! This must be set to one of the + CURL_HTTP_VERSION* enums set below. */ + CURLOPT(CURLOPT_HTTP_VERSION, CURLOPTTYPE_LONG, 84), + + /* Specifically switch on or off the FTP engine's use of the EPSV command. By + default, that one will always be attempted before the more traditional + PASV command. */ + CURLOPT(CURLOPT_FTP_USE_EPSV, CURLOPTTYPE_LONG, 85), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ + CURLOPT(CURLOPT_SSLCERTTYPE, CURLOPTTYPE_STRINGPOINT, 86), + + /* name of the file keeping your private SSL-key */ + CURLOPT(CURLOPT_SSLKEY, CURLOPTTYPE_STRINGPOINT, 87), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ + CURLOPT(CURLOPT_SSLKEYTYPE, CURLOPTTYPE_STRINGPOINT, 88), + + /* crypto engine for the SSL-sub system */ + CURLOPT(CURLOPT_SSLENGINE, CURLOPTTYPE_STRINGPOINT, 89), + + /* set the crypto engine for the SSL-sub system as default + the param has no meaning... + */ + CURLOPT(CURLOPT_SSLENGINE_DEFAULT, CURLOPTTYPE_LONG, 90), + + /* Non-zero value means to use the global dns cache */ + /* DEPRECATED, do not use! */ + CURLOPT(CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOPTTYPE_LONG, 91), + + /* DNS cache timeout */ + CURLOPT(CURLOPT_DNS_CACHE_TIMEOUT, CURLOPTTYPE_LONG, 92), + + /* send linked-list of pre-transfer QUOTE commands */ + CURLOPT(CURLOPT_PREQUOTE, CURLOPTTYPE_SLISTPOINT, 93), + + /* set the debug function */ + CURLOPT(CURLOPT_DEBUGFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 94), + + /* set the data for the debug function */ + CURLOPT(CURLOPT_DEBUGDATA, CURLOPTTYPE_OBJECTPOINT, 95), + + /* mark this as start of a cookie session */ + CURLOPT(CURLOPT_COOKIESESSION, CURLOPTTYPE_LONG, 96), + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_CAPATH, CURLOPTTYPE_STRINGPOINT, 97), + + /* Instruct libcurl to use a smaller receive buffer */ + CURLOPT(CURLOPT_BUFFERSIZE, CURLOPTTYPE_LONG, 98), + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + CURLOPT(CURLOPT_NOSIGNAL, CURLOPTTYPE_LONG, 99), + + /* Provide a CURLShare for mutexing non-ts data */ + CURLOPT(CURLOPT_SHARE, CURLOPTTYPE_OBJECTPOINT, 100), + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), + CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and + CURLPROXY_SOCKS5. */ + CURLOPT(CURLOPT_PROXYTYPE, CURLOPTTYPE_LONG, 101), + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. Before 7.21.6, this was known as + CURLOPT_ENCODING */ + CURLOPT(CURLOPT_ACCEPT_ENCODING, CURLOPTTYPE_STRINGPOINT, 102), + + /* Set pointer to private data */ + CURLOPT(CURLOPT_PRIVATE, CURLOPTTYPE_OBJECTPOINT, 103), + + /* Set aliases for HTTP 200 in the HTTP Response header */ + CURLOPT(CURLOPT_HTTP200ALIASES, CURLOPTTYPE_SLISTPOINT, 104), + + /* Continue to send authentication (user+password) when following locations, + even when hostname changed. This can potentially send off the name + and password to whatever host the server decides. */ + CURLOPT(CURLOPT_UNRESTRICTED_AUTH, CURLOPTTYPE_LONG, 105), + + /* Specifically switch on or off the FTP engine's use of the EPRT command ( + it also disables the LPRT attempt). By default, those ones will always be + attempted before the good old traditional PORT command. */ + CURLOPT(CURLOPT_FTP_USE_EPRT, CURLOPTTYPE_LONG, 106), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_USERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CURLOPT(CURLOPT_HTTPAUTH, CURLOPTTYPE_LONG, 107), + + /* Set the ssl context callback function, currently only for OpenSSL or + WolfSSL ssl_ctx, or mbedTLS mbedtls_ssl_config in the second argument. + The function must match the curl_ssl_ctx_callback prototype. */ + CURLOPT(CURLOPT_SSL_CTX_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 108), + + /* Set the userdata for the ssl context callback function's third + argument */ + CURLOPT(CURLOPT_SSL_CTX_DATA, CURLOPTTYPE_OBJECTPOINT, 109), + + /* FTP Option that causes missing dirs to be created on the remote server. + In 7.19.4 we introduced the convenience enums for this option using the + CURLFTP_CREATE_DIR prefix. + */ + CURLOPT(CURLOPT_FTP_CREATE_MISSING_DIRS, CURLOPTTYPE_LONG, 110), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CURLOPT(CURLOPT_PROXYAUTH, CURLOPTTYPE_LONG, 111), + + /* FTP option that changes the timeout, in seconds, associated with + getting a response. This is different from transfer timeout time and + essentially places a demand on the FTP server to acknowledge commands + in a timely manner. */ + CURLOPT(CURLOPT_FTP_RESPONSE_TIMEOUT, CURLOPTTYPE_LONG, 112), +#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT + + /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to + tell libcurl to resolve names to those IP versions only. This only has + affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */ + CURLOPT(CURLOPT_IPRESOLVE, CURLOPTTYPE_LONG, 113), + + /* Set this option to limit the size of a file that will be downloaded from + an HTTP or FTP server. + + Note there is also _LARGE version which adds large file support for + platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */ + CURLOPT(CURLOPT_MAXFILESIZE, CURLOPTTYPE_LONG, 114), + + /* See the comment for INFILESIZE above, but in short, specifies + * the size of the file being uploaded. -1 means unknown. + */ + CURLOPT(CURLOPT_INFILESIZE_LARGE, CURLOPTTYPE_OFF_T, 115), + + /* Sets the continuation offset. There is also a CURLOPTTYPE_LONG version + * of this; look above for RESUME_FROM. + */ + CURLOPT(CURLOPT_RESUME_FROM_LARGE, CURLOPTTYPE_OFF_T, 116), + + /* Sets the maximum size of data that will be downloaded from + * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. + */ + CURLOPT(CURLOPT_MAXFILESIZE_LARGE, CURLOPTTYPE_OFF_T, 117), + + /* Set this option to the file name of your .netrc file you want libcurl + to parse (using the CURLOPT_NETRC option). If not set, libcurl will do + a poor attempt to find the user's home directory and check for a .netrc + file in there. */ + CURLOPT(CURLOPT_NETRC_FILE, CURLOPTTYPE_STRINGPOINT, 118), + + /* Enable SSL/TLS for FTP, pick one of: + CURLUSESSL_TRY - try using SSL, proceed anyway otherwise + CURLUSESSL_CONTROL - SSL for the control connection or fail + CURLUSESSL_ALL - SSL for all communication or fail + */ + CURLOPT(CURLOPT_USE_SSL, CURLOPTTYPE_LONG, 119), + + /* The _LARGE version of the standard POSTFIELDSIZE option */ + CURLOPT(CURLOPT_POSTFIELDSIZE_LARGE, CURLOPTTYPE_OFF_T, 120), + + /* Enable/disable the TCP Nagle algorithm */ + CURLOPT(CURLOPT_TCP_NODELAY, CURLOPTTYPE_LONG, 121), + + /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 123 OBSOLETE. Gone in 7.16.0 */ + /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 127 OBSOLETE. Gone in 7.16.0 */ + /* 128 OBSOLETE. Gone in 7.16.0 */ + + /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option + can be used to change libcurl's default action which is to first try + "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK + response has been received. + + Available parameters are: + CURLFTPAUTH_DEFAULT - let libcurl decide + CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS + CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL + */ + CURLOPT(CURLOPT_FTPSSLAUTH, CURLOPTTYPE_LONG, 129), + + CURLOPT(CURLOPT_IOCTLFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 130), + CURLOPT(CURLOPT_IOCTLDATA, CURLOPTTYPE_OBJECTPOINT, 131), + + /* 132 OBSOLETE. Gone in 7.16.0 */ + /* 133 OBSOLETE. Gone in 7.16.0 */ + + /* zero terminated string for pass on to the FTP server when asked for + "account" info */ + CURLOPT(CURLOPT_FTP_ACCOUNT, CURLOPTTYPE_STRINGPOINT, 134), + + /* feed cookie into cookie engine */ + CURLOPT(CURLOPT_COOKIELIST, CURLOPTTYPE_STRINGPOINT, 135), + + /* ignore Content-Length */ + CURLOPT(CURLOPT_IGNORE_CONTENT_LENGTH, CURLOPTTYPE_LONG, 136), + + /* Set to non-zero to skip the IP address received in a 227 PASV FTP server + response. Typically used for FTP-SSL purposes but is not restricted to + that. libcurl will then instead use the same IP address it used for the + control connection. */ + CURLOPT(CURLOPT_FTP_SKIP_PASV_IP, CURLOPTTYPE_LONG, 137), + + /* Select "file method" to use when doing FTP, see the curl_ftpmethod + above. */ + CURLOPT(CURLOPT_FTP_FILEMETHOD, CURLOPTTYPE_LONG, 138), + + /* Local port number to bind the socket to */ + CURLOPT(CURLOPT_LOCALPORT, CURLOPTTYPE_LONG, 139), + + /* Number of ports to try, including the first one set with LOCALPORT. + Thus, setting it to 1 will make no additional attempts but the first. + */ + CURLOPT(CURLOPT_LOCALPORTRANGE, CURLOPTTYPE_LONG, 140), + + /* no transfer, set up connection and let application use the socket by + extracting it with CURLINFO_LASTSOCKET */ + CURLOPT(CURLOPT_CONNECT_ONLY, CURLOPTTYPE_LONG, 141), + + /* Function that will be called to convert from the + network encoding (instead of using the iconv calls in libcurl) */ + CURLOPT(CURLOPT_CONV_FROM_NETWORK_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 142), + + /* Function that will be called to convert to the + network encoding (instead of using the iconv calls in libcurl) */ + CURLOPT(CURLOPT_CONV_TO_NETWORK_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 143), + + /* Function that will be called to convert from UTF8 + (instead of using the iconv calls in libcurl) + Note that this is used only for SSL certificate processing */ + CURLOPT(CURLOPT_CONV_FROM_UTF8_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 144), + + /* if the connection proceeds too quickly then need to slow it down */ + /* limit-rate: maximum number of bytes per second to send or receive */ + CURLOPT(CURLOPT_MAX_SEND_SPEED_LARGE, CURLOPTTYPE_OFF_T, 145), + CURLOPT(CURLOPT_MAX_RECV_SPEED_LARGE, CURLOPTTYPE_OFF_T, 146), + + /* Pointer to command string to send if USER/PASS fails. */ + CURLOPT(CURLOPT_FTP_ALTERNATIVE_TO_USER, CURLOPTTYPE_STRINGPOINT, 147), + + /* callback function for setting socket options */ + CURLOPT(CURLOPT_SOCKOPTFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 148), + CURLOPT(CURLOPT_SOCKOPTDATA, CURLOPTTYPE_OBJECTPOINT, 149), + + /* set to 0 to disable session ID re-use for this transfer, default is + enabled (== 1) */ + CURLOPT(CURLOPT_SSL_SESSIONID_CACHE, CURLOPTTYPE_LONG, 150), + + /* allowed SSH authentication methods */ + CURLOPT(CURLOPT_SSH_AUTH_TYPES, CURLOPTTYPE_LONG, 151), + + /* Used by scp/sftp to do public/private key authentication */ + CURLOPT(CURLOPT_SSH_PUBLIC_KEYFILE, CURLOPTTYPE_STRINGPOINT, 152), + CURLOPT(CURLOPT_SSH_PRIVATE_KEYFILE, CURLOPTTYPE_STRINGPOINT, 153), + + /* Send CCC (Clear Command Channel) after authentication */ + CURLOPT(CURLOPT_FTP_SSL_CCC, CURLOPTTYPE_LONG, 154), + + /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ + CURLOPT(CURLOPT_TIMEOUT_MS, CURLOPTTYPE_LONG, 155), + CURLOPT(CURLOPT_CONNECTTIMEOUT_MS, CURLOPTTYPE_LONG, 156), + + /* set to zero to disable the libcurl's decoding and thus pass the raw body + data to the application even when it is encoded/compressed */ + CURLOPT(CURLOPT_HTTP_TRANSFER_DECODING, CURLOPTTYPE_LONG, 157), + CURLOPT(CURLOPT_HTTP_CONTENT_DECODING, CURLOPTTYPE_LONG, 158), + + /* Permission used when creating new files and directories on the remote + server for protocols that support it, SFTP/SCP/FILE */ + CURLOPT(CURLOPT_NEW_FILE_PERMS, CURLOPTTYPE_LONG, 159), + CURLOPT(CURLOPT_NEW_DIRECTORY_PERMS, CURLOPTTYPE_LONG, 160), + + /* Set the behaviour of POST when redirecting. Values must be set to one + of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ + CURLOPT(CURLOPT_POSTREDIR, CURLOPTTYPE_LONG, 161), + + /* used by scp/sftp to verify the host's public key */ + CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, CURLOPTTYPE_STRINGPOINT, 162), + + /* Callback function for opening socket (instead of socket(2)). Optionally, + callback is able change the address or refuse to connect returning + CURL_SOCKET_BAD. The callback should have type + curl_opensocket_callback */ + CURLOPT(CURLOPT_OPENSOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 163), + CURLOPT(CURLOPT_OPENSOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 164), + + /* POST volatile input fields. */ + CURLOPT(CURLOPT_COPYPOSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 165), + + /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ + CURLOPT(CURLOPT_PROXY_TRANSFER_MODE, CURLOPTTYPE_LONG, 166), + + /* Callback function for seeking in the input stream */ + CURLOPT(CURLOPT_SEEKFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 167), + CURLOPT(CURLOPT_SEEKDATA, CURLOPTTYPE_OBJECTPOINT, 168), + + /* CRL file */ + CURLOPT(CURLOPT_CRLFILE, CURLOPTTYPE_STRINGPOINT, 169), + + /* Issuer certificate */ + CURLOPT(CURLOPT_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 170), + + /* (IPv6) Address scope */ + CURLOPT(CURLOPT_ADDRESS_SCOPE, CURLOPTTYPE_LONG, 171), + + /* Collect certificate chain info and allow it to get retrievable with + CURLINFO_CERTINFO after the transfer is complete. */ + CURLOPT(CURLOPT_CERTINFO, CURLOPTTYPE_LONG, 172), + + /* "name" and "pwd" to use when fetching. */ + CURLOPT(CURLOPT_USERNAME, CURLOPTTYPE_STRINGPOINT, 173), + CURLOPT(CURLOPT_PASSWORD, CURLOPTTYPE_STRINGPOINT, 174), + + /* "name" and "pwd" to use with Proxy when fetching. */ + CURLOPT(CURLOPT_PROXYUSERNAME, CURLOPTTYPE_STRINGPOINT, 175), + CURLOPT(CURLOPT_PROXYPASSWORD, CURLOPTTYPE_STRINGPOINT, 176), + + /* Comma separated list of hostnames defining no-proxy zones. These should + match both hostnames directly, and hostnames within a domain. For + example, local.com will match local.com and www.local.com, but NOT + notlocal.com or www.notlocal.com. For compatibility with other + implementations of this, .local.com will be considered to be the same as + local.com. A single * is the only valid wildcard, and effectively + disables the use of proxy. */ + CURLOPT(CURLOPT_NOPROXY, CURLOPTTYPE_STRINGPOINT, 177), + + /* block size for TFTP transfers */ + CURLOPT(CURLOPT_TFTP_BLKSIZE, CURLOPTTYPE_LONG, 178), + + /* Socks Service */ + /* DEPRECATED, do not use! */ + CURLOPT(CURLOPT_SOCKS5_GSSAPI_SERVICE, CURLOPTTYPE_STRINGPOINT, 179), + + /* Socks Service */ + CURLOPT(CURLOPT_SOCKS5_GSSAPI_NEC, CURLOPTTYPE_LONG, 180), + + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + CURLOPT(CURLOPT_PROTOCOLS, CURLOPTTYPE_LONG, 181), + + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. */ + CURLOPT(CURLOPT_REDIR_PROTOCOLS, CURLOPTTYPE_LONG, 182), + + /* set the SSH knownhost file name to use */ + CURLOPT(CURLOPT_SSH_KNOWNHOSTS, CURLOPTTYPE_STRINGPOINT, 183), + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + CURLOPT(CURLOPT_SSH_KEYFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 184), + + /* set the SSH host key callback custom pointer */ + CURLOPT(CURLOPT_SSH_KEYDATA, CURLOPTTYPE_OBJECTPOINT, 185), + + /* set the SMTP mail originator */ + CURLOPT(CURLOPT_MAIL_FROM, CURLOPTTYPE_STRINGPOINT, 186), + + /* set the list of SMTP mail receiver(s) */ + CURLOPT(CURLOPT_MAIL_RCPT, CURLOPTTYPE_SLISTPOINT, 187), + + /* FTP: send PRET before PASV */ + CURLOPT(CURLOPT_FTP_USE_PRET, CURLOPTTYPE_LONG, 188), + + /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */ + CURLOPT(CURLOPT_RTSP_REQUEST, CURLOPTTYPE_LONG, 189), + + /* The RTSP session identifier */ + CURLOPT(CURLOPT_RTSP_SESSION_ID, CURLOPTTYPE_STRINGPOINT, 190), + + /* The RTSP stream URI */ + CURLOPT(CURLOPT_RTSP_STREAM_URI, CURLOPTTYPE_STRINGPOINT, 191), + + /* The Transport: header to use in RTSP requests */ + CURLOPT(CURLOPT_RTSP_TRANSPORT, CURLOPTTYPE_STRINGPOINT, 192), + + /* Manually initialize the client RTSP CSeq for this handle */ + CURLOPT(CURLOPT_RTSP_CLIENT_CSEQ, CURLOPTTYPE_LONG, 193), + + /* Manually initialize the server RTSP CSeq for this handle */ + CURLOPT(CURLOPT_RTSP_SERVER_CSEQ, CURLOPTTYPE_LONG, 194), + + /* The stream to pass to INTERLEAVEFUNCTION. */ + CURLOPT(CURLOPT_INTERLEAVEDATA, CURLOPTTYPE_OBJECTPOINT, 195), + + /* Let the application define a custom write method for RTP data */ + CURLOPT(CURLOPT_INTERLEAVEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 196), + + /* Turn on wildcard matching */ + CURLOPT(CURLOPT_WILDCARDMATCH, CURLOPTTYPE_LONG, 197), + + /* Directory matching callback called before downloading of an + individual file (chunk) started */ + CURLOPT(CURLOPT_CHUNK_BGN_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 198), + + /* Directory matching callback called after the file (chunk) + was downloaded, or skipped */ + CURLOPT(CURLOPT_CHUNK_END_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 199), + + /* Change match (fnmatch-like) callback for wildcard matching */ + CURLOPT(CURLOPT_FNMATCH_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 200), + + /* Let the application define custom chunk data pointer */ + CURLOPT(CURLOPT_CHUNK_DATA, CURLOPTTYPE_OBJECTPOINT, 201), + + /* FNMATCH_FUNCTION user pointer */ + CURLOPT(CURLOPT_FNMATCH_DATA, CURLOPTTYPE_OBJECTPOINT, 202), + + /* send linked-list of name:port:address sets */ + CURLOPT(CURLOPT_RESOLVE, CURLOPTTYPE_SLISTPOINT, 203), + + /* Set a username for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 204), + + /* Set a password for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_PASSWORD, CURLOPTTYPE_STRINGPOINT, 205), + + /* Set authentication type for authenticated TLS */ + CURLOPT(CURLOPT_TLSAUTH_TYPE, CURLOPTTYPE_STRINGPOINT, 206), + + /* Set to 1 to enable the "TE:" header in HTTP requests to ask for + compressed transfer-encoded responses. Set to 0 to disable the use of TE: + in outgoing requests. The current default is 0, but it might change in a + future libcurl release. + + libcurl will ask for the compressed methods it knows of, and if that + isn't any, it will not ask for transfer-encoding at all even if this + option is set to 1. + + */ + CURLOPT(CURLOPT_TRANSFER_ENCODING, CURLOPTTYPE_LONG, 207), + + /* Callback function for closing socket (instead of close(2)). The callback + should have type curl_closesocket_callback */ + CURLOPT(CURLOPT_CLOSESOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 208), + CURLOPT(CURLOPT_CLOSESOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 209), + + /* allow GSSAPI credential delegation */ + CURLOPT(CURLOPT_GSSAPI_DELEGATION, CURLOPTTYPE_LONG, 210), + + /* Set the name servers to use for DNS resolution */ + CURLOPT(CURLOPT_DNS_SERVERS, CURLOPTTYPE_STRINGPOINT, 211), + + /* Time-out accept operations (currently for FTP only) after this amount + of milliseconds. */ + CURLOPT(CURLOPT_ACCEPTTIMEOUT_MS, CURLOPTTYPE_LONG, 212), + + /* Set TCP keepalive */ + CURLOPT(CURLOPT_TCP_KEEPALIVE, CURLOPTTYPE_LONG, 213), + + /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */ + CURLOPT(CURLOPT_TCP_KEEPIDLE, CURLOPTTYPE_LONG, 214), + CURLOPT(CURLOPT_TCP_KEEPINTVL, CURLOPTTYPE_LONG, 215), + + /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */ + CURLOPT(CURLOPT_SSL_OPTIONS, CURLOPTTYPE_LONG, 216), + + /* Set the SMTP auth originator */ + CURLOPT(CURLOPT_MAIL_AUTH, CURLOPTTYPE_STRINGPOINT, 217), + + /* Enable/disable SASL initial response */ + CURLOPT(CURLOPT_SASL_IR, CURLOPTTYPE_LONG, 218), + + /* Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_xferinfo_callback + * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ + CURLOPT(CURLOPT_XFERINFOFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 219), + + /* The XOAUTH2 bearer token */ + CURLOPT(CURLOPT_XOAUTH2_BEARER, CURLOPTTYPE_STRINGPOINT, 220), + + /* Set the interface string to use as outgoing network + * interface for DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_INTERFACE, CURLOPTTYPE_STRINGPOINT, 221), + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_LOCAL_IP4, CURLOPTTYPE_STRINGPOINT, 222), + + /* Set the local IPv6 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CURLOPT(CURLOPT_DNS_LOCAL_IP6, CURLOPTTYPE_STRINGPOINT, 223), + + /* Set authentication options directly */ + CURLOPT(CURLOPT_LOGIN_OPTIONS, CURLOPTTYPE_STRINGPOINT, 224), + + /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */ + CURLOPT(CURLOPT_SSL_ENABLE_NPN, CURLOPTTYPE_LONG, 225), + + /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */ + CURLOPT(CURLOPT_SSL_ENABLE_ALPN, CURLOPTTYPE_LONG, 226), + + /* Time to wait for a response to a HTTP request containing an + * Expect: 100-continue header before sending the data anyway. */ + CURLOPT(CURLOPT_EXPECT_100_TIMEOUT_MS, CURLOPTTYPE_LONG, 227), + + /* This points to a linked list of headers used for proxy requests only, + struct curl_slist kind */ + CURLOPT(CURLOPT_PROXYHEADER, CURLOPTTYPE_SLISTPOINT, 228), + + /* Pass in a bitmask of "header options" */ + CURLOPT(CURLOPT_HEADEROPT, CURLOPTTYPE_LONG, 229), + + /* The public key in DER form used to validate the peer public key + this option is used only if SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 230), + + /* Path to Unix domain socket */ + CURLOPT(CURLOPT_UNIX_SOCKET_PATH, CURLOPTTYPE_STRINGPOINT, 231), + + /* Set if we should verify the certificate status. */ + CURLOPT(CURLOPT_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 232), + + /* Set if we should enable TLS false start. */ + CURLOPT(CURLOPT_SSL_FALSESTART, CURLOPTTYPE_LONG, 233), + + /* Do not squash dot-dot sequences */ + CURLOPT(CURLOPT_PATH_AS_IS, CURLOPTTYPE_LONG, 234), + + /* Proxy Service Name */ + CURLOPT(CURLOPT_PROXY_SERVICE_NAME, CURLOPTTYPE_STRINGPOINT, 235), + + /* Service Name */ + CURLOPT(CURLOPT_SERVICE_NAME, CURLOPTTYPE_STRINGPOINT, 236), + + /* Wait/don't wait for pipe/mutex to clarify */ + CURLOPT(CURLOPT_PIPEWAIT, CURLOPTTYPE_LONG, 237), + + /* Set the protocol used when curl is given a URL without a protocol */ + CURLOPT(CURLOPT_DEFAULT_PROTOCOL, CURLOPTTYPE_STRINGPOINT, 238), + + /* Set stream weight, 1 - 256 (default is 16) */ + CURLOPT(CURLOPT_STREAM_WEIGHT, CURLOPTTYPE_LONG, 239), + + /* Set stream dependency on another CURL handle */ + CURLOPT(CURLOPT_STREAM_DEPENDS, CURLOPTTYPE_OBJECTPOINT, 240), + + /* Set E-xclusive stream dependency on another CURL handle */ + CURLOPT(CURLOPT_STREAM_DEPENDS_E, CURLOPTTYPE_OBJECTPOINT, 241), + + /* Do not send any tftp option requests to the server */ + CURLOPT(CURLOPT_TFTP_NO_OPTIONS, CURLOPTTYPE_LONG, 242), + + /* Linked-list of host:port:connect-to-host:connect-to-port, + overrides the URL's host:port (only for the network layer) */ + CURLOPT(CURLOPT_CONNECT_TO, CURLOPTTYPE_SLISTPOINT, 243), + + /* Set TCP Fast Open */ + CURLOPT(CURLOPT_TCP_FASTOPEN, CURLOPTTYPE_LONG, 244), + + /* Continue to send data if the server responds early with an + * HTTP status code >= 300 */ + CURLOPT(CURLOPT_KEEP_SENDING_ON_ERROR, CURLOPTTYPE_LONG, 245), + + /* The CApath or CAfile used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAINFO, CURLOPTTYPE_STRINGPOINT, 246), + + /* The CApath directory used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_CAPATH, CURLOPTTYPE_STRINGPOINT, 247), + + /* Set if we should verify the proxy in ssl handshake, + set 1 to verify. */ + CURLOPT(CURLOPT_PROXY_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 248), + + /* Set if we should verify the Common name from the proxy certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches + * the provided hostname. */ + CURLOPT(CURLOPT_PROXY_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 249), + + /* What version to specifically try to use for proxy. + See CURL_SSLVERSION defines below. */ + CURLOPT(CURLOPT_PROXY_SSLVERSION, CURLOPTTYPE_LONG, 250), + + /* Set a username for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 251), + + /* Set a password for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_PASSWORD, CURLOPTTYPE_STRINGPOINT, 252), + + /* Set authentication type for authenticated TLS for proxy */ + CURLOPT(CURLOPT_PROXY_TLSAUTH_TYPE, CURLOPTTYPE_STRINGPOINT, 253), + + /* name of the file keeping your private SSL-certificate for proxy */ + CURLOPT(CURLOPT_PROXY_SSLCERT, CURLOPTTYPE_STRINGPOINT, 254), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for + proxy */ + CURLOPT(CURLOPT_PROXY_SSLCERTTYPE, CURLOPTTYPE_STRINGPOINT, 255), + + /* name of the file keeping your private SSL-key for proxy */ + CURLOPT(CURLOPT_PROXY_SSLKEY, CURLOPTTYPE_STRINGPOINT, 256), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for + proxy */ + CURLOPT(CURLOPT_PROXY_SSLKEYTYPE, CURLOPTTYPE_STRINGPOINT, 257), + + /* password for the SSL private key for proxy */ + CURLOPT(CURLOPT_PROXY_KEYPASSWD, CURLOPTTYPE_STRINGPOINT, 258), + + /* Specify which SSL ciphers to use for proxy */ + CURLOPT(CURLOPT_PROXY_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 259), + + /* CRL file for proxy */ + CURLOPT(CURLOPT_PROXY_CRLFILE, CURLOPTTYPE_STRINGPOINT, 260), + + /* Enable/disable specific SSL features with a bitmask for proxy, see + CURLSSLOPT_* */ + CURLOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLOPTTYPE_LONG, 261), + + /* Name of pre proxy to use. */ + CURLOPT(CURLOPT_PRE_PROXY, CURLOPTTYPE_STRINGPOINT, 262), + + /* The public key in DER form used to validate the proxy public key + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CURLOPT(CURLOPT_PROXY_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 263), + + /* Path to an abstract Unix domain socket */ + CURLOPT(CURLOPT_ABSTRACT_UNIX_SOCKET, CURLOPTTYPE_STRINGPOINT, 264), + + /* Suppress proxy CONNECT response headers from user callbacks */ + CURLOPT(CURLOPT_SUPPRESS_CONNECT_HEADERS, CURLOPTTYPE_LONG, 265), + + /* The request target, instead of extracted from the URL */ + CURLOPT(CURLOPT_REQUEST_TARGET, CURLOPTTYPE_STRINGPOINT, 266), + + /* bitmask of allowed auth methods for connections to SOCKS5 proxies */ + CURLOPT(CURLOPT_SOCKS5_AUTH, CURLOPTTYPE_LONG, 267), + + /* Enable/disable SSH compression */ + CURLOPT(CURLOPT_SSH_COMPRESSION, CURLOPTTYPE_LONG, 268), + + /* Post MIME data. */ + CURLOPT(CURLOPT_MIMEPOST, CURLOPTTYPE_OBJECTPOINT, 269), + + /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of + seconds since 1 Jan 1970. */ + CURLOPT(CURLOPT_TIMEVALUE_LARGE, CURLOPTTYPE_OFF_T, 270), + + /* Head start in milliseconds to give happy eyeballs. */ + CURLOPT(CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, CURLOPTTYPE_LONG, 271), + + /* Function that will be called before a resolver request is made */ + CURLOPT(CURLOPT_RESOLVER_START_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 272), + + /* User data to pass to the resolver start callback. */ + CURLOPT(CURLOPT_RESOLVER_START_DATA, CURLOPTTYPE_OBJECTPOINT, 273), + + /* send HAProxy PROXY protocol header? */ + CURLOPT(CURLOPT_HAPROXYPROTOCOL, CURLOPTTYPE_LONG, 274), + + /* shuffle addresses before use when DNS returns multiple */ + CURLOPT(CURLOPT_DNS_SHUFFLE_ADDRESSES, CURLOPTTYPE_LONG, 275), + + /* Specify which TLS 1.3 ciphers suites to use */ + CURLOPT(CURLOPT_TLS13_CIPHERS, CURLOPTTYPE_STRINGPOINT, 276), + CURLOPT(CURLOPT_PROXY_TLS13_CIPHERS, CURLOPTTYPE_STRINGPOINT, 277), + + /* Disallow specifying username/login in URL. */ + CURLOPT(CURLOPT_DISALLOW_USERNAME_IN_URL, CURLOPTTYPE_LONG, 278), + + /* DNS-over-HTTPS URL */ + CURLOPT(CURLOPT_DOH_URL, CURLOPTTYPE_STRINGPOINT, 279), + + /* Preferred buffer size to use for uploads */ + CURLOPT(CURLOPT_UPLOAD_BUFFERSIZE, CURLOPTTYPE_LONG, 280), + + /* Time in ms between connection upkeep calls for long-lived connections. */ + CURLOPT(CURLOPT_UPKEEP_INTERVAL_MS, CURLOPTTYPE_LONG, 281), + + /* Specify URL using CURL URL API. */ + CURLOPT(CURLOPT_CURLU, CURLOPTTYPE_OBJECTPOINT, 282), + + /* add trailing data just after no more data is available */ + CURLOPT(CURLOPT_TRAILERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 283), + + /* pointer to be passed to HTTP_TRAILER_FUNCTION */ + CURLOPT(CURLOPT_TRAILERDATA, CURLOPTTYPE_OBJECTPOINT, 284), + + /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */ + CURLOPT(CURLOPT_HTTP09_ALLOWED, CURLOPTTYPE_LONG, 285), + + /* alt-svc control bitmask */ + CURLOPT(CURLOPT_ALTSVC_CTRL, CURLOPTTYPE_LONG, 286), + + /* alt-svc cache file name to possibly read from/write to */ + CURLOPT(CURLOPT_ALTSVC, CURLOPTTYPE_STRINGPOINT, 287), + + /* maximum age of a connection to consider it for reuse (in seconds) */ + CURLOPT(CURLOPT_MAXAGE_CONN, CURLOPTTYPE_LONG, 288), + + /* SASL authorisation identity */ + CURLOPT(CURLOPT_SASL_AUTHZID, CURLOPTTYPE_STRINGPOINT, 289), + + /* allow RCPT TO command to fail for some recipients */ + CURLOPT(CURLOPT_MAIL_RCPT_ALLLOWFAILS, CURLOPTTYPE_LONG, 290), + + CURLOPT_LASTENTRY /* the last unused */ +} CURLoption; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2011 */ + +/* This was added in version 7.19.1 */ +#define CURLOPT_POST301 CURLOPT_POSTREDIR + +/* These are scheduled to disappear by 2009 */ + +/* The following were added in 7.17.0 */ +#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_FTPAPPEND CURLOPT_APPEND +#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY +#define CURLOPT_FTP_SSL CURLOPT_USE_SSL + +/* The following were added earlier */ + +#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL + +#else +/* This is set if CURL_NO_OLDIES is defined at compile-time */ +#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */ +#endif + + + /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host + name resolves addresses using more than one IP protocol version, this + option might be handy to force libcurl to use a specific IP version. */ +#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP + versions that your system allows */ +#define CURL_IPRESOLVE_V4 1 /* resolve to IPv4 addresses */ +#define CURL_IPRESOLVE_V6 2 /* resolve to IPv6 addresses */ + + /* three convenient "aliases" that follow the name scheme better */ +#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER + + /* These enums are for use with the CURLOPT_HTTP_VERSION option. */ +enum { + CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd + like the library to choose the best possible + for us! */ + CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ + CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ + CURL_HTTP_VERSION_2_0, /* please use HTTP 2 in the request */ + CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */ + CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE, /* please use HTTP 2 without HTTP/1.1 + Upgrade */ + CURL_HTTP_VERSION_3 = 30, /* Makes use of explicit HTTP/3 without fallback. + Use CURLOPT_ALTSVC to enable HTTP/3 upgrade */ + CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ +}; + +/* Convenience definition simple because the name of the version is HTTP/2 and + not 2.0. The 2_0 version of the enum name was set while the version was + still planned to be 2.0 and we stick to it for compatibility. */ +#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0 + +/* + * Public API enums for RTSP requests + */ +enum { + CURL_RTSPREQ_NONE, /* first in list */ + CURL_RTSPREQ_OPTIONS, + CURL_RTSPREQ_DESCRIBE, + CURL_RTSPREQ_ANNOUNCE, + CURL_RTSPREQ_SETUP, + CURL_RTSPREQ_PLAY, + CURL_RTSPREQ_PAUSE, + CURL_RTSPREQ_TEARDOWN, + CURL_RTSPREQ_GET_PARAMETER, + CURL_RTSPREQ_SET_PARAMETER, + CURL_RTSPREQ_RECORD, + CURL_RTSPREQ_RECEIVE, + CURL_RTSPREQ_LAST /* last in list */ +}; + + /* These enums are for use with the CURLOPT_NETRC option. */ +enum CURL_NETRC_OPTION { + CURL_NETRC_IGNORED, /* The .netrc will never be read. + * This is the default. */ + CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred + * to one in the .netrc. */ + CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. + * Unless one is set programmatically, the .netrc + * will be queried. */ + CURL_NETRC_LAST +}; + +enum { + CURL_SSLVERSION_DEFAULT, + CURL_SSLVERSION_TLSv1, /* TLS 1.x */ + CURL_SSLVERSION_SSLv2, + CURL_SSLVERSION_SSLv3, + CURL_SSLVERSION_TLSv1_0, + CURL_SSLVERSION_TLSv1_1, + CURL_SSLVERSION_TLSv1_2, + CURL_SSLVERSION_TLSv1_3, + + CURL_SSLVERSION_LAST /* never use, keep last */ +}; + +enum { + CURL_SSLVERSION_MAX_NONE = 0, + CURL_SSLVERSION_MAX_DEFAULT = (CURL_SSLVERSION_TLSv1 << 16), + CURL_SSLVERSION_MAX_TLSv1_0 = (CURL_SSLVERSION_TLSv1_0 << 16), + CURL_SSLVERSION_MAX_TLSv1_1 = (CURL_SSLVERSION_TLSv1_1 << 16), + CURL_SSLVERSION_MAX_TLSv1_2 = (CURL_SSLVERSION_TLSv1_2 << 16), + CURL_SSLVERSION_MAX_TLSv1_3 = (CURL_SSLVERSION_TLSv1_3 << 16), + + /* never use, keep last */ + CURL_SSLVERSION_MAX_LAST = (CURL_SSLVERSION_LAST << 16) +}; + +enum CURL_TLSAUTH { + CURL_TLSAUTH_NONE, + CURL_TLSAUTH_SRP, + CURL_TLSAUTH_LAST /* never use, keep last */ +}; + +/* symbols to use with CURLOPT_POSTREDIR. + CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303 + can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302 + | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */ + +#define CURL_REDIR_GET_ALL 0 +#define CURL_REDIR_POST_301 1 +#define CURL_REDIR_POST_302 2 +#define CURL_REDIR_POST_303 4 +#define CURL_REDIR_POST_ALL \ + (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303) + +typedef enum { + CURL_TIMECOND_NONE, + + CURL_TIMECOND_IFMODSINCE, + CURL_TIMECOND_IFUNMODSINCE, + CURL_TIMECOND_LASTMOD, + + CURL_TIMECOND_LAST +} curl_TimeCond; + +/* Special size_t value signaling a zero-terminated string. */ +#define CURL_ZERO_TERMINATED ((size_t) -1) + +/* curl_strequal() and curl_strnequal() are subject for removal in a future + release */ +CURL_EXTERN int curl_strequal(const char *s1, const char *s2); +CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n); + +/* Mime/form handling support. */ +typedef struct curl_mime_s curl_mime; /* Mime context. */ +typedef struct curl_mimepart_s curl_mimepart; /* Mime part context. */ + +/* + * NAME curl_mime_init() + * + * DESCRIPTION + * + * Create a mime context and return its handle. The easy parameter is the + * target handle. + */ +CURL_EXTERN curl_mime *curl_mime_init(CURL *easy); + +/* + * NAME curl_mime_free() + * + * DESCRIPTION + * + * release a mime handle and its substructures. + */ +CURL_EXTERN void curl_mime_free(curl_mime *mime); + +/* + * NAME curl_mime_addpart() + * + * DESCRIPTION + * + * Append a new empty part to the given mime context and return a handle to + * the created part. + */ +CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime); + +/* + * NAME curl_mime_name() + * + * DESCRIPTION + * + * Set mime/form part name. + */ +CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name); + +/* + * NAME curl_mime_filename() + * + * DESCRIPTION + * + * Set mime part remote file name. + */ +CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_type() + * + * DESCRIPTION + * + * Set mime part type. + */ +CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype); + +/* + * NAME curl_mime_encoder() + * + * DESCRIPTION + * + * Set mime data transfer encoder. + */ +CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part, + const char *encoding); + +/* + * NAME curl_mime_data() + * + * DESCRIPTION + * + * Set mime part data source from memory data, + */ +CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part, + const char *data, size_t datasize); + +/* + * NAME curl_mime_filedata() + * + * DESCRIPTION + * + * Set mime part data source from named file. + */ +CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part, + const char *filename); + +/* + * NAME curl_mime_data_cb() + * + * DESCRIPTION + * + * Set mime part data source from callback function. + */ +CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part, + curl_off_t datasize, + curl_read_callback readfunc, + curl_seek_callback seekfunc, + curl_free_callback freefunc, + void *arg); + +/* + * NAME curl_mime_subparts() + * + * DESCRIPTION + * + * Set mime part data source from subparts. + */ +CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part, + curl_mime *subparts); +/* + * NAME curl_mime_headers() + * + * DESCRIPTION + * + * Set mime part headers. + */ +CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part, + struct curl_slist *headers, + int take_ownership); + +typedef enum { + CURLFORM_NOTHING, /********* the first one is unused ************/ + CURLFORM_COPYNAME, + CURLFORM_PTRNAME, + CURLFORM_NAMELENGTH, + CURLFORM_COPYCONTENTS, + CURLFORM_PTRCONTENTS, + CURLFORM_CONTENTSLENGTH, + CURLFORM_FILECONTENT, + CURLFORM_ARRAY, + CURLFORM_OBSOLETE, + CURLFORM_FILE, + + CURLFORM_BUFFER, + CURLFORM_BUFFERPTR, + CURLFORM_BUFFERLENGTH, + + CURLFORM_CONTENTTYPE, + CURLFORM_CONTENTHEADER, + CURLFORM_FILENAME, + CURLFORM_END, + CURLFORM_OBSOLETE2, + + CURLFORM_STREAM, + CURLFORM_CONTENTLEN, /* added in 7.46.0, provide a curl_off_t length */ + + CURLFORM_LASTENTRY /* the last unused */ +} CURLformoption; + +/* structure to be used as parameter for CURLFORM_ARRAY */ +struct curl_forms { + CURLformoption option; + const char *value; +}; + +/* use this for multipart formpost building */ +/* Returns code for curl_formadd() + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ +typedef enum { + CURL_FORMADD_OK, /* first, no error */ + + CURL_FORMADD_MEMORY, + CURL_FORMADD_OPTION_TWICE, + CURL_FORMADD_NULL, + CURL_FORMADD_UNKNOWN_OPTION, + CURL_FORMADD_INCOMPLETE, + CURL_FORMADD_ILLEGAL_ARRAY, + CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */ + + CURL_FORMADD_LAST /* last */ +} CURLFORMcode; + +/* + * NAME curl_formadd() + * + * DESCRIPTION + * + * Pretty advanced function for building multi-part formposts. Each invoke + * adds one part that together construct a full post. Then use + * CURLOPT_HTTPPOST to send it off to libcurl. + */ +CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...); + +/* + * callback function for curl_formget() + * The void *arg pointer will be the one passed as second argument to + * curl_formget(). + * The character buffer passed to it must not be freed. + * Should return the buffer length passed to it as the argument "len" on + * success. + */ +typedef size_t (*curl_formget_callback)(void *arg, const char *buf, + size_t len); + +/* + * NAME curl_formget() + * + * DESCRIPTION + * + * Serialize a curl_httppost struct built with curl_formadd(). + * Accepts a void pointer as second argument which will be passed to + * the curl_formget_callback function. + * Returns 0 on success. + */ +CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append); +/* + * NAME curl_formfree() + * + * DESCRIPTION + * + * Free a multipart formpost previously built with curl_formadd(). + */ +CURL_EXTERN void curl_formfree(struct curl_httppost *form); + +/* + * NAME curl_getenv() + * + * DESCRIPTION + * + * Returns a malloc()'ed string that MUST be curl_free()ed after usage is + * complete. DEPRECATED - see lib/README.curlx + */ +CURL_EXTERN char *curl_getenv(const char *variable); + +/* + * NAME curl_version() + * + * DESCRIPTION + * + * Returns a static ascii string of the libcurl version. + */ +CURL_EXTERN char *curl_version(void); + +/* + * NAME curl_easy_escape() + * + * DESCRIPTION + * + * Escapes URL strings (converts all letters consider illegal in URLs to their + * %XX versions). This function returns a new allocated string or NULL if an + * error occurred. + */ +CURL_EXTERN char *curl_easy_escape(CURL *handle, + const char *string, + int length); + +/* the previous version: */ +CURL_EXTERN char *curl_escape(const char *string, + int length); + + +/* + * NAME curl_easy_unescape() + * + * DESCRIPTION + * + * Unescapes URL encoding in strings (converts all %XX codes to their 8bit + * versions). This function returns a new allocated string or NULL if an error + * occurred. + * Conversion Note: On non-ASCII platforms the ASCII %XX codes are + * converted into the host encoding. + */ +CURL_EXTERN char *curl_easy_unescape(CURL *handle, + const char *string, + int length, + int *outlength); + +/* the previous version */ +CURL_EXTERN char *curl_unescape(const char *string, + int length); + +/* + * NAME curl_free() + * + * DESCRIPTION + * + * Provided for de-allocation in the same translation unit that did the + * allocation. Added in libcurl 7.10 + */ +CURL_EXTERN void curl_free(void *p); + +/* + * NAME curl_global_init() + * + * DESCRIPTION + * + * curl_global_init() should be invoked exactly once for each application that + * uses libcurl and before any call of other libcurl functions. + * + * This function is not thread-safe! + */ +CURL_EXTERN CURLcode curl_global_init(long flags); + +/* + * NAME curl_global_init_mem() + * + * DESCRIPTION + * + * curl_global_init() or curl_global_init_mem() should be invoked exactly once + * for each application that uses libcurl. This function can be used to + * initialize libcurl and set user defined memory management callback + * functions. Users can implement memory management routines to check for + * memory leaks, check for mis-use of the curl library etc. User registered + * callback routines with be invoked by this library instead of the system + * memory management routines like malloc, free etc. + */ +CURL_EXTERN CURLcode curl_global_init_mem(long flags, + curl_malloc_callback m, + curl_free_callback f, + curl_realloc_callback r, + curl_strdup_callback s, + curl_calloc_callback c); + +/* + * NAME curl_global_cleanup() + * + * DESCRIPTION + * + * curl_global_cleanup() should be invoked exactly once for each application + * that uses libcurl + */ +CURL_EXTERN void curl_global_cleanup(void); + +/* linked-list structure for the CURLOPT_QUOTE option (and other) */ +struct curl_slist { + char *data; + struct curl_slist *next; +}; + +/* + * NAME curl_global_sslset() + * + * DESCRIPTION + * + * When built with multiple SSL backends, curl_global_sslset() allows to + * choose one. This function can only be called once, and it must be called + * *before* curl_global_init(). + * + * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The + * backend can also be specified via the name parameter (passing -1 as id). + * If both id and name are specified, the name will be ignored. If neither id + * nor name are specified, the function will fail with + * CURLSSLSET_UNKNOWN_BACKEND and set the "avail" pointer to the + * NULL-terminated list of available backends. + * + * Upon success, the function returns CURLSSLSET_OK. + * + * If the specified SSL backend is not available, the function returns + * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a NULL-terminated + * list of available SSL backends. + * + * The SSL backend can be set only once. If it has already been set, a + * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE. + */ + +typedef struct { + curl_sslbackend id; + const char *name; +} curl_ssl_backend; + +typedef enum { + CURLSSLSET_OK = 0, + CURLSSLSET_UNKNOWN_BACKEND, + CURLSSLSET_TOO_LATE, + CURLSSLSET_NO_BACKENDS /* libcurl was built without any SSL support */ +} CURLsslset; + +CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name, + const curl_ssl_backend ***avail); + +/* + * NAME curl_slist_append() + * + * DESCRIPTION + * + * Appends a string to a linked list. If no list exists, it will be created + * first. Returns the new list, after appending. + */ +CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *, + const char *); + +/* + * NAME curl_slist_free_all() + * + * DESCRIPTION + * + * free a previously built curl_slist. + */ +CURL_EXTERN void curl_slist_free_all(struct curl_slist *); + +/* + * NAME curl_getdate() + * + * DESCRIPTION + * + * Returns the time, in seconds since 1 Jan 1970 of the time string given in + * the first argument. The time argument in the second parameter is unused + * and should be set to NULL. + */ +CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused); + +/* info about the certificate chain, only for OpenSSL, GnuTLS, Schannel, NSS + and GSKit builds. Asked for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ +struct curl_certinfo { + int num_of_certs; /* number of certificates with information */ + struct curl_slist **certinfo; /* for each index in this array, there's a + linked list with textual information in the + format "name: value" */ +}; + +/* Information about the SSL library used and the respective internal SSL + handle, which can be used to obtain further information regarding the + connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */ +struct curl_tlssessioninfo { + curl_sslbackend backend; + void *internals; +}; + +#define CURLINFO_STRING 0x100000 +#define CURLINFO_LONG 0x200000 +#define CURLINFO_DOUBLE 0x300000 +#define CURLINFO_SLIST 0x400000 +#define CURLINFO_PTR 0x400000 /* same as SLIST */ +#define CURLINFO_SOCKET 0x500000 +#define CURLINFO_OFF_T 0x600000 +#define CURLINFO_MASK 0x0fffff +#define CURLINFO_TYPEMASK 0xf00000 + +typedef enum { + CURLINFO_NONE, /* first, never use this */ + CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, + CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2, + CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, + CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, + CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, + CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, + CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7, + CURLINFO_SIZE_UPLOAD_T = CURLINFO_OFF_T + 7, + CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8, + CURLINFO_SIZE_DOWNLOAD_T = CURLINFO_OFF_T + 8, + CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9, + CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T + 9, + CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10, + CURLINFO_SPEED_UPLOAD_T = CURLINFO_OFF_T + 10, + CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, + CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, + CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, + CURLINFO_FILETIME = CURLINFO_LONG + 14, + CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14, + CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15, + CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15, + CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16, + CURLINFO_CONTENT_LENGTH_UPLOAD_T = CURLINFO_OFF_T + 16, + CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, + CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, + CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, + CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, + CURLINFO_PRIVATE = CURLINFO_STRING + 21, + CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22, + CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23, + CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24, + CURLINFO_OS_ERRNO = CURLINFO_LONG + 25, + CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26, + CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27, + CURLINFO_COOKIELIST = CURLINFO_SLIST + 28, + CURLINFO_LASTSOCKET = CURLINFO_LONG + 29, + CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30, + CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, + CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, + CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, + CURLINFO_CERTINFO = CURLINFO_PTR + 34, + CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, + CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36, + CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, + CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38, + CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39, + CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, + CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, + CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, + CURLINFO_TLS_SESSION = CURLINFO_PTR + 43, + CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44, + CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45, + CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46, + CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47, + CURLINFO_PROTOCOL = CURLINFO_LONG + 48, + CURLINFO_SCHEME = CURLINFO_STRING + 49, + /* Fill in new entries below here! */ + + /* Preferably these would be defined conditionally based on the + sizeof curl_off_t being 64-bits */ + CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50, + CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51, + CURLINFO_CONNECT_TIME_T = CURLINFO_OFF_T + 52, + CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53, + CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54, + CURLINFO_REDIRECT_TIME_T = CURLINFO_OFF_T + 55, + CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56, + CURLINFO_RETRY_AFTER = CURLINFO_OFF_T + 57, + + CURLINFO_LASTONE = 57 +} CURLINFO; + +/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as + CURLINFO_HTTP_CODE */ +#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE + +typedef enum { + CURLCLOSEPOLICY_NONE, /* first, never use this */ + + CURLCLOSEPOLICY_OLDEST, + CURLCLOSEPOLICY_LEAST_RECENTLY_USED, + CURLCLOSEPOLICY_LEAST_TRAFFIC, + CURLCLOSEPOLICY_SLOWEST, + CURLCLOSEPOLICY_CALLBACK, + + CURLCLOSEPOLICY_LAST /* last, never use this */ +} curl_closepolicy; + +#define CURL_GLOBAL_SSL (1<<0) /* no purpose since since 7.57.0 */ +#define CURL_GLOBAL_WIN32 (1<<1) +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) +#define CURL_GLOBAL_NOTHING 0 +#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL +#define CURL_GLOBAL_ACK_EINTR (1<<2) + + +/***************************************************************************** + * Setup defines, protos etc for the sharing stuff. + */ + +/* Different data locks for a single share */ +typedef enum { + CURL_LOCK_DATA_NONE = 0, + /* CURL_LOCK_DATA_SHARE is used internally to say that + * the locking is just made to change the internal state of the share + * itself. + */ + CURL_LOCK_DATA_SHARE, + CURL_LOCK_DATA_COOKIE, + CURL_LOCK_DATA_DNS, + CURL_LOCK_DATA_SSL_SESSION, + CURL_LOCK_DATA_CONNECT, + CURL_LOCK_DATA_PSL, + CURL_LOCK_DATA_LAST +} curl_lock_data; + +/* Different lock access types */ +typedef enum { + CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */ + CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */ + CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */ + CURL_LOCK_ACCESS_LAST /* never use */ +} curl_lock_access; + +typedef void (*curl_lock_function)(CURL *handle, + curl_lock_data data, + curl_lock_access locktype, + void *userptr); +typedef void (*curl_unlock_function)(CURL *handle, + curl_lock_data data, + void *userptr); + + +typedef enum { + CURLSHE_OK, /* all is fine */ + CURLSHE_BAD_OPTION, /* 1 */ + CURLSHE_IN_USE, /* 2 */ + CURLSHE_INVALID, /* 3 */ + CURLSHE_NOMEM, /* 4 out of memory */ + CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */ + CURLSHE_LAST /* never use */ +} CURLSHcode; + +typedef enum { + CURLSHOPT_NONE, /* don't use */ + CURLSHOPT_SHARE, /* specify a data type to share */ + CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */ + CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */ + CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */ + CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock + callback functions */ + CURLSHOPT_LAST /* never use */ +} CURLSHoption; + +CURL_EXTERN CURLSH *curl_share_init(void); +CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...); +CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *); + +/**************************************************************************** + * Structures for querying information about the curl library at runtime. + */ + +typedef enum { + CURLVERSION_FIRST, + CURLVERSION_SECOND, + CURLVERSION_THIRD, + CURLVERSION_FOURTH, + CURLVERSION_FIFTH, + CURLVERSION_SIXTH, + CURLVERSION_LAST /* never actually use this */ +} CURLversion; + +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by + basically all programs ever that want to get version information. It is + meant to be a built-in version number for what kind of struct the caller + expects. If the struct ever changes, we redefine the NOW to another enum + from above. */ +#define CURLVERSION_NOW CURLVERSION_SIXTH + +typedef struct { + CURLversion age; /* age of the returned struct */ + const char *version; /* LIBCURL_VERSION */ + unsigned int version_num; /* LIBCURL_VERSION_NUM */ + const char *host; /* OS/host/cpu/machine when configured */ + int features; /* bitmask, see defines below */ + const char *ssl_version; /* human readable string */ + long ssl_version_num; /* not used anymore, always 0 */ + const char *libz_version; /* human readable string */ + /* protocols is terminated by an entry with a NULL protoname */ + const char * const *protocols; + + /* The fields below this were added in CURLVERSION_SECOND */ + const char *ares; + int ares_num; + + /* This field was added in CURLVERSION_THIRD */ + const char *libidn; + + /* These field were added in CURLVERSION_FOURTH */ + + /* Same as '_libiconv_version' if built with HAVE_ICONV */ + int iconv_ver_num; + + const char *libssh_version; /* human readable string */ + + /* These fields were added in CURLVERSION_FIFTH */ + unsigned int brotli_ver_num; /* Numeric Brotli version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + const char *brotli_version; /* human readable string. */ + + /* These fields were added in CURLVERSION_SIXTH */ + unsigned int nghttp2_ver_num; /* Numeric nghttp2 version + (MAJOR << 16) | (MINOR << 8) | PATCH */ + const char *nghttp2_version; /* human readable string. */ + const char *quic_version; /* human readable quic (+ HTTP/3) library + + version or NULL */ +} curl_version_info_data; + +#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */ +#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported + (deprecated) */ +#define CURL_VERSION_SSL (1<<2) /* SSL options are present */ +#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */ +#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */ +#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported + (deprecated) */ +#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */ +#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */ +#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */ +#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */ +#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are + supported */ +#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */ +#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */ +#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */ +#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ +#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper + is supported */ +#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */ +#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */ +#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */ +#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */ +#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used + for cookie domain verification */ +#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */ +#define CURL_VERSION_MULTI_SSL (1<<22) /* Multiple SSL backends available */ +#define CURL_VERSION_BROTLI (1<<23) /* Brotli features are present. */ +#define CURL_VERSION_ALTSVC (1<<24) /* Alt-Svc handling built-in */ +#define CURL_VERSION_HTTP3 (1<<25) /* HTTP3 support built-in */ + +#define CURL_VERSION_ESNI (1<<26) /* ESNI support */ + + /* + * NAME curl_version_info() + * + * DESCRIPTION + * + * This function returns a pointer to a static copy of the version info + * struct. See above. + */ +CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion); + +/* + * NAME curl_easy_strerror() + * + * DESCRIPTION + * + * The curl_easy_strerror function may be used to turn a CURLcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_easy_strerror(CURLcode); + +/* + * NAME curl_share_strerror() + * + * DESCRIPTION + * + * The curl_share_strerror function may be used to turn a CURLSHcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_share_strerror(CURLSHcode); + +/* + * NAME curl_easy_pause() + * + * DESCRIPTION + * + * The curl_easy_pause function pauses or unpauses transfers. Select the new + * state by setting the bitmask, use the convenience defines below. + * + */ +CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); + +#define CURLPAUSE_RECV (1<<0) +#define CURLPAUSE_RECV_CONT (0) + +#define CURLPAUSE_SEND (1<<2) +#define CURLPAUSE_SEND_CONT (0) + +#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND) +#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) + +#ifdef __cplusplus +} +#endif + +/* unfortunately, the easy.h and multi.h include files need options and info + stuff before they can be included! */ +#include "easy.h" /* nothing in curl is fun without the easy stuff */ +#include "multi.h" +#include "urlapi.h" + +/* the typechecker doesn't work in C++ (yet) */ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \ + ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \ + !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK) +#include "typecheck-gcc.h" +#else +#if defined(__STDC__) && (__STDC__ >= 1) +/* This preprocessor magic that replaces a call with the exact same call is + only done to make sure application authors pass exactly three arguments + to these functions. */ +#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) +#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg) +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) +#endif /* __STDC__ >= 1 */ +#endif /* gcc >= 4.3 && !__cplusplus */ + +#endif /* CURLINC_CURL_H */ diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/curlver.h b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/curlver.h new file mode 100644 index 0000000000..5fc49d4188 --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/curlver.h @@ -0,0 +1,77 @@ +#ifndef CURLINC_CURLVER_H +#define CURLINC_CURLVER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This header file contains nothing but libcurl version info, generated by + a script at release-time. This was made its own header file in 7.11.2 */ + +/* This is the global package copyright */ +#define LIBCURL_COPYRIGHT "1996 - 2020 Daniel Stenberg, ." + +/* This is the version number of the libcurl package from which this header + file origins: */ +#define LIBCURL_VERSION "7.69.1" + +/* The numeric version number is also available "in parts" by using these + defines: */ +#define LIBCURL_VERSION_MAJOR 7 +#define LIBCURL_VERSION_MINOR 69 +#define LIBCURL_VERSION_PATCH 1 + +/* This is the numeric version of the libcurl version number, meant for easier + parsing and comparions by programs. The LIBCURL_VERSION_NUM define will + always follow this syntax: + + 0xXXYYZZ + + Where XX, YY and ZZ are the main version, release and patch numbers in + hexadecimal (using 8 bits each). All three numbers are always represented + using two digits. 1.2 would appear as "0x010200" while version 9.11.7 + appears as "0x090b07". + + This 6-digit (24 bits) hexadecimal number does not show pre-release number, + and it is always a greater number in a more recent release. It makes + comparisons with greater than and less than work. + + Note: This define is the full hex number and _does not_ use the + CURL_VERSION_BITS() macro since curl's own configure script greps for it + and needs it to contain the full number. +*/ +#define LIBCURL_VERSION_NUM 0x074501 + +/* + * This is the date and time when the full source package was created. The + * timestamp is not stored in git, as the timestamp is properly set in the + * tarballs by the maketgz script. + * + * The format of the date follows this template: + * + * "2007-11-23" + */ +#define LIBCURL_TIMESTAMP "2020-03-11" + +#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z)) +#define CURL_AT_LEAST_VERSION(x,y,z) \ + (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z)) + +#endif /* CURLINC_CURLVER_H */ diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/easy.h b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/easy.h new file mode 100644 index 0000000000..592f5d3c1c --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/easy.h @@ -0,0 +1,112 @@ +#ifndef CURLINC_EASY_H +#define CURLINC_EASY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +CURL_EXTERN CURL *curl_easy_init(void); +CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); +CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); +CURL_EXTERN void curl_easy_cleanup(CURL *curl); + +/* + * NAME curl_easy_getinfo() + * + * DESCRIPTION + * + * Request internal information from the curl session with this function. The + * third argument MUST be a pointer to a long, a pointer to a char * or a + * pointer to a double (as the documentation describes elsewhere). The data + * pointed to will be filled in accordingly and can be relied upon only if the + * function returns CURLE_OK. This function is intended to get used *AFTER* a + * performed transfer, all results from this function are undefined until the + * transfer is completed. + */ +CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); + + +/* + * NAME curl_easy_duphandle() + * + * DESCRIPTION + * + * Creates a new curl session handle with the same options set for the handle + * passed in. Duplicating a handle could only be a matter of cloning data and + * options, internal state info and things like persistent connections cannot + * be transferred. It is useful in multithreaded applications when you can run + * curl_easy_duphandle() for each new thread to avoid a series of identical + * curl_easy_setopt() invokes in every thread. + */ +CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl); + +/* + * NAME curl_easy_reset() + * + * DESCRIPTION + * + * Re-initializes a CURL handle to the default values. This puts back the + * handle to the same state as it was in when it was just created. + * + * It does keep: live connections, the Session ID cache, the DNS cache and the + * cookies. + */ +CURL_EXTERN void curl_easy_reset(CURL *curl); + +/* + * NAME curl_easy_recv() + * + * DESCRIPTION + * + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, + size_t *n); + +/* + * NAME curl_easy_send() + * + * DESCRIPTION + * + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, + size_t buflen, size_t *n); + + +/* + * NAME curl_easy_upkeep() + * + * DESCRIPTION + * + * Performs connection upkeep for the given session handle. + */ +CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/mprintf.h b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/mprintf.h new file mode 100644 index 0000000000..f615ed7d63 --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/mprintf.h @@ -0,0 +1,50 @@ +#ifndef CURLINC_MPRINTF_H +#define CURLINC_MPRINTF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include +#include /* needed for FILE */ +#include "curl.h" /* for CURL_EXTERN */ + +#ifdef __cplusplus +extern "C" { +#endif + +CURL_EXTERN int curl_mprintf(const char *format, ...); +CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...); +CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...); +CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, + const char *format, ...); +CURL_EXTERN int curl_mvprintf(const char *format, va_list args); +CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args); +CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args); +CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, + const char *format, va_list args); +CURL_EXTERN char *curl_maprintf(const char *format, ...); +CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args); + +#ifdef __cplusplus +} +#endif + +#endif /* CURLINC_MPRINTF_H */ diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/multi.h b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/multi.h new file mode 100644 index 0000000000..bda9bb7b81 --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/multi.h @@ -0,0 +1,456 @@ +#ifndef CURLINC_MULTI_H +#define CURLINC_MULTI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + This is an "external" header file. Don't give away any internals here! + + GOALS + + o Enable a "pull" interface. The application that uses libcurl decides where + and when to ask libcurl to get/send data. + + o Enable multiple simultaneous transfers in the same thread without making it + complicated for the application. + + o Enable the application to select() on its own file descriptors and curl's + file descriptors simultaneous easily. + +*/ + +/* + * This header file should not really need to include "curl.h" since curl.h + * itself includes this file and we expect user applications to do #include + * without the need for especially including multi.h. + * + * For some reason we added this include here at one point, and rather than to + * break existing (wrongly written) libcurl applications, we leave it as-is + * but with this warning attached. + */ +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) +typedef struct Curl_multi CURLM; +#else +typedef void CURLM; +#endif + +typedef enum { + CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or + curl_multi_socket*() soon */ + CURLM_OK, + CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */ + CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ + CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */ + CURLM_INTERNAL_ERROR, /* this is a libcurl bug */ + CURLM_BAD_SOCKET, /* the passed in socket argument did not match */ + CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */ + CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was + attempted to get added - again */ + CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a + callback */ + CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */ + CURLM_BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */ + CURLM_LAST +} CURLMcode; + +/* just to make code nicer when using curl_multi_socket() you can now check + for CURLM_CALL_MULTI_SOCKET too in the same style it works for + curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */ +#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM + +/* bitmask bits for CURLMOPT_PIPELINING */ +#define CURLPIPE_NOTHING 0L +#define CURLPIPE_HTTP1 1L +#define CURLPIPE_MULTIPLEX 2L + +typedef enum { + CURLMSG_NONE, /* first, not used */ + CURLMSG_DONE, /* This easy handle has completed. 'result' contains + the CURLcode of the transfer */ + CURLMSG_LAST /* last, not used */ +} CURLMSG; + +struct CURLMsg { + CURLMSG msg; /* what this message means */ + CURL *easy_handle; /* the handle it concerns */ + union { + void *whatever; /* message-specific data */ + CURLcode result; /* return code for transfer */ + } data; +}; +typedef struct CURLMsg CURLMsg; + +/* Based on poll(2) structure and values. + * We don't use pollfd and POLL* constants explicitly + * to cover platforms without poll(). */ +#define CURL_WAIT_POLLIN 0x0001 +#define CURL_WAIT_POLLPRI 0x0002 +#define CURL_WAIT_POLLOUT 0x0004 + +struct curl_waitfd { + curl_socket_t fd; + short events; + short revents; /* not supported yet */ +}; + +/* + * Name: curl_multi_init() + * + * Desc: inititalize multi-style curl usage + * + * Returns: a new CURLM handle to use in all 'curl_multi' functions. + */ +CURL_EXTERN CURLM *curl_multi_init(void); + +/* + * Name: curl_multi_add_handle() + * + * Desc: add a standard curl handle to the multi stack + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_remove_handle() + * + * Desc: removes a curl handle from the multi stack again + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle, + CURL *curl_handle); + + /* + * Name: curl_multi_fdset() + * + * Desc: Ask curl for its fd_set sets. The app can use these to select() or + * poll() on. We want curl_multi_perform() called as soon as one of + * them are ready. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle, + fd_set *read_fd_set, + fd_set *write_fd_set, + fd_set *exc_fd_set, + int *max_fd); + +/* + * Name: curl_multi_wait() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + +/* + * Name: curl_multi_poll() + * + * Desc: Poll on all fds within a CURLM set as well as any + * additional fds passed to the function. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_poll(CURLM *multi_handle, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret); + +/* + * Name: curl_multi_wakeup() + * + * Desc: wakes up a sleeping curl_multi_poll call. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_wakeup(CURLM *multi_handle); + + /* + * Name: curl_multi_perform() + * + * Desc: When the app thinks there's data available for curl it calls this + * function to read/write whatever there is right now. This returns + * as soon as the reads and writes are done. This function does not + * require that there actually is data available for reading or that + * data can be written, it can be called just in case. It returns + * the number of handles that still transfer data in the second + * argument's integer-pointer. + * + * Returns: CURLMcode type, general multi error code. *NOTE* that this only + * returns errors etc regarding the whole multi stack. There might + * still have occurred problems on individual transfers even when + * this returns OK. + */ +CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle, + int *running_handles); + + /* + * Name: curl_multi_cleanup() + * + * Desc: Cleans up and removes a whole multi stack. It does not free or + * touch any individual easy handles in any way. We need to define + * in what state those handles will be if this function is called + * in the middle of a transfer. + * + * Returns: CURLMcode type, general multi error code. + */ +CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle); + +/* + * Name: curl_multi_info_read() + * + * Desc: Ask the multi handle if there's any messages/informationals from + * the individual transfers. Messages include informationals such as + * error code from the transfer or just the fact that a transfer is + * completed. More details on these should be written down as well. + * + * Repeated calls to this function will return a new struct each + * time, until a special "end of msgs" struct is returned as a signal + * that there is no more to get at this point. + * + * The data the returned pointer points to will not survive calling + * curl_multi_cleanup(). + * + * The 'CURLMsg' struct is meant to be very simple and only contain + * very basic information. If more involved information is wanted, + * we will provide the particular "transfer handle" in that struct + * and that should/could/would be used in subsequent + * curl_easy_getinfo() calls (or similar). The point being that we + * must never expose complex structs to applications, as then we'll + * undoubtably get backwards compatibility problems in the future. + * + * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out + * of structs. It also writes the number of messages left in the + * queue (after this read) in the integer the second argument points + * to. + */ +CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle, + int *msgs_in_queue); + +/* + * Name: curl_multi_strerror() + * + * Desc: The curl_multi_strerror function may be used to turn a CURLMcode + * value into the equivalent human readable error string. This is + * useful for printing meaningful error messages. + * + * Returns: A pointer to a zero-terminated error message. + */ +CURL_EXTERN const char *curl_multi_strerror(CURLMcode); + +/* + * Name: curl_multi_socket() and + * curl_multi_socket_all() + * + * Desc: An alternative version of curl_multi_perform() that allows the + * application to pass in one of the file descriptors that have been + * detected to have "action" on them and let libcurl perform. + * See man page for details. + */ +#define CURL_POLL_NONE 0 +#define CURL_POLL_IN 1 +#define CURL_POLL_OUT 2 +#define CURL_POLL_INOUT 3 +#define CURL_POLL_REMOVE 4 + +#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD + +#define CURL_CSELECT_IN 0x01 +#define CURL_CSELECT_OUT 0x02 +#define CURL_CSELECT_ERR 0x04 + +typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */ + curl_socket_t s, /* socket */ + int what, /* see above */ + void *userp, /* private callback + pointer */ + void *socketp); /* private socket + pointer */ +/* + * Name: curl_multi_timer_callback + * + * Desc: Called by libcurl whenever the library detects a change in the + * maximum number of milliseconds the app is allowed to wait before + * curl_multi_socket() or curl_multi_perform() must be called + * (to allow libcurl's timed events to take place). + * + * Returns: The callback should return zero. + */ +typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */ + long timeout_ms, /* see above */ + void *userp); /* private callback + pointer */ + +CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle, + curl_socket_t s, + int ev_bitmask, + int *running_handles); + +CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle, + int *running_handles); + +#ifndef CURL_ALLOW_OLD_MULTI_SOCKET +/* This macro below was added in 7.16.3 to push users who recompile to use + the new curl_multi_socket_action() instead of the old curl_multi_socket() +*/ +#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z) +#endif + +/* + * Name: curl_multi_timeout() + * + * Desc: Returns the maximum number of milliseconds the app is allowed to + * wait before curl_multi_socket() or curl_multi_perform() must be + * called (to allow libcurl's timed events to take place). + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle, + long *milliseconds); + +typedef enum { + /* This is the socket callback function pointer */ + CURLOPT(CURLMOPT_SOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 1), + + /* This is the argument passed to the socket callback */ + CURLOPT(CURLMOPT_SOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 2), + + /* set to 1 to enable pipelining for this multi handle */ + CURLOPT(CURLMOPT_PIPELINING, CURLOPTTYPE_LONG, 3), + + /* This is the timer callback function pointer */ + CURLOPT(CURLMOPT_TIMERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 4), + + /* This is the argument passed to the timer callback */ + CURLOPT(CURLMOPT_TIMERDATA, CURLOPTTYPE_OBJECTPOINT, 5), + + /* maximum number of entries in the connection cache */ + CURLOPT(CURLMOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 6), + + /* maximum number of (pipelining) connections to one host */ + CURLOPT(CURLMOPT_MAX_HOST_CONNECTIONS, CURLOPTTYPE_LONG, 7), + + /* maximum number of requests in a pipeline */ + CURLOPT(CURLMOPT_MAX_PIPELINE_LENGTH, CURLOPTTYPE_LONG, 8), + + /* a connection with a content-length longer than this + will not be considered for pipelining */ + CURLOPT(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 9), + + /* a connection with a chunk length longer than this + will not be considered for pipelining */ + CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10), + + /* a list of site names(+port) that are blacklisted from + pipelining */ + CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11), + + /* a list of server types that are blacklisted from + pipelining */ + CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12), + + /* maximum number of open connections in total */ + CURLOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, CURLOPTTYPE_LONG, 13), + + /* This is the server push callback function pointer */ + CURLOPT(CURLMOPT_PUSHFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 14), + + /* This is the argument passed to the server push callback */ + CURLOPT(CURLMOPT_PUSHDATA, CURLOPTTYPE_OBJECTPOINT, 15), + + /* maximum number of concurrent streams to support on a connection */ + CURLOPT(CURLMOPT_MAX_CONCURRENT_STREAMS, CURLOPTTYPE_LONG, 16), + + CURLMOPT_LASTENTRY /* the last unused */ +} CURLMoption; + + +/* + * Name: curl_multi_setopt() + * + * Desc: Sets options for the multi handle. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle, + CURLMoption option, ...); + + +/* + * Name: curl_multi_assign() + * + * Desc: This function sets an association in the multi handle between the + * given socket and a private pointer of the application. This is + * (only) useful for curl_multi_socket uses. + * + * Returns: CURLM error code. + */ +CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, + curl_socket_t sockfd, void *sockp); + + +/* + * Name: curl_push_callback + * + * Desc: This callback gets called when a new stream is being pushed by the + * server. It approves or denies the new stream. + * + * Returns: CURL_PUSH_OK or CURL_PUSH_DENY. + */ +#define CURL_PUSH_OK 0 +#define CURL_PUSH_DENY 1 + +struct curl_pushheaders; /* forward declaration only */ + +CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h, + size_t num); +CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h, + const char *name); + +typedef int (*curl_push_callback)(CURL *parent, + CURL *easy, + size_t num_headers, + struct curl_pushheaders *headers, + void *userp); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/stdcheaders.h b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/stdcheaders.h new file mode 100644 index 0000000000..a6bdc1a25c --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/stdcheaders.h @@ -0,0 +1,33 @@ +#ifndef CURLINC_STDCHEADERS_H +#define CURLINC_STDCHEADERS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +size_t fread(void *, size_t, size_t, FILE *); +size_t fwrite(const void *, size_t, size_t, FILE *); + +int strcasecmp(const char *, const char *); +int strncasecmp(const char *, const char *, size_t); + +#endif /* CURLINC_STDCHEADERS_H */ diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/system.h b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/system.h new file mode 100644 index 0000000000..867af61418 --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/system.h @@ -0,0 +1,504 @@ +#ifndef CURLINC_SYSTEM_H +#define CURLINC_SYSTEM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Try to keep one section per platform, compiler and architecture, otherwise, + * if an existing section is reused for a different one and later on the + * original is adjusted, probably the piggybacking one can be adversely + * changed. + * + * In order to differentiate between platforms/compilers/architectures use + * only compiler built in predefined preprocessor symbols. + * + * curl_off_t + * ---------- + * + * For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit + * wide signed integral data type. The width of this data type must remain + * constant and independent of any possible large file support settings. + * + * As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit + * wide signed integral data type if there is no 64-bit type. + * + * As a general rule, curl_off_t shall not be mapped to off_t. This rule shall + * only be violated if off_t is the only 64-bit data type available and the + * size of off_t is independent of large file support settings. Keep your + * build on the safe side avoiding an off_t gating. If you have a 64-bit + * off_t then take for sure that another 64-bit data type exists, dig deeper + * and you will find it. + * + */ + +#if defined(__DJGPP__) || defined(__GO32__) +# if defined(__DJGPP__) && (__DJGPP__ > 1) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__SALFORDC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__BORLANDC__) +# if (__BORLANDC__ < 0x520) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__TURBOC__) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__WATCOMC__) +# if defined(__386__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__POCC__) +# if (__POCC__ < 280) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# elif defined(_MSC_VER) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__LCC__) +# if defined(__e2k__) /* MCST eLbrus C Compiler */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# else /* Local (or Little) C Compiler */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +# endif + +#elif defined(__SYMBIAN32__) +# if defined(__EABI__) /* Treat all ARM compilers equally */ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__CW32__) +# pragma longlong on +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__VC32__) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__MWERKS__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(_WIN32_WCE) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__MINGW32__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_WS2TCPIP_H 1 + +#elif defined(__VMS) +# if defined(__VAX) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int + +#elif defined(__OS400__) +# if defined(__ILEC400__) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__MVS__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# elif defined(_LP64) +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(__370__) +# if defined(__IBMC__) || defined(__IBMCPP__) +# if defined(_ILP32) +# elif defined(_LP64) +# endif +# if defined(_LONG_LONG) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 +# endif + +#elif defined(TPF) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +#elif defined(__TINYC__) /* also known as tcc */ +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */ +# if !defined(__LP64) && (defined(__ILP32) || \ + defined(__i386) || \ + defined(__sparcv8) || \ + defined(__sparcv8plus)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64) || \ + defined(__amd64) || defined(__sparcv9) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#elif defined(__xlc__) /* IBM xlc compiler */ +# if !defined(_LP64) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +/* ===================================== */ +/* KEEP MSVC THE PENULTIMATE ENTRY */ +/* ===================================== */ + +#elif defined(_MSC_VER) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# else +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T int + +/* ===================================== */ +/* KEEP GENERIC GCC THE LAST ENTRY */ +/* ===================================== */ + +#elif defined(__GNUC__) && !defined(_SCO_DS) +# if !defined(__LP64__) && \ + (defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \ + defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \ + defined(__sparc__) || defined(__mips__) || defined(__sh__) || \ + defined(__XTENSA__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L)) +# define CURL_TYPEOF_CURL_OFF_T long long +# define CURL_FORMAT_CURL_OFF_T "lld" +# define CURL_FORMAT_CURL_OFF_TU "llu" +# define CURL_SUFFIX_CURL_OFF_T LL +# define CURL_SUFFIX_CURL_OFF_TU ULL +# elif defined(__LP64__) || \ + defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \ + defined(__e2k__) || \ + (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \ + (defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L) +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# endif +# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +# define CURL_PULL_SYS_TYPES_H 1 +# define CURL_PULL_SYS_SOCKET_H 1 + +#else +/* generic "safe guess" on old 32 bit style */ +# define CURL_TYPEOF_CURL_OFF_T long +# define CURL_FORMAT_CURL_OFF_T "ld" +# define CURL_FORMAT_CURL_OFF_TU "lu" +# define CURL_SUFFIX_CURL_OFF_T L +# define CURL_SUFFIX_CURL_OFF_TU UL +# define CURL_TYPEOF_CURL_SOCKLEN_T int +#endif + +#ifdef _AIX +/* AIX needs */ +#define CURL_PULL_SYS_POLL_H +#endif + + +/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file */ +/* ws2tcpip.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_WS2TCPIP_H +# include +# include +# include +#endif + +/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */ +/* sys/types.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_TYPES_H +# include +#endif + +/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */ +/* sys/socket.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_SOCKET_H +# include +#endif + +/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */ +/* sys/poll.h is required here to properly make type definitions below. */ +#ifdef CURL_PULL_SYS_POLL_H +# include +#endif + +/* Data type definition of curl_socklen_t. */ +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T + typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; +#endif + +/* Data type definition of curl_off_t. */ + +#ifdef CURL_TYPEOF_CURL_OFF_T + typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; +#endif + +/* + * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow + * these to be visible and exported by the external libcurl interface API, + * while also making them visible to the library internals, simply including + * curl_setup.h, without actually needing to include curl.h internally. + * If some day this section would grow big enough, all this should be moved + * to its own header file. + */ + +/* + * Figure out if we can use the ## preprocessor operator, which is supported + * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__ + * or __cplusplus so we need to carefully check for them too. + */ + +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \ + defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \ + defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \ + defined(__ILEC400__) + /* This compiler is believed to have an ISO compatible preprocessor */ +#define CURL_ISOCPP +#else + /* This compiler is believed NOT to have an ISO compatible preprocessor */ +#undef CURL_ISOCPP +#endif + +/* + * Macros for minimum-width signed and unsigned curl_off_t integer constants. + */ + +#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551) +# define CURLINC_OFF_T_C_HLPR2(x) x +# define CURLINC_OFF_T_C_HLPR1(x) CURLINC_OFF_T_C_HLPR2(x) +# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \ + CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \ + CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU) +#else +# ifdef CURL_ISOCPP +# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix +# else +# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix +# endif +# define CURLINC_OFF_T_C_HLPR1(Val,Suffix) CURLINC_OFF_T_C_HLPR2(Val,Suffix) +# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T) +# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU) +#endif + +#endif /* CURLINC_SYSTEM_H */ diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/typecheck-gcc.h b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/typecheck-gcc.h new file mode 100644 index 0000000000..03c84fc85b --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/typecheck-gcc.h @@ -0,0 +1,699 @@ +#ifndef CURLINC_TYPECHECK_GCC_H +#define CURLINC_TYPECHECK_GCC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* wraps curl_easy_setopt() with typechecking */ + +/* To add a new kind of warning, add an + * if(curlcheck_sometype_option(_curl_opt)) + * if(!curlcheck_sometype(value)) + * _curl_easy_setopt_err_sometype(); + * block and define curlcheck_sometype_option, curlcheck_sometype and + * _curl_easy_setopt_err_sometype below + * + * NOTE: We use two nested 'if' statements here instead of the && operator, in + * order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x + * when compiling with -Wlogical-op. + * + * To add an option that uses the same type as an existing option, you'll just + * need to extend the appropriate _curl_*_option macro + */ +#define curl_easy_setopt(handle, option, value) \ + __extension__({ \ + __typeof__(option) _curl_opt = option; \ + if(__builtin_constant_p(_curl_opt)) { \ + if(curlcheck_long_option(_curl_opt)) \ + if(!curlcheck_long(value)) \ + _curl_easy_setopt_err_long(); \ + if(curlcheck_off_t_option(_curl_opt)) \ + if(!curlcheck_off_t(value)) \ + _curl_easy_setopt_err_curl_off_t(); \ + if(curlcheck_string_option(_curl_opt)) \ + if(!curlcheck_string(value)) \ + _curl_easy_setopt_err_string(); \ + if(curlcheck_write_cb_option(_curl_opt)) \ + if(!curlcheck_write_cb(value)) \ + _curl_easy_setopt_err_write_callback(); \ + if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \ + if(!curlcheck_resolver_start_callback(value)) \ + _curl_easy_setopt_err_resolver_start_callback(); \ + if((_curl_opt) == CURLOPT_READFUNCTION) \ + if(!curlcheck_read_cb(value)) \ + _curl_easy_setopt_err_read_cb(); \ + if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \ + if(!curlcheck_ioctl_cb(value)) \ + _curl_easy_setopt_err_ioctl_cb(); \ + if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \ + if(!curlcheck_sockopt_cb(value)) \ + _curl_easy_setopt_err_sockopt_cb(); \ + if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \ + if(!curlcheck_opensocket_cb(value)) \ + _curl_easy_setopt_err_opensocket_cb(); \ + if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \ + if(!curlcheck_progress_cb(value)) \ + _curl_easy_setopt_err_progress_cb(); \ + if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \ + if(!curlcheck_debug_cb(value)) \ + _curl_easy_setopt_err_debug_cb(); \ + if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \ + if(!curlcheck_ssl_ctx_cb(value)) \ + _curl_easy_setopt_err_ssl_ctx_cb(); \ + if(curlcheck_conv_cb_option(_curl_opt)) \ + if(!curlcheck_conv_cb(value)) \ + _curl_easy_setopt_err_conv_cb(); \ + if((_curl_opt) == CURLOPT_SEEKFUNCTION) \ + if(!curlcheck_seek_cb(value)) \ + _curl_easy_setopt_err_seek_cb(); \ + if(curlcheck_cb_data_option(_curl_opt)) \ + if(!curlcheck_cb_data(value)) \ + _curl_easy_setopt_err_cb_data(); \ + if((_curl_opt) == CURLOPT_ERRORBUFFER) \ + if(!curlcheck_error_buffer(value)) \ + _curl_easy_setopt_err_error_buffer(); \ + if((_curl_opt) == CURLOPT_STDERR) \ + if(!curlcheck_FILE(value)) \ + _curl_easy_setopt_err_FILE(); \ + if(curlcheck_postfields_option(_curl_opt)) \ + if(!curlcheck_postfields(value)) \ + _curl_easy_setopt_err_postfields(); \ + if((_curl_opt) == CURLOPT_HTTPPOST) \ + if(!curlcheck_arr((value), struct curl_httppost)) \ + _curl_easy_setopt_err_curl_httpost(); \ + if((_curl_opt) == CURLOPT_MIMEPOST) \ + if(!curlcheck_ptr((value), curl_mime)) \ + _curl_easy_setopt_err_curl_mimepost(); \ + if(curlcheck_slist_option(_curl_opt)) \ + if(!curlcheck_arr((value), struct curl_slist)) \ + _curl_easy_setopt_err_curl_slist(); \ + if((_curl_opt) == CURLOPT_SHARE) \ + if(!curlcheck_ptr((value), CURLSH)) \ + _curl_easy_setopt_err_CURLSH(); \ + } \ + curl_easy_setopt(handle, _curl_opt, value); \ + }) + +/* wraps curl_easy_getinfo() with typechecking */ +#define curl_easy_getinfo(handle, info, arg) \ + __extension__({ \ + __typeof__(info) _curl_info = info; \ + if(__builtin_constant_p(_curl_info)) { \ + if(curlcheck_string_info(_curl_info)) \ + if(!curlcheck_arr((arg), char *)) \ + _curl_easy_getinfo_err_string(); \ + if(curlcheck_long_info(_curl_info)) \ + if(!curlcheck_arr((arg), long)) \ + _curl_easy_getinfo_err_long(); \ + if(curlcheck_double_info(_curl_info)) \ + if(!curlcheck_arr((arg), double)) \ + _curl_easy_getinfo_err_double(); \ + if(curlcheck_slist_info(_curl_info)) \ + if(!curlcheck_arr((arg), struct curl_slist *)) \ + _curl_easy_getinfo_err_curl_slist(); \ + if(curlcheck_tlssessioninfo_info(_curl_info)) \ + if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \ + _curl_easy_getinfo_err_curl_tlssesssioninfo(); \ + if(curlcheck_certinfo_info(_curl_info)) \ + if(!curlcheck_arr((arg), struct curl_certinfo *)) \ + _curl_easy_getinfo_err_curl_certinfo(); \ + if(curlcheck_socket_info(_curl_info)) \ + if(!curlcheck_arr((arg), curl_socket_t)) \ + _curl_easy_getinfo_err_curl_socket(); \ + if(curlcheck_off_t_info(_curl_info)) \ + if(!curlcheck_arr((arg), curl_off_t)) \ + _curl_easy_getinfo_err_curl_off_t(); \ + } \ + curl_easy_getinfo(handle, _curl_info, arg); \ + }) + +/* + * For now, just make sure that the functions are called with three arguments + */ +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) + + +/* the actual warnings, triggered by calling the _curl_easy_setopt_err* + * functions */ + +/* To define a new warning, use _CURL_WARNING(identifier, "message") */ +#define CURLWARNING(id, message) \ + static void __attribute__((__warning__(message))) \ + __attribute__((__unused__)) __attribute__((__noinline__)) \ + id(void) { __asm__(""); } + +CURLWARNING(_curl_easy_setopt_err_long, + "curl_easy_setopt expects a long argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_off_t, + "curl_easy_setopt expects a curl_off_t argument for this option") +CURLWARNING(_curl_easy_setopt_err_string, + "curl_easy_setopt expects a " + "string ('char *' or char[]) argument for this option" + ) +CURLWARNING(_curl_easy_setopt_err_write_callback, + "curl_easy_setopt expects a curl_write_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_resolver_start_callback, + "curl_easy_setopt expects a " + "curl_resolver_start_callback argument for this option" + ) +CURLWARNING(_curl_easy_setopt_err_read_cb, + "curl_easy_setopt expects a curl_read_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_ioctl_cb, + "curl_easy_setopt expects a curl_ioctl_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_sockopt_cb, + "curl_easy_setopt expects a curl_sockopt_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_opensocket_cb, + "curl_easy_setopt expects a " + "curl_opensocket_callback argument for this option" + ) +CURLWARNING(_curl_easy_setopt_err_progress_cb, + "curl_easy_setopt expects a curl_progress_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_debug_cb, + "curl_easy_setopt expects a curl_debug_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_ssl_ctx_cb, + "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_conv_cb, + "curl_easy_setopt expects a curl_conv_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_seek_cb, + "curl_easy_setopt expects a curl_seek_callback argument for this option") +CURLWARNING(_curl_easy_setopt_err_cb_data, + "curl_easy_setopt expects a " + "private data pointer as argument for this option") +CURLWARNING(_curl_easy_setopt_err_error_buffer, + "curl_easy_setopt expects a " + "char buffer of CURL_ERROR_SIZE as argument for this option") +CURLWARNING(_curl_easy_setopt_err_FILE, + "curl_easy_setopt expects a 'FILE *' argument for this option") +CURLWARNING(_curl_easy_setopt_err_postfields, + "curl_easy_setopt expects a 'void *' or 'char *' argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_httpost, + "curl_easy_setopt expects a 'struct curl_httppost *' " + "argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_mimepost, + "curl_easy_setopt expects a 'curl_mime *' " + "argument for this option") +CURLWARNING(_curl_easy_setopt_err_curl_slist, + "curl_easy_setopt expects a 'struct curl_slist *' argument for this option") +CURLWARNING(_curl_easy_setopt_err_CURLSH, + "curl_easy_setopt expects a CURLSH* argument for this option") + +CURLWARNING(_curl_easy_getinfo_err_string, + "curl_easy_getinfo expects a pointer to 'char *' for this info") +CURLWARNING(_curl_easy_getinfo_err_long, + "curl_easy_getinfo expects a pointer to long for this info") +CURLWARNING(_curl_easy_getinfo_err_double, + "curl_easy_getinfo expects a pointer to double for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_slist, + "curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_tlssessioninfo *' for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_certinfo, + "curl_easy_getinfo expects a pointer to " + "'struct curl_certinfo *' for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_socket, + "curl_easy_getinfo expects a pointer to curl_socket_t for this info") +CURLWARNING(_curl_easy_getinfo_err_curl_off_t, + "curl_easy_getinfo expects a pointer to curl_off_t for this info") + +/* groups of curl_easy_setops options that take the same type of argument */ + +/* To add a new option to one of the groups, just add + * (option) == CURLOPT_SOMETHING + * to the or-expression. If the option takes a long or curl_off_t, you don't + * have to do anything + */ + +/* evaluates to true if option takes a long argument */ +#define curlcheck_long_option(option) \ + (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT) + +#define curlcheck_off_t_option(option) \ + ((option) > CURLOPTTYPE_OFF_T) + +/* evaluates to true if option takes a char* argument */ +#define curlcheck_string_option(option) \ + ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \ + (option) == CURLOPT_ACCEPT_ENCODING || \ + (option) == CURLOPT_ALTSVC || \ + (option) == CURLOPT_CAINFO || \ + (option) == CURLOPT_CAPATH || \ + (option) == CURLOPT_COOKIE || \ + (option) == CURLOPT_COOKIEFILE || \ + (option) == CURLOPT_COOKIEJAR || \ + (option) == CURLOPT_COOKIELIST || \ + (option) == CURLOPT_CRLFILE || \ + (option) == CURLOPT_CUSTOMREQUEST || \ + (option) == CURLOPT_DEFAULT_PROTOCOL || \ + (option) == CURLOPT_DNS_INTERFACE || \ + (option) == CURLOPT_DNS_LOCAL_IP4 || \ + (option) == CURLOPT_DNS_LOCAL_IP6 || \ + (option) == CURLOPT_DNS_SERVERS || \ + (option) == CURLOPT_DOH_URL || \ + (option) == CURLOPT_EGDSOCKET || \ + (option) == CURLOPT_FTPPORT || \ + (option) == CURLOPT_FTP_ACCOUNT || \ + (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \ + (option) == CURLOPT_INTERFACE || \ + (option) == CURLOPT_ISSUERCERT || \ + (option) == CURLOPT_KEYPASSWD || \ + (option) == CURLOPT_KRBLEVEL || \ + (option) == CURLOPT_LOGIN_OPTIONS || \ + (option) == CURLOPT_MAIL_AUTH || \ + (option) == CURLOPT_MAIL_FROM || \ + (option) == CURLOPT_NETRC_FILE || \ + (option) == CURLOPT_NOPROXY || \ + (option) == CURLOPT_PASSWORD || \ + (option) == CURLOPT_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PRE_PROXY || \ + (option) == CURLOPT_PROXY || \ + (option) == CURLOPT_PROXYPASSWORD || \ + (option) == CURLOPT_PROXYUSERNAME || \ + (option) == CURLOPT_PROXYUSERPWD || \ + (option) == CURLOPT_PROXY_CAINFO || \ + (option) == CURLOPT_PROXY_CAPATH || \ + (option) == CURLOPT_PROXY_CRLFILE || \ + (option) == CURLOPT_PROXY_KEYPASSWD || \ + (option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \ + (option) == CURLOPT_PROXY_SERVICE_NAME || \ + (option) == CURLOPT_PROXY_SSLCERT || \ + (option) == CURLOPT_PROXY_SSLCERTTYPE || \ + (option) == CURLOPT_PROXY_SSLKEY || \ + (option) == CURLOPT_PROXY_SSLKEYTYPE || \ + (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \ + (option) == CURLOPT_PROXY_TLS13_CIPHERS || \ + (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_PROXY_TLSAUTH_TYPE || \ + (option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \ + (option) == CURLOPT_RANDOM_FILE || \ + (option) == CURLOPT_RANGE || \ + (option) == CURLOPT_REFERER || \ + (option) == CURLOPT_REQUEST_TARGET || \ + (option) == CURLOPT_RTSP_SESSION_ID || \ + (option) == CURLOPT_RTSP_STREAM_URI || \ + (option) == CURLOPT_RTSP_TRANSPORT || \ + (option) == CURLOPT_SASL_AUTHZID || \ + (option) == CURLOPT_SERVICE_NAME || \ + (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ + (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \ + (option) == CURLOPT_SSH_KNOWNHOSTS || \ + (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \ + (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \ + (option) == CURLOPT_SSLCERT || \ + (option) == CURLOPT_SSLCERTTYPE || \ + (option) == CURLOPT_SSLENGINE || \ + (option) == CURLOPT_SSLKEY || \ + (option) == CURLOPT_SSLKEYTYPE || \ + (option) == CURLOPT_SSL_CIPHER_LIST || \ + (option) == CURLOPT_TLS13_CIPHERS || \ + (option) == CURLOPT_TLSAUTH_PASSWORD || \ + (option) == CURLOPT_TLSAUTH_TYPE || \ + (option) == CURLOPT_TLSAUTH_USERNAME || \ + (option) == CURLOPT_UNIX_SOCKET_PATH || \ + (option) == CURLOPT_URL || \ + (option) == CURLOPT_USERAGENT || \ + (option) == CURLOPT_USERNAME || \ + (option) == CURLOPT_USERPWD || \ + (option) == CURLOPT_XOAUTH2_BEARER || \ + 0) + +/* evaluates to true if option takes a curl_write_callback argument */ +#define curlcheck_write_cb_option(option) \ + ((option) == CURLOPT_HEADERFUNCTION || \ + (option) == CURLOPT_WRITEFUNCTION) + +/* evaluates to true if option takes a curl_conv_callback argument */ +#define curlcheck_conv_cb_option(option) \ + ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \ + (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION) + +/* evaluates to true if option takes a data argument to pass to a callback */ +#define curlcheck_cb_data_option(option) \ + ((option) == CURLOPT_CHUNK_DATA || \ + (option) == CURLOPT_CLOSESOCKETDATA || \ + (option) == CURLOPT_DEBUGDATA || \ + (option) == CURLOPT_FNMATCH_DATA || \ + (option) == CURLOPT_HEADERDATA || \ + (option) == CURLOPT_INTERLEAVEDATA || \ + (option) == CURLOPT_IOCTLDATA || \ + (option) == CURLOPT_OPENSOCKETDATA || \ + (option) == CURLOPT_PRIVATE || \ + (option) == CURLOPT_PROGRESSDATA || \ + (option) == CURLOPT_READDATA || \ + (option) == CURLOPT_SEEKDATA || \ + (option) == CURLOPT_SOCKOPTDATA || \ + (option) == CURLOPT_SSH_KEYDATA || \ + (option) == CURLOPT_SSL_CTX_DATA || \ + (option) == CURLOPT_WRITEDATA || \ + (option) == CURLOPT_RESOLVER_START_DATA || \ + (option) == CURLOPT_TRAILERDATA || \ + 0) + +/* evaluates to true if option takes a POST data argument (void* or char*) */ +#define curlcheck_postfields_option(option) \ + ((option) == CURLOPT_POSTFIELDS || \ + (option) == CURLOPT_COPYPOSTFIELDS || \ + 0) + +/* evaluates to true if option takes a struct curl_slist * argument */ +#define curlcheck_slist_option(option) \ + ((option) == CURLOPT_HTTP200ALIASES || \ + (option) == CURLOPT_HTTPHEADER || \ + (option) == CURLOPT_MAIL_RCPT || \ + (option) == CURLOPT_POSTQUOTE || \ + (option) == CURLOPT_PREQUOTE || \ + (option) == CURLOPT_PROXYHEADER || \ + (option) == CURLOPT_QUOTE || \ + (option) == CURLOPT_RESOLVE || \ + (option) == CURLOPT_TELNETOPTIONS || \ + (option) == CURLOPT_CONNECT_TO || \ + 0) + +/* groups of curl_easy_getinfo infos that take the same type of argument */ + +/* evaluates to true if info expects a pointer to char * argument */ +#define curlcheck_string_info(info) \ + (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG) + +/* evaluates to true if info expects a pointer to long argument */ +#define curlcheck_long_info(info) \ + (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE) + +/* evaluates to true if info expects a pointer to double argument */ +#define curlcheck_double_info(info) \ + (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST) + +/* true if info expects a pointer to struct curl_slist * argument */ +#define curlcheck_slist_info(info) \ + (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST)) + +/* true if info expects a pointer to struct curl_tlssessioninfo * argument */ +#define curlcheck_tlssessioninfo_info(info) \ + (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION)) + +/* true if info expects a pointer to struct curl_certinfo * argument */ +#define curlcheck_certinfo_info(info) ((info) == CURLINFO_CERTINFO) + +/* true if info expects a pointer to struct curl_socket_t argument */ +#define curlcheck_socket_info(info) \ + (CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T) + +/* true if info expects a pointer to curl_off_t argument */ +#define curlcheck_off_t_info(info) \ + (CURLINFO_OFF_T < (info)) + + +/* typecheck helpers -- check whether given expression has requested type*/ + +/* For pointers, you can use the curlcheck_ptr/curlcheck_arr macros, + * otherwise define a new macro. Search for __builtin_types_compatible_p + * in the GCC manual. + * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is + * the actual expression passed to the curl_easy_setopt macro. This + * means that you can only apply the sizeof and __typeof__ operators, no + * == or whatsoever. + */ + +/* XXX: should evaluate to true if expr is a pointer */ +#define curlcheck_any_ptr(expr) \ + (sizeof(expr) == sizeof(void *)) + +/* evaluates to true if expr is NULL */ +/* XXX: must not evaluate expr, so this check is not accurate */ +#define curlcheck_NULL(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL))) + +/* evaluates to true if expr is type*, const type* or NULL */ +#define curlcheck_ptr(expr, type) \ + (curlcheck_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), type *) || \ + __builtin_types_compatible_p(__typeof__(expr), const type *)) + +/* evaluates to true if expr is one of type[], type*, NULL or const type* */ +#define curlcheck_arr(expr, type) \ + (curlcheck_ptr((expr), type) || \ + __builtin_types_compatible_p(__typeof__(expr), type [])) + +/* evaluates to true if expr is a string */ +#define curlcheck_string(expr) \ + (curlcheck_arr((expr), char) || \ + curlcheck_arr((expr), signed char) || \ + curlcheck_arr((expr), unsigned char)) + +/* evaluates to true if expr is a long (no matter the signedness) + * XXX: for now, int is also accepted (and therefore short and char, which + * are promoted to int when passed to a variadic function) */ +#define curlcheck_long(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), long) || \ + __builtin_types_compatible_p(__typeof__(expr), signed long) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \ + __builtin_types_compatible_p(__typeof__(expr), int) || \ + __builtin_types_compatible_p(__typeof__(expr), signed int) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \ + __builtin_types_compatible_p(__typeof__(expr), short) || \ + __builtin_types_compatible_p(__typeof__(expr), signed short) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \ + __builtin_types_compatible_p(__typeof__(expr), char) || \ + __builtin_types_compatible_p(__typeof__(expr), signed char) || \ + __builtin_types_compatible_p(__typeof__(expr), unsigned char)) + +/* evaluates to true if expr is of type curl_off_t */ +#define curlcheck_off_t(expr) \ + (__builtin_types_compatible_p(__typeof__(expr), curl_off_t)) + +/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */ +/* XXX: also check size of an char[] array? */ +#define curlcheck_error_buffer(expr) \ + (curlcheck_NULL(expr) || \ + __builtin_types_compatible_p(__typeof__(expr), char *) || \ + __builtin_types_compatible_p(__typeof__(expr), char[])) + +/* evaluates to true if expr is of type (const) void* or (const) FILE* */ +#if 0 +#define curlcheck_cb_data(expr) \ + (curlcheck_ptr((expr), void) || \ + curlcheck_ptr((expr), FILE)) +#else /* be less strict */ +#define curlcheck_cb_data(expr) \ + curlcheck_any_ptr(expr) +#endif + +/* evaluates to true if expr is of type FILE* */ +#define curlcheck_FILE(expr) \ + (curlcheck_NULL(expr) || \ + (__builtin_types_compatible_p(__typeof__(expr), FILE *))) + +/* evaluates to true if expr can be passed as POST data (void* or char*) */ +#define curlcheck_postfields(expr) \ + (curlcheck_ptr((expr), void) || \ + curlcheck_arr((expr), char) || \ + curlcheck_arr((expr), unsigned char)) + +/* helper: __builtin_types_compatible_p distinguishes between functions and + * function pointers, hide it */ +#define curlcheck_cb_compatible(func, type) \ + (__builtin_types_compatible_p(__typeof__(func), type) || \ + __builtin_types_compatible_p(__typeof__(func) *, type)) + +/* evaluates to true if expr is of type curl_resolver_start_callback */ +#define curlcheck_resolver_start_callback(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_resolver_start_callback)) + +/* evaluates to true if expr is of type curl_read_callback or "similar" */ +#define curlcheck_read_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), __typeof__(fread) *) || \ + curlcheck_cb_compatible((expr), curl_read_callback) || \ + curlcheck_cb_compatible((expr), _curl_read_callback1) || \ + curlcheck_cb_compatible((expr), _curl_read_callback2) || \ + curlcheck_cb_compatible((expr), _curl_read_callback3) || \ + curlcheck_cb_compatible((expr), _curl_read_callback4) || \ + curlcheck_cb_compatible((expr), _curl_read_callback5) || \ + curlcheck_cb_compatible((expr), _curl_read_callback6)) +typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *); +typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *); +typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *); +typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_write_callback or "similar" */ +#define curlcheck_write_cb(expr) \ + (curlcheck_read_cb(expr) || \ + curlcheck_cb_compatible((expr), __typeof__(fwrite) *) || \ + curlcheck_cb_compatible((expr), curl_write_callback) || \ + curlcheck_cb_compatible((expr), _curl_write_callback1) || \ + curlcheck_cb_compatible((expr), _curl_write_callback2) || \ + curlcheck_cb_compatible((expr), _curl_write_callback3) || \ + curlcheck_cb_compatible((expr), _curl_write_callback4) || \ + curlcheck_cb_compatible((expr), _curl_write_callback5) || \ + curlcheck_cb_compatible((expr), _curl_write_callback6)) +typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *); +typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *); +typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t, + const void *); +typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *); + +/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */ +#define curlcheck_ioctl_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_ioctl_callback) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback1) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback2) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback3) || \ + curlcheck_cb_compatible((expr), _curl_ioctl_callback4)) +typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *); +typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *); +typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *); +typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *); + +/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */ +#define curlcheck_sockopt_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_sockopt_callback) || \ + curlcheck_cb_compatible((expr), _curl_sockopt_callback1) || \ + curlcheck_cb_compatible((expr), _curl_sockopt_callback2)) +typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype); +typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t, + curlsocktype); + +/* evaluates to true if expr is of type curl_opensocket_callback or + "similar" */ +#define curlcheck_opensocket_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_opensocket_callback) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback1) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback2) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback3) || \ + curlcheck_cb_compatible((expr), _curl_opensocket_callback4)) +typedef curl_socket_t (*_curl_opensocket_callback1) + (void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback2) + (void *, curlsocktype, const struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback3) + (const void *, curlsocktype, struct curl_sockaddr *); +typedef curl_socket_t (*_curl_opensocket_callback4) + (const void *, curlsocktype, const struct curl_sockaddr *); + +/* evaluates to true if expr is of type curl_progress_callback or "similar" */ +#define curlcheck_progress_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_progress_callback) || \ + curlcheck_cb_compatible((expr), _curl_progress_callback1) || \ + curlcheck_cb_compatible((expr), _curl_progress_callback2)) +typedef int (*_curl_progress_callback1)(void *, + double, double, double, double); +typedef int (*_curl_progress_callback2)(const void *, + double, double, double, double); + +/* evaluates to true if expr is of type curl_debug_callback or "similar" */ +#define curlcheck_debug_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_debug_callback) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback1) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback2) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback3) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback4) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback5) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback6) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback7) || \ + curlcheck_cb_compatible((expr), _curl_debug_callback8)) +typedef int (*_curl_debug_callback1) (CURL *, + curl_infotype, char *, size_t, void *); +typedef int (*_curl_debug_callback2) (CURL *, + curl_infotype, char *, size_t, const void *); +typedef int (*_curl_debug_callback3) (CURL *, + curl_infotype, const char *, size_t, void *); +typedef int (*_curl_debug_callback4) (CURL *, + curl_infotype, const char *, size_t, const void *); +typedef int (*_curl_debug_callback5) (CURL *, + curl_infotype, unsigned char *, size_t, void *); +typedef int (*_curl_debug_callback6) (CURL *, + curl_infotype, unsigned char *, size_t, const void *); +typedef int (*_curl_debug_callback7) (CURL *, + curl_infotype, const unsigned char *, size_t, void *); +typedef int (*_curl_debug_callback8) (CURL *, + curl_infotype, const unsigned char *, size_t, const void *); + +/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */ +/* this is getting even messier... */ +#define curlcheck_ssl_ctx_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_ssl_ctx_callback) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback1) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback2) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback3) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback4) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback5) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback6) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback7) || \ + curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback8)) +typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *); +typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *, + const void *); +#ifdef HEADER_SSL_H +/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX + * this will of course break if we're included before OpenSSL headers... + */ +typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *); +typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *); +typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *); +typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, + const void *); +#else +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7; +typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8; +#endif + +/* evaluates to true if expr is of type curl_conv_callback or "similar" */ +#define curlcheck_conv_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_conv_callback) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback1) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback2) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback3) || \ + curlcheck_cb_compatible((expr), _curl_conv_callback4)) +typedef CURLcode (*_curl_conv_callback1)(char *, size_t length); +typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length); +typedef CURLcode (*_curl_conv_callback3)(void *, size_t length); +typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length); + +/* evaluates to true if expr is of type curl_seek_callback or "similar" */ +#define curlcheck_seek_cb(expr) \ + (curlcheck_NULL(expr) || \ + curlcheck_cb_compatible((expr), curl_seek_callback) || \ + curlcheck_cb_compatible((expr), _curl_seek_callback1) || \ + curlcheck_cb_compatible((expr), _curl_seek_callback2)) +typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int); +typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int); + + +#endif /* CURLINC_TYPECHECK_GCC_H */ diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/urlapi.h b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/urlapi.h new file mode 100644 index 0000000000..f2d06770dc --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/include/curl/urlapi.h @@ -0,0 +1,125 @@ +#ifndef CURLINC_URLAPI_H +#define CURLINC_URLAPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* the error codes for the URL API */ +typedef enum { + CURLUE_OK, + CURLUE_BAD_HANDLE, /* 1 */ + CURLUE_BAD_PARTPOINTER, /* 2 */ + CURLUE_MALFORMED_INPUT, /* 3 */ + CURLUE_BAD_PORT_NUMBER, /* 4 */ + CURLUE_UNSUPPORTED_SCHEME, /* 5 */ + CURLUE_URLDECODE, /* 6 */ + CURLUE_OUT_OF_MEMORY, /* 7 */ + CURLUE_USER_NOT_ALLOWED, /* 8 */ + CURLUE_UNKNOWN_PART, /* 9 */ + CURLUE_NO_SCHEME, /* 10 */ + CURLUE_NO_USER, /* 11 */ + CURLUE_NO_PASSWORD, /* 12 */ + CURLUE_NO_OPTIONS, /* 13 */ + CURLUE_NO_HOST, /* 14 */ + CURLUE_NO_PORT, /* 15 */ + CURLUE_NO_QUERY, /* 16 */ + CURLUE_NO_FRAGMENT /* 17 */ +} CURLUcode; + +typedef enum { + CURLUPART_URL, + CURLUPART_SCHEME, + CURLUPART_USER, + CURLUPART_PASSWORD, + CURLUPART_OPTIONS, + CURLUPART_HOST, + CURLUPART_PORT, + CURLUPART_PATH, + CURLUPART_QUERY, + CURLUPART_FRAGMENT, + CURLUPART_ZONEID /* added in 7.65.0 */ +} CURLUPart; + +#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */ +#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set, + if the port number matches the + default for the scheme */ +#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if + missing */ +#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */ +#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */ +#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */ +#define CURLU_URLDECODE (1<<6) /* URL decode on get */ +#define CURLU_URLENCODE (1<<7) /* URL encode on set */ +#define CURLU_APPENDQUERY (1<<8) /* append a form style part */ +#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */ +#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the + scheme is unknown. */ + +typedef struct Curl_URL CURLU; + +/* + * curl_url() creates a new CURLU handle and returns a pointer to it. + * Must be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url(void); + +/* + * curl_url_cleanup() frees the CURLU handle and related resources used for + * the URL parsing. It will not free strings previously returned with the URL + * API. + */ +CURL_EXTERN void curl_url_cleanup(CURLU *handle); + +/* + * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new + * handle must also be freed with curl_url_cleanup(). + */ +CURL_EXTERN CURLU *curl_url_dup(CURLU *in); + +/* + * curl_url_get() extracts a specific part of the URL from a CURLU + * handle. Returns error code. The returned pointer MUST be freed with + * curl_free() afterwards. + */ +CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what, + char **part, unsigned int flags); + +/* + * curl_url_set() sets a specific part of the URL in a CURLU handle. Returns + * error code. The passed in string will be copied. Passing a NULL instead of + * a part string, clears that part. + */ +CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what, + const char *part, unsigned int flags); + + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* CURLINC_URLAPI_H */ diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/lib/libcurl.a b/packages/php-wasm/compile/libcurl/dist/root/lib/lib/libcurl.a new file mode 100644 index 0000000000..90bec77f51 Binary files /dev/null and b/packages/php-wasm/compile/libcurl/dist/root/lib/lib/libcurl.a differ diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/lib/libcurl.la b/packages/php-wasm/compile/libcurl/dist/root/lib/lib/libcurl.la new file mode 120000 index 0000000000..6e3b4c6b49 --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/lib/libcurl.la @@ -0,0 +1 @@ +../libcurl.la \ No newline at end of file diff --git a/packages/php-wasm/compile/libcurl/dist/root/lib/lib/libcurl.lai b/packages/php-wasm/compile/libcurl/dist/root/lib/lib/libcurl.lai new file mode 100644 index 0000000000..5e93509607 --- /dev/null +++ b/packages/php-wasm/compile/libcurl/dist/root/lib/lib/libcurl.lai @@ -0,0 +1,41 @@ +# libcurl.la - a libtool library file +# Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-13 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='' + +# Names of this library. +library_names='' + +# The name of the static archive. +old_library='libcurl.a' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='' + +# Libraries that this one depends upon. +dependency_libs=' -L/root/lib/lib -lssl -lcrypto -lz' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libcurl. +current=10 +age=6 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/root/install/lib' diff --git a/packages/php-wasm/compile/php/Dockerfile b/packages/php-wasm/compile/php/Dockerfile index 22445df89a..76a03893c8 100644 --- a/packages/php-wasm/compile/php/Dockerfile +++ b/packages/php-wasm/compile/php/Dockerfile @@ -21,6 +21,7 @@ RUN mkdir -p /root/lib/include /root/lib/lib /libs COPY ./bison2.7/dist/ /libs/bison2.7 COPY ./libedit/dist/root/lib /root/lib COPY ./libiconv/dist/root/lib /root/lib +COPY ./libcurl/dist/root/lib /root/lib COPY ./libncurses/dist/root/lib /root/lib COPY ./libopenssl/dist/root/lib /root/lib COPY ./libpng16/dist/root/lib /root/lib @@ -34,6 +35,7 @@ COPY ./oniguruma/dist/root/lib /root/lib # Build PHP # The PHP extensions to build: +ARG WITH_CURL ARG WITH_VRZNO ARG WITH_FILEINFO ARG WITH_LIBXML @@ -189,6 +191,13 @@ RUN if [ "$WITH_ICONV" = "yes" ]; \ echo -n ' --without-iconv ' >> /root/.php-configure-flags; \ fi; +# Add curl if needed +RUN if [ "$WITH_CURL" = "yes" ]; \ + then \ + echo -n ' --with-curl=/root/lib ' >> /root/.php-configure-flags; \ + echo -n ' /root/lib/lib/libcurl.a' >> /root/.emcc-php-wasm-sources; \ + fi; + # Add mbstring if needed RUN if [ "$WITH_MBSTRING" = "yes" ]; \ then echo -n ' --enable-mbstring ' >> /root/.php-configure-flags; \ @@ -236,6 +245,8 @@ RUN if [ "$WITH_MYSQL" = "yes" ]; then \ # Build the patched PHP WORKDIR /root/php-src RUN source /root/emsdk/emsdk_env.sh && \ + CURL_CFLAGS="-I/root/lib/include" \ + CURL_LIBS="-L/root/lib/lib" \ emconfigure ./configure \ PKG_CONFIG_PATH=$PKG_CONFIG_PATH \ # Fibers are a PHP 8.1+ feature. They are compiled as @@ -290,14 +301,10 @@ RUN if [[ "${PHP_VERSION:0:1}" -le "7" && "${PHP_VERSION:2:1}" -le "3" ]]; then # Rename the original php_pollfd_for() implementation so that we can link our own version. RUN /root/replace.sh 's/static inline int php_pollfd_for\(/int php_pollfd_for(php_socket_t fd, int events, struct timeval *timeouttv); static inline int __real_php_pollfd_for(/g' /root/php-src/main/php_network.h -RUN /root/replace.sh 's/static int php_cli_server_poller_poll/extern int wasm_select(int, fd_set * __restrict, fd_set * __restrict, fd_set * __restrict, struct timeval * __restrict); static int php_cli_server_poller_poll/g' /root/php-src/sapi/cli/php_cli_server.c RUN echo 'extern ssize_t wasm_read(int fd, void *buf, size_t count);' >> /root/php-src/main/php.h; RUN /root/replace.sh 's/ret = read/ret = wasm_read/g' /root/php-src/main/streams/plain_wrapper.c -# Provide a custom implementation of the php_select() function. -RUN /root/replace.sh 's/return php_select\(/return wasm_select(/g' /root/php-src/sapi/cli/php_cli_server.c - # Provide a custom implementation of the php_exec() function that handles spawning # the process inside exec(), passthru(), system(), etc. # We effectively remove the php_exec() implementation from the build by renaming it @@ -464,7 +471,22 @@ RUN echo -n ' -s ASYNCIFY=1 -s ASYNCIFY_IGNORE_INDIRECT=1 ' >> /root/.emcc-php-w "dynCall_viiiii",\ "dynCall_viiiiiii",\ "dynCall_viiiiiiii",'; \ - export ASYNCIFY_ONLY=$'"zend_generator_iterator_move_forward",\ + export ASYNCIFY_ONLY=$'"RAND_poll",\ +"rand_status",\ +"RAND_status",\ +"Curl_ossl_seed",\ +"ossl_connect_common",\ +"Curl_ossl_connect_nonblocking",\ +"Curl_ssl_connect_nonblocking",\ +"https_connecting",\ +"Curl_http_connect",\ +"Curl_socket_check",\ +"Curl_is_connected",\ +"multi_runsingle",\ +"curl_multi_perform",\ +"zif_curl_exec",\ +"rc_dtor_func",\ +"zend_generator_iterator_move_forward",\ "ZEND_FE_FETCH_R_SPEC_VAR_HANDLER",\ "zend_generator_resume",\ "zend_generator_iterator_rewind",\ @@ -503,6 +525,21 @@ RUN echo -n ' -s ASYNCIFY=1 -s ASYNCIFY_IGNORE_INDIRECT=1 ' >> /root/.emcc-php-w "_php_stream_free_enclosed",\ "stream_resource_persistent_dtor",\ "stream_resource_regular_dtor",\ +"curl_easy_perform",\ +"curl_multi_poll",\ +"Curl_multi_wait",\ +"Curl_poll",\ +"Curl_wait_ms",\ +"Curl_readwrite",\ +"Curl_http_connect",\ +"https_connecting",\ +"Curl_ssl_connect_nonblocking",\ +"Curl_ossl_connect_nonblocking"\ +"ossl_connect_common",\ +"Curl_ossl_seed",\ +"RAND_status",\ +"rand_status",\ +"RAND_poll",\ "zend_std_has_dimension",\ "zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST",\ "zend_assign_to_object",\ @@ -714,7 +751,7 @@ RUN echo -n ' -s ASYNCIFY=1 -s ASYNCIFY_IGNORE_INDIRECT=1 ' >> /root/.emcc-php-w "shutdown_executor",\ "shutdown_destructors",\ "stream_resource_regular_dtor",\ -"wasm_select",\ +"__wrap_select",\ "zend_call_function",\ "zend_call_known_function",\ "zend_close_rsrc_list",\ @@ -844,7 +881,7 @@ RUN set -euxo pipefail; \ if [ "${WITH_SOURCEMAPS}" = "yes" ]; then \ export OPTIMIZATION_FLAGS="-O0"; \ fi; \ - emcc $OPTIMIZATION_FLAGS \ + emcc -O0 -g2 \ --js-library /root/phpwasm-emscripten-library.js \ -I . \ -I ext \ @@ -867,6 +904,7 @@ RUN set -euxo pipefail; \ -s NODEJS_CATCH_REJECTION=0 \ -s INVOKE_RUN=0 \ -s EXIT_RUNTIME=1 \ + -Wl,--wrap=select \ /root/lib/libphp.a \ /root/proc_open.c \ /root/php_wasm.c \ diff --git a/packages/php-wasm/compile/php/php_wasm.c b/packages/php-wasm/compile/php/php_wasm.c index ff8d510c20..629468fb65 100644 --- a/packages/php-wasm/compile/php/php_wasm.c +++ b/packages/php-wasm/compile/php/php_wasm.c @@ -408,19 +408,10 @@ PHP_FUNCTION(post_message_to_js) } } -#if WITH_CLI_SAPI == 1 -#include "sapi/cli/php_cli_process_title.h" -#if PHP_MAJOR_VERSION >= 8 -#include "sapi/cli/php_cli_process_title_arginfo.h" -#endif - -extern int wasm_shutdown(int sockfd, int how); -extern int wasm_close(int sockfd); - /** - * select(2) shim for PHP dev server. + * select(2) shim. */ -EMSCRIPTEN_KEEPALIVE int wasm_select(int max_fd, fd_set *read_fds, fd_set *write_fds, fd_set *except_fds, struct timeval *timeouttv) +EMSCRIPTEN_KEEPALIVE int __wrap_select(int max_fd, fd_set *read_fds, fd_set *write_fds, fd_set *except_fds, struct timeval *timeouttv) { emscripten_sleep(0); // always yield to JS event loop int timeoutms = php_tvtoto(timeouttv); @@ -431,14 +422,29 @@ EMSCRIPTEN_KEEPALIVE int wasm_select(int max_fd, fd_set *read_fds, fd_set *write { n += wasm_poll_socket(i, POLLIN | POLLOUT, timeoutms); } - else if (FD_ISSET(i, write_fds)) + if (FD_ISSET(i, write_fds)) { n += wasm_poll_socket(i, POLLOUT, timeoutms); } + if (FD_ISSET(i, except_fds)) + { + n += wasm_poll_socket(i, POLLERR, timeoutms); + FD_CLR(i, except_fds); + } } return n; } +#if WITH_CLI_SAPI == 1 +#include "sapi/cli/php_cli_process_title.h" +#if PHP_MAJOR_VERSION >= 8 +#include "sapi/cli/php_cli_process_title_arginfo.h" +#endif + +extern int wasm_shutdown(int sockfd, int how); +extern int wasm_close(int sockfd); + + static const zend_function_entry additional_functions[] = { ZEND_FE(dl, arginfo_dl) PHP_FE(cli_set_process_title, arginfo_cli_set_process_title) diff --git a/packages/php-wasm/node/public/8_0_30/php_8_0.wasm b/packages/php-wasm/node/public/8_0_30/php_8_0.wasm index fbfd7f0102..bcc177cf80 100755 Binary files a/packages/php-wasm/node/public/8_0_30/php_8_0.wasm and b/packages/php-wasm/node/public/8_0_30/php_8_0.wasm differ diff --git a/packages/php-wasm/node/public/php_8_0.js b/packages/php-wasm/node/public/php_8_0.js index 19b0fbdbb4..5d618e0692 100644 --- a/packages/php-wasm/node/public/php_8_0.js +++ b/packages/php-wasm/node/public/php_8_0.js @@ -1,6 +1,6 @@ const dependencyFilename = __dirname + '/8_0_30/php_8_0.wasm'; export { dependencyFilename }; -export const dependenciesTotalSize = 13597144; +export const dependenciesTotalSize = 20744504; export function init(RuntimeName, PHPLoader) { /** * Overrides Emscripten's default ExitStatus object which gets @@ -38,133 +38,244 @@ export function init(RuntimeName, PHPLoader) { } // The rest of the code comes from the built php.js file and esm-suffix.js -var Module = typeof PHPLoader != "undefined" ? PHPLoader : {}; - +// include: shell.js +// The Module object: Our interface to the outside world. We import +// and export values on it. There are various ways Module can be used: +// 1. Not defined. We create it here +// 2. A function parameter, function(Module) { ..generated code.. } +// 3. pre-run appended it, var Module = {}; ..generated code.. +// 4. External script tag defines var Module. +// We need to check if Module already exists (e.g. case 3 above). +// Substitution will be replaced with actual code on later stage of the build, +// this way Closure Compiler will not mangle it (e.g. case 4. above). +// Note that if you want to run closure, and also to use Module +// after the generated code, you will need to define var Module = {}; +// before the code. Then that object will be used in the code, and you +// can continue to use Module afterwards as well. +var Module = typeof PHPLoader != 'undefined' ? PHPLoader : {}; + +// --pre-jses are emitted after the Module integration code, so that they can +// refer to Module (if they choose; they can also define Module) + + +// Sometimes an existing Module object exists with properties +// meant to overwrite the default module functionality. Here +// we collect those properties and reapply _after_ we configure +// the current environment's defaults to avoid having to be so +// defensive during initialization. var moduleOverrides = Object.assign({}, Module); var arguments_ = []; - -var thisProgram = "./this.program"; - +var thisProgram = './this.program'; var quit_ = (status, toThrow) => { - throw toThrow; + throw toThrow; }; -var ENVIRONMENT_IS_WEB=RuntimeName==="WEB"; +// Determine the runtime environment we are in. You can customize this by +// setting the ENVIRONMENT setting at compile time (see settings.js). +var ENVIRONMENT_IS_WEB=RuntimeName==="WEB"; var ENVIRONMENT_IS_WORKER=RuntimeName==="WORKER"; - var ENVIRONMENT_IS_NODE=RuntimeName==="NODE"; +var ENVIRONMENT_IS_SHELL=RuntimeName==="SHELL"; -var scriptDirectory = ""; - +// `/` should be present at the end if `scriptDirectory` is not empty +var scriptDirectory = ''; function locateFile(path) { - if (Module["locateFile"]) { - return Module["locateFile"](path, scriptDirectory); - } - return scriptDirectory + path; + if (Module['locateFile']) { + return Module['locateFile'](path, scriptDirectory); + } + return scriptDirectory + path; } -var read_, readAsync, readBinary; +// Hooks that are implemented differently in different runtime environments. +var read_, + readAsync, + readBinary, + setWindowTitle; if (ENVIRONMENT_IS_NODE) { - var fs = require("fs"); - var nodePath = require("path"); - if (ENVIRONMENT_IS_WORKER) { - scriptDirectory = nodePath.dirname(scriptDirectory) + "/"; - } else { - scriptDirectory = __dirname + "/"; - } - read_ = (filename, binary) => { + + // `require()` is no-op in an ESM module, use `createRequire()` to construct + // the require()` function. This is only necessary for multi-environment + // builds, `-sENVIRONMENT=node` emits a static import declaration instead. + // TODO: Swap all `require()`'s with `import()`'s? + // These modules will usually be used on Node.js. Load them eagerly to avoid + // the complexity of lazy-loading. + var fs = require('fs'); + var nodePath = require('path'); + + if (ENVIRONMENT_IS_WORKER) { + scriptDirectory = nodePath.dirname(scriptDirectory) + '/'; + } else { + scriptDirectory = __dirname + '/'; + } + +// include: node_shell_read.js +read_ = (filename, binary) => { + // We need to re-wrap `file://` strings to URLs. Normalizing isn't + // necessary in that case, the path should already be absolute. filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); - return fs.readFileSync(filename, binary ? undefined : "utf8"); - }; - readBinary = filename => { + return fs.readFileSync(filename, binary ? undefined : 'utf8'); +}; + +readBinary = (filename) => { var ret = read_(filename, true); if (!ret.buffer) { - ret = new Uint8Array(ret); + ret = new Uint8Array(ret); } return ret; - }; - readAsync = (filename, onload, onerror, binary = true) => { +}; + +readAsync = (filename, onload, onerror, binary = true) => { + // See the comment in the `read_` function. filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); - fs.readFile(filename, binary ? undefined : "utf8", ((err, data) => { - if (err) onerror(err); else onload(binary ? data.buffer : data); - })); - }; - if (!Module["thisProgram"] && process.argv.length > 1) { - thisProgram = process.argv[1].replace(/\\/g, "/"); - } - arguments_ = process.argv.slice(2); - if (typeof module != "undefined") { - module["exports"] = Module; - } - quit_ = (status, toThrow) => { - process.exitCode = status; - throw toThrow; - }; - Module["inspect"] = () => "[Emscripten Module object]"; -} else {} + fs.readFile(filename, binary ? undefined : 'utf8', (err, data) => { + if (err) onerror(err); + else onload(binary ? data.buffer : data); + }); +}; +// end include: node_shell_read.js + if (!Module['thisProgram'] && process.argv.length > 1) { + thisProgram = process.argv[1].replace(/\\/g, '/'); + } -var out = Module["print"] || console.log.bind(console); + arguments_ = process.argv.slice(2); -var err = Module["printErr"] || console.error.bind(console); + if (typeof module != 'undefined') { + module['exports'] = Module; + } -Object.assign(Module, moduleOverrides); + quit_ = (status, toThrow) => { + process.exitCode = status; + throw toThrow; + }; + Module['inspect'] = () => '[Emscripten Module object]'; + +} else + +// Note that this includes Node.js workers when relevant (pthreads is enabled). +// Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and +// ENVIRONMENT_IS_NODE. +{ +} + +var out = Module['print'] || console.log.bind(console); +var err = Module['printErr'] || console.error.bind(console); + +// Merge back in the overrides +Object.assign(Module, moduleOverrides); +// Free the object hierarchy contained in the overrides, this lets the GC +// reclaim data used e.g. in memoryInitializerRequest, which is a large typed array. moduleOverrides = null; -if (Module["arguments"]) arguments_ = Module["arguments"]; +// Emit code to handle expected values on the Module object. This applies Module.x +// to the proper local x. This has two benefits: first, we only emit it if it is +// expected to arrive, and second, by using a local everywhere else that can be +// minified. -if (Module["thisProgram"]) thisProgram = Module["thisProgram"]; +if (Module['arguments']) arguments_ = Module['arguments']; -if (Module["quit"]) quit_ = Module["quit"]; +if (Module['thisProgram']) thisProgram = Module['thisProgram']; -var wasmBinary; +if (Module['quit']) quit_ = Module['quit']; + +// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message -if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"]; +// end include: shell.js +// include: preamble.js +// === Preamble library stuff === -var noExitRuntime = Module["noExitRuntime"] || false; +// Documentation for the public APIs defined in this file must be updated in: +// site/source/docs/api_reference/preamble.js.rst +// A prebuilt local version of the documentation is available at: +// site/build/text/docs/api_reference/preamble.js.txt +// You can also build docs locally as HTML or other formats in site/ +// An online HTML version (which may be of a different version of Emscripten) +// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html -if (typeof WebAssembly != "object") { - abort("no native wasm support detected"); +var wasmBinary; +if (Module['wasmBinary']) wasmBinary = Module['wasmBinary']; +var noExitRuntime = Module['noExitRuntime'] || false; + +if (typeof WebAssembly != 'object') { + abort('no native wasm support detected'); } +// Wasm globals + var wasmMemory; +//======================================== +// Runtime essentials +//======================================== + +// whether we are quitting the application. no code should run after this. +// set in exit() and abort() var ABORT = false; +// set by exit() and abort(). Passed to 'onExit' handler. +// NOTE: This is also used as the process return code code in shell environments +// but only when noExitRuntime is false. var EXITSTATUS; +/** @type {function(*, string=)} */ function assert(condition, text) { - if (!condition) { - abort(text); - } + if (!condition) { + // This build was created without ASSERTIONS defined. `assert()` should not + // ever be called in this configuration but in case there are callers in + // the wild leave this simple abort() implemenation here for now. + abort(text); + } } -var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; +// Memory management + +var HEAP, +/** @type {!Int8Array} */ + HEAP8, +/** @type {!Uint8Array} */ + HEAPU8, +/** @type {!Int16Array} */ + HEAP16, +/** @type {!Uint16Array} */ + HEAPU16, +/** @type {!Int32Array} */ + HEAP32, +/** @type {!Uint32Array} */ + HEAPU32, +/** @type {!Float32Array} */ + HEAPF32, +/** @type {!Float64Array} */ + HEAPF64; function updateMemoryViews() { - var b = wasmMemory.buffer; - Module["HEAP8"] = HEAP8 = new Int8Array(b); - Module["HEAP16"] = HEAP16 = new Int16Array(b); - Module["HEAP32"] = HEAP32 = new Int32Array(b); - Module["HEAPU8"] = HEAPU8 = new Uint8Array(b); - Module["HEAPU16"] = HEAPU16 = new Uint16Array(b); - Module["HEAPU32"] = HEAPU32 = new Uint32Array(b); - Module["HEAPF32"] = HEAPF32 = new Float32Array(b); - Module["HEAPF64"] = HEAPF64 = new Float64Array(b); + var b = wasmMemory.buffer; + Module['HEAP8'] = HEAP8 = new Int8Array(b); + Module['HEAP16'] = HEAP16 = new Int16Array(b); + Module['HEAP32'] = HEAP32 = new Int32Array(b); + Module['HEAPU8'] = HEAPU8 = new Uint8Array(b); + Module['HEAPU16'] = HEAPU16 = new Uint16Array(b); + Module['HEAPU32'] = HEAPU32 = new Uint32Array(b); + Module['HEAPF32'] = HEAPF32 = new Float32Array(b); + Module['HEAPF64'] = HEAPF64 = new Float64Array(b); } +// include: runtime_init_table.js +// In regular non-RELOCATABLE mode the table is exported +// from the wasm module and this will be assigned once +// the exports are available. var wasmTable; - -var __ATPRERUN__ = []; - -var __ATINIT__ = []; - -var __ATEXIT__ = []; - -var __ATPOSTRUN__ = []; +// end include: runtime_init_table.js +// include: runtime_stack_check.js +// end include: runtime_stack_check.js +// include: runtime_assertions.js +// end include: runtime_assertions.js +var __ATPRERUN__ = []; // functions called before the runtime is initialized +var __ATINIT__ = []; // functions called during startup +var __ATEXIT__ = []; // functions called during shutdown +var __ATPOSTRUN__ = []; // functions called after the main() is called var runtimeInitialized = false; @@ -173,7585 +284,9259 @@ var runtimeExited = false; var runtimeKeepaliveCounter = 0; function keepRuntimeAlive() { - return noExitRuntime || runtimeKeepaliveCounter > 0; + return noExitRuntime || runtimeKeepaliveCounter > 0; } function preRun() { - if (Module["preRun"]) { - if (typeof Module["preRun"] == "function") Module["preRun"] = [ Module["preRun"] ]; - while (Module["preRun"].length) { - addOnPreRun(Module["preRun"].shift()); + if (Module['preRun']) { + if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + while (Module['preRun'].length) { + addOnPreRun(Module['preRun'].shift()); + } } - } - callRuntimeCallbacks(__ATPRERUN__); + callRuntimeCallbacks(__ATPRERUN__); } function initRuntime() { - runtimeInitialized = true; - if (!Module["noFSInit"] && !FS.init.initialized) FS.init(); - FS.ignorePermissions = false; - TTY.init(); - SOCKFS.root = FS.mount(SOCKFS, {}, null); - PIPEFS.root = FS.mount(PIPEFS, {}, null); - callRuntimeCallbacks(__ATINIT__); + runtimeInitialized = true; + + SOCKFS.root = FS.mount(SOCKFS, {}, null); + +if (!Module["noFSInit"] && !FS.init.initialized) + FS.init(); +FS.ignorePermissions = false; + +TTY.init(); +PIPEFS.root = FS.mount(PIPEFS, {}, null); + callRuntimeCallbacks(__ATINIT__); } function exitRuntime() { - ___funcs_on_exit(); - callRuntimeCallbacks(__ATEXIT__); - FS.quit(); - TTY.shutdown(); - runtimeExited = true; + ___funcs_on_exit(); // Native atexit() functions + callRuntimeCallbacks(__ATEXIT__); + FS.quit(); +TTY.shutdown(); + runtimeExited = true; } function postRun() { - if (Module["postRun"]) { - if (typeof Module["postRun"] == "function") Module["postRun"] = [ Module["postRun"] ]; - while (Module["postRun"].length) { - addOnPostRun(Module["postRun"].shift()); + + if (Module['postRun']) { + if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; + while (Module['postRun'].length) { + addOnPostRun(Module['postRun'].shift()); + } } - } - callRuntimeCallbacks(__ATPOSTRUN__); + + callRuntimeCallbacks(__ATPOSTRUN__); } function addOnPreRun(cb) { - __ATPRERUN__.unshift(cb); + __ATPRERUN__.unshift(cb); } function addOnInit(cb) { - __ATINIT__.unshift(cb); + __ATINIT__.unshift(cb); +} + +function addOnExit(cb) { + __ATEXIT__.unshift(cb); } function addOnPostRun(cb) { - __ATPOSTRUN__.unshift(cb); + __ATPOSTRUN__.unshift(cb); } -var runDependencies = 0; +// include: runtime_math.js +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul -var runDependencyWatcher = null; +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround -var dependenciesFulfilled = null; +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc + +// end include: runtime_math.js +// A counter of dependencies for calling run(). If we need to +// do asynchronous work before running, increment this and +// decrement it. Incrementing must happen in a place like +// Module.preRun (used by emcc to add file preloading). +// Note that you can add dependencies in preRun, even though +// it happens right before run - run will be postponed until +// the dependencies are met. +var runDependencies = 0; +var runDependencyWatcher = null; +var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled function getUniqueRunDependency(id) { - return id; + return id; } function addRunDependency(id) { - runDependencies++; - if (Module["monitorRunDependencies"]) { - Module["monitorRunDependencies"](runDependencies); - } + runDependencies++; + + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + } function removeRunDependency(id) { - runDependencies--; - if (Module["monitorRunDependencies"]) { - Module["monitorRunDependencies"](runDependencies); - } - if (runDependencies == 0) { - if (runDependencyWatcher !== null) { - clearInterval(runDependencyWatcher); - runDependencyWatcher = null; - } - if (dependenciesFulfilled) { - var callback = dependenciesFulfilled; - dependenciesFulfilled = null; - callback(); - } - } + runDependencies--; + + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + if (dependenciesFulfilled) { + var callback = dependenciesFulfilled; + dependenciesFulfilled = null; + callback(); // can add another dependenciesFulfilled + } + } } +/** @param {string|number=} what */ function abort(what) { - if (Module["onAbort"]) { - Module["onAbort"](what); - } - what = "Aborted(" + what + ")"; - err(what); - ABORT = true; - EXITSTATUS = 1; - what += ". Build with -sASSERTIONS for more info."; - var e = new WebAssembly.RuntimeError(what); - throw e; + if (Module['onAbort']) { + Module['onAbort'](what); + } + + what = 'Aborted(' + what + ')'; + // TODO(sbc): Should we remove printing and leave it up to whoever + // catches the exception? + err(what); + + ABORT = true; + EXITSTATUS = 1; + + what += '. Build with -sASSERTIONS for more info.'; + + // Use a wasm runtime error, because a JS error might be seen as a foreign + // exception, which means we'd run destructors on it. We need the error to + // simply make the program stop. + // FIXME This approach does not work in Wasm EH because it currently does not assume + // all RuntimeErrors are from traps; it decides whether a RuntimeError is from + // a trap or not based on a hidden field within the object. So at the moment + // we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that + // allows this in the wasm spec. + + // Suppress closure compiler warning here. Closure compiler's builtin extern + // defintion for WebAssembly.RuntimeError claims it takes no arguments even + // though it can. + // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed. + /** @suppress {checkTypes} */ + var e = new WebAssembly.RuntimeError(what); + + // Throw the error whether or not MODULARIZE is set because abort is used + // in code paths apart from instantiation where an exception is expected + // to be thrown when abort is called. + throw e; } -var dataURIPrefix = "data:application/octet-stream;base64,"; +// include: memoryprofiler.js +// end include: memoryprofiler.js +// include: URIUtils.js +// Prefix of data URIs emitted by SINGLE_FILE and related options. +var dataURIPrefix = 'data:application/octet-stream;base64,'; +// Indicates whether filename is a base64 data URI. function isDataURI(filename) { - return filename.startsWith(dataURIPrefix); + // Prefix of data URIs emitted by SINGLE_FILE and related options. + return filename.startsWith(dataURIPrefix); } +// Indicates whether filename is delivered via file protocol (as opposed to http/https) function isFileURI(filename) { - return filename.startsWith("file://"); + return filename.startsWith('file://'); } - +// end include: URIUtils.js +// include: runtime_exceptions.js +// end include: runtime_exceptions.js var wasmBinaryFile; - -wasmBinaryFile = dependencyFilename; - -if (!isDataURI(wasmBinaryFile)) { - wasmBinaryFile = locateFile(wasmBinaryFile); -} + wasmBinaryFile = dependencyFilename; + if (!isDataURI(wasmBinaryFile)) { + wasmBinaryFile = locateFile(wasmBinaryFile); + } function getBinarySync(file) { - if (file == wasmBinaryFile && wasmBinary) { - return new Uint8Array(wasmBinary); - } - if (readBinary) { - return readBinary(file); - } - throw "both async and sync fetching of the wasm failed"; + if (file == wasmBinaryFile && wasmBinary) { + return new Uint8Array(wasmBinary); + } + if (readBinary) { + return readBinary(file); + } + throw "both async and sync fetching of the wasm failed"; } function getBinaryPromise(binaryFile) { - if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) { - if (typeof fetch == "function") { - return fetch(binaryFile, { - credentials: "same-origin" - }).then((response => { - if (!response["ok"]) { - throw "failed to load wasm binary file at '" + binaryFile + "'"; + // If we don't have the binary yet, try to load it asynchronously. + // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url. + // See https://github.com/github/fetch/pull/92#issuecomment-140665932 + // Cordova or Electron apps are typically loaded from a file:// url. + // So use fetch if it is available and the url is not a file, otherwise fall back to XHR. + if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) { + if (typeof fetch == 'function' + ) { + return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { + if (!response['ok']) { + throw "failed to load wasm binary file at '" + binaryFile + "'"; + } + return response['arrayBuffer'](); + }).catch(() => getBinarySync(binaryFile)); } - return response["arrayBuffer"](); - })).catch((() => getBinarySync(binaryFile))); } - } - return Promise.resolve().then((() => getBinarySync(binaryFile))); + + // Otherwise, getBinarySync should be able to get it synchronously + return Promise.resolve().then(() => getBinarySync(binaryFile)); } function instantiateArrayBuffer(binaryFile, imports, receiver) { - return getBinaryPromise(binaryFile).then((binary => WebAssembly.instantiate(binary, imports))).then((instance => instance)).then(receiver, (reason => { - err("failed to asynchronously prepare wasm: " + reason); - abort(reason); - })); + return getBinaryPromise(binaryFile).then((binary) => { + return WebAssembly.instantiate(binary, imports); + }).then((instance) => { + return instance; + }).then(receiver, (reason) => { + err('failed to asynchronously prepare wasm: ' + reason); + + abort(reason); + }); } function instantiateAsync(binary, binaryFile, imports, callback) { - if (!binary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(binaryFile) && !ENVIRONMENT_IS_NODE && typeof fetch == "function") { - return fetch(binaryFile, { - credentials: "same-origin" - }).then((response => { - var result = WebAssembly.instantiateStreaming(response, imports); - return result.then(callback, (function(reason) { - err("wasm streaming compile failed: " + reason); - err("falling back to ArrayBuffer instantiation"); - return instantiateArrayBuffer(binaryFile, imports, callback); - })); - })); - } - return instantiateArrayBuffer(binaryFile, imports, callback); + if (!binary && + typeof WebAssembly.instantiateStreaming == 'function' && + !isDataURI(binaryFile) && + // Avoid instantiateStreaming() on Node.js environment for now, as while + // Node.js v18.1.0 implements it, it does not have a full fetch() + // implementation yet. + // + // Reference: + // https://github.com/emscripten-core/emscripten/pull/16917 + !ENVIRONMENT_IS_NODE && + typeof fetch == 'function') { + return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { + // Suppress closure warning here since the upstream definition for + // instantiateStreaming only allows Promise rather than + // an actual Response. + // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed. + /** @suppress {checkTypes} */ + var result = WebAssembly.instantiateStreaming(response, imports); + + return result.then( + callback, + function(reason) { + // We expect the most common failure cause to be a bad MIME type for the binary, + // in which case falling back to ArrayBuffer instantiation should work. + err('wasm streaming compile failed: ' + reason); + err('falling back to ArrayBuffer instantiation'); + return instantiateArrayBuffer(binaryFile, imports, callback); + }); + }); + } + return instantiateArrayBuffer(binaryFile, imports, callback); } +// Create the wasm instance. +// Receives the wasm imports, returns the exports. function createWasm() { - var info = { - "a": wasmImports - }; - function receiveInstance(instance, module) { - var exports = instance.exports; - exports = Asyncify.instrumentWasmExports(exports); - Module["asm"] = exports; - wasmMemory = Module["asm"]["$a"]; - updateMemoryViews(); - wasmTable = Module["asm"]["db"]; - addOnInit(Module["asm"]["ab"]); - removeRunDependency("wasm-instantiate"); - return exports; - } - addRunDependency("wasm-instantiate"); - function receiveInstantiationResult(result) { - receiveInstance(result["instance"]); - } - if (Module["instantiateWasm"]) { - try { - return Module["instantiateWasm"](info, receiveInstance); - } catch (e) { - err("Module.instantiateWasm callback failed with error: " + e); - return false; - } - } - instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult); - return {}; -} - -var tempDouble; - -var tempI64; - -function ExitStatus(status) { - this.name = "ExitStatus"; - this.message = `Program terminated with exit(${status})`; - this.status = status; -} + // prepare imports + var info = { + 'env': wasmImports, + 'wasi_snapshot_preview1': wasmImports, + }; + // Load the wasm module and create an instance of using native support in the JS engine. + // handle a generated wasm instance, receiving its exports and + // performing other necessary setup + /** @param {WebAssembly.Module=} module*/ + function receiveInstance(instance, module) { + var exports = instance.exports; -var callRuntimeCallbacks = callbacks => { - while (callbacks.length > 0) { - callbacks.shift()(Module); - } -}; + exports = Asyncify.instrumentWasmExports(exports); -var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder("utf8") : undefined; - -var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => { - var endIdx = idx + maxBytesToRead; - var endPtr = idx; - while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr; - if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { - return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr)); - } - var str = ""; - while (idx < endPtr) { - var u0 = heapOrArray[idx++]; - if (!(u0 & 128)) { - str += String.fromCharCode(u0); - continue; - } - var u1 = heapOrArray[idx++] & 63; - if ((u0 & 224) == 192) { - str += String.fromCharCode((u0 & 31) << 6 | u1); - continue; - } - var u2 = heapOrArray[idx++] & 63; - if ((u0 & 240) == 224) { - u0 = (u0 & 15) << 12 | u1 << 6 | u2; - } else { - u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heapOrArray[idx++] & 63; - } - if (u0 < 65536) { - str += String.fromCharCode(u0); - } else { - var ch = u0 - 65536; - str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023); - } - } - return str; -}; + Module['asm'] = exports; -var UTF8ToString = (ptr, maxBytesToRead) => ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ""; + wasmMemory = Module['asm']['memory']; + updateMemoryViews(); -Module["UTF8ToString"] = UTF8ToString; + wasmTable = Module['asm']['__indirect_function_table']; -var ___assert_fail = (condition, filename, line, func) => { - abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]); -}; + addOnInit(Module['asm']['__wasm_call_ctors']); -var ___call_sighandler = (fp, sig) => (a1 => dynCall_vi.apply(null, [ fp, a1 ]))(sig); - -var PATH = { - isAbs: path => path.charAt(0) === "/", - splitPath: filename => { - var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; - return splitPathRe.exec(filename).slice(1); - }, - normalizeArray: (parts, allowAboveRoot) => { - var up = 0; - for (var i = parts.length - 1; i >= 0; i--) { - var last = parts[i]; - if (last === ".") { - parts.splice(i, 1); - } else if (last === "..") { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } + removeRunDependency('wasm-instantiate'); + return exports; } - if (allowAboveRoot) { - for (;up; up--) { - parts.unshift(".."); - } + // wait for the pthread pool (if any) + addRunDependency('wasm-instantiate'); + + // Prefer streaming instantiation if available. + function receiveInstantiationResult(result) { + // 'result' is a ResultObject object which has both the module and instance. + // receiveInstance() will swap in the exports (to Module.asm) so they can be called + // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line. + // When the regression is fixed, can restore the above PTHREADS-enabled path. + receiveInstance(result['instance']); } - return parts; - }, - normalize: path => { - var isAbsolute = PATH.isAbs(path), trailingSlash = path.substr(-1) === "/"; - path = PATH.normalizeArray(path.split("/").filter((p => !!p)), !isAbsolute).join("/"); - if (!path && !isAbsolute) { - path = "."; - } - if (path && trailingSlash) { - path += "/"; - } - return (isAbsolute ? "/" : "") + path; - }, - dirname: path => { - var result = PATH.splitPath(path), root = result[0], dir = result[1]; - if (!root && !dir) { - return "."; - } - if (dir) { - dir = dir.substr(0, dir.length - 1); - } - return root + dir; - }, - basename: path => { - if (path === "/") return "/"; - path = PATH.normalize(path); - path = path.replace(/\/$/, ""); - var lastSlash = path.lastIndexOf("/"); - if (lastSlash === -1) return path; - return path.substr(lastSlash + 1); - }, - join: function() { - var paths = Array.prototype.slice.call(arguments); - return PATH.normalize(paths.join("/")); - }, - join2: (l, r) => PATH.normalize(l + "/" + r) -}; -var initRandomFill = () => { - if (typeof crypto == "object" && typeof crypto["getRandomValues"] == "function") { - return view => crypto.getRandomValues(view); - } else if (ENVIRONMENT_IS_NODE) { - try { - var crypto_module = require("crypto"); - var randomFillSync = crypto_module["randomFillSync"]; - if (randomFillSync) { - return view => crypto_module["randomFillSync"](view); - } - var randomBytes = crypto_module["randomBytes"]; - return view => (view.set(randomBytes(view.byteLength)), view); - } catch (e) {} - } - abort("initRandomDevice"); -}; + // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback + // to manually instantiate the Wasm module themselves. This allows pages to + // run the instantiation parallel to any other async startup actions they are + // performing. + // Also pthreads and wasm workers initialize the wasm instance through this + // path. + if (Module['instantiateWasm']) { -var randomFill = view => (randomFill = initRandomFill())(view); - -var PATH_FS = { - resolve: function() { - var resolvedPath = "", resolvedAbsolute = false; - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = i >= 0 ? arguments[i] : FS.cwd(); - if (typeof path != "string") { - throw new TypeError("Arguments to path.resolve must be strings"); - } else if (!path) { - return ""; - } - resolvedPath = path + "/" + resolvedPath; - resolvedAbsolute = PATH.isAbs(path); - } - resolvedPath = PATH.normalizeArray(resolvedPath.split("/").filter((p => !!p)), !resolvedAbsolute).join("/"); - return (resolvedAbsolute ? "/" : "") + resolvedPath || "."; - }, - relative: (from, to) => { - from = PATH_FS.resolve(from).substr(1); - to = PATH_FS.resolve(to).substr(1); - function trim(arr) { - var start = 0; - for (;start < arr.length; start++) { - if (arr[start] !== "") break; - } - var end = arr.length - 1; - for (;end >= 0; end--) { - if (arr[end] !== "") break; - } - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - var fromParts = trim(from.split("/")); - var toParts = trim(to.split("/")); - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } - } - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push(".."); + try { + return Module['instantiateWasm'](info, receiveInstance); + } catch(e) { + err('Module.instantiateWasm callback failed with error: ' + e); + return false; + } } - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - return outputParts.join("/"); - } -}; -var FS_stdin_getChar_buffer = []; - -var lengthBytesUTF8 = str => { - var len = 0; - for (var i = 0; i < str.length; ++i) { - var c = str.charCodeAt(i); - if (c <= 127) { - len++; - } else if (c <= 2047) { - len += 2; - } else if (c >= 55296 && c <= 57343) { - len += 4; - ++i; - } else { - len += 3; - } - } - return len; -}; + instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult); + return {}; // no exports yet; we'll fill them in later +} -Module["lengthBytesUTF8"] = lengthBytesUTF8; - -var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { - if (!(maxBytesToWrite > 0)) return 0; - var startIdx = outIdx; - var endIdx = outIdx + maxBytesToWrite - 1; - for (var i = 0; i < str.length; ++i) { - var u = str.charCodeAt(i); - if (u >= 55296 && u <= 57343) { - var u1 = str.charCodeAt(++i); - u = 65536 + ((u & 1023) << 10) | u1 & 1023; - } - if (u <= 127) { - if (outIdx >= endIdx) break; - heap[outIdx++] = u; - } else if (u <= 2047) { - if (outIdx + 1 >= endIdx) break; - heap[outIdx++] = 192 | u >> 6; - heap[outIdx++] = 128 | u & 63; - } else if (u <= 65535) { - if (outIdx + 2 >= endIdx) break; - heap[outIdx++] = 224 | u >> 12; - heap[outIdx++] = 128 | u >> 6 & 63; - heap[outIdx++] = 128 | u & 63; - } else { - if (outIdx + 3 >= endIdx) break; - heap[outIdx++] = 240 | u >> 18; - heap[outIdx++] = 128 | u >> 12 & 63; - heap[outIdx++] = 128 | u >> 6 & 63; - heap[outIdx++] = 128 | u & 63; - } - } - heap[outIdx] = 0; - return outIdx - startIdx; -}; +// Globals used by JS i64 conversions (see makeSetValue) +var tempDouble; +var tempI64; -function intArrayFromString(stringy, dontAddNull, length) { - var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1; - var u8array = new Array(len); - var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length); - if (dontAddNull) u8array.length = numBytesWritten; - return u8array; -} +// include: runtime_debug.js +// end include: runtime_debug.js +// === Body === -var FS_stdin_getChar = () => { - if (!FS_stdin_getChar_buffer.length) { - var result = null; - if (ENVIRONMENT_IS_NODE) { - var BUFSIZE = 256; - var buf = Buffer.alloc(BUFSIZE); - var bytesRead = 0; - var fd = process.stdin.fd; - try { - bytesRead = fs.readSync(fd, buf, 0, BUFSIZE, -1); - } catch (e) { - if (e.toString().includes("EOF")) bytesRead = 0; else throw e; - } - if (bytesRead > 0) { - result = buf.slice(0, bytesRead).toString("utf-8"); - } else { - result = null; - } - } else if (typeof window != "undefined" && typeof window.prompt == "function") { - result = window.prompt("Input: "); - if (result !== null) { - result += "\n"; - } - } else if (typeof readline == "function") { - result = readline(); - if (result !== null) { - result += "\n"; - } - } - if (!result) { - return null; - } - FS_stdin_getChar_buffer = intArrayFromString(result, true); - } - return FS_stdin_getChar_buffer.shift(); -}; +// end include: preamble.js -var TTY = { - ttys: [], - init: function() {}, - shutdown: function() {}, - register: function(dev, ops) { - TTY.ttys[dev] = { - input: [], - output: [], - ops: ops - }; - FS.registerDevice(dev, TTY.stream_ops); - }, - stream_ops: { - open: function(stream) { - var tty = TTY.ttys[stream.node.rdev]; - if (!tty) { - throw new FS.ErrnoError(43); - } - stream.tty = tty; - stream.seekable = false; - }, - close: function(stream) { - stream.tty.ops.fsync(stream.tty); - }, - fsync: function(stream) { - stream.tty.ops.fsync(stream.tty); - }, - read: function(stream, buffer, offset, length, pos) { - if (!stream.tty || !stream.tty.ops.get_char) { - throw new FS.ErrnoError(60); - } - var bytesRead = 0; - for (var i = 0; i < length; i++) { - var result; - try { - result = stream.tty.ops.get_char(stream.tty); - } catch (e) { - throw new FS.ErrnoError(29); + /** @constructor */ + function ExitStatus(status) { + this.name = 'ExitStatus'; + this.message = `Program terminated with exit(${status})`; + this.status = status; } - if (result === undefined && bytesRead === 0) { - throw new FS.ErrnoError(6); + + var callRuntimeCallbacks = (callbacks) => { + while (callbacks.length > 0) { + // Pass the module as the first argument. + callbacks.shift()(Module); + } + }; + + + /** + * @param {number} ptr + * @param {string} type + */ + function getValue(ptr, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': return HEAP8[((ptr)>>0)]; + case 'i8': return HEAP8[((ptr)>>0)]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': abort('to do getValue(i64) use WASM_BIGINT'); + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + case '*': return HEAPU32[((ptr)>>2)]; + default: abort(`invalid type for getValue: ${type}`); } - if (result === null || result === undefined) break; - bytesRead++; - buffer[offset + i] = result; - } - if (bytesRead) { - stream.node.timestamp = Date.now(); - } - return bytesRead; - }, - write: function(stream, buffer, offset, length, pos) { - if (!stream.tty || !stream.tty.ops.put_char) { - throw new FS.ErrnoError(60); - } - try { - for (var i = 0; i < length; i++) { - stream.tty.ops.put_char(stream.tty, buffer[offset + i]); + } + + + /** + * @param {number} ptr + * @param {number} value + * @param {string} type + */ + function setValue(ptr, value, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': HEAP8[((ptr)>>0)] = value; break; + case 'i8': HEAP8[((ptr)>>0)] = value; break; + case 'i16': HEAP16[((ptr)>>1)] = value; break; + case 'i32': HEAP32[((ptr)>>2)] = value; break; + case 'i64': abort('to do setValue(i64) use WASM_BIGINT'); + case 'float': HEAPF32[((ptr)>>2)] = value; break; + case 'double': HEAPF64[((ptr)>>3)] = value; break; + case '*': HEAPU32[((ptr)>>2)] = value; break; + default: abort(`invalid type for setValue: ${type}`); } - } catch (e) { - throw new FS.ErrnoError(29); - } - if (length) { - stream.node.timestamp = Date.now(); - } - return i; } - }, - default_tty_ops: { - get_char: function(tty) { - return FS_stdin_getChar(); - }, - put_char: function(tty, val) { - if (val === null || val === 10) { - out(UTF8ArrayToString(tty.output, 0)); - tty.output = []; - } else { - if (val != 0) tty.output.push(val); - } - }, - fsync: function(tty) { - if (tty.output && tty.output.length > 0) { - out(UTF8ArrayToString(tty.output, 0)); - tty.output = []; - } - }, - ioctl_tcgets: function(tty) { - return { - c_iflag: 25856, - c_oflag: 5, - c_cflag: 191, - c_lflag: 35387, - c_cc: [ 3, 28, 127, 21, 4, 0, 1, 0, 17, 19, 26, 0, 18, 15, 23, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] - }; + + var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined; + + /** + * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given + * array that contains uint8 values, returns a copy of that string as a + * Javascript String object. + * heapOrArray is either a regular array, or a JavaScript typed array view. + * @param {number} idx + * @param {number=} maxBytesToRead + * @return {string} + */ + var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => { + var endIdx = idx + maxBytesToRead; + var endPtr = idx; + // TextDecoder needs to know the byte length in advance, it doesn't stop on + // null terminator by itself. Also, use the length info to avoid running tiny + // strings through TextDecoder, since .subarray() allocates garbage. + // (As a tiny code save trick, compare endPtr against endIdx using a negation, + // so that undefined means Infinity) + while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr; + + if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { + return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr)); + } + var str = ''; + // If building with TextDecoder, we have already computed the string length + // above, so test loop end condition against that + while (idx < endPtr) { + // For UTF8 byte structure, see: + // http://en.wikipedia.org/wiki/UTF-8#Description + // https://www.ietf.org/rfc/rfc2279.txt + // https://tools.ietf.org/html/rfc3629 + var u0 = heapOrArray[idx++]; + if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } + var u1 = heapOrArray[idx++] & 63; + if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } + var u2 = heapOrArray[idx++] & 63; + if ((u0 & 0xF0) == 0xE0) { + u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; + } else { + u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63); + } + + if (u0 < 0x10000) { + str += String.fromCharCode(u0); + } else { + var ch = u0 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } + } + return str; + }; + + /** + * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the + * emscripten HEAP, returns a copy of that string as a Javascript String object. + * + * @param {number} ptr + * @param {number=} maxBytesToRead - An optional length that specifies the + * maximum number of bytes to read. You can omit this parameter to scan the + * string until the first 0 byte. If maxBytesToRead is passed, and the string + * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the + * string will cut short at that byte index (i.e. maxBytesToRead will not + * produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing + * frequent uses of UTF8ToString() with and without maxBytesToRead may throw + * JS JIT optimizations off, so it is worth to consider consistently using one + * @return {string} + */ + var UTF8ToString = (ptr, maxBytesToRead) => { + return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''; + }; + Module['UTF8ToString'] = UTF8ToString; + var ___assert_fail = (condition, filename, line, func) => { + abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']); + }; + + var ___call_sighandler = (fp, sig) => ((a1) => dynCall_vi.apply(null, [fp, a1]))(sig); + + var initRandomFill = () => { + if (typeof crypto == 'object' && typeof crypto['getRandomValues'] == 'function') { + // for modern web browsers + return (view) => crypto.getRandomValues(view); + } else + if (ENVIRONMENT_IS_NODE) { + // for nodejs with or without crypto support included + try { + var crypto_module = require('crypto'); + var randomFillSync = crypto_module['randomFillSync']; + if (randomFillSync) { + // nodejs with LTS crypto support + return (view) => crypto_module['randomFillSync'](view); + } + // very old nodejs with the original crypto API + var randomBytes = crypto_module['randomBytes']; + return (view) => ( + view.set(randomBytes(view.byteLength)), + // Return the original view to match modern native implementations. + view + ); + } catch (e) { + // nodejs doesn't have crypto support + } + } + // we couldn't find a proper implementation, as Math.random() is not suitable for /dev/random, see emscripten-core/emscripten/pull/7096 + abort("initRandomDevice"); + }; + var randomFill = (view) => { + // Lazily init on the first invocation. + return (randomFill = initRandomFill())(view); + }; + + var PATH = { + isAbs:(path) => path.charAt(0) === '/', + splitPath:(filename) => { + var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; + return splitPathRe.exec(filename).slice(1); + }, + normalizeArray:(parts, allowAboveRoot) => { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up; up--) { + parts.unshift('..'); + } + } + return parts; + }, + normalize:(path) => { + var isAbsolute = PATH.isAbs(path), + trailingSlash = path.substr(-1) === '/'; + // Normalize the path + path = PATH.normalizeArray(path.split('/').filter((p) => !!p), !isAbsolute).join('/'); + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + return (isAbsolute ? '/' : '') + path; + }, + dirname:(path) => { + var result = PATH.splitPath(path), + root = result[0], + dir = result[1]; + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + return root + dir; + }, + basename:(path) => { + // EMSCRIPTEN return '/'' for '/', not an empty string + if (path === '/') return '/'; + path = PATH.normalize(path); + path = path.replace(/\/$/, ""); + var lastSlash = path.lastIndexOf('/'); + if (lastSlash === -1) return path; + return path.substr(lastSlash+1); + }, + join:function() { + var paths = Array.prototype.slice.call(arguments); + return PATH.normalize(paths.join('/')); + }, + join2:(l, r) => { + return PATH.normalize(l + '/' + r); + }, + }; + + + var PATH_FS = { + resolve:function() { + var resolvedPath = '', + resolvedAbsolute = false; + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : FS.cwd(); + // Skip empty and invalid entries + if (typeof path != 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + return ''; // an invalid portion invalidates the whole thing + } + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = PATH.isAbs(path); + } + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter((p) => !!p), !resolvedAbsolute).join('/'); + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; + }, + relative:(from, to) => { + from = PATH_FS.resolve(from).substr(1); + to = PATH_FS.resolve(to).substr(1); + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + return outputParts.join('/'); + }, + }; + + + + var FS_stdin_getChar_buffer = []; + + var lengthBytesUTF8 = (str) => { + var len = 0; + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code + // unit, not a Unicode code point of the character! So decode + // UTF16->UTF32->UTF8. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + var c = str.charCodeAt(i); // possibly a lead surrogate + if (c <= 0x7F) { + len++; + } else if (c <= 0x7FF) { + len += 2; + } else if (c >= 0xD800 && c <= 0xDFFF) { + len += 4; ++i; + } else { + len += 3; + } + } + return len; + }; + Module['lengthBytesUTF8'] = lengthBytesUTF8; + + var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { + // Parameter maxBytesToWrite is not optional. Negative values, 0, null, + // undefined and false each don't write out any bytes. + if (!(maxBytesToWrite > 0)) + return 0; + + var startIdx = outIdx; + var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code + // unit, not a Unicode code point of the character! So decode + // UTF16->UTF32->UTF8. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description + // and https://www.ietf.org/rfc/rfc2279.txt + // and https://tools.ietf.org/html/rfc3629 + var u = str.charCodeAt(i); // possibly a lead surrogate + if (u >= 0xD800 && u <= 0xDFFF) { + var u1 = str.charCodeAt(++i); + u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF); + } + if (u <= 0x7F) { + if (outIdx >= endIdx) break; + heap[outIdx++] = u; + } else if (u <= 0x7FF) { + if (outIdx + 1 >= endIdx) break; + heap[outIdx++] = 0xC0 | (u >> 6); + heap[outIdx++] = 0x80 | (u & 63); + } else if (u <= 0xFFFF) { + if (outIdx + 2 >= endIdx) break; + heap[outIdx++] = 0xE0 | (u >> 12); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } else { + if (outIdx + 3 >= endIdx) break; + heap[outIdx++] = 0xF0 | (u >> 18); + heap[outIdx++] = 0x80 | ((u >> 12) & 63); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } + } + // Null-terminate the pointer to the buffer. + heap[outIdx] = 0; + return outIdx - startIdx; + }; + /** @type {function(string, boolean=, number=)} */ + function intArrayFromString(stringy, dontAddNull, length) { + var len = length > 0 ? length : lengthBytesUTF8(stringy)+1; + var u8array = new Array(len); + var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length); + if (dontAddNull) u8array.length = numBytesWritten; + return u8array; + } + var FS_stdin_getChar = () => { + if (!FS_stdin_getChar_buffer.length) { + var result = null; + if (ENVIRONMENT_IS_NODE) { + // we will read data by chunks of BUFSIZE + var BUFSIZE = 256; + var buf = Buffer.alloc(BUFSIZE); + var bytesRead = 0; + + // For some reason we must suppress a closure warning here, even though + // fd definitely exists on process.stdin, and is even the proper way to + // get the fd of stdin, + // https://github.com/nodejs/help/issues/2136#issuecomment-523649904 + // This started to happen after moving this logic out of library_tty.js, + // so it is related to the surrounding code in some unclear manner. + /** @suppress {missingProperties} */ + var fd = process.stdin.fd; + + try { + bytesRead = fs.readSync(fd, buf, 0, BUFSIZE, -1); + } catch(e) { + // Cross-platform differences: on Windows, reading EOF throws an exception, but on other OSes, + // reading EOF returns 0. Uniformize behavior by treating the EOF exception to return 0. + if (e.toString().includes('EOF')) bytesRead = 0; + else throw e; + } + + if (bytesRead > 0) { + result = buf.slice(0, bytesRead).toString('utf-8'); + } else { + result = null; + } + } else + if (typeof window != 'undefined' && + typeof window.prompt == 'function') { + // Browser. + result = window.prompt('Input: '); // returns null on cancel + if (result !== null) { + result += '\n'; + } + } else if (typeof readline == 'function') { + // Command line. + result = readline(); + if (result !== null) { + result += '\n'; + } + } + if (!result) { + return null; + } + FS_stdin_getChar_buffer = intArrayFromString(result, true); + } + return FS_stdin_getChar_buffer.shift(); + }; + var TTY = { + ttys:[], + init:function () { + // https://github.com/emscripten-core/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // currently, FS.init does not distinguish if process.stdin is a file or TTY + // // device, it always assumes it's a TTY device. because of this, we're forcing + // // process.stdin to UTF8 encoding to at least make stdin reading compatible + // // with text files until FS.init can be refactored. + // process.stdin.setEncoding('utf8'); + // } + }, + shutdown:function() { + // https://github.com/emscripten-core/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)? + // // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation + // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists? + // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle + // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call + // process.stdin.pause(); + // } + }, + register:function(dev, ops) { + TTY.ttys[dev] = { input: [], output: [], ops: ops }; + FS.registerDevice(dev, TTY.stream_ops); + }, + stream_ops:{ + open:function(stream) { + var tty = TTY.ttys[stream.node.rdev]; + if (!tty) { + throw new FS.ErrnoError(43); + } + stream.tty = tty; + stream.seekable = false; + }, + close:function(stream) { + // flush any pending line data + stream.tty.ops.fsync(stream.tty); + }, + fsync:function(stream) { + stream.tty.ops.fsync(stream.tty); + }, + read:function(stream, buffer, offset, length, pos /* ignored */) { + if (!stream.tty || !stream.tty.ops.get_char) { + throw new FS.ErrnoError(60); + } + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = stream.tty.ops.get_char(stream.tty); + } catch (e) { + throw new FS.ErrnoError(29); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(6); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + }, + write:function(stream, buffer, offset, length, pos) { + if (!stream.tty || !stream.tty.ops.put_char) { + throw new FS.ErrnoError(60); + } + try { + for (var i = 0; i < length; i++) { + stream.tty.ops.put_char(stream.tty, buffer[offset+i]); + } + } catch (e) { + throw new FS.ErrnoError(29); + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + }, }, - ioctl_tcsets: function(tty, optional_actions, data) { - return 0; + default_tty_ops:{ + get_char:function(tty) { + return FS_stdin_getChar(); + }, + put_char:function(tty, val) { + if (val === null || val === 10) { + out(UTF8ArrayToString(tty.output, 0)); + tty.output = []; + } else { + if (val != 0) tty.output.push(val); // val == 0 would cut text output off in the middle. + } + }, + fsync:function(tty) { + if (tty.output && tty.output.length > 0) { + out(UTF8ArrayToString(tty.output, 0)); + tty.output = []; + } + }, + ioctl_tcgets:function(tty) { + // typical setting + return { + c_iflag: 25856, + c_oflag: 5, + c_cflag: 191, + c_lflag: 35387, + c_cc: [ + 0x03, 0x1c, 0x7f, 0x15, 0x04, 0x00, 0x01, 0x00, 0x11, 0x13, 0x1a, 0x00, + 0x12, 0x0f, 0x17, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ] + }; + }, + ioctl_tcsets:function(tty, optional_actions, data) { + // currently just ignore + return 0; + }, + ioctl_tiocgwinsz:function(tty) { + return [24, 80]; + }, }, - ioctl_tiocgwinsz: function(tty) { - return [ 24, 80 ]; - } - }, - default_tty1_ops: { - put_char: function(tty, val) { - if (val === null || val === 10) { - err(UTF8ArrayToString(tty.output, 0)); - tty.output = []; - } else { - if (val != 0) tty.output.push(val); - } + default_tty1_ops:{ + put_char:function(tty, val) { + if (val === null || val === 10) { + err(UTF8ArrayToString(tty.output, 0)); + tty.output = []; + } else { + if (val != 0) tty.output.push(val); + } + }, + fsync:function(tty) { + if (tty.output && tty.output.length > 0) { + err(UTF8ArrayToString(tty.output, 0)); + tty.output = []; + } + }, }, - fsync: function(tty) { - if (tty.output && tty.output.length > 0) { - err(UTF8ArrayToString(tty.output, 0)); - tty.output = []; - } - } - } -}; - -var zeroMemory = (address, size) => { - HEAPU8.fill(0, address, address + size); - return address; -}; - -var alignMemory = (size, alignment) => Math.ceil(size / alignment) * alignment; - -var mmapAlloc = size => { - size = alignMemory(size, 65536); - var ptr = _emscripten_builtin_memalign(65536, size); - if (!ptr) return 0; - return zeroMemory(ptr, size); -}; - -var MEMFS = { - ops_table: null, - mount(mount) { - return MEMFS.createNode(null, "/", 16384 | 511, 0); - }, - createNode(parent, name, mode, dev) { - if (FS.isBlkdev(mode) || FS.isFIFO(mode)) { - throw new FS.ErrnoError(63); - } - if (!MEMFS.ops_table) { - MEMFS.ops_table = { - dir: { - node: { - getattr: MEMFS.node_ops.getattr, - setattr: MEMFS.node_ops.setattr, - lookup: MEMFS.node_ops.lookup, - mknod: MEMFS.node_ops.mknod, - rename: MEMFS.node_ops.rename, - unlink: MEMFS.node_ops.unlink, - rmdir: MEMFS.node_ops.rmdir, - readdir: MEMFS.node_ops.readdir, - symlink: MEMFS.node_ops.symlink - }, - stream: { - llseek: MEMFS.stream_ops.llseek - } - }, - file: { - node: { - getattr: MEMFS.node_ops.getattr, - setattr: MEMFS.node_ops.setattr - }, - stream: { - llseek: MEMFS.stream_ops.llseek, - read: MEMFS.stream_ops.read, - write: MEMFS.stream_ops.write, - allocate: MEMFS.stream_ops.allocate, - mmap: MEMFS.stream_ops.mmap, - msync: MEMFS.stream_ops.msync - } - }, - link: { - node: { - getattr: MEMFS.node_ops.getattr, - setattr: MEMFS.node_ops.setattr, - readlink: MEMFS.node_ops.readlink - }, - stream: {} - }, - chrdev: { - node: { - getattr: MEMFS.node_ops.getattr, - setattr: MEMFS.node_ops.setattr - }, - stream: FS.chrdev_stream_ops - } - }; - } - var node = FS.createNode(parent, name, mode, dev); - if (FS.isDir(node.mode)) { - node.node_ops = MEMFS.ops_table.dir.node; - node.stream_ops = MEMFS.ops_table.dir.stream; - node.contents = {}; - } else if (FS.isFile(node.mode)) { - node.node_ops = MEMFS.ops_table.file.node; - node.stream_ops = MEMFS.ops_table.file.stream; - node.usedBytes = 0; - node.contents = null; - } else if (FS.isLink(node.mode)) { - node.node_ops = MEMFS.ops_table.link.node; - node.stream_ops = MEMFS.ops_table.link.stream; - } else if (FS.isChrdev(node.mode)) { - node.node_ops = MEMFS.ops_table.chrdev.node; - node.stream_ops = MEMFS.ops_table.chrdev.stream; - } - node.timestamp = Date.now(); - if (parent) { - parent.contents[name] = node; - parent.timestamp = node.timestamp; - } - return node; - }, - getFileDataAsTypedArray(node) { - if (!node.contents) return new Uint8Array(0); - if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes); - return new Uint8Array(node.contents); - }, - expandFileStorage(node, newCapacity) { - var prevCapacity = node.contents ? node.contents.length : 0; - if (prevCapacity >= newCapacity) return; - var CAPACITY_DOUBLING_MAX = 1024 * 1024; - newCapacity = Math.max(newCapacity, prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125) >>> 0); - if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); - var oldContents = node.contents; - node.contents = new Uint8Array(newCapacity); - if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); - }, - resizeFileStorage(node, newSize) { - if (node.usedBytes == newSize) return; - if (newSize == 0) { - node.contents = null; - node.usedBytes = 0; - } else { - var oldContents = node.contents; - node.contents = new Uint8Array(newSize); - if (oldContents) { - node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); - } - node.usedBytes = newSize; - } - }, - node_ops: { + }; + + + var zeroMemory = (address, size) => { + HEAPU8.fill(0, address, address + size); + return address; + }; + + var alignMemory = (size, alignment) => { + return Math.ceil(size / alignment) * alignment; + }; + var mmapAlloc = (size) => { + size = alignMemory(size, 65536); + var ptr = _emscripten_builtin_memalign(65536, size); + if (!ptr) return 0; + return zeroMemory(ptr, size); + }; + var MEMFS = { + ops_table:null, + mount(mount) { + return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + }, + createNode(parent, name, mode, dev) { + if (FS.isBlkdev(mode) || FS.isFIFO(mode)) { + // no supported + throw new FS.ErrnoError(63); + } + if (!MEMFS.ops_table) { + MEMFS.ops_table = { + dir: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr, + lookup: MEMFS.node_ops.lookup, + mknod: MEMFS.node_ops.mknod, + rename: MEMFS.node_ops.rename, + unlink: MEMFS.node_ops.unlink, + rmdir: MEMFS.node_ops.rmdir, + readdir: MEMFS.node_ops.readdir, + symlink: MEMFS.node_ops.symlink + }, + stream: { + llseek: MEMFS.stream_ops.llseek + } + }, + file: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr + }, + stream: { + llseek: MEMFS.stream_ops.llseek, + read: MEMFS.stream_ops.read, + write: MEMFS.stream_ops.write, + allocate: MEMFS.stream_ops.allocate, + mmap: MEMFS.stream_ops.mmap, + msync: MEMFS.stream_ops.msync + } + }, + link: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr, + readlink: MEMFS.node_ops.readlink + }, + stream: {} + }, + chrdev: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr + }, + stream: FS.chrdev_stream_ops + } + }; + } + var node = FS.createNode(parent, name, mode, dev); + if (FS.isDir(node.mode)) { + node.node_ops = MEMFS.ops_table.dir.node; + node.stream_ops = MEMFS.ops_table.dir.stream; + node.contents = {}; + } else if (FS.isFile(node.mode)) { + node.node_ops = MEMFS.ops_table.file.node; + node.stream_ops = MEMFS.ops_table.file.stream; + node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity. + // When the byte data of the file is populated, this will point to either a typed array, or a normal JS array. Typed arrays are preferred + // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size + // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme. + node.contents = null; + } else if (FS.isLink(node.mode)) { + node.node_ops = MEMFS.ops_table.link.node; + node.stream_ops = MEMFS.ops_table.link.stream; + } else if (FS.isChrdev(node.mode)) { + node.node_ops = MEMFS.ops_table.chrdev.node; + node.stream_ops = MEMFS.ops_table.chrdev.stream; + } + node.timestamp = Date.now(); + // add the new node to the parent + if (parent) { + parent.contents[name] = node; + parent.timestamp = node.timestamp; + } + return node; + }, + getFileDataAsTypedArray(node) { + if (!node.contents) return new Uint8Array(0); + if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes. + return new Uint8Array(node.contents); + }, + expandFileStorage(node, newCapacity) { + var prevCapacity = node.contents ? node.contents.length : 0; + if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough. + // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity. + // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to + // avoid overshooting the allocation cap by a very large margin. + var CAPACITY_DOUBLING_MAX = 1024 * 1024; + newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0); + if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding. + var oldContents = node.contents; + node.contents = new Uint8Array(newCapacity); // Allocate new storage. + if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); // Copy old data over to the new storage. + }, + resizeFileStorage(node, newSize) { + if (node.usedBytes == newSize) return; + if (newSize == 0) { + node.contents = null; // Fully decommit when requesting a resize to zero. + node.usedBytes = 0; + } else { + var oldContents = node.contents; + node.contents = new Uint8Array(newSize); // Allocate new storage. + if (oldContents) { + node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage. + } + node.usedBytes = newSize; + } + }, + node_ops:{ getattr(node) { - var attr = {}; - attr.dev = FS.isChrdev(node.mode) ? node.id : 1; - attr.ino = node.id; - attr.mode = node.mode; - attr.nlink = 1; - attr.uid = 0; - attr.gid = 0; - attr.rdev = node.rdev; - if (FS.isDir(node.mode)) { - attr.size = 4096; - } else if (FS.isFile(node.mode)) { - attr.size = node.usedBytes; - } else if (FS.isLink(node.mode)) { - attr.size = node.link.length; - } else { - attr.size = 0; - } - attr.atime = new Date(node.timestamp); - attr.mtime = new Date(node.timestamp); - attr.ctime = new Date(node.timestamp); - attr.blksize = 4096; - attr.blocks = Math.ceil(attr.size / attr.blksize); - return attr; - }, + var attr = {}; + // device numbers reuse inode numbers. + attr.dev = FS.isChrdev(node.mode) ? node.id : 1; + attr.ino = node.id; + attr.mode = node.mode; + attr.nlink = 1; + attr.uid = 0; + attr.gid = 0; + attr.rdev = node.rdev; + if (FS.isDir(node.mode)) { + attr.size = 4096; + } else if (FS.isFile(node.mode)) { + attr.size = node.usedBytes; + } else if (FS.isLink(node.mode)) { + attr.size = node.link.length; + } else { + attr.size = 0; + } + attr.atime = new Date(node.timestamp); + attr.mtime = new Date(node.timestamp); + attr.ctime = new Date(node.timestamp); + // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize), + // but this is not required by the standard. + attr.blksize = 4096; + attr.blocks = Math.ceil(attr.size / attr.blksize); + return attr; + }, setattr(node, attr) { - if (attr.mode !== undefined) { - node.mode = attr.mode; - } - if (attr.timestamp !== undefined) { - node.timestamp = attr.timestamp; - } - if (attr.size !== undefined) { - MEMFS.resizeFileStorage(node, attr.size); - } - }, + if (attr.mode !== undefined) { + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + node.timestamp = attr.timestamp; + } + if (attr.size !== undefined) { + MEMFS.resizeFileStorage(node, attr.size); + } + }, lookup(parent, name) { - throw FS.genericErrors[44]; - }, + throw FS.genericErrors[44]; + }, mknod(parent, name, mode, dev) { - return MEMFS.createNode(parent, name, mode, dev); - }, + return MEMFS.createNode(parent, name, mode, dev); + }, rename(old_node, new_dir, new_name) { - if (FS.isDir(old_node.mode)) { - var new_node; - try { - new_node = FS.lookupNode(new_dir, new_name); - } catch (e) {} - if (new_node) { - for (var i in new_node.contents) { - throw new FS.ErrnoError(55); - } - } - } - delete old_node.parent.contents[old_node.name]; - old_node.parent.timestamp = Date.now(); - old_node.name = new_name; - new_dir.contents[new_name] = old_node; - new_dir.timestamp = old_node.parent.timestamp; - old_node.parent = new_dir; - }, + // if we're overwriting a directory at new_name, make sure it's empty. + if (FS.isDir(old_node.mode)) { + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + } + if (new_node) { + for (var i in new_node.contents) { + throw new FS.ErrnoError(55); + } + } + } + // do the internal rewiring + delete old_node.parent.contents[old_node.name]; + old_node.parent.timestamp = Date.now() + old_node.name = new_name; + new_dir.contents[new_name] = old_node; + new_dir.timestamp = old_node.parent.timestamp; + old_node.parent = new_dir; + }, unlink(parent, name) { - delete parent.contents[name]; - parent.timestamp = Date.now(); - }, + delete parent.contents[name]; + parent.timestamp = Date.now(); + }, rmdir(parent, name) { - var node = FS.lookupNode(parent, name); - for (var i in node.contents) { - throw new FS.ErrnoError(55); - } - delete parent.contents[name]; - parent.timestamp = Date.now(); - }, + var node = FS.lookupNode(parent, name); + for (var i in node.contents) { + throw new FS.ErrnoError(55); + } + delete parent.contents[name]; + parent.timestamp = Date.now(); + }, readdir(node) { - var entries = [ ".", ".." ]; - for (var key in node.contents) { - if (!node.contents.hasOwnProperty(key)) { - continue; - } - entries.push(key); - } - return entries; - }, + var entries = ['.', '..']; + for (var key in node.contents) { + if (!node.contents.hasOwnProperty(key)) { + continue; + } + entries.push(key); + } + return entries; + }, symlink(parent, newname, oldpath) { - var node = MEMFS.createNode(parent, newname, 511 | 40960, 0); - node.link = oldpath; - return node; - }, + var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0); + node.link = oldpath; + return node; + }, readlink(node) { - if (!FS.isLink(node.mode)) { - throw new FS.ErrnoError(28); - } - return node.link; - } - }, - stream_ops: { - read(stream, buffer, offset, length, position) { - var contents = stream.node.contents; - if (position >= stream.node.usedBytes) return 0; - var size = Math.min(stream.node.usedBytes - position, length); - if (size > 8 && contents.subarray) { - buffer.set(contents.subarray(position, position + size), offset); - } else { - for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i]; - } - return size; + if (!FS.isLink(node.mode)) { + throw new FS.ErrnoError(28); + } + return node.link; + }, }, + stream_ops:{ + read(stream, buffer, offset, length, position) { + var contents = stream.node.contents; + if (position >= stream.node.usedBytes) return 0; + var size = Math.min(stream.node.usedBytes - position, length); + if (size > 8 && contents.subarray) { // non-trivial, and typed array + buffer.set(contents.subarray(position, position + size), offset); + } else { + for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i]; + } + return size; + }, write(stream, buffer, offset, length, position, canOwn) { - if (buffer.buffer === HEAP8.buffer) { - canOwn = false; - } - if (!length) return 0; - var node = stream.node; - node.timestamp = Date.now(); - if (buffer.subarray && (!node.contents || node.contents.subarray)) { - if (canOwn) { - node.contents = buffer.subarray(offset, offset + length); - node.usedBytes = length; - return length; - } else if (node.usedBytes === 0 && position === 0) { - node.contents = buffer.slice(offset, offset + length); - node.usedBytes = length; - return length; - } else if (position + length <= node.usedBytes) { - node.contents.set(buffer.subarray(offset, offset + length), position); - return length; - } - } - MEMFS.expandFileStorage(node, position + length); - if (node.contents.subarray && buffer.subarray) { - node.contents.set(buffer.subarray(offset, offset + length), position); - } else { - for (var i = 0; i < length; i++) { - node.contents[position + i] = buffer[offset + i]; - } - } - node.usedBytes = Math.max(node.usedBytes, position + length); - return length; - }, + // If the buffer is located in main memory (HEAP), and if + // memory can grow, we can't hold on to references of the + // memory buffer, as they may get invalidated. That means we + // need to do copy its contents. + if (buffer.buffer === HEAP8.buffer) { + canOwn = false; + } + + if (!length) return 0; + var node = stream.node; + node.timestamp = Date.now(); + + if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array? + if (canOwn) { + node.contents = buffer.subarray(offset, offset + length); + node.usedBytes = length; + return length; + } else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data. + node.contents = buffer.slice(offset, offset + length); + node.usedBytes = length; + return length; + } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file? + node.contents.set(buffer.subarray(offset, offset + length), position); + return length; + } + } + + // Appending to an existing file and we need to reallocate, or source data did not come as a typed array. + MEMFS.expandFileStorage(node, position+length); + if (node.contents.subarray && buffer.subarray) { + // Use typed array write which is available. + node.contents.set(buffer.subarray(offset, offset + length), position); + } else { + for (var i = 0; i < length; i++) { + node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not. + } + } + node.usedBytes = Math.max(node.usedBytes, position + length); + return length; + }, llseek(stream, offset, whence) { - var position = offset; - if (whence === 1) { - position += stream.position; - } else if (whence === 2) { - if (FS.isFile(stream.node.mode)) { - position += stream.node.usedBytes; - } - } - if (position < 0) { - throw new FS.ErrnoError(28); - } - return position; - }, + var position = offset; + if (whence === 1) { + position += stream.position; + } else if (whence === 2) { + if (FS.isFile(stream.node.mode)) { + position += stream.node.usedBytes; + } + } + if (position < 0) { + throw new FS.ErrnoError(28); + } + return position; + }, allocate(stream, offset, length) { - MEMFS.expandFileStorage(stream.node, offset + length); - stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length); - }, + MEMFS.expandFileStorage(stream.node, offset + length); + stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length); + }, mmap(stream, length, position, prot, flags) { - if (!FS.isFile(stream.node.mode)) { - throw new FS.ErrnoError(43); - } - var ptr; - var allocated; - var contents = stream.node.contents; - if (!(flags & 2) && contents.buffer === HEAP8.buffer) { - allocated = false; - ptr = contents.byteOffset; - } else { - if (position > 0 || position + length < contents.length) { - if (contents.subarray) { - contents = contents.subarray(position, position + length); - } else { - contents = Array.prototype.slice.call(contents, position, position + length); - } - } - allocated = true; - ptr = mmapAlloc(length); - if (!ptr) { - throw new FS.ErrnoError(48); - } - HEAP8.set(contents, ptr); - } - return { - ptr: ptr, - allocated: allocated - }; - }, + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(43); + } + var ptr; + var allocated; + var contents = stream.node.contents; + // Only make a new copy when MAP_PRIVATE is specified. + if (!(flags & 2) && contents.buffer === HEAP8.buffer) { + // We can't emulate MAP_SHARED when the file is not backed by the + // buffer we're mapping to (e.g. the HEAP buffer). + allocated = false; + ptr = contents.byteOffset; + } else { + // Try to avoid unnecessary slices. + if (position > 0 || position + length < contents.length) { + if (contents.subarray) { + contents = contents.subarray(position, position + length); + } else { + contents = Array.prototype.slice.call(contents, position, position + length); + } + } + allocated = true; + ptr = mmapAlloc(length); + if (!ptr) { + throw new FS.ErrnoError(48); + } + HEAP8.set(contents, ptr); + } + return { ptr, allocated }; + }, msync(stream, buffer, offset, length, mmapFlags) { - MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false); - return 0; - } - } -}; - -var asyncLoad = (url, onload, onerror, noRunDep) => { - var dep = !noRunDep ? getUniqueRunDependency(`al ${url}`) : ""; - readAsync(url, (arrayBuffer => { - assert(arrayBuffer, `Loading data file "${url}" failed (no arrayBuffer).`); - onload(new Uint8Array(arrayBuffer)); - if (dep) removeRunDependency(dep); - }), (event => { - if (onerror) { - onerror(); - } else { - throw `Loading data file "${url}" failed.`; - } - })); - if (dep) addRunDependency(dep); -}; - -var preloadPlugins = Module["preloadPlugins"] || []; - -function FS_handledByPreloadPlugin(byteArray, fullname, finish, onerror) { - if (typeof Browser != "undefined") Browser.init(); - var handled = false; - preloadPlugins.forEach((function(plugin) { - if (handled) return; - if (plugin["canHandle"](fullname)) { - plugin["handle"](byteArray, fullname, finish, onerror); - handled = true; - } - })); - return handled; -} - -function FS_createPreloadedFile(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) { - var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent; - var dep = getUniqueRunDependency(`cp ${fullname}`); - function processData(byteArray) { - function finish(byteArray) { - if (preFinish) preFinish(); - if (!dontCreateFile) { - FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); - } - if (onload) onload(); - removeRunDependency(dep); - } - if (FS_handledByPreloadPlugin(byteArray, fullname, finish, (() => { - if (onerror) onerror(); - removeRunDependency(dep); - }))) { - return; - } - finish(byteArray); - } - addRunDependency(dep); - if (typeof url == "string") { - asyncLoad(url, (byteArray => processData(byteArray)), onerror); - } else { - processData(url); - } -} - -function FS_modeStringToFlags(str) { - var flagModes = { - "r": 0, - "r+": 2, - "w": 512 | 64 | 1, - "w+": 512 | 64 | 2, - "a": 1024 | 64 | 1, - "a+": 1024 | 64 | 2 - }; - var flags = flagModes[str]; - if (typeof flags == "undefined") { - throw new Error(`Unknown file open mode: ${str}`); - } - return flags; -} - -function FS_getMode(canRead, canWrite) { - var mode = 0; - if (canRead) mode |= 292 | 73; - if (canWrite) mode |= 146; - return mode; -} - -var ERRNO_CODES = {}; - -var NODEFS = { - isWindows: false, - staticInit: () => { - NODEFS.isWindows = !!process.platform.match(/^win/); - var flags = process.binding("constants"); - if (flags["fs"]) { - flags = flags["fs"]; - } - NODEFS.flagsForNodeMap = { - 1024: flags["O_APPEND"], - 64: flags["O_CREAT"], - 128: flags["O_EXCL"], - 256: flags["O_NOCTTY"], - 0: flags["O_RDONLY"], - 2: flags["O_RDWR"], - 4096: flags["O_SYNC"], - 512: flags["O_TRUNC"], - 1: flags["O_WRONLY"], - 131072: flags["O_NOFOLLOW"] - }; - }, - convertNodeCode: e => { - var code = e.code; - return ERRNO_CODES[code]; - }, - mount: mount => NODEFS.createNode(null, "/", NODEFS.getMode(mount.opts.root), 0), - createNode: (parent, name, mode, dev) => { - if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) { - throw new FS.ErrnoError(28); - } - var node = FS.createNode(parent, name, mode); - node.node_ops = NODEFS.node_ops; - node.stream_ops = NODEFS.stream_ops; - return node; - }, - getMode: path => { - var stat; - try { - stat = fs.lstatSync(path); - if (NODEFS.isWindows) { - stat.mode = stat.mode | (stat.mode & 292) >> 2; - } - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); - } - return stat.mode; - }, - realPath: node => { - var parts = []; - while (node.parent !== node) { - parts.push(node.name); - node = node.parent; - } - parts.push(node.mount.opts.root); - parts.reverse(); - return PATH.join.apply(null, parts); - }, - flagsForNode: flags => { - flags &= ~2097152; - flags &= ~2048; - flags &= ~32768; - flags &= ~524288; - flags &= ~65536; - var newFlags = 0; - for (var k in NODEFS.flagsForNodeMap) { - if (flags & k) { - newFlags |= NODEFS.flagsForNodeMap[k]; - flags ^= k; - } - } - if (flags) { - throw new FS.ErrnoError(28); - } - return newFlags; - }, - node_ops: { - getattr: node => { - var path = NODEFS.realPath(node); - var stat; - try { - stat = fs.lstatSync(path); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); - } - if (NODEFS.isWindows && !stat.blksize) { - stat.blksize = 4096; - } - if (NODEFS.isWindows && !stat.blocks) { - stat.blocks = (stat.size + stat.blksize - 1) / stat.blksize | 0; - } - return { - dev: stat.dev, - ino: stat.ino, - mode: stat.mode, - nlink: stat.nlink, - uid: stat.uid, - gid: stat.gid, - rdev: stat.rdev, - size: stat.size, - atime: stat.atime, - mtime: stat.mtime, - ctime: stat.ctime, - blksize: stat.blksize, - blocks: stat.blocks - }; - }, - setattr: (node, attr) => { - var path = NODEFS.realPath(node); - try { - if (attr.mode !== undefined) { - fs.chmodSync(path, attr.mode); - node.mode = attr.mode; - } - if (attr.timestamp !== undefined) { - var date = new Date(attr.timestamp); - fs.utimesSync(path, date, date); - } - if (attr.size !== undefined) { - fs.truncateSync(path, attr.size); - } - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); - } - }, - lookup: (parent, name) => { - var path = PATH.join2(NODEFS.realPath(parent), name); - var mode = NODEFS.getMode(path); - return NODEFS.createNode(parent, name, mode); + MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false); + // should we check if bytesWritten and length are the same? + return 0; + }, }, - mknod: (parent, name, mode, dev) => { - var node = NODEFS.createNode(parent, name, mode, dev); - var path = NODEFS.realPath(node); - try { - if (FS.isDir(node.mode)) { - fs.mkdirSync(path, node.mode); - } else { - fs.writeFileSync(path, "", { - mode: node.mode - }); + }; + + /** @param {boolean=} noRunDep */ + var asyncLoad = (url, onload, onerror, noRunDep) => { + var dep = !noRunDep ? getUniqueRunDependency(`al ${url}`) : ''; + readAsync(url, (arrayBuffer) => { + assert(arrayBuffer, `Loading data file "${url}" failed (no arrayBuffer).`); + onload(new Uint8Array(arrayBuffer)); + if (dep) removeRunDependency(dep); + }, (event) => { + if (onerror) { + onerror(); + } else { + throw `Loading data file "${url}" failed.`; + } + }); + if (dep) addRunDependency(dep); + }; + + + var preloadPlugins = Module['preloadPlugins'] || []; + function FS_handledByPreloadPlugin(byteArray, fullname, finish, onerror) { + // Ensure plugins are ready. + if (typeof Browser != 'undefined') Browser.init(); + + var handled = false; + preloadPlugins.forEach(function(plugin) { + if (handled) return; + if (plugin['canHandle'](fullname)) { + plugin['handle'](byteArray, fullname, finish, onerror); + handled = true; + } + }); + return handled; } - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); - } - return node; - }, - rename: (oldNode, newDir, newName) => { - var oldPath = NODEFS.realPath(oldNode); - var newPath = PATH.join2(NODEFS.realPath(newDir), newName); - try { - fs.renameSync(oldPath, newPath); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); - } - oldNode.name = newName; - }, - unlink: (parent, name) => { - var path = PATH.join2(NODEFS.realPath(parent), name); - try { - fs.unlinkSync(path); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); - } - }, - rmdir: (parent, name) => { - var path = PATH.join2(NODEFS.realPath(parent), name); - try { - fs.rmdirSync(path); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); - } - }, - readdir: node => { - var path = NODEFS.realPath(node); - try { - return fs.readdirSync(path); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); - } - }, - symlink: (parent, newName, oldPath) => { - var newPath = PATH.join2(NODEFS.realPath(parent), newName); - try { - fs.symlinkSync(oldPath, newPath); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); - } - }, - readlink: node => { - var path = NODEFS.realPath(node); - try { - path = fs.readlinkSync(path); - path = nodePath.relative(nodePath.resolve(node.mount.opts.root), path); - return path; - } catch (e) { - if (!e.code) throw e; - if (e.code === "UNKNOWN") throw new FS.ErrnoError(28); - throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); - } - } - }, - stream_ops: { - open: stream => { - var path = NODEFS.realPath(stream.node); - try { - if (FS.isFile(stream.node.mode)) { - stream.nfd = fs.openSync(path, NODEFS.flagsForNode(stream.flags)); + function FS_createPreloadedFile(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) { + // TODO we should allow people to just pass in a complete filename instead + // of parent and name being that we just join them anyways + var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent; + var dep = getUniqueRunDependency(`cp ${fullname}`); // might have several active requests for the same fullname + function processData(byteArray) { + function finish(byteArray) { + if (preFinish) preFinish(); + if (!dontCreateFile) { + FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); + } + if (onload) onload(); + removeRunDependency(dep); + } + if (FS_handledByPreloadPlugin(byteArray, fullname, finish, () => { + if (onerror) onerror(); + removeRunDependency(dep); + })) { + return; + } + finish(byteArray); + } + addRunDependency(dep); + if (typeof url == 'string') { + asyncLoad(url, (byteArray) => processData(byteArray), onerror); + } else { + processData(url); + } } - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); - } - }, - close: stream => { - try { - if (FS.isFile(stream.node.mode) && stream.nfd) { - fs.closeSync(stream.nfd); + + function FS_modeStringToFlags(str) { + var flagModes = { + 'r': 0, + 'r+': 2, + 'w': 512 | 64 | 1, + 'w+': 512 | 64 | 2, + 'a': 1024 | 64 | 1, + 'a+': 1024 | 64 | 2, + }; + var flags = flagModes[str]; + if (typeof flags == 'undefined') { + throw new Error(`Unknown file open mode: ${str}`); + } + return flags; } - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); - } - }, - read: (stream, buffer, offset, length, position) => { - if (length === 0) return 0; - try { - return fs.readSync(stream.nfd, Buffer.from(buffer.buffer), offset, length, position); - } catch (e) { - throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); - } - }, - write: (stream, buffer, offset, length, position) => { - try { - return fs.writeSync(stream.nfd, Buffer.from(buffer.buffer), offset, length, position); - } catch (e) { - throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); - } - }, - llseek: (stream, offset, whence) => { - var position = offset; - if (whence === 1) { - position += stream.position; - } else if (whence === 2) { - if (FS.isFile(stream.node.mode)) { - try { - var stat = fs.fstatSync(stream.nfd); - position += stat.size; - } catch (e) { - throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); - } + + function FS_getMode(canRead, canWrite) { + var mode = 0; + if (canRead) mode |= 292 | 73; + if (canWrite) mode |= 146; + return mode; } - } - if (position < 0) { - throw new FS.ErrnoError(28); - } - return position; + + + + + + + var ERRNO_CODES = { + }; + + var NODEFS = { + isWindows:false, + staticInit:() => { + NODEFS.isWindows = !!process.platform.match(/^win/); + var flags = process.binding("constants"); + // Node.js 4 compatibility: it has no namespaces for constants + if (flags["fs"]) { + flags = flags["fs"]; + } + NODEFS.flagsForNodeMap = { + "1024": flags["O_APPEND"], + "64": flags["O_CREAT"], + "128": flags["O_EXCL"], + "256": flags["O_NOCTTY"], + "0": flags["O_RDONLY"], + "2": flags["O_RDWR"], + "4096": flags["O_SYNC"], + "512": flags["O_TRUNC"], + "1": flags["O_WRONLY"], + "131072": flags["O_NOFOLLOW"], + }; + }, + convertNodeCode:(e) => { + var code = e.code; + return ERRNO_CODES[code]; + }, + mount:(mount) => { + return NODEFS.createNode(null, '/', NODEFS.getMode(mount.opts.root), 0); + }, + createNode:(parent, name, mode, dev) => { + if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) { + throw new FS.ErrnoError(28); + } + var node = FS.createNode(parent, name, mode); + node.node_ops = NODEFS.node_ops; + node.stream_ops = NODEFS.stream_ops; + return node; + }, + getMode:(path) => { + var stat; + try { + stat = fs.lstatSync(path); + if (NODEFS.isWindows) { + // Node.js on Windows never represents permission bit 'x', so + // propagate read bits to execute bits + stat.mode = stat.mode | ((stat.mode & 292) >> 2); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); + } + return stat.mode; + }, + realPath:(node) => { + var parts = []; + while (node.parent !== node) { + parts.push(node.name); + node = node.parent; + } + parts.push(node.mount.opts.root); + parts.reverse(); + return PATH.join.apply(null, parts); + }, + flagsForNode:(flags) => { + flags &= ~2097152; // Ignore this flag from musl, otherwise node.js fails to open the file. + flags &= ~2048; // Ignore this flag from musl, otherwise node.js fails to open the file. + flags &= ~32768; // Ignore this flag from musl, otherwise node.js fails to open the file. + flags &= ~524288; // Some applications may pass it; it makes no sense for a single process. + flags &= ~65536; // Node.js doesn't need this passed in, it errors. + var newFlags = 0; + for (var k in NODEFS.flagsForNodeMap) { + if (flags & k) { + newFlags |= NODEFS.flagsForNodeMap[k]; + flags ^= k; + } + } + if (flags) { + throw new FS.ErrnoError(28); + } + return newFlags; + }, + node_ops:{ + getattr:(node) => { + var path = NODEFS.realPath(node); + var stat; + try { + stat = fs.lstatSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); + } + // node.js v0.10.20 doesn't report blksize and blocks on Windows. Fake them with default blksize of 4096. + // See http://support.microsoft.com/kb/140365 + if (NODEFS.isWindows && !stat.blksize) { + stat.blksize = 4096; + } + if (NODEFS.isWindows && !stat.blocks) { + stat.blocks = (stat.size+stat.blksize-1)/stat.blksize|0; + } + return { + dev: stat.dev, + ino: stat.ino, + mode: stat.mode, + nlink: stat.nlink, + uid: stat.uid, + gid: stat.gid, + rdev: stat.rdev, + size: stat.size, + atime: stat.atime, + mtime: stat.mtime, + ctime: stat.ctime, + blksize: stat.blksize, + blocks: stat.blocks + }; + }, + setattr:(node, attr) => { + var path = NODEFS.realPath(node); + try { + if (attr.mode !== undefined) { + fs.chmodSync(path, attr.mode); + // update the common node structure mode as well + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + var date = new Date(attr.timestamp); + fs.utimesSync(path, date, date); + } + if (attr.size !== undefined) { + fs.truncateSync(path, attr.size); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); + } + }, + lookup:(parent, name) => { + var path = PATH.join2(NODEFS.realPath(parent), name); + var mode = NODEFS.getMode(path); + return NODEFS.createNode(parent, name, mode); + }, + mknod:(parent, name, mode, dev) => { + var node = NODEFS.createNode(parent, name, mode, dev); + // create the backing node for this in the fs root as well + var path = NODEFS.realPath(node); + try { + if (FS.isDir(node.mode)) { + fs.mkdirSync(path, node.mode); + } else { + fs.writeFileSync(path, '', { mode: node.mode }); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); + } + return node; + }, + rename:(oldNode, newDir, newName) => { + var oldPath = NODEFS.realPath(oldNode); + var newPath = PATH.join2(NODEFS.realPath(newDir), newName); + try { + fs.renameSync(oldPath, newPath); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); + } + oldNode.name = newName; + }, + unlink:(parent, name) => { + var path = PATH.join2(NODEFS.realPath(parent), name); + try { + fs.unlinkSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); + } + }, + rmdir:(parent, name) => { + var path = PATH.join2(NODEFS.realPath(parent), name); + try { + fs.rmdirSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); + } + }, + readdir:(node) => { + var path = NODEFS.realPath(node); + try { + return fs.readdirSync(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); + } + }, + symlink:(parent, newName, oldPath) => { + var newPath = PATH.join2(NODEFS.realPath(parent), newName); + try { + fs.symlinkSync(oldPath, newPath); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); + } + }, + readlink:(node) => { + var path = NODEFS.realPath(node); + try { + path = fs.readlinkSync(path); + path = nodePath.relative(nodePath.resolve(node.mount.opts.root), path); + return path; + } catch (e) { + if (!e.code) throw e; + // node under windows can return code 'UNKNOWN' here: + // https://github.com/emscripten-core/emscripten/issues/15468 + if (e.code === 'UNKNOWN') throw new FS.ErrnoError(28); + throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); + } + }, }, - mmap: (stream, length, position, prot, flags) => { - if (!FS.isFile(stream.node.mode)) { - throw new FS.ErrnoError(43); - } - var ptr = mmapAlloc(length); - NODEFS.stream_ops.read(stream, HEAP8, ptr, length, position); - return { - ptr: ptr, - allocated: true - }; + stream_ops:{ + open:(stream) => { + var path = NODEFS.realPath(stream.node); + try { + if (FS.isFile(stream.node.mode)) { + stream.nfd = fs.openSync(path, NODEFS.flagsForNode(stream.flags)); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); + } + }, + close:(stream) => { + try { + if (FS.isFile(stream.node.mode) && stream.nfd) { + fs.closeSync(stream.nfd); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); + } + }, + read:(stream, buffer, offset, length, position) => { + // Node.js < 6 compatibility: node errors on 0 length reads + if (length === 0) return 0; + try { + return fs.readSync(stream.nfd, Buffer.from(buffer.buffer), offset, length, position); + } catch (e) { + throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); + } + }, + write:(stream, buffer, offset, length, position) => { + try { + return fs.writeSync(stream.nfd, Buffer.from(buffer.buffer), offset, length, position); + } catch (e) { + throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); + } + }, + llseek:(stream, offset, whence) => { + var position = offset; + if (whence === 1) { + position += stream.position; + } else if (whence === 2) { + if (FS.isFile(stream.node.mode)) { + try { + var stat = fs.fstatSync(stream.nfd); + position += stat.size; + } catch (e) { + throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); + } + } + } + + if (position < 0) { + throw new FS.ErrnoError(28); + } + + return position; + }, + mmap:(stream, length, position, prot, flags) => { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(43); + } + + var ptr = mmapAlloc(length); + + NODEFS.stream_ops.read(stream, HEAP8, ptr, length, position); + return { ptr, allocated: true }; + }, + msync:(stream, buffer, offset, length, mmapFlags) => { + NODEFS.stream_ops.write(stream, buffer, 0, length, offset, false); + // should we check if bytesWritten and length are the same? + return 0; + }, }, - msync: (stream, buffer, offset, length, mmapFlags) => { - NODEFS.stream_ops.write(stream, buffer, 0, length, offset, false); - return 0; - } - } -}; - -var PROXYFS = { - mount(mount) { - return PROXYFS.createNode(null, "/", mount.opts.fs.lstat(mount.opts.root).mode, 0); - }, - createNode(parent, name, mode, dev) { - if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) { - throw new FS.ErrnoError(ERRNO_CODES.EINVAL); - } - var node = FS.createNode(parent, name, mode); - node.node_ops = PROXYFS.node_ops; - node.stream_ops = PROXYFS.stream_ops; - return node; - }, - realPath(node) { - var parts = []; - while (node.parent !== node) { - parts.push(node.name); - node = node.parent; - } - parts.push(node.mount.opts.root); - parts.reverse(); - return PATH.join.apply(null, parts); - }, - node_ops: { + }; + + + + var PROXYFS = { + mount(mount) { + return PROXYFS.createNode(null, '/', mount.opts.fs.lstat(mount.opts.root).mode, 0); + }, + createNode(parent, name, mode, dev) { + if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var node = FS.createNode(parent, name, mode); + node.node_ops = PROXYFS.node_ops; + node.stream_ops = PROXYFS.stream_ops; + return node; + }, + realPath(node) { + var parts = []; + while (node.parent !== node) { + parts.push(node.name); + node = node.parent; + } + parts.push(node.mount.opts.root); + parts.reverse(); + return PATH.join.apply(null, parts); + }, + node_ops:{ getattr(node) { - var path = PROXYFS.realPath(node); - var stat; - try { - stat = node.mount.opts.fs.lstat(path); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(ERRNO_CODES[e.code]); - } - return { - dev: stat.dev, - ino: stat.ino, - mode: stat.mode, - nlink: stat.nlink, - uid: stat.uid, - gid: stat.gid, - rdev: stat.rdev, - size: stat.size, - atime: stat.atime, - mtime: stat.mtime, - ctime: stat.ctime, - blksize: stat.blksize, - blocks: stat.blocks - }; - }, + var path = PROXYFS.realPath(node); + var stat; + try { + stat = node.mount.opts.fs.lstat(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return { + dev: stat.dev, + ino: stat.ino, + mode: stat.mode, + nlink: stat.nlink, + uid: stat.uid, + gid: stat.gid, + rdev: stat.rdev, + size: stat.size, + atime: stat.atime, + mtime: stat.mtime, + ctime: stat.ctime, + blksize: stat.blksize, + blocks: stat.blocks + }; + }, setattr(node, attr) { - var path = PROXYFS.realPath(node); - try { - if (attr.mode !== undefined) { - node.mount.opts.fs.chmod(path, attr.mode); - node.mode = attr.mode; - } - if (attr.timestamp !== undefined) { - var date = new Date(attr.timestamp); - node.mount.opts.fs.utime(path, date, date); - } - if (attr.size !== undefined) { - node.mount.opts.fs.truncate(path, attr.size); - } - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(ERRNO_CODES[e.code]); - } - }, + var path = PROXYFS.realPath(node); + try { + if (attr.mode !== undefined) { + node.mount.opts.fs.chmod(path, attr.mode); + // update the common node structure mode as well + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + var date = new Date(attr.timestamp); + node.mount.opts.fs.utime(path, date, date); + } + if (attr.size !== undefined) { + node.mount.opts.fs.truncate(path, attr.size); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, lookup(parent, name) { - try { - var path = PATH.join2(PROXYFS.realPath(parent), name); - var mode = parent.mount.opts.fs.lstat(path).mode; - var node = PROXYFS.createNode(parent, name, mode); - return node; - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(ERRNO_CODES[e.code]); - } - }, + try { + var path = PATH.join2(PROXYFS.realPath(parent), name); + var mode = parent.mount.opts.fs.lstat(path).mode; + var node = PROXYFS.createNode(parent, name, mode); + return node; + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, mknod(parent, name, mode, dev) { - var node = PROXYFS.createNode(parent, name, mode, dev); - var path = PROXYFS.realPath(node); - try { - if (FS.isDir(node.mode)) { - node.mount.opts.fs.mkdir(path, node.mode); - } else { - node.mount.opts.fs.writeFile(path, "", { - mode: node.mode - }); - } - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(ERRNO_CODES[e.code]); - } - return node; - }, + var node = PROXYFS.createNode(parent, name, mode, dev); + // create the backing node for this in the fs root as well + var path = PROXYFS.realPath(node); + try { + if (FS.isDir(node.mode)) { + node.mount.opts.fs.mkdir(path, node.mode); + } else { + node.mount.opts.fs.writeFile(path, '', { mode: node.mode }); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return node; + }, rename(oldNode, newDir, newName) { - var oldPath = PROXYFS.realPath(oldNode); - var newPath = PATH.join2(PROXYFS.realPath(newDir), newName); - try { - oldNode.mount.opts.fs.rename(oldPath, newPath); - oldNode.name = newName; - oldNode.parent = newDir; - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(ERRNO_CODES[e.code]); - } - }, + var oldPath = PROXYFS.realPath(oldNode); + var newPath = PATH.join2(PROXYFS.realPath(newDir), newName); + try { + oldNode.mount.opts.fs.rename(oldPath, newPath); + oldNode.name = newName; + oldNode.parent = newDir; + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, unlink(parent, name) { - var path = PATH.join2(PROXYFS.realPath(parent), name); - try { - parent.mount.opts.fs.unlink(path); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(ERRNO_CODES[e.code]); - } - }, + var path = PATH.join2(PROXYFS.realPath(parent), name); + try { + parent.mount.opts.fs.unlink(path); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, rmdir(parent, name) { - var path = PATH.join2(PROXYFS.realPath(parent), name); - try { - parent.mount.opts.fs.rmdir(path); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(ERRNO_CODES[e.code]); - } - }, + var path = PATH.join2(PROXYFS.realPath(parent), name); + try { + parent.mount.opts.fs.rmdir(path); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, readdir(node) { - var path = PROXYFS.realPath(node); - try { - return node.mount.opts.fs.readdir(path); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(ERRNO_CODES[e.code]); - } - }, + var path = PROXYFS.realPath(node); + try { + return node.mount.opts.fs.readdir(path); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, symlink(parent, newName, oldPath) { - var newPath = PATH.join2(PROXYFS.realPath(parent), newName); - try { - parent.mount.opts.fs.symlink(oldPath, newPath); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(ERRNO_CODES[e.code]); - } - }, + var newPath = PATH.join2(PROXYFS.realPath(parent), newName); + try { + parent.mount.opts.fs.symlink(oldPath, newPath); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, readlink(node) { - var path = PROXYFS.realPath(node); - try { - return node.mount.opts.fs.readlink(path); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(ERRNO_CODES[e.code]); - } - } - }, - stream_ops: { - open(stream) { - var path = PROXYFS.realPath(stream.node); - try { - stream.nfd = stream.node.mount.opts.fs.open(path, stream.flags); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(ERRNO_CODES[e.code]); - } + var path = PROXYFS.realPath(node); + try { + return node.mount.opts.fs.readlink(path); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, }, + stream_ops:{ + open(stream) { + var path = PROXYFS.realPath(stream.node); + try { + stream.nfd = stream.node.mount.opts.fs.open(path,stream.flags); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, close(stream) { - try { - stream.node.mount.opts.fs.close(stream.nfd); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(ERRNO_CODES[e.code]); - } - }, + try { + stream.node.mount.opts.fs.close(stream.nfd); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, read(stream, buffer, offset, length, position) { - try { - return stream.node.mount.opts.fs.read(stream.nfd, buffer, offset, length, position); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(ERRNO_CODES[e.code]); - } - }, + try { + return stream.node.mount.opts.fs.read(stream.nfd, buffer, offset, length, position); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, write(stream, buffer, offset, length, position) { - try { - return stream.node.mount.opts.fs.write(stream.nfd, buffer, offset, length, position); - } catch (e) { - if (!e.code) throw e; - throw new FS.ErrnoError(ERRNO_CODES[e.code]); - } - }, + try { + return stream.node.mount.opts.fs.write(stream.nfd, buffer, offset, length, position); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, llseek(stream, offset, whence) { - var position = offset; - if (whence === 1) { - position += stream.position; - } else if (whence === 2) { - if (FS.isFile(stream.node.mode)) { - try { - var stat = stream.node.node_ops.getattr(stream.node); - position += stat.size; - } catch (e) { - throw new FS.ErrnoError(ERRNO_CODES[e.code]); - } - } - } - if (position < 0) { - throw new FS.ErrnoError(ERRNO_CODES.EINVAL); - } - return position; - } - } -}; - -var FS = { - root: null, - mounts: [], - devices: {}, - streams: [], - nextInode: 1, - nameTable: null, - currentPath: "/", - initialized: false, - ignorePermissions: true, - ErrnoError: null, - genericErrors: {}, - filesystems: null, - syncFSRequests: 0, - lookupPath: (path, opts = {}) => { - path = PATH_FS.resolve(path); - if (!path) return { - path: "", - node: null - }; - var defaults = { - follow_mount: true, - recurse_count: 0 - }; - opts = Object.assign(defaults, opts); - if (opts.recurse_count > 8) { - throw new FS.ErrnoError(32); - } - var parts = path.split("/").filter((p => !!p)); - var current = FS.root; - var current_path = "/"; - for (var i = 0; i < parts.length; i++) { - var islast = i === parts.length - 1; - if (islast && opts.parent) { - break; - } - current = FS.lookupNode(current, parts[i]); - current_path = PATH.join2(current_path, parts[i]); - if (FS.isMountpoint(current)) { - if (!islast || islast && opts.follow_mount) { - current = current.mounted.root; - } - } - if (!islast || opts.follow) { - var count = 0; - while (FS.isLink(current.mode)) { - var link = FS.readlink(current_path); - current_path = PATH_FS.resolve(PATH.dirname(current_path), link); - var lookup = FS.lookupPath(current_path, { - recurse_count: opts.recurse_count + 1 - }); - current = lookup.node; - if (count++ > 40) { - throw new FS.ErrnoError(32); - } - } - } - } - return { - path: current_path, - node: current - }; - }, - getPath: node => { - var path; - while (true) { - if (FS.isRoot(node)) { - var mount = node.mount.mountpoint; - if (!path) return mount; - return mount[mount.length - 1] !== "/" ? `${mount}/${path}` : mount + path; - } - path = path ? `${node.name}/${path}` : node.name; - node = node.parent; - } - }, - hashName: (parentid, name) => { - var hash = 0; - for (var i = 0; i < name.length; i++) { - hash = (hash << 5) - hash + name.charCodeAt(i) | 0; - } - return (parentid + hash >>> 0) % FS.nameTable.length; - }, - hashAddNode: node => { - var hash = FS.hashName(node.parent.id, node.name); - node.name_next = FS.nameTable[hash]; - FS.nameTable[hash] = node; - }, - hashRemoveNode: node => { - var hash = FS.hashName(node.parent.id, node.name); - if (FS.nameTable[hash] === node) { - FS.nameTable[hash] = node.name_next; - } else { - var current = FS.nameTable[hash]; - while (current) { - if (current.name_next === node) { - current.name_next = node.name_next; - break; - } - current = current.name_next; - } - } - }, - lookupNode: (parent, name) => { - var errCode = FS.mayLookup(parent); - if (errCode) { - throw new FS.ErrnoError(errCode, parent); - } - var hash = FS.hashName(parent.id, name); - for (var node = FS.nameTable[hash]; node; node = node.name_next) { - var nodeName = node.name; - if (node.parent.id === parent.id && nodeName === name) { - return node; - } - } - return FS.lookup(parent, name); - }, - createNode: (parent, name, mode, rdev) => { - var node = new FS.FSNode(parent, name, mode, rdev); - FS.hashAddNode(node); - return node; - }, - destroyNode: node => { - FS.hashRemoveNode(node); - }, - isRoot: node => node === node.parent, - isMountpoint: node => !!node.mounted, - isFile: mode => (mode & 61440) === 32768, - isDir: mode => (mode & 61440) === 16384, - isLink: mode => (mode & 61440) === 40960, - isChrdev: mode => (mode & 61440) === 8192, - isBlkdev: mode => (mode & 61440) === 24576, - isFIFO: mode => (mode & 61440) === 4096, - isSocket: mode => (mode & 49152) === 49152, - flagsToPermissionString: flag => { - var perms = [ "r", "w", "rw" ][flag & 3]; - if (flag & 512) { - perms += "w"; - } - return perms; - }, - nodePermissions: (node, perms) => { - if (FS.ignorePermissions) { - return 0; - } - if (perms.includes("r") && !(node.mode & 292)) { - return 2; - } else if (perms.includes("w") && !(node.mode & 146)) { - return 2; - } else if (perms.includes("x") && !(node.mode & 73)) { - return 2; - } - return 0; - }, - mayLookup: dir => { - var errCode = FS.nodePermissions(dir, "x"); - if (errCode) return errCode; - if (!dir.node_ops.lookup) return 2; - return 0; - }, - mayCreate: (dir, name) => { - try { - var node = FS.lookupNode(dir, name); - return 20; - } catch (e) {} - return FS.nodePermissions(dir, "wx"); - }, - mayDelete: (dir, name, isdir) => { - var node; - try { - node = FS.lookupNode(dir, name); - } catch (e) { - return e.errno; - } - var errCode = FS.nodePermissions(dir, "wx"); - if (errCode) { - return errCode; - } - if (isdir) { - if (!FS.isDir(node.mode)) { - return 54; - } - if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) { - return 10; - } - } else { - if (FS.isDir(node.mode)) { - return 31; - } - } - return 0; - }, - mayOpen: (node, flags) => { - if (!node) { - return 44; - } - if (FS.isLink(node.mode)) { - return 32; - } else if (FS.isDir(node.mode)) { - if (FS.flagsToPermissionString(flags) !== "r" || flags & 512) { - return 31; - } - } - return FS.nodePermissions(node, FS.flagsToPermissionString(flags)); - }, - MAX_OPEN_FDS: 4096, - nextfd: () => { - for (var fd = 0; fd <= FS.MAX_OPEN_FDS; fd++) { - if (!FS.streams[fd]) { - return fd; - } - } - throw new FS.ErrnoError(33); - }, - getStreamChecked: fd => { - var stream = FS.getStream(fd); - if (!stream) { - throw new FS.ErrnoError(8); - } - return stream; - }, - getStream: fd => FS.streams[fd], - createStream: (stream, fd = -1) => { - if (!FS.FSStream) { - FS.FSStream = function() { - this.shared = {}; - }; - FS.FSStream.prototype = {}; - Object.defineProperties(FS.FSStream.prototype, { - object: { - get() { - return this.node; - }, - set(val) { - this.node = val; - } - }, - isRead: { - get() { - return (this.flags & 2097155) !== 1; - } - }, - isWrite: { - get() { - return (this.flags & 2097155) !== 0; - } - }, - isAppend: { - get() { - return this.flags & 1024; - } - }, - flags: { - get() { - return this.shared.flags; - }, - set(val) { - this.shared.flags = val; - } - }, - position: { - get() { - return this.shared.position; - }, - set(val) { - this.shared.position = val; - } - } - }); - } - stream = Object.assign(new FS.FSStream, stream); - if (fd == -1) { - fd = FS.nextfd(); - } - stream.fd = fd; - FS.streams[fd] = stream; - return stream; - }, - closeStream: fd => { - FS.streams[fd] = null; - }, - chrdev_stream_ops: { - open: stream => { - var device = FS.getDevice(stream.node.rdev); - stream.stream_ops = device.stream_ops; - if (stream.stream_ops.open) { - stream.stream_ops.open(stream); - } + var position = offset; + if (whence === 1) { + position += stream.position; + } else if (whence === 2) { + if (FS.isFile(stream.node.mode)) { + try { + var stat = stream.node.node_ops.getattr(stream.node); + position += stat.size; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + } + } + + if (position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + + return position; + }, }, - llseek: () => { - throw new FS.ErrnoError(70); - } - }, - major: dev => dev >> 8, - minor: dev => dev & 255, - makedev: (ma, mi) => ma << 8 | mi, - registerDevice: (dev, ops) => { - FS.devices[dev] = { - stream_ops: ops - }; - }, - getDevice: dev => FS.devices[dev], - getMounts: mount => { - var mounts = []; - var check = [ mount ]; - while (check.length) { - var m = check.pop(); - mounts.push(m); - check.push.apply(check, m.mounts); - } - return mounts; - }, - syncfs: (populate, callback) => { - if (typeof populate == "function") { - callback = populate; - populate = false; - } - FS.syncFSRequests++; - if (FS.syncFSRequests > 1) { - err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`); - } - var mounts = FS.getMounts(FS.root.mount); - var completed = 0; - function doCallback(errCode) { - FS.syncFSRequests--; - return callback(errCode); - } - function done(errCode) { - if (errCode) { - if (!done.errored) { - done.errored = true; - return doCallback(errCode); - } - return; - } - if (++completed >= mounts.length) { - doCallback(null); - } - } - mounts.forEach((mount => { - if (!mount.type.syncfs) { - return done(null); - } - mount.type.syncfs(mount, populate, done); - })); - }, - mount: (type, opts, mountpoint) => { - var root = mountpoint === "/"; - var pseudo = !mountpoint; - var node; - if (root && FS.root) { - throw new FS.ErrnoError(10); - } else if (!root && !pseudo) { - var lookup = FS.lookupPath(mountpoint, { - follow_mount: false - }); - mountpoint = lookup.path; - node = lookup.node; - if (FS.isMountpoint(node)) { - throw new FS.ErrnoError(10); - } - if (!FS.isDir(node.mode)) { - throw new FS.ErrnoError(54); - } - } - var mount = { - type: type, - opts: opts, - mountpoint: mountpoint, - mounts: [] - }; - var mountRoot = type.mount(mount); - mountRoot.mount = mount; - mount.root = mountRoot; - if (root) { - FS.root = mountRoot; - } else if (node) { - node.mounted = mount; - if (node.mount) { - node.mount.mounts.push(mount); - } - } - return mountRoot; - }, - unmount: mountpoint => { - var lookup = FS.lookupPath(mountpoint, { - follow_mount: false - }); - if (!FS.isMountpoint(lookup.node)) { - throw new FS.ErrnoError(28); - } - var node = lookup.node; - var mount = node.mounted; - var mounts = FS.getMounts(mount); - Object.keys(FS.nameTable).forEach((hash => { - var current = FS.nameTable[hash]; - while (current) { - var next = current.name_next; - if (mounts.includes(current.mount)) { - FS.destroyNode(current); - } - current = next; - } - })); - node.mounted = null; - var idx = node.mount.mounts.indexOf(mount); - node.mount.mounts.splice(idx, 1); - }, - lookup: (parent, name) => parent.node_ops.lookup(parent, name), - mknod: (path, mode, dev) => { - var lookup = FS.lookupPath(path, { - parent: true - }); - var parent = lookup.node; - var name = PATH.basename(path); - if (!name || name === "." || name === "..") { - throw new FS.ErrnoError(28); - } - var errCode = FS.mayCreate(parent, name); - if (errCode) { - throw new FS.ErrnoError(errCode); - } - if (!parent.node_ops.mknod) { - throw new FS.ErrnoError(63); - } - return parent.node_ops.mknod(parent, name, mode, dev); - }, - create: (path, mode) => { - mode = mode !== undefined ? mode : 438; - mode &= 4095; - mode |= 32768; - return FS.mknod(path, mode, 0); - }, - mkdir: (path, mode) => { - mode = mode !== undefined ? mode : 511; - mode &= 511 | 512; - mode |= 16384; - return FS.mknod(path, mode, 0); - }, - mkdirTree: (path, mode) => { - var dirs = path.split("/"); - var d = ""; - for (var i = 0; i < dirs.length; ++i) { - if (!dirs[i]) continue; - d += "/" + dirs[i]; - try { - FS.mkdir(d, mode); - } catch (e) { - if (e.errno != 20) throw e; - } - } - }, - mkdev: (path, mode, dev) => { - if (typeof dev == "undefined") { - dev = mode; - mode = 438; - } - mode |= 8192; - return FS.mknod(path, mode, dev); - }, - symlink: (oldpath, newpath) => { - if (!PATH_FS.resolve(oldpath)) { - throw new FS.ErrnoError(44); - } - var lookup = FS.lookupPath(newpath, { - parent: true - }); - var parent = lookup.node; - if (!parent) { - throw new FS.ErrnoError(44); - } - var newname = PATH.basename(newpath); - var errCode = FS.mayCreate(parent, newname); - if (errCode) { - throw new FS.ErrnoError(errCode); - } - if (!parent.node_ops.symlink) { - throw new FS.ErrnoError(63); - } - return parent.node_ops.symlink(parent, newname, oldpath); - }, - rename: (old_path, new_path) => { - var old_dirname = PATH.dirname(old_path); - var new_dirname = PATH.dirname(new_path); - var old_name = PATH.basename(old_path); - var new_name = PATH.basename(new_path); - var lookup, old_dir, new_dir; - lookup = FS.lookupPath(old_path, { - parent: true - }); - old_dir = lookup.node; - lookup = FS.lookupPath(new_path, { - parent: true - }); - new_dir = lookup.node; - if (!old_dir || !new_dir) throw new FS.ErrnoError(44); - if (old_dir.mount !== new_dir.mount) { - throw new FS.ErrnoError(75); - } - var old_node = FS.lookupNode(old_dir, old_name); - var relative = PATH_FS.relative(old_path, new_dirname); - if (relative.charAt(0) !== ".") { - throw new FS.ErrnoError(28); - } - relative = PATH_FS.relative(new_path, old_dirname); - if (relative.charAt(0) !== ".") { - throw new FS.ErrnoError(55); - } - var new_node; - try { - new_node = FS.lookupNode(new_dir, new_name); - } catch (e) {} - if (old_node === new_node) { - return; - } - var isdir = FS.isDir(old_node.mode); - var errCode = FS.mayDelete(old_dir, old_name, isdir); - if (errCode) { - throw new FS.ErrnoError(errCode); - } - errCode = new_node ? FS.mayDelete(new_dir, new_name, isdir) : FS.mayCreate(new_dir, new_name); - if (errCode) { - throw new FS.ErrnoError(errCode); - } - if (!old_dir.node_ops.rename) { - throw new FS.ErrnoError(63); - } - if (FS.isMountpoint(old_node) || new_node && FS.isMountpoint(new_node)) { - throw new FS.ErrnoError(10); - } - if (new_dir !== old_dir) { - errCode = FS.nodePermissions(old_dir, "w"); - if (errCode) { - throw new FS.ErrnoError(errCode); - } - } - FS.hashRemoveNode(old_node); - try { - old_dir.node_ops.rename(old_node, new_dir, new_name); - } catch (e) { - throw e; - } finally { - FS.hashAddNode(old_node); - } - }, - rmdir: path => { - var lookup = FS.lookupPath(path, { - parent: true - }); - var parent = lookup.node; - var name = PATH.basename(path); - var node = FS.lookupNode(parent, name); - var errCode = FS.mayDelete(parent, name, true); - if (errCode) { - throw new FS.ErrnoError(errCode); - } - if (!parent.node_ops.rmdir) { - throw new FS.ErrnoError(63); - } - if (FS.isMountpoint(node)) { - throw new FS.ErrnoError(10); - } - parent.node_ops.rmdir(parent, name); - FS.destroyNode(node); - }, - readdir: path => { - var lookup = FS.lookupPath(path, { - follow: true - }); - var node = lookup.node; - if (!node.node_ops.readdir) { - throw new FS.ErrnoError(54); - } - return node.node_ops.readdir(node); - }, - unlink: path => { - var lookup = FS.lookupPath(path, { - parent: true - }); - var parent = lookup.node; - if (!parent) { - throw new FS.ErrnoError(44); - } - var name = PATH.basename(path); - var node = FS.lookupNode(parent, name); - var errCode = FS.mayDelete(parent, name, false); - if (errCode) { - throw new FS.ErrnoError(errCode); - } - if (!parent.node_ops.unlink) { - throw new FS.ErrnoError(63); - } - if (FS.isMountpoint(node)) { - throw new FS.ErrnoError(10); - } - parent.node_ops.unlink(parent, name); - FS.destroyNode(node); - }, - readlink: path => { - var lookup = FS.lookupPath(path); - var link = lookup.node; - if (!link) { - throw new FS.ErrnoError(44); - } - if (!link.node_ops.readlink) { - throw new FS.ErrnoError(28); - } - return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link)); - }, - stat: (path, dontFollow) => { - var lookup = FS.lookupPath(path, { - follow: !dontFollow - }); - var node = lookup.node; - if (!node) { - throw new FS.ErrnoError(44); - } - if (!node.node_ops.getattr) { - throw new FS.ErrnoError(63); - } - return node.node_ops.getattr(node); - }, - lstat: path => FS.stat(path, true), - chmod: (path, mode, dontFollow) => { - var node; - if (typeof path == "string") { - var lookup = FS.lookupPath(path, { - follow: !dontFollow - }); - node = lookup.node; - } else { - node = path; - } - if (!node.node_ops.setattr) { - throw new FS.ErrnoError(63); - } - node.node_ops.setattr(node, { - mode: mode & 4095 | node.mode & ~4095, - timestamp: Date.now() - }); - }, - lchmod: (path, mode) => { - FS.chmod(path, mode, true); - }, - fchmod: (fd, mode) => { - var stream = FS.getStreamChecked(fd); - FS.chmod(stream.node, mode); - }, - chown: (path, uid, gid, dontFollow) => { - var node; - if (typeof path == "string") { - var lookup = FS.lookupPath(path, { - follow: !dontFollow - }); - node = lookup.node; - } else { - node = path; - } - if (!node.node_ops.setattr) { - throw new FS.ErrnoError(63); - } - node.node_ops.setattr(node, { - timestamp: Date.now() - }); - }, - lchown: (path, uid, gid) => { - FS.chown(path, uid, gid, true); - }, - fchown: (fd, uid, gid) => { - var stream = FS.getStreamChecked(fd); - FS.chown(stream.node, uid, gid); - }, - truncate: (path, len) => { - if (len < 0) { - throw new FS.ErrnoError(28); - } - var node; - if (typeof path == "string") { - var lookup = FS.lookupPath(path, { - follow: true - }); - node = lookup.node; - } else { - node = path; - } - if (!node.node_ops.setattr) { - throw new FS.ErrnoError(63); - } - if (FS.isDir(node.mode)) { - throw new FS.ErrnoError(31); - } - if (!FS.isFile(node.mode)) { - throw new FS.ErrnoError(28); - } - var errCode = FS.nodePermissions(node, "w"); - if (errCode) { - throw new FS.ErrnoError(errCode); - } - node.node_ops.setattr(node, { - size: len, - timestamp: Date.now() - }); - }, - ftruncate: (fd, len) => { - var stream = FS.getStreamChecked(fd); - if ((stream.flags & 2097155) === 0) { - throw new FS.ErrnoError(28); - } - FS.truncate(stream.node, len); - }, - utime: (path, atime, mtime) => { - var lookup = FS.lookupPath(path, { - follow: true - }); - var node = lookup.node; - node.node_ops.setattr(node, { - timestamp: Math.max(atime, mtime) - }); - }, - open: (path, flags, mode) => { - if (path === "") { - throw new FS.ErrnoError(44); - } - flags = typeof flags == "string" ? FS_modeStringToFlags(flags) : flags; - mode = typeof mode == "undefined" ? 438 : mode; - if (flags & 64) { - mode = mode & 4095 | 32768; - } else { - mode = 0; - } - var node; - if (typeof path == "object") { - node = path; - } else { - path = PATH.normalize(path); - try { - var lookup = FS.lookupPath(path, { - follow: !(flags & 131072) - }); - node = lookup.node; - } catch (e) {} - } - var created = false; - if (flags & 64) { - if (node) { - if (flags & 128) { - throw new FS.ErrnoError(20); - } - } else { - node = FS.mknod(path, mode, 0); - created = true; - } - } - if (!node) { - throw new FS.ErrnoError(44); - } - if (FS.isChrdev(node.mode)) { - flags &= ~512; - } - if (flags & 65536 && !FS.isDir(node.mode)) { - throw new FS.ErrnoError(54); - } - if (!created) { - var errCode = FS.mayOpen(node, flags); - if (errCode) { - throw new FS.ErrnoError(errCode); - } - } - if (flags & 512 && !created) { - FS.truncate(node, 0); - } - flags &= ~(128 | 512 | 131072); - var stream = FS.createStream({ - node: node, - path: FS.getPath(node), - flags: flags, - seekable: true, - position: 0, - stream_ops: node.stream_ops, - ungotten: [], - error: false - }); - if (stream.stream_ops.open) { - stream.stream_ops.open(stream); - } - if (Module["logReadFiles"] && !(flags & 1)) { - if (!FS.readFiles) FS.readFiles = {}; - if (!(path in FS.readFiles)) { - FS.readFiles[path] = 1; - } - } - return stream; - }, - close: stream => { - if (FS.isClosed(stream)) { - throw new FS.ErrnoError(8); - } - if (stream.getdents) stream.getdents = null; - try { - if (stream.stream_ops.close) { - stream.stream_ops.close(stream); - } - } catch (e) { - throw e; - } finally { - FS.closeStream(stream.fd); - } - stream.fd = null; - }, - isClosed: stream => stream.fd === null, - llseek: (stream, offset, whence) => { - if (FS.isClosed(stream)) { - throw new FS.ErrnoError(8); - } - if (!stream.seekable || !stream.stream_ops.llseek) { - throw new FS.ErrnoError(70); - } - if (whence != 0 && whence != 1 && whence != 2) { - throw new FS.ErrnoError(28); - } - stream.position = stream.stream_ops.llseek(stream, offset, whence); - stream.ungotten = []; - return stream.position; - }, - read: (stream, buffer, offset, length, position) => { - if (length < 0 || position < 0) { - throw new FS.ErrnoError(28); - } - if (FS.isClosed(stream)) { - throw new FS.ErrnoError(8); - } - if ((stream.flags & 2097155) === 1) { - throw new FS.ErrnoError(8); - } - if (FS.isDir(stream.node.mode)) { - throw new FS.ErrnoError(31); - } - if (!stream.stream_ops.read) { - throw new FS.ErrnoError(28); - } - var seeking = typeof position != "undefined"; - if (!seeking) { - position = stream.position; - } else if (!stream.seekable) { - throw new FS.ErrnoError(70); - } - var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position); - if (!seeking) stream.position += bytesRead; - return bytesRead; - }, - write: (stream, buffer, offset, length, position, canOwn) => { - if (length < 0 || position < 0) { - throw new FS.ErrnoError(28); - } - if (FS.isClosed(stream)) { - throw new FS.ErrnoError(8); - } - if ((stream.flags & 2097155) === 0) { - throw new FS.ErrnoError(8); - } - if (FS.isDir(stream.node.mode)) { - throw new FS.ErrnoError(31); - } - if (!stream.stream_ops.write) { - throw new FS.ErrnoError(28); - } - if (stream.seekable && stream.flags & 1024) { - FS.llseek(stream, 0, 2); - } - var seeking = typeof position != "undefined"; - if (!seeking) { - position = stream.position; - } else if (!stream.seekable) { - throw new FS.ErrnoError(70); - } - var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn); - if (!seeking) stream.position += bytesWritten; - return bytesWritten; - }, - allocate: (stream, offset, length) => { - if (FS.isClosed(stream)) { - throw new FS.ErrnoError(8); - } - if (offset < 0 || length <= 0) { - throw new FS.ErrnoError(28); - } - if ((stream.flags & 2097155) === 0) { - throw new FS.ErrnoError(8); - } - if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) { - throw new FS.ErrnoError(43); - } - if (!stream.stream_ops.allocate) { - throw new FS.ErrnoError(138); - } - stream.stream_ops.allocate(stream, offset, length); - }, - mmap: (stream, length, position, prot, flags) => { - if ((prot & 2) !== 0 && (flags & 2) === 0 && (stream.flags & 2097155) !== 2) { - throw new FS.ErrnoError(2); - } - if ((stream.flags & 2097155) === 1) { - throw new FS.ErrnoError(2); - } - if (!stream.stream_ops.mmap) { - throw new FS.ErrnoError(43); - } - return stream.stream_ops.mmap(stream, length, position, prot, flags); - }, - msync: (stream, buffer, offset, length, mmapFlags) => { - if (!stream.stream_ops.msync) { - return 0; - } - return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags); - }, - munmap: stream => 0, - ioctl: (stream, cmd, arg) => { - if (!stream.stream_ops.ioctl) { - throw new FS.ErrnoError(59); - } - return stream.stream_ops.ioctl(stream, cmd, arg); - }, - readFile: (path, opts = {}) => { - opts.flags = opts.flags || 0; - opts.encoding = opts.encoding || "binary"; - if (opts.encoding !== "utf8" && opts.encoding !== "binary") { - throw new Error(`Invalid encoding type "${opts.encoding}"`); - } - var ret; - var stream = FS.open(path, opts.flags); - var stat = FS.stat(path); - var length = stat.size; - var buf = new Uint8Array(length); - FS.read(stream, buf, 0, length, 0); - if (opts.encoding === "utf8") { - ret = UTF8ArrayToString(buf, 0); - } else if (opts.encoding === "binary") { - ret = buf; - } - FS.close(stream); - return ret; - }, - writeFile: (path, data, opts = {}) => { - opts.flags = opts.flags || 577; - var stream = FS.open(path, opts.flags, opts.mode); - if (typeof data == "string") { - var buf = new Uint8Array(lengthBytesUTF8(data) + 1); - var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length); - FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn); - } else if (ArrayBuffer.isView(data)) { - FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn); - } else { - throw new Error("Unsupported data type"); - } - FS.close(stream); - }, - cwd: () => FS.currentPath, - chdir: path => { - var lookup = FS.lookupPath(path, { - follow: true - }); - if (lookup.node === null) { - throw new FS.ErrnoError(44); - } - if (!FS.isDir(lookup.node.mode)) { - throw new FS.ErrnoError(54); - } - var errCode = FS.nodePermissions(lookup.node, "x"); - if (errCode) { - throw new FS.ErrnoError(errCode); - } - FS.currentPath = lookup.path; - }, - createDefaultDirectories: () => { - FS.mkdir("/tmp"); - FS.mkdir("/home"); - FS.mkdir("/home/web_user"); - }, - createDefaultDevices: () => { - FS.mkdir("/dev"); - FS.registerDevice(FS.makedev(1, 3), { - read: () => 0, - write: (stream, buffer, offset, length, pos) => length - }); - FS.mkdev("/dev/null", FS.makedev(1, 3)); - TTY.register(FS.makedev(5, 0), TTY.default_tty_ops); - TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops); - FS.mkdev("/dev/tty", FS.makedev(5, 0)); - FS.mkdev("/dev/tty1", FS.makedev(6, 0)); - var randomBuffer = new Uint8Array(1024), randomLeft = 0; - var randomByte = () => { - if (randomLeft === 0) { - randomLeft = randomFill(randomBuffer).byteLength; - } - return randomBuffer[--randomLeft]; - }; - FS.createDevice("/dev", "random", randomByte); - FS.createDevice("/dev", "urandom", randomByte); - FS.mkdir("/dev/shm"); - FS.mkdir("/dev/shm/tmp"); - }, - createSpecialDirectories: () => { - FS.mkdir("/proc"); - var proc_self = FS.mkdir("/proc/self"); - FS.mkdir("/proc/self/fd"); - FS.mount({ - mount: () => { - var node = FS.createNode(proc_self, "fd", 16384 | 511, 73); - node.node_ops = { - lookup: (parent, name) => { - var fd = +name; - var stream = FS.getStreamChecked(fd); - var ret = { - parent: null, - mount: { - mountpoint: "fake" - }, - node_ops: { - readlink: () => stream.path - } - }; - ret.parent = ret; - return ret; - } - }; - return node; - } - }, {}, "/proc/self/fd"); - }, - createStandardStreams: () => { - if (Module["stdin"]) { - FS.createDevice("/dev", "stdin", Module["stdin"]); - } else { - FS.symlink("/dev/tty", "/dev/stdin"); - } - if (Module["stdout"]) { - FS.createDevice("/dev", "stdout", null, Module["stdout"]); - } else { - FS.symlink("/dev/tty", "/dev/stdout"); - } - if (Module["stderr"]) { - FS.createDevice("/dev", "stderr", null, Module["stderr"]); - } else { - FS.symlink("/dev/tty1", "/dev/stderr"); - } - var stdin = FS.open("/dev/stdin", 0); - var stdout = FS.open("/dev/stdout", 1); - var stderr = FS.open("/dev/stderr", 1); - }, - ensureErrnoError: () => { - if (FS.ErrnoError) return; - FS.ErrnoError = function ErrnoError(errno, node) { - this.name = "ErrnoError"; - this.node = node; - this.setErrno = function(errno) { - this.errno = errno; - }; - this.setErrno(errno); - this.message = "FS error"; - }; - FS.ErrnoError.prototype = new Error; - FS.ErrnoError.prototype.constructor = FS.ErrnoError; - [ 44 ].forEach((code => { - FS.genericErrors[code] = new FS.ErrnoError(code); - FS.genericErrors[code].stack = ""; - })); - }, - staticInit: () => { - FS.ensureErrnoError(); - FS.nameTable = new Array(4096); - FS.mount(MEMFS, {}, "/"); - FS.createDefaultDirectories(); - FS.createDefaultDevices(); - FS.createSpecialDirectories(); - FS.filesystems = { - "MEMFS": MEMFS, - "NODEFS": NODEFS, - "PROXYFS": PROXYFS - }; - }, - init: (input, output, error) => { - FS.init.initialized = true; - FS.ensureErrnoError(); - Module["stdin"] = input || Module["stdin"]; - Module["stdout"] = output || Module["stdout"]; - Module["stderr"] = error || Module["stderr"]; - FS.createStandardStreams(); - }, - quit: () => { - FS.init.initialized = false; - _fflush(0); - for (var i = 0; i < FS.streams.length; i++) { - var stream = FS.streams[i]; - if (!stream) { - continue; - } - FS.close(stream); - } - }, - findObject: (path, dontResolveLastLink) => { - var ret = FS.analyzePath(path, dontResolveLastLink); - if (!ret.exists) { - return null; - } - return ret.object; - }, - analyzePath: (path, dontResolveLastLink) => { - try { - var lookup = FS.lookupPath(path, { - follow: !dontResolveLastLink - }); - path = lookup.path; - } catch (e) {} - var ret = { - isRoot: false, - exists: false, - error: 0, - name: null, - path: null, - object: null, - parentExists: false, - parentPath: null, - parentObject: null }; - try { - var lookup = FS.lookupPath(path, { - parent: true - }); - ret.parentExists = true; - ret.parentPath = lookup.path; - ret.parentObject = lookup.node; - ret.name = PATH.basename(path); - lookup = FS.lookupPath(path, { - follow: !dontResolveLastLink - }); - ret.exists = true; - ret.path = lookup.path; - ret.object = lookup.node; - ret.name = lookup.node.name; - ret.isRoot = lookup.path === "/"; - } catch (e) { - ret.error = e.errno; - } - return ret; - }, - createPath: (parent, path, canRead, canWrite) => { - parent = typeof parent == "string" ? parent : FS.getPath(parent); - var parts = path.split("/").reverse(); - while (parts.length) { - var part = parts.pop(); - if (!part) continue; - var current = PATH.join2(parent, part); - try { - FS.mkdir(current); - } catch (e) {} - parent = current; - } - return current; - }, - createFile: (parent, name, properties, canRead, canWrite) => { - var path = PATH.join2(typeof parent == "string" ? parent : FS.getPath(parent), name); - var mode = FS_getMode(canRead, canWrite); - return FS.create(path, mode); - }, - createDataFile: (parent, name, data, canRead, canWrite, canOwn) => { - var path = name; - if (parent) { - parent = typeof parent == "string" ? parent : FS.getPath(parent); - path = name ? PATH.join2(parent, name) : parent; - } - var mode = FS_getMode(canRead, canWrite); - var node = FS.create(path, mode); - if (data) { - if (typeof data == "string") { - var arr = new Array(data.length); - for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i); - data = arr; - } - FS.chmod(node, mode | 146); - var stream = FS.open(node, 577); - FS.write(stream, data, 0, data.length, 0, canOwn); - FS.close(stream); - FS.chmod(node, mode); - } - return node; - }, - createDevice: (parent, name, input, output) => { - var path = PATH.join2(typeof parent == "string" ? parent : FS.getPath(parent), name); - var mode = FS_getMode(!!input, !!output); - if (!FS.createDevice.major) FS.createDevice.major = 64; - var dev = FS.makedev(FS.createDevice.major++, 0); - FS.registerDevice(dev, { - open: stream => { - stream.seekable = false; - }, - close: stream => { - if (output && output.buffer && output.buffer.length) { - output(10); - } - }, - read: (stream, buffer, offset, length, pos) => { - var bytesRead = 0; - for (var i = 0; i < length; i++) { - var result; - try { - result = input(); - } catch (e) { - throw new FS.ErrnoError(29); - } - if (result === undefined && bytesRead === 0) { - throw new FS.ErrnoError(6); - } - if (result === null || result === undefined) break; - bytesRead++; - buffer[offset + i] = result; - } - if (bytesRead) { - stream.node.timestamp = Date.now(); - } - return bytesRead; - }, - write: (stream, buffer, offset, length, pos) => { - for (var i = 0; i < length; i++) { - try { - output(buffer[offset + i]); - } catch (e) { - throw new FS.ErrnoError(29); - } - } - if (length) { - stream.node.timestamp = Date.now(); - } - return i; - } - }); - return FS.mkdev(path, mode, dev); - }, - forceLoadFile: obj => { - if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; - if (typeof XMLHttpRequest != "undefined") { - throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); - } else if (read_) { - try { - obj.contents = intArrayFromString(read_(obj.url), true); - obj.usedBytes = obj.contents.length; - } catch (e) { - throw new FS.ErrnoError(29); - } - } else { - throw new Error("Cannot load without read() or XMLHttpRequest."); - } - }, - createLazyFile: (parent, name, url, canRead, canWrite) => { - function LazyUint8Array() { - this.lengthKnown = false; - this.chunks = []; - } - LazyUint8Array.prototype.get = function LazyUint8Array_get(idx) { - if (idx > this.length - 1 || idx < 0) { - return undefined; - } - var chunkOffset = idx % this.chunkSize; - var chunkNum = idx / this.chunkSize | 0; - return this.getter(chunkNum)[chunkOffset]; - }; - LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) { - this.getter = getter; - }; - LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() { - var xhr = new XMLHttpRequest; - xhr.open("HEAD", url, false); - xhr.send(null); - if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); - var datalength = Number(xhr.getResponseHeader("Content-length")); - var header; - var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes"; - var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip"; - var chunkSize = 1024 * 1024; - if (!hasByteServing) chunkSize = datalength; - var doXHR = (from, to) => { - if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); - if (to > datalength - 1) throw new Error("only " + datalength + " bytes available! programmer error!"); - var xhr = new XMLHttpRequest; - xhr.open("GET", url, false); - if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); - xhr.responseType = "arraybuffer"; - if (xhr.overrideMimeType) { - xhr.overrideMimeType("text/plain; charset=x-user-defined"); - } - xhr.send(null); - if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); - if (xhr.response !== undefined) { - return new Uint8Array(xhr.response || []); - } - return intArrayFromString(xhr.responseText || "", true); - }; - var lazyArray = this; - lazyArray.setDataGetter((chunkNum => { - var start = chunkNum * chunkSize; - var end = (chunkNum + 1) * chunkSize - 1; - end = Math.min(end, datalength - 1); - if (typeof lazyArray.chunks[chunkNum] == "undefined") { - lazyArray.chunks[chunkNum] = doXHR(start, end); - } - if (typeof lazyArray.chunks[chunkNum] == "undefined") throw new Error("doXHR failed!"); - return lazyArray.chunks[chunkNum]; - })); - if (usesGzip || !datalength) { - chunkSize = datalength = 1; - datalength = this.getter(0).length; - chunkSize = datalength; - out("LazyFiles on gzip forces download of the whole file when length is accessed"); - } - this._length = datalength; - this._chunkSize = chunkSize; - this.lengthKnown = true; - }; - if (typeof XMLHttpRequest != "undefined") { - if (!ENVIRONMENT_IS_WORKER) throw "Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc"; - var lazyArray = new LazyUint8Array; - Object.defineProperties(lazyArray, { - length: { - get: function() { - if (!this.lengthKnown) { - this.cacheLength(); - } - return this._length; - } - }, - chunkSize: { - get: function() { - if (!this.lengthKnown) { - this.cacheLength(); - } - return this._chunkSize; - } - } - }); - var properties = { - isDevice: false, - contents: lazyArray - }; - } else { - var properties = { - isDevice: false, - url: url - }; - } - var node = FS.createFile(parent, name, properties, canRead, canWrite); - if (properties.contents) { - node.contents = properties.contents; - } else if (properties.url) { - node.contents = null; - node.url = properties.url; - } - Object.defineProperties(node, { - usedBytes: { - get: function() { - return this.contents.length; - } - } - }); - var stream_ops = {}; - var keys = Object.keys(node.stream_ops); - keys.forEach((key => { - var fn = node.stream_ops[key]; - stream_ops[key] = function forceLoadLazyFile() { - FS.forceLoadFile(node); - return fn.apply(null, arguments); - }; - })); - function writeChunks(stream, buffer, offset, length, position) { - var contents = stream.node.contents; - if (position >= contents.length) return 0; - var size = Math.min(contents.length - position, length); - if (contents.slice) { - for (var i = 0; i < size; i++) { - buffer[offset + i] = contents[position + i]; - } - } else { - for (var i = 0; i < size; i++) { - buffer[offset + i] = contents.get(position + i); - } - } - return size; - } - stream_ops.read = (stream, buffer, offset, length, position) => { - FS.forceLoadFile(node); - return writeChunks(stream, buffer, offset, length, position); - }; - stream_ops.mmap = (stream, length, position, prot, flags) => { - FS.forceLoadFile(node); - var ptr = mmapAlloc(length); - if (!ptr) { - throw new FS.ErrnoError(48); - } - writeChunks(stream, HEAP8, ptr, length, position); - return { - ptr: ptr, - allocated: true - }; - }; - node.stream_ops = stream_ops; - return node; - } -}; - -Module["FS"] = FS; - -var SYSCALLS = { - DEFAULT_POLLMASK: 5, - calculateAt: function(dirfd, path, allowEmpty) { - if (PATH.isAbs(path)) { - return path; - } - var dir; - if (dirfd === -100) { - dir = FS.cwd(); - } else { - var dirstream = SYSCALLS.getStreamFromFD(dirfd); - dir = dirstream.path; - } - if (path.length == 0) { - if (!allowEmpty) { - throw new FS.ErrnoError(44); - } - return dir; - } - return PATH.join2(dir, path); - }, - doStat: function(func, path, buf) { - try { - var stat = func(path); - } catch (e) { - if (e && e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) { - return -54; - } - throw e; - } - HEAP32[buf >> 2] = stat.dev; - HEAP32[buf + 4 >> 2] = stat.mode; - HEAPU32[buf + 8 >> 2] = stat.nlink; - HEAP32[buf + 12 >> 2] = stat.uid; - HEAP32[buf + 16 >> 2] = stat.gid; - HEAP32[buf + 20 >> 2] = stat.rdev; - tempI64 = [ stat.size >>> 0, (tempDouble = stat.size, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], - HEAP32[buf + 24 >> 2] = tempI64[0], HEAP32[buf + 28 >> 2] = tempI64[1]; - HEAP32[buf + 32 >> 2] = 4096; - HEAP32[buf + 36 >> 2] = stat.blocks; - var atime = stat.atime.getTime(); - var mtime = stat.mtime.getTime(); - var ctime = stat.ctime.getTime(); - tempI64 = [ Math.floor(atime / 1e3) >>> 0, (tempDouble = Math.floor(atime / 1e3), - +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], - HEAP32[buf + 40 >> 2] = tempI64[0], HEAP32[buf + 44 >> 2] = tempI64[1]; - HEAPU32[buf + 48 >> 2] = atime % 1e3 * 1e3; - tempI64 = [ Math.floor(mtime / 1e3) >>> 0, (tempDouble = Math.floor(mtime / 1e3), - +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], - HEAP32[buf + 56 >> 2] = tempI64[0], HEAP32[buf + 60 >> 2] = tempI64[1]; - HEAPU32[buf + 64 >> 2] = mtime % 1e3 * 1e3; - tempI64 = [ Math.floor(ctime / 1e3) >>> 0, (tempDouble = Math.floor(ctime / 1e3), - +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], - HEAP32[buf + 72 >> 2] = tempI64[0], HEAP32[buf + 76 >> 2] = tempI64[1]; - HEAPU32[buf + 80 >> 2] = ctime % 1e3 * 1e3; - tempI64 = [ stat.ino >>> 0, (tempDouble = stat.ino, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], - HEAP32[buf + 88 >> 2] = tempI64[0], HEAP32[buf + 92 >> 2] = tempI64[1]; - return 0; - }, - doMsync: function(addr, stream, len, flags, offset) { - if (!FS.isFile(stream.node.mode)) { - throw new FS.ErrnoError(43); - } - if (flags & 2) { - return 0; - } - var buffer = HEAPU8.slice(addr, addr + len); - FS.msync(stream, buffer, offset, len, flags); - }, - varargs: undefined, - get() { - SYSCALLS.varargs += 4; - var ret = HEAP32[SYSCALLS.varargs - 4 >> 2]; - return ret; - }, - getStr(ptr) { - var ret = UTF8ToString(ptr); - return ret; - }, - getStreamFromFD: function(fd) { - var stream = FS.getStreamChecked(fd); - return stream; - } -}; - -function ___syscall__newselect(nfds, readfds, writefds, exceptfds, timeout) { - try { - var total = 0; - var srcReadLow = readfds ? HEAP32[readfds >> 2] : 0, srcReadHigh = readfds ? HEAP32[readfds + 4 >> 2] : 0; - var srcWriteLow = writefds ? HEAP32[writefds >> 2] : 0, srcWriteHigh = writefds ? HEAP32[writefds + 4 >> 2] : 0; - var srcExceptLow = exceptfds ? HEAP32[exceptfds >> 2] : 0, srcExceptHigh = exceptfds ? HEAP32[exceptfds + 4 >> 2] : 0; - var dstReadLow = 0, dstReadHigh = 0; - var dstWriteLow = 0, dstWriteHigh = 0; - var dstExceptLow = 0, dstExceptHigh = 0; - var allLow = (readfds ? HEAP32[readfds >> 2] : 0) | (writefds ? HEAP32[writefds >> 2] : 0) | (exceptfds ? HEAP32[exceptfds >> 2] : 0); - var allHigh = (readfds ? HEAP32[readfds + 4 >> 2] : 0) | (writefds ? HEAP32[writefds + 4 >> 2] : 0) | (exceptfds ? HEAP32[exceptfds + 4 >> 2] : 0); - var check = function(fd, low, high, val) { - return fd < 32 ? low & val : high & val; - }; - for (var fd = 0; fd < nfds; fd++) { - var mask = 1 << fd % 32; - if (!check(fd, allLow, allHigh, mask)) { - continue; - } - var stream = SYSCALLS.getStreamFromFD(fd); - var flags = SYSCALLS.DEFAULT_POLLMASK; - if (stream.stream_ops?.poll) { - var timeoutInMillis = -1; - if (timeout) { - var tv_sec = readfds ? HEAP32[timeout >> 2] : 0, tv_usec = readfds ? HEAP32[timeout + 8 >> 2] : 0; - timeoutInMillis = (tv_sec + tv_usec / 1e6) * 1e3; - } - flags = stream.stream_ops.poll(stream, timeoutInMillis); - } - if (flags & 1 && check(fd, srcReadLow, srcReadHigh, mask)) { - fd < 32 ? dstReadLow = dstReadLow | mask : dstReadHigh = dstReadHigh | mask; - total++; - } - if (flags & 4 && check(fd, srcWriteLow, srcWriteHigh, mask)) { - fd < 32 ? dstWriteLow = dstWriteLow | mask : dstWriteHigh = dstWriteHigh | mask; - total++; - } - if (flags & 2 && check(fd, srcExceptLow, srcExceptHigh, mask)) { - fd < 32 ? dstExceptLow = dstExceptLow | mask : dstExceptHigh = dstExceptHigh | mask; - total++; - } - } - if (readfds) { - HEAP32[readfds >> 2] = dstReadLow; - HEAP32[readfds + 4 >> 2] = dstReadHigh; - } - if (writefds) { - HEAP32[writefds >> 2] = dstWriteLow; - HEAP32[writefds + 4 >> 2] = dstWriteHigh; - } - if (exceptfds) { - HEAP32[exceptfds >> 2] = dstExceptLow; - HEAP32[exceptfds + 4 >> 2] = dstExceptHigh; - } - return total; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -var SOCKFS = { - mount(mount) { - Module["websocket"] = Module["websocket"] && "object" === typeof Module["websocket"] ? Module["websocket"] : {}; - Module["websocket"]._callbacks = {}; - Module["websocket"]["on"] = function(event, callback) { - if ("function" === typeof callback) { - this._callbacks[event] = callback; - } - return this; - }; - Module["websocket"].emit = function(event, param) { - if ("function" === typeof this._callbacks[event]) { - this._callbacks[event].call(this, param); - } - }; - return FS.createNode(null, "/", 16384 | 511, 0); - }, - createSocket(family, type, protocol) { - type &= ~526336; - var streaming = type == 1; - if (streaming && protocol && protocol != 6) { - throw new FS.ErrnoError(66); - } - var sock = { - family: family, - type: type, - protocol: protocol, - server: null, - error: null, - peers: {}, - pending: [], - recv_queue: [], - sock_ops: SOCKFS.websocket_sock_ops - }; - var name = SOCKFS.nextname(); - var node = FS.createNode(SOCKFS.root, name, 49152, 0); - node.sock = sock; - var stream = FS.createStream({ - path: name, - node: node, - flags: 2, - seekable: false, - stream_ops: SOCKFS.stream_ops - }); - sock.stream = stream; - return sock; - }, - getSocket(fd) { - var stream = FS.getStream(fd); - if (!stream || !FS.isSocket(stream.node.mode)) { - return null; - } - return stream.node.sock; - }, - stream_ops: { - poll(stream) { - var sock = stream.node.sock; - return sock.sock_ops.poll(sock); - }, - ioctl(stream, request, varargs) { - var sock = stream.node.sock; - return sock.sock_ops.ioctl(sock, request, varargs); + var FS = { + root:null, + mounts:[], + devices:{ }, - read(stream, buffer, offset, length, position) { - var sock = stream.node.sock; - var msg = sock.sock_ops.recvmsg(sock, length); - if (!msg) { - return 0; - } - buffer.set(msg.buffer, offset); - return msg.buffer.length; + streams:[], + nextInode:1, + nameTable:null, + currentPath:"/", + initialized:false, + ignorePermissions:true, + ErrnoError:null, + genericErrors:{ }, - write(stream, buffer, offset, length, position) { - var sock = stream.node.sock; - return sock.sock_ops.sendmsg(sock, buffer, offset, length); + filesystems:null, + syncFSRequests:0, + lookupPath:(path, opts = {}) => { + path = PATH_FS.resolve(path); + + if (!path) return { path: '', node: null }; + + var defaults = { + follow_mount: true, + recurse_count: 0 + }; + opts = Object.assign(defaults, opts) + + if (opts.recurse_count > 8) { // max recursive lookup of 8 + throw new FS.ErrnoError(32); + } + + // split the absolute path + var parts = path.split('/').filter((p) => !!p); + + // start at the root + var current = FS.root; + var current_path = '/'; + + for (var i = 0; i < parts.length; i++) { + var islast = (i === parts.length-1); + if (islast && opts.parent) { + // stop resolving + break; + } + + current = FS.lookupNode(current, parts[i]); + current_path = PATH.join2(current_path, parts[i]); + + // jump to the mount's root node if this is a mountpoint + if (FS.isMountpoint(current)) { + if (!islast || (islast && opts.follow_mount)) { + current = current.mounted.root; + } + } + + // by default, lookupPath will not follow a symlink if it is the final path component. + // setting opts.follow = true will override this behavior. + if (!islast || opts.follow) { + var count = 0; + while (FS.isLink(current.mode)) { + var link = FS.readlink(current_path); + current_path = PATH_FS.resolve(PATH.dirname(current_path), link); + + var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count + 1 }); + current = lookup.node; + + if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX). + throw new FS.ErrnoError(32); + } + } + } + } + + return { path: current_path, node: current }; + }, + getPath:(node) => { + var path; + while (true) { + if (FS.isRoot(node)) { + var mount = node.mount.mountpoint; + if (!path) return mount; + return mount[mount.length-1] !== '/' ? `${mount}/${path}` : mount + path; + } + path = path ? `${node.name}/${path}` : node.name; + node = node.parent; + } + }, + hashName:(parentid, name) => { + var hash = 0; + + for (var i = 0; i < name.length; i++) { + hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0; + } + return ((parentid + hash) >>> 0) % FS.nameTable.length; + }, + hashAddNode:(node) => { + var hash = FS.hashName(node.parent.id, node.name); + node.name_next = FS.nameTable[hash]; + FS.nameTable[hash] = node; + }, + hashRemoveNode:(node) => { + var hash = FS.hashName(node.parent.id, node.name); + if (FS.nameTable[hash] === node) { + FS.nameTable[hash] = node.name_next; + } else { + var current = FS.nameTable[hash]; + while (current) { + if (current.name_next === node) { + current.name_next = node.name_next; + break; + } + current = current.name_next; + } + } + }, + lookupNode:(parent, name) => { + var errCode = FS.mayLookup(parent); + if (errCode) { + throw new FS.ErrnoError(errCode, parent); + } + var hash = FS.hashName(parent.id, name); + for (var node = FS.nameTable[hash]; node; node = node.name_next) { + var nodeName = node.name; + if (node.parent.id === parent.id && nodeName === name) { + return node; + } + } + // if we failed to find it in the cache, call into the VFS + return FS.lookup(parent, name); + }, + createNode:(parent, name, mode, rdev) => { + var node = new FS.FSNode(parent, name, mode, rdev); + + FS.hashAddNode(node); + + return node; + }, + destroyNode:(node) => { + FS.hashRemoveNode(node); + }, + isRoot:(node) => { + return node === node.parent; + }, + isMountpoint:(node) => { + return !!node.mounted; + }, + isFile:(mode) => { + return (mode & 61440) === 32768; + }, + isDir:(mode) => { + return (mode & 61440) === 16384; + }, + isLink:(mode) => { + return (mode & 61440) === 40960; + }, + isChrdev:(mode) => { + return (mode & 61440) === 8192; + }, + isBlkdev:(mode) => { + return (mode & 61440) === 24576; + }, + isFIFO:(mode) => { + return (mode & 61440) === 4096; + }, + isSocket:(mode) => { + return (mode & 49152) === 49152; + }, + flagsToPermissionString:(flag) => { + var perms = ['r', 'w', 'rw'][flag & 3]; + if ((flag & 512)) { + perms += 'w'; + } + return perms; + }, + nodePermissions:(node, perms) => { + if (FS.ignorePermissions) { + return 0; + } + // return 0 if any user, group or owner bits are set. + if (perms.includes('r') && !(node.mode & 292)) { + return 2; + } else if (perms.includes('w') && !(node.mode & 146)) { + return 2; + } else if (perms.includes('x') && !(node.mode & 73)) { + return 2; + } + return 0; + }, + mayLookup:(dir) => { + var errCode = FS.nodePermissions(dir, 'x'); + if (errCode) return errCode; + if (!dir.node_ops.lookup) return 2; + return 0; + }, + mayCreate:(dir, name) => { + try { + var node = FS.lookupNode(dir, name); + return 20; + } catch (e) { + } + return FS.nodePermissions(dir, 'wx'); + }, + mayDelete:(dir, name, isdir) => { + var node; + try { + node = FS.lookupNode(dir, name); + } catch (e) { + return e.errno; + } + var errCode = FS.nodePermissions(dir, 'wx'); + if (errCode) { + return errCode; + } + if (isdir) { + if (!FS.isDir(node.mode)) { + return 54; + } + if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) { + return 10; + } + } else { + if (FS.isDir(node.mode)) { + return 31; + } + } + return 0; + }, + mayOpen:(node, flags) => { + if (!node) { + return 44; + } + if (FS.isLink(node.mode)) { + return 32; + } else if (FS.isDir(node.mode)) { + if (FS.flagsToPermissionString(flags) !== 'r' || // opening for write + (flags & 512)) { // TODO: check for O_SEARCH? (== search for dir only) + return 31; + } + } + return FS.nodePermissions(node, FS.flagsToPermissionString(flags)); + }, + MAX_OPEN_FDS:4096, + nextfd:() => { + for (var fd = 0; fd <= FS.MAX_OPEN_FDS; fd++) { + if (!FS.streams[fd]) { + return fd; + } + } + throw new FS.ErrnoError(33); + }, + getStreamChecked:(fd) => { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(8); + } + return stream; + }, + getStream:(fd) => FS.streams[fd], + createStream:(stream, fd = -1) => { + if (!FS.FSStream) { + FS.FSStream = /** @constructor */ function() { + this.shared = { }; + }; + FS.FSStream.prototype = {}; + Object.defineProperties(FS.FSStream.prototype, { + object: { + /** @this {FS.FSStream} */ + get() { return this.node; }, + /** @this {FS.FSStream} */ + set(val) { this.node = val; } + }, + isRead: { + /** @this {FS.FSStream} */ + get() { return (this.flags & 2097155) !== 1; } + }, + isWrite: { + /** @this {FS.FSStream} */ + get() { return (this.flags & 2097155) !== 0; } + }, + isAppend: { + /** @this {FS.FSStream} */ + get() { return (this.flags & 1024); } + }, + flags: { + /** @this {FS.FSStream} */ + get() { return this.shared.flags; }, + /** @this {FS.FSStream} */ + set(val) { this.shared.flags = val; }, + }, + position : { + /** @this {FS.FSStream} */ + get() { return this.shared.position; }, + /** @this {FS.FSStream} */ + set(val) { this.shared.position = val; }, + }, + }); + } + // clone it, so we can return an instance of FSStream + stream = Object.assign(new FS.FSStream(), stream); + if (fd == -1) { + fd = FS.nextfd(); + } + stream.fd = fd; + FS.streams[fd] = stream; + return stream; + }, + closeStream:(fd) => { + FS.streams[fd] = null; + }, + chrdev_stream_ops:{ + open:(stream) => { + var device = FS.getDevice(stream.node.rdev); + // override node's stream ops with the device's + stream.stream_ops = device.stream_ops; + // forward the open call + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + }, + llseek:() => { + throw new FS.ErrnoError(70); + }, }, + major:(dev) => ((dev) >> 8), + minor:(dev) => ((dev) & 0xff), + makedev:(ma, mi) => ((ma) << 8 | (mi)), + registerDevice:(dev, ops) => { + FS.devices[dev] = { stream_ops: ops }; + }, + getDevice:(dev) => FS.devices[dev], + getMounts:(mount) => { + var mounts = []; + var check = [mount]; + + while (check.length) { + var m = check.pop(); + + mounts.push(m); + + check.push.apply(check, m.mounts); + } + + return mounts; + }, + syncfs:(populate, callback) => { + if (typeof populate == 'function') { + callback = populate; + populate = false; + } + + FS.syncFSRequests++; + + if (FS.syncFSRequests > 1) { + err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`); + } + + var mounts = FS.getMounts(FS.root.mount); + var completed = 0; + + function doCallback(errCode) { + FS.syncFSRequests--; + return callback(errCode); + } + + function done(errCode) { + if (errCode) { + if (!done.errored) { + done.errored = true; + return doCallback(errCode); + } + return; + } + if (++completed >= mounts.length) { + doCallback(null); + } + }; + + // sync all mounts + mounts.forEach((mount) => { + if (!mount.type.syncfs) { + return done(null); + } + mount.type.syncfs(mount, populate, done); + }); + }, + mount:(type, opts, mountpoint) => { + var root = mountpoint === '/'; + var pseudo = !mountpoint; + var node; + + if (root && FS.root) { + throw new FS.ErrnoError(10); + } else if (!root && !pseudo) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + mountpoint = lookup.path; // use the absolute path + node = lookup.node; + + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(10); + } + + if (!FS.isDir(node.mode)) { + throw new FS.ErrnoError(54); + } + } + + var mount = { + type, + opts, + mountpoint, + mounts: [] + }; + + // create a root node for the fs + var mountRoot = type.mount(mount); + mountRoot.mount = mount; + mount.root = mountRoot; + + if (root) { + FS.root = mountRoot; + } else if (node) { + // set as a mountpoint + node.mounted = mount; + + // add the new mount to the current mount's children + if (node.mount) { + node.mount.mounts.push(mount); + } + } + + return mountRoot; + }, + unmount:(mountpoint) => { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + if (!FS.isMountpoint(lookup.node)) { + throw new FS.ErrnoError(28); + } + + // destroy the nodes for this mount, and all its child mounts + var node = lookup.node; + var mount = node.mounted; + var mounts = FS.getMounts(mount); + + Object.keys(FS.nameTable).forEach((hash) => { + var current = FS.nameTable[hash]; + + while (current) { + var next = current.name_next; + + if (mounts.includes(current.mount)) { + FS.destroyNode(current); + } + + current = next; + } + }); + + // no longer a mountpoint + node.mounted = null; + + // remove this mount from the child mounts + var idx = node.mount.mounts.indexOf(mount); + node.mount.mounts.splice(idx, 1); + }, + lookup:(parent, name) => { + return parent.node_ops.lookup(parent, name); + }, + mknod:(path, mode, dev) => { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + if (!name || name === '.' || name === '..') { + throw new FS.ErrnoError(28); + } + var errCode = FS.mayCreate(parent, name); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.mknod) { + throw new FS.ErrnoError(63); + } + return parent.node_ops.mknod(parent, name, mode, dev); + }, + create:(path, mode) => { + mode = mode !== undefined ? mode : 438 /* 0666 */; + mode &= 4095; + mode |= 32768; + return FS.mknod(path, mode, 0); + }, + mkdir:(path, mode) => { + mode = mode !== undefined ? mode : 511 /* 0777 */; + mode &= 511 | 512; + mode |= 16384; + return FS.mknod(path, mode, 0); + }, + mkdirTree:(path, mode) => { + var dirs = path.split('/'); + var d = ''; + for (var i = 0; i < dirs.length; ++i) { + if (!dirs[i]) continue; + d += '/' + dirs[i]; + try { + FS.mkdir(d, mode); + } catch(e) { + if (e.errno != 20) throw e; + } + } + }, + mkdev:(path, mode, dev) => { + if (typeof dev == 'undefined') { + dev = mode; + mode = 438 /* 0666 */; + } + mode |= 8192; + return FS.mknod(path, mode, dev); + }, + symlink:(oldpath, newpath) => { + if (!PATH_FS.resolve(oldpath)) { + throw new FS.ErrnoError(44); + } + var lookup = FS.lookupPath(newpath, { parent: true }); + var parent = lookup.node; + if (!parent) { + throw new FS.ErrnoError(44); + } + var newname = PATH.basename(newpath); + var errCode = FS.mayCreate(parent, newname); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.symlink) { + throw new FS.ErrnoError(63); + } + return parent.node_ops.symlink(parent, newname, oldpath); + }, + rename:(old_path, new_path) => { + var old_dirname = PATH.dirname(old_path); + var new_dirname = PATH.dirname(new_path); + var old_name = PATH.basename(old_path); + var new_name = PATH.basename(new_path); + // parents must exist + var lookup, old_dir, new_dir; + + // let the errors from non existant directories percolate up + lookup = FS.lookupPath(old_path, { parent: true }); + old_dir = lookup.node; + lookup = FS.lookupPath(new_path, { parent: true }); + new_dir = lookup.node; + + if (!old_dir || !new_dir) throw new FS.ErrnoError(44); + // need to be part of the same mount + if (old_dir.mount !== new_dir.mount) { + throw new FS.ErrnoError(75); + } + // source must exist + var old_node = FS.lookupNode(old_dir, old_name); + // old path should not be an ancestor of the new path + var relative = PATH_FS.relative(old_path, new_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(28); + } + // new path should not be an ancestor of the old path + relative = PATH_FS.relative(new_path, old_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(55); + } + // see if the new path already exists + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + // not fatal + } + // early out if nothing needs to change + if (old_node === new_node) { + return; + } + // we'll need to delete the old entry + var isdir = FS.isDir(old_node.mode); + var errCode = FS.mayDelete(old_dir, old_name, isdir); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + // need delete permissions if we'll be overwriting. + // need create permissions if new doesn't already exist. + errCode = new_node ? + FS.mayDelete(new_dir, new_name, isdir) : + FS.mayCreate(new_dir, new_name); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!old_dir.node_ops.rename) { + throw new FS.ErrnoError(63); + } + if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) { + throw new FS.ErrnoError(10); + } + // if we are going to change the parent, check write permissions + if (new_dir !== old_dir) { + errCode = FS.nodePermissions(old_dir, 'w'); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + } + // remove the node from the lookup hash + FS.hashRemoveNode(old_node); + // do the underlying fs rename + try { + old_dir.node_ops.rename(old_node, new_dir, new_name); + } catch (e) { + throw e; + } finally { + // add the node back to the hash (in case node_ops.rename + // changed its name) + FS.hashAddNode(old_node); + } + }, + rmdir:(path) => { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var errCode = FS.mayDelete(parent, name, true); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.rmdir) { + throw new FS.ErrnoError(63); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(10); + } + parent.node_ops.rmdir(parent, name); + FS.destroyNode(node); + }, + readdir:(path) => { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + if (!node.node_ops.readdir) { + throw new FS.ErrnoError(54); + } + return node.node_ops.readdir(node); + }, + unlink:(path) => { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + if (!parent) { + throw new FS.ErrnoError(44); + } + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var errCode = FS.mayDelete(parent, name, false); + if (errCode) { + // According to POSIX, we should map EISDIR to EPERM, but + // we instead do what Linux does (and we must, as we use + // the musl linux libc). + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.unlink) { + throw new FS.ErrnoError(63); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(10); + } + parent.node_ops.unlink(parent, name); + FS.destroyNode(node); + }, + readlink:(path) => { + var lookup = FS.lookupPath(path); + var link = lookup.node; + if (!link) { + throw new FS.ErrnoError(44); + } + if (!link.node_ops.readlink) { + throw new FS.ErrnoError(28); + } + return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link)); + }, + stat:(path, dontFollow) => { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + var node = lookup.node; + if (!node) { + throw new FS.ErrnoError(44); + } + if (!node.node_ops.getattr) { + throw new FS.ErrnoError(63); + } + return node.node_ops.getattr(node); + }, + lstat:(path) => { + return FS.stat(path, true); + }, + chmod:(path, mode, dontFollow) => { + var node; + if (typeof path == 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(63); + } + node.node_ops.setattr(node, { + mode: (mode & 4095) | (node.mode & ~4095), + timestamp: Date.now() + }); + }, + lchmod:(path, mode) => { + FS.chmod(path, mode, true); + }, + fchmod:(fd, mode) => { + var stream = FS.getStreamChecked(fd); + FS.chmod(stream.node, mode); + }, + chown:(path, uid, gid, dontFollow) => { + var node; + if (typeof path == 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(63); + } + node.node_ops.setattr(node, { + timestamp: Date.now() + // we ignore the uid / gid for now + }); + }, + lchown:(path, uid, gid) => { + FS.chown(path, uid, gid, true); + }, + fchown:(fd, uid, gid) => { + var stream = FS.getStreamChecked(fd); + FS.chown(stream.node, uid, gid); + }, + truncate:(path, len) => { + if (len < 0) { + throw new FS.ErrnoError(28); + } + var node; + if (typeof path == 'string') { + var lookup = FS.lookupPath(path, { follow: true }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(63); + } + if (FS.isDir(node.mode)) { + throw new FS.ErrnoError(31); + } + if (!FS.isFile(node.mode)) { + throw new FS.ErrnoError(28); + } + var errCode = FS.nodePermissions(node, 'w'); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + node.node_ops.setattr(node, { + size: len, + timestamp: Date.now() + }); + }, + ftruncate:(fd, len) => { + var stream = FS.getStreamChecked(fd); + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(28); + } + FS.truncate(stream.node, len); + }, + utime:(path, atime, mtime) => { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + node.node_ops.setattr(node, { + timestamp: Math.max(atime, mtime) + }); + }, + open:(path, flags, mode) => { + if (path === "") { + throw new FS.ErrnoError(44); + } + flags = typeof flags == 'string' ? FS_modeStringToFlags(flags) : flags; + mode = typeof mode == 'undefined' ? 438 /* 0666 */ : mode; + if ((flags & 64)) { + mode = (mode & 4095) | 32768; + } else { + mode = 0; + } + var node; + if (typeof path == 'object') { + node = path; + } else { + path = PATH.normalize(path); + try { + var lookup = FS.lookupPath(path, { + follow: !(flags & 131072) + }); + node = lookup.node; + } catch (e) { + // ignore + } + } + // perhaps we need to create the node + var created = false; + if ((flags & 64)) { + if (node) { + // if O_CREAT and O_EXCL are set, error out if the node already exists + if ((flags & 128)) { + throw new FS.ErrnoError(20); + } + } else { + // node doesn't exist, try to create it + node = FS.mknod(path, mode, 0); + created = true; + } + } + if (!node) { + throw new FS.ErrnoError(44); + } + // can't truncate a device + if (FS.isChrdev(node.mode)) { + flags &= ~512; + } + // if asked only for a directory, then this must be one + if ((flags & 65536) && !FS.isDir(node.mode)) { + throw new FS.ErrnoError(54); + } + // check permissions, if this is not a file we just created now (it is ok to + // create and write to a file with read-only permissions; it is read-only + // for later use) + if (!created) { + var errCode = FS.mayOpen(node, flags); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + } + // do truncation if necessary + if ((flags & 512) && !created) { + FS.truncate(node, 0); + } + // we've already handled these, don't pass down to the underlying vfs + flags &= ~(128 | 512 | 131072); + + // register the stream with the filesystem + var stream = FS.createStream({ + node, + path: FS.getPath(node), // we want the absolute path to the node + flags, + seekable: true, + position: 0, + stream_ops: node.stream_ops, + // used by the file family libc calls (fopen, fwrite, ferror, etc.) + ungotten: [], + error: false + }); + // call the new stream's open function + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + if (Module['logReadFiles'] && !(flags & 1)) { + if (!FS.readFiles) FS.readFiles = {}; + if (!(path in FS.readFiles)) { + FS.readFiles[path] = 1; + } + } + return stream; + }, + close:(stream) => { + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if (stream.getdents) stream.getdents = null; // free readdir state + try { + if (stream.stream_ops.close) { + stream.stream_ops.close(stream); + } + } catch (e) { + throw e; + } finally { + FS.closeStream(stream.fd); + } + stream.fd = null; + }, + isClosed:(stream) => { + return stream.fd === null; + }, + llseek:(stream, offset, whence) => { + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if (!stream.seekable || !stream.stream_ops.llseek) { + throw new FS.ErrnoError(70); + } + if (whence != 0 && whence != 1 && whence != 2) { + throw new FS.ErrnoError(28); + } + stream.position = stream.stream_ops.llseek(stream, offset, whence); + stream.ungotten = []; + return stream.position; + }, + read:(stream, buffer, offset, length, position) => { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(28); + } + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(8); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(31); + } + if (!stream.stream_ops.read) { + throw new FS.ErrnoError(28); + } + var seeking = typeof position != 'undefined'; + if (!seeking) { + position = stream.position; + } else if (!stream.seekable) { + throw new FS.ErrnoError(70); + } + var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position); + if (!seeking) stream.position += bytesRead; + return bytesRead; + }, + write:(stream, buffer, offset, length, position, canOwn) => { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(28); + } + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(8); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(31); + } + if (!stream.stream_ops.write) { + throw new FS.ErrnoError(28); + } + if (stream.seekable && stream.flags & 1024) { + // seek to the end before writing in append mode + FS.llseek(stream, 0, 2); + } + var seeking = typeof position != 'undefined'; + if (!seeking) { + position = stream.position; + } else if (!stream.seekable) { + throw new FS.ErrnoError(70); + } + var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn); + if (!seeking) stream.position += bytesWritten; + return bytesWritten; + }, + allocate:(stream, offset, length) => { + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if (offset < 0 || length <= 0) { + throw new FS.ErrnoError(28); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(8); + } + if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(43); + } + if (!stream.stream_ops.allocate) { + throw new FS.ErrnoError(138); + } + stream.stream_ops.allocate(stream, offset, length); + }, + mmap:(stream, length, position, prot, flags) => { + // User requests writing to file (prot & PROT_WRITE != 0). + // Checking if we have permissions to write to the file unless + // MAP_PRIVATE flag is set. According to POSIX spec it is possible + // to write to file opened in read-only mode with MAP_PRIVATE flag, + // as all modifications will be visible only in the memory of + // the current process. + if ((prot & 2) !== 0 + && (flags & 2) === 0 + && (stream.flags & 2097155) !== 2) { + throw new FS.ErrnoError(2); + } + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(2); + } + if (!stream.stream_ops.mmap) { + throw new FS.ErrnoError(43); + } + return stream.stream_ops.mmap(stream, length, position, prot, flags); + }, + msync:(stream, buffer, offset, length, mmapFlags) => { + if (!stream.stream_ops.msync) { + return 0; + } + return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags); + }, + munmap:(stream) => 0, + ioctl:(stream, cmd, arg) => { + if (!stream.stream_ops.ioctl) { + throw new FS.ErrnoError(59); + } + return stream.stream_ops.ioctl(stream, cmd, arg); + }, + readFile:(path, opts = {}) => { + opts.flags = opts.flags || 0; + opts.encoding = opts.encoding || 'binary'; + if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { + throw new Error(`Invalid encoding type "${opts.encoding}"`); + } + var ret; + var stream = FS.open(path, opts.flags); + var stat = FS.stat(path); + var length = stat.size; + var buf = new Uint8Array(length); + FS.read(stream, buf, 0, length, 0); + if (opts.encoding === 'utf8') { + ret = UTF8ArrayToString(buf, 0); + } else if (opts.encoding === 'binary') { + ret = buf; + } + FS.close(stream); + return ret; + }, + writeFile:(path, data, opts = {}) => { + opts.flags = opts.flags || 577; + var stream = FS.open(path, opts.flags, opts.mode); + if (typeof data == 'string') { + var buf = new Uint8Array(lengthBytesUTF8(data)+1); + var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length); + FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn); + } else if (ArrayBuffer.isView(data)) { + FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn); + } else { + throw new Error('Unsupported data type'); + } + FS.close(stream); + }, + cwd:() => FS.currentPath, + chdir:(path) => { + var lookup = FS.lookupPath(path, { follow: true }); + if (lookup.node === null) { + throw new FS.ErrnoError(44); + } + if (!FS.isDir(lookup.node.mode)) { + throw new FS.ErrnoError(54); + } + var errCode = FS.nodePermissions(lookup.node, 'x'); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + FS.currentPath = lookup.path; + }, + createDefaultDirectories:() => { + FS.mkdir('/tmp'); + FS.mkdir('/home'); + FS.mkdir('/home/web_user'); + }, + createDefaultDevices:() => { + // create /dev + FS.mkdir('/dev'); + // setup /dev/null + FS.registerDevice(FS.makedev(1, 3), { + read: () => 0, + write: (stream, buffer, offset, length, pos) => length, + }); + FS.mkdev('/dev/null', FS.makedev(1, 3)); + // setup /dev/tty and /dev/tty1 + // stderr needs to print output using err() rather than out() + // so we register a second tty just for it. + TTY.register(FS.makedev(5, 0), TTY.default_tty_ops); + TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops); + FS.mkdev('/dev/tty', FS.makedev(5, 0)); + FS.mkdev('/dev/tty1', FS.makedev(6, 0)); + // setup /dev/[u]random + // use a buffer to avoid overhead of individual crypto calls per byte + var randomBuffer = new Uint8Array(1024), randomLeft = 0; + var randomByte = () => { + if (randomLeft === 0) { + randomLeft = randomFill(randomBuffer).byteLength; + } + return randomBuffer[--randomLeft]; + }; + FS.createDevice('/dev', 'random', randomByte); + FS.createDevice('/dev', 'urandom', randomByte); + // we're not going to emulate the actual shm device, + // just create the tmp dirs that reside in it commonly + FS.mkdir('/dev/shm'); + FS.mkdir('/dev/shm/tmp'); + }, + createSpecialDirectories:() => { + // create /proc/self/fd which allows /proc/self/fd/6 => readlink gives the + // name of the stream for fd 6 (see test_unistd_ttyname) + FS.mkdir('/proc'); + var proc_self = FS.mkdir('/proc/self'); + FS.mkdir('/proc/self/fd'); + FS.mount({ + mount: () => { + var node = FS.createNode(proc_self, 'fd', 16384 | 511 /* 0777 */, 73); + node.node_ops = { + lookup: (parent, name) => { + var fd = +name; + var stream = FS.getStreamChecked(fd); + var ret = { + parent: null, + mount: { mountpoint: 'fake' }, + node_ops: { readlink: () => stream.path }, + }; + ret.parent = ret; // make it look like a simple root node + return ret; + } + }; + return node; + } + }, {}, '/proc/self/fd'); + }, + createStandardStreams:() => { + // TODO deprecate the old functionality of a single + // input / output callback and that utilizes FS.createDevice + // and instead require a unique set of stream ops + + // by default, we symlink the standard streams to the + // default tty devices. however, if the standard streams + // have been overwritten we create a unique device for + // them instead. + if (Module['stdin']) { + FS.createDevice('/dev', 'stdin', Module['stdin']); + } else { + FS.symlink('/dev/tty', '/dev/stdin'); + } + if (Module['stdout']) { + FS.createDevice('/dev', 'stdout', null, Module['stdout']); + } else { + FS.symlink('/dev/tty', '/dev/stdout'); + } + if (Module['stderr']) { + FS.createDevice('/dev', 'stderr', null, Module['stderr']); + } else { + FS.symlink('/dev/tty1', '/dev/stderr'); + } + + // open default streams for the stdin, stdout and stderr devices + var stdin = FS.open('/dev/stdin', 0); + var stdout = FS.open('/dev/stdout', 1); + var stderr = FS.open('/dev/stderr', 1); + }, + ensureErrnoError:() => { + if (FS.ErrnoError) return; + FS.ErrnoError = /** @this{Object} */ function ErrnoError(errno, node) { + // We set the `name` property to be able to identify `FS.ErrnoError` + // - the `name` is a standard ECMA-262 property of error objects. Kind of good to have it anyway. + // - when using PROXYFS, an error can come from an underlying FS + // as different FS objects have their own FS.ErrnoError each, + // the test `err instanceof FS.ErrnoError` won't detect an error coming from another filesystem, causing bugs. + // we'll use the reliable test `err.name == "ErrnoError"` instead + this.name = 'ErrnoError'; + this.node = node; + this.setErrno = /** @this{Object} */ function(errno) { + this.errno = errno; + }; + this.setErrno(errno); + this.message = 'FS error'; + + }; + FS.ErrnoError.prototype = new Error(); + FS.ErrnoError.prototype.constructor = FS.ErrnoError; + // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info) + [44].forEach((code) => { + FS.genericErrors[code] = new FS.ErrnoError(code); + FS.genericErrors[code].stack = ''; + }); + }, + staticInit:() => { + FS.ensureErrnoError(); + + FS.nameTable = new Array(4096); + + FS.mount(MEMFS, {}, '/'); + + FS.createDefaultDirectories(); + FS.createDefaultDevices(); + FS.createSpecialDirectories(); + + FS.filesystems = { + 'MEMFS': MEMFS, + 'NODEFS': NODEFS, + 'PROXYFS': PROXYFS, + }; + }, + init:(input, output, error) => { + FS.init.initialized = true; + + FS.ensureErrnoError(); + + // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here + Module['stdin'] = input || Module['stdin']; + Module['stdout'] = output || Module['stdout']; + Module['stderr'] = error || Module['stderr']; + + FS.createStandardStreams(); + }, + quit:() => { + FS.init.initialized = false; + // force-flush all streams, so we get musl std streams printed out + _fflush(0); + // close all of our streams + for (var i = 0; i < FS.streams.length; i++) { + var stream = FS.streams[i]; + if (!stream) { + continue; + } + FS.close(stream); + } + }, + findObject:(path, dontResolveLastLink) => { + var ret = FS.analyzePath(path, dontResolveLastLink); + if (!ret.exists) { + return null; + } + return ret.object; + }, + analyzePath:(path, dontResolveLastLink) => { + // operate from within the context of the symlink's target + try { + var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); + path = lookup.path; + } catch (e) { + } + var ret = { + isRoot: false, exists: false, error: 0, name: null, path: null, object: null, + parentExists: false, parentPath: null, parentObject: null + }; + try { + var lookup = FS.lookupPath(path, { parent: true }); + ret.parentExists = true; + ret.parentPath = lookup.path; + ret.parentObject = lookup.node; + ret.name = PATH.basename(path); + lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); + ret.exists = true; + ret.path = lookup.path; + ret.object = lookup.node; + ret.name = lookup.node.name; + ret.isRoot = lookup.path === '/'; + } catch (e) { + ret.error = e.errno; + }; + return ret; + }, + createPath:(parent, path, canRead, canWrite) => { + parent = typeof parent == 'string' ? parent : FS.getPath(parent); + var parts = path.split('/').reverse(); + while (parts.length) { + var part = parts.pop(); + if (!part) continue; + var current = PATH.join2(parent, part); + try { + FS.mkdir(current); + } catch (e) { + // ignore EEXIST + } + parent = current; + } + return current; + }, + createFile:(parent, name, properties, canRead, canWrite) => { + var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name); + var mode = FS_getMode(canRead, canWrite); + return FS.create(path, mode); + }, + createDataFile:(parent, name, data, canRead, canWrite, canOwn) => { + var path = name; + if (parent) { + parent = typeof parent == 'string' ? parent : FS.getPath(parent); + path = name ? PATH.join2(parent, name) : parent; + } + var mode = FS_getMode(canRead, canWrite); + var node = FS.create(path, mode); + if (data) { + if (typeof data == 'string') { + var arr = new Array(data.length); + for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i); + data = arr; + } + // make sure we can write to the file + FS.chmod(node, mode | 146); + var stream = FS.open(node, 577); + FS.write(stream, data, 0, data.length, 0, canOwn); + FS.close(stream); + FS.chmod(node, mode); + } + return node; + }, + createDevice:(parent, name, input, output) => { + var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name); + var mode = FS_getMode(!!input, !!output); + if (!FS.createDevice.major) FS.createDevice.major = 64; + var dev = FS.makedev(FS.createDevice.major++, 0); + // Create a fake device that a set of stream ops to emulate + // the old behavior. + FS.registerDevice(dev, { + open: (stream) => { + stream.seekable = false; + }, + close: (stream) => { + // flush any pending line data + if (output && output.buffer && output.buffer.length) { + output(10); + } + }, + read: (stream, buffer, offset, length, pos /* ignored */) => { + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = input(); + } catch (e) { + throw new FS.ErrnoError(29); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(6); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + }, + write: (stream, buffer, offset, length, pos) => { + for (var i = 0; i < length; i++) { + try { + output(buffer[offset+i]); + } catch (e) { + throw new FS.ErrnoError(29); + } + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + } + }); + return FS.mkdev(path, mode, dev); + }, + forceLoadFile:(obj) => { + if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; + if (typeof XMLHttpRequest != 'undefined') { + throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); + } else if (read_) { + // Command-line. + try { + // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as + // read() will try to parse UTF8. + obj.contents = intArrayFromString(read_(obj.url), true); + obj.usedBytes = obj.contents.length; + } catch (e) { + throw new FS.ErrnoError(29); + } + } else { + throw new Error('Cannot load without read() or XMLHttpRequest.'); + } + }, + createLazyFile:(parent, name, url, canRead, canWrite) => { + // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse. + /** @constructor */ + function LazyUint8Array() { + this.lengthKnown = false; + this.chunks = []; // Loaded chunks. Index is the chunk number + } + LazyUint8Array.prototype.get = /** @this{Object} */ function LazyUint8Array_get(idx) { + if (idx > this.length-1 || idx < 0) { + return undefined; + } + var chunkOffset = idx % this.chunkSize; + var chunkNum = (idx / this.chunkSize)|0; + return this.getter(chunkNum)[chunkOffset]; + }; + LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) { + this.getter = getter; + }; + LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() { + // Find length + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', url, false); + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + var datalength = Number(xhr.getResponseHeader("Content-length")); + var header; + var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes"; + var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip"; + + var chunkSize = 1024*1024; // Chunk size in bytes + + if (!hasByteServing) chunkSize = datalength; + + // Function to get a range from the remote URL. + var doXHR = (from, to) => { + if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); + if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); + + // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + + // Some hints to the browser that we want binary data. + xhr.responseType = 'arraybuffer'; + if (xhr.overrideMimeType) { + xhr.overrideMimeType('text/plain; charset=x-user-defined'); + } + + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + if (xhr.response !== undefined) { + return new Uint8Array(/** @type{Array} */(xhr.response || [])); + } + return intArrayFromString(xhr.responseText || '', true); + }; + var lazyArray = this; + lazyArray.setDataGetter((chunkNum) => { + var start = chunkNum * chunkSize; + var end = (chunkNum+1) * chunkSize - 1; // including this byte + end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block + if (typeof lazyArray.chunks[chunkNum] == 'undefined') { + lazyArray.chunks[chunkNum] = doXHR(start, end); + } + if (typeof lazyArray.chunks[chunkNum] == 'undefined') throw new Error('doXHR failed!'); + return lazyArray.chunks[chunkNum]; + }); + + if (usesGzip || !datalength) { + // if the server uses gzip or doesn't supply the length, we have to download the whole file to get the (uncompressed) length + chunkSize = datalength = 1; // this will force getter(0)/doXHR do download the whole file + datalength = this.getter(0).length; + chunkSize = datalength; + out("LazyFiles on gzip forces download of the whole file when length is accessed"); + } + + this._length = datalength; + this._chunkSize = chunkSize; + this.lengthKnown = true; + }; + if (typeof XMLHttpRequest != 'undefined') { + if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'; + var lazyArray = new LazyUint8Array(); + Object.defineProperties(lazyArray, { + length: { + get: /** @this{Object} */ function() { + if (!this.lengthKnown) { + this.cacheLength(); + } + return this._length; + } + }, + chunkSize: { + get: /** @this{Object} */ function() { + if (!this.lengthKnown) { + this.cacheLength(); + } + return this._chunkSize; + } + } + }); + + var properties = { isDevice: false, contents: lazyArray }; + } else { + var properties = { isDevice: false, url: url }; + } + + var node = FS.createFile(parent, name, properties, canRead, canWrite); + // This is a total hack, but I want to get this lazy file code out of the + // core of MEMFS. If we want to keep this lazy file concept I feel it should + // be its own thin LAZYFS proxying calls to MEMFS. + if (properties.contents) { + node.contents = properties.contents; + } else if (properties.url) { + node.contents = null; + node.url = properties.url; + } + // Add a function that defers querying the file size until it is asked the first time. + Object.defineProperties(node, { + usedBytes: { + get: /** @this {FSNode} */ function() { return this.contents.length; } + } + }); + // override each stream op with one that tries to force load the lazy file first + var stream_ops = {}; + var keys = Object.keys(node.stream_ops); + keys.forEach((key) => { + var fn = node.stream_ops[key]; + stream_ops[key] = function forceLoadLazyFile() { + FS.forceLoadFile(node); + return fn.apply(null, arguments); + }; + }); + function writeChunks(stream, buffer, offset, length, position) { + var contents = stream.node.contents; + if (position >= contents.length) + return 0; + var size = Math.min(contents.length - position, length); + if (contents.slice) { // normal array + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents[position + i]; + } + } else { + for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR + buffer[offset + i] = contents.get(position + i); + } + } + return size; + } + // use a custom read function + stream_ops.read = (stream, buffer, offset, length, position) => { + FS.forceLoadFile(node); + return writeChunks(stream, buffer, offset, length, position) + }; + // use a custom mmap function + stream_ops.mmap = (stream, length, position, prot, flags) => { + FS.forceLoadFile(node); + var ptr = mmapAlloc(length); + if (!ptr) { + throw new FS.ErrnoError(48); + } + writeChunks(stream, HEAP8, ptr, length, position); + return { ptr, allocated: true }; + }; + node.stream_ops = stream_ops; + return node; + }, + }; + Module['FS'] = FS; + var SOCKFS = { + mount(mount) { + // If Module['websocket'] has already been defined (e.g. for configuring + // the subprotocol/url) use that, if not initialise it to a new object. + Module['websocket'] = (Module['websocket'] && + ('object' === typeof Module['websocket'])) ? Module['websocket'] : {}; + + // Add the Event registration mechanism to the exported websocket configuration + // object so we can register network callbacks from native JavaScript too. + // For more documentation see system/include/emscripten/emscripten.h + Module['websocket']._callbacks = {}; + Module['websocket']['on'] = /** @this{Object} */ function(event, callback) { + if ('function' === typeof callback) { + this._callbacks[event] = callback; + } + return this; + }; + + Module['websocket'].emit = /** @this{Object} */ function(event, param) { + if ('function' === typeof this._callbacks[event]) { + this._callbacks[event].call(this, param); + } + }; + + // If debug is enabled register simple default logging callbacks for each Event. + + return FS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + }, + createSocket(family, type, protocol) { + type &= ~526336; // Some applications may pass it; it makes no sense for a single process. + var streaming = type == 1; + if (streaming && protocol && protocol != 6) { + throw new FS.ErrnoError(66); // if SOCK_STREAM, must be tcp or 0. + } + + // create our internal socket structure + var sock = { + family, + type, + protocol, + server: null, + error: null, // Used in getsockopt for SOL_SOCKET/SO_ERROR test + peers: {}, + pending: [], + recv_queue: [], + sock_ops: SOCKFS.websocket_sock_ops + }; + + // create the filesystem node to store the socket structure + var name = SOCKFS.nextname(); + var node = FS.createNode(SOCKFS.root, name, 49152, 0); + node.sock = sock; + + // and the wrapping stream that enables library functions such + // as read and write to indirectly interact with the socket + var stream = FS.createStream({ + path: name, + node, + flags: 2, + seekable: false, + stream_ops: SOCKFS.stream_ops + }); + + // map the new stream to the socket structure (sockets have a 1:1 + // relationship with a stream) + sock.stream = stream; + + return sock; + }, + getSocket(fd) { + var stream = FS.getStream(fd); + if (!stream || !FS.isSocket(stream.node.mode)) { + return null; + } + return stream.node.sock; + }, + stream_ops:{ + poll(stream) { + var sock = stream.node.sock; + return sock.sock_ops.poll(sock); + }, + ioctl(stream, request, varargs) { + var sock = stream.node.sock; + return sock.sock_ops.ioctl(sock, request, varargs); + }, + read(stream, buffer, offset, length, position /* ignored */) { + var sock = stream.node.sock; + var msg = sock.sock_ops.recvmsg(sock, length); + if (!msg) { + // socket is closed + return 0; + } + buffer.set(msg.buffer, offset); + return msg.buffer.length; + }, + write(stream, buffer, offset, length, position /* ignored */) { + var sock = stream.node.sock; + return sock.sock_ops.sendmsg(sock, buffer, offset, length); + }, close(stream) { - var sock = stream.node.sock; - sock.sock_ops.close(sock); - } - }, - nextname() { - if (!SOCKFS.nextname.current) { - SOCKFS.nextname.current = 0; - } - return "socket[" + SOCKFS.nextname.current++ + "]"; - }, - websocket_sock_ops: { + var sock = stream.node.sock; + sock.sock_ops.close(sock); + }, + }, + nextname() { + if (!SOCKFS.nextname.current) { + SOCKFS.nextname.current = 0; + } + return 'socket[' + (SOCKFS.nextname.current++) + ']'; + }, + websocket_sock_ops:{ createPeer(sock, addr, port) { - var ws; - if (typeof addr == "object") { - ws = addr; - addr = null; - port = null; - } - if (ws) { - if (ws._socket) { - addr = ws._socket.remoteAddress; - port = ws._socket.remotePort; - } else { - var result = /ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url); - if (!result) { - throw new Error("WebSocket URL must be in the format ws(s)://address:port"); - } - addr = result[1]; - port = parseInt(result[2], 10); - } - } else { - try { - var runtimeConfig = Module["websocket"] && "object" === typeof Module["websocket"]; - var url = "ws:#".replace("#", "//"); - if (runtimeConfig) { - if("function"===typeof Module["websocket"]["url"]) { + var ws; + + if (typeof addr == 'object') { + ws = addr; + addr = null; + port = null; + } + + if (ws) { + // for sockets that've already connected (e.g. we're the server) + // we can inspect the _socket property for the address + if (ws._socket) { + addr = ws._socket.remoteAddress; + port = ws._socket.remotePort; + } + // if we're just now initializing a connection to the remote, + // inspect the url property + else { + var result = /ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url); + if (!result) { + throw new Error('WebSocket URL must be in the format ws(s)://address:port'); + } + addr = result[1]; + port = parseInt(result[2], 10); + } + } else { + // create the actual websocket object and connect + try { + // runtimeConfig gets set to true if WebSocket runtime configuration is available. + var runtimeConfig = (Module['websocket'] && ('object' === typeof Module['websocket'])); + + // The default value is 'ws://' the replace is needed because the compiler replaces '//' comments with '#' + // comments without checking context, so we'd end up with ws:#, the replace swaps the '#' for '//' again. + var url = 'ws:#'.replace('#', '//'); + + if (runtimeConfig) { + if("function"===typeof Module["websocket"]["url"]) { url = Module["websocket"]["url"](...arguments); }else if ("string" === typeof Module["websocket"]["url"]) { - url = Module["websocket"]["url"]; - } - } - if (url === "ws://" || url === "wss://") { - var parts = addr.split("/"); - url = url + parts[0] + ":" + port + "/" + parts.slice(1).join("/"); - } - var subProtocols = "binary"; - if (runtimeConfig) { - if ("string" === typeof Module["websocket"]["subprotocol"]) { - subProtocols = Module["websocket"]["subprotocol"]; - } - } - var opts = undefined; - if (subProtocols !== "null") { - subProtocols = subProtocols.replace(/^ +| +$/g, "").split(/ *, */); - opts = subProtocols; - } - if (runtimeConfig && null === Module["websocket"]["subprotocol"]) { - subProtocols = "null"; - opts = undefined; - } - var WebSocketConstructor; - if (ENVIRONMENT_IS_NODE) { - WebSocketConstructor = require("ws"); - } else { - WebSocketConstructor = WebSocket; - } - if (Module['websocket']['decorator']) {WebSocketConstructor = Module['websocket']['decorator'](WebSocketConstructor);}ws = new WebSocketConstructor(url, opts); - ws.binaryType = "arraybuffer"; - } catch (e) { - throw new FS.ErrnoError(23); - } - } - var peer = { - addr: addr, - port: port, - socket: ws, - dgram_send_queue: [] - }; - SOCKFS.websocket_sock_ops.addPeer(sock, peer); - SOCKFS.websocket_sock_ops.handlePeerEvents(sock, peer); - if (sock.type === 2 && typeof sock.sport != "undefined") { - peer.dgram_send_queue.push(new Uint8Array([ 255, 255, 255, 255, "p".charCodeAt(0), "o".charCodeAt(0), "r".charCodeAt(0), "t".charCodeAt(0), (sock.sport & 65280) >> 8, sock.sport & 255 ])); - } - return peer; - }, + url = Module['websocket']['url']; // Fetch runtime WebSocket URL config. + } + } + + if (url === 'ws://' || url === 'wss://') { // Is the supplied URL config just a prefix, if so complete it. + var parts = addr.split('/'); + url = url + parts[0] + ":" + port + "/" + parts.slice(1).join('/'); + } + + // Make the WebSocket subprotocol (Sec-WebSocket-Protocol) default to binary if no configuration is set. + var subProtocols = 'binary'; // The default value is 'binary' + + if (runtimeConfig) { + if ('string' === typeof Module['websocket']['subprotocol']) { + subProtocols = Module['websocket']['subprotocol']; // Fetch runtime WebSocket subprotocol config. + } + } + + // The default WebSocket options + var opts = undefined; + + if (subProtocols !== 'null') { + // The regex trims the string (removes spaces at the beginning and end, then splits the string by + // , into an Array. Whitespace removal is important for Websockify and ws. + subProtocols = subProtocols.replace(/^ +| +$/g,"").split(/ *, */); + + opts = subProtocols; + } + + // some webservers (azure) does not support subprotocol header + if (runtimeConfig && null === Module['websocket']['subprotocol']) { + subProtocols = 'null'; + opts = undefined; + } + + // If node we use the ws library. + var WebSocketConstructor; + if (ENVIRONMENT_IS_NODE) { + WebSocketConstructor = /** @type{(typeof WebSocket)} */(require('ws')); + } else + { + WebSocketConstructor = WebSocket; + } + if (Module['websocket']['decorator']) {WebSocketConstructor = Module['websocket']['decorator'](WebSocketConstructor);}ws = new WebSocketConstructor(url, opts); + ws.binaryType = 'arraybuffer'; + } catch (e) { + throw new FS.ErrnoError(23); + } + } + + var peer = { + addr, + port, + socket: ws, + dgram_send_queue: [] + }; + + SOCKFS.websocket_sock_ops.addPeer(sock, peer); + SOCKFS.websocket_sock_ops.handlePeerEvents(sock, peer); + + // if this is a bound dgram socket, send the port number first to allow + // us to override the ephemeral port reported to us by remotePort on the + // remote end. + if (sock.type === 2 && typeof sock.sport != 'undefined') { + peer.dgram_send_queue.push(new Uint8Array([ + 255, 255, 255, 255, + 'p'.charCodeAt(0), 'o'.charCodeAt(0), 'r'.charCodeAt(0), 't'.charCodeAt(0), + ((sock.sport & 0xff00) >> 8) , (sock.sport & 0xff) + ])); + } + + return peer; + }, getPeer(sock, addr, port) { - return sock.peers[addr + ":" + port]; - }, + return sock.peers[addr + ':' + port]; + }, addPeer(sock, peer) { - sock.peers[peer.addr + ":" + peer.port] = peer; - }, + sock.peers[peer.addr + ':' + peer.port] = peer; + }, removePeer(sock, peer) { - delete sock.peers[peer.addr + ":" + peer.port]; - }, + delete sock.peers[peer.addr + ':' + peer.port]; + }, handlePeerEvents(sock, peer) { - var first = true; - var handleOpen = function() { - Module["websocket"].emit("open", sock.stream.fd); - try { - var queued = peer.dgram_send_queue.shift(); - while (queued) { - peer.socket.send(queued); - queued = peer.dgram_send_queue.shift(); - } - } catch (e) { - peer.socket.close(); - } - }; - function handleMessage(data) { - if (typeof data == "string") { - var encoder = new TextEncoder; - data = encoder.encode(data); - } else { - assert(data.byteLength !== undefined); - if (data.byteLength == 0) { - return; - } - data = new Uint8Array(data); - } - var wasfirst = first; - first = false; - if (wasfirst && data.length === 10 && data[0] === 255 && data[1] === 255 && data[2] === 255 && data[3] === 255 && data[4] === "p".charCodeAt(0) && data[5] === "o".charCodeAt(0) && data[6] === "r".charCodeAt(0) && data[7] === "t".charCodeAt(0)) { - var newport = data[8] << 8 | data[9]; - SOCKFS.websocket_sock_ops.removePeer(sock, peer); - peer.port = newport; - SOCKFS.websocket_sock_ops.addPeer(sock, peer); - return; - } - sock.recv_queue.push({ - addr: peer.addr, - port: peer.port, - data: data - }); - Module["websocket"].emit("message", sock.stream.fd); - } - if (ENVIRONMENT_IS_NODE) { - peer.socket.on("open", handleOpen); - peer.socket.on("message", (function(data, isBinary) { - if (!isBinary) { - return; - } - handleMessage(new Uint8Array(data).buffer); - })); - peer.socket.on("close", (function() { - Module["websocket"].emit("close", sock.stream.fd); - })); - peer.socket.on("error", (function(error) { - sock.error = 14; - Module["websocket"].emit("error", [ sock.stream.fd, sock.error, "ECONNREFUSED: Connection refused" ]); - })); - } else { - peer.socket.onopen = handleOpen; - peer.socket.onclose = function() { - Module["websocket"].emit("close", sock.stream.fd); - }; - peer.socket.onmessage = function peer_socket_onmessage(event) { - handleMessage(event.data); - }; - peer.socket.onerror = function(error) { - sock.error = 14; - Module["websocket"].emit("error", [ sock.stream.fd, sock.error, "ECONNREFUSED: Connection refused" ]); - }; - } - }, + var first = true; + + var handleOpen = function () { + + Module['websocket'].emit('open', sock.stream.fd); + + try { + var queued = peer.dgram_send_queue.shift(); + while (queued) { + peer.socket.send(queued); + queued = peer.dgram_send_queue.shift(); + } + } catch (e) { + // not much we can do here in the way of proper error handling as we've already + // lied and said this data was sent. shut it down. + peer.socket.close(); + } + }; + + function handleMessage(data) { + if (typeof data == 'string') { + var encoder = new TextEncoder(); // should be utf-8 + data = encoder.encode(data); // make a typed array from the string + } else { + assert(data.byteLength !== undefined); // must receive an ArrayBuffer + if (data.byteLength == 0) { + // An empty ArrayBuffer will emit a pseudo disconnect event + // as recv/recvmsg will return zero which indicates that a socket + // has performed a shutdown although the connection has not been disconnected yet. + return; + } + data = new Uint8Array(data); // make a typed array view on the array buffer + } + + // if this is the port message, override the peer's port with it + var wasfirst = first; + first = false; + if (wasfirst && + data.length === 10 && + data[0] === 255 && data[1] === 255 && data[2] === 255 && data[3] === 255 && + data[4] === 'p'.charCodeAt(0) && data[5] === 'o'.charCodeAt(0) && data[6] === 'r'.charCodeAt(0) && data[7] === 't'.charCodeAt(0)) { + // update the peer's port and it's key in the peer map + var newport = ((data[8] << 8) | data[9]); + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + peer.port = newport; + SOCKFS.websocket_sock_ops.addPeer(sock, peer); + return; + } + + sock.recv_queue.push({ addr: peer.addr, port: peer.port, data: data }); + Module['websocket'].emit('message', sock.stream.fd); + }; + + if (ENVIRONMENT_IS_NODE) { + peer.socket.on('open', handleOpen); + peer.socket.on('message', function(data, isBinary) { + if (!isBinary) { + return; + } + handleMessage((new Uint8Array(data)).buffer); // copy from node Buffer -> ArrayBuffer + }); + peer.socket.on('close', function() { + Module['websocket'].emit('close', sock.stream.fd); + }); + peer.socket.on('error', function(error) { + // Although the ws library may pass errors that may be more descriptive than + // ECONNREFUSED they are not necessarily the expected error code e.g. + // ENOTFOUND on getaddrinfo seems to be node.js specific, so using ECONNREFUSED + // is still probably the most useful thing to do. + sock.error = 14; // Used in getsockopt for SOL_SOCKET/SO_ERROR test. + Module['websocket'].emit('error', [sock.stream.fd, sock.error, 'ECONNREFUSED: Connection refused']); + // don't throw + }); + } else { + peer.socket.onopen = handleOpen; + peer.socket.onclose = function() { + Module['websocket'].emit('close', sock.stream.fd); + }; + peer.socket.onmessage = function peer_socket_onmessage(event) { + handleMessage(event.data); + }; + peer.socket.onerror = function(error) { + // The WebSocket spec only allows a 'simple event' to be thrown on error, + // so we only really know as much as ECONNREFUSED. + sock.error = 14; // Used in getsockopt for SOL_SOCKET/SO_ERROR test. + Module['websocket'].emit('error', [sock.stream.fd, sock.error, 'ECONNREFUSED: Connection refused']); + }; + } + }, poll(sock) { - if (sock.type === 1 && sock.server) { - return sock.pending.length ? 64 | 1 : 0; - } - var mask = 0; - var dest = sock.type === 1 ? SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport) : null; - if (sock.recv_queue.length || !dest || dest && dest.socket.readyState === dest.socket.CLOSING || dest && dest.socket.readyState === dest.socket.CLOSED) { - mask |= 64 | 1; - } - if (!dest || dest && dest.socket.readyState === dest.socket.OPEN) { - mask |= 4; - } - if (dest && dest.socket.readyState === dest.socket.CLOSING || dest && dest.socket.readyState === dest.socket.CLOSED) { - mask |= 16; - } - return mask; - }, + if (sock.type === 1 && sock.server) { + // listen sockets should only say they're available for reading + // if there are pending clients. + return sock.pending.length ? (64 | 1) : 0; + } + + var mask = 0; + var dest = sock.type === 1 ? // we only care about the socket state for connection-based sockets + SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport) : + null; + + if (sock.recv_queue.length || + !dest || // connection-less sockets are always ready to read + (dest && dest.socket.readyState === dest.socket.CLOSING) || + (dest && dest.socket.readyState === dest.socket.CLOSED)) { // let recv return 0 once closed + mask |= (64 | 1); + } + + if (!dest || // connection-less sockets are always ready to write + (dest && dest.socket.readyState === dest.socket.OPEN)) { + mask |= 4; + } + + if ((dest && dest.socket.readyState === dest.socket.CLOSING) || + (dest && dest.socket.readyState === dest.socket.CLOSED)) { + mask |= 16; + } + + return mask; + }, ioctl(sock, request, arg) { - switch (request) { - case 21531: - var bytes = 0; - if (sock.recv_queue.length) { - bytes = sock.recv_queue[0].data.length; - } - HEAP32[arg >> 2] = bytes; - return 0; - - default: - return 28; - } - }, + switch (request) { + case 21531: + var bytes = 0; + if (sock.recv_queue.length) { + bytes = sock.recv_queue[0].data.length; + } + HEAP32[((arg)>>2)] = bytes; + return 0; + default: + return 28; + } + }, close(sock) { - if (sock.server) { - try { - sock.server.close(); - } catch (e) {} - sock.server = null; - } - var peers = Object.keys(sock.peers); - for (var i = 0; i < peers.length; i++) { - var peer = sock.peers[peers[i]]; - try { - peer.socket.close(); - } catch (e) {} - SOCKFS.websocket_sock_ops.removePeer(sock, peer); - } - return 0; - }, + // if we've spawned a listen server, close it + if (sock.server) { + try { + sock.server.close(); + } catch (e) { + } + sock.server = null; + } + // close any peer connections + var peers = Object.keys(sock.peers); + for (var i = 0; i < peers.length; i++) { + var peer = sock.peers[peers[i]]; + try { + peer.socket.close(); + } catch (e) { + } + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + } + return 0; + }, bind(sock, addr, port) { - if (typeof sock.saddr != "undefined" || typeof sock.sport != "undefined") { - throw new FS.ErrnoError(28); - } - sock.saddr = addr; - sock.sport = port; - if (sock.type === 2) { - if (sock.server) { - sock.server.close(); - sock.server = null; - } - try { - sock.sock_ops.listen(sock, 0); - } catch (e) { - if (!(e.name === "ErrnoError")) throw e; - if (e.errno !== 138) throw e; - } - } - }, + if (typeof sock.saddr != 'undefined' || typeof sock.sport != 'undefined') { + throw new FS.ErrnoError(28); // already bound + } + sock.saddr = addr; + sock.sport = port; + // in order to emulate dgram sockets, we need to launch a listen server when + // binding on a connection-less socket + // note: this is only required on the server side + if (sock.type === 2) { + // close the existing server if it exists + if (sock.server) { + sock.server.close(); + sock.server = null; + } + // swallow error operation not supported error that occurs when binding in the + // browser where this isn't supported + try { + sock.sock_ops.listen(sock, 0); + } catch (e) { + if (!(e.name === 'ErrnoError')) throw e; + if (e.errno !== 138) throw e; + } + } + }, connect(sock, addr, port) { - if (sock.server) { - throw new FS.ErrnoError(138); - } - if (typeof sock.daddr != "undefined" && typeof sock.dport != "undefined") { - var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); - if (dest) { - if (dest.socket.readyState === dest.socket.CONNECTING) { - throw new FS.ErrnoError(7); - } else { - throw new FS.ErrnoError(30); - } - } - } - var peer = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); - sock.daddr = peer.addr; - sock.dport = peer.port; - throw new FS.ErrnoError(26); - }, + if (sock.server) { + throw new FS.ErrnoError(138); + } + + // TODO autobind + // if (!sock.addr && sock.type == 2) { + // } + + // early out if we're already connected / in the middle of connecting + if (typeof sock.daddr != 'undefined' && typeof sock.dport != 'undefined') { + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); + if (dest) { + if (dest.socket.readyState === dest.socket.CONNECTING) { + throw new FS.ErrnoError(7); + } else { + throw new FS.ErrnoError(30); + } + } + } + + // add the socket to our peer list and set our + // destination address / port to match + var peer = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); + sock.daddr = peer.addr; + sock.dport = peer.port; + + // always "fail" in non-blocking mode + throw new FS.ErrnoError(26); + }, listen(sock, backlog) { - if (!ENVIRONMENT_IS_NODE) { - throw new FS.ErrnoError(138); - } - if (sock.server) { - throw new FS.ErrnoError(28); - } - var WebSocketServer = require("ws").Server; - var host = sock.saddr; - if (Module['websocket']['serverDecorator']) {WebSocketServer = Module['websocket']['serverDecorator'](WebSocketServer);}sock.server = new WebSocketServer({ - host: host, - port: sock.sport - }); - Module["websocket"].emit("listen", sock.stream.fd); - sock.server.on("connection", (function(ws) { - if (sock.type === 1) { - var newsock = SOCKFS.createSocket(sock.family, sock.type, sock.protocol); - var peer = SOCKFS.websocket_sock_ops.createPeer(newsock, ws); - newsock.daddr = peer.addr; - newsock.dport = peer.port; - sock.pending.push(newsock); - Module["websocket"].emit("connection", newsock.stream.fd); - } else { - SOCKFS.websocket_sock_ops.createPeer(sock, ws); - Module["websocket"].emit("connection", sock.stream.fd); - } - })); - sock.server.on("close", (function() { - Module["websocket"].emit("close", sock.stream.fd); - sock.server = null; - })); - sock.server.on("error", (function(error) { - sock.error = 23; - Module["websocket"].emit("error", [ sock.stream.fd, sock.error, "EHOSTUNREACH: Host is unreachable" ]); - })); - }, + if (!ENVIRONMENT_IS_NODE) { + throw new FS.ErrnoError(138); + } + if (sock.server) { + throw new FS.ErrnoError(28); // already listening + } + var WebSocketServer = require('ws').Server; + var host = sock.saddr; + if (Module['websocket']['serverDecorator']) {WebSocketServer = Module['websocket']['serverDecorator'](WebSocketServer);}sock.server = new WebSocketServer({ + host, + port: sock.sport + // TODO support backlog + }); + Module['websocket'].emit('listen', sock.stream.fd); // Send Event with listen fd. + + sock.server.on('connection', function(ws) { + if (sock.type === 1) { + var newsock = SOCKFS.createSocket(sock.family, sock.type, sock.protocol); + + // create a peer on the new socket + var peer = SOCKFS.websocket_sock_ops.createPeer(newsock, ws); + newsock.daddr = peer.addr; + newsock.dport = peer.port; + + // push to queue for accept to pick up + sock.pending.push(newsock); + Module['websocket'].emit('connection', newsock.stream.fd); + } else { + // create a peer on the listen socket so calling sendto + // with the listen socket and an address will resolve + // to the correct client + SOCKFS.websocket_sock_ops.createPeer(sock, ws); + Module['websocket'].emit('connection', sock.stream.fd); + } + }); + sock.server.on('close', function() { + Module['websocket'].emit('close', sock.stream.fd); + sock.server = null; + }); + sock.server.on('error', function(error) { + // Although the ws library may pass errors that may be more descriptive than + // ECONNREFUSED they are not necessarily the expected error code e.g. + // ENOTFOUND on getaddrinfo seems to be node.js specific, so using EHOSTUNREACH + // is still probably the most useful thing to do. This error shouldn't + // occur in a well written app as errors should get trapped in the compiled + // app's own getaddrinfo call. + sock.error = 23; // Used in getsockopt for SOL_SOCKET/SO_ERROR test. + Module['websocket'].emit('error', [sock.stream.fd, sock.error, 'EHOSTUNREACH: Host is unreachable']); + // don't throw + }); + }, accept(listensock) { - if (!listensock.server || !listensock.pending.length) { - throw new FS.ErrnoError(28); - } - var newsock = listensock.pending.shift(); - newsock.stream.flags = listensock.stream.flags; - return newsock; - }, + if (!listensock.server || !listensock.pending.length) { + throw new FS.ErrnoError(28); + } + var newsock = listensock.pending.shift(); + newsock.stream.flags = listensock.stream.flags; + return newsock; + }, getname(sock, peer) { - var addr, port; - if (peer) { - if (sock.daddr === undefined || sock.dport === undefined) { - throw new FS.ErrnoError(53); - } - addr = sock.daddr; - port = sock.dport; - } else { - addr = sock.saddr || 0; - port = sock.sport || 0; - } - return { - addr: addr, - port: port - }; - }, + var addr, port; + if (peer) { + if (sock.daddr === undefined || sock.dport === undefined) { + throw new FS.ErrnoError(53); + } + addr = sock.daddr; + port = sock.dport; + } else { + // TODO saddr and sport will be set for bind()'d UDP sockets, but what + // should we be returning for TCP sockets that've been connect()'d? + addr = sock.saddr || 0; + port = sock.sport || 0; + } + return { addr, port }; + }, sendmsg(sock, buffer, offset, length, addr, port) { - if (sock.type === 2) { - if (addr === undefined || port === undefined) { - addr = sock.daddr; - port = sock.dport; - } - if (addr === undefined || port === undefined) { - throw new FS.ErrnoError(17); - } - } else { - addr = sock.daddr; - port = sock.dport; - } - var dest = SOCKFS.websocket_sock_ops.getPeer(sock, addr, port); - if (sock.type === 1) { - if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { - throw new FS.ErrnoError(53); - } else if (dest.socket.readyState === dest.socket.CONNECTING) { - throw new FS.ErrnoError(6); - } - } - if (ArrayBuffer.isView(buffer)) { - offset += buffer.byteOffset; - buffer = buffer.buffer; - } - var data; - data = buffer.slice(offset, offset + length); - if (sock.type === 2) { - if (!dest || dest.socket.readyState !== dest.socket.OPEN) { - if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { - dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); - } - dest.dgram_send_queue.push(data); - return length; - } - } - try { - dest.socket.send(data); - return length; - } catch (e) { - throw new FS.ErrnoError(28); - } - }, + if (sock.type === 2) { + // connection-less sockets will honor the message address, + // and otherwise fall back to the bound destination address + if (addr === undefined || port === undefined) { + addr = sock.daddr; + port = sock.dport; + } + // if there was no address to fall back to, error out + if (addr === undefined || port === undefined) { + throw new FS.ErrnoError(17); + } + } else { + // connection-based sockets will only use the bound + addr = sock.daddr; + port = sock.dport; + } + + // find the peer for the destination address + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, addr, port); + + // early out if not connected with a connection-based socket + if (sock.type === 1) { + if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + throw new FS.ErrnoError(53); + } else if (dest.socket.readyState === dest.socket.CONNECTING) { + throw new FS.ErrnoError(6); + } + } + + // create a copy of the incoming data to send, as the WebSocket API + // doesn't work entirely with an ArrayBufferView, it'll just send + // the entire underlying buffer + if (ArrayBuffer.isView(buffer)) { + offset += buffer.byteOffset; + buffer = buffer.buffer; + } + + var data; + data = buffer.slice(offset, offset + length); + + // if we're emulating a connection-less dgram socket and don't have + // a cached connection, queue the buffer to send upon connect and + // lie, saying the data was sent now. + if (sock.type === 2) { + if (!dest || dest.socket.readyState !== dest.socket.OPEN) { + // if we're not connected, open a new connection + if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); + } + dest.dgram_send_queue.push(data); + return length; + } + } + + try { + // send the actual data + dest.socket.send(data); + return length; + } catch (e) { + throw new FS.ErrnoError(28); + } + }, recvmsg(sock, length, flags) { - if (sock.type === 1 && sock.server) { - throw new FS.ErrnoError(53); - } - var queued = sock.recv_queue.shift(); - if (!queued) { - if (sock.type === 1) { - var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); - if (!dest) { - throw new FS.ErrnoError(53); - } - if (dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { - return null; - } - throw new FS.ErrnoError(6); - } - throw new FS.ErrnoError(6); - } - var queuedLength = queued.data.byteLength || queued.data.length; - var queuedOffset = queued.data.byteOffset || 0; - var queuedBuffer = queued.data.buffer || queued.data; - var bytesRead = Math.min(length, queuedLength); - var res = { - buffer: new Uint8Array(queuedBuffer, queuedOffset, bytesRead), - addr: queued.addr, - port: queued.port - }; - if (flags&2) {bytesRead = 0;} if (sock.type === 1 && bytesRead < queuedLength) { - var bytesRemaining = queuedLength - bytesRead; - queued.data = new Uint8Array(queuedBuffer, queuedOffset + bytesRead, bytesRemaining); - sock.recv_queue.unshift(queued); - } - return res; - } - } -}; - -function getSocketFromFD(fd) { - var socket = SOCKFS.getSocket(fd); - if (!socket) throw new FS.ErrnoError(8); - return socket; -} - -var setErrNo = value => { - HEAP32[___errno_location() >> 2] = value; - return value; -}; - -var inetPton4 = str => { - var b = str.split("."); - for (var i = 0; i < 4; i++) { - var tmp = Number(b[i]); - if (isNaN(tmp)) return null; - b[i] = tmp; - } - return (b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24) >>> 0; -}; - -var jstoi_q = str => parseInt(str); - -var inetPton6 = str => { - var words; - var w, offset, z; - var valid6regx = /^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i; - var parts = []; - if (!valid6regx.test(str)) { - return null; - } - if (str === "::") { - return [ 0, 0, 0, 0, 0, 0, 0, 0 ]; - } - if (str.startsWith("::")) { - str = str.replace("::", "Z:"); - } else { - str = str.replace("::", ":Z:"); - } - if (str.indexOf(".") > 0) { - str = str.replace(new RegExp("[.]", "g"), ":"); - words = str.split(":"); - words[words.length - 4] = jstoi_q(words[words.length - 4]) + jstoi_q(words[words.length - 3]) * 256; - words[words.length - 3] = jstoi_q(words[words.length - 2]) + jstoi_q(words[words.length - 1]) * 256; - words = words.slice(0, words.length - 2); - } else { - words = str.split(":"); - } - offset = 0; - z = 0; - for (w = 0; w < words.length; w++) { - if (typeof words[w] == "string") { - if (words[w] === "Z") { - for (z = 0; z < 8 - words.length + 1; z++) { - parts[w + z] = 0; - } - offset = z - 1; - } else { - parts[w + offset] = _htons(parseInt(words[w], 16)); - } - } else { - parts[w + offset] = words[w]; - } - } - return [ parts[1] << 16 | parts[0], parts[3] << 16 | parts[2], parts[5] << 16 | parts[4], parts[7] << 16 | parts[6] ]; -}; - -var writeSockaddr = (sa, family, addr, port, addrlen) => { - switch (family) { - case 2: - addr = inetPton4(addr); - zeroMemory(sa, 16); - if (addrlen) { - HEAP32[addrlen >> 2] = 16; - } - HEAP16[sa >> 1] = family; - HEAP32[sa + 4 >> 2] = addr; - HEAP16[sa + 2 >> 1] = _htons(port); - break; - - case 10: - addr = inetPton6(addr); - zeroMemory(sa, 28); - if (addrlen) { - HEAP32[addrlen >> 2] = 28; - } - HEAP32[sa >> 2] = family; - HEAP32[sa + 8 >> 2] = addr[0]; - HEAP32[sa + 12 >> 2] = addr[1]; - HEAP32[sa + 16 >> 2] = addr[2]; - HEAP32[sa + 20 >> 2] = addr[3]; - HEAP16[sa + 2 >> 1] = _htons(port); - break; - - default: - return 5; - } - return 0; -}; - -var DNS = { - address_map: { - id: 1, - addrs: {}, - names: {} - }, - lookup_name: name => { - var res = inetPton4(name); - if (res !== null) { - return name; - } - res = inetPton6(name); - if (res !== null) { - return name; - } - var addr; - if (DNS.address_map.addrs[name]) { - addr = DNS.address_map.addrs[name]; - } else { - var id = DNS.address_map.id++; - assert(id < 65535, "exceeded max address mappings of 65535"); - addr = "172.29." + (id & 255) + "." + (id & 65280); - DNS.address_map.names[addr] = name; - DNS.address_map.addrs[name] = addr; - } - return addr; - }, - lookup_addr: addr => { - if (DNS.address_map.names[addr]) { - return DNS.address_map.names[addr]; - } - return null; - } -}; - -function ___syscall_accept4(fd, addr, addrlen, flags, d1, d2) { - try { - var sock = getSocketFromFD(fd); - var newsock = sock.sock_ops.accept(sock); - if (addr) { - var errno = writeSockaddr(addr, newsock.family, DNS.lookup_name(newsock.daddr), newsock.dport, addrlen); - } - return newsock.stream.fd; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -var inetNtop4 = addr => (addr & 255) + "." + (addr >> 8 & 255) + "." + (addr >> 16 & 255) + "." + (addr >> 24 & 255); - -var inetNtop6 = ints => { - var str = ""; - var word = 0; - var longest = 0; - var lastzero = 0; - var zstart = 0; - var len = 0; - var i = 0; - var parts = [ ints[0] & 65535, ints[0] >> 16, ints[1] & 65535, ints[1] >> 16, ints[2] & 65535, ints[2] >> 16, ints[3] & 65535, ints[3] >> 16 ]; - var hasipv4 = true; - var v4part = ""; - for (i = 0; i < 5; i++) { - if (parts[i] !== 0) { - hasipv4 = false; - break; - } - } - if (hasipv4) { - v4part = inetNtop4(parts[6] | parts[7] << 16); - if (parts[5] === -1) { - str = "::ffff:"; - str += v4part; - return str; - } - if (parts[5] === 0) { - str = "::"; - if (v4part === "0.0.0.0") v4part = ""; - if (v4part === "0.0.0.1") v4part = "1"; - str += v4part; - return str; - } - } - for (word = 0; word < 8; word++) { - if (parts[word] === 0) { - if (word - lastzero > 1) { - len = 0; - } - lastzero = word; - len++; - } - if (len > longest) { - longest = len; - zstart = word - longest + 1; - } - } - for (word = 0; word < 8; word++) { - if (longest > 1) { - if (parts[word] === 0 && word >= zstart && word < zstart + longest) { - if (word === zstart) { - str += ":"; - if (zstart === 0) str += ":"; - } - continue; - } - } - str += Number(_ntohs(parts[word] & 65535)).toString(16); - str += word < 7 ? ":" : ""; - } - return str; -}; - -var readSockaddr = (sa, salen) => { - var family = HEAP16[sa >> 1]; - var port = _ntohs(HEAPU16[sa + 2 >> 1]); - var addr; - switch (family) { - case 2: - if (salen !== 16) { - return { - errno: 28 - }; - } - addr = HEAP32[sa + 4 >> 2]; - addr = inetNtop4(addr); - break; - - case 10: - if (salen !== 28) { - return { - errno: 28 - }; - } - addr = [ HEAP32[sa + 8 >> 2], HEAP32[sa + 12 >> 2], HEAP32[sa + 16 >> 2], HEAP32[sa + 20 >> 2] ]; - addr = inetNtop6(addr); - break; - - default: - return { - errno: 5 - }; - } - return { - family: family, - addr: addr, - port: port - }; -}; - -function getSocketAddress(addrp, addrlen, allowNull) { - if (allowNull && addrp === 0) return null; - var info = readSockaddr(addrp, addrlen); - if (info.errno) throw new FS.ErrnoError(info.errno); - info.addr = DNS.lookup_addr(info.addr) || info.addr; - return info; -} - -function ___syscall_bind(fd, addr, addrlen, d1, d2, d3) { - try { - var sock = getSocketFromFD(fd); - var info = getSocketAddress(addr, addrlen); - sock.sock_ops.bind(sock, info.addr, info.port); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_chdir(path) { - try { - path = SYSCALLS.getStr(path); - FS.chdir(path); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_chmod(path, mode) { - try { - path = SYSCALLS.getStr(path); - FS.chmod(path, mode); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_connect(fd, addr, addrlen, d1, d2, d3) { - try { - var sock = getSocketFromFD(fd); - var info = getSocketAddress(addr, addrlen); - sock.sock_ops.connect(sock, info.addr, info.port); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_dup(fd) { - try { - var old = SYSCALLS.getStreamFromFD(fd); - return FS.createStream(old).fd; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_dup3(fd, newfd, flags) { - try { - var old = SYSCALLS.getStreamFromFD(fd); - if (old.fd === newfd) return -28; - var existing = FS.getStream(newfd); - if (existing) FS.close(existing); - return FS.createStream(old, newfd).fd; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_faccessat(dirfd, path, amode, flags) { - try { - path = SYSCALLS.getStr(path); - path = SYSCALLS.calculateAt(dirfd, path); - if (amode & ~7) { - return -28; - } - var lookup = FS.lookupPath(path, { - follow: true - }); - var node = lookup.node; - if (!node) { - return -44; - } - var perms = ""; - if (amode & 4) perms += "r"; - if (amode & 2) perms += "w"; - if (amode & 1) perms += "x"; - if (perms && FS.nodePermissions(node, perms)) { - return -2; - } - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function convertI32PairToI53Checked(lo, hi) { - return hi + 2097152 >>> 0 < 4194305 - !!lo ? (lo >>> 0) + hi * 4294967296 : NaN; -} - -function ___syscall_fallocate(fd, mode, offset_low, offset_high, len_low, len_high) { - var offset = convertI32PairToI53Checked(offset_low, offset_high); - var len = convertI32PairToI53Checked(len_low, len_high); - try { - if (isNaN(offset)) return 61; - var stream = SYSCALLS.getStreamFromFD(fd); - FS.allocate(stream, offset, len); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_fchmod(fd, mode) { - try { - FS.fchmod(fd, mode); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_fchown32(fd, owner, group) { - try { - FS.fchown(fd, owner, group); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_fchownat(dirfd, path, owner, group, flags) { - try { - path = SYSCALLS.getStr(path); - var nofollow = flags & 256; - flags = flags & ~256; - path = SYSCALLS.calculateAt(dirfd, path); - (nofollow ? FS.lchown : FS.chown)(path, owner, group); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_fcntl64(fd, cmd, varargs) { - SYSCALLS.varargs = varargs; - try { - var stream = SYSCALLS.getStreamFromFD(fd); - switch (cmd) { - case 0: - { - var arg = SYSCALLS.get(); - if (arg < 0) { - return -28; - } - var newStream; - newStream = FS.createStream(stream, arg); - return newStream.fd; - } - - case 1: - case 2: - return 0; - - case 3: - return stream.flags; - - case 4: - { - var arg = SYSCALLS.get(); - stream.flags |= arg; - return 0; - } - - case 5: - { - var arg = SYSCALLS.get(); - var offset = 0; - HEAP16[arg + offset >> 1] = 2; - return 0; - } - - case 6: - case 7: - return 0; - - case 16: - case 8: - return -28; - - case 9: - setErrNo(28); - return -1; - - default: - { - return -28; - } - } - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_fdatasync(fd) { - try { - var stream = SYSCALLS.getStreamFromFD(fd); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_fstat64(fd, buf) { - try { - var stream = SYSCALLS.getStreamFromFD(fd); - return SYSCALLS.doStat(FS.stat, stream.path, buf); - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_ftruncate64(fd, length_low, length_high) { - var length = convertI32PairToI53Checked(length_low, length_high); - try { - if (isNaN(length)) return 61; - FS.ftruncate(fd, length); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -var stringToUTF8 = (str, outPtr, maxBytesToWrite) => stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite); - -Module["stringToUTF8"] = stringToUTF8; - -function ___syscall_getcwd(buf, size) { - try { - if (size === 0) return -28; - var cwd = FS.cwd(); - var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1; - if (size < cwdLengthInBytes) return -68; - stringToUTF8(cwd, buf, size); - return cwdLengthInBytes; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_getdents64(fd, dirp, count) { - try { - var stream = SYSCALLS.getStreamFromFD(fd); - if (!stream.getdents) { - stream.getdents = FS.readdir(stream.path); - } - var struct_size = 280; - var pos = 0; - var off = FS.llseek(stream, 0, 1); - var idx = Math.floor(off / struct_size); - while (idx < stream.getdents.length && pos + struct_size <= count) { - var id; - var type; - var name = stream.getdents[idx]; - if (name === ".") { - id = stream.node.id; - type = 4; - } else if (name === "..") { - var lookup = FS.lookupPath(stream.path, { - parent: true - }); - id = lookup.node.id; - type = 4; - } else { - var child = FS.lookupNode(stream.node, name); - id = child.id; - type = FS.isChrdev(child.mode) ? 2 : FS.isDir(child.mode) ? 4 : FS.isLink(child.mode) ? 10 : 8; - } - tempI64 = [ id >>> 0, (tempDouble = id, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], - HEAP32[dirp + pos >> 2] = tempI64[0], HEAP32[dirp + pos + 4 >> 2] = tempI64[1]; - tempI64 = [ (idx + 1) * struct_size >>> 0, (tempDouble = (idx + 1) * struct_size, - +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], - HEAP32[dirp + pos + 8 >> 2] = tempI64[0], HEAP32[dirp + pos + 12 >> 2] = tempI64[1]; - HEAP16[dirp + pos + 16 >> 1] = 280; - HEAP8[dirp + pos + 18 >> 0] = type; - stringToUTF8(name, dirp + pos + 19, 256); - pos += struct_size; - idx += 1; - } - FS.llseek(stream, idx * struct_size, 0); - return pos; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_getpeername(fd, addr, addrlen, d1, d2, d3) { - try { - var sock = getSocketFromFD(fd); - if (!sock.daddr) { - return -53; - } - var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(sock.daddr), sock.dport, addrlen); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_getsockname(fd, addr, addrlen, d1, d2, d3) { - try { - var sock = getSocketFromFD(fd); - var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(sock.saddr || "0.0.0.0"), sock.sport, addrlen); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_getsockopt(fd, level, optname, optval, optlen, d1) { - try { - var sock = getSocketFromFD(fd); - if (level === 1) { - if (optname === 4) { - HEAP32[optval >> 2] = sock.error; - HEAP32[optlen >> 2] = 4; - sock.error = null; - return 0; - } - } - return -50; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_ioctl(fd, op, varargs) { - SYSCALLS.varargs = varargs; - try { - var stream = SYSCALLS.getStreamFromFD(fd); - switch (op) { - case 21509: - { - if (!stream.tty) return -59; - return 0; - } - - case 21505: - { - if (!stream.tty) return -59; - if (stream.tty.ops.ioctl_tcgets) { - var termios = stream.tty.ops.ioctl_tcgets(stream); - var argp = SYSCALLS.get(); - HEAP32[argp >> 2] = termios.c_iflag || 0; - HEAP32[argp + 4 >> 2] = termios.c_oflag || 0; - HEAP32[argp + 8 >> 2] = termios.c_cflag || 0; - HEAP32[argp + 12 >> 2] = termios.c_lflag || 0; - for (var i = 0; i < 32; i++) { - HEAP8[argp + i + 17 >> 0] = termios.c_cc[i] || 0; - } - return 0; - } - return 0; - } - - case 21510: - case 21511: - case 21512: - { - if (!stream.tty) return -59; - return 0; - } - - case 21506: - case 21507: - case 21508: - { - if (!stream.tty) return -59; - if (stream.tty.ops.ioctl_tcsets) { - var argp = SYSCALLS.get(); - var c_iflag = HEAP32[argp >> 2]; - var c_oflag = HEAP32[argp + 4 >> 2]; - var c_cflag = HEAP32[argp + 8 >> 2]; - var c_lflag = HEAP32[argp + 12 >> 2]; - var c_cc = []; - for (var i = 0; i < 32; i++) { - c_cc.push(HEAP8[argp + i + 17 >> 0]); - } - return stream.tty.ops.ioctl_tcsets(stream.tty, op, { - c_iflag: c_iflag, - c_oflag: c_oflag, - c_cflag: c_cflag, - c_lflag: c_lflag, - c_cc: c_cc - }); - } - return 0; - } - - case 21519: - { - if (!stream.tty) return -59; - var argp = SYSCALLS.get(); - HEAP32[argp >> 2] = 0; - return 0; - } - - case 21520: - { - if (!stream.tty) return -59; - return -28; - } - - case 21531: - { - var argp = SYSCALLS.get(); - return FS.ioctl(stream, op, argp); - } - - case 21523: - { - if (!stream.tty) return -59; - if (stream.tty.ops.ioctl_tiocgwinsz) { - var winsize = stream.tty.ops.ioctl_tiocgwinsz(stream.tty); - var argp = SYSCALLS.get(); - HEAP16[argp >> 1] = winsize[0]; - HEAP16[argp + 2 >> 1] = winsize[1]; - } - return 0; - } - - case 21524: - { - if (!stream.tty) return -59; - return 0; - } - - case 21515: - { - if (!stream.tty) return -59; - return 0; - } - - default: - return -28; - } - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_listen(fd, backlog) { - try { - var sock = getSocketFromFD(fd); - sock.sock_ops.listen(sock, backlog); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_lstat64(path, buf) { - try { - path = SYSCALLS.getStr(path); - return SYSCALLS.doStat(FS.lstat, path, buf); - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_mkdirat(dirfd, path, mode) { - try { - path = SYSCALLS.getStr(path); - path = SYSCALLS.calculateAt(dirfd, path); - path = PATH.normalize(path); - if (path[path.length - 1] === "/") path = path.substr(0, path.length - 1); - FS.mkdir(path, mode, 0); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_newfstatat(dirfd, path, buf, flags) { - try { - path = SYSCALLS.getStr(path); - var nofollow = flags & 256; - var allowEmpty = flags & 4096; - flags = flags & ~6400; - path = SYSCALLS.calculateAt(dirfd, path, allowEmpty); - return SYSCALLS.doStat(nofollow ? FS.lstat : FS.stat, path, buf); - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -function ___syscall_openat(dirfd, path, flags, varargs) { - SYSCALLS.varargs = varargs; - try { - path = SYSCALLS.getStr(path); - path = SYSCALLS.calculateAt(dirfd, path); - var mode = varargs ? SYSCALLS.get() : 0; - return FS.open(path, flags, mode).fd; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} - -var PIPEFS = { - BUCKET_BUFFER_SIZE: 8192, - mount(mount) { - return FS.createNode(null, "/", 16384 | 511, 0); - }, - createPipe() { - var pipe = { - buckets: [], - refcnt: 2 - }; - pipe.buckets.push({ - buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE), - offset: 0, - roffset: 0 - }); - var rName = PIPEFS.nextname(); - var wName = PIPEFS.nextname(); - var rNode = FS.createNode(PIPEFS.root, rName, 4096, 0); - var wNode = FS.createNode(PIPEFS.root, wName, 4096, 0); - rNode.pipe = pipe; - wNode.pipe = pipe; - var readableStream = FS.createStream({ - path: rName, - node: rNode, - flags: 0, - seekable: false, - stream_ops: PIPEFS.stream_ops - }); - rNode.stream = readableStream; - var writableStream = FS.createStream({ - path: wName, - node: wNode, - flags: 1, - seekable: false, - stream_ops: PIPEFS.stream_ops - }); - wNode.stream = writableStream; - return { - readable_fd: readableStream.fd, - writable_fd: writableStream.fd + // http://pubs.opengroup.org/onlinepubs/7908799/xns/recvmsg.html + if (sock.type === 1 && sock.server) { + // tcp servers should not be recv()'ing on the listen socket + throw new FS.ErrnoError(53); + } + + var queued = sock.recv_queue.shift(); + if (!queued) { + if (sock.type === 1) { + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); + + if (!dest) { + // if we have a destination address but are not connected, error out + throw new FS.ErrnoError(53); + } + if (dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + // return null if the socket has closed + return null; + } + // else, our socket is in a valid state but truly has nothing available + throw new FS.ErrnoError(6); + } + throw new FS.ErrnoError(6); + } + + // queued.data will be an ArrayBuffer if it's unadulterated, but if it's + // requeued TCP data it'll be an ArrayBufferView + var queuedLength = queued.data.byteLength || queued.data.length; + var queuedOffset = queued.data.byteOffset || 0; + var queuedBuffer = queued.data.buffer || queued.data; + var bytesRead = Math.min(length, queuedLength); + var res = { + buffer: new Uint8Array(queuedBuffer, queuedOffset, bytesRead), + addr: queued.addr, + port: queued.port + }; + + // push back any unread data for TCP connections + if (flags&2) {bytesRead = 0;} if (sock.type === 1 && bytesRead < queuedLength) { + var bytesRemaining = queuedLength - bytesRead; + queued.data = new Uint8Array(queuedBuffer, queuedOffset + bytesRead, bytesRemaining); + sock.recv_queue.unshift(queued); + } + + return res; + }, + }, }; - }, - stream_ops: { - poll(stream) { - var pipe = stream.node.pipe; - if ((stream.flags & 2097155) === 1) { - return 256 | 4; - } - if (pipe.buckets.length > 0) { - for (var i = 0; i < pipe.buckets.length; i++) { - var bucket = pipe.buckets[i]; - if (bucket.offset - bucket.roffset > 0) { - return 64 | 1; - } + + function getSocketFromFD(fd) { + var socket = SOCKFS.getSocket(fd); + if (!socket) throw new FS.ErrnoError(8); + return socket; } - } - return 0; - }, - ioctl(stream, request, varargs) { - return 28; + + var setErrNo = (value) => { + HEAP32[((___errno_location())>>2)] = value; + return value; + }; + var Sockets = { + BUFFER_SIZE:10240, + MAX_BUFFER_SIZE:10485760, + nextFd:1, + fds:{ }, - fsync(stream) { - return 28; + nextport:1, + maxport:65535, + peer:null, + connections:{ }, - read(stream, buffer, offset, length, position) { - var pipe = stream.node.pipe; - var currentLength = 0; - for (var i = 0; i < pipe.buckets.length; i++) { - var bucket = pipe.buckets[i]; - currentLength += bucket.offset - bucket.roffset; - } - assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer)); - var data = buffer.subarray(offset, offset + length); - if (length <= 0) { - return 0; - } - if (currentLength == 0) { - throw new FS.ErrnoError(6); - } - var toRead = Math.min(currentLength, length); - var totalRead = toRead; - var toRemove = 0; - for (var i = 0; i < pipe.buckets.length; i++) { - var currBucket = pipe.buckets[i]; - var bucketSize = currBucket.offset - currBucket.roffset; - if (toRead <= bucketSize) { - var tmpSlice = currBucket.buffer.subarray(currBucket.roffset, currBucket.offset); - if (toRead < bucketSize) { - tmpSlice = tmpSlice.subarray(0, toRead); - currBucket.roffset += toRead; - } else { - toRemove++; - } - data.set(tmpSlice); - break; - } else { - var tmpSlice = currBucket.buffer.subarray(currBucket.roffset, currBucket.offset); - data.set(tmpSlice); - data = data.subarray(tmpSlice.byteLength); - toRead -= tmpSlice.byteLength; - toRemove++; - } - } - if (toRemove && toRemove == pipe.buckets.length) { - toRemove--; - pipe.buckets[toRemove].offset = 0; - pipe.buckets[toRemove].roffset = 0; - } - pipe.buckets.splice(0, toRemove); - return totalRead; + portmap:{ }, - write(stream, buffer, offset, length, position) { - var pipe = stream.node.pipe; - assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer)); - var data = buffer.subarray(offset, offset + length); - var dataLen = data.byteLength; - if (dataLen <= 0) { - return 0; - } - var currBucket = null; - if (pipe.buckets.length == 0) { - currBucket = { - buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE), - offset: 0, - roffset: 0 + localAddr:4261412874, + addrPool:[33554442,50331658,67108874,83886090,100663306,117440522,134217738,150994954,167772170,184549386,201326602,218103818,234881034], + }; + + var inetPton4 = (str) => { + var b = str.split('.'); + for (var i = 0; i < 4; i++) { + var tmp = Number(b[i]); + if (isNaN(tmp)) return null; + b[i] = tmp; + } + return (b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)) >>> 0; }; - pipe.buckets.push(currBucket); - } else { - currBucket = pipe.buckets[pipe.buckets.length - 1]; - } - assert(currBucket.offset <= PIPEFS.BUCKET_BUFFER_SIZE); - var freeBytesInCurrBuffer = PIPEFS.BUCKET_BUFFER_SIZE - currBucket.offset; - if (freeBytesInCurrBuffer >= dataLen) { - currBucket.buffer.set(data, currBucket.offset); - currBucket.offset += dataLen; - return dataLen; - } else if (freeBytesInCurrBuffer > 0) { - currBucket.buffer.set(data.subarray(0, freeBytesInCurrBuffer), currBucket.offset); - currBucket.offset += freeBytesInCurrBuffer; - data = data.subarray(freeBytesInCurrBuffer, data.byteLength); - } - var numBuckets = data.byteLength / PIPEFS.BUCKET_BUFFER_SIZE | 0; - var remElements = data.byteLength % PIPEFS.BUCKET_BUFFER_SIZE; - for (var i = 0; i < numBuckets; i++) { - var newBucket = { - buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE), - offset: PIPEFS.BUCKET_BUFFER_SIZE, - roffset: 0 + + + /** @suppress {checkTypes} */ + var jstoi_q = (str) => parseInt(str); + var inetPton6 = (str) => { + var words; + var w, offset, z, i; + /* http://home.deds.nl/~aeron/regex/ */ + var valid6regx = /^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i + var parts = []; + if (!valid6regx.test(str)) { + return null; + } + if (str === "::") { + return [0, 0, 0, 0, 0, 0, 0, 0]; + } + // Z placeholder to keep track of zeros when splitting the string on ":" + if (str.startsWith("::")) { + str = str.replace("::", "Z:"); // leading zeros case + } else { + str = str.replace("::", ":Z:"); + } + + if (str.indexOf(".") > 0) { + // parse IPv4 embedded stress + str = str.replace(new RegExp('[.]', 'g'), ":"); + words = str.split(":"); + words[words.length-4] = jstoi_q(words[words.length-4]) + jstoi_q(words[words.length-3])*256; + words[words.length-3] = jstoi_q(words[words.length-2]) + jstoi_q(words[words.length-1])*256; + words = words.slice(0, words.length-2); + } else { + words = str.split(":"); + } + + offset = 0; z = 0; + for (w=0; w < words.length; w++) { + if (typeof words[w] == 'string') { + if (words[w] === 'Z') { + // compressed zeros - write appropriate number of zero words + for (z = 0; z < (8 - words.length+1); z++) { + parts[w+z] = 0; + } + offset = z-1; + } else { + // parse hex to field to 16-bit value and write it in network byte-order + parts[w+offset] = _htons(parseInt(words[w],16)); + } + } else { + // parsed IPv4 words + parts[w+offset] = words[w]; + } + } + return [ + (parts[1] << 16) | parts[0], + (parts[3] << 16) | parts[2], + (parts[5] << 16) | parts[4], + (parts[7] << 16) | parts[6] + ]; }; - pipe.buckets.push(newBucket); - newBucket.buffer.set(data.subarray(0, PIPEFS.BUCKET_BUFFER_SIZE)); - data = data.subarray(PIPEFS.BUCKET_BUFFER_SIZE, data.byteLength); - } - if (remElements > 0) { - var newBucket = { - buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE), - offset: data.byteLength, - roffset: 0 + + + /** @param {number=} addrlen */ + var writeSockaddr = (sa, family, addr, port, addrlen) => { + switch (family) { + case 2: + addr = inetPton4(addr); + zeroMemory(sa, 16); + if (addrlen) { + HEAP32[((addrlen)>>2)] = 16; + } + HEAP16[((sa)>>1)] = family; + HEAP32[(((sa)+(4))>>2)] = addr; + HEAP16[(((sa)+(2))>>1)] = _htons(port); + break; + case 10: + addr = inetPton6(addr); + zeroMemory(sa, 28); + if (addrlen) { + HEAP32[((addrlen)>>2)] = 28; + } + HEAP32[((sa)>>2)] = family; + HEAP32[(((sa)+(8))>>2)] = addr[0]; + HEAP32[(((sa)+(12))>>2)] = addr[1]; + HEAP32[(((sa)+(16))>>2)] = addr[2]; + HEAP32[(((sa)+(20))>>2)] = addr[3]; + HEAP16[(((sa)+(2))>>1)] = _htons(port); + break; + default: + return 5; + } + return 0; }; - pipe.buckets.push(newBucket); - newBucket.buffer.set(data); - } - return dataLen; + + + var DNS = { + address_map:{ + id:1, + addrs:{ }, - close(stream) { - var pipe = stream.node.pipe; - pipe.refcnt--; - if (pipe.refcnt === 0) { - pipe.buckets = null; - } + names:{ + }, + }, + lookup_name:(name) => { + // If the name is already a valid ipv4 / ipv6 address, don't generate a fake one. + var res = inetPton4(name); + if (res !== null) { + return name; + } + res = inetPton6(name); + if (res !== null) { + return name; + } + + // See if this name is already mapped. + var addr; + + if (DNS.address_map.addrs[name]) { + addr = DNS.address_map.addrs[name]; + } else { + var id = DNS.address_map.id++; + assert(id < 65535, 'exceeded max address mappings of 65535'); + + addr = '172.29.' + (id & 0xff) + '.' + (id & 0xff00); + + DNS.address_map.names[addr] = name; + DNS.address_map.addrs[name] = addr; + } + + return addr; + }, + lookup_addr:(addr) => { + if (DNS.address_map.names[addr]) { + return DNS.address_map.names[addr]; + } + + return null; + }, + }; + + + + var SYSCALLS = { + DEFAULT_POLLMASK:5, + calculateAt:function(dirfd, path, allowEmpty) { + if (PATH.isAbs(path)) { + return path; + } + // relative path + var dir; + if (dirfd === -100) { + dir = FS.cwd(); + } else { + var dirstream = SYSCALLS.getStreamFromFD(dirfd); + dir = dirstream.path; + } + if (path.length == 0) { + if (!allowEmpty) { + throw new FS.ErrnoError(44);; + } + return dir; + } + return PATH.join2(dir, path); + }, + doStat:function(func, path, buf) { + try { + var stat = func(path); + } catch (e) { + if (e && e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) { + // an error occurred while trying to look up the path; we should just report ENOTDIR + return -54; + } + throw e; + } + HEAP32[((buf)>>2)] = stat.dev; + HEAP32[(((buf)+(4))>>2)] = stat.mode; + HEAPU32[(((buf)+(8))>>2)] = stat.nlink; + HEAP32[(((buf)+(12))>>2)] = stat.uid; + HEAP32[(((buf)+(16))>>2)] = stat.gid; + HEAP32[(((buf)+(20))>>2)] = stat.rdev; + (tempI64 = [stat.size>>>0,(tempDouble=stat.size,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(24))>>2)] = tempI64[0],HEAP32[(((buf)+(28))>>2)] = tempI64[1]); + HEAP32[(((buf)+(32))>>2)] = 4096; + HEAP32[(((buf)+(36))>>2)] = stat.blocks; + var atime = stat.atime.getTime(); + var mtime = stat.mtime.getTime(); + var ctime = stat.ctime.getTime(); + (tempI64 = [Math.floor(atime / 1000)>>>0,(tempDouble=Math.floor(atime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(40))>>2)] = tempI64[0],HEAP32[(((buf)+(44))>>2)] = tempI64[1]); + HEAPU32[(((buf)+(48))>>2)] = (atime % 1000) * 1000; + (tempI64 = [Math.floor(mtime / 1000)>>>0,(tempDouble=Math.floor(mtime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(56))>>2)] = tempI64[0],HEAP32[(((buf)+(60))>>2)] = tempI64[1]); + HEAPU32[(((buf)+(64))>>2)] = (mtime % 1000) * 1000; + (tempI64 = [Math.floor(ctime / 1000)>>>0,(tempDouble=Math.floor(ctime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(72))>>2)] = tempI64[0],HEAP32[(((buf)+(76))>>2)] = tempI64[1]); + HEAPU32[(((buf)+(80))>>2)] = (ctime % 1000) * 1000; + (tempI64 = [stat.ino>>>0,(tempDouble=stat.ino,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(88))>>2)] = tempI64[0],HEAP32[(((buf)+(92))>>2)] = tempI64[1]); + return 0; + }, + doMsync:function(addr, stream, len, flags, offset) { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(43); + } + if (flags & 2) { + // MAP_PRIVATE calls need not to be synced back to underlying fs + return 0; + } + var buffer = HEAPU8.slice(addr, addr + len); + FS.msync(stream, buffer, offset, len, flags); + }, + varargs:undefined, + get() { + SYSCALLS.varargs += 4; + var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)]; + return ret; + }, + getStr(ptr) { + var ret = UTF8ToString(ptr); + return ret; + }, + getStreamFromFD:function(fd) { + var stream = FS.getStreamChecked(fd); + return stream; + }, + }; + function ___syscall_accept4(fd, addr, addrlen, flags, d1, d2) { + try { + + var sock = getSocketFromFD(fd); + var newsock = sock.sock_ops.accept(sock); + if (addr) { + var errno = writeSockaddr(addr, newsock.family, DNS.lookup_name(newsock.daddr), newsock.dport, addrlen); + } + return newsock.stream.fd; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + + var inetNtop4 = (addr) => { + return (addr & 0xff) + '.' + ((addr >> 8) & 0xff) + '.' + ((addr >> 16) & 0xff) + '.' + ((addr >> 24) & 0xff) + }; + + + var inetNtop6 = (ints) => { + // ref: http://www.ietf.org/rfc/rfc2373.txt - section 2.5.4 + // Format for IPv4 compatible and mapped 128-bit IPv6 Addresses + // 128-bits are split into eight 16-bit words + // stored in network byte order (big-endian) + // | 80 bits | 16 | 32 bits | + // +-----------------------------------------------------------------+ + // | 10 bytes | 2 | 4 bytes | + // +--------------------------------------+--------------------------+ + // + 5 words | 1 | 2 words | + // +--------------------------------------+--------------------------+ + // |0000..............................0000|0000| IPv4 ADDRESS | (compatible) + // +--------------------------------------+----+---------------------+ + // |0000..............................0000|FFFF| IPv4 ADDRESS | (mapped) + // +--------------------------------------+----+---------------------+ + var str = ""; + var word = 0; + var longest = 0; + var lastzero = 0; + var zstart = 0; + var len = 0; + var i = 0; + var parts = [ + ints[0] & 0xffff, + (ints[0] >> 16), + ints[1] & 0xffff, + (ints[1] >> 16), + ints[2] & 0xffff, + (ints[2] >> 16), + ints[3] & 0xffff, + (ints[3] >> 16) + ]; + + // Handle IPv4-compatible, IPv4-mapped, loopback and any/unspecified addresses + + var hasipv4 = true; + var v4part = ""; + // check if the 10 high-order bytes are all zeros (first 5 words) + for (i = 0; i < 5; i++) { + if (parts[i] !== 0) { hasipv4 = false; break; } + } + + if (hasipv4) { + // low-order 32-bits store an IPv4 address (bytes 13 to 16) (last 2 words) + v4part = inetNtop4(parts[6] | (parts[7] << 16)); + // IPv4-mapped IPv6 address if 16-bit value (bytes 11 and 12) == 0xFFFF (6th word) + if (parts[5] === -1) { + str = "::ffff:"; + str += v4part; + return str; + } + // IPv4-compatible IPv6 address if 16-bit value (bytes 11 and 12) == 0x0000 (6th word) + if (parts[5] === 0) { + str = "::"; + //special case IPv6 addresses + if (v4part === "0.0.0.0") v4part = ""; // any/unspecified address + if (v4part === "0.0.0.1") v4part = "1";// loopback address + str += v4part; + return str; + } + } + + // Handle all other IPv6 addresses + + // first run to find the longest contiguous zero words + for (word = 0; word < 8; word++) { + if (parts[word] === 0) { + if (word - lastzero > 1) { + len = 0; + } + lastzero = word; + len++; + } + if (len > longest) { + longest = len; + zstart = word - longest + 1; + } + } + + for (word = 0; word < 8; word++) { + if (longest > 1) { + // compress contiguous zeros - to produce "::" + if (parts[word] === 0 && word >= zstart && word < (zstart + longest) ) { + if (word === zstart) { + str += ":"; + if (zstart === 0) str += ":"; //leading zeros case + } + continue; + } + } + // converts 16-bit words from big-endian to little-endian before converting to hex string + str += Number(_ntohs(parts[word] & 0xffff)).toString(16); + str += word < 7 ? ":" : ""; + } + return str; + }; + + var readSockaddr = (sa, salen) => { + // family / port offsets are common to both sockaddr_in and sockaddr_in6 + var family = HEAP16[((sa)>>1)]; + var port = _ntohs(HEAPU16[(((sa)+(2))>>1)]); + var addr; + + switch (family) { + case 2: + if (salen !== 16) { + return { errno: 28 }; + } + addr = HEAP32[(((sa)+(4))>>2)]; + addr = inetNtop4(addr); + break; + case 10: + if (salen !== 28) { + return { errno: 28 }; + } + addr = [ + HEAP32[(((sa)+(8))>>2)], + HEAP32[(((sa)+(12))>>2)], + HEAP32[(((sa)+(16))>>2)], + HEAP32[(((sa)+(20))>>2)] + ]; + addr = inetNtop6(addr); + break; + default: + return { errno: 5 }; + } + + return { family: family, addr: addr, port: port }; + }; + + + /** @param {boolean=} allowNull */ + function getSocketAddress(addrp, addrlen, allowNull) { + if (allowNull && addrp === 0) return null; + var info = readSockaddr(addrp, addrlen); + if (info.errno) throw new FS.ErrnoError(info.errno); + info.addr = DNS.lookup_addr(info.addr) || info.addr; + return info; + } + + function ___syscall_bind(fd, addr, addrlen, d1, d2, d3) { + try { + + var sock = getSocketFromFD(fd); + var info = getSocketAddress(addr, addrlen); + sock.sock_ops.bind(sock, info.addr, info.port); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_chdir(path) { + try { + + path = SYSCALLS.getStr(path); + FS.chdir(path); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; } - }, - nextname() { - if (!PIPEFS.nextname.current) { - PIPEFS.nextname.current = 0; } - return "pipe[" + PIPEFS.nextname.current++ + "]"; - } -}; -function ___syscall_pipe(fdPtr) { - try { - if (fdPtr == 0) { - throw new FS.ErrnoError(21); - } - var res = PIPEFS.createPipe(); - HEAP32[fdPtr >> 2] = res.readable_fd; - HEAP32[fdPtr + 4 >> 2] = res.writable_fd; - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} + function ___syscall_chmod(path, mode) { + try { + + path = SYSCALLS.getStr(path); + FS.chmod(path, mode); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -function ___syscall_poll(fds, nfds, timeout) { - try { - var nonzero = 0; - for (var i = 0; i < nfds; i++) { - var pollfd = fds + 8 * i; - var fd = HEAP32[pollfd >> 2]; - var events = HEAP16[pollfd + 4 >> 1]; - var mask = 32; - var stream = FS.getStream(fd); - if (stream) { - mask = SYSCALLS.DEFAULT_POLLMASK; - if (stream.stream_ops?.poll) { - mask = stream.stream_ops.poll(stream, -1); - } - } - mask &= events | 8 | 16; - if (mask) nonzero++; - HEAP16[pollfd + 6 >> 1] = mask; - } - return nonzero; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} + + + function ___syscall_connect(fd, addr, addrlen, d1, d2, d3) { + try { + + var sock = getSocketFromFD(fd); + var info = getSocketAddress(addr, addrlen); + sock.sock_ops.connect(sock, info.addr, info.port); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -function ___syscall_readlinkat(dirfd, path, buf, bufsize) { - try { - path = SYSCALLS.getStr(path); - path = SYSCALLS.calculateAt(dirfd, path); - if (bufsize <= 0) return -28; - var ret = FS.readlink(path); - var len = Math.min(bufsize, lengthBytesUTF8(ret)); - var endChar = HEAP8[buf + len]; - stringToUTF8(ret, buf, bufsize + 1); - HEAP8[buf + len] = endChar; - return len; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} + function ___syscall_dup(fd) { + try { + + var old = SYSCALLS.getStreamFromFD(fd); + return FS.createStream(old).fd; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -function ___syscall_recvfrom(fd, buf, len, flags, addr, addrlen) { - try { - var sock = getSocketFromFD(fd); - var msg = sock.sock_ops.recvmsg(sock, len, typeof flags !== "undefined" ? flags : 0); - if (!msg) return 0; - if (addr) { - var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(msg.addr), msg.port, addrlen); - } - HEAPU8.set(msg.buffer, buf); - return msg.buffer.byteLength; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} + function ___syscall_dup3(fd, newfd, flags) { + try { + + var old = SYSCALLS.getStreamFromFD(fd); + if (old.fd === newfd) return -28; + var existing = FS.getStream(newfd); + if (existing) FS.close(existing); + return FS.createStream(old, newfd).fd; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) { - try { - oldpath = SYSCALLS.getStr(oldpath); - newpath = SYSCALLS.getStr(newpath); - oldpath = SYSCALLS.calculateAt(olddirfd, oldpath); - newpath = SYSCALLS.calculateAt(newdirfd, newpath); - FS.rename(oldpath, newpath); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} + function ___syscall_faccessat(dirfd, path, amode, flags) { + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + if (amode & ~7) { + // need a valid mode + return -28; + } + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + if (!node) { + return -44; + } + var perms = ''; + if (amode & 4) perms += 'r'; + if (amode & 2) perms += 'w'; + if (amode & 1) perms += 'x'; + if (perms /* otherwise, they've just passed F_OK */ && FS.nodePermissions(node, perms)) { + return -2; + } + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -function ___syscall_rmdir(path) { - try { - path = SYSCALLS.getStr(path); - FS.rmdir(path); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} + + function convertI32PairToI53Checked(lo, hi) { + return ((hi + 0x200000) >>> 0 < 0x400001 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN; + } + function ___syscall_fallocate(fd,mode,offset_low, offset_high,len_low, len_high) { + var offset = convertI32PairToI53Checked(offset_low, offset_high);; + var len = convertI32PairToI53Checked(len_low, len_high);; + + + try { + + if (isNaN(offset)) return 61; + var stream = SYSCALLS.getStreamFromFD(fd) + FS.allocate(stream, offset, len); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + ; + } -function ___syscall_sendto(fd, message, length, flags, addr, addr_len) { - try { - var sock = getSocketFromFD(fd); - var dest = getSocketAddress(addr, addr_len, true); - if (!dest) { - return FS.write(sock.stream, HEAP8, message, length); - } - return sock.sock_ops.sendmsg(sock, HEAP8, message, length, dest.addr, dest.port); - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} + function ___syscall_fchmod(fd, mode) { + try { + + FS.fchmod(fd, mode); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -function ___syscall_socket(domain, type, protocol) { - try { - var sock = SOCKFS.createSocket(domain, type, protocol); - return sock.stream.fd; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} + function ___syscall_fchown32(fd, owner, group) { + try { + + FS.fchown(fd, owner, group); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -function ___syscall_stat64(path, buf) { - try { - path = SYSCALLS.getStr(path); - return SYSCALLS.doStat(FS.stat, path, buf); - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} + function ___syscall_fchownat(dirfd, path, owner, group, flags) { + try { + + path = SYSCALLS.getStr(path); + var nofollow = flags & 256; + flags = flags & (~256); + path = SYSCALLS.calculateAt(dirfd, path); + (nofollow ? FS.lchown : FS.chown)(path, owner, group); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -function ___syscall_statfs64(path, size, buf) { - try { - path = SYSCALLS.getStr(path); - HEAP32[buf + 4 >> 2] = 4096; - HEAP32[buf + 40 >> 2] = 4096; - HEAP32[buf + 8 >> 2] = 1e6; - HEAP32[buf + 12 >> 2] = 5e5; - HEAP32[buf + 16 >> 2] = 5e5; - HEAP32[buf + 20 >> 2] = FS.nextInode; - HEAP32[buf + 24 >> 2] = 1e6; - HEAP32[buf + 28 >> 2] = 42; - HEAP32[buf + 44 >> 2] = 2; - HEAP32[buf + 36 >> 2] = 255; - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} + + function ___syscall_fcntl64(fd, cmd, varargs) { + SYSCALLS.varargs = varargs; + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + switch (cmd) { + case 0: { + var arg = SYSCALLS.get(); + if (arg < 0) { + return -28; + } + var newStream; + newStream = FS.createStream(stream, arg); + return newStream.fd; + } + case 1: + case 2: + return 0; // FD_CLOEXEC makes no sense for a single process. + case 3: + return stream.flags; + case 4: { + var arg = SYSCALLS.get(); + stream.flags |= arg; + return 0; + } + case 5: + /* case 5: Currently in musl F_GETLK64 has same value as F_GETLK, so omitted to avoid duplicate case blocks. If that changes, uncomment this */ { + + var arg = SYSCALLS.get(); + var offset = 0; + // We're always unlocked. + HEAP16[(((arg)+(offset))>>1)] = 2; + return 0; + } + case 6: + case 7: + /* case 6: Currently in musl F_SETLK64 has same value as F_SETLK, so omitted to avoid duplicate case blocks. If that changes, uncomment this */ + /* case 7: Currently in musl F_SETLKW64 has same value as F_SETLKW, so omitted to avoid duplicate case blocks. If that changes, uncomment this */ + + + return 0; // Pretend that the locking is successful. + case 16: + case 8: + return -28; // These are for sockets. We don't have them fully implemented yet. + case 9: + // musl trusts getown return values, due to a bug where they must be, as they overlap with errors. just return -1 here, so fcntl() returns that, and we set errno ourselves. + setErrNo(28); + return -1; + default: { + return -28; + } + } + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -function ___syscall_symlink(target, linkpath) { - try { - target = SYSCALLS.getStr(target); - linkpath = SYSCALLS.getStr(linkpath); - FS.symlink(target, linkpath); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} + function ___syscall_fdatasync(fd) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + return 0; // we can't do anything synchronously; the in-memory FS is already synced to + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -function ___syscall_unlinkat(dirfd, path, flags) { - try { - path = SYSCALLS.getStr(path); - path = SYSCALLS.calculateAt(dirfd, path); - if (flags === 0) { - FS.unlink(path); - } else if (flags === 512) { - FS.rmdir(path); - } else { - abort("Invalid flags passed to unlinkat"); + function ___syscall_fstat64(fd, buf) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + return SYSCALLS.doStat(FS.stat, stream.path, buf); + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } } - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} -function readI53FromI64(ptr) { - return HEAPU32[ptr >> 2] + HEAP32[ptr + 4 >> 2] * 4294967296; -} + + function ___syscall_ftruncate64(fd,length_low, length_high) { + var length = convertI32PairToI53Checked(length_low, length_high);; + + + try { + + if (isNaN(length)) return 61; + FS.ftruncate(fd, length); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + ; + } -function ___syscall_utimensat(dirfd, path, times, flags) { - try { - path = SYSCALLS.getStr(path); - path = SYSCALLS.calculateAt(dirfd, path, true); - if (!times) { - var atime = Date.now(); - var mtime = atime; - } else { - var seconds = readI53FromI64(times); - var nanoseconds = HEAP32[times + 8 >> 2]; - atime = seconds * 1e3 + nanoseconds / (1e3 * 1e3); - times += 16; - seconds = readI53FromI64(times); - nanoseconds = HEAP32[times + 8 >> 2]; - mtime = seconds * 1e3 + nanoseconds / (1e3 * 1e3); - } - FS.utime(path, atime, mtime); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} + + var stringToUTF8 = (str, outPtr, maxBytesToWrite) => { + return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite); + }; + Module['stringToUTF8'] = stringToUTF8; + + function ___syscall_getcwd(buf, size) { + try { + + if (size === 0) return -28; + var cwd = FS.cwd(); + var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1; + if (size < cwdLengthInBytes) return -68; + stringToUTF8(cwd, buf, size); + return cwdLengthInBytes; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_getdents64(fd, dirp, count) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd) + if (!stream.getdents) { + stream.getdents = FS.readdir(stream.path); + } + + var struct_size = 280; + var pos = 0; + var off = FS.llseek(stream, 0, 1); + + var idx = Math.floor(off / struct_size); + + while (idx < stream.getdents.length && pos + struct_size <= count) { + var id; + var type; + var name = stream.getdents[idx]; + if (name === '.') { + id = stream.node.id; + type = 4; // DT_DIR + } + else if (name === '..') { + var lookup = FS.lookupPath(stream.path, { parent: true }); + id = lookup.node.id; + type = 4; // DT_DIR + } + else { + var child = FS.lookupNode(stream.node, name); + id = child.id; + type = FS.isChrdev(child.mode) ? 2 : // DT_CHR, character device. + FS.isDir(child.mode) ? 4 : // DT_DIR, directory. + FS.isLink(child.mode) ? 10 : // DT_LNK, symbolic link. + 8; // DT_REG, regular file. + } + (tempI64 = [id>>>0,(tempDouble=id,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[((dirp + pos)>>2)] = tempI64[0],HEAP32[(((dirp + pos)+(4))>>2)] = tempI64[1]); + (tempI64 = [(idx + 1) * struct_size>>>0,(tempDouble=(idx + 1) * struct_size,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((dirp + pos)+(8))>>2)] = tempI64[0],HEAP32[(((dirp + pos)+(12))>>2)] = tempI64[1]); + HEAP16[(((dirp + pos)+(16))>>1)] = 280; + HEAP8[(((dirp + pos)+(18))>>0)] = type; + stringToUTF8(name, dirp + pos + 19, 256); + pos += struct_size; + idx += 1; + } + FS.llseek(stream, idx * struct_size, 0); + return pos; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var nowIsMonotonic = true; + + + + function ___syscall_getpeername(fd, addr, addrlen, d1, d2, d3) { + try { + + var sock = getSocketFromFD(fd); + if (!sock.daddr) { + return -53; // The socket is not connected. + } + var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(sock.daddr), sock.dport, addrlen); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var __emscripten_get_now_is_monotonic = () => nowIsMonotonic; + + + + function ___syscall_getsockname(fd, addr, addrlen, d1, d2, d3) { + try { + + var sock = getSocketFromFD(fd); + // TODO: sock.saddr should never be undefined, see TODO in websocket_sock_ops.getname + var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(sock.saddr || '0.0.0.0'), sock.sport, addrlen); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var __emscripten_throw_longjmp = () => { - throw Infinity; -}; + + function ___syscall_getsockopt(fd, level, optname, optval, optlen, d1) { + try { + + var sock = getSocketFromFD(fd); + // Minimal getsockopt aimed at resolving https://github.com/emscripten-core/emscripten/issues/2211 + // so only supports SOL_SOCKET with SO_ERROR. + if (level === 1) { + if (optname === 4) { + HEAP32[((optval)>>2)] = sock.error; + HEAP32[((optlen)>>2)] = 4; + sock.error = null; // Clear the error (The SO_ERROR option obtains and then clears this field). + return 0; + } + } + return -50; // The option is unknown at the level indicated. + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -function __gmtime_js(time_low, time_high, tmPtr) { - var time = convertI32PairToI53Checked(time_low, time_high); - var date = new Date(time * 1e3); - HEAP32[tmPtr >> 2] = date.getUTCSeconds(); - HEAP32[tmPtr + 4 >> 2] = date.getUTCMinutes(); - HEAP32[tmPtr + 8 >> 2] = date.getUTCHours(); - HEAP32[tmPtr + 12 >> 2] = date.getUTCDate(); - HEAP32[tmPtr + 16 >> 2] = date.getUTCMonth(); - HEAP32[tmPtr + 20 >> 2] = date.getUTCFullYear() - 1900; - HEAP32[tmPtr + 24 >> 2] = date.getUTCDay(); - var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0); - var yday = (date.getTime() - start) / (1e3 * 60 * 60 * 24) | 0; - HEAP32[tmPtr + 28 >> 2] = yday; -} + function ___syscall_ioctl(fd, op, varargs) { + SYSCALLS.varargs = varargs; + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + switch (op) { + case 21509: { + if (!stream.tty) return -59; + return 0; + } + case 21505: { + if (!stream.tty) return -59; + if (stream.tty.ops.ioctl_tcgets) { + var termios = stream.tty.ops.ioctl_tcgets(stream); + var argp = SYSCALLS.get(); + HEAP32[((argp)>>2)] = termios.c_iflag || 0; + HEAP32[(((argp)+(4))>>2)] = termios.c_oflag || 0; + HEAP32[(((argp)+(8))>>2)] = termios.c_cflag || 0; + HEAP32[(((argp)+(12))>>2)] = termios.c_lflag || 0; + for (var i = 0; i < 32; i++) { + HEAP8[(((argp + i)+(17))>>0)] = termios.c_cc[i] || 0; + } + return 0; + } + return 0; + } + case 21510: + case 21511: + case 21512: { + if (!stream.tty) return -59; + return 0; // no-op, not actually adjusting terminal settings + } + case 21506: + case 21507: + case 21508: { + if (!stream.tty) return -59; + if (stream.tty.ops.ioctl_tcsets) { + var argp = SYSCALLS.get(); + var c_iflag = HEAP32[((argp)>>2)]; + var c_oflag = HEAP32[(((argp)+(4))>>2)]; + var c_cflag = HEAP32[(((argp)+(8))>>2)]; + var c_lflag = HEAP32[(((argp)+(12))>>2)]; + var c_cc = [] + for (var i = 0; i < 32; i++) { + c_cc.push(HEAP8[(((argp + i)+(17))>>0)]); + } + return stream.tty.ops.ioctl_tcsets(stream.tty, op, { c_iflag, c_oflag, c_cflag, c_lflag, c_cc }); + } + return 0; // no-op, not actually adjusting terminal settings + } + case 21519: { + if (!stream.tty) return -59; + var argp = SYSCALLS.get(); + HEAP32[((argp)>>2)] = 0; + return 0; + } + case 21520: { + if (!stream.tty) return -59; + return -28; // not supported + } + case 21531: { + var argp = SYSCALLS.get(); + return FS.ioctl(stream, op, argp); + } + case 21523: { + // TODO: in theory we should write to the winsize struct that gets + // passed in, but for now musl doesn't read anything on it + if (!stream.tty) return -59; + if (stream.tty.ops.ioctl_tiocgwinsz) { + var winsize = stream.tty.ops.ioctl_tiocgwinsz(stream.tty); + var argp = SYSCALLS.get(); + HEAP16[((argp)>>1)] = winsize[0]; + HEAP16[(((argp)+(2))>>1)] = winsize[1]; + } + return 0; + } + case 21524: { + // TODO: technically, this ioctl call should change the window size. + // but, since emscripten doesn't have any concept of a terminal window + // yet, we'll just silently throw it away as we do TIOCGWINSZ + if (!stream.tty) return -59; + return 0; + } + case 21515: { + if (!stream.tty) return -59; + return 0; + } + default: return -28; // not supported + } + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var isLeapYear = year => year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); + + function ___syscall_listen(fd, backlog) { + try { + + var sock = getSocketFromFD(fd); + sock.sock_ops.listen(sock, backlog); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var MONTH_DAYS_LEAP_CUMULATIVE = [ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 ]; + function ___syscall_lstat64(path, buf) { + try { + + path = SYSCALLS.getStr(path); + return SYSCALLS.doStat(FS.lstat, path, buf); + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var MONTH_DAYS_REGULAR_CUMULATIVE = [ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ]; + function ___syscall_mkdirat(dirfd, path, mode) { + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + // remove a trailing slash, if one - /a/b/ has basename of '', but + // we want to create b in the context of this function + path = PATH.normalize(path); + if (path[path.length-1] === '/') path = path.substr(0, path.length-1); + FS.mkdir(path, mode, 0); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var ydayFromDate = date => { - var leap = isLeapYear(date.getFullYear()); - var monthDaysCumulative = leap ? MONTH_DAYS_LEAP_CUMULATIVE : MONTH_DAYS_REGULAR_CUMULATIVE; - var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1; - return yday; -}; + function ___syscall_newfstatat(dirfd, path, buf, flags) { + try { + + path = SYSCALLS.getStr(path); + var nofollow = flags & 256; + var allowEmpty = flags & 4096; + flags = flags & (~6400); + path = SYSCALLS.calculateAt(dirfd, path, allowEmpty); + return SYSCALLS.doStat(nofollow ? FS.lstat : FS.stat, path, buf); + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -function __localtime_js(time_low, time_high, tmPtr) { - var time = convertI32PairToI53Checked(time_low, time_high); - var date = new Date(time * 1e3); - HEAP32[tmPtr >> 2] = date.getSeconds(); - HEAP32[tmPtr + 4 >> 2] = date.getMinutes(); - HEAP32[tmPtr + 8 >> 2] = date.getHours(); - HEAP32[tmPtr + 12 >> 2] = date.getDate(); - HEAP32[tmPtr + 16 >> 2] = date.getMonth(); - HEAP32[tmPtr + 20 >> 2] = date.getFullYear() - 1900; - HEAP32[tmPtr + 24 >> 2] = date.getDay(); - var yday = ydayFromDate(date) | 0; - HEAP32[tmPtr + 28 >> 2] = yday; - HEAP32[tmPtr + 36 >> 2] = -(date.getTimezoneOffset() * 60); - var start = new Date(date.getFullYear(), 0, 1); - var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset(); - var winterOffset = start.getTimezoneOffset(); - var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset)) | 0; - HEAP32[tmPtr + 32 >> 2] = dst; -} + function ___syscall_openat(dirfd, path, flags, varargs) { + SYSCALLS.varargs = varargs; + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + var mode = varargs ? SYSCALLS.get() : 0; + return FS.open(path, flags, mode).fd; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + var PIPEFS = { + BUCKET_BUFFER_SIZE:8192, + mount(mount) { + // Do not pollute the real root directory or its child nodes with pipes + // Looks like it is OK to create another pseudo-root node not linked to the FS.root hierarchy this way + return FS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + }, + createPipe() { + var pipe = { + buckets: [], + // refcnt 2 because pipe has a read end and a write end. We need to be + // able to read from the read end after write end is closed. + refcnt : 2, + }; + + pipe.buckets.push({ + buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE), + offset: 0, + roffset: 0 + }); + + var rName = PIPEFS.nextname(); + var wName = PIPEFS.nextname(); + var rNode = FS.createNode(PIPEFS.root, rName, 4096, 0); + var wNode = FS.createNode(PIPEFS.root, wName, 4096, 0); + + rNode.pipe = pipe; + wNode.pipe = pipe; + + var readableStream = FS.createStream({ + path: rName, + node: rNode, + flags: 0, + seekable: false, + stream_ops: PIPEFS.stream_ops + }); + rNode.stream = readableStream; + + var writableStream = FS.createStream({ + path: wName, + node: wNode, + flags: 1, + seekable: false, + stream_ops: PIPEFS.stream_ops + }); + wNode.stream = writableStream; + + return { + readable_fd: readableStream.fd, + writable_fd: writableStream.fd + }; + }, + stream_ops:{ + poll(stream) { + var pipe = stream.node.pipe; + + if ((stream.flags & 2097155) === 1) { + return (256 | 4); + } + if (pipe.buckets.length > 0) { + for (var i = 0; i < pipe.buckets.length; i++) { + var bucket = pipe.buckets[i]; + if (bucket.offset - bucket.roffset > 0) { + return (64 | 1); + } + } + } + + return 0; + }, + ioctl(stream, request, varargs) { + return 28; + }, + fsync(stream) { + return 28; + }, + read(stream, buffer, offset, length, position /* ignored */) { + var pipe = stream.node.pipe; + var currentLength = 0; + + for (var i = 0; i < pipe.buckets.length; i++) { + var bucket = pipe.buckets[i]; + currentLength += bucket.offset - bucket.roffset; + } + + assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer)); + var data = buffer.subarray(offset, offset + length); + + if (length <= 0) { + return 0; + } + if (currentLength == 0) { + // Behave as if the read end is always non-blocking + throw new FS.ErrnoError(6); + } + var toRead = Math.min(currentLength, length); + + var totalRead = toRead; + var toRemove = 0; + + for (var i = 0; i < pipe.buckets.length; i++) { + var currBucket = pipe.buckets[i]; + var bucketSize = currBucket.offset - currBucket.roffset; + + if (toRead <= bucketSize) { + var tmpSlice = currBucket.buffer.subarray(currBucket.roffset, currBucket.offset); + if (toRead < bucketSize) { + tmpSlice = tmpSlice.subarray(0, toRead); + currBucket.roffset += toRead; + } else { + toRemove++; + } + data.set(tmpSlice); + break; + } else { + var tmpSlice = currBucket.buffer.subarray(currBucket.roffset, currBucket.offset); + data.set(tmpSlice); + data = data.subarray(tmpSlice.byteLength); + toRead -= tmpSlice.byteLength; + toRemove++; + } + } + + if (toRemove && toRemove == pipe.buckets.length) { + // Do not generate excessive garbage in use cases such as + // write several bytes, read everything, write several bytes, read everything... + toRemove--; + pipe.buckets[toRemove].offset = 0; + pipe.buckets[toRemove].roffset = 0; + } + + pipe.buckets.splice(0, toRemove); + + return totalRead; + }, + write(stream, buffer, offset, length, position /* ignored */) { + var pipe = stream.node.pipe; + + assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer)); + var data = buffer.subarray(offset, offset + length); + + var dataLen = data.byteLength; + if (dataLen <= 0) { + return 0; + } + + var currBucket = null; + + if (pipe.buckets.length == 0) { + currBucket = { + buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE), + offset: 0, + roffset: 0 + }; + pipe.buckets.push(currBucket); + } else { + currBucket = pipe.buckets[pipe.buckets.length - 1]; + } + + assert(currBucket.offset <= PIPEFS.BUCKET_BUFFER_SIZE); + + var freeBytesInCurrBuffer = PIPEFS.BUCKET_BUFFER_SIZE - currBucket.offset; + if (freeBytesInCurrBuffer >= dataLen) { + currBucket.buffer.set(data, currBucket.offset); + currBucket.offset += dataLen; + return dataLen; + } else if (freeBytesInCurrBuffer > 0) { + currBucket.buffer.set(data.subarray(0, freeBytesInCurrBuffer), currBucket.offset); + currBucket.offset += freeBytesInCurrBuffer; + data = data.subarray(freeBytesInCurrBuffer, data.byteLength); + } + + var numBuckets = (data.byteLength / PIPEFS.BUCKET_BUFFER_SIZE) | 0; + var remElements = data.byteLength % PIPEFS.BUCKET_BUFFER_SIZE; + + for (var i = 0; i < numBuckets; i++) { + var newBucket = { + buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE), + offset: PIPEFS.BUCKET_BUFFER_SIZE, + roffset: 0 + }; + pipe.buckets.push(newBucket); + newBucket.buffer.set(data.subarray(0, PIPEFS.BUCKET_BUFFER_SIZE)); + data = data.subarray(PIPEFS.BUCKET_BUFFER_SIZE, data.byteLength); + } + + if (remElements > 0) { + var newBucket = { + buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE), + offset: data.byteLength, + roffset: 0 + }; + pipe.buckets.push(newBucket); + newBucket.buffer.set(data); + } + + return dataLen; + }, + close(stream) { + var pipe = stream.node.pipe; + pipe.refcnt--; + if (pipe.refcnt === 0) { + pipe.buckets = null; + } + }, + }, + nextname() { + if (!PIPEFS.nextname.current) { + PIPEFS.nextname.current = 0; + } + return 'pipe[' + (PIPEFS.nextname.current++) + ']'; + }, + }; + + function ___syscall_pipe(fdPtr) { + try { + + if (fdPtr == 0) { + throw new FS.ErrnoError(21); + } + + var res = PIPEFS.createPipe(); + + HEAP32[((fdPtr)>>2)] = res.readable_fd; + HEAP32[(((fdPtr)+(4))>>2)] = res.writable_fd; + + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var __mktime_js = function(tmPtr) { - var ret = (() => { - var date = new Date(HEAP32[tmPtr + 20 >> 2] + 1900, HEAP32[tmPtr + 16 >> 2], HEAP32[tmPtr + 12 >> 2], HEAP32[tmPtr + 8 >> 2], HEAP32[tmPtr + 4 >> 2], HEAP32[tmPtr >> 2], 0); - var dst = HEAP32[tmPtr + 32 >> 2]; - var guessedOffset = date.getTimezoneOffset(); - var start = new Date(date.getFullYear(), 0, 1); - var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset(); - var winterOffset = start.getTimezoneOffset(); - var dstOffset = Math.min(winterOffset, summerOffset); - if (dst < 0) { - HEAP32[tmPtr + 32 >> 2] = Number(summerOffset != winterOffset && dstOffset == guessedOffset); - } else if (dst > 0 != (dstOffset == guessedOffset)) { - var nonDstOffset = Math.max(winterOffset, summerOffset); - var trueOffset = dst > 0 ? dstOffset : nonDstOffset; - date.setTime(date.getTime() + (trueOffset - guessedOffset) * 6e4); - } - HEAP32[tmPtr + 24 >> 2] = date.getDay(); - var yday = ydayFromDate(date) | 0; - HEAP32[tmPtr + 28 >> 2] = yday; - HEAP32[tmPtr >> 2] = date.getSeconds(); - HEAP32[tmPtr + 4 >> 2] = date.getMinutes(); - HEAP32[tmPtr + 8 >> 2] = date.getHours(); - HEAP32[tmPtr + 12 >> 2] = date.getDate(); - HEAP32[tmPtr + 16 >> 2] = date.getMonth(); - HEAP32[tmPtr + 20 >> 2] = date.getYear(); - return date.getTime() / 1e3; - })(); - return setTempRet0((tempDouble = ret, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0)), - ret >>> 0; -}; + function ___syscall_poll(fds, nfds, timeout) { + try { + + var nonzero = 0; + for (var i = 0; i < nfds; i++) { + var pollfd = fds + 8 * i; + var fd = HEAP32[((pollfd)>>2)]; + var events = HEAP16[(((pollfd)+(4))>>1)]; + var mask = 32; + var stream = FS.getStream(fd); + if (stream) { + mask = SYSCALLS.DEFAULT_POLLMASK; + if (stream.stream_ops?.poll) { + mask = stream.stream_ops.poll(stream, -1); + } + } + mask &= events | 8 | 16; + if (mask) nonzero++; + HEAP16[(((pollfd)+(6))>>1)] = mask; + } + return nonzero; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -function __mmap_js(len, prot, flags, fd, offset_low, offset_high, allocated, addr) { - var offset = convertI32PairToI53Checked(offset_low, offset_high); - try { - if (isNaN(offset)) return 61; - var stream = SYSCALLS.getStreamFromFD(fd); - var res = FS.mmap(stream, len, offset, prot, flags); - var ptr = res.ptr; - HEAP32[allocated >> 2] = res.allocated; - HEAPU32[addr >> 2] = ptr; - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} + + + function ___syscall_readlinkat(dirfd, path, buf, bufsize) { + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + if (bufsize <= 0) return -28; + var ret = FS.readlink(path); + + var len = Math.min(bufsize, lengthBytesUTF8(ret)); + var endChar = HEAP8[buf+len]; + stringToUTF8(ret, buf, bufsize+1); + // readlink is one of the rare functions that write out a C string, but does never append a null to the output buffer(!) + // stringToUTF8() always appends a null byte, so restore the character under the null byte after the write. + HEAP8[buf+len] = endChar; + return len; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -function __munmap_js(addr, len, prot, flags, fd, offset_low, offset_high) { - var offset = convertI32PairToI53Checked(offset_low, offset_high); - try { - if (isNaN(offset)) return 61; - var stream = SYSCALLS.getStreamFromFD(fd); - if (prot & 2) { - SYSCALLS.doMsync(addr, stream, len, flags, offset); - } - FS.munmap(stream); - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return -e.errno; - } -} + + + + function ___syscall_recvfrom(fd, buf, len, flags, addr, addrlen) { + try { + + var sock = getSocketFromFD(fd); + var msg = sock.sock_ops.recvmsg(sock, len, typeof flags !== "undefined" ? flags : 0); + if (!msg) return 0; // socket is closed + if (addr) { + var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(msg.addr), msg.port, addrlen); + } + HEAPU8.set(msg.buffer, buf); + return msg.buffer.byteLength; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var timers = {}; + function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) { + try { + + oldpath = SYSCALLS.getStr(oldpath); + newpath = SYSCALLS.getStr(newpath); + oldpath = SYSCALLS.calculateAt(olddirfd, oldpath); + newpath = SYSCALLS.calculateAt(newdirfd, newpath); + FS.rename(oldpath, newpath); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var handleException = e => { - if (e instanceof ExitStatus || e == "unwind") { - return EXITSTATUS; - } - quit_(1, e); -}; + function ___syscall_rmdir(path) { + try { + + path = SYSCALLS.getStr(path); + FS.rmdir(path); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var _proc_exit = code => { - EXITSTATUS = code; - if (!keepRuntimeAlive()) { - if (Module["onExit"]) Module["onExit"](code); - ABORT = true; - } - quit_(code, new ExitStatus(code)); -}; + + + function ___syscall_sendto(fd, message, length, flags, addr, addr_len) { + try { + + var sock = getSocketFromFD(fd); + var dest = getSocketAddress(addr, addr_len, true); + if (!dest) { + // send, no address provided + return FS.write(sock.stream, HEAP8,message, length); + } + // sendto an address + return sock.sock_ops.sendmsg(sock, HEAP8,message, length, dest.addr, dest.port); + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var exitJS = (status, implicit) => { - EXITSTATUS = status; - if (!keepRuntimeAlive()) { - exitRuntime(); - } - _proc_exit(status); -}; + + function ___syscall_socket(domain, type, protocol) { + try { + + var sock = SOCKFS.createSocket(domain, type, protocol); + return sock.stream.fd; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var _exit = exitJS; + function ___syscall_stat64(path, buf) { + try { + + path = SYSCALLS.getStr(path); + return SYSCALLS.doStat(FS.stat, path, buf); + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -Module["_exit"] = _exit; + function ___syscall_statfs64(path, size, buf) { + try { + + path = SYSCALLS.getStr(path); + // NOTE: None of the constants here are true. We're just returning safe and + // sane values. + HEAP32[(((buf)+(4))>>2)] = 4096; + HEAP32[(((buf)+(40))>>2)] = 4096; + HEAP32[(((buf)+(8))>>2)] = 1000000; + HEAP32[(((buf)+(12))>>2)] = 500000; + HEAP32[(((buf)+(16))>>2)] = 500000; + HEAP32[(((buf)+(20))>>2)] = FS.nextInode; + HEAP32[(((buf)+(24))>>2)] = 1000000; + HEAP32[(((buf)+(28))>>2)] = 42; + HEAP32[(((buf)+(44))>>2)] = 2; // ST_NOSUID + HEAP32[(((buf)+(36))>>2)] = 255; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var maybeExit = () => { - if (runtimeExited) { - return; - } - if (!keepRuntimeAlive()) { + function ___syscall_symlink(target, linkpath) { try { - _exit(EXITSTATUS); - } catch (e) { - handleException(e); + + target = SYSCALLS.getStr(target); + linkpath = SYSCALLS.getStr(linkpath); + FS.symlink(target, linkpath); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } } - } -}; -var callUserCallback = func => { - if (runtimeExited || ABORT) { - return; - } - try { - func(); - maybeExit(); - } catch (e) { - handleException(e); - } -}; + function ___syscall_unlinkat(dirfd, path, flags) { + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + if (flags === 0) { + FS.unlink(path); + } else if (flags === 512) { + FS.rmdir(path); + } else { + abort('Invalid flags passed to unlinkat'); + } + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var _emscripten_get_now; - -_emscripten_get_now = () => performance.now(); - -var __setitimer_js = (which, timeout_ms) => { - if (timers[which]) { - clearTimeout(timers[which].id); - delete timers[which]; - } - if (!timeout_ms) return 0; - var id = setTimeout((() => { - delete timers[which]; - callUserCallback((() => __emscripten_timeout(which, _emscripten_get_now()))); - }), timeout_ms); - timers[which] = { - id: id, - timeout_ms: timeout_ms - }; - return 0; -}; + function readI53FromI64(ptr) { + return HEAPU32[ptr>>2] + HEAP32[ptr+4>>2] * 4294967296; + } + + function ___syscall_utimensat(dirfd, path, times, flags) { + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path, true); + if (!times) { + var atime = Date.now(); + var mtime = atime; + } else { + var seconds = readI53FromI64(times); + var nanoseconds = HEAP32[(((times)+(8))>>2)]; + atime = (seconds*1000) + (nanoseconds/(1000*1000)); + times += 16; + seconds = readI53FromI64(times); + nanoseconds = HEAP32[(((times)+(8))>>2)]; + mtime = (seconds*1000) + (nanoseconds/(1000*1000)); + } + FS.utime(path, atime, mtime); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } -var stringToNewUTF8 = str => { - var size = lengthBytesUTF8(str) + 1; - var ret = _malloc(size); - if (ret) stringToUTF8(str, ret, size); - return ret; -}; + var nowIsMonotonic = true;; + var __emscripten_get_now_is_monotonic = () => nowIsMonotonic; -var __tzset_js = (timezone, daylight, tzname) => { - var currentYear = (new Date).getFullYear(); - var winter = new Date(currentYear, 0, 1); - var summer = new Date(currentYear, 6, 1); - var winterOffset = winter.getTimezoneOffset(); - var summerOffset = summer.getTimezoneOffset(); - var stdTimezoneOffset = Math.max(winterOffset, summerOffset); - HEAPU32[timezone >> 2] = stdTimezoneOffset * 60; - HEAP32[daylight >> 2] = Number(winterOffset != summerOffset); - function extractZone(date) { - var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/); - return match ? match[1] : "GMT"; - } - var winterName = extractZone(winter); - var summerName = extractZone(summer); - var winterNamePtr = stringToNewUTF8(winterName); - var summerNamePtr = stringToNewUTF8(summerName); - if (summerOffset < winterOffset) { - HEAPU32[tzname >> 2] = winterNamePtr; - HEAPU32[tzname + 4 >> 2] = summerNamePtr; - } else { - HEAPU32[tzname >> 2] = summerNamePtr; - HEAPU32[tzname + 4 >> 2] = winterNamePtr; - } -}; + var __emscripten_throw_longjmp = () => { + throw Infinity; + }; -var _abort = () => { - abort(""); -}; + function __gmtime_js(time_low, time_high,tmPtr) { + var time = convertI32PairToI53Checked(time_low, time_high);; + + + var date = new Date(time * 1000); + HEAP32[((tmPtr)>>2)] = date.getUTCSeconds(); + HEAP32[(((tmPtr)+(4))>>2)] = date.getUTCMinutes(); + HEAP32[(((tmPtr)+(8))>>2)] = date.getUTCHours(); + HEAP32[(((tmPtr)+(12))>>2)] = date.getUTCDate(); + HEAP32[(((tmPtr)+(16))>>2)] = date.getUTCMonth(); + HEAP32[(((tmPtr)+(20))>>2)] = date.getUTCFullYear()-1900; + HEAP32[(((tmPtr)+(24))>>2)] = date.getUTCDay(); + var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0); + var yday = ((date.getTime() - start) / (1000 * 60 * 60 * 24))|0; + HEAP32[(((tmPtr)+(28))>>2)] = yday; + ; + } + + var isLeapYear = (year) => { + return year%4 === 0 && (year%100 !== 0 || year%400 === 0); + }; + + var MONTH_DAYS_LEAP_CUMULATIVE = [0,31,60,91,121,152,182,213,244,274,305,335]; + + var MONTH_DAYS_REGULAR_CUMULATIVE = [0,31,59,90,120,151,181,212,243,273,304,334]; + var ydayFromDate = (date) => { + var leap = isLeapYear(date.getFullYear()); + var monthDaysCumulative = (leap ? MONTH_DAYS_LEAP_CUMULATIVE : MONTH_DAYS_REGULAR_CUMULATIVE); + var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1; // -1 since it's days since Jan 1 + + return yday; + }; + + function __localtime_js(time_low, time_high,tmPtr) { + var time = convertI32PairToI53Checked(time_low, time_high);; + + + var date = new Date(time*1000); + HEAP32[((tmPtr)>>2)] = date.getSeconds(); + HEAP32[(((tmPtr)+(4))>>2)] = date.getMinutes(); + HEAP32[(((tmPtr)+(8))>>2)] = date.getHours(); + HEAP32[(((tmPtr)+(12))>>2)] = date.getDate(); + HEAP32[(((tmPtr)+(16))>>2)] = date.getMonth(); + HEAP32[(((tmPtr)+(20))>>2)] = date.getFullYear()-1900; + HEAP32[(((tmPtr)+(24))>>2)] = date.getDay(); + + var yday = ydayFromDate(date)|0; + HEAP32[(((tmPtr)+(28))>>2)] = yday; + HEAP32[(((tmPtr)+(36))>>2)] = -(date.getTimezoneOffset() * 60); + + // Attention: DST is in December in South, and some regions don't have DST at all. + var start = new Date(date.getFullYear(), 0, 1); + var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset(); + var winterOffset = start.getTimezoneOffset(); + var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset))|0; + HEAP32[(((tmPtr)+(32))>>2)] = dst; + ; + } + + + + var __mktime_js = function(tmPtr) { + + var ret = (() => { + var date = new Date(HEAP32[(((tmPtr)+(20))>>2)] + 1900, + HEAP32[(((tmPtr)+(16))>>2)], + HEAP32[(((tmPtr)+(12))>>2)], + HEAP32[(((tmPtr)+(8))>>2)], + HEAP32[(((tmPtr)+(4))>>2)], + HEAP32[((tmPtr)>>2)], + 0); + + // There's an ambiguous hour when the time goes back; the tm_isdst field is + // used to disambiguate it. Date() basically guesses, so we fix it up if it + // guessed wrong, or fill in tm_isdst with the guess if it's -1. + var dst = HEAP32[(((tmPtr)+(32))>>2)]; + var guessedOffset = date.getTimezoneOffset(); + var start = new Date(date.getFullYear(), 0, 1); + var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset(); + var winterOffset = start.getTimezoneOffset(); + var dstOffset = Math.min(winterOffset, summerOffset); // DST is in December in South + if (dst < 0) { + // Attention: some regions don't have DST at all. + HEAP32[(((tmPtr)+(32))>>2)] = Number(summerOffset != winterOffset && dstOffset == guessedOffset); + } else if ((dst > 0) != (dstOffset == guessedOffset)) { + var nonDstOffset = Math.max(winterOffset, summerOffset); + var trueOffset = dst > 0 ? dstOffset : nonDstOffset; + // Don't try setMinutes(date.getMinutes() + ...) -- it's messed up. + date.setTime(date.getTime() + (trueOffset - guessedOffset)*60000); + } + + HEAP32[(((tmPtr)+(24))>>2)] = date.getDay(); + var yday = ydayFromDate(date)|0; + HEAP32[(((tmPtr)+(28))>>2)] = yday; + // To match expected behavior, update fields from date + HEAP32[((tmPtr)>>2)] = date.getSeconds(); + HEAP32[(((tmPtr)+(4))>>2)] = date.getMinutes(); + HEAP32[(((tmPtr)+(8))>>2)] = date.getHours(); + HEAP32[(((tmPtr)+(12))>>2)] = date.getDate(); + HEAP32[(((tmPtr)+(16))>>2)] = date.getMonth(); + HEAP32[(((tmPtr)+(20))>>2)] = date.getYear(); + + return date.getTime() / 1000; + })(); + return (setTempRet0((tempDouble=ret,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)), ret>>>0); + }; -function _emscripten_date_now() { - return Date.now(); -} + + + + + + function __mmap_js(len,prot,flags,fd,offset_low, offset_high,allocated,addr) { + var offset = convertI32PairToI53Checked(offset_low, offset_high);; + + + try { + + if (isNaN(offset)) return 61; + var stream = SYSCALLS.getStreamFromFD(fd); + var res = FS.mmap(stream, len, offset, prot, flags); + var ptr = res.ptr; + HEAP32[((allocated)>>2)] = res.allocated; + HEAPU32[((addr)>>2)] = ptr; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + ; + } -var getHeapMax = () => 2147483648; + + + + function __munmap_js(addr,len,prot,flags,fd,offset_low, offset_high) { + var offset = convertI32PairToI53Checked(offset_low, offset_high);; + + + try { + + if (isNaN(offset)) return 61; + var stream = SYSCALLS.getStreamFromFD(fd); + if (prot & 2) { + SYSCALLS.doMsync(addr, stream, len, flags, offset); + } + FS.munmap(stream); + // implicitly return 0 + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + ; + } -var _emscripten_get_heap_max = () => getHeapMax(); + var timers = { + }; + + var handleException = (e) => { + // Certain exception types we do not treat as errors since they are used for + // internal control flow. + // 1. ExitStatus, which is thrown by exit() + // 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others + // that wish to return to JS event loop. + if (e instanceof ExitStatus || e == 'unwind') { + return EXITSTATUS; + } + quit_(1, e); + }; + + + var _proc_exit = (code) => { + EXITSTATUS = code; + if (!keepRuntimeAlive()) { + if (Module['onExit']) Module['onExit'](code); + ABORT = true; + } + quit_(code, new ExitStatus(code)); + }; + /** @suppress {duplicate } */ + /** @param {boolean|number=} implicit */ + var exitJS = (status, implicit) => { + EXITSTATUS = status; + + if (!keepRuntimeAlive()) { + exitRuntime(); + } + + _proc_exit(status); + }; + var _exit = exitJS; + Module['_exit'] = _exit; + + var maybeExit = () => { + if (runtimeExited) { + return; + } + if (!keepRuntimeAlive()) { + try { + _exit(EXITSTATUS); + } catch (e) { + handleException(e); + } + } + }; + var callUserCallback = (func) => { + if (runtimeExited || ABORT) { + return; + } + try { + func(); + maybeExit(); + } catch (e) { + handleException(e); + } + }; + + + var _emscripten_get_now; + // Modern environment where performance.now() is supported: + // N.B. a shorter form "_emscripten_get_now = performance.now;" is + // unfortunately not allowed even in current browsers (e.g. FF Nightly 75). + _emscripten_get_now = () => performance.now(); + ; + var __setitimer_js = (which, timeout_ms) => { + // First, clear any existing timer. + if (timers[which]) { + clearTimeout(timers[which].id); + delete timers[which]; + } + + // A timeout of zero simply cancels the current timeout so we have nothing + // more to do. + if (!timeout_ms) return 0; + + var id = setTimeout(() => { + delete timers[which]; + callUserCallback(() => __emscripten_timeout(which, _emscripten_get_now())); + }, timeout_ms); + timers[which] = { id, timeout_ms }; + return 0; + }; -var _emscripten_memcpy_big = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num); + + + var stringToNewUTF8 = (str) => { + var size = lengthBytesUTF8(str) + 1; + var ret = _malloc(size); + if (ret) stringToUTF8(str, ret, size); + return ret; + }; + var __tzset_js = (timezone, daylight, tzname) => { + // TODO: Use (malleable) environment variables instead of system settings. + var currentYear = new Date().getFullYear(); + var winter = new Date(currentYear, 0, 1); + var summer = new Date(currentYear, 6, 1); + var winterOffset = winter.getTimezoneOffset(); + var summerOffset = summer.getTimezoneOffset(); + + // Local standard timezone offset. Local standard time is not adjusted for daylight savings. + // This code uses the fact that getTimezoneOffset returns a greater value during Standard Time versus Daylight Saving Time (DST). + // Thus it determines the expected output during Standard Time, and it compares whether the output of the given date the same (Standard) or less (DST). + var stdTimezoneOffset = Math.max(winterOffset, summerOffset); + + // timezone is specified as seconds west of UTC ("The external variable + // `timezone` shall be set to the difference, in seconds, between + // Coordinated Universal Time (UTC) and local standard time."), the same + // as returned by stdTimezoneOffset. + // See http://pubs.opengroup.org/onlinepubs/009695399/functions/tzset.html + HEAPU32[((timezone)>>2)] = stdTimezoneOffset * 60; + + HEAP32[((daylight)>>2)] = Number(winterOffset != summerOffset); + + function extractZone(date) { + var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/); + return match ? match[1] : "GMT"; + }; + var winterName = extractZone(winter); + var summerName = extractZone(summer); + var winterNamePtr = stringToNewUTF8(winterName); + var summerNamePtr = stringToNewUTF8(summerName); + if (summerOffset < winterOffset) { + // Northern hemisphere + HEAPU32[((tzname)>>2)] = winterNamePtr; + HEAPU32[(((tzname)+(4))>>2)] = summerNamePtr; + } else { + HEAPU32[((tzname)>>2)] = summerNamePtr; + HEAPU32[(((tzname)+(4))>>2)] = winterNamePtr; + } + }; -var growMemory = size => { - var b = wasmMemory.buffer; - var pages = size - b.byteLength + 65535 >>> 16; - try { - wasmMemory.grow(pages); - updateMemoryViews(); - return 1; - } catch (e) {} -}; + var _abort = () => { + abort(''); + }; -var _emscripten_resize_heap = requestedSize => { - var oldSize = HEAPU8.length; - requestedSize >>>= 0; - var maxHeapSize = getHeapMax(); - if (requestedSize > maxHeapSize) { - return false; - } - var alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple; - for (var cutDown = 1; cutDown <= 4; cutDown *= 2) { - var overGrownHeapSize = oldSize * (1 + .2 / cutDown); - overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296); - var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536)); - var replacement = growMemory(newSize); - if (replacement) { - return true; - } - } - return false; -}; + function _emscripten_date_now() { + return Date.now(); + } -var runtimeKeepalivePush = () => { - runtimeKeepaliveCounter += 1; -}; + var getHeapMax = () => + // Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate + // full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side + // for any code that deals with heap sizes, which would require special + // casing all heap size related code to treat 0 specially. + 2147483648; + var _emscripten_get_heap_max = () => getHeapMax(); -var runtimeKeepalivePop = () => { - runtimeKeepaliveCounter -= 1; -}; -var safeSetTimeout = (func, timeout) => { - runtimeKeepalivePush(); - return setTimeout((() => { - runtimeKeepalivePop(); - callUserCallback(func); - }), timeout); -}; + var _emscripten_memcpy_big = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num); -var _emscripten_sleep = function(ms) { - return Asyncify.handleSleep((wakeUp => safeSetTimeout(wakeUp, ms))); -}; + + var growMemory = (size) => { + var b = wasmMemory.buffer; + var pages = (size - b.byteLength + 65535) >>> 16; + try { + // round size grow request up to wasm page size (fixed 64KB per spec) + wasmMemory.grow(pages); // .grow() takes a delta compared to the previous size + updateMemoryViews(); + return 1 /*success*/; + } catch(e) { + } + // implicit 0 return to save code size (caller will cast "undefined" into 0 + // anyhow) + }; + var _emscripten_resize_heap = (requestedSize) => { + var oldSize = HEAPU8.length; + // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned. + requestedSize >>>= 0; + // With multithreaded builds, races can happen (another thread might increase the size + // in between), so return a failure, and let the caller retry. + + // Memory resize rules: + // 1. Always increase heap size to at least the requested size, rounded up + // to next page multiple. + // 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap + // geometrically: increase the heap size according to + // MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most + // overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB). + // 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap + // linearly: increase the heap size by at least + // MEMORY_GROWTH_LINEAR_STEP bytes. + // 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by + // MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest + // 4. If we were unable to allocate as much memory, it may be due to + // over-eager decision to excessively reserve due to (3) above. + // Hence if an allocation fails, cut down on the amount of excess + // growth, in an attempt to succeed to perform a smaller allocation. + + // A limit is set for how much we can grow. We should not exceed that + // (the wasm binary specifies it, so if we tried, we'd fail anyhow). + var maxHeapSize = getHeapMax(); + if (requestedSize > maxHeapSize) { + return false; + } + + var alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple; + + // Loop through potential heap size increases. If we attempt a too eager + // reservation that fails, cut down on the attempted size and reserve a + // smaller bump instead. (max 3 times, chosen somewhat arbitrarily) + for (var cutDown = 1; cutDown <= 4; cutDown *= 2) { + var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); // ensure geometric growth + // but limit overreserving (default to capping at +96MB overgrowth at most) + overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 ); + + var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536)); + + var replacement = growMemory(newSize); + if (replacement) { + + return true; + } + } + return false; + }; -Module["_emscripten_sleep"] = _emscripten_sleep; + + var runtimeKeepalivePush = () => { + runtimeKeepaliveCounter += 1; + }; + + var runtimeKeepalivePop = () => { + runtimeKeepaliveCounter -= 1; + }; + /** @param {number=} timeout */ + var safeSetTimeout = (func, timeout) => { + runtimeKeepalivePush(); + return setTimeout(() => { + runtimeKeepalivePop(); + callUserCallback(func); + }, timeout); + }; + var _emscripten_sleep = function(ms) { + // emscripten_sleep() does not return a value, but we still need a |return| + // here for stack switching support (ASYNCIFY=2). In that mode this function + // returns a Promise instead of nothing, and that Promise is what tells the + // wasm VM to pause the stack. + return Asyncify.handleSleep((wakeUp) => safeSetTimeout(wakeUp, ms)); + }; + Module['_emscripten_sleep'] = _emscripten_sleep; + _emscripten_sleep.isAsync = true; -_emscripten_sleep.isAsync = true; + var ENV = PHPLoader.ENV || { + }; + + var getExecutableName = () => { + return thisProgram || './this.program'; + }; + var getEnvStrings = () => { + if (!getEnvStrings.strings) { + // Default values. + // Browser language detection #8751 + var lang = ((typeof navigator == 'object' && navigator.languages && navigator.languages[0]) || 'C').replace('-', '_') + '.UTF-8'; + var env = { + 'USER': 'web_user', + 'LOGNAME': 'web_user', + 'PATH': '/', + 'PWD': '/', + 'HOME': '/home/web_user', + 'LANG': lang, + '_': getExecutableName() + }; + // Apply the user-provided values, if any. + for (var x in ENV) { + // x is a key in ENV; if ENV[x] is undefined, that means it was + // explicitly set to be so. We allow user code to do that to + // force variables with default values to remain unset. + if (ENV[x] === undefined) delete env[x]; + else env[x] = ENV[x]; + } + var strings = []; + for (var x in env) { + strings.push(`${x}=${env[x]}`); + } + getEnvStrings.strings = strings; + } + return getEnvStrings.strings; + }; + + var stringToAscii = (str, buffer) => { + for (var i = 0; i < str.length; ++i) { + HEAP8[((buffer++)>>0)] = str.charCodeAt(i); + } + // Null-terminate the string + HEAP8[((buffer)>>0)] = 0; + }; + + var _environ_get = (__environ, environ_buf) => { + var bufSize = 0; + getEnvStrings().forEach(function(string, i) { + var ptr = environ_buf + bufSize; + HEAPU32[(((__environ)+(i*4))>>2)] = ptr; + stringToAscii(string, ptr); + bufSize += string.length + 1; + }); + return 0; + }; -var ENV = PHPLoader.ENV || {}; + + var _environ_sizes_get = (penviron_count, penviron_buf_size) => { + var strings = getEnvStrings(); + HEAPU32[((penviron_count)>>2)] = strings.length; + var bufSize = 0; + strings.forEach(function(string) { + bufSize += string.length + 1; + }); + HEAPU32[((penviron_buf_size)>>2)] = bufSize; + return 0; + }; -var getExecutableName = () => thisProgram || "./this.program"; -var getEnvStrings = () => { - if (!getEnvStrings.strings) { - var lang = (typeof navigator == "object" && navigator.languages && navigator.languages[0] || "C").replace("-", "_") + ".UTF-8"; - var env = { - "USER": "web_user", - "LOGNAME": "web_user", - "PATH": "/", - "PWD": "/", - "HOME": "/home/web_user", - "LANG": lang, - "_": getExecutableName() - }; - for (var x in ENV) { - if (ENV[x] === undefined) delete env[x]; else env[x] = ENV[x]; + function _fd_close(fd) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + FS.close(stream); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; } - var strings = []; - for (var x in env) { - strings.push(`${x}=${env[x]}`); } - getEnvStrings.strings = strings; - } - return getEnvStrings.strings; -}; - -var stringToAscii = (str, buffer) => { - for (var i = 0; i < str.length; ++i) { - HEAP8[buffer++ >> 0] = str.charCodeAt(i); - } - HEAP8[buffer >> 0] = 0; -}; - -var _environ_get = (__environ, environ_buf) => { - var bufSize = 0; - getEnvStrings().forEach((function(string, i) { - var ptr = environ_buf + bufSize; - HEAPU32[__environ + i * 4 >> 2] = ptr; - stringToAscii(string, ptr); - bufSize += string.length + 1; - })); - return 0; -}; - -var _environ_sizes_get = (penviron_count, penviron_buf_size) => { - var strings = getEnvStrings(); - HEAPU32[penviron_count >> 2] = strings.length; - var bufSize = 0; - strings.forEach((function(string) { - bufSize += string.length + 1; - })); - HEAPU32[penviron_buf_size >> 2] = bufSize; - return 0; -}; - -function _fd_close(fd) { - try { - var stream = SYSCALLS.getStreamFromFD(fd); - FS.close(stream); - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return e.errno; - } -} - -function _fd_fdstat_get(fd, pbuf) { - try { - var rightsBase = 0; - var rightsInheriting = 0; - var flags = 0; - { - var stream = SYSCALLS.getStreamFromFD(fd); - var type = stream.tty ? 2 : FS.isDir(stream.mode) ? 3 : FS.isLink(stream.mode) ? 7 : 4; - } - HEAP8[pbuf >> 0] = type; - HEAP16[pbuf + 2 >> 1] = flags; - tempI64 = [ rightsBase >>> 0, (tempDouble = rightsBase, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], - HEAP32[pbuf + 8 >> 2] = tempI64[0], HEAP32[pbuf + 12 >> 2] = tempI64[1]; - tempI64 = [ rightsInheriting >>> 0, (tempDouble = rightsInheriting, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], - HEAP32[pbuf + 16 >> 2] = tempI64[0], HEAP32[pbuf + 20 >> 2] = tempI64[1]; - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return e.errno; - } -} - -var doReadv = (stream, iov, iovcnt, offset) => { - var ret = 0; - for (var i = 0; i < iovcnt; i++) { - var ptr = HEAPU32[iov >> 2]; - var len = HEAPU32[iov + 4 >> 2]; - iov += 8; - var curr = FS.read(stream, HEAP8, ptr, len, offset); - if (curr < 0) return -1; - ret += curr; - if (curr < len) break; - if (typeof offset !== "undefined") { - offset += curr; - } - } - return ret; -}; - -function _fd_read(fd, iov, iovcnt, pnum) { - try { - var stream = SYSCALLS.getStreamFromFD(fd); - var num = doReadv(stream, iov, iovcnt); - HEAPU32[pnum >> 2] = num; - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return e.errno; - } -} - -function _fd_seek(fd, offset_low, offset_high, whence, newOffset) { - var offset = convertI32PairToI53Checked(offset_low, offset_high); - try { - if (isNaN(offset)) return 61; - var stream = SYSCALLS.getStreamFromFD(fd); - FS.llseek(stream, offset, whence); - tempI64 = [ stream.position >>> 0, (tempDouble = stream.position, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? +Math.floor(tempDouble / 4294967296) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ], - HEAP32[newOffset >> 2] = tempI64[0], HEAP32[newOffset + 4 >> 2] = tempI64[1]; - if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return e.errno; - } -} - -var doWritev = (stream, iov, iovcnt, offset) => { - var ret = 0; - for (var i = 0; i < iovcnt; i++) { - var ptr = HEAPU32[iov >> 2]; - var len = HEAPU32[iov + 4 >> 2]; - iov += 8; - var curr = FS.write(stream, HEAP8, ptr, len, offset); - if (curr < 0) return -1; - ret += curr; - if (typeof offset !== "undefined") { - offset += curr; - } - } - return ret; -}; - -function _fd_write(fd, iov, iovcnt, pnum) { - try { - var stream = SYSCALLS.getStreamFromFD(fd); - var num = doWritev(stream, iov, iovcnt); - HEAPU32[pnum >> 2] = num; - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; - return e.errno; - } -} -var _getaddrinfo = (node, service, hint, out) => { - var addr = 0; - var port = 0; - var flags = 0; - var family = 0; - var type = 0; - var proto = 0; - var ai; - function allocaddrinfo(family, type, proto, canon, addr, port) { - var sa, salen, ai; - var errno; - salen = family === 10 ? 28 : 16; - addr = family === 10 ? inetNtop6(addr) : inetNtop4(addr); - sa = _malloc(salen); - errno = writeSockaddr(sa, family, addr, port); - assert(!errno); - ai = _malloc(32); - HEAP32[ai + 4 >> 2] = family; - HEAP32[ai + 8 >> 2] = type; - HEAP32[ai + 12 >> 2] = proto; - HEAPU32[ai + 24 >> 2] = canon; - HEAPU32[ai + 20 >> 2] = sa; - if (family === 10) { - HEAP32[ai + 16 >> 2] = 28; - } else { - HEAP32[ai + 16 >> 2] = 16; - } - HEAP32[ai + 28 >> 2] = 0; - return ai; - } - if (hint) { - flags = HEAP32[hint >> 2]; - family = HEAP32[hint + 4 >> 2]; - type = HEAP32[hint + 8 >> 2]; - proto = HEAP32[hint + 12 >> 2]; - } - if (type && !proto) { - proto = type === 2 ? 17 : 6; - } - if (!type && proto) { - type = proto === 17 ? 2 : 1; - } - if (proto === 0) { - proto = 6; - } - if (type === 0) { - type = 1; - } - if (!node && !service) { - return -2; - } - if (flags & ~(1 | 2 | 4 | 1024 | 8 | 16 | 32)) { - return -1; - } - if (hint !== 0 && HEAP32[hint >> 2] & 2 && !node) { - return -1; - } - if (flags & 32) { - return -2; - } - if (type !== 0 && type !== 1 && type !== 2) { - return -7; - } - if (family !== 0 && family !== 2 && family !== 10) { - return -6; - } - if (service) { - service = UTF8ToString(service); - port = parseInt(service, 10); - if (isNaN(port)) { - if (flags & 1024) { - return -2; - } - return -8; - } - } - if (!node) { - if (family === 0) { - family = 2; - } - if ((flags & 1) === 0) { - if (family === 2) { - addr = _htonl(2130706433); - } else { - addr = [ 0, 0, 0, 1 ]; - } + function _fd_fdstat_get(fd, pbuf) { + try { + + var rightsBase = 0; + var rightsInheriting = 0; + var flags = 0; + { + var stream = SYSCALLS.getStreamFromFD(fd); + // All character devices are terminals (other things a Linux system would + // assume is a character device, like the mouse, we have special APIs for). + var type = stream.tty ? 2 : + FS.isDir(stream.mode) ? 3 : + FS.isLink(stream.mode) ? 7 : + 4; + } + HEAP8[((pbuf)>>0)] = type; + HEAP16[(((pbuf)+(2))>>1)] = flags; + (tempI64 = [rightsBase>>>0,(tempDouble=rightsBase,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((pbuf)+(8))>>2)] = tempI64[0],HEAP32[(((pbuf)+(12))>>2)] = tempI64[1]); + (tempI64 = [rightsInheriting>>>0,(tempDouble=rightsInheriting,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((pbuf)+(16))>>2)] = tempI64[0],HEAP32[(((pbuf)+(20))>>2)] = tempI64[1]); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + /** @param {number=} offset */ + var doReadv = (stream, iov, iovcnt, offset) => { + var ret = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[((iov)>>2)]; + var len = HEAPU32[(((iov)+(4))>>2)]; + iov += 8; + var curr = FS.read(stream, HEAP8,ptr, len, offset); + if (curr < 0) return -1; + ret += curr; + if (curr < len) break; // nothing more to read + if (typeof offset !== 'undefined') { + offset += curr; + } + } + return ret; + }; + + function _fd_read(fd, iov, iovcnt, pnum) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + var num = doReadv(stream, iov, iovcnt); + HEAPU32[((pnum)>>2)] = num; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; } - ai = allocaddrinfo(family, type, proto, null, addr, port); - HEAPU32[out >> 2] = ai; - return 0; - } - node = UTF8ToString(node); - addr = inetPton4(node); - if (addr !== null) { - if (family === 0 || family === 2) { - family = 2; - } else if (family === 10 && flags & 8) { - addr = [ 0, 0, _htonl(65535), addr ]; - family = 10; - } else { - return -2; - } - } else { - addr = inetPton6(node); - if (addr !== null) { - if (family === 0 || family === 10) { - family = 10; - } else { - return -2; - } } - } - if (addr != null) { - ai = allocaddrinfo(family, type, proto, node, addr, port); - HEAPU32[out >> 2] = ai; - return 0; - } - if (flags & 4) { - return -2; - } - node = DNS.lookup_name(node); - addr = inetPton4(node); - if (family === 0) { - family = 2; - } else if (family === 10) { - addr = [ 0, 0, _htonl(65535), addr ]; - } - ai = allocaddrinfo(family, type, proto, null, addr, port); - HEAPU32[out >> 2] = ai; - return 0; -}; - -var getHostByName = name => { - var ret = _malloc(20); - var nameBuf = stringToNewUTF8(name); - HEAPU32[ret >> 2] = nameBuf; - var aliasesBuf = _malloc(4); - HEAPU32[aliasesBuf >> 2] = 0; - HEAPU32[ret + 4 >> 2] = aliasesBuf; - var afinet = 2; - HEAP32[ret + 8 >> 2] = afinet; - HEAP32[ret + 12 >> 2] = 4; - var addrListBuf = _malloc(12); - HEAPU32[addrListBuf >> 2] = addrListBuf + 8; - HEAPU32[addrListBuf + 4 >> 2] = 0; - HEAP32[addrListBuf + 8 >> 2] = inetPton4(DNS.lookup_name(name)); - HEAPU32[ret + 16 >> 2] = addrListBuf; - return ret; -}; -var _gethostbyaddr = (addr, addrlen, type) => { - if (type !== 2) { - setErrNo(5); - return null; - } - addr = HEAP32[addr >> 2]; - var host = inetNtop4(addr); - var lookup = DNS.lookup_addr(host); - if (lookup) { - host = lookup; - } - return getHostByName(host); -}; + + function _fd_seek(fd,offset_low, offset_high,whence,newOffset) { + var offset = convertI32PairToI53Checked(offset_low, offset_high);; + + + try { + + if (isNaN(offset)) return 61; + var stream = SYSCALLS.getStreamFromFD(fd); + FS.llseek(stream, offset, whence); + (tempI64 = [stream.position>>>0,(tempDouble=stream.position,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[((newOffset)>>2)] = tempI64[0],HEAP32[(((newOffset)+(4))>>2)] = tempI64[1]); + if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + ; + } + + /** @param {number=} offset */ + var doWritev = (stream, iov, iovcnt, offset) => { + var ret = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[((iov)>>2)]; + var len = HEAPU32[(((iov)+(4))>>2)]; + iov += 8; + var curr = FS.write(stream, HEAP8,ptr, len, offset); + if (curr < 0) return -1; + ret += curr; + if (typeof offset !== 'undefined') { + offset += curr; + } + } + return ret; + }; + + function _fd_write(fd, iov, iovcnt, pnum) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + var num = doWritev(stream, iov, iovcnt); + HEAPU32[((pnum)>>2)] = num; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + + + + + + + + + + var _getaddrinfo = (node, service, hint, out) => { + // Note getaddrinfo currently only returns a single addrinfo with ai_next defaulting to NULL. When NULL + // hints are specified or ai_family set to AF_UNSPEC or ai_socktype or ai_protocol set to 0 then we + // really should provide a linked list of suitable addrinfo values. + var addrs = []; + var canon = null; + var addr = 0; + var port = 0; + var flags = 0; + var family = 0; + var type = 0; + var proto = 0; + var ai, last; + + function allocaddrinfo(family, type, proto, canon, addr, port) { + var sa, salen, ai; + var errno; + + salen = family === 10 ? + 28 : + 16; + addr = family === 10 ? + inetNtop6(addr) : + inetNtop4(addr); + sa = _malloc(salen); + errno = writeSockaddr(sa, family, addr, port); + assert(!errno); + + ai = _malloc(32); + HEAP32[(((ai)+(4))>>2)] = family; + HEAP32[(((ai)+(8))>>2)] = type; + HEAP32[(((ai)+(12))>>2)] = proto; + HEAPU32[(((ai)+(24))>>2)] = canon; + HEAPU32[(((ai)+(20))>>2)] = sa; + if (family === 10) { + HEAP32[(((ai)+(16))>>2)] = 28; + } else { + HEAP32[(((ai)+(16))>>2)] = 16; + } + HEAP32[(((ai)+(28))>>2)] = 0; + + return ai; + } + + if (hint) { + flags = HEAP32[((hint)>>2)]; + family = HEAP32[(((hint)+(4))>>2)]; + type = HEAP32[(((hint)+(8))>>2)]; + proto = HEAP32[(((hint)+(12))>>2)]; + } + if (type && !proto) { + proto = type === 2 ? 17 : 6; + } + if (!type && proto) { + type = proto === 17 ? 2 : 1; + } + + // If type or proto are set to zero in hints we should really be returning multiple addrinfo values, but for + // now default to a TCP STREAM socket so we can at least return a sensible addrinfo given NULL hints. + if (proto === 0) { + proto = 6; + } + if (type === 0) { + type = 1; + } + + if (!node && !service) { + return -2; + } + if (flags & ~(1|2|4| + 1024|8|16|32)) { + return -1; + } + if (hint !== 0 && (HEAP32[((hint)>>2)] & 2) && !node) { + return -1; + } + if (flags & 32) { + // TODO + return -2; + } + if (type !== 0 && type !== 1 && type !== 2) { + return -7; + } + if (family !== 0 && family !== 2 && family !== 10) { + return -6; + } + + if (service) { + service = UTF8ToString(service); + port = parseInt(service, 10); + + if (isNaN(port)) { + if (flags & 1024) { + return -2; + } + // TODO support resolving well-known service names from: + // http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt + return -8; + } + } + + if (!node) { + if (family === 0) { + family = 2; + } + if ((flags & 1) === 0) { + if (family === 2) { + addr = _htonl(2130706433); + } else { + addr = [0, 0, 0, 1]; + } + } + ai = allocaddrinfo(family, type, proto, null, addr, port); + HEAPU32[((out)>>2)] = ai; + return 0; + } + + // + // try as a numeric address + // + node = UTF8ToString(node); + addr = inetPton4(node); + if (addr !== null) { + // incoming node is a valid ipv4 address + if (family === 0 || family === 2) { + family = 2; + } + else if (family === 10 && (flags & 8)) { + addr = [0, 0, _htonl(0xffff), addr]; + family = 10; + } else { + return -2; + } + } else { + addr = inetPton6(node); + if (addr !== null) { + // incoming node is a valid ipv6 address + if (family === 0 || family === 10) { + family = 10; + } else { + return -2; + } + } + } + if (addr != null) { + ai = allocaddrinfo(family, type, proto, node, addr, port); + HEAPU32[((out)>>2)] = ai; + return 0; + } + if (flags & 4) { + return -2; + } + + // + // try as a hostname + // + // resolve the hostname to a temporary fake address + node = DNS.lookup_name(node); + addr = inetPton4(node); + if (family === 0) { + family = 2; + } else if (family === 10) { + addr = [0, 0, _htonl(0xffff), addr]; + } + ai = allocaddrinfo(family, type, proto, null, addr, port); + HEAPU32[((out)>>2)] = ai; + return 0; + }; -var _gethostbyname = name => getHostByName(UTF8ToString(name)); + + + + + var getHostByName = (name) => { + // generate hostent + var ret = _malloc(20); // XXX possibly leaked, as are others here + var nameBuf = stringToNewUTF8(name); + HEAPU32[((ret)>>2)] = nameBuf; + var aliasesBuf = _malloc(4); + HEAPU32[((aliasesBuf)>>2)] = 0; + HEAPU32[(((ret)+(4))>>2)] = aliasesBuf; + var afinet = 2; + HEAP32[(((ret)+(8))>>2)] = afinet; + HEAP32[(((ret)+(12))>>2)] = 4; + var addrListBuf = _malloc(12); + HEAPU32[((addrListBuf)>>2)] = addrListBuf+8; + HEAPU32[(((addrListBuf)+(4))>>2)] = 0; + HEAP32[(((addrListBuf)+(8))>>2)] = inetPton4(DNS.lookup_name(name)); + HEAPU32[(((ret)+(16))>>2)] = addrListBuf; + return ret; + }; + + + var _gethostbyaddr = (addr, addrlen, type) => { + if (type !== 2) { + setErrNo(5); + // TODO: set h_errno + return null; + } + addr = HEAP32[((addr)>>2)]; // addr is in_addr + var host = inetNtop4(addr); + var lookup = DNS.lookup_addr(host); + if (lookup) { + host = lookup; + } + return getHostByName(host); + }; -var _gethostbyname_r = (name, ret, buf, buflen, out, err) => { - var data = _gethostbyname(name); - _memcpy(ret, data, 20); - _free(data); - HEAP32[err >> 2] = 0; - HEAPU32[out >> 2] = ret; - return 0; -}; + + var _gethostbyname = (name) => { + return getHostByName(UTF8ToString(name)); + }; + + + var _gethostbyname_r = (name, ret, buf, buflen, out, err) => { + var data = _gethostbyname(name); + _memcpy(ret, data, 20); + _free(data); + HEAP32[((err)>>2)] = 0; + HEAPU32[((out)>>2)] = ret; + return 0; + }; -var _getloadavg = (loadavg, nelem) => { - var limit = Math.min(nelem, 3); - var doubleSize = 8; - for (var i = 0; i < limit; i++) { - HEAPF64[loadavg + i * doubleSize >> 3] = .1; - } - return limit; -}; + var _getloadavg = (loadavg, nelem) => { + // int getloadavg(double loadavg[], int nelem); + // http://linux.die.net/man/3/getloadavg + var limit = Math.min(nelem, 3); + var doubleSize = 8; + for (var i = 0; i < limit; i++) { + HEAPF64[(((loadavg)+(i * doubleSize))>>3)] = 0.1; + } + return limit; + }; -var _getnameinfo = (sa, salen, node, nodelen, serv, servlen, flags) => { - var info = readSockaddr(sa, salen); - if (info.errno) { - return -6; - } - var port = info.port; - var addr = info.addr; - var overflowed = false; - if (node && nodelen) { - var lookup; - if (flags & 1 || !(lookup = DNS.lookup_addr(addr))) { - if (flags & 8) { - return -2; - } - } else { - addr = lookup; - } - var numBytesWrittenExclNull = stringToUTF8(addr, node, nodelen); - if (numBytesWrittenExclNull + 1 >= nodelen) { - overflowed = true; - } - } - if (serv && servlen) { - port = "" + port; - var numBytesWrittenExclNull = stringToUTF8(port, serv, servlen); - if (numBytesWrittenExclNull + 1 >= servlen) { - overflowed = true; - } - } - if (overflowed) { - return -12; - } - return 0; -}; + + + + var _getnameinfo = (sa, salen, node, nodelen, serv, servlen, flags) => { + var info = readSockaddr(sa, salen); + if (info.errno) { + return -6; + } + var port = info.port; + var addr = info.addr; + + var overflowed = false; + + if (node && nodelen) { + var lookup; + if ((flags & 1) || !(lookup = DNS.lookup_addr(addr))) { + if (flags & 8) { + return -2; + } + } else { + addr = lookup; + } + var numBytesWrittenExclNull = stringToUTF8(addr, node, nodelen); + + if (numBytesWrittenExclNull+1 >= nodelen) { + overflowed = true; + } + } + + if (serv && servlen) { + port = '' + port; + var numBytesWrittenExclNull = stringToUTF8(port, serv, servlen); + + if (numBytesWrittenExclNull+1 >= servlen) { + overflowed = true; + } + } + + if (overflowed) { + // Note: even when we overflow, getnameinfo() is specced to write out the truncated results. + return -12; + } + + return 0; + }; -var Protocols = { - list: [], - map: {} -}; + var Protocols = { + list:[], + map:{ + }, + }; + + + var _setprotoent = (stayopen) => { + // void setprotoent(int stayopen); + + // Allocate and populate a protoent structure given a name, protocol number and array of aliases + function allocprotoent(name, proto, aliases) { + // write name into buffer + var nameBuf = _malloc(name.length + 1); + stringToAscii(name, nameBuf); + + // write aliases into buffer + var j = 0; + var length = aliases.length; + var aliasListBuf = _malloc((length + 1) * 4); // Use length + 1 so we have space for the terminating NULL ptr. + + for (var i = 0; i < length; i++, j += 4) { + var alias = aliases[i]; + var aliasBuf = _malloc(alias.length + 1); + stringToAscii(alias, aliasBuf); + HEAPU32[(((aliasListBuf)+(j))>>2)] = aliasBuf; + } + HEAPU32[(((aliasListBuf)+(j))>>2)] = 0; // Terminating NULL pointer. + + // generate protoent + var pe = _malloc(12); + HEAPU32[((pe)>>2)] = nameBuf; + HEAPU32[(((pe)+(4))>>2)] = aliasListBuf; + HEAP32[(((pe)+(8))>>2)] = proto; + return pe; + }; + + // Populate the protocol 'database'. The entries are limited to tcp and udp, though it is fairly trivial + // to add extra entries from /etc/protocols if desired - though not sure if that'd actually be useful. + var list = Protocols.list; + var map = Protocols.map; + if (list.length === 0) { + var entry = allocprotoent('tcp', 6, ['TCP']); + list.push(entry); + map['tcp'] = map['6'] = entry; + entry = allocprotoent('udp', 17, ['UDP']); + list.push(entry); + map['udp'] = map['17'] = entry; + } + + _setprotoent.index = 0; + }; + + + var _getprotobyname = (name) => { + // struct protoent *getprotobyname(const char *); + name = UTF8ToString(name); + _setprotoent(true); + var result = Protocols.map[name]; + return result; + }; -var _setprotoent = stayopen => { - function allocprotoent(name, proto, aliases) { - var nameBuf = _malloc(name.length + 1); - stringToAscii(name, nameBuf); - var j = 0; - var length = aliases.length; - var aliasListBuf = _malloc((length + 1) * 4); - for (var i = 0; i < length; i++, j += 4) { - var alias = aliases[i]; - var aliasBuf = _malloc(alias.length + 1); - stringToAscii(alias, aliasBuf); - HEAPU32[aliasListBuf + j >> 2] = aliasBuf; - } - HEAPU32[aliasListBuf + j >> 2] = 0; - var pe = _malloc(12); - HEAPU32[pe >> 2] = nameBuf; - HEAPU32[pe + 4 >> 2] = aliasListBuf; - HEAP32[pe + 8 >> 2] = proto; - return pe; - } - var list = Protocols.list; - var map = Protocols.map; - if (list.length === 0) { - var entry = allocprotoent("tcp", 6, [ "TCP" ]); - list.push(entry); - map["tcp"] = map["6"] = entry; - entry = allocprotoent("udp", 17, [ "UDP" ]); - list.push(entry); - map["udp"] = map["17"] = entry; - } - _setprotoent.index = 0; -}; + + var _getprotobynumber = (number) => { + // struct protoent *getprotobynumber(int proto); + _setprotoent(true); + var result = Protocols.map[number]; + return result; + }; -var _getprotobyname = name => { - name = UTF8ToString(name); - _setprotoent(true); - var result = Protocols.map[name]; - return result; -}; + + /** @suppress {duplicate } */ + var stringToUTF8OnStack = (str) => { + var size = lengthBytesUTF8(str) + 1; + var ret = stackAlloc(size); + stringToUTF8(str, ret, size); + return ret; + }; + var allocateUTF8OnStack = stringToUTF8OnStack; + + var PHPWASM = { + init:function () { + // The /internal directory is required by the C module. It's where the + // stdout, stderr, and headers information are written for the JavaScript + // code to read later on. + FS.mkdir("/internal"); + + PHPWASM.EventEmitter = ENVIRONMENT_IS_NODE + ? require('events').EventEmitter + : class EventEmitter { + constructor() { + this.listeners = {}; + } + emit(eventName, data) { + if (this.listeners[eventName]) { + this.listeners[eventName].forEach( + (callback) => { + callback(data); + } + ); + } + } + once(eventName, callback) { + const self = this; + function removedCallback() { + callback(...arguments); + self.removeListener(eventName, removedCallback); + } + this.on(eventName, removedCallback); + } + removeAllListeners(eventName) { + if (eventName) { + delete this.listeners[eventName]; + } else { + this.listeners = {}; + } + } + removeListener(eventName, callback) { + if (this.listeners[eventName]) { + const idx = + this.listeners[eventName].indexOf(callback); + if (idx !== -1) { + this.listeners[eventName].splice(idx, 1); + } + } + } + }; + PHPWASM.child_proc_by_fd = {}; + PHPWASM.child_proc_by_pid = {}; + PHPWASM.input_devices = {}; + }, + getAllWebSockets:function (sock) { + const webSockets = /* @__PURE__ */ new Set(); + if (sock.server) { + sock.server.clients.forEach((ws) => { + webSockets.add(ws); + }); + } + for (const peer of PHPWASM.getAllPeers(sock)) { + webSockets.add(peer.socket); + } + return Array.from(webSockets); + }, + getAllPeers:function (sock) { + const peers = new Set(); + if (sock.server) { + sock.pending + .filter((pending) => pending.peers) + .forEach((pending) => { + for (const peer of Object.values(pending.peers)) { + peers.add(peer); + } + }); + } + if (sock.peers) { + for (const peer of Object.values(sock.peers)) { + peers.add(peer); + } + } + return Array.from(peers); + }, + awaitData:function (ws) { + return PHPWASM.awaitEvent(ws, 'message'); + }, + awaitConnection:function (ws) { + if (ws.OPEN === ws.readyState) { + return [Promise.resolve(), PHPWASM.noop]; + } + return PHPWASM.awaitEvent(ws, 'open'); + }, + awaitClose:function (ws) { + if ([ws.CLOSING, ws.CLOSED].includes(ws.readyState)) { + return [Promise.resolve(), PHPWASM.noop]; + } + return PHPWASM.awaitEvent(ws, 'close'); + }, + awaitError:function (ws) { + if ([ws.CLOSING, ws.CLOSED].includes(ws.readyState)) { + return [Promise.resolve(), PHPWASM.noop]; + } + return PHPWASM.awaitEvent(ws, 'error'); + }, + awaitEvent:function (ws, event) { + let resolve; + const listener = () => { + resolve(); + }; + const promise = new Promise(function (_resolve) { + resolve = _resolve; + ws.once(event, listener); + }); + const cancel = () => { + ws.removeListener(event, listener); + // Rejecting the promises bubbles up and kills the entire + // node process. Let's resolve them on the next tick instead + // to give the caller some space to unbind any handlers. + setTimeout(resolve); + }; + return [promise, cancel]; + }, + noop:function () { }, + spawnProcess:function (command, args, options) { + if (Module['spawnProcess']) { + const spawnedPromise = Module['spawnProcess'](command, args, options); + return Promise.resolve(spawnedPromise).then(function (spawned) { + if (!spawned || !spawned.on) { + throw new Error( + 'spawnProcess() must return an EventEmitter but returned a different type.' + ); + } + return spawned; + }); + } + + if (ENVIRONMENT_IS_NODE) { + return require('child_process').spawn(command, args, { + ...options, + shell: true, + stdio: ['pipe', 'pipe', 'pipe'], + timeout: 100, + }); + } + const e = new Error( + 'popen(), proc_open() etc. are unsupported in the browser. Call php.setSpawnHandler() ' + + 'and provide a callback to handle spawning processes, or disable a popen(), proc_open() ' + + 'and similar functions via php.ini.' + ); + e.code = 'SPAWN_UNSUPPORTED'; + throw e; + }, + shutdownSocket:function (socketd, how) { + // This implementation only supports websockets at the moment + const sock = getSocketFromFD(socketd); + const peer = Object.values(sock.peers)[0]; + + if (!peer) { + return -1; + } + + try { + peer.socket.close(); + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + return 0; + } catch (e) { + console.log('Socket shutdown error', e); + return -1; + } + }, + }; + function _js_create_input_device(deviceId) { + let dataBuffer = []; + let dataCallback; + const filename = 'proc_id_' + deviceId; + const device = FS.createDevice( + '/dev', + filename, + function () { }, + function (byte) { + try { + dataBuffer.push(byte); + if (dataCallback) { + dataCallback(new Uint8Array(dataBuffer)); + dataBuffer = []; + } + } catch (e) { + console.error(e); + throw e; + } + } + ); + + const devicePath = '/dev/' + filename; + PHPWASM.input_devices[deviceId] = { + devicePath: devicePath, + onData: function (cb) { + dataCallback = cb; + dataBuffer.forEach(function (data) { + cb(data); + }); + dataBuffer.length = 0; + }, + }; + return allocateUTF8OnStack(devicePath); + } + + function _js_fd_read(fd, iov, iovcnt, pnum) { + // Only run the read operation on a regular call, + // never when rewinding the stack. + if (Asyncify.state === Asyncify.State.Normal) { + var returnCode; + var stream; + let num = 0; + try { + stream = SYSCALLS.getStreamFromFD(fd); + const num = doReadv(stream, iov, iovcnt); + HEAPU32[pnum >> 2] = num; + return 0; + } catch (e) { + // Rethrow any unexpected non-filesystem errors. + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) { + throw e; + } + // Only return synchronously if this isn't an asynchronous pipe. + // Error code 6 indicates EWOULDBLOCK – this is our signal to wait. + // We also need to distinguish between a process pipe and a file pipe, otherwise + // reading from an empty file would block until the timeout. + if (e.errno !== 6 || !(stream?.fd in PHPWASM.child_proc_by_fd)) { + // On failure, yield 0 bytes read to indicate EOF. + HEAPU32[pnum >> 2] = 0; + return returnCode + } + } + } + + // At this point we know we have to poll. + // You might wonder why we duplicate the code here instead of always using + // Asyncify.handleSleep(). The reason is performance. Most of the time, + // the read operation will work synchronously and won't require yielding + // back to JS. In these cases we don't want to pay the Asyncify overhead, + // save the stack, yield back to JS, restore the stack etc. + return Asyncify.handleSleep(function (wakeUp) { + var retries = 0; + var interval = 50; + var timeout = 5000; + // We poll for data and give up after a timeout. + // We can't simply rely on PHP timeout here because we don't want + // to, say, block the entire PHPUnit test suite without any visible + // feedback. + var maxRetries = timeout / interval; + function poll() { + var returnCode; + var stream; + let num; + try { + stream = SYSCALLS.getStreamFromFD(fd); + num = doReadv(stream, iov, iovcnt); + returnCode = 0; + } catch (e) { + if ( + typeof FS == 'undefined' || + !(e.name === 'ErrnoError') + ) { + console.error(e); + throw e; + } + returnCode = e.errno; + } + + const success = returnCode === 0; + const failure = ( + ++retries > maxRetries || + !(fd in PHPWASM.child_proc_by_fd) || + PHPWASM.child_proc_by_fd[fd]?.exited || + FS.isClosed(stream) + ); + + if (success) { + HEAPU32[pnum >> 2] = num; + wakeUp(0); + } else if (failure) { + // On failure, yield 0 bytes read to indicate EOF. + HEAPU32[pnum >> 2] = 0; + // If the failure is due to a timeout, return 0 to indicate that we + // reached EOF. Otherwise, propagate the error code. + wakeUp(returnCode === 6 ? 0 : returnCode); + } else { + setTimeout(poll, interval); + } + } + poll(); + }); + } + + + function _js_module_onMessage(data, bufPtr) { + if (typeof Asyncify === 'undefined') { + return; + } + + if (Module['onMessage']) { + const dataStr = UTF8ToString(data); + + return Asyncify.handleSleep((wakeUp) => { + Module['onMessage'](dataStr) + .then((response) => { + const responseBytes = + typeof response === 'string' + ? new TextEncoder().encode(response) + : response; + + // Copy the response bytes to heap + const responseSize = responseBytes.byteLength; + const responsePtr = _malloc(responseSize + 1); + HEAPU8.set(responseBytes, responsePtr); + HEAPU8[responsePtr + responseSize] = 0; + HEAPU8[bufPtr] = responsePtr; + HEAPU8[bufPtr + 1] = responsePtr >> 8; + HEAPU8[bufPtr + 2] = responsePtr >> 16; + HEAPU8[bufPtr + 3] = responsePtr >> 24; + + wakeUp(responseSize); + }) + .catch((e) => { + // Log the error and return NULL. Message passing + // separates JS context from the PHP context so we + // don't let PHP crash here. + console.error(e); + wakeUp(-1); + }); + }); + } + } + + + function _js_open_process( + command, + argsPtr, + argsLength, + descriptorsPtr, + descriptorsLength, + cwdPtr, + cwdLength, + envPtr, + envLength + ) { + if (!command) { + return 1; + } + + const cmdstr = UTF8ToString(command); + if (!cmdstr.length) { + return 0; + } + + let argsArray = []; + if (argsLength) { + for (var i = 0; i < argsLength; i++) { + const charPointer = argsPtr + i * 4; + argsArray.push(UTF8ToString(HEAPU32[charPointer >> 2])); + } + } + + const cwdstr = cwdPtr ? UTF8ToString(cwdPtr) : null; + let envObject = null; + + if (envLength) { + envObject = {}; + for (var i = 0; i < envLength; i++) { + const envPointer = envPtr + i * 4; + const envEntry = UTF8ToString(HEAPU32[envPointer >> 2]); + const splitAt = envEntry.indexOf('='); + if (splitAt === -1) { + continue; + } + const key = envEntry.substring(0, splitAt); + const value = envEntry.substring(splitAt + 1); + envObject[key] = value; + } + } + + var std = {}; + // Extracts an array of available descriptors that should be dispatched to streams. + // On the C side, the descriptors are expressed as `**int` so we must go read + // each of the `descriptorsLength` `*int` pointers and convert the associated data into + // a JavaScript object { descriptor : { child : fd, parent : fd } }. + for (var i = 0; i < descriptorsLength; i++) { + const descriptorPtr = HEAPU32[(descriptorsPtr + i * 4) >> 2]; + std[HEAPU32[descriptorPtr >> 2]] = { + child: HEAPU32[(descriptorPtr + 4) >> 2], + parent: HEAPU32[(descriptorPtr + 8) >> 2], + }; + } + + return Asyncify.handleSleep(async (wakeUp) => { + let cp; + try { + const options = {}; + if (cwdstr !== null) { + options.cwd = cwdstr; + } + if (envObject !== null) { + options.env = envObject; + } + cp = PHPWASM.spawnProcess(cmdstr, argsArray, options); + if (cp instanceof Promise) { + cp = await cp; + } + } catch (e) { + if (e.code === 'SPAWN_UNSUPPORTED') { + wakeUp(1); + return; + } + console.error(e); + wakeUp(1); + throw e; + } + + const ProcInfo = { + pid: cp.pid, + exited: false, + stdinFd: std[0]?.child, + stdinIsDevice: std[0]?.child in PHPWASM.input_devices, + stdoutChildFd: std[1]?.child, + stdoutParentFd: std[1]?.parent, + stderrChildFd: std[2]?.child, + stderrParentFd: std[2]?.parent, + stdout: new PHPWASM.EventEmitter(), + stderr: new PHPWASM.EventEmitter(), + }; + if (ProcInfo.stdoutChildFd) + PHPWASM.child_proc_by_fd[ProcInfo.stdoutChildFd] = ProcInfo; + if (ProcInfo.stderrChildFd) + PHPWASM.child_proc_by_fd[ProcInfo.stderrChildFd] = ProcInfo; + if (ProcInfo.stdoutParentFd) + PHPWASM.child_proc_by_fd[ProcInfo.stdoutParentFd] = ProcInfo; + if (ProcInfo.stderrParentFd) + PHPWASM.child_proc_by_fd[ProcInfo.stderrParentFd] = ProcInfo; + PHPWASM.child_proc_by_pid[ProcInfo.pid] = ProcInfo; + + cp.on('exit', function (code) { + ProcInfo.exitCode = code; + ProcInfo.exited = true; + // Emit events for the wasm_poll_socket function. + ProcInfo.stdout.emit('data'); + ProcInfo.stderr.emit('data'); + }); + + // Pass data from child process's stdout to PHP's end of the stdout pipe. + if (ProcInfo.stdoutChildFd) { + const stdoutStream = SYSCALLS.getStreamFromFD( + ProcInfo.stdoutChildFd + ); + let stdoutAt = 0; + cp.stdout.on('data', function (data) { + ProcInfo.stdout.emit('data', data); + stdoutStream.stream_ops.write( + stdoutStream, + data, + 0, + data.length, + stdoutAt + ); + stdoutAt += data.length; + }); + } + + // Pass data from child process's stderr to PHP's end of the stdout pipe. + if (ProcInfo.stderrChildFd) { + const stderrStream = SYSCALLS.getStreamFromFD( + ProcInfo.stderrChildFd + ); + let stderrAt = 0; + cp.stderr.on('data', function (data) { + ProcInfo.stderr.emit('data', data); + stderrStream.stream_ops.write( + stderrStream, + data, + 0, + data.length, + stderrAt + ); + stderrAt += data.length; + }); + } + + /** + * Wait until the child process has been spawned. + * Unfortunately there is no Node.js API to check whether + * the process has already been spawned. We can only listen + * to the 'spawn' event and if it has already been spawned, + * listen to the 'exit' event. + */ + try { + await new Promise((resolve, reject) => { + cp.on('spawn', resolve); + cp.on('error', reject); + }); + } catch (e) { + console.error(e); + wakeUp(1); + return; + } + + // Now we want to pass data from the STDIN source supplied by PHP + // to the child process. + + // PHP will write STDIN data to a device. + if (ProcInfo.stdinIsDevice) { + // We use Emscripten devices as pipes. This is a bit of a hack + // but it works as we get a callback when the device is written to. + // Let's listen to anything it outputs and pass it to the child process. + PHPWASM.input_devices[ProcInfo.stdinFd].onData(function (data) { + if (!data) return; + const dataStr = new TextDecoder('utf-8').decode(data); + cp.stdin.write(dataStr); + }); + wakeUp(ProcInfo.pid); + return; + } + + if (ProcInfo.stdinFd) { + // PHP will write STDIN data to a file descriptor. + const stdinStream = SYSCALLS.getStreamFromFD(ProcInfo.stdinFd); + if (stdinStream.node) { + // Pipe the entire stdinStream to cp.stdin + const CHUNK_SIZE = 1024; + const buffer = new Uint8Array(CHUNK_SIZE); + let offset = 0; + + while (true) { + const bytesRead = stdinStream.stream_ops.read( + stdinStream, + buffer, + 0, + CHUNK_SIZE, + offset + ); + if (bytesRead === null || bytesRead === 0) { + break; + } + try { + cp.stdin.write(buffer.subarray(0, bytesRead)); + } catch (e) { + console.error(e); + return 1; + } + if (bytesRead < CHUNK_SIZE) { + break; + } + offset += bytesRead; + } + + wakeUp(ProcInfo.pid); + return; + } + } + + wakeUp(ProcInfo.pid); + }); + } + + + function _js_popen_to_file(command, mode, exitCodePtr) { + // Parse args + if (!command) return 1; // shell is available + + const cmdstr = UTF8ToString(command); + if (!cmdstr.length) return 0; // this is what glibc seems to do (shell works test?) + + const modestr = UTF8ToString(mode); + if (!modestr.length) return 0; // this is what glibc seems to do (shell works test?) + if (modestr === 'w') { + console.error('popen($cmd, "w") is not implemented yet'); + } + + return Asyncify.handleSleep(async (wakeUp) => { + let cp; + try { + cp = PHPWASM.spawnProcess(cmdstr, []); + if (cp instanceof Promise) { + cp = await cp; + } + } catch (e) { + console.error(e); + if (e.code === 'SPAWN_UNSUPPORTED') { + return 1; + } + throw e; + } + + const outByteArrays = []; + cp.stdout.on('data', function (data) { + outByteArrays.push(data); + }); + + const outputPath = '/tmp/popen_output'; + cp.on('exit', function (exitCode) { + // Concat outByteArrays, an array of UInt8Arrays + // into a single Uint8Array. + const outBytes = new Uint8Array( + outByteArrays.reduce((acc, curr) => acc + curr.length, 0) + ); + let offset = 0; + for (const byteArray of outByteArrays) { + outBytes.set(byteArray, offset); + offset += byteArray.length; + } + + FS.writeFile(outputPath, outBytes); + + HEAPU8[exitCodePtr] = exitCode; + wakeUp(allocateUTF8OnStack(outputPath)); // 2 is SIGINT + }); + }); + } + + function _js_process_status(pid, exitCodePtr) { + if (!PHPWASM.child_proc_by_pid[pid]) { + return -1; + } + if (PHPWASM.child_proc_by_pid[pid].exited) { + HEAPU32[exitCodePtr >> 2] = + PHPWASM.child_proc_by_pid[pid].exitCode; + return 1; + } + return 0; + } + + function _js_waitpid(pid, exitCodePtr) { + if (!PHPWASM.child_proc_by_pid[pid]) { + return -1; + } + return Asyncify.handleSleep((wakeUp) => { + const poll = function () { + if (PHPWASM.child_proc_by_pid[pid]?.exited) { + HEAPU32[exitCodePtr >> 2] = + PHPWASM.child_proc_by_pid[pid].exitCode; + wakeUp(pid); + } else { + setTimeout(poll, 50); + } + }; + poll(); + }); + } + + + + var arraySum = (array, index) => { + var sum = 0; + for (var i = 0; i <= index; sum += array[i++]) { + // no-op + } + return sum; + }; + + + var MONTH_DAYS_LEAP = [31,29,31,30,31,30,31,31,30,31,30,31]; + + var MONTH_DAYS_REGULAR = [31,28,31,30,31,30,31,31,30,31,30,31]; + var addDays = (date, days) => { + var newDate = new Date(date.getTime()); + while (days > 0) { + var leap = isLeapYear(newDate.getFullYear()); + var currentMonth = newDate.getMonth(); + var daysInCurrentMonth = (leap ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR)[currentMonth]; + + if (days > daysInCurrentMonth-newDate.getDate()) { + // we spill over to next month + days -= (daysInCurrentMonth-newDate.getDate()+1); + newDate.setDate(1); + if (currentMonth < 11) { + newDate.setMonth(currentMonth+1) + } else { + newDate.setMonth(0); + newDate.setFullYear(newDate.getFullYear()+1); + } + } else { + // we stay in current month + newDate.setDate(newDate.getDate()+days); + return newDate; + } + } + + return newDate; + }; + + + + + var writeArrayToMemory = (array, buffer) => { + HEAP8.set(array, buffer); + }; + + var _strftime = (s, maxsize, format, tm) => { + // size_t strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct tm *restrict timeptr); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html + + var tm_zone = HEAP32[(((tm)+(40))>>2)]; + + var date = { + tm_sec: HEAP32[((tm)>>2)], + tm_min: HEAP32[(((tm)+(4))>>2)], + tm_hour: HEAP32[(((tm)+(8))>>2)], + tm_mday: HEAP32[(((tm)+(12))>>2)], + tm_mon: HEAP32[(((tm)+(16))>>2)], + tm_year: HEAP32[(((tm)+(20))>>2)], + tm_wday: HEAP32[(((tm)+(24))>>2)], + tm_yday: HEAP32[(((tm)+(28))>>2)], + tm_isdst: HEAP32[(((tm)+(32))>>2)], + tm_gmtoff: HEAP32[(((tm)+(36))>>2)], + tm_zone: tm_zone ? UTF8ToString(tm_zone) : '' + }; + + var pattern = UTF8ToString(format); + + // expand format + var EXPANSION_RULES_1 = { + '%c': '%a %b %d %H:%M:%S %Y', // Replaced by the locale's appropriate date and time representation - e.g., Mon Aug 3 14:02:01 2013 + '%D': '%m/%d/%y', // Equivalent to %m / %d / %y + '%F': '%Y-%m-%d', // Equivalent to %Y - %m - %d + '%h': '%b', // Equivalent to %b + '%r': '%I:%M:%S %p', // Replaced by the time in a.m. and p.m. notation + '%R': '%H:%M', // Replaced by the time in 24-hour notation + '%T': '%H:%M:%S', // Replaced by the time + '%x': '%m/%d/%y', // Replaced by the locale's appropriate date representation + '%X': '%H:%M:%S', // Replaced by the locale's appropriate time representation + // Modified Conversion Specifiers + '%Ec': '%c', // Replaced by the locale's alternative appropriate date and time representation. + '%EC': '%C', // Replaced by the name of the base year (period) in the locale's alternative representation. + '%Ex': '%m/%d/%y', // Replaced by the locale's alternative date representation. + '%EX': '%H:%M:%S', // Replaced by the locale's alternative time representation. + '%Ey': '%y', // Replaced by the offset from %EC (year only) in the locale's alternative representation. + '%EY': '%Y', // Replaced by the full alternative year representation. + '%Od': '%d', // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading zeros if there is any alternative symbol for zero; otherwise, with leading characters. + '%Oe': '%e', // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading characters. + '%OH': '%H', // Replaced by the hour (24-hour clock) using the locale's alternative numeric symbols. + '%OI': '%I', // Replaced by the hour (12-hour clock) using the locale's alternative numeric symbols. + '%Om': '%m', // Replaced by the month using the locale's alternative numeric symbols. + '%OM': '%M', // Replaced by the minutes using the locale's alternative numeric symbols. + '%OS': '%S', // Replaced by the seconds using the locale's alternative numeric symbols. + '%Ou': '%u', // Replaced by the weekday as a number in the locale's alternative representation (Monday=1). + '%OU': '%U', // Replaced by the week number of the year (Sunday as the first day of the week, rules corresponding to %U ) using the locale's alternative numeric symbols. + '%OV': '%V', // Replaced by the week number of the year (Monday as the first day of the week, rules corresponding to %V ) using the locale's alternative numeric symbols. + '%Ow': '%w', // Replaced by the number of the weekday (Sunday=0) using the locale's alternative numeric symbols. + '%OW': '%W', // Replaced by the week number of the year (Monday as the first day of the week) using the locale's alternative numeric symbols. + '%Oy': '%y', // Replaced by the year (offset from %C ) using the locale's alternative numeric symbols. + }; + for (var rule in EXPANSION_RULES_1) { + pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_1[rule]); + } + + var WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; + var MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + + function leadingSomething(value, digits, character) { + var str = typeof value == 'number' ? value.toString() : (value || ''); + while (str.length < digits) { + str = character[0]+str; + } + return str; + } + + function leadingNulls(value, digits) { + return leadingSomething(value, digits, '0'); + } + + function compareByDay(date1, date2) { + function sgn(value) { + return value < 0 ? -1 : (value > 0 ? 1 : 0); + } + + var compare; + if ((compare = sgn(date1.getFullYear()-date2.getFullYear())) === 0) { + if ((compare = sgn(date1.getMonth()-date2.getMonth())) === 0) { + compare = sgn(date1.getDate()-date2.getDate()); + } + } + return compare; + } + + function getFirstWeekStartDate(janFourth) { + switch (janFourth.getDay()) { + case 0: // Sunday + return new Date(janFourth.getFullYear()-1, 11, 29); + case 1: // Monday + return janFourth; + case 2: // Tuesday + return new Date(janFourth.getFullYear(), 0, 3); + case 3: // Wednesday + return new Date(janFourth.getFullYear(), 0, 2); + case 4: // Thursday + return new Date(janFourth.getFullYear(), 0, 1); + case 5: // Friday + return new Date(janFourth.getFullYear()-1, 11, 31); + case 6: // Saturday + return new Date(janFourth.getFullYear()-1, 11, 30); + } + } + + function getWeekBasedYear(date) { + var thisDate = addDays(new Date(date.tm_year+1900, 0, 1), date.tm_yday); + + var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4); + var janFourthNextYear = new Date(thisDate.getFullYear()+1, 0, 4); + + var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear); + var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear); + + if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) { + // this date is after the start of the first week of this year + if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) { + return thisDate.getFullYear()+1; + } + return thisDate.getFullYear(); + } + return thisDate.getFullYear()-1; + } + + var EXPANSION_RULES_2 = { + '%a': (date) => WEEKDAYS[date.tm_wday].substring(0,3) , + '%A': (date) => WEEKDAYS[date.tm_wday], + '%b': (date) => MONTHS[date.tm_mon].substring(0,3), + '%B': (date) => MONTHS[date.tm_mon], + '%C': (date) => { + var year = date.tm_year+1900; + return leadingNulls((year/100)|0,2); + }, + '%d': (date) => leadingNulls(date.tm_mday, 2), + '%e': (date) => leadingSomething(date.tm_mday, 2, ' '), + '%g': (date) => { + // %g, %G, and %V give values according to the ISO 8601:2000 standard week-based year. + // In this system, weeks begin on a Monday and week 1 of the year is the week that includes + // January 4th, which is also the week that includes the first Thursday of the year, and + // is also the first week that contains at least four days in the year. + // If the first Monday of January is the 2nd, 3rd, or 4th, the preceding days are part of + // the last week of the preceding year; thus, for Saturday 2nd January 1999, + // %G is replaced by 1998 and %V is replaced by 53. If December 29th, 30th, + // or 31st is a Monday, it and any following days are part of week 1 of the following year. + // Thus, for Tuesday 30th December 1997, %G is replaced by 1998 and %V is replaced by 01. + + return getWeekBasedYear(date).toString().substring(2); + }, + '%G': (date) => getWeekBasedYear(date), + '%H': (date) => leadingNulls(date.tm_hour, 2), + '%I': (date) => { + var twelveHour = date.tm_hour; + if (twelveHour == 0) twelveHour = 12; + else if (twelveHour > 12) twelveHour -= 12; + return leadingNulls(twelveHour, 2); + }, + '%j': (date) => { + // Day of the year (001-366) + return leadingNulls(date.tm_mday + arraySum(isLeapYear(date.tm_year+1900) ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, date.tm_mon-1), 3); + }, + '%m': (date) => leadingNulls(date.tm_mon+1, 2), + '%M': (date) => leadingNulls(date.tm_min, 2), + '%n': () => '\n', + '%p': (date) => { + if (date.tm_hour >= 0 && date.tm_hour < 12) { + return 'AM'; + } + return 'PM'; + }, + '%S': (date) => leadingNulls(date.tm_sec, 2), + '%t': () => '\t', + '%u': (date) => date.tm_wday || 7, + '%U': (date) => { + var days = date.tm_yday + 7 - date.tm_wday; + return leadingNulls(Math.floor(days / 7), 2); + }, + '%V': (date) => { + // Replaced by the week number of the year (Monday as the first day of the week) + // as a decimal number [01,53]. If the week containing 1 January has four + // or more days in the new year, then it is considered week 1. + // Otherwise, it is the last week of the previous year, and the next week is week 1. + // Both January 4th and the first Thursday of January are always in week 1. [ tm_year, tm_wday, tm_yday] + var val = Math.floor((date.tm_yday + 7 - (date.tm_wday + 6) % 7 ) / 7); + // If 1 Jan is just 1-3 days past Monday, the previous week + // is also in this year. + if ((date.tm_wday + 371 - date.tm_yday - 2) % 7 <= 2) { + val++; + } + if (!val) { + val = 52; + // If 31 December of prev year a Thursday, or Friday of a + // leap year, then the prev year has 53 weeks. + var dec31 = (date.tm_wday + 7 - date.tm_yday - 1) % 7; + if (dec31 == 4 || (dec31 == 5 && isLeapYear(date.tm_year%400-1))) { + val++; + } + } else if (val == 53) { + // If 1 January is not a Thursday, and not a Wednesday of a + // leap year, then this year has only 52 weeks. + var jan1 = (date.tm_wday + 371 - date.tm_yday) % 7; + if (jan1 != 4 && (jan1 != 3 || !isLeapYear(date.tm_year))) + val = 1; + } + return leadingNulls(val, 2); + }, + '%w': (date) => date.tm_wday, + '%W': (date) => { + var days = date.tm_yday + 7 - ((date.tm_wday + 6) % 7); + return leadingNulls(Math.floor(days / 7), 2); + }, + '%y': (date) => { + // Replaced by the last two digits of the year as a decimal number [00,99]. [ tm_year] + return (date.tm_year+1900).toString().substring(2); + }, + // Replaced by the year as a decimal number (for example, 1997). [ tm_year] + '%Y': (date) => date.tm_year+1900, + '%z': (date) => { + // Replaced by the offset from UTC in the ISO 8601:2000 standard format ( +hhmm or -hhmm ). + // For example, "-0430" means 4 hours 30 minutes behind UTC (west of Greenwich). + var off = date.tm_gmtoff; + var ahead = off >= 0; + off = Math.abs(off) / 60; + // convert from minutes into hhmm format (which means 60 minutes = 100 units) + off = (off / 60)*100 + (off % 60); + return (ahead ? '+' : '-') + String("0000" + off).slice(-4); + }, + '%Z': (date) => date.tm_zone, + '%%': () => '%' + }; + + // Replace %% with a pair of NULLs (which cannot occur in a C string), then + // re-inject them after processing. + pattern = pattern.replace(/%%/g, '\0\0') + for (var rule in EXPANSION_RULES_2) { + if (pattern.includes(rule)) { + pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_2[rule](date)); + } + } + pattern = pattern.replace(/\0\0/g, '%') + + var bytes = intArrayFromString(pattern, false); + if (bytes.length > maxsize) { + return 0; + } + + writeArrayToMemory(bytes, s); + return bytes.length-1; + }; -var _getprotobynumber = number => { - _setprotoent(true); - var result = Protocols.map[number]; - return result; -}; + + + + + + + + var _strptime = (buf, format, tm) => { + // char *strptime(const char *restrict buf, const char *restrict format, struct tm *restrict tm); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/strptime.html + var pattern = UTF8ToString(format); + + // escape special characters + // TODO: not sure we really need to escape all of these in JS regexps + var SPECIAL_CHARS = '\\!@#$^&*()+=-[]/{}|:<>?,.'; + for (var i=0, ii=SPECIAL_CHARS.length; i=0; i=pattern.indexOf('%')) { + capture.push(pattern[i+1]); + pattern = pattern.replace(new RegExp('\\%'+pattern[i+1], 'g'), ''); + } + + var matches = new RegExp('^'+pattern, "i").exec(UTF8ToString(buf)) + // out(UTF8ToString(buf)+ ' is matched by '+((new RegExp('^'+pattern)).source)+' into: '+JSON.stringify(matches)); + + function initDate() { + function fixup(value, min, max) { + return (typeof value != 'number' || isNaN(value)) ? min : (value>=min ? (value<=max ? value: max): min); + }; + return { + year: fixup(HEAP32[(((tm)+(20))>>2)] + 1900 , 1970, 9999), + month: fixup(HEAP32[(((tm)+(16))>>2)], 0, 11), + day: fixup(HEAP32[(((tm)+(12))>>2)], 1, 31), + hour: fixup(HEAP32[(((tm)+(8))>>2)], 0, 23), + min: fixup(HEAP32[(((tm)+(4))>>2)], 0, 59), + sec: fixup(HEAP32[((tm)>>2)], 0, 59) + }; + }; + + if (matches) { + var date = initDate(); + var value; + + var getMatch = (symbol) => { + var pos = capture.indexOf(symbol); + // check if symbol appears in regexp + if (pos >= 0) { + // return matched value or null (falsy!) for non-matches + return matches[pos+1]; + } + return; + }; + + // seconds + if ((value=getMatch('S'))) { + date.sec = jstoi_q(value); + } + + // minutes + if ((value=getMatch('M'))) { + date.min = jstoi_q(value); + } + + // hours + if ((value=getMatch('H'))) { + // 24h clock + date.hour = jstoi_q(value); + } else if ((value = getMatch('I'))) { + // AM/PM clock + var hour = jstoi_q(value); + if ((value=getMatch('p'))) { + hour += value.toUpperCase()[0] === 'P' ? 12 : 0; + } + date.hour = hour; + } + + // year + if ((value=getMatch('Y'))) { + // parse from four-digit year + date.year = jstoi_q(value); + } else if ((value=getMatch('y'))) { + // parse from two-digit year... + var year = jstoi_q(value); + if ((value=getMatch('C'))) { + // ...and century + year += jstoi_q(value)*100; + } else { + // ...and rule-of-thumb + year += year<69 ? 2000 : 1900; + } + date.year = year; + } + + // month + if ((value=getMatch('m'))) { + // parse from month number + date.month = jstoi_q(value)-1; + } else if ((value=getMatch('b'))) { + // parse from month name + date.month = MONTH_NUMBERS[value.substring(0,3).toUpperCase()] || 0; + // TODO: derive month from day in year+year, week number+day of week+year + } + + // day + if ((value=getMatch('d'))) { + // get day of month directly + date.day = jstoi_q(value); + } else if ((value=getMatch('j'))) { + // get day of month from day of year ... + var day = jstoi_q(value); + var leapYear = isLeapYear(date.year); + for (var month=0; month<12; ++month) { + var daysUntilMonth = arraySum(leapYear ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, month-1); + if (day<=daysUntilMonth+(leapYear ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR)[month]) { + date.day = day-daysUntilMonth; + } + } + } else if ((value=getMatch('a'))) { + // get day of month from weekday ... + var weekDay = value.substring(0,3).toUpperCase(); + if ((value=getMatch('U'))) { + // ... and week number (Sunday being first day of week) + // Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. + // All days in a new year preceding the first Sunday are considered to be in week 0. + var weekDayNumber = DAY_NUMBERS_SUN_FIRST[weekDay]; + var weekNumber = jstoi_q(value); + + // January 1st + var janFirst = new Date(date.year, 0, 1); + var endDate; + if (janFirst.getDay() === 0) { + // Jan 1st is a Sunday, and, hence in the 1st CW + endDate = addDays(janFirst, weekDayNumber+7*(weekNumber-1)); + } else { + // Jan 1st is not a Sunday, and, hence still in the 0th CW + endDate = addDays(janFirst, 7-janFirst.getDay()+weekDayNumber+7*(weekNumber-1)); + } + date.day = endDate.getDate(); + date.month = endDate.getMonth(); + } else if ((value=getMatch('W'))) { + // ... and week number (Monday being first day of week) + // Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. + // All days in a new year preceding the first Monday are considered to be in week 0. + var weekDayNumber = DAY_NUMBERS_MON_FIRST[weekDay]; + var weekNumber = jstoi_q(value); + + // January 1st + var janFirst = new Date(date.year, 0, 1); + var endDate; + if (janFirst.getDay()===1) { + // Jan 1st is a Monday, and, hence in the 1st CW + endDate = addDays(janFirst, weekDayNumber+7*(weekNumber-1)); + } else { + // Jan 1st is not a Monday, and, hence still in the 0th CW + endDate = addDays(janFirst, 7-janFirst.getDay()+1+weekDayNumber+7*(weekNumber-1)); + } + + date.day = endDate.getDate(); + date.month = endDate.getMonth(); + } + } + + /* + tm_sec int seconds after the minute 0-61* + tm_min int minutes after the hour 0-59 + tm_hour int hours since midnight 0-23 + tm_mday int day of the month 1-31 + tm_mon int months since January 0-11 + tm_year int years since 1900 + tm_wday int days since Sunday 0-6 + tm_yday int days since January 1 0-365 + tm_isdst int Daylight Saving Time flag + */ + + var fullDate = new Date(date.year, date.month, date.day, date.hour, date.min, date.sec, 0); + HEAP32[((tm)>>2)] = fullDate.getSeconds(); + HEAP32[(((tm)+(4))>>2)] = fullDate.getMinutes(); + HEAP32[(((tm)+(8))>>2)] = fullDate.getHours(); + HEAP32[(((tm)+(12))>>2)] = fullDate.getDate(); + HEAP32[(((tm)+(16))>>2)] = fullDate.getMonth(); + HEAP32[(((tm)+(20))>>2)] = fullDate.getFullYear()-1900; + HEAP32[(((tm)+(24))>>2)] = fullDate.getDay(); + HEAP32[(((tm)+(28))>>2)] = arraySum(isLeapYear(fullDate.getFullYear()) ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, fullDate.getMonth()-1)+fullDate.getDate()-1; + HEAP32[(((tm)+(32))>>2)] = 0; + + // we need to convert the matched sequence into an integer array to take care of UTF-8 characters > 0x7F + // TODO: not sure that intArrayFromString handles all unicode characters correctly + return buf+intArrayFromString(matches[0]).length-1; + } + + return 0; + }; -var stringToUTF8OnStack = str => { - var size = lengthBytesUTF8(str) + 1; - var ret = stackAlloc(size); - stringToUTF8(str, ret, size); - return ret; -}; + function _wasm_close(socketd) { + return PHPWASM.shutdownSocket(socketd, 2); + } + + function _wasm_poll_socket(socketd, events, timeout) { + if (typeof Asyncify === 'undefined') { + return 0; + } + + const POLLIN = 0x0001; /* There is data to read */ + const POLLPRI = 0x0002; /* There is urgent data to read */ + const POLLOUT = 0x0004; /* Writing now will not block */ + const POLLERR = 0x0008; /* Error condition */ + const POLLHUP = 0x0010; /* Hung up */ + const POLLNVAL = 0x0020; /* Invalid request: fd not open */ + + console.trace(); + process.exit(0); + return Asyncify.handleSleep((wakeUp) => { + const polls = []; + if (socketd in PHPWASM.child_proc_by_fd) { + // This is a child process-related socket. + const procInfo = PHPWASM.child_proc_by_fd[socketd]; + if (procInfo.exited) { + wakeUp(0); + return; + } + polls.push(PHPWASM.awaitEvent(procInfo.stdout, 'data')); + } else { + // This is, most likely, a websocket. Let's make sure. + const sock = getSocketFromFD(socketd); + if (!sock) { + wakeUp(0); + return; + } + const lookingFor = new Set(); + + if (events & POLLIN || events & POLLPRI) { + if (sock.server) { + for (const client of sock.pending) { + if ((client.recv_queue || []).length > 0) { + wakeUp(1); + return; + } + } + } else if ((sock.recv_queue || []).length > 0) { + wakeUp(1); + return; + } + } + + const webSockets = PHPWASM.getAllWebSockets(sock); + if (!webSockets.length) { + wakeUp(0); + return; + } + for (const ws of webSockets) { + if (events & POLLIN || events & POLLPRI) { + polls.push(PHPWASM.awaitData(ws)); + lookingFor.add('POLLIN'); + } + if (events & POLLOUT) { + polls.push(PHPWASM.awaitConnection(ws)); + lookingFor.add('POLLOUT'); + } + if (events & POLLHUP) { + polls.push(PHPWASM.awaitClose(ws)); + lookingFor.add('POLLHUP'); + } + if (events & POLLERR || events & POLLNVAL) { + polls.push(PHPWASM.awaitError(ws)); + lookingFor.add('POLLERR'); + } + } + } + if (polls.length === 0) { + console.warn( + 'Unsupported poll event ' + + events + + ', defaulting to setTimeout().' + ); + setTimeout(function () { + wakeUp(0); + }, timeout); + return; + } + + const promises = polls.map(([promise]) => promise); + const clearPolling = () => polls.forEach(([, clear]) => clear()); + let awaken = false; + let timeoutId; + Promise.race(promises).then(function (results) { + if (!awaken) { + awaken = true; + wakeUp(1); + if (timeoutId) { + clearTimeout(timeoutId); + } + clearPolling(); + } + }); + + if (timeout !== -1) { + timeoutId = setTimeout(function () { + if (!awaken) { + awaken = true; + wakeUp(0); + clearPolling(); + } + }, timeout); + } + }); + } + + function _wasm_setsockopt( + socketd, + level, + optionName, + optionValuePtr, + optionLen + ) { + const optionValue = HEAPU8[optionValuePtr]; + const SOL_SOCKET = 1; + const SO_KEEPALIVE = 9; + const IPPROTO_TCP = 6; + const TCP_NODELAY = 1; + const isSupported = + (level === SOL_SOCKET && optionName === SO_KEEPALIVE) || + (level === IPPROTO_TCP && optionName === TCP_NODELAY); + if (!isSupported) { + console.warn( + `Unsupported socket option: ${level}, ${optionName}, ${optionValue}` + ); + return -1; + } + const ws = PHPWASM.getAllWebSockets(socketd)[0]; + if (!ws) { + return -1; + } + ws.setSocketOpt(level, optionName, optionValuePtr); + return 0; + } + + function _wasm_shutdown(socketd, how) { + return PHPWASM.shutdownSocket(socketd, how); + } + + var wasmTableMirror = []; + var getWasmTableEntry = (funcPtr) => { + var func = wasmTableMirror[funcPtr]; + if (!func) { + if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1; + wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr); + } + return func; + }; -var allocateUTF8OnStack = stringToUTF8OnStack; -var PHPWASM = { - init: function() { - FS.mkdir("/internal"); - PHPWASM.EventEmitter = ENVIRONMENT_IS_NODE ? require("events").EventEmitter : class EventEmitter { - constructor() { - this.listeners = {}; - } - emit(eventName, data) { - if (this.listeners[eventName]) { - this.listeners[eventName].forEach((callback => { - callback(data); - })); - } - } - once(eventName, callback) { - const self = this; - function removedCallback() { - callback(...arguments); - self.removeListener(eventName, removedCallback); - } - this.on(eventName, removedCallback); - } - removeAllListeners(eventName) { - if (eventName) { - delete this.listeners[eventName]; - } else { - this.listeners = {}; - } - } - removeListener(eventName, callback) { - if (this.listeners[eventName]) { - const idx = this.listeners[eventName].indexOf(callback); - if (idx !== -1) { - this.listeners[eventName].splice(idx, 1); - } + function runAndAbortIfError(func) { + try { + return func(); + } catch (e) { + abort(e); + } } - } - }; - PHPWASM.child_proc_by_fd = {}; - PHPWASM.child_proc_by_pid = {}; - PHPWASM.input_devices = {}; - }, - getAllWebSockets: function(sock) { - const webSockets = new Set; - if (sock.server) { - sock.server.clients.forEach((ws => { - webSockets.add(ws); - })); - } - for (const peer of PHPWASM.getAllPeers(sock)) { - webSockets.add(peer.socket); - } - return Array.from(webSockets); - }, - getAllPeers: function(sock) { - const peers = new Set; - if (sock.server) { - sock.pending.filter((pending => pending.peers)).forEach((pending => { - for (const peer of Object.values(pending.peers)) { - peers.add(peer); + + + function sigToWasmTypes(sig) { + var typeNames = { + 'i': 'i32', + 'j': 'i64', + 'f': 'f32', + 'd': 'f64', + 'p': 'i32', + }; + var type = { + parameters: [], + results: sig[0] == 'v' ? [] : [typeNames[sig[0]]] + }; + for (var i = 1; i < sig.length; ++i) { + type.parameters.push(typeNames[sig[i]]); + } + return type; } - })); - } - if (sock.peers) { - for (const peer of Object.values(sock.peers)) { - peers.add(peer); - } - } - return Array.from(peers); - }, - awaitData: function(ws) { - return PHPWASM.awaitEvent(ws, "message"); - }, - awaitConnection: function(ws) { - if (ws.OPEN === ws.readyState) { - return [ Promise.resolve(), PHPWASM.noop ]; - } - return PHPWASM.awaitEvent(ws, "open"); - }, - awaitClose: function(ws) { - if ([ ws.CLOSING, ws.CLOSED ].includes(ws.readyState)) { - return [ Promise.resolve(), PHPWASM.noop ]; - } - return PHPWASM.awaitEvent(ws, "close"); - }, - awaitError: function(ws) { - if ([ ws.CLOSING, ws.CLOSED ].includes(ws.readyState)) { - return [ Promise.resolve(), PHPWASM.noop ]; - } - return PHPWASM.awaitEvent(ws, "error"); - }, - awaitEvent: function(ws, event) { - let resolve; - const listener = () => { - resolve(); - }; - const promise = new Promise((function(_resolve) { - resolve = _resolve; - ws.once(event, listener); - })); - const cancel = () => { - ws.removeListener(event, listener); - setTimeout(resolve); + + + + + + + var Asyncify = { + instrumentWasmImports:function(imports) { + var importPatterns = [/^_dlopen_js$/,/^invoke_i$/,/^invoke_ii$/,/^invoke_iii$/,/^invoke_iiii$/,/^invoke_iiiii$/,/^invoke_iiiiii$/,/^invoke_iiiiiii$/,/^invoke_iiiiiiii$/,/^invoke_iiiiiiiiii$/,/^invoke_v$/,/^invoke_vi$/,/^invoke_vii$/,/^invoke_viidii$/,/^invoke_viii$/,/^invoke_viiii$/,/^invoke_viiiii$/,/^invoke_viiiiii$/,/^invoke_viiiiiii$/,/^invoke_viiiiiiiii$/,/^js_open_process$/,/^js_popen_to_file$/,/^js_fd_read$/,/^js_module_onMessage$/,/^js_waitpid$/,/^wasm_poll_socket$/,/^wasm_shutdown$/,/^fd_sync$/,/^__wasi_fd_sync$/,/^__asyncjs__.*$/,/^emscripten_promise_await$/,/^emscripten_idb_load$/,/^emscripten_idb_store$/,/^emscripten_idb_delete$/,/^emscripten_idb_exists$/,/^emscripten_idb_load_blob$/,/^emscripten_idb_store_blob$/,/^emscripten_sleep$/,/^emscripten_wget_data$/,/^emscripten_scan_registers$/,/^emscripten_lazy_load_code$/,/^_load_secondary_module$/,/^emscripten_fiber_swap$/,/^SDL_Delay$/]; + + for (var x in imports) { + (function(x) { + var original = imports[x]; + var sig = original.sig; + if (typeof original == 'function') { + var isAsyncifyImport = original.isAsync || + importPatterns.some(pattern => !!x.match(pattern)); + } + })(x); + } + }, + instrumentWasmExports:function(exports) { + var ret = {}; + for (var x in exports) { + (function(x) { + var original = exports[x]; + if (typeof original == 'function') { + ret[x] = function() { + Asyncify.exportCallStack.push(x); + try { + return original.apply(null, arguments); + } finally { + if (!ABORT) { + var y = Asyncify.exportCallStack.pop(); + assert(y === x); + Asyncify.maybeStopUnwind(); + } + } + }; + } else { + ret[x] = original; + } + })(x); + } + return ret; + }, + State:{ + Normal:0, + Unwinding:1, + Rewinding:2, + Disabled:3, + }, + state:0, + StackSize:4096, + currData:null, + handleSleepReturnValue:0, + exportCallStack:[], + callStackNameToId:{ + }, + callStackIdToName:{ + }, + callStackId:0, + asyncPromiseHandlers:null, + sleepCallbacks:[], + getCallStackId:function(funcName) { + var id = Asyncify.callStackNameToId[funcName]; + if (id === undefined) { + id = Asyncify.callStackId++; + Asyncify.callStackNameToId[funcName] = id; + Asyncify.callStackIdToName[id] = funcName; + } + return id; + }, + maybeStopUnwind:function() { + if (Asyncify.currData && + Asyncify.state === Asyncify.State.Unwinding && + Asyncify.exportCallStack.length === 0) { + // We just finished unwinding. + // Be sure to set the state before calling any other functions to avoid + // possible infinite recursion here (For example in debug pthread builds + // the dbg() function itself can call back into WebAssembly to get the + // current pthread_self() pointer). + Asyncify.state = Asyncify.State.Normal; + runtimeKeepalivePush(); + // Keep the runtime alive so that a re-wind can be done later. + runAndAbortIfError(_asyncify_stop_unwind); + if (typeof Fibers != 'undefined') { + Fibers.trampoline(); + } + } + }, + whenDone:function() { + return new Promise((resolve, reject) => { + Asyncify.asyncPromiseHandlers = { resolve, reject }; + }); + }, + allocateData:function() { + // An asyncify data structure has three fields: + // 0 current stack pos + // 4 max stack pos + // 8 id of function at bottom of the call stack (callStackIdToName[id] == name of js function) + // + // The Asyncify ABI only interprets the first two fields, the rest is for the runtime. + // We also embed a stack in the same memory region here, right next to the structure. + // This struct is also defined as asyncify_data_t in emscripten/fiber.h + var ptr = _malloc(12 + Asyncify.StackSize); + Asyncify.setDataHeader(ptr, ptr + 12, Asyncify.StackSize); + Asyncify.setDataRewindFunc(ptr); + return ptr; + }, + setDataHeader:function(ptr, stack, stackSize) { + HEAP32[((ptr)>>2)] = stack; + HEAP32[(((ptr)+(4))>>2)] = stack + stackSize; + }, + setDataRewindFunc:function(ptr) { + var bottomOfCallStack = Asyncify.exportCallStack[0]; + var rewindId = Asyncify.getCallStackId(bottomOfCallStack); + HEAP32[(((ptr)+(8))>>2)] = rewindId; + }, + getDataRewindFunc:function(ptr) { + var id = HEAP32[(((ptr)+(8))>>2)]; + var name = Asyncify.callStackIdToName[id]; + var func = Module['asm'][name]; + return func; + }, + doRewind:function(ptr) { + var start = Asyncify.getDataRewindFunc(ptr); + // Once we have rewound and the stack we no longer need to artificially + // keep the runtime alive. + runtimeKeepalivePop(); + return start(); + }, + handleSleep:function(startAsync) { + if (ABORT) return; + if (Asyncify.state === Asyncify.State.Normal) { + // Prepare to sleep. Call startAsync, and see what happens: + // if the code decided to call our callback synchronously, + // then no async operation was in fact begun, and we don't + // need to do anything. + var reachedCallback = false; + var reachedAfterCallback = false; + startAsync((handleSleepReturnValue = 0) => { + if (ABORT) return; + Asyncify.handleSleepReturnValue = handleSleepReturnValue; + reachedCallback = true; + if (!reachedAfterCallback) { + // We are happening synchronously, so no need for async. + return; + } + Asyncify.state = Asyncify.State.Rewinding; + runAndAbortIfError(() => _asyncify_start_rewind(Asyncify.currData)); + if (typeof Browser != 'undefined' && Browser.mainLoop.func) { + Browser.mainLoop.resume(); + } + var asyncWasmReturnValue, isError = false; + try { + asyncWasmReturnValue = Asyncify.doRewind(Asyncify.currData); + } catch (err) { + asyncWasmReturnValue = err; + isError = true; + } + // Track whether the return value was handled by any promise handlers. + var handled = false; + if (!Asyncify.currData) { + // All asynchronous execution has finished. + // `asyncWasmReturnValue` now contains the final + // return value of the exported async WASM function. + // + // Note: `asyncWasmReturnValue` is distinct from + // `Asyncify.handleSleepReturnValue`. + // `Asyncify.handleSleepReturnValue` contains the return + // value of the last C function to have executed + // `Asyncify.handleSleep()`, where as `asyncWasmReturnValue` + // contains the return value of the exported WASM function + // that may have called C functions that + // call `Asyncify.handleSleep()`. + var asyncPromiseHandlers = Asyncify.asyncPromiseHandlers; + if (asyncPromiseHandlers) { + Asyncify.asyncPromiseHandlers = null; + (isError ? asyncPromiseHandlers.reject : asyncPromiseHandlers.resolve)(asyncWasmReturnValue); + handled = true; + } + } + if (isError && !handled) { + // If there was an error and it was not handled by now, we have no choice but to + // rethrow that error into the global scope where it can be caught only by + // `onerror` or `onunhandledpromiserejection`. + throw asyncWasmReturnValue; + } + }); + reachedAfterCallback = true; + if (!reachedCallback) { + // A true async operation was begun; start a sleep. + Asyncify.state = Asyncify.State.Unwinding; + // TODO: reuse, don't alloc/free every sleep + Asyncify.currData = Asyncify.allocateData(); + if (typeof Browser != 'undefined' && Browser.mainLoop.func) { + Browser.mainLoop.pause(); + } + runAndAbortIfError(() => _asyncify_start_unwind(Asyncify.currData)); + } + } else if (Asyncify.state === Asyncify.State.Rewinding) { + // Stop a resume. + Asyncify.state = Asyncify.State.Normal; + runAndAbortIfError(_asyncify_stop_rewind); + _free(Asyncify.currData); + Asyncify.currData = null; + // Call all sleep callbacks now that the sleep-resume is all done. + Asyncify.sleepCallbacks.forEach((func) => callUserCallback(func)); + } else { + abort(`invalid state: ${Asyncify.state}`); + } + return Asyncify.handleSleepReturnValue; + }, + handleAsync:function(startAsync) { + return Asyncify.handleSleep((wakeUp) => { + // TODO: add error handling as a second param when handleSleep implements it. + startAsync().then(wakeUp); + }); + }, }; - return [ promise, cancel ]; - }, - noop: function() {}, - spawnProcess: function(command, args, options) { - if (Module["spawnProcess"]) { - const spawnedPromise = Module["spawnProcess"](command, args, options); - return Promise.resolve(spawnedPromise).then((function(spawned) { - if (!spawned || !spawned.on) { - throw new Error("spawnProcess() must return an EventEmitter but returned a different type."); - } - return spawned; - })); - } - if (ENVIRONMENT_IS_NODE) { - return require("child_process").spawn(command, args, { - ...options, - shell: true, - stdio: [ "pipe", "pipe", "pipe" ], - timeout: 100 - }); - } - const e = new Error("popen(), proc_open() etc. are unsupported in the browser. Call php.setSpawnHandler() " + "and provide a callback to handle spawning processes, or disable a popen(), proc_open() " + "and similar functions via php.ini."); - e.code = "SPAWN_UNSUPPORTED"; - throw e; - }, - shutdownSocket: function(socketd, how) { - const sock = getSocketFromFD(socketd); - const peer = Object.values(sock.peers)[0]; - if (!peer) { - return -1; - } - try { - peer.socket.close(); - SOCKFS.websocket_sock_ops.removePeer(sock, peer); - return 0; - } catch (e) { - console.log("Socket shutdown error", e); - return -1; - } - } -}; - -function _js_create_input_device(deviceId) { - let dataBuffer = []; - let dataCallback; - const filename = "proc_id_" + deviceId; - const device = FS.createDevice("/dev", filename, (function() {}), (function(byte) { - try { - dataBuffer.push(byte); - if (dataCallback) { - dataCallback(new Uint8Array(dataBuffer)); - dataBuffer = []; - } - } catch (e) { - console.error(e); - throw e; - } - })); - const devicePath = "/dev/" + filename; - PHPWASM.input_devices[deviceId] = { - devicePath: devicePath, - onData: function(cb) { - dataCallback = cb; - dataBuffer.forEach((function(data) { - cb(data); - })); - dataBuffer.length = 0; - } - }; - return allocateUTF8OnStack(devicePath); -} -function _js_fd_read(fd, iov, iovcnt, pnum) { - if (Asyncify.state === Asyncify.State.Normal) { - var returnCode; - var stream; - let num = 0; - try { - stream = SYSCALLS.getStreamFromFD(fd); - const num = doReadv(stream, iov, iovcnt); - HEAPU32[pnum >> 2] = num; - return 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) { - throw e; - } - if (e.errno !== 6 || !(stream?.fd in PHPWASM.child_proc_by_fd)) { - HEAPU32[pnum >> 2] = 0; - return returnCode; - } - } - } - return Asyncify.handleSleep((function(wakeUp) { - var retries = 0; - var interval = 50; - var timeout = 5e3; - var maxRetries = timeout / interval; - function poll() { - var returnCode; - var stream; - let num; - try { - stream = SYSCALLS.getStreamFromFD(fd); - num = doReadv(stream, iov, iovcnt); - returnCode = 0; - } catch (e) { - if (typeof FS == "undefined" || !(e.name === "ErrnoError")) { - console.error(e); - throw e; + function getCFunc(ident) { + var func = Module['_' + ident]; // closure exported function + return func; } - returnCode = e.errno; - } - const success = returnCode === 0; - const failure = ++retries > maxRetries || !(fd in PHPWASM.child_proc_by_fd) || PHPWASM.child_proc_by_fd[fd]?.exited || FS.isClosed(stream); - if (success) { - HEAPU32[pnum >> 2] = num; - wakeUp(0); - } else if (failure) { - HEAPU32[pnum >> 2] = 0; - wakeUp(returnCode === 6 ? 0 : returnCode); - } else { - setTimeout(poll, interval); - } - } - poll(); - })); -} + + + + + + + /** + * @param {string|null=} returnType + * @param {Array=} argTypes + * @param {Arguments|Array=} args + * @param {Object=} opts + */ + var ccall = function(ident, returnType, argTypes, args, opts) { + // For fast lookup of conversion functions + var toC = { + 'string': (str) => { + var ret = 0; + if (str !== null && str !== undefined && str !== 0) { // null string + // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0' + ret = stringToUTF8OnStack(str); + } + return ret; + }, + 'array': (arr) => { + var ret = stackAlloc(arr.length); + writeArrayToMemory(arr, ret); + return ret; + } + }; + + function convertReturnValue(ret) { + if (returnType === 'string') { + + return UTF8ToString(ret); + } + if (returnType === 'boolean') return Boolean(ret); + return ret; + } + + var func = getCFunc(ident); + var cArgs = []; + var stack = 0; + if (args) { + for (var i = 0; i < args.length; i++) { + var converter = toC[argTypes[i]]; + if (converter) { + if (stack === 0) stack = stackSave(); + cArgs[i] = converter(args[i]); + } else { + cArgs[i] = args[i]; + } + } + } + // Data for a previous async operation that was in flight before us. + var previousAsync = Asyncify.currData; + var ret = func.apply(null, cArgs); + function onDone(ret) { + runtimeKeepalivePop(); + if (stack !== 0) stackRestore(stack); + return convertReturnValue(ret); + } + var asyncMode = opts && opts.async; + + // Keep the runtime alive through all calls. Note that this call might not be + // async, but for simplicity we push and pop in all calls. + runtimeKeepalivePush(); + if (Asyncify.currData != previousAsync) { + // This is a new async operation. The wasm is paused and has unwound its stack. + // We need to return a Promise that resolves the return value + // once the stack is rewound and execution finishes. + return Asyncify.whenDone().then(onDone); + } + + ret = onDone(ret); + // If this is an async ccall, ensure we return a promise + if (asyncMode) return Promise.resolve(ret); + return ret; + }; -function _js_module_onMessage(data, bufPtr) { - if (typeof Asyncify === "undefined") { - return; - } - if (Module["onMessage"]) { - const dataStr = UTF8ToString(data); - return Asyncify.handleSleep((wakeUp => { - Module["onMessage"](dataStr).then((response => { - const responseBytes = typeof response === "string" ? (new TextEncoder).encode(response) : response; - const responseSize = responseBytes.byteLength; - const responsePtr = _malloc(responseSize + 1); - HEAPU8.set(responseBytes, responsePtr); - HEAPU8[responsePtr + responseSize] = 0; - HEAPU8[bufPtr] = responsePtr; - HEAPU8[bufPtr + 1] = responsePtr >> 8; - HEAPU8[bufPtr + 2] = responsePtr >> 16; - HEAPU8[bufPtr + 3] = responsePtr >> 24; - wakeUp(responseSize); - })).catch((e => { - console.error(e); - wakeUp(-1); - })); - })); - } -} -function _js_open_process(command, argsPtr, argsLength, descriptorsPtr, descriptorsLength, cwdPtr, cwdLength, envPtr, envLength) { - if (!command) { - return 1; - } - const cmdstr = UTF8ToString(command); - if (!cmdstr.length) { - return 0; - } - let argsArray = []; - if (argsLength) { - for (var i = 0; i < argsLength; i++) { - const charPointer = argsPtr + i * 4; - argsArray.push(UTF8ToString(HEAPU32[charPointer >> 2])); - } - } - const cwdstr = cwdPtr ? UTF8ToString(cwdPtr) : null; - let envObject = null; - if (envLength) { - envObject = {}; - for (var i = 0; i < envLength; i++) { - const envPointer = envPtr + i * 4; - const envEntry = UTF8ToString(HEAPU32[envPointer >> 2]); - const splitAt = envEntry.indexOf("="); - if (splitAt === -1) { - continue; - } - const key = envEntry.substring(0, splitAt); - const value = envEntry.substring(splitAt + 1); - envObject[key] = value; - } - } - var std = {}; - for (var i = 0; i < descriptorsLength; i++) { - const descriptorPtr = HEAPU32[descriptorsPtr + i * 4 >> 2]; - std[HEAPU32[descriptorPtr >> 2]] = { - child: HEAPU32[descriptorPtr + 4 >> 2], - parent: HEAPU32[descriptorPtr + 8 >> 2] - }; - } - return Asyncify.handleSleep((async wakeUp => { - let cp; - try { - const options = {}; - if (cwdstr !== null) { - options.cwd = cwdstr; - } - if (envObject !== null) { - options.env = envObject; - } - cp = PHPWASM.spawnProcess(cmdstr, argsArray, options); - if (cp instanceof Promise) { - cp = await cp; - } - } catch (e) { - if (e.code === "SPAWN_UNSUPPORTED") { - wakeUp(1); - return; - } - console.error(e); - wakeUp(1); - throw e; - } - const ProcInfo = { - pid: cp.pid, - exited: false, - stdinFd: std[0]?.child, - stdinIsDevice: std[0]?.child in PHPWASM.input_devices, - stdoutChildFd: std[1]?.child, - stdoutParentFd: std[1]?.parent, - stderrChildFd: std[2]?.child, - stderrParentFd: std[2]?.parent, - stdout: new PHPWASM.EventEmitter, - stderr: new PHPWASM.EventEmitter + + var FSNode = /** @constructor */ function(parent, name, mode, rdev) { + if (!parent) { + parent = this; // root node sets parent to itself + } + this.parent = parent; + this.mount = parent.mount; + this.mounted = null; + this.id = FS.nextInode++; + this.name = name; + this.mode = mode; + this.node_ops = {}; + this.stream_ops = {}; + this.rdev = rdev; }; - if (ProcInfo.stdoutChildFd) PHPWASM.child_proc_by_fd[ProcInfo.stdoutChildFd] = ProcInfo; - if (ProcInfo.stderrChildFd) PHPWASM.child_proc_by_fd[ProcInfo.stderrChildFd] = ProcInfo; - if (ProcInfo.stdoutParentFd) PHPWASM.child_proc_by_fd[ProcInfo.stdoutParentFd] = ProcInfo; - if (ProcInfo.stderrParentFd) PHPWASM.child_proc_by_fd[ProcInfo.stderrParentFd] = ProcInfo; - PHPWASM.child_proc_by_pid[ProcInfo.pid] = ProcInfo; - cp.on("exit", (function(code) { - ProcInfo.exitCode = code; - ProcInfo.exited = true; - ProcInfo.stdout.emit("data"); - ProcInfo.stderr.emit("data"); - })); - if (ProcInfo.stdoutChildFd) { - const stdoutStream = SYSCALLS.getStreamFromFD(ProcInfo.stdoutChildFd); - let stdoutAt = 0; - cp.stdout.on("data", (function(data) { - ProcInfo.stdout.emit("data", data); - stdoutStream.stream_ops.write(stdoutStream, data, 0, data.length, stdoutAt); - stdoutAt += data.length; - })); - } - if (ProcInfo.stderrChildFd) { - const stderrStream = SYSCALLS.getStreamFromFD(ProcInfo.stderrChildFd); - let stderrAt = 0; - cp.stderr.on("data", (function(data) { - ProcInfo.stderr.emit("data", data); - stderrStream.stream_ops.write(stderrStream, data, 0, data.length, stderrAt); - stderrAt += data.length; - })); - } - try { - await new Promise(((resolve, reject) => { - cp.on("spawn", resolve); - cp.on("error", reject); - })); - } catch (e) { - console.error(e); - wakeUp(1); - return; - } - if (ProcInfo.stdinIsDevice) { - PHPWASM.input_devices[ProcInfo.stdinFd].onData((function(data) { - if (!data) return; - const dataStr = new TextDecoder("utf-8").decode(data); - cp.stdin.write(dataStr); - })); - wakeUp(ProcInfo.pid); - return; - } - if (ProcInfo.stdinFd) { - const stdinStream = SYSCALLS.getStreamFromFD(ProcInfo.stdinFd); - if (stdinStream.node) { - const CHUNK_SIZE = 1024; - const buffer = new Uint8Array(CHUNK_SIZE); - let offset = 0; - while (true) { - const bytesRead = stdinStream.stream_ops.read(stdinStream, buffer, 0, CHUNK_SIZE, offset); - if (bytesRead === null || bytesRead === 0) { - break; - } - try { - cp.stdin.write(buffer.subarray(0, bytesRead)); - } catch (e) { - console.error(e); - return 1; - } - if (bytesRead < CHUNK_SIZE) { - break; - } - offset += bytesRead; + var readMode = 292/*292*/ | 73/*73*/; + var writeMode = 146/*146*/; + Object.defineProperties(FSNode.prototype, { + read: { + get: /** @this{FSNode} */function() { + return (this.mode & readMode) === readMode; + }, + set: /** @this{FSNode} */function(val) { + val ? this.mode |= readMode : this.mode &= ~readMode; + } + }, + write: { + get: /** @this{FSNode} */function() { + return (this.mode & writeMode) === writeMode; + }, + set: /** @this{FSNode} */function(val) { + val ? this.mode |= writeMode : this.mode &= ~writeMode; + } + }, + isFolder: { + get: /** @this{FSNode} */function() { + return FS.isDir(this.mode); + } + }, + isDevice: { + get: /** @this{FSNode} */function() { + return FS.isChrdev(this.mode); } - wakeUp(ProcInfo.pid); - return; } - } - wakeUp(ProcInfo.pid); - })); -} + }); + FS.FSNode = FSNode; + FS.createPreloadedFile = FS_createPreloadedFile; + FS.staticInit();Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_unlink"] = FS.unlink;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createDevice"] = FS.createDevice;; +if (ENVIRONMENT_IS_NODE) { NODEFS.staticInit(); }; +ERRNO_CODES = { + 'EPERM': 63, + 'ENOENT': 44, + 'ESRCH': 71, + 'EINTR': 27, + 'EIO': 29, + 'ENXIO': 60, + 'E2BIG': 1, + 'ENOEXEC': 45, + 'EBADF': 8, + 'ECHILD': 12, + 'EAGAIN': 6, + 'EWOULDBLOCK': 6, + 'ENOMEM': 48, + 'EACCES': 2, + 'EFAULT': 21, + 'ENOTBLK': 105, + 'EBUSY': 10, + 'EEXIST': 20, + 'EXDEV': 75, + 'ENODEV': 43, + 'ENOTDIR': 54, + 'EISDIR': 31, + 'EINVAL': 28, + 'ENFILE': 41, + 'EMFILE': 33, + 'ENOTTY': 59, + 'ETXTBSY': 74, + 'EFBIG': 22, + 'ENOSPC': 51, + 'ESPIPE': 70, + 'EROFS': 69, + 'EMLINK': 34, + 'EPIPE': 64, + 'EDOM': 18, + 'ERANGE': 68, + 'ENOMSG': 49, + 'EIDRM': 24, + 'ECHRNG': 106, + 'EL2NSYNC': 156, + 'EL3HLT': 107, + 'EL3RST': 108, + 'ELNRNG': 109, + 'EUNATCH': 110, + 'ENOCSI': 111, + 'EL2HLT': 112, + 'EDEADLK': 16, + 'ENOLCK': 46, + 'EBADE': 113, + 'EBADR': 114, + 'EXFULL': 115, + 'ENOANO': 104, + 'EBADRQC': 103, + 'EBADSLT': 102, + 'EDEADLOCK': 16, + 'EBFONT': 101, + 'ENOSTR': 100, + 'ENODATA': 116, + 'ETIME': 117, + 'ENOSR': 118, + 'ENONET': 119, + 'ENOPKG': 120, + 'EREMOTE': 121, + 'ENOLINK': 47, + 'EADV': 122, + 'ESRMNT': 123, + 'ECOMM': 124, + 'EPROTO': 65, + 'EMULTIHOP': 36, + 'EDOTDOT': 125, + 'EBADMSG': 9, + 'ENOTUNIQ': 126, + 'EBADFD': 127, + 'EREMCHG': 128, + 'ELIBACC': 129, + 'ELIBBAD': 130, + 'ELIBSCN': 131, + 'ELIBMAX': 132, + 'ELIBEXEC': 133, + 'ENOSYS': 52, + 'ENOTEMPTY': 55, + 'ENAMETOOLONG': 37, + 'ELOOP': 32, + 'EOPNOTSUPP': 138, + 'EPFNOSUPPORT': 139, + 'ECONNRESET': 15, + 'ENOBUFS': 42, + 'EAFNOSUPPORT': 5, + 'EPROTOTYPE': 67, + 'ENOTSOCK': 57, + 'ENOPROTOOPT': 50, + 'ESHUTDOWN': 140, + 'ECONNREFUSED': 14, + 'EADDRINUSE': 3, + 'ECONNABORTED': 13, + 'ENETUNREACH': 40, + 'ENETDOWN': 38, + 'ETIMEDOUT': 73, + 'EHOSTDOWN': 142, + 'EHOSTUNREACH': 23, + 'EINPROGRESS': 26, + 'EALREADY': 7, + 'EDESTADDRREQ': 17, + 'EMSGSIZE': 35, + 'EPROTONOSUPPORT': 66, + 'ESOCKTNOSUPPORT': 137, + 'EADDRNOTAVAIL': 4, + 'ENETRESET': 39, + 'EISCONN': 30, + 'ENOTCONN': 53, + 'ETOOMANYREFS': 141, + 'EUSERS': 136, + 'EDQUOT': 19, + 'ESTALE': 72, + 'ENOTSUP': 138, + 'ENOMEDIUM': 148, + 'EILSEQ': 25, + 'EOVERFLOW': 61, + 'ECANCELED': 11, + 'ENOTRECOVERABLE': 56, + 'EOWNERDEAD': 62, + 'ESTRPIPE': 135, + };; +PHPWASM.init();; +var wasmImports = { + __assert_fail: ___assert_fail, + __call_sighandler: ___call_sighandler, + __syscall_accept4: ___syscall_accept4, + __syscall_bind: ___syscall_bind, + __syscall_chdir: ___syscall_chdir, + __syscall_chmod: ___syscall_chmod, + __syscall_connect: ___syscall_connect, + __syscall_dup: ___syscall_dup, + __syscall_dup3: ___syscall_dup3, + __syscall_faccessat: ___syscall_faccessat, + __syscall_fallocate: ___syscall_fallocate, + __syscall_fchmod: ___syscall_fchmod, + __syscall_fchown32: ___syscall_fchown32, + __syscall_fchownat: ___syscall_fchownat, + __syscall_fcntl64: ___syscall_fcntl64, + __syscall_fdatasync: ___syscall_fdatasync, + __syscall_fstat64: ___syscall_fstat64, + __syscall_ftruncate64: ___syscall_ftruncate64, + __syscall_getcwd: ___syscall_getcwd, + __syscall_getdents64: ___syscall_getdents64, + __syscall_getpeername: ___syscall_getpeername, + __syscall_getsockname: ___syscall_getsockname, + __syscall_getsockopt: ___syscall_getsockopt, + __syscall_ioctl: ___syscall_ioctl, + __syscall_listen: ___syscall_listen, + __syscall_lstat64: ___syscall_lstat64, + __syscall_mkdirat: ___syscall_mkdirat, + __syscall_newfstatat: ___syscall_newfstatat, + __syscall_openat: ___syscall_openat, + __syscall_pipe: ___syscall_pipe, + __syscall_poll: ___syscall_poll, + __syscall_readlinkat: ___syscall_readlinkat, + __syscall_recvfrom: ___syscall_recvfrom, + __syscall_renameat: ___syscall_renameat, + __syscall_rmdir: ___syscall_rmdir, + __syscall_sendto: ___syscall_sendto, + __syscall_socket: ___syscall_socket, + __syscall_stat64: ___syscall_stat64, + __syscall_statfs64: ___syscall_statfs64, + __syscall_symlink: ___syscall_symlink, + __syscall_unlinkat: ___syscall_unlinkat, + __syscall_utimensat: ___syscall_utimensat, + _emscripten_get_now_is_monotonic: __emscripten_get_now_is_monotonic, + _emscripten_throw_longjmp: __emscripten_throw_longjmp, + _gmtime_js: __gmtime_js, + _localtime_js: __localtime_js, + _mktime_js: __mktime_js, + _mmap_js: __mmap_js, + _munmap_js: __munmap_js, + _setitimer_js: __setitimer_js, + _tzset_js: __tzset_js, + abort: _abort, + emscripten_date_now: _emscripten_date_now, + emscripten_get_heap_max: _emscripten_get_heap_max, + emscripten_get_now: _emscripten_get_now, + emscripten_memcpy_big: _emscripten_memcpy_big, + emscripten_resize_heap: _emscripten_resize_heap, + emscripten_sleep: _emscripten_sleep, + environ_get: _environ_get, + environ_sizes_get: _environ_sizes_get, + exit: _exit, + fd_close: _fd_close, + fd_fdstat_get: _fd_fdstat_get, + fd_read: _fd_read, + fd_seek: _fd_seek, + fd_write: _fd_write, + getaddrinfo: _getaddrinfo, + gethostbyaddr: _gethostbyaddr, + gethostbyname_r: _gethostbyname_r, + getloadavg: _getloadavg, + getnameinfo: _getnameinfo, + getprotobyname: _getprotobyname, + getprotobynumber: _getprotobynumber, + invoke_i: invoke_i, + invoke_ii: invoke_ii, + invoke_iii: invoke_iii, + invoke_iiii: invoke_iiii, + invoke_iiiii: invoke_iiiii, + invoke_iiiiii: invoke_iiiiii, + invoke_iiiiiii: invoke_iiiiiii, + invoke_iiiiiiii: invoke_iiiiiiii, + invoke_iiiiiiiiii: invoke_iiiiiiiiii, + invoke_jii: invoke_jii, + invoke_v: invoke_v, + invoke_vi: invoke_vi, + invoke_vii: invoke_vii, + invoke_viidii: invoke_viidii, + invoke_viii: invoke_viii, + invoke_viiii: invoke_viiii, + invoke_viiiii: invoke_viiiii, + invoke_viiiiii: invoke_viiiiii, + invoke_viiiiiii: invoke_viiiiiii, + invoke_viiiiiiiii: invoke_viiiiiiiii, + js_create_input_device: _js_create_input_device, + js_fd_read: _js_fd_read, + js_module_onMessage: _js_module_onMessage, + js_open_process: _js_open_process, + js_popen_to_file: _js_popen_to_file, + js_process_status: _js_process_status, + js_waitpid: _js_waitpid, + proc_exit: _proc_exit, + strftime: _strftime, + strptime: _strptime, + wasm_close: _wasm_close, + wasm_poll_socket: _wasm_poll_socket, + wasm_setsockopt: _wasm_setsockopt, + wasm_shutdown: _wasm_shutdown +}; +var asm = createWasm(); +/** @type {function(...*):?} */ +var ___wasm_call_ctors = function() { + return (___wasm_call_ctors = Module['asm']['__wasm_call_ctors']).apply(null, arguments); +}; -function _js_popen_to_file(command, mode, exitCodePtr) { - if (!command) return 1; - const cmdstr = UTF8ToString(command); - if (!cmdstr.length) return 0; - const modestr = UTF8ToString(mode); - if (!modestr.length) return 0; - if (modestr === "w") { - console.error('popen($cmd, "w") is not implemented yet'); - } - return Asyncify.handleSleep((async wakeUp => { - let cp; - try { - cp = PHPWASM.spawnProcess(cmdstr, []); - if (cp instanceof Promise) { - cp = await cp; - } - } catch (e) { - console.error(e); - if (e.code === "SPAWN_UNSUPPORTED") { - return 1; - } - throw e; - } - const outByteArrays = []; - cp.stdout.on("data", (function(data) { - outByteArrays.push(data); - })); - const outputPath = "/tmp/popen_output"; - cp.on("exit", (function(exitCode) { - const outBytes = new Uint8Array(outByteArrays.reduce(((acc, curr) => acc + curr.length), 0)); - let offset = 0; - for (const byteArray of outByteArrays) { - outBytes.set(byteArray, offset); - offset += byteArray.length; - } - FS.writeFile(outputPath, outBytes); - HEAPU8[exitCodePtr] = exitCode; - wakeUp(allocateUTF8OnStack(outputPath)); - })); - })); -} +/** @type {function(...*):?} */ +var _free = function() { + return (_free = Module['asm']['free']).apply(null, arguments); +}; -function _js_process_status(pid, exitCodePtr) { - if (!PHPWASM.child_proc_by_pid[pid]) { - return -1; - } - if (PHPWASM.child_proc_by_pid[pid].exited) { - HEAPU32[exitCodePtr >> 2] = PHPWASM.child_proc_by_pid[pid].exitCode; - return 1; - } - return 0; -} +/** @type {function(...*):?} */ +var _memcpy = function() { + return (_memcpy = Module['asm']['memcpy']).apply(null, arguments); +}; -function _js_waitpid(pid, exitCodePtr) { - if (!PHPWASM.child_proc_by_pid[pid]) { - return -1; - } - return Asyncify.handleSleep((wakeUp => { - const poll = function() { - if (PHPWASM.child_proc_by_pid[pid]?.exited) { - HEAPU32[exitCodePtr >> 2] = PHPWASM.child_proc_by_pid[pid].exitCode; - wakeUp(pid); - } else { - setTimeout(poll, 50); - } - }; - poll(); - })); -} +/** @type {function(...*):?} */ +var _malloc = function() { + return (_malloc = Module['asm']['malloc']).apply(null, arguments); +}; -var arraySum = (array, index) => { - var sum = 0; - for (var i = 0; i <= index; sum += array[i++]) {} - return sum; +/** @type {function(...*):?} */ +var setTempRet0 = function() { + return (setTempRet0 = Module['asm']['setTempRet0']).apply(null, arguments); }; -var MONTH_DAYS_LEAP = [ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; - -var MONTH_DAYS_REGULAR = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; - -var addDays = (date, days) => { - var newDate = new Date(date.getTime()); - while (days > 0) { - var leap = isLeapYear(newDate.getFullYear()); - var currentMonth = newDate.getMonth(); - var daysInCurrentMonth = (leap ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR)[currentMonth]; - if (days > daysInCurrentMonth - newDate.getDate()) { - days -= daysInCurrentMonth - newDate.getDate() + 1; - newDate.setDate(1); - if (currentMonth < 11) { - newDate.setMonth(currentMonth + 1); - } else { - newDate.setMonth(0); - newDate.setFullYear(newDate.getFullYear() + 1); - } - } else { - newDate.setDate(newDate.getDate() + days); - return newDate; - } - } - return newDate; +/** @type {function(...*):?} */ +var ___errno_location = function() { + return (___errno_location = Module['asm']['__errno_location']).apply(null, arguments); }; -var writeArrayToMemory = (array, buffer) => { - HEAP8.set(array, buffer); +/** @type {function(...*):?} */ +var _wasm_read = Module['_wasm_read'] = function() { + return (_wasm_read = Module['_wasm_read'] = Module['asm']['wasm_read']).apply(null, arguments); }; -var _strftime = (s, maxsize, format, tm) => { - var tm_zone = HEAP32[tm + 40 >> 2]; - var date = { - tm_sec: HEAP32[tm >> 2], - tm_min: HEAP32[tm + 4 >> 2], - tm_hour: HEAP32[tm + 8 >> 2], - tm_mday: HEAP32[tm + 12 >> 2], - tm_mon: HEAP32[tm + 16 >> 2], - tm_year: HEAP32[tm + 20 >> 2], - tm_wday: HEAP32[tm + 24 >> 2], - tm_yday: HEAP32[tm + 28 >> 2], - tm_isdst: HEAP32[tm + 32 >> 2], - tm_gmtoff: HEAP32[tm + 36 >> 2], - tm_zone: tm_zone ? UTF8ToString(tm_zone) : "" - }; - var pattern = UTF8ToString(format); - var EXPANSION_RULES_1 = { - "%c": "%a %b %d %H:%M:%S %Y", - "%D": "%m/%d/%y", - "%F": "%Y-%m-%d", - "%h": "%b", - "%r": "%I:%M:%S %p", - "%R": "%H:%M", - "%T": "%H:%M:%S", - "%x": "%m/%d/%y", - "%X": "%H:%M:%S", - "%Ec": "%c", - "%EC": "%C", - "%Ex": "%m/%d/%y", - "%EX": "%H:%M:%S", - "%Ey": "%y", - "%EY": "%Y", - "%Od": "%d", - "%Oe": "%e", - "%OH": "%H", - "%OI": "%I", - "%Om": "%m", - "%OM": "%M", - "%OS": "%S", - "%Ou": "%u", - "%OU": "%U", - "%OV": "%V", - "%Ow": "%w", - "%OW": "%W", - "%Oy": "%y" - }; - for (var rule in EXPANSION_RULES_1) { - pattern = pattern.replace(new RegExp(rule, "g"), EXPANSION_RULES_1[rule]); - } - var WEEKDAYS = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ]; - var MONTHS = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]; - function leadingSomething(value, digits, character) { - var str = typeof value == "number" ? value.toString() : value || ""; - while (str.length < digits) { - str = character[0] + str; - } - return str; - } - function leadingNulls(value, digits) { - return leadingSomething(value, digits, "0"); - } - function compareByDay(date1, date2) { - function sgn(value) { - return value < 0 ? -1 : value > 0 ? 1 : 0; - } - var compare; - if ((compare = sgn(date1.getFullYear() - date2.getFullYear())) === 0) { - if ((compare = sgn(date1.getMonth() - date2.getMonth())) === 0) { - compare = sgn(date1.getDate() - date2.getDate()); - } - } - return compare; - } - function getFirstWeekStartDate(janFourth) { - switch (janFourth.getDay()) { - case 0: - return new Date(janFourth.getFullYear() - 1, 11, 29); - - case 1: - return janFourth; - - case 2: - return new Date(janFourth.getFullYear(), 0, 3); - - case 3: - return new Date(janFourth.getFullYear(), 0, 2); - - case 4: - return new Date(janFourth.getFullYear(), 0, 1); - - case 5: - return new Date(janFourth.getFullYear() - 1, 11, 31); - - case 6: - return new Date(janFourth.getFullYear() - 1, 11, 30); - } - } - function getWeekBasedYear(date) { - var thisDate = addDays(new Date(date.tm_year + 1900, 0, 1), date.tm_yday); - var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4); - var janFourthNextYear = new Date(thisDate.getFullYear() + 1, 0, 4); - var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear); - var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear); - if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) { - if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) { - return thisDate.getFullYear() + 1; - } - return thisDate.getFullYear(); - } - return thisDate.getFullYear() - 1; - } - var EXPANSION_RULES_2 = { - "%a": date => WEEKDAYS[date.tm_wday].substring(0, 3), - "%A": date => WEEKDAYS[date.tm_wday], - "%b": date => MONTHS[date.tm_mon].substring(0, 3), - "%B": date => MONTHS[date.tm_mon], - "%C": date => { - var year = date.tm_year + 1900; - return leadingNulls(year / 100 | 0, 2); - }, - "%d": date => leadingNulls(date.tm_mday, 2), - "%e": date => leadingSomething(date.tm_mday, 2, " "), - "%g": date => getWeekBasedYear(date).toString().substring(2), - "%G": date => getWeekBasedYear(date), - "%H": date => leadingNulls(date.tm_hour, 2), - "%I": date => { - var twelveHour = date.tm_hour; - if (twelveHour == 0) twelveHour = 12; else if (twelveHour > 12) twelveHour -= 12; - return leadingNulls(twelveHour, 2); - }, - "%j": date => leadingNulls(date.tm_mday + arraySum(isLeapYear(date.tm_year + 1900) ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, date.tm_mon - 1), 3), - "%m": date => leadingNulls(date.tm_mon + 1, 2), - "%M": date => leadingNulls(date.tm_min, 2), - "%n": () => "\n", - "%p": date => { - if (date.tm_hour >= 0 && date.tm_hour < 12) { - return "AM"; - } - return "PM"; - }, - "%S": date => leadingNulls(date.tm_sec, 2), - "%t": () => "\t", - "%u": date => date.tm_wday || 7, - "%U": date => { - var days = date.tm_yday + 7 - date.tm_wday; - return leadingNulls(Math.floor(days / 7), 2); - }, - "%V": date => { - var val = Math.floor((date.tm_yday + 7 - (date.tm_wday + 6) % 7) / 7); - if ((date.tm_wday + 371 - date.tm_yday - 2) % 7 <= 2) { - val++; - } - if (!val) { - val = 52; - var dec31 = (date.tm_wday + 7 - date.tm_yday - 1) % 7; - if (dec31 == 4 || dec31 == 5 && isLeapYear(date.tm_year % 400 - 1)) { - val++; - } - } else if (val == 53) { - var jan1 = (date.tm_wday + 371 - date.tm_yday) % 7; - if (jan1 != 4 && (jan1 != 3 || !isLeapYear(date.tm_year))) val = 1; - } - return leadingNulls(val, 2); - }, - "%w": date => date.tm_wday, - "%W": date => { - var days = date.tm_yday + 7 - (date.tm_wday + 6) % 7; - return leadingNulls(Math.floor(days / 7), 2); - }, - "%y": date => (date.tm_year + 1900).toString().substring(2), - "%Y": date => date.tm_year + 1900, - "%z": date => { - var off = date.tm_gmtoff; - var ahead = off >= 0; - off = Math.abs(off) / 60; - off = off / 60 * 100 + off % 60; - return (ahead ? "+" : "-") + String("0000" + off).slice(-4); - }, - "%Z": date => date.tm_zone, - "%%": () => "%" - }; - pattern = pattern.replace(/%%/g, "\0\0"); - for (var rule in EXPANSION_RULES_2) { - if (pattern.includes(rule)) { - pattern = pattern.replace(new RegExp(rule, "g"), EXPANSION_RULES_2[rule](date)); - } - } - pattern = pattern.replace(/\0\0/g, "%"); - var bytes = intArrayFromString(pattern, false); - if (bytes.length > maxsize) { - return 0; - } - writeArrayToMemory(bytes, s); - return bytes.length - 1; +/** @type {function(...*):?} */ +var _fflush = Module['_fflush'] = function() { + return (_fflush = Module['_fflush'] = Module['asm']['fflush']).apply(null, arguments); }; -var _strptime = (buf, format, tm) => { - var pattern = UTF8ToString(format); - var SPECIAL_CHARS = "\\!@#$^&*()+=-[]/{}|:<>?,."; - for (var i = 0, ii = SPECIAL_CHARS.length; i < ii; ++i) { - pattern = pattern.replace(new RegExp("\\" + SPECIAL_CHARS[i], "g"), "\\" + SPECIAL_CHARS[i]); - } - var EQUIVALENT_MATCHERS = { - "%A": "%a", - "%B": "%b", - "%c": "%a %b %d %H:%M:%S %Y", - "%D": "%m\\/%d\\/%y", - "%e": "%d", - "%F": "%Y-%m-%d", - "%h": "%b", - "%R": "%H\\:%M", - "%r": "%I\\:%M\\:%S\\s%p", - "%T": "%H\\:%M\\:%S", - "%x": "%m\\/%d\\/(?:%y|%Y)", - "%X": "%H\\:%M\\:%S" - }; - for (var matcher in EQUIVALENT_MATCHERS) { - pattern = pattern.replace(matcher, EQUIVALENT_MATCHERS[matcher]); - } - var DATE_PATTERNS = { - "%a": "(?:Sun(?:day)?)|(?:Mon(?:day)?)|(?:Tue(?:sday)?)|(?:Wed(?:nesday)?)|(?:Thu(?:rsday)?)|(?:Fri(?:day)?)|(?:Sat(?:urday)?)", - "%b": "(?:Jan(?:uary)?)|(?:Feb(?:ruary)?)|(?:Mar(?:ch)?)|(?:Apr(?:il)?)|May|(?:Jun(?:e)?)|(?:Jul(?:y)?)|(?:Aug(?:ust)?)|(?:Sep(?:tember)?)|(?:Oct(?:ober)?)|(?:Nov(?:ember)?)|(?:Dec(?:ember)?)", - "%C": "\\d\\d", - "%d": "0[1-9]|[1-9](?!\\d)|1\\d|2\\d|30|31", - "%H": "\\d(?!\\d)|[0,1]\\d|20|21|22|23", - "%I": "\\d(?!\\d)|0\\d|10|11|12", - "%j": "00[1-9]|0?[1-9](?!\\d)|0?[1-9]\\d(?!\\d)|[1,2]\\d\\d|3[0-6]\\d", - "%m": "0[1-9]|[1-9](?!\\d)|10|11|12", - "%M": "0\\d|\\d(?!\\d)|[1-5]\\d", - "%n": "\\s", - "%p": "AM|am|PM|pm|A\\.M\\.|a\\.m\\.|P\\.M\\.|p\\.m\\.", - "%S": "0\\d|\\d(?!\\d)|[1-5]\\d|60", - "%U": "0\\d|\\d(?!\\d)|[1-4]\\d|50|51|52|53", - "%W": "0\\d|\\d(?!\\d)|[1-4]\\d|50|51|52|53", - "%w": "[0-6]", - "%y": "\\d\\d", - "%Y": "\\d\\d\\d\\d", - "%%": "%", - "%t": "\\s" - }; - var MONTH_NUMBERS = { - JAN: 0, - FEB: 1, - MAR: 2, - APR: 3, - MAY: 4, - JUN: 5, - JUL: 6, - AUG: 7, - SEP: 8, - OCT: 9, - NOV: 10, - DEC: 11 - }; - var DAY_NUMBERS_SUN_FIRST = { - SUN: 0, - MON: 1, - TUE: 2, - WED: 3, - THU: 4, - FRI: 5, - SAT: 6 - }; - var DAY_NUMBERS_MON_FIRST = { - MON: 0, - TUE: 1, - WED: 2, - THU: 3, - FRI: 4, - SAT: 5, - SUN: 6 - }; - for (var datePattern in DATE_PATTERNS) { - pattern = pattern.replace(datePattern, "(" + datePattern + DATE_PATTERNS[datePattern] + ")"); - } - var capture = []; - for (var i = pattern.indexOf("%"); i >= 0; i = pattern.indexOf("%")) { - capture.push(pattern[i + 1]); - pattern = pattern.replace(new RegExp("\\%" + pattern[i + 1], "g"), ""); - } - var matches = new RegExp("^" + pattern, "i").exec(UTF8ToString(buf)); - function initDate() { - function fixup(value, min, max) { - return typeof value != "number" || isNaN(value) ? min : value >= min ? value <= max ? value : max : min; - } - return { - year: fixup(HEAP32[tm + 20 >> 2] + 1900, 1970, 9999), - month: fixup(HEAP32[tm + 16 >> 2], 0, 11), - day: fixup(HEAP32[tm + 12 >> 2], 1, 31), - hour: fixup(HEAP32[tm + 8 >> 2], 0, 23), - min: fixup(HEAP32[tm + 4 >> 2], 0, 59), - sec: fixup(HEAP32[tm >> 2], 0, 59) - }; - } - if (matches) { - var date = initDate(); - var value; - var getMatch = symbol => { - var pos = capture.indexOf(symbol); - if (pos >= 0) { - return matches[pos + 1]; - } - return; - }; - if (value = getMatch("S")) { - date.sec = jstoi_q(value); - } - if (value = getMatch("M")) { - date.min = jstoi_q(value); - } - if (value = getMatch("H")) { - date.hour = jstoi_q(value); - } else if (value = getMatch("I")) { - var hour = jstoi_q(value); - if (value = getMatch("p")) { - hour += value.toUpperCase()[0] === "P" ? 12 : 0; - } - date.hour = hour; - } - if (value = getMatch("Y")) { - date.year = jstoi_q(value); - } else if (value = getMatch("y")) { - var year = jstoi_q(value); - if (value = getMatch("C")) { - year += jstoi_q(value) * 100; - } else { - year += year < 69 ? 2e3 : 1900; - } - date.year = year; - } - if (value = getMatch("m")) { - date.month = jstoi_q(value) - 1; - } else if (value = getMatch("b")) { - date.month = MONTH_NUMBERS[value.substring(0, 3).toUpperCase()] || 0; - } - if (value = getMatch("d")) { - date.day = jstoi_q(value); - } else if (value = getMatch("j")) { - var day = jstoi_q(value); - var leapYear = isLeapYear(date.year); - for (var month = 0; month < 12; ++month) { - var daysUntilMonth = arraySum(leapYear ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, month - 1); - if (day <= daysUntilMonth + (leapYear ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR)[month]) { - date.day = day - daysUntilMonth; - } - } - } else if (value = getMatch("a")) { - var weekDay = value.substring(0, 3).toUpperCase(); - if (value = getMatch("U")) { - var weekDayNumber = DAY_NUMBERS_SUN_FIRST[weekDay]; - var weekNumber = jstoi_q(value); - var janFirst = new Date(date.year, 0, 1); - var endDate; - if (janFirst.getDay() === 0) { - endDate = addDays(janFirst, weekDayNumber + 7 * (weekNumber - 1)); - } else { - endDate = addDays(janFirst, 7 - janFirst.getDay() + weekDayNumber + 7 * (weekNumber - 1)); - } - date.day = endDate.getDate(); - date.month = endDate.getMonth(); - } else if (value = getMatch("W")) { - var weekDayNumber = DAY_NUMBERS_MON_FIRST[weekDay]; - var weekNumber = jstoi_q(value); - var janFirst = new Date(date.year, 0, 1); - var endDate; - if (janFirst.getDay() === 1) { - endDate = addDays(janFirst, weekDayNumber + 7 * (weekNumber - 1)); - } else { - endDate = addDays(janFirst, 7 - janFirst.getDay() + 1 + weekDayNumber + 7 * (weekNumber - 1)); - } - date.day = endDate.getDate(); - date.month = endDate.getMonth(); - } - } - var fullDate = new Date(date.year, date.month, date.day, date.hour, date.min, date.sec, 0); - HEAP32[tm >> 2] = fullDate.getSeconds(); - HEAP32[tm + 4 >> 2] = fullDate.getMinutes(); - HEAP32[tm + 8 >> 2] = fullDate.getHours(); - HEAP32[tm + 12 >> 2] = fullDate.getDate(); - HEAP32[tm + 16 >> 2] = fullDate.getMonth(); - HEAP32[tm + 20 >> 2] = fullDate.getFullYear() - 1900; - HEAP32[tm + 24 >> 2] = fullDate.getDay(); - HEAP32[tm + 28 >> 2] = arraySum(isLeapYear(fullDate.getFullYear()) ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, fullDate.getMonth() - 1) + fullDate.getDate() - 1; - HEAP32[tm + 32 >> 2] = 0; - return buf + intArrayFromString(matches[0]).length - 1; - } - return 0; +/** @type {function(...*):?} */ +var _wasm_popen = Module['_wasm_popen'] = function() { + return (_wasm_popen = Module['_wasm_popen'] = Module['asm']['wasm_popen']).apply(null, arguments); }; -function _wasm_close(socketd) { - return PHPWASM.shutdownSocket(socketd, 2); -} +/** @type {function(...*):?} */ +var _wasm_php_exec = Module['_wasm_php_exec'] = function() { + return (_wasm_php_exec = Module['_wasm_php_exec'] = Module['asm']['wasm_php_exec']).apply(null, arguments); +}; -function _wasm_poll_socket(socketd, events, timeout) { - if (typeof Asyncify === "undefined") { - return 0; - } - const POLLIN = 1; - const POLLPRI = 2; - const POLLOUT = 4; - const POLLERR = 8; - const POLLHUP = 16; - const POLLNVAL = 32; - return Asyncify.handleSleep((wakeUp => { - const polls = []; - if (socketd in PHPWASM.child_proc_by_fd) { - const procInfo = PHPWASM.child_proc_by_fd[socketd]; - if (procInfo.exited) { - wakeUp(0); - return; - } - polls.push(PHPWASM.awaitEvent(procInfo.stdout, "data")); - } else { - const sock = getSocketFromFD(socketd); - if (!sock) { - wakeUp(0); - return; - } - const lookingFor = new Set; - if (events & POLLIN || events & POLLPRI) { - if (sock.server) { - for (const client of sock.pending) { - if ((client.recv_queue || []).length > 0) { - wakeUp(1); - return; - } - } - } else if ((sock.recv_queue || []).length > 0) { - wakeUp(1); - return; - } - } - const webSockets = PHPWASM.getAllWebSockets(sock); - if (!webSockets.length) { - wakeUp(0); - return; - } - for (const ws of webSockets) { - if (events & POLLIN || events & POLLPRI) { - polls.push(PHPWASM.awaitData(ws)); - lookingFor.add("POLLIN"); - } - if (events & POLLOUT) { - polls.push(PHPWASM.awaitConnection(ws)); - lookingFor.add("POLLOUT"); - } - if (events & POLLHUP) { - polls.push(PHPWASM.awaitClose(ws)); - lookingFor.add("POLLHUP"); - } - if (events & POLLERR || events & POLLNVAL) { - polls.push(PHPWASM.awaitError(ws)); - lookingFor.add("POLLERR"); - } - } - } - if (polls.length === 0) { - console.warn("Unsupported poll event " + events + ", defaulting to setTimeout()."); - setTimeout((function() { - wakeUp(0); - }), timeout); - return; - } - const promises = polls.map((([promise]) => promise)); - const clearPolling = () => polls.forEach((([, clear]) => clear())); - let awaken = false; - let timeoutId; - Promise.race(promises).then((function(results) { - if (!awaken) { - awaken = true; - wakeUp(1); - if (timeoutId) { - clearTimeout(timeoutId); - } - clearPolling(); - } - })); - if (timeout !== -1) { - timeoutId = setTimeout((function() { - if (!awaken) { - awaken = true; - wakeUp(0); - clearPolling(); - } - }), timeout); - } - })); -} +/** @type {function(...*):?} */ +var _php_pollfd_for = Module['_php_pollfd_for'] = function() { + return (_php_pollfd_for = Module['_php_pollfd_for'] = Module['asm']['php_pollfd_for']).apply(null, arguments); +}; -function _wasm_setsockopt(socketd, level, optionName, optionValuePtr, optionLen) { - const optionValue = HEAPU8[optionValuePtr]; - const SOL_SOCKET = 1; - const SO_KEEPALIVE = 9; - const IPPROTO_TCP = 6; - const TCP_NODELAY = 1; - const isSupported = level === SOL_SOCKET && optionName === SO_KEEPALIVE || level === IPPROTO_TCP && optionName === TCP_NODELAY; - if (!isSupported) { - console.warn(`Unsupported socket option: ${level}, ${optionName}, ${optionValue}`); - return -1; - } - const ws = PHPWASM.getAllWebSockets(socketd)[0]; - if (!ws) { - return -1; - } - ws.setSocketOpt(level, optionName, optionValuePtr); - return 0; -} +/** @type {function(...*):?} */ +var _htons = function() { + return (_htons = Module['asm']['htons']).apply(null, arguments); +}; -function _wasm_shutdown(socketd, how) { - return PHPWASM.shutdownSocket(socketd, how); -} +/** @type {function(...*):?} */ +var _ntohs = function() { + return (_ntohs = Module['asm']['ntohs']).apply(null, arguments); +}; -function runAndAbortIfError(func) { - try { - return func(); - } catch (e) { - abort(e); - } -} +/** @type {function(...*):?} */ +var _htonl = function() { + return (_htonl = Module['asm']['htonl']).apply(null, arguments); +}; -var Asyncify = { - instrumentWasmImports: function(imports) { - var importPatterns = [ /^_dlopen_js$/, /^invoke_i$/, /^invoke_ii$/, /^invoke_iii$/, /^invoke_iiii$/, /^invoke_iiiii$/, /^invoke_iiiiii$/, /^invoke_iiiiiii$/, /^invoke_iiiiiiii$/, /^invoke_iiiiiiiiii$/, /^invoke_v$/, /^invoke_vi$/, /^invoke_vii$/, /^invoke_viidii$/, /^invoke_viii$/, /^invoke_viiii$/, /^invoke_viiiii$/, /^invoke_viiiiii$/, /^invoke_viiiiiii$/, /^invoke_viiiiiiiii$/, /^js_open_process$/, /^js_popen_to_file$/, /^js_fd_read$/, /^js_module_onMessage$/, /^js_waitpid$/, /^wasm_poll_socket$/, /^wasm_shutdown$/, /^fd_sync$/, /^__wasi_fd_sync$/, /^__asyncjs__.*$/, /^emscripten_promise_await$/, /^emscripten_idb_load$/, /^emscripten_idb_store$/, /^emscripten_idb_delete$/, /^emscripten_idb_exists$/, /^emscripten_idb_load_blob$/, /^emscripten_idb_store_blob$/, /^emscripten_sleep$/, /^emscripten_wget_data$/, /^emscripten_scan_registers$/, /^emscripten_lazy_load_code$/, /^_load_secondary_module$/, /^emscripten_fiber_swap$/, /^SDL_Delay$/ ]; - for (var x in imports) { - (function(x) { - var original = imports[x]; - var sig = original.sig; - if (typeof original == "function") { - var isAsyncifyImport = original.isAsync || importPatterns.some((pattern => !!x.match(pattern))); - } - })(x); - } - }, - instrumentWasmExports: function(exports) { - var ret = {}; - for (var x in exports) { - (function(x) { - var original = exports[x]; - if (typeof original == "function") { - ret[x] = function() { - Asyncify.exportCallStack.push(x); - try { - return original.apply(null, arguments); - } finally { - if (!ABORT) { - var y = Asyncify.exportCallStack.pop(); - assert(y === x); - Asyncify.maybeStopUnwind(); - } - } - }; - } else { - ret[x] = original; - } - })(x); - } - return ret; - }, - State: { - Normal: 0, - Unwinding: 1, - Rewinding: 2, - Disabled: 3 - }, - state: 0, - StackSize: 4096, - currData: null, - handleSleepReturnValue: 0, - exportCallStack: [], - callStackNameToId: {}, - callStackIdToName: {}, - callStackId: 0, - asyncPromiseHandlers: null, - sleepCallbacks: [], - getCallStackId: function(funcName) { - var id = Asyncify.callStackNameToId[funcName]; - if (id === undefined) { - id = Asyncify.callStackId++; - Asyncify.callStackNameToId[funcName] = id; - Asyncify.callStackIdToName[id] = funcName; - } - return id; - }, - maybeStopUnwind: function() { - if (Asyncify.currData && Asyncify.state === Asyncify.State.Unwinding && Asyncify.exportCallStack.length === 0) { - Asyncify.state = Asyncify.State.Normal; - runtimeKeepalivePush(); - runAndAbortIfError(_asyncify_stop_unwind); - if (typeof Fibers != "undefined") { - Fibers.trampoline(); - } - } - }, - whenDone: function() { - return new Promise(((resolve, reject) => { - Asyncify.asyncPromiseHandlers = { - resolve: resolve, - reject: reject - }; - })); - }, - allocateData: function() { - var ptr = _malloc(12 + Asyncify.StackSize); - Asyncify.setDataHeader(ptr, ptr + 12, Asyncify.StackSize); - Asyncify.setDataRewindFunc(ptr); - return ptr; - }, - setDataHeader: function(ptr, stack, stackSize) { - HEAP32[ptr >> 2] = stack; - HEAP32[ptr + 4 >> 2] = stack + stackSize; - }, - setDataRewindFunc: function(ptr) { - var bottomOfCallStack = Asyncify.exportCallStack[0]; - var rewindId = Asyncify.getCallStackId(bottomOfCallStack); - HEAP32[ptr + 8 >> 2] = rewindId; - }, - getDataRewindFunc: function(ptr) { - var id = HEAP32[ptr + 8 >> 2]; - var name = Asyncify.callStackIdToName[id]; - var func = Module["asm"][name]; - return func; - }, - doRewind: function(ptr) { - var start = Asyncify.getDataRewindFunc(ptr); - runtimeKeepalivePop(); - return start(); - }, - handleSleep: function(startAsync) { - if (ABORT) return; - if (Asyncify.state === Asyncify.State.Normal) { - var reachedCallback = false; - var reachedAfterCallback = false; - startAsync(((handleSleepReturnValue = 0) => { - if (ABORT) return; - Asyncify.handleSleepReturnValue = handleSleepReturnValue; - reachedCallback = true; - if (!reachedAfterCallback) { - return; - } - Asyncify.state = Asyncify.State.Rewinding; - runAndAbortIfError((() => _asyncify_start_rewind(Asyncify.currData))); - if (typeof Browser != "undefined" && Browser.mainLoop.func) { - Browser.mainLoop.resume(); - } - var asyncWasmReturnValue, isError = false; - try { - asyncWasmReturnValue = Asyncify.doRewind(Asyncify.currData); - } catch (err) { - asyncWasmReturnValue = err; - isError = true; - } - var handled = false; - if (!Asyncify.currData) { - var asyncPromiseHandlers = Asyncify.asyncPromiseHandlers; - if (asyncPromiseHandlers) { - Asyncify.asyncPromiseHandlers = null; - (isError ? asyncPromiseHandlers.reject : asyncPromiseHandlers.resolve)(asyncWasmReturnValue); - handled = true; - } - } - if (isError && !handled) { - throw asyncWasmReturnValue; - } - })); - reachedAfterCallback = true; - if (!reachedCallback) { - Asyncify.state = Asyncify.State.Unwinding; - Asyncify.currData = Asyncify.allocateData(); - if (typeof Browser != "undefined" && Browser.mainLoop.func) { - Browser.mainLoop.pause(); - } - runAndAbortIfError((() => _asyncify_start_unwind(Asyncify.currData))); - } - } else if (Asyncify.state === Asyncify.State.Rewinding) { - Asyncify.state = Asyncify.State.Normal; - runAndAbortIfError(_asyncify_stop_rewind); - _free(Asyncify.currData); - Asyncify.currData = null; - Asyncify.sleepCallbacks.forEach((func => callUserCallback(func))); - } else { - abort(`invalid state: ${Asyncify.state}`); - } - return Asyncify.handleSleepReturnValue; - }, - handleAsync: function(startAsync) { - return Asyncify.handleSleep((wakeUp => { - startAsync().then(wakeUp); - })); - } +/** @type {function(...*):?} */ +var _wasm_sleep = Module['_wasm_sleep'] = function() { + return (_wasm_sleep = Module['_wasm_sleep'] = Module['asm']['wasm_sleep']).apply(null, arguments); }; -function getCFunc(ident) { - var func = Module["_" + ident]; - return func; -} +/** @type {function(...*):?} */ +var ___wrap_select = Module['___wrap_select'] = function() { + return (___wrap_select = Module['___wrap_select'] = Module['asm']['__wrap_select']).apply(null, arguments); +}; -var ccall = function(ident, returnType, argTypes, args, opts) { - var toC = { - "string": str => { - var ret = 0; - if (str !== null && str !== undefined && str !== 0) { - ret = stringToUTF8OnStack(str); - } - return ret; - }, - "array": arr => { - var ret = stackAlloc(arr.length); - writeArrayToMemory(arr, ret); - return ret; - } - }; - function convertReturnValue(ret) { - if (returnType === "string") { - return UTF8ToString(ret); - } - if (returnType === "boolean") return Boolean(ret); - return ret; - } - var func = getCFunc(ident); - var cArgs = []; - var stack = 0; - if (args) { - for (var i = 0; i < args.length; i++) { - var converter = toC[argTypes[i]]; - if (converter) { - if (stack === 0) stack = stackSave(); - cArgs[i] = converter(args[i]); - } else { - cArgs[i] = args[i]; - } - } - } - var previousAsync = Asyncify.currData; - var ret = func.apply(null, cArgs); - function onDone(ret) { - runtimeKeepalivePop(); - if (stack !== 0) stackRestore(stack); - return convertReturnValue(ret); - } - var asyncMode = opts && opts.async; - runtimeKeepalivePush(); - if (Asyncify.currData != previousAsync) { - return Asyncify.whenDone().then(onDone); - } - ret = onDone(ret); - if (asyncMode) return Promise.resolve(ret); - return ret; +/** @type {function(...*):?} */ +var _wasm_add_cli_arg = Module['_wasm_add_cli_arg'] = function() { + return (_wasm_add_cli_arg = Module['_wasm_add_cli_arg'] = Module['asm']['wasm_add_cli_arg']).apply(null, arguments); }; -var FSNode = function(parent, name, mode, rdev) { - if (!parent) { - parent = this; - } - this.parent = parent; - this.mount = parent.mount; - this.mounted = null; - this.id = FS.nextInode++; - this.name = name; - this.mode = mode; - this.node_ops = {}; - this.stream_ops = {}; - this.rdev = rdev; +/** @type {function(...*):?} */ +var _run_cli = Module['_run_cli'] = function() { + return (_run_cli = Module['_run_cli'] = Module['asm']['run_cli']).apply(null, arguments); }; -var readMode = 292 | 73; +/** @type {function(...*):?} */ +var _wasm_set_sapi_name = Module['_wasm_set_sapi_name'] = function() { + return (_wasm_set_sapi_name = Module['_wasm_set_sapi_name'] = Module['asm']['wasm_set_sapi_name']).apply(null, arguments); +}; -var writeMode = 146; +/** @type {function(...*):?} */ +var _wasm_set_phpini_path = Module['_wasm_set_phpini_path'] = function() { + return (_wasm_set_phpini_path = Module['_wasm_set_phpini_path'] = Module['asm']['wasm_set_phpini_path']).apply(null, arguments); +}; -Object.defineProperties(FSNode.prototype, { - read: { - get: function() { - return (this.mode & readMode) === readMode; - }, - set: function(val) { - val ? this.mode |= readMode : this.mode &= ~readMode; - } - }, - write: { - get: function() { - return (this.mode & writeMode) === writeMode; - }, - set: function(val) { - val ? this.mode |= writeMode : this.mode &= ~writeMode; - } - }, - isFolder: { - get: function() { - return FS.isDir(this.mode); - } - }, - isDevice: { - get: function() { - return FS.isChrdev(this.mode); - } - } -}); +/** @type {function(...*):?} */ +var _wasm_set_phpini_entries = Module['_wasm_set_phpini_entries'] = function() { + return (_wasm_set_phpini_entries = Module['_wasm_set_phpini_entries'] = Module['asm']['wasm_set_phpini_entries']).apply(null, arguments); +}; -FS.FSNode = FSNode; +/** @type {function(...*):?} */ +var _wasm_add_SERVER_entry = Module['_wasm_add_SERVER_entry'] = function() { + return (_wasm_add_SERVER_entry = Module['_wasm_add_SERVER_entry'] = Module['asm']['wasm_add_SERVER_entry']).apply(null, arguments); +}; -FS.createPreloadedFile = FS_createPreloadedFile; +/** @type {function(...*):?} */ +var _wasm_add_ENV_entry = Module['_wasm_add_ENV_entry'] = function() { + return (_wasm_add_ENV_entry = Module['_wasm_add_ENV_entry'] = Module['asm']['wasm_add_ENV_entry']).apply(null, arguments); +}; -FS.staticInit(); +/** @type {function(...*):?} */ +var _wasm_set_query_string = Module['_wasm_set_query_string'] = function() { + return (_wasm_set_query_string = Module['_wasm_set_query_string'] = Module['asm']['wasm_set_query_string']).apply(null, arguments); +}; -Module["FS_createPath"] = FS.createPath; +/** @type {function(...*):?} */ +var _wasm_set_path_translated = Module['_wasm_set_path_translated'] = function() { + return (_wasm_set_path_translated = Module['_wasm_set_path_translated'] = Module['asm']['wasm_set_path_translated']).apply(null, arguments); +}; -Module["FS_createDataFile"] = FS.createDataFile; +/** @type {function(...*):?} */ +var _wasm_set_skip_shebang = Module['_wasm_set_skip_shebang'] = function() { + return (_wasm_set_skip_shebang = Module['_wasm_set_skip_shebang'] = Module['asm']['wasm_set_skip_shebang']).apply(null, arguments); +}; -Module["FS_createPreloadedFile"] = FS.createPreloadedFile; +/** @type {function(...*):?} */ +var _wasm_set_request_uri = Module['_wasm_set_request_uri'] = function() { + return (_wasm_set_request_uri = Module['_wasm_set_request_uri'] = Module['asm']['wasm_set_request_uri']).apply(null, arguments); +}; -Module["FS_unlink"] = FS.unlink; +/** @type {function(...*):?} */ +var _wasm_set_request_method = Module['_wasm_set_request_method'] = function() { + return (_wasm_set_request_method = Module['_wasm_set_request_method'] = Module['asm']['wasm_set_request_method']).apply(null, arguments); +}; -Module["FS_createLazyFile"] = FS.createLazyFile; +/** @type {function(...*):?} */ +var _wasm_set_request_host = Module['_wasm_set_request_host'] = function() { + return (_wasm_set_request_host = Module['_wasm_set_request_host'] = Module['asm']['wasm_set_request_host']).apply(null, arguments); +}; -Module["FS_createDevice"] = FS.createDevice; +/** @type {function(...*):?} */ +var _wasm_set_content_type = Module['_wasm_set_content_type'] = function() { + return (_wasm_set_content_type = Module['_wasm_set_content_type'] = Module['asm']['wasm_set_content_type']).apply(null, arguments); +}; -if (ENVIRONMENT_IS_NODE) { - NODEFS.staticInit(); -} +/** @type {function(...*):?} */ +var _wasm_set_request_body = Module['_wasm_set_request_body'] = function() { + return (_wasm_set_request_body = Module['_wasm_set_request_body'] = Module['asm']['wasm_set_request_body']).apply(null, arguments); +}; -ERRNO_CODES = { - "EPERM": 63, - "ENOENT": 44, - "ESRCH": 71, - "EINTR": 27, - "EIO": 29, - "ENXIO": 60, - "E2BIG": 1, - "ENOEXEC": 45, - "EBADF": 8, - "ECHILD": 12, - "EAGAIN": 6, - "EWOULDBLOCK": 6, - "ENOMEM": 48, - "EACCES": 2, - "EFAULT": 21, - "ENOTBLK": 105, - "EBUSY": 10, - "EEXIST": 20, - "EXDEV": 75, - "ENODEV": 43, - "ENOTDIR": 54, - "EISDIR": 31, - "EINVAL": 28, - "ENFILE": 41, - "EMFILE": 33, - "ENOTTY": 59, - "ETXTBSY": 74, - "EFBIG": 22, - "ENOSPC": 51, - "ESPIPE": 70, - "EROFS": 69, - "EMLINK": 34, - "EPIPE": 64, - "EDOM": 18, - "ERANGE": 68, - "ENOMSG": 49, - "EIDRM": 24, - "ECHRNG": 106, - "EL2NSYNC": 156, - "EL3HLT": 107, - "EL3RST": 108, - "ELNRNG": 109, - "EUNATCH": 110, - "ENOCSI": 111, - "EL2HLT": 112, - "EDEADLK": 16, - "ENOLCK": 46, - "EBADE": 113, - "EBADR": 114, - "EXFULL": 115, - "ENOANO": 104, - "EBADRQC": 103, - "EBADSLT": 102, - "EDEADLOCK": 16, - "EBFONT": 101, - "ENOSTR": 100, - "ENODATA": 116, - "ETIME": 117, - "ENOSR": 118, - "ENONET": 119, - "ENOPKG": 120, - "EREMOTE": 121, - "ENOLINK": 47, - "EADV": 122, - "ESRMNT": 123, - "ECOMM": 124, - "EPROTO": 65, - "EMULTIHOP": 36, - "EDOTDOT": 125, - "EBADMSG": 9, - "ENOTUNIQ": 126, - "EBADFD": 127, - "EREMCHG": 128, - "ELIBACC": 129, - "ELIBBAD": 130, - "ELIBSCN": 131, - "ELIBMAX": 132, - "ELIBEXEC": 133, - "ENOSYS": 52, - "ENOTEMPTY": 55, - "ENAMETOOLONG": 37, - "ELOOP": 32, - "EOPNOTSUPP": 138, - "EPFNOSUPPORT": 139, - "ECONNRESET": 15, - "ENOBUFS": 42, - "EAFNOSUPPORT": 5, - "EPROTOTYPE": 67, - "ENOTSOCK": 57, - "ENOPROTOOPT": 50, - "ESHUTDOWN": 140, - "ECONNREFUSED": 14, - "EADDRINUSE": 3, - "ECONNABORTED": 13, - "ENETUNREACH": 40, - "ENETDOWN": 38, - "ETIMEDOUT": 73, - "EHOSTDOWN": 142, - "EHOSTUNREACH": 23, - "EINPROGRESS": 26, - "EALREADY": 7, - "EDESTADDRREQ": 17, - "EMSGSIZE": 35, - "EPROTONOSUPPORT": 66, - "ESOCKTNOSUPPORT": 137, - "EADDRNOTAVAIL": 4, - "ENETRESET": 39, - "EISCONN": 30, - "ENOTCONN": 53, - "ETOOMANYREFS": 141, - "EUSERS": 136, - "EDQUOT": 19, - "ESTALE": 72, - "ENOTSUP": 138, - "ENOMEDIUM": 148, - "EILSEQ": 25, - "EOVERFLOW": 61, - "ECANCELED": 11, - "ENOTRECOVERABLE": 56, - "EOWNERDEAD": 62, - "ESTRPIPE": 135 +/** @type {function(...*):?} */ +var _wasm_set_content_length = Module['_wasm_set_content_length'] = function() { + return (_wasm_set_content_length = Module['_wasm_set_content_length'] = Module['asm']['wasm_set_content_length']).apply(null, arguments); }; -PHPWASM.init(); +/** @type {function(...*):?} */ +var _wasm_set_cookies = Module['_wasm_set_cookies'] = function() { + return (_wasm_set_cookies = Module['_wasm_set_cookies'] = Module['asm']['wasm_set_cookies']).apply(null, arguments); +}; -var wasmImports = { - m: ___assert_fail, - _a: ___call_sighandler, - Za: ___syscall__newselect, - Ya: ___syscall_accept4, - Xa: ___syscall_bind, - Wa: ___syscall_chdir, - T: ___syscall_chmod, - Va: ___syscall_connect, - Ua: ___syscall_dup, - Ta: ___syscall_dup3, - Sa: ___syscall_faccessat, - ba: ___syscall_fallocate, - Ra: ___syscall_fchmod, - Qa: ___syscall_fchown32, - S: ___syscall_fchownat, - o: ___syscall_fcntl64, - Pa: ___syscall_fdatasync, - Oa: ___syscall_fstat64, - aa: ___syscall_ftruncate64, - Na: ___syscall_getcwd, - Ma: ___syscall_getdents64, - La: ___syscall_getpeername, - Ka: ___syscall_getsockname, - Ja: ___syscall_getsockopt, - R: ___syscall_ioctl, - Ia: ___syscall_listen, - Ha: ___syscall_lstat64, - Ga: ___syscall_mkdirat, - Fa: ___syscall_newfstatat, - x: ___syscall_openat, - Ea: ___syscall_pipe, - Da: ___syscall_poll, - Ca: ___syscall_readlinkat, - Ba: ___syscall_recvfrom, - Aa: ___syscall_renameat, - Q: ___syscall_rmdir, - za: ___syscall_sendto, - P: ___syscall_socket, - ya: ___syscall_stat64, - xa: ___syscall_statfs64, - wa: ___syscall_symlink, - D: ___syscall_unlinkat, - va: ___syscall_utimensat, - ra: __emscripten_get_now_is_monotonic, - qa: __emscripten_throw_longjmp, - _: __gmtime_js, - Z: __localtime_js, - Y: __mktime_js, - X: __mmap_js, - W: __munmap_js, - M: __setitimer_js, - pa: __tzset_js, - f: _abort, - B: _emscripten_date_now, - oa: _emscripten_get_heap_max, - v: _emscripten_get_now, - na: _emscripten_memcpy_big, - ma: _emscripten_resize_heap, - L: _emscripten_sleep, - ua: _environ_get, - ta: _environ_sizes_get, - p: _exit, - s: _fd_close, - O: _fd_fdstat_get, - N: _fd_read, - $: _fd_seek, - C: _fd_write, - la: _getaddrinfo, - K: _gethostbyaddr, - J: _gethostbyname_r, - ka: _getloadavg, - I: _getnameinfo, - ja: _getprotobyname, - ia: _getprotobynumber, - i: invoke_i, - c: invoke_ii, - b: invoke_iii, - g: invoke_iiii, - h: invoke_iiiii, - u: invoke_iiiiii, - r: invoke_iiiiiii, - w: invoke_iiiiiiii, - H: invoke_iiiiiiiiii, - e: invoke_v, - a: invoke_vi, - d: invoke_vii, - A: invoke_viidii, - l: invoke_viii, - j: invoke_viiii, - n: invoke_viiiii, - k: invoke_viiiiii, - ha: invoke_viiiiiii, - z: invoke_viiiiiiiii, - G: _js_create_input_device, - ga: _js_fd_read, - fa: _js_module_onMessage, - F: _js_open_process, - ea: _js_popen_to_file, - da: _js_process_status, - ca: _js_waitpid, - sa: _proc_exit, - E: _strftime, - V: _strptime, - t: _wasm_close, - y: _wasm_poll_socket, - q: _wasm_setsockopt, - U: _wasm_shutdown +/** @type {function(...*):?} */ +var _wasm_set_php_code = Module['_wasm_set_php_code'] = function() { + return (_wasm_set_php_code = Module['_wasm_set_php_code'] = Module['asm']['wasm_set_php_code']).apply(null, arguments); }; -var asm = createWasm(); +/** @type {function(...*):?} */ +var _wasm_set_request_port = Module['_wasm_set_request_port'] = function() { + return (_wasm_set_request_port = Module['_wasm_set_request_port'] = Module['asm']['wasm_set_request_port']).apply(null, arguments); +}; -var ___wasm_call_ctors = function() { - return (___wasm_call_ctors = Module["asm"]["ab"]).apply(null, arguments); +/** @type {function(...*):?} */ +var _wasm_sapi_request_shutdown = Module['_wasm_sapi_request_shutdown'] = function() { + return (_wasm_sapi_request_shutdown = Module['_wasm_sapi_request_shutdown'] = Module['asm']['wasm_sapi_request_shutdown']).apply(null, arguments); }; -var _free = function() { - return (_free = Module["asm"]["bb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var _wasm_sapi_handle_request = Module['_wasm_sapi_handle_request'] = function() { + return (_wasm_sapi_handle_request = Module['_wasm_sapi_handle_request'] = Module['asm']['wasm_sapi_handle_request']).apply(null, arguments); }; -var _memcpy = function() { - return (_memcpy = Module["asm"]["cb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var _php_wasm_init = Module['_php_wasm_init'] = function() { + return (_php_wasm_init = Module['_php_wasm_init'] = Module['asm']['php_wasm_init']).apply(null, arguments); }; -var _malloc = function() { - return (_malloc = Module["asm"]["eb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var ___funcs_on_exit = function() { + return (___funcs_on_exit = Module['asm']['__funcs_on_exit']).apply(null, arguments); }; -var setTempRet0 = function() { - return (setTempRet0 = Module["asm"]["fb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var _emscripten_builtin_memalign = function() { + return (_emscripten_builtin_memalign = Module['asm']['emscripten_builtin_memalign']).apply(null, arguments); }; -var ___errno_location = function() { - return (___errno_location = Module["asm"]["gb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var __emscripten_timeout = function() { + return (__emscripten_timeout = Module['asm']['_emscripten_timeout']).apply(null, arguments); }; -var _wasm_read = Module["_wasm_read"] = function() { - return (_wasm_read = Module["_wasm_read"] = Module["asm"]["hb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var _setThrew = function() { + return (_setThrew = Module['asm']['setThrew']).apply(null, arguments); }; -var _fflush = Module["_fflush"] = function() { - return (_fflush = Module["_fflush"] = Module["asm"]["ib"]).apply(null, arguments); +/** @type {function(...*):?} */ +var _emscripten_stack_set_limits = function() { + return (_emscripten_stack_set_limits = Module['asm']['emscripten_stack_set_limits']).apply(null, arguments); }; -var _wasm_popen = Module["_wasm_popen"] = function() { - return (_wasm_popen = Module["_wasm_popen"] = Module["asm"]["jb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var _emscripten_stack_get_base = function() { + return (_emscripten_stack_get_base = Module['asm']['emscripten_stack_get_base']).apply(null, arguments); }; -var _wasm_php_exec = Module["_wasm_php_exec"] = function() { - return (_wasm_php_exec = Module["_wasm_php_exec"] = Module["asm"]["kb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var _emscripten_stack_get_end = function() { + return (_emscripten_stack_get_end = Module['asm']['emscripten_stack_get_end']).apply(null, arguments); }; -var _php_pollfd_for = Module["_php_pollfd_for"] = function() { - return (_php_pollfd_for = Module["_php_pollfd_for"] = Module["asm"]["lb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var stackSave = function() { + return (stackSave = Module['asm']['stackSave']).apply(null, arguments); }; -var _htons = function() { - return (_htons = Module["asm"]["mb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var stackRestore = function() { + return (stackRestore = Module['asm']['stackRestore']).apply(null, arguments); }; -var _ntohs = function() { - return (_ntohs = Module["asm"]["nb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var stackAlloc = function() { + return (stackAlloc = Module['asm']['stackAlloc']).apply(null, arguments); }; -var _htonl = function() { - return (_htonl = Module["asm"]["ob"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiii = Module['dynCall_iiii'] = function() { + return (dynCall_iiii = Module['dynCall_iiii'] = Module['asm']['dynCall_iiii']).apply(null, arguments); }; -var _wasm_sleep = Module["_wasm_sleep"] = function() { - return (_wasm_sleep = Module["_wasm_sleep"] = Module["asm"]["pb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_ii = Module['dynCall_ii'] = function() { + return (dynCall_ii = Module['dynCall_ii'] = Module['asm']['dynCall_ii']).apply(null, arguments); }; -var _wasm_select = Module["_wasm_select"] = function() { - return (_wasm_select = Module["_wasm_select"] = Module["asm"]["qb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_vi = Module['dynCall_vi'] = function() { + return (dynCall_vi = Module['dynCall_vi'] = Module['asm']['dynCall_vi']).apply(null, arguments); }; -var _wasm_add_cli_arg = Module["_wasm_add_cli_arg"] = function() { - return (_wasm_add_cli_arg = Module["_wasm_add_cli_arg"] = Module["asm"]["rb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_vii = Module['dynCall_vii'] = function() { + return (dynCall_vii = Module['dynCall_vii'] = Module['asm']['dynCall_vii']).apply(null, arguments); }; -var _run_cli = Module["_run_cli"] = function() { - return (_run_cli = Module["_run_cli"] = Module["asm"]["sb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_viiiii = Module['dynCall_viiiii'] = function() { + return (dynCall_viiiii = Module['dynCall_viiiii'] = Module['asm']['dynCall_viiiii']).apply(null, arguments); }; -var _wasm_set_sapi_name = Module["_wasm_set_sapi_name"] = function() { - return (_wasm_set_sapi_name = Module["_wasm_set_sapi_name"] = Module["asm"]["tb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iii = Module['dynCall_iii'] = function() { + return (dynCall_iii = Module['dynCall_iii'] = Module['asm']['dynCall_iii']).apply(null, arguments); }; -var _wasm_set_phpini_path = Module["_wasm_set_phpini_path"] = function() { - return (_wasm_set_phpini_path = Module["_wasm_set_phpini_path"] = Module["asm"]["ub"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiiii = Module['dynCall_iiiii'] = function() { + return (dynCall_iiiii = Module['dynCall_iiiii'] = Module['asm']['dynCall_iiiii']).apply(null, arguments); }; -var _wasm_set_phpini_entries = Module["_wasm_set_phpini_entries"] = function() { - return (_wasm_set_phpini_entries = Module["_wasm_set_phpini_entries"] = Module["asm"]["vb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiiiiii = Module['dynCall_iiiiiii'] = function() { + return (dynCall_iiiiiii = Module['dynCall_iiiiiii'] = Module['asm']['dynCall_iiiiiii']).apply(null, arguments); }; -var _wasm_add_SERVER_entry = Module["_wasm_add_SERVER_entry"] = function() { - return (_wasm_add_SERVER_entry = Module["_wasm_add_SERVER_entry"] = Module["asm"]["wb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiiiii = Module['dynCall_iiiiii'] = function() { + return (dynCall_iiiiii = Module['dynCall_iiiiii'] = Module['asm']['dynCall_iiiiii']).apply(null, arguments); }; -var _wasm_add_ENV_entry = Module["_wasm_add_ENV_entry"] = function() { - return (_wasm_add_ENV_entry = Module["_wasm_add_ENV_entry"] = Module["asm"]["xb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_i = Module['dynCall_i'] = function() { + return (dynCall_i = Module['dynCall_i'] = Module['asm']['dynCall_i']).apply(null, arguments); }; -var _wasm_set_query_string = Module["_wasm_set_query_string"] = function() { - return (_wasm_set_query_string = Module["_wasm_set_query_string"] = Module["asm"]["yb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_viii = Module['dynCall_viii'] = function() { + return (dynCall_viii = Module['dynCall_viii'] = Module['asm']['dynCall_viii']).apply(null, arguments); }; -var _wasm_set_path_translated = Module["_wasm_set_path_translated"] = function() { - return (_wasm_set_path_translated = Module["_wasm_set_path_translated"] = Module["asm"]["zb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_viiii = Module['dynCall_viiii'] = function() { + return (dynCall_viiii = Module['dynCall_viiii'] = Module['asm']['dynCall_viiii']).apply(null, arguments); }; -var _wasm_set_skip_shebang = Module["_wasm_set_skip_shebang"] = function() { - return (_wasm_set_skip_shebang = Module["_wasm_set_skip_shebang"] = Module["asm"]["Ab"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_viiiiiiii = Module['dynCall_viiiiiiii'] = function() { + return (dynCall_viiiiiiii = Module['dynCall_viiiiiiii'] = Module['asm']['dynCall_viiiiiiii']).apply(null, arguments); }; -var _wasm_set_request_uri = Module["_wasm_set_request_uri"] = function() { - return (_wasm_set_request_uri = Module["_wasm_set_request_uri"] = Module["asm"]["Bb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_v = Module['dynCall_v'] = function() { + return (dynCall_v = Module['dynCall_v'] = Module['asm']['dynCall_v']).apply(null, arguments); }; -var _wasm_set_request_method = Module["_wasm_set_request_method"] = function() { - return (_wasm_set_request_method = Module["_wasm_set_request_method"] = Module["asm"]["Cb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_viiiiiiiii = Module['dynCall_viiiiiiiii'] = function() { + return (dynCall_viiiiiiiii = Module['dynCall_viiiiiiiii'] = Module['asm']['dynCall_viiiiiiiii']).apply(null, arguments); }; -var _wasm_set_request_host = Module["_wasm_set_request_host"] = function() { - return (_wasm_set_request_host = Module["_wasm_set_request_host"] = Module["asm"]["Db"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_viiiiiii = Module['dynCall_viiiiiii'] = function() { + return (dynCall_viiiiiii = Module['dynCall_viiiiiii'] = Module['asm']['dynCall_viiiiiii']).apply(null, arguments); }; -var _wasm_set_content_type = Module["_wasm_set_content_type"] = function() { - return (_wasm_set_content_type = Module["_wasm_set_content_type"] = Module["asm"]["Eb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_viiiiii = Module['dynCall_viiiiii'] = function() { + return (dynCall_viiiiii = Module['dynCall_viiiiii'] = Module['asm']['dynCall_viiiiii']).apply(null, arguments); }; -var _wasm_set_request_body = Module["_wasm_set_request_body"] = function() { - return (_wasm_set_request_body = Module["_wasm_set_request_body"] = Module["asm"]["Fb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiiiiiii = Module['dynCall_iiiiiiii'] = function() { + return (dynCall_iiiiiiii = Module['dynCall_iiiiiiii'] = Module['asm']['dynCall_iiiiiiii']).apply(null, arguments); }; -var _wasm_set_content_length = Module["_wasm_set_content_length"] = function() { - return (_wasm_set_content_length = Module["_wasm_set_content_length"] = Module["asm"]["Gb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiid = Module['dynCall_iiid'] = function() { + return (dynCall_iiid = Module['dynCall_iiid'] = Module['asm']['dynCall_iiid']).apply(null, arguments); }; -var _wasm_set_cookies = Module["_wasm_set_cookies"] = function() { - return (_wasm_set_cookies = Module["_wasm_set_cookies"] = Module["asm"]["Hb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiiiiiiii = Module['dynCall_iiiiiiiii'] = function() { + return (dynCall_iiiiiiiii = Module['dynCall_iiiiiiiii'] = Module['asm']['dynCall_iiiiiiiii']).apply(null, arguments); }; -var _wasm_set_php_code = Module["_wasm_set_php_code"] = function() { - return (_wasm_set_php_code = Module["_wasm_set_php_code"] = Module["asm"]["Ib"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiiiiiiiii = Module['dynCall_iiiiiiiiii'] = function() { + return (dynCall_iiiiiiiiii = Module['dynCall_iiiiiiiiii'] = Module['asm']['dynCall_iiiiiiiiii']).apply(null, arguments); }; -var _wasm_set_request_port = Module["_wasm_set_request_port"] = function() { - return (_wasm_set_request_port = Module["_wasm_set_request_port"] = Module["asm"]["Jb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiiij = Module['dynCall_iiiij'] = function() { + return (dynCall_iiiij = Module['dynCall_iiiij'] = Module['asm']['dynCall_iiiij']).apply(null, arguments); }; -var _wasm_sapi_request_shutdown = Module["_wasm_sapi_request_shutdown"] = function() { - return (_wasm_sapi_request_shutdown = Module["_wasm_sapi_request_shutdown"] = Module["asm"]["Kb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_vijii = Module['dynCall_vijii'] = function() { + return (dynCall_vijii = Module['dynCall_vijii'] = Module['asm']['dynCall_vijii']).apply(null, arguments); }; -var _wasm_sapi_handle_request = Module["_wasm_sapi_handle_request"] = function() { - return (_wasm_sapi_handle_request = Module["_wasm_sapi_handle_request"] = Module["asm"]["Lb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iijj = Module['dynCall_iijj'] = function() { + return (dynCall_iijj = Module['dynCall_iijj'] = Module['asm']['dynCall_iijj']).apply(null, arguments); }; -var _php_wasm_init = Module["_php_wasm_init"] = function() { - return (_php_wasm_init = Module["_php_wasm_init"] = Module["asm"]["Mb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iij = Module['dynCall_iij'] = function() { + return (dynCall_iij = Module['dynCall_iij'] = Module['asm']['dynCall_iij']).apply(null, arguments); }; -var ___funcs_on_exit = function() { - return (___funcs_on_exit = Module["asm"]["Nb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iijii = Module['dynCall_iijii'] = function() { + return (dynCall_iijii = Module['dynCall_iijii'] = Module['asm']['dynCall_iijii']).apply(null, arguments); }; -var _emscripten_builtin_memalign = function() { - return (_emscripten_builtin_memalign = Module["asm"]["Ob"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiji = Module['dynCall_iiji'] = function() { + return (dynCall_iiji = Module['dynCall_iiji'] = Module['asm']['dynCall_iiji']).apply(null, arguments); }; -var __emscripten_timeout = function() { - return (__emscripten_timeout = Module["asm"]["Pb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiiiiij = Module['dynCall_iiiiiij'] = function() { + return (dynCall_iiiiiij = Module['dynCall_iiiiiij'] = Module['asm']['dynCall_iiiiiij']).apply(null, arguments); }; -var _setThrew = function() { - return (_setThrew = Module["asm"]["Qb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiij = Module['dynCall_iiij'] = function() { + return (dynCall_iiij = Module['dynCall_iiij'] = Module['asm']['dynCall_iiij']).apply(null, arguments); }; -var _emscripten_stack_set_limits = function() { - return (_emscripten_stack_set_limits = Module["asm"]["emscripten_stack_set_limits"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_dii = Module['dynCall_dii'] = function() { + return (dynCall_dii = Module['dynCall_dii'] = Module['asm']['dynCall_dii']).apply(null, arguments); }; -var _emscripten_stack_get_base = function() { - return (_emscripten_stack_get_base = Module["asm"]["emscripten_stack_get_base"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_jii = Module['dynCall_jii'] = function() { + return (dynCall_jii = Module['dynCall_jii'] = Module['asm']['dynCall_jii']).apply(null, arguments); }; -var _emscripten_stack_get_end = function() { - return (_emscripten_stack_get_end = Module["asm"]["emscripten_stack_get_end"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_ji = Module['dynCall_ji'] = function() { + return (dynCall_ji = Module['dynCall_ji'] = Module['asm']['dynCall_ji']).apply(null, arguments); }; -var stackSave = function() { - return (stackSave = Module["asm"]["Rb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_vid = Module['dynCall_vid'] = function() { + return (dynCall_vid = Module['dynCall_vid'] = Module['asm']['dynCall_vid']).apply(null, arguments); }; -var stackRestore = function() { - return (stackRestore = Module["asm"]["Sb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_vij = Module['dynCall_vij'] = function() { + return (dynCall_vij = Module['dynCall_vij'] = Module['asm']['dynCall_vij']).apply(null, arguments); }; -var stackAlloc = function() { - return (stackAlloc = Module["asm"]["Tb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_di = Module['dynCall_di'] = function() { + return (dynCall_di = Module['dynCall_di'] = Module['asm']['dynCall_di']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiiiijii = Module['dynCall_iiiiijii'] = function() { + return (dynCall_iiiiijii = Module['dynCall_iiiiijii'] = Module['asm']['dynCall_iiiiijii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_j = Module['dynCall_j'] = function() { + return (dynCall_j = Module['dynCall_j'] = Module['asm']['dynCall_j']).apply(null, arguments); }; -var dynCall_iiii = Module["dynCall_iiii"] = function() { - return (dynCall_iiii = Module["dynCall_iiii"] = Module["asm"]["Ub"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_jj = Module['dynCall_jj'] = function() { + return (dynCall_jj = Module['dynCall_jj'] = Module['asm']['dynCall_jj']).apply(null, arguments); }; -var dynCall_ii = Module["dynCall_ii"] = function() { - return (dynCall_ii = Module["dynCall_ii"] = Module["asm"]["Vb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_jiij = Module['dynCall_jiij'] = function() { + return (dynCall_jiij = Module['dynCall_jiij'] = Module['asm']['dynCall_jiij']).apply(null, arguments); }; -var dynCall_vi = Module["dynCall_vi"] = function() { - return (dynCall_vi = Module["dynCall_vi"] = Module["asm"]["Wb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiiiji = Module['dynCall_iiiiji'] = function() { + return (dynCall_iiiiji = Module['dynCall_iiiiji'] = Module['asm']['dynCall_iiiiji']).apply(null, arguments); }; -var dynCall_vii = Module["dynCall_vii"] = function() { - return (dynCall_vii = Module["dynCall_vii"] = Module["asm"]["Xb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiiijii = Module['dynCall_iiiijii'] = function() { + return (dynCall_iiiijii = Module['dynCall_iiiijii'] = Module['asm']['dynCall_iiiijii']).apply(null, arguments); }; -var dynCall_viiiii = Module["dynCall_viiiii"] = function() { - return (dynCall_viiiii = Module["dynCall_viiiii"] = Module["asm"]["Yb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_ij = Module['dynCall_ij'] = function() { + return (dynCall_ij = Module['dynCall_ij'] = Module['asm']['dynCall_ij']).apply(null, arguments); }; -var dynCall_iii = Module["dynCall_iii"] = function() { - return (dynCall_iii = Module["dynCall_iii"] = Module["asm"]["Zb"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_viiji = Module['dynCall_viiji'] = function() { + return (dynCall_viiji = Module['dynCall_viiji'] = Module['asm']['dynCall_viiji']).apply(null, arguments); }; -var dynCall_iiiii = Module["dynCall_iiiii"] = function() { - return (dynCall_iiiii = Module["dynCall_iiiii"] = Module["asm"]["_b"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_viijii = Module['dynCall_viijii'] = function() { + return (dynCall_viijii = Module['dynCall_viijii'] = Module['asm']['dynCall_viijii']).apply(null, arguments); }; -var dynCall_iiiiiii = Module["dynCall_iiiiiii"] = function() { - return (dynCall_iiiiiii = Module["dynCall_iiiiiii"] = Module["asm"]["$b"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiiiiiiiiii = Module['dynCall_iiiiiiiiiii'] = function() { + return (dynCall_iiiiiiiiiii = Module['dynCall_iiiiiiiiiii'] = Module['asm']['dynCall_iiiiiiiiiii']).apply(null, arguments); }; -var dynCall_iiiiii = Module["dynCall_iiiiii"] = function() { - return (dynCall_iiiiii = Module["dynCall_iiiiii"] = Module["asm"]["ac"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiiijji = Module['dynCall_iiiijji'] = function() { + return (dynCall_iiiijji = Module['dynCall_iiiijji'] = Module['asm']['dynCall_iiiijji']).apply(null, arguments); }; -var dynCall_i = Module["dynCall_i"] = function() { - return (dynCall_i = Module["dynCall_i"] = Module["asm"]["bc"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_dd = Module['dynCall_dd'] = function() { + return (dynCall_dd = Module['dynCall_dd'] = Module['asm']['dynCall_dd']).apply(null, arguments); }; -var dynCall_viii = Module["dynCall_viii"] = function() { - return (dynCall_viii = Module["dynCall_viii"] = Module["asm"]["cc"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_ddd = Module['dynCall_ddd'] = function() { + return (dynCall_ddd = Module['dynCall_ddd'] = Module['asm']['dynCall_ddd']).apply(null, arguments); }; -var dynCall_viiii = Module["dynCall_viiii"] = function() { - return (dynCall_viiii = Module["dynCall_viiii"] = Module["asm"]["dc"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iidddd = Module['dynCall_iidddd'] = function() { + return (dynCall_iidddd = Module['dynCall_iidddd'] = Module['asm']['dynCall_iidddd']).apply(null, arguments); }; -var dynCall_v = Module["dynCall_v"] = function() { - return (dynCall_v = Module["dynCall_v"] = Module["asm"]["ec"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiiiiiiiiiii = Module['dynCall_iiiiiiiiiiii'] = function() { + return (dynCall_iiiiiiiiiiii = Module['dynCall_iiiiiiiiiiii'] = Module['asm']['dynCall_iiiiiiiiiiii']).apply(null, arguments); }; -var dynCall_viiiiiiiii = Module["dynCall_viiiiiiiii"] = function() { - return (dynCall_viiiiiiiii = Module["dynCall_viiiiiiiii"] = Module["asm"]["fc"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_viidii = Module['dynCall_viidii'] = function() { + return (dynCall_viidii = Module['dynCall_viidii'] = Module['asm']['dynCall_viidii']).apply(null, arguments); }; -var dynCall_viiiiiii = Module["dynCall_viiiiiii"] = function() { - return (dynCall_viiiiiii = Module["dynCall_viiiiiii"] = Module["asm"]["gc"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_jiiji = Module['dynCall_jiiji'] = function() { + return (dynCall_jiiji = Module['dynCall_jiiji'] = Module['asm']['dynCall_jiiji']).apply(null, arguments); }; -var dynCall_viiiiii = Module["dynCall_viiiiii"] = function() { - return (dynCall_viiiiii = Module["dynCall_viiiiii"] = Module["asm"]["hc"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_jiiiji = Module['dynCall_jiiiji'] = function() { + return (dynCall_jiiiji = Module['dynCall_jiiiji'] = Module['asm']['dynCall_jiiiji']).apply(null, arguments); }; -var dynCall_iiiiiiii = Module["dynCall_iiiiiiii"] = function() { - return (dynCall_iiiiiiii = Module["dynCall_iiiiiiii"] = Module["asm"]["ic"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iiiji = Module['dynCall_iiiji'] = function() { + return (dynCall_iiiji = Module['dynCall_iiiji'] = Module['asm']['dynCall_iiiji']).apply(null, arguments); }; -var dynCall_iiiiiiiiii = Module["dynCall_iiiiiiiiii"] = function() { - return (dynCall_iiiiiiiiii = Module["dynCall_iiiiiiiiii"] = Module["asm"]["jc"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_jiji = Module['dynCall_jiji'] = function() { + return (dynCall_jiji = Module['dynCall_jiji'] = Module['asm']['dynCall_jiji']).apply(null, arguments); }; -var dynCall_viidii = Module["dynCall_viidii"] = function() { - return (dynCall_viidii = Module["dynCall_viidii"] = Module["asm"]["kc"]).apply(null, arguments); +/** @type {function(...*):?} */ +var dynCall_iidiiii = Module['dynCall_iidiiii'] = function() { + return (dynCall_iidiiii = Module['dynCall_iidiiii'] = Module['asm']['dynCall_iidiiii']).apply(null, arguments); }; +/** @type {function(...*):?} */ var _asyncify_start_unwind = function() { - return (_asyncify_start_unwind = Module["asm"]["lc"]).apply(null, arguments); + return (_asyncify_start_unwind = Module['asm']['asyncify_start_unwind']).apply(null, arguments); }; +/** @type {function(...*):?} */ var _asyncify_stop_unwind = function() { - return (_asyncify_stop_unwind = Module["asm"]["mc"]).apply(null, arguments); + return (_asyncify_stop_unwind = Module['asm']['asyncify_stop_unwind']).apply(null, arguments); }; +/** @type {function(...*):?} */ var _asyncify_start_rewind = function() { - return (_asyncify_start_rewind = Module["asm"]["nc"]).apply(null, arguments); + return (_asyncify_start_rewind = Module['asm']['asyncify_start_rewind']).apply(null, arguments); }; +/** @type {function(...*):?} */ var _asyncify_stop_rewind = function() { - return (_asyncify_stop_rewind = Module["asm"]["oc"]).apply(null, arguments); + return (_asyncify_stop_rewind = Module['asm']['asyncify_stop_rewind']).apply(null, arguments); }; -function invoke_iiiiiii(index, a1, a2, a3, a4, a5, a6) { - var sp = stackSave(); - try { - return dynCall_iiiiiii(index, a1, a2, a3, a4, a5, a6); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } + +function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6) { + var sp = stackSave(); + try { + return dynCall_iiiiiii(index,a1,a2,a3,a4,a5,a6); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_vi(index, a1) { - var sp = stackSave(); - try { - dynCall_vi(index, a1); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_vi(index,a1) { + var sp = stackSave(); + try { + dynCall_vi(index,a1); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_iii(index, a1, a2) { - var sp = stackSave(); - try { - return dynCall_iii(index, a1, a2); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_iii(index,a1,a2) { + var sp = stackSave(); + try { + return dynCall_iii(index,a1,a2); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_iiiii(index, a1, a2, a3, a4) { - var sp = stackSave(); - try { - return dynCall_iiiii(index, a1, a2, a3, a4); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_iiiii(index,a1,a2,a3,a4) { + var sp = stackSave(); + try { + return dynCall_iiiii(index,a1,a2,a3,a4); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_ii(index, a1) { - var sp = stackSave(); - try { - return dynCall_ii(index, a1); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_ii(index,a1) { + var sp = stackSave(); + try { + return dynCall_ii(index,a1); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_iiii(index, a1, a2, a3) { - var sp = stackSave(); - try { - return dynCall_iiii(index, a1, a2, a3); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_iiii(index,a1,a2,a3) { + var sp = stackSave(); + try { + return dynCall_iiii(index,a1,a2,a3); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_viiii(index, a1, a2, a3, a4) { - var sp = stackSave(); - try { - dynCall_viiii(index, a1, a2, a3, a4); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_viiii(index,a1,a2,a3,a4) { + var sp = stackSave(); + try { + dynCall_viiii(index,a1,a2,a3,a4); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_iiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9) { - var sp = stackSave(); - try { - return dynCall_iiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9) { + var sp = stackSave(); + try { + return dynCall_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_vii(index, a1, a2) { - var sp = stackSave(); - try { - dynCall_vii(index, a1, a2); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_vii(index,a1,a2) { + var sp = stackSave(); + try { + dynCall_vii(index,a1,a2); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } function invoke_i(index) { - var sp = stackSave(); - try { - return dynCall_i(index); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } + var sp = stackSave(); + try { + return dynCall_i(index); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_viii(index, a1, a2, a3) { - var sp = stackSave(); - try { - dynCall_viii(index, a1, a2, a3); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_viii(index,a1,a2,a3) { + var sp = stackSave(); + try { + dynCall_viii(index,a1,a2,a3); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } function invoke_v(index) { - var sp = stackSave(); - try { - dynCall_v(index); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } + var sp = stackSave(); + try { + dynCall_v(index); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_viiiiii(index, a1, a2, a3, a4, a5, a6) { - var sp = stackSave(); - try { - dynCall_viiiiii(index, a1, a2, a3, a4, a5, a6); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6) { + var sp = stackSave(); + try { + dynCall_viiiiii(index,a1,a2,a3,a4,a5,a6); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_viiiii(index, a1, a2, a3, a4, a5) { - var sp = stackSave(); - try { - dynCall_viiiii(index, a1, a2, a3, a4, a5); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_viiiii(index,a1,a2,a3,a4,a5) { + var sp = stackSave(); + try { + dynCall_viiiii(index,a1,a2,a3,a4,a5); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_viidii(index, a1, a2, a3, a4, a5) { - var sp = stackSave(); - try { - dynCall_viidii(index, a1, a2, a3, a4, a5); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_viidii(index,a1,a2,a3,a4,a5) { + var sp = stackSave(); + try { + dynCall_viidii(index,a1,a2,a3,a4,a5); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_iiiiii(index, a1, a2, a3, a4, a5) { - var sp = stackSave(); - try { - return dynCall_iiiiii(index, a1, a2, a3, a4, a5); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_iiiiii(index,a1,a2,a3,a4,a5) { + var sp = stackSave(); + try { + return dynCall_iiiiii(index,a1,a2,a3,a4,a5); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_viiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9) { - var sp = stackSave(); - try { - dynCall_viiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9) { + var sp = stackSave(); + try { + dynCall_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_iiiiiiii(index, a1, a2, a3, a4, a5, a6, a7) { - var sp = stackSave(); - try { - return dynCall_iiiiiiii(index, a1, a2, a3, a4, a5, a6, a7); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7) { + var sp = stackSave(); + try { + return dynCall_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -function invoke_viiiiiii(index, a1, a2, a3, a4, a5, a6, a7) { - var sp = stackSave(); - try { - dynCall_viiiiiii(index, a1, a2, a3, a4, a5, a6, a7); - } catch (e) { - stackRestore(sp); - if (e !== e + 0) throw e; - _setThrew(1, 0); - } +function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7) { + var sp = stackSave(); + try { + dynCall_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } } -Module["addRunDependency"] = addRunDependency; - -Module["removeRunDependency"] = removeRunDependency; - -Module["FS_createPath"] = FS.createPath; +function invoke_jii(index,a1,a2) { + var sp = stackSave(); + try { + return dynCall_jii(index,a1,a2); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} -Module["FS_createDataFile"] = FS.createDataFile; -Module["FS_createLazyFile"] = FS.createLazyFile; +// include: postamble.js +// === Auto-generated postamble setup entry stuff === -Module["FS_createDevice"] = FS.createDevice; +// include: base64Utils.js +// Converts a string of base64 into a byte array. +// Throws error on invalid input. +function intArrayFromBase64(s) { + if (typeof ENVIRONMENT_IS_NODE != 'undefined' && ENVIRONMENT_IS_NODE) { + var buf = Buffer.from(s, 'base64'); + return new Uint8Array(buf['buffer'], buf['byteOffset'], buf['byteLength']); + } -Module["FS_unlink"] = FS.unlink; + try { + var decoded = atob(s); + var bytes = new Uint8Array(decoded.length); + for (var i = 0 ; i < decoded.length ; ++i) { + bytes[i] = decoded.charCodeAt(i); + } + return bytes; + } catch (_) { + throw new Error('Converting base64 string to bytes failed.'); + } +} -Module["ccall"] = ccall; +// If filename is a base64 data URI, parses and returns data (Buffer on node, +// Uint8Array otherwise). If filename is not a base64 data URI, returns undefined. +function tryParseAsDataURI(filename) { + if (!isDataURI(filename)) { + return; + } -Module["FS_createPreloadedFile"] = FS.createPreloadedFile; + return intArrayFromBase64(filename.slice(dataURIPrefix.length)); +} +// end include: base64Utils.js +Module['addRunDependency'] = addRunDependency; +Module['removeRunDependency'] = removeRunDependency; +Module['FS_createPath'] = FS.createPath; +Module['FS_createDataFile'] = FS.createDataFile; +Module['FS_createLazyFile'] = FS.createLazyFile; +Module['FS_createDevice'] = FS.createDevice; +Module['FS_unlink'] = FS.unlink; +Module['ccall'] = ccall; +Module['FS_createPreloadedFile'] = FS.createPreloadedFile; +Module['PROXYFS'] = PROXYFS; -Module["PROXYFS"] = PROXYFS; var calledRun; dependenciesFulfilled = function runCaller() { - if (!calledRun) run(); - if (!calledRun) dependenciesFulfilled = runCaller; + // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) + if (!calledRun) run(); + if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled }; function run() { - if (runDependencies > 0) { - return; - } - preRun(); - if (runDependencies > 0) { - return; - } - function doRun() { - if (calledRun) return; - calledRun = true; - Module["calledRun"] = true; - if (ABORT) return; - initRuntime(); - if (Module["onRuntimeInitialized"]) Module["onRuntimeInitialized"](); - postRun(); - } - if (Module["setStatus"]) { - Module["setStatus"]("Running..."); - setTimeout((function() { - setTimeout((function() { - Module["setStatus"](""); - }), 1); - doRun(); - }), 1); - } else { - doRun(); - } + + if (runDependencies > 0) { + return; + } + + preRun(); + + // a preRun added a dependency, run will be called later + if (runDependencies > 0) { + return; + } + + function doRun() { + // run may have just been called through dependencies being fulfilled just in this very frame, + // or while the async setStatus time below was happening + if (calledRun) return; + calledRun = true; + Module['calledRun'] = true; + + if (ABORT) return; + + initRuntime(); + + if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized'](); + + postRun(); + } + + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(function() { + setTimeout(function() { + Module['setStatus'](''); + }, 1); + doRun(); + }, 1); + } else + { + doRun(); + } } -if (Module["preInit"]) { - if (typeof Module["preInit"] == "function") Module["preInit"] = [ Module["preInit"] ]; - while (Module["preInit"].length > 0) { - Module["preInit"].pop()(); - } +if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].pop()(); + } } run(); + + +// end include: postamble.js /** * Emscripten resolves `localhost` to a random IP address. Let's * make it always resolve to 127.0.0.1. diff --git a/packages/php-wasm/node/src/test/php-asyncify.spec.ts b/packages/php-wasm/node/src/test/php-asyncify.spec.ts index 7f0a6f5262..2d8118b734 100644 --- a/packages/php-wasm/node/src/test/php-asyncify.spec.ts +++ b/packages/php-wasm/node/src/test/php-asyncify.spec.ts @@ -44,6 +44,14 @@ describe.each(phpVersions)('PHP %s – asyncify', (phpVersion) => { fread($fp, 10); fclose($fp);`, `gethostbyname(${js['httpUrl']});`, + `$ch = curl_init(); + curl_setopt( $ch, CURLOPT_URL, ${js['httpUrl']} ); + curl_setopt($ch, CURLOPT_VERBOSE, 1); + curl_setopt($ch, CURLOPT_TCP_NODELAY, 0); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); + curl_setopt($ch, CURLOPT_TIMEOUT, 2); + curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); + curl_exec($ch);`, // @TODO: @@ -56,6 +64,7 @@ describe.each(phpVersions)('PHP %s – asyncify', (phpVersion) => { let php: NodePHP; beforeEach(async () => { php = await NodePHP.load(phpVersion as any); + php.setPhpIniEntry('disable_functions', ''); php.setPhpIniEntry('allow_url_fopen', '1'); }); diff --git a/packages/php-wasm/node/src/test/php-networking.spec.ts b/packages/php-wasm/node/src/test/php-networking.spec.ts index 7593031e11..14e8ea33ac 100644 --- a/packages/php-wasm/node/src/test/php-networking.spec.ts +++ b/packages/php-wasm/node/src/test/php-networking.spec.ts @@ -2,9 +2,41 @@ import { SupportedPHPVersions } from '@php-wasm/universal'; import express from 'express'; import { NodePHP } from '..'; -describe.each(SupportedPHPVersions)( +describe.each(['8.0'])( 'PHP %s', (phpVersion) => { + it.only('should be able to use CURL', async () => { + const php = await NodePHP.load(phpVersion); + php.setPhpIniEntry('disable_functions', ''); + php.setPhpIniEntry('allow_url_fopen', 'On'); + php.setPhpIniEntry('openssl.cafile', '/tmp/ca-bundle.crt'); + php.writeFile( + '/tmp/test.php', + ` { const serverUrl = await startServer(); const php = await NodePHP.load(phpVersion); diff --git a/packages/php-wasm/node/src/test/php.spec.ts b/packages/php-wasm/node/src/test/php.spec.ts index 05fa5df57d..cf08612f80 100644 --- a/packages/php-wasm/node/src/test/php.spec.ts +++ b/packages/php-wasm/node/src/test/php.spec.ts @@ -67,7 +67,7 @@ destructive results fifty years hence. He was, I believe, not in the least an ill-natured man: very much the opposite, I should say; but he would not suffer fools gladly.`; -describe.each(SupportedPHPVersions)('PHP %s', (phpVersion) => { +describe.each(['8.0'])('PHP %s', (phpVersion) => { let php: NodePHP; beforeEach(async () => { php = await NodePHP.load(phpVersion as any, { diff --git a/packages/php-wasm/universal/src/lib/wasm-error-reporting.ts b/packages/php-wasm/universal/src/lib/wasm-error-reporting.ts index 7eb6d7fe39..272240c396 100644 --- a/packages/php-wasm/universal/src/lib/wasm-error-reporting.ts +++ b/packages/php-wasm/universal/src/lib/wasm-error-reporting.ts @@ -86,7 +86,12 @@ export function clarifyErrorMessage( crypticError: Error, asyncifyStack?: string ) { - if (crypticError.message === 'unreachable') { + if ( + [ + 'unreachable', + 'null function or function signature mismatch', + ].includes(crypticError.message) + ) { let betterMessage = UNREACHABLE_ERROR; if (!asyncifyStack) { betterMessage += @@ -159,7 +164,7 @@ function extractPHPFunctionsFromStack(stack: string) { const parts = line.trim().substring('at '.length).split(' '); return { fn: parts.length >= 2 ? parts[0] : '', - isWasm: line.includes('wasm://'), + isWasm: line.includes('wasm:/'), }; }) .filter( diff --git a/packages/php-wasm/web/public/kitchen-sink/8_0_30/php_8_0.wasm b/packages/php-wasm/web/public/kitchen-sink/8_0_30/php_8_0.wasm index ac71d7df08..767b087d1a 100755 Binary files a/packages/php-wasm/web/public/kitchen-sink/8_0_30/php_8_0.wasm and b/packages/php-wasm/web/public/kitchen-sink/8_0_30/php_8_0.wasm differ diff --git a/packages/php-wasm/web/public/kitchen-sink/php_8_0.js b/packages/php-wasm/web/public/kitchen-sink/php_8_0.js index 7f83b9d6a9..17b143df15 100644 --- a/packages/php-wasm/web/public/kitchen-sink/php_8_0.js +++ b/packages/php-wasm/web/public/kitchen-sink/php_8_0.js @@ -1,6 +1,6 @@ import dependencyFilename from './8_0_30/php_8_0.wasm'; export { dependencyFilename }; -export const dependenciesTotalSize = 11610889; +export const dependenciesTotalSize = 19549057; export function init(RuntimeName, PHPLoader) { /** * Overrides Emscripten's default ExitStatus object which gets @@ -38,9 +38,9053 @@ export function init(RuntimeName, PHPLoader) { } // The rest of the code comes from the built php.js file and esm-suffix.js -var Module=typeof PHPLoader!="undefined"?PHPLoader:{};var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=RuntimeName==="WEB";var ENVIRONMENT_IS_WORKER=RuntimeName==="WORKER";var ENVIRONMENT_IS_NODE=RuntimeName==="NODE";var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=title=>document.title=title}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime=Module["noExitRuntime"]||false;if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort(text)}}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;var runtimeKeepaliveCounter=0;function keepRuntimeAlive(){return noExitRuntime||runtimeKeepaliveCounter>0}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();FS.ignorePermissions=false;TTY.init();SOCKFS.root=FS.mount(SOCKFS,{},null);PIPEFS.root=FS.mount(PIPEFS,{},null);callRuntimeCallbacks(__ATINIT__)}function exitRuntime(){___funcs_on_exit();callRuntimeCallbacks(__ATEXIT__);FS.quit();TTY.shutdown();runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}var wasmBinaryFile;wasmBinaryFile=dependencyFilename;if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then((response=>{if(!response["ok"]){throw"failed to load wasm binary file at '"+binaryFile+"'"}return response["arrayBuffer"]()})).catch((()=>getBinarySync(binaryFile)))}}return Promise.resolve().then((()=>getBinarySync(binaryFile)))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then((binary=>WebAssembly.instantiate(binary,imports))).then((instance=>instance)).then(receiver,(reason=>{err("failed to asynchronously prepare wasm: "+reason);abort(reason)}))}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then((response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,(function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)}))}))}return instantiateArrayBuffer(binaryFile,imports,callback)}function createWasm(){var info={"a":wasmImports};function receiveInstance(instance,module){var exports=instance.exports;exports=Asyncify.instrumentWasmExports(exports);Module["asm"]=exports;wasmMemory=Module["asm"]["Ya"];updateMemoryViews();wasmTable=Module["asm"]["ab"];addOnInit(Module["asm"]["Za"]);removeRunDependency("wasm-instantiate");return exports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult);return{}}var tempDouble;var tempI64;function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf8"):undefined;var UTF8ArrayToString=(heapOrArray,idx,maxBytesToRead)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):"";Module["UTF8ToString"]=UTF8ToString;var ___assert_fail=(condition,filename,line,func)=>{abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])};var ___call_sighandler=(fp,sig)=>(a1=>dynCall_vi.apply(null,[fp,a1]))(sig);var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter((p=>!!p)),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:function(){var paths=Array.prototype.slice.call(arguments);return PATH.normalize(paths.join("/"))},join2:(l,r)=>PATH.normalize(l+"/"+r)};var initRandomFill=()=>{if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){return view=>crypto.getRandomValues(view)}else abort("initRandomDevice")};var randomFill=view=>(randomFill=initRandomFill())(view);var PATH_FS={resolve:function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter((p=>!!p)),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};Module["lengthBytesUTF8"]=lengthBytesUTF8;var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init:function(){},shutdown:function(){},register:function(dev,ops){TTY.ttys[dev]={input:[],output:[],ops:ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open:function(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close:function(stream){stream.tty.ops.fsync(stream.tty)},fsync:function(stream){stream.tty.ops.fsync(stream.tty)},read:function(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}},ioctl_tcgets:function(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets:function(tty,optional_actions,data){return 0},ioctl_tiocgwinsz:function(tty){return[24,80]}},default_tty1_ops:{put_char:function(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync:function(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};var zeroMemory=(address,size)=>{HEAPU8.fill(0,address,address+size);return address};var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var mmapAlloc=size=>{size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(!ptr)return 0;return zeroMemory(ptr,size)};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}if(!MEMFS.ops_table){MEMFS.ops_table={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}}}var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){throw FS.genericErrors[44]},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp;old_node.parent=new_dir},unlink(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir(node){var entries=[".",".."];for(var key in node.contents){if(!node.contents.hasOwnProperty(key)){continue}entries.push(key)}return entries},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length{var dep=!noRunDep?getUniqueRunDependency(`al ${url}`):"";readAsync(url,(arrayBuffer=>{assert(arrayBuffer,`Loading data file "${url}" failed (no arrayBuffer).`);onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)}),(event=>{if(onerror){onerror()}else{throw`Loading data file "${url}" failed.`}}));if(dep)addRunDependency(dep)};var preloadPlugins=Module["preloadPlugins"]||[];function FS_handledByPreloadPlugin(byteArray,fullname,finish,onerror){if(typeof Browser!="undefined")Browser.init();var handled=false;preloadPlugins.forEach((function(plugin){if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,onerror);handled=true}}));return handled}function FS_createPreloadedFile(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish){var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){if(preFinish)preFinish();if(!dontCreateFile){FS.createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}if(onload)onload();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,(()=>{if(onerror)onerror();removeRunDependency(dep)}))){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url,(byteArray=>processData(byteArray)),onerror)}else{processData(url)}}function FS_modeStringToFlags(str){var flagModes={"r":0,"r+":2,"w":512|64|1,"w+":512|64|2,"a":1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags}function FS_getMode(canRead,canWrite){var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode}var ERRNO_CODES={};var PROXYFS={mount(mount){return PROXYFS.createNode(null,"/",mount.opts.fs.lstat(mount.opts.root).mode,0)},createNode(parent,name,mode,dev){if(!FS.isDir(mode)&&!FS.isFile(mode)&&!FS.isLink(mode)){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var node=FS.createNode(parent,name,mode);node.node_ops=PROXYFS.node_ops;node.stream_ops=PROXYFS.stream_ops;return node},realPath(node){var parts=[];while(node.parent!==node){parts.push(node.name);node=node.parent}parts.push(node.mount.opts.root);parts.reverse();return PATH.join.apply(null,parts)},node_ops:{getattr(node){var path=PROXYFS.realPath(node);var stat;try{stat=node.mount.opts.fs.lstat(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}return{dev:stat.dev,ino:stat.ino,mode:stat.mode,nlink:stat.nlink,uid:stat.uid,gid:stat.gid,rdev:stat.rdev,size:stat.size,atime:stat.atime,mtime:stat.mtime,ctime:stat.ctime,blksize:stat.blksize,blocks:stat.blocks}},setattr(node,attr){var path=PROXYFS.realPath(node);try{if(attr.mode!==undefined){node.mount.opts.fs.chmod(path,attr.mode);node.mode=attr.mode}if(attr.timestamp!==undefined){var date=new Date(attr.timestamp);node.mount.opts.fs.utime(path,date,date)}if(attr.size!==undefined){node.mount.opts.fs.truncate(path,attr.size)}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}},lookup(parent,name){try{var path=PATH.join2(PROXYFS.realPath(parent),name);var mode=parent.mount.opts.fs.lstat(path).mode;var node=PROXYFS.createNode(parent,name,mode);return node}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}},mknod(parent,name,mode,dev){var node=PROXYFS.createNode(parent,name,mode,dev);var path=PROXYFS.realPath(node);try{if(FS.isDir(node.mode)){node.mount.opts.fs.mkdir(path,node.mode)}else{node.mount.opts.fs.writeFile(path,"",{mode:node.mode})}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}return node},rename(oldNode,newDir,newName){var oldPath=PROXYFS.realPath(oldNode);var newPath=PATH.join2(PROXYFS.realPath(newDir),newName);try{oldNode.mount.opts.fs.rename(oldPath,newPath);oldNode.name=newName;oldNode.parent=newDir}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}},unlink(parent,name){var path=PATH.join2(PROXYFS.realPath(parent),name);try{parent.mount.opts.fs.unlink(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}},rmdir(parent,name){var path=PATH.join2(PROXYFS.realPath(parent),name);try{parent.mount.opts.fs.rmdir(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}},readdir(node){var path=PROXYFS.realPath(node);try{return node.mount.opts.fs.readdir(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}},symlink(parent,newName,oldPath){var newPath=PATH.join2(PROXYFS.realPath(parent),newName);try{parent.mount.opts.fs.symlink(oldPath,newPath)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}},readlink(node){var path=PROXYFS.realPath(node);try{return node.mount.opts.fs.readlink(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}},stream_ops:{open(stream){var path=PROXYFS.realPath(stream.node);try{stream.nfd=stream.node.mount.opts.fs.open(path,stream.flags)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}},close(stream){try{stream.node.mount.opts.fs.close(stream.nfd)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}},read(stream,buffer,offset,length,position){try{return stream.node.mount.opts.fs.read(stream.nfd,buffer,offset,length,position)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}},write(stream,buffer,offset,length,position){try{return stream.node.mount.opts.fs.write(stream.nfd,buffer,offset,length,position)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}},llseek(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){try{var stat=stream.node.node_ops.getattr(stream.node);position+=stat.size}catch(e){throw new FS.ErrnoError(ERRNO_CODES[e.code])}}}if(position<0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}return position}}};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,lookupPath:(path,opts={})=>{path=PATH_FS.resolve(path);if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split("/").filter((p=>!!p));var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath:node=>{var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName:(parentid,name)=>{var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode:node=>{var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode:node=>{var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode:(parent,name)=>{var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode:(parent,name,mode,rdev)=>{var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode:node=>{FS.hashRemoveNode(node)},isRoot:node=>node===node.parent,isMountpoint:node=>!!node.mounted,isFile:mode=>(mode&61440)===32768,isDir:mode=>(mode&61440)===16384,isLink:mode=>(mode&61440)===40960,isChrdev:mode=>(mode&61440)===8192,isBlkdev:mode=>(mode&61440)===24576,isFIFO:mode=>(mode&61440)===4096,isSocket:mode=>(mode&49152)===49152,flagsToPermissionString:flag=>{var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions:(node,perms)=>{if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup:dir=>{var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate:(dir,name)=>{try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete:(dir,name,isdir)=>{var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen:(node,flags)=>{if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd:()=>{for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked:fd=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream:(stream,fd=-1)=>{if(!FS.FSStream){FS.FSStream=function(){this.shared={}};FS.FSStream.prototype={};Object.defineProperties(FS.FSStream.prototype,{object:{get(){return this.node},set(val){this.node=val}},isRead:{get(){return(this.flags&2097155)!==1}},isWrite:{get(){return(this.flags&2097155)!==0}},isAppend:{get(){return this.flags&1024}},flags:{get(){return this.shared.flags},set(val){this.shared.flags=val}},position:{get(){return this.shared.position},set(val){this.shared.position=val}}})}stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream:fd=>{FS.streams[fd]=null},chrdev_stream_ops:{open:stream=>{var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}},llseek:()=>{throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice:(dev,ops)=>{FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts:mount=>{var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts},syncfs:(populate,callback)=>{if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach((mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)}))},mount:(type,opts,mountpoint)=>{var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount:mountpoint=>{var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach((hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}}));node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup:(parent,name)=>parent.node_ops.lookup(parent,name),mknod:(path,mode,dev)=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create:(path,mode)=>{mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir:(path,mode)=>{mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree:(path,mode)=>{var dirs=path.split("/");var d="";for(var i=0;i{if(typeof dev=="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink:(oldpath,newpath)=>{if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(44)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(63)}return parent.node_ops.symlink(parent,newname,oldpath)},rename:(old_path,new_path)=>{var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node;if(!old_dir||!new_dir)throw new FS.ErrnoError(44);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}errCode=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(errCode){throw new FS.ErrnoError(errCode)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(63)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(10)}if(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,"w");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name)}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir:path=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,true);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir:path=>{var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node.node_ops.readdir){throw new FS.ErrnoError(54)}return node.node_ops.readdir(node)},unlink:path=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink:path=>{var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(44)}if(!link.node_ops.readlink){throw new FS.ErrnoError(28)}return PATH_FS.resolve(FS.getPath(link.parent),link.node_ops.readlink(link))},stat:(path,dontFollow)=>{var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;if(!node){throw new FS.ErrnoError(44)}if(!node.node_ops.getattr){throw new FS.ErrnoError(63)}return node.node_ops.getattr(node)},lstat:path=>FS.stat(path,true),chmod:(path,mode,dontFollow)=>{var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{mode:mode&4095|node.mode&~4095,timestamp:Date.now()})},lchmod:(path,mode)=>{FS.chmod(path,mode,true)},fchmod:(fd,mode)=>{var stream=FS.getStreamChecked(fd);FS.chmod(stream.node,mode)},chown:(path,uid,gid,dontFollow)=>{var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{timestamp:Date.now()})},lchown:(path,uid,gid)=>{FS.chown(path,uid,gid,true)},fchown:(fd,uid,gid)=>{var stream=FS.getStreamChecked(fd);FS.chown(stream.node,uid,gid)},truncate:(path,len)=>{if(len<0){throw new FS.ErrnoError(28)}var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}if(FS.isDir(node.mode)){throw new FS.ErrnoError(31)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(28)}var errCode=FS.nodePermissions(node,"w");if(errCode){throw new FS.ErrnoError(errCode)}node.node_ops.setattr(node,{size:len,timestamp:Date.now()})},ftruncate:(fd,len)=>{var stream=FS.getStreamChecked(fd);if((stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.truncate(stream.node,len)},utime:(path,atime,mtime)=>{var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;node.node_ops.setattr(node,{timestamp:Math.max(atime,mtime)})},open:(path,flags,mode)=>{if(path===""){throw new FS.ErrnoError(44)}flags=typeof flags=="string"?FS_modeStringToFlags(flags):flags;mode=typeof mode=="undefined"?438:mode;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;if(typeof path=="object"){node=path}else{path=PATH.normalize(path);try{var lookup=FS.lookupPath(path,{follow:!(flags&131072)});node=lookup.node}catch(e){}}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else{node=FS.mknod(path,mode,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node:node,path:FS.getPath(node),flags:flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(Module["logReadFiles"]&&!(flags&1)){if(!FS.readFiles)FS.readFiles={};if(!(path in FS.readFiles)){FS.readFiles[path]=1}}return stream},close:stream=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed:stream=>stream.fd===null,llseek:(stream,offset,whence)=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(70)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(28)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read:(stream,buffer,offset,length,position)=>{if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write:(stream,buffer,offset,length,position,canOwn)=>{if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},allocate:(stream,offset,length)=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(offset<0||length<=0){throw new FS.ErrnoError(28)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(43)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(138)}stream.stream_ops.allocate(stream,offset,length)},mmap:(stream,length,position,prot,flags)=>{if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync:(stream,buffer,offset,length,mmapFlags)=>{if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},munmap:stream=>0,ioctl:(stream,cmd,arg)=>{if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile:(path,opts={})=>{opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){throw new Error(`Invalid encoding type "${opts.encoding}"`)}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){ret=UTF8ArrayToString(buf,0)}else if(opts.encoding==="binary"){ret=buf}FS.close(stream);return ret},writeFile:(path,data,opts={})=>{opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir:path=>{var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories:()=>{FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices:()=>{FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories:()=>{FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount:()=>{var node=FS.createNode(proc_self,"fd",16384|511,73);node.node_ops={lookup:(parent,name)=>{var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams:()=>{if(Module["stdin"]){FS.createDevice("/dev","stdin",Module["stdin"])}else{FS.symlink("/dev/tty","/dev/stdin")}if(Module["stdout"]){FS.createDevice("/dev","stdout",null,Module["stdout"])}else{FS.symlink("/dev/tty","/dev/stdout")}if(Module["stderr"]){FS.createDevice("/dev","stderr",null,Module["stderr"])}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},ensureErrnoError:()=>{if(FS.ErrnoError)return;FS.ErrnoError=function ErrnoError(errno,node){this.name="ErrnoError";this.node=node;this.setErrno=function(errno){this.errno=errno};this.setErrno(errno);this.message="FS error"};FS.ErrnoError.prototype=new Error;FS.ErrnoError.prototype.constructor=FS.ErrnoError;[44].forEach((code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack=""}))},staticInit:()=>{FS.ensureErrnoError();FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={"MEMFS":MEMFS,"PROXYFS":PROXYFS}},init:(input,output,error)=>{FS.init.initialized=true;FS.ensureErrnoError();Module["stdin"]=input||Module["stdin"];Module["stdout"]=output||Module["stdout"];Module["stderr"]=error||Module["stderr"];FS.createStandardStreams()},quit:()=>{FS.init.initialized=false;_fflush(0);for(var i=0;i{var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath:(path,dontResolveLastLink)=>{try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path==="/"}catch(e){ret.error=e.errno}return ret},createPath:(parent,path,canRead,canWrite)=>{parent=typeof parent=="string"?parent:FS.getPath(parent);var parts=path.split("/").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){}parent=current}return current},createFile:(parent,name,properties,canRead,canWrite)=>{var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile:(parent,name,data,canRead,canWrite,canOwn)=>{var path=name;if(parent){parent=typeof parent=="string"?parent:FS.getPath(parent);path=name?PATH.join2(parent,name):parent}var mode=FS_getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data=="string"){var arr=new Array(data.length);for(var i=0,len=data.length;i{var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(!!input,!!output);if(!FS.createDevice.major)FS.createDevice.major=64;var dev=FS.makedev(FS.createDevice.major++,0);FS.registerDevice(dev,{open:stream=>{stream.seekable=false},close:stream=>{if(output&&output.buffer&&output.buffer.length){output(10)}},read:(stream,buffer,offset,length,pos)=>{var bytesRead=0;for(var i=0;i{for(var i=0;i{if(obj.isDevice||obj.isFolder||obj.link||obj.contents)return true;if(typeof XMLHttpRequest!="undefined"){throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.")}else if(read_){try{obj.contents=intArrayFromString(read_(obj.url),true);obj.usedBytes=obj.contents.length}catch(e){throw new FS.ErrnoError(29)}}else{throw new Error("Cannot load without read() or XMLHttpRequest.")}},createLazyFile:(parent,name,url,canRead,canWrite)=>{function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}LazyUint8Array.prototype.get=function LazyUint8Array_get(idx){if(idx>this.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter((chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]}));if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach((key=>{var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){FS.forceLoadFile(node);return fn.apply(null,arguments)}}));function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr:ptr,allocated:true}};node.stream_ops=stream_ops;return node}};Module["FS"]=FS;var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt:function(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat:function(func,path,buf){try{var stat=func(path)}catch(e){if(e&&e.node&&PATH.normalize(path)!==PATH.normalize(FS.getPath(e.node))){return-54}throw e}HEAP32[buf>>2]=stat.dev;HEAP32[buf+4>>2]=stat.mode;HEAPU32[buf+8>>2]=stat.nlink;HEAP32[buf+12>>2]=stat.uid;HEAP32[buf+16>>2]=stat.gid;HEAP32[buf+20>>2]=stat.rdev;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+24>>2]=tempI64[0],HEAP32[buf+28>>2]=tempI64[1];HEAP32[buf+32>>2]=4096;HEAP32[buf+36>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAPU32[buf+48>>2]=atime%1e3*1e3;tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+56>>2]=tempI64[0],HEAP32[buf+60>>2]=tempI64[1];HEAPU32[buf+64>>2]=mtime%1e3*1e3;tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+72>>2]=tempI64[0],HEAP32[buf+76>>2]=tempI64[1];HEAPU32[buf+80>>2]=ctime%1e3*1e3;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+88>>2]=tempI64[0],HEAP32[buf+92>>2]=tempI64[1];return 0},doMsync:function(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},varargs:undefined,get(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr(ptr){var ret=UTF8ToString(ptr);return ret},getStreamFromFD:function(fd){var stream=FS.getStreamChecked(fd);return stream}};function ___syscall__newselect(nfds,readfds,writefds,exceptfds,timeout){try{var total=0;var srcReadLow=readfds?HEAP32[readfds>>2]:0,srcReadHigh=readfds?HEAP32[readfds+4>>2]:0;var srcWriteLow=writefds?HEAP32[writefds>>2]:0,srcWriteHigh=writefds?HEAP32[writefds+4>>2]:0;var srcExceptLow=exceptfds?HEAP32[exceptfds>>2]:0,srcExceptHigh=exceptfds?HEAP32[exceptfds+4>>2]:0;var dstReadLow=0,dstReadHigh=0;var dstWriteLow=0,dstWriteHigh=0;var dstExceptLow=0,dstExceptHigh=0;var allLow=(readfds?HEAP32[readfds>>2]:0)|(writefds?HEAP32[writefds>>2]:0)|(exceptfds?HEAP32[exceptfds>>2]:0);var allHigh=(readfds?HEAP32[readfds+4>>2]:0)|(writefds?HEAP32[writefds+4>>2]:0)|(exceptfds?HEAP32[exceptfds+4>>2]:0);var check=function(fd,low,high,val){return fd<32?low&val:high&val};for(var fd=0;fd>2]:0,tv_usec=readfds?HEAP32[timeout+8>>2]:0;timeoutInMillis=(tv_sec+tv_usec/1e6)*1e3}flags=stream.stream_ops.poll(stream,timeoutInMillis)}if(flags&1&&check(fd,srcReadLow,srcReadHigh,mask)){fd<32?dstReadLow=dstReadLow|mask:dstReadHigh=dstReadHigh|mask;total++}if(flags&4&&check(fd,srcWriteLow,srcWriteHigh,mask)){fd<32?dstWriteLow=dstWriteLow|mask:dstWriteHigh=dstWriteHigh|mask;total++}if(flags&2&&check(fd,srcExceptLow,srcExceptHigh,mask)){fd<32?dstExceptLow=dstExceptLow|mask:dstExceptHigh=dstExceptHigh|mask;total++}}if(readfds){HEAP32[readfds>>2]=dstReadLow;HEAP32[readfds+4>>2]=dstReadHigh}if(writefds){HEAP32[writefds>>2]=dstWriteLow;HEAP32[writefds+4>>2]=dstWriteHigh}if(exceptfds){HEAP32[exceptfds>>2]=dstExceptLow;HEAP32[exceptfds+4>>2]=dstExceptHigh}return total}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var SOCKFS={mount(mount){Module["websocket"]=Module["websocket"]&&"object"===typeof Module["websocket"]?Module["websocket"]:{};Module["websocket"]._callbacks={};Module["websocket"]["on"]=function(event,callback){if("function"===typeof callback){this._callbacks[event]=callback}return this};Module["websocket"].emit=function(event,param){if("function"===typeof this._callbacks[event]){this._callbacks[event].call(this,param)}};return FS.createNode(null,"/",16384|511,0)},createSocket(family,type,protocol){type&=~526336;var streaming=type==1;if(streaming&&protocol&&protocol!=6){throw new FS.ErrnoError(66)}var sock={family:family,type:type,protocol:protocol,server:null,error:null,peers:{},pending:[],recv_queue:[],sock_ops:SOCKFS.websocket_sock_ops};var name=SOCKFS.nextname();var node=FS.createNode(SOCKFS.root,name,49152,0);node.sock=sock;var stream=FS.createStream({path:name,node:node,flags:2,seekable:false,stream_ops:SOCKFS.stream_ops});sock.stream=stream;return sock},getSocket(fd){var stream=FS.getStream(fd);if(!stream||!FS.isSocket(stream.node.mode)){return null}return stream.node.sock},stream_ops:{poll(stream){var sock=stream.node.sock;return sock.sock_ops.poll(sock)},ioctl(stream,request,varargs){var sock=stream.node.sock;return sock.sock_ops.ioctl(sock,request,varargs)},read(stream,buffer,offset,length,position){var sock=stream.node.sock;var msg=sock.sock_ops.recvmsg(sock,length);if(!msg){return 0}buffer.set(msg.buffer,offset);return msg.buffer.length},write(stream,buffer,offset,length,position){var sock=stream.node.sock;return sock.sock_ops.sendmsg(sock,buffer,offset,length)},close(stream){var sock=stream.node.sock;sock.sock_ops.close(sock)}},nextname(){if(!SOCKFS.nextname.current){SOCKFS.nextname.current=0}return"socket["+SOCKFS.nextname.current+++"]"},websocket_sock_ops:{createPeer(sock,addr,port){var ws;if(typeof addr=="object"){ws=addr;addr=null;port=null}if(ws){if(ws._socket){addr=ws._socket.remoteAddress;port=ws._socket.remotePort}else{var result=/ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url);if(!result){throw new Error("WebSocket URL must be in the format ws(s)://address:port")}addr=result[1];port=parseInt(result[2],10)}}else{try{var runtimeConfig=Module["websocket"]&&"object"===typeof Module["websocket"];var url="ws:#".replace("#","//");if(runtimeConfig){if("function"===typeof Module["websocket"]["url"]) { +// include: shell.js +// The Module object: Our interface to the outside world. We import +// and export values on it. There are various ways Module can be used: +// 1. Not defined. We create it here +// 2. A function parameter, function(Module) { ..generated code.. } +// 3. pre-run appended it, var Module = {}; ..generated code.. +// 4. External script tag defines var Module. +// We need to check if Module already exists (e.g. case 3 above). +// Substitution will be replaced with actual code on later stage of the build, +// this way Closure Compiler will not mangle it (e.g. case 4. above). +// Note that if you want to run closure, and also to use Module +// after the generated code, you will need to define var Module = {}; +// before the code. Then that object will be used in the code, and you +// can continue to use Module afterwards as well. +var Module = typeof PHPLoader != 'undefined' ? PHPLoader : {}; + +// --pre-jses are emitted after the Module integration code, so that they can +// refer to Module (if they choose; they can also define Module) + + +// Sometimes an existing Module object exists with properties +// meant to overwrite the default module functionality. Here +// we collect those properties and reapply _after_ we configure +// the current environment's defaults to avoid having to be so +// defensive during initialization. +var moduleOverrides = Object.assign({}, Module); + +var arguments_ = []; +var thisProgram = './this.program'; +var quit_ = (status, toThrow) => { + throw toThrow; +}; + +// Determine the runtime environment we are in. You can customize this by +// setting the ENVIRONMENT setting at compile time (see settings.js). + +var ENVIRONMENT_IS_WEB=RuntimeName==="WEB"; +var ENVIRONMENT_IS_WORKER=RuntimeName==="WORKER"; +var ENVIRONMENT_IS_NODE=RuntimeName==="NODE"; +var ENVIRONMENT_IS_SHELL=RuntimeName==="SHELL"; + +// `/` should be present at the end if `scriptDirectory` is not empty +var scriptDirectory = ''; +function locateFile(path) { + if (Module['locateFile']) { + return Module['locateFile'](path, scriptDirectory); + } + return scriptDirectory + path; +} + +// Hooks that are implemented differently in different runtime environments. +var read_, + readAsync, + readBinary, + setWindowTitle; + +// Note that this includes Node.js workers when relevant (pthreads is enabled). +// Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and +// ENVIRONMENT_IS_NODE. +if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled + scriptDirectory = self.location.href; + } else if (typeof document != 'undefined' && document.currentScript) { // web + scriptDirectory = document.currentScript.src; + } + // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them. + // otherwise, slice off the final part of the url to find the script directory. + // if scriptDirectory does not contain a slash, lastIndexOf will return -1, + // and scriptDirectory will correctly be replaced with an empty string. + // If scriptDirectory contains a query (starting with ?) or a fragment (starting with #), + // they are removed because they could contain a slash. + if (scriptDirectory.indexOf('blob:') !== 0) { + scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf('/')+1); + } else { + scriptDirectory = ''; + } + + // Differentiate the Web Worker from the Node Worker case, as reading must + // be done differently. + { +// include: web_or_worker_shell_read.js +read_ = (url) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.send(null); + return xhr.responseText; + } + + if (ENVIRONMENT_IS_WORKER) { + readBinary = (url) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + xhr.responseType = 'arraybuffer'; + xhr.send(null); + return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response)); + }; + } + + readAsync = (url, onload, onerror) => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'arraybuffer'; + xhr.onload = () => { + if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + onload(xhr.response); + return; + } + onerror(); + }; + xhr.onerror = onerror; + xhr.send(null); + } + +// end include: web_or_worker_shell_read.js + } + + setWindowTitle = (title) => document.title = title; +} else +{ +} + +var out = Module['print'] || console.log.bind(console); +var err = Module['printErr'] || console.error.bind(console); + +// Merge back in the overrides +Object.assign(Module, moduleOverrides); +// Free the object hierarchy contained in the overrides, this lets the GC +// reclaim data used e.g. in memoryInitializerRequest, which is a large typed array. +moduleOverrides = null; + +// Emit code to handle expected values on the Module object. This applies Module.x +// to the proper local x. This has two benefits: first, we only emit it if it is +// expected to arrive, and second, by using a local everywhere else that can be +// minified. + +if (Module['arguments']) arguments_ = Module['arguments']; + +if (Module['thisProgram']) thisProgram = Module['thisProgram']; + +if (Module['quit']) quit_ = Module['quit']; + +// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message + +// end include: shell.js +// include: preamble.js +// === Preamble library stuff === + +// Documentation for the public APIs defined in this file must be updated in: +// site/source/docs/api_reference/preamble.js.rst +// A prebuilt local version of the documentation is available at: +// site/build/text/docs/api_reference/preamble.js.txt +// You can also build docs locally as HTML or other formats in site/ +// An online HTML version (which may be of a different version of Emscripten) +// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html + +var wasmBinary; +if (Module['wasmBinary']) wasmBinary = Module['wasmBinary']; +var noExitRuntime = Module['noExitRuntime'] || false; + +if (typeof WebAssembly != 'object') { + abort('no native wasm support detected'); +} + +// Wasm globals + +var wasmMemory; + +//======================================== +// Runtime essentials +//======================================== + +// whether we are quitting the application. no code should run after this. +// set in exit() and abort() +var ABORT = false; + +// set by exit() and abort(). Passed to 'onExit' handler. +// NOTE: This is also used as the process return code code in shell environments +// but only when noExitRuntime is false. +var EXITSTATUS; + +/** @type {function(*, string=)} */ +function assert(condition, text) { + if (!condition) { + // This build was created without ASSERTIONS defined. `assert()` should not + // ever be called in this configuration but in case there are callers in + // the wild leave this simple abort() implemenation here for now. + abort(text); + } +} + +// Memory management + +var HEAP, +/** @type {!Int8Array} */ + HEAP8, +/** @type {!Uint8Array} */ + HEAPU8, +/** @type {!Int16Array} */ + HEAP16, +/** @type {!Uint16Array} */ + HEAPU16, +/** @type {!Int32Array} */ + HEAP32, +/** @type {!Uint32Array} */ + HEAPU32, +/** @type {!Float32Array} */ + HEAPF32, +/** @type {!Float64Array} */ + HEAPF64; + +function updateMemoryViews() { + var b = wasmMemory.buffer; + Module['HEAP8'] = HEAP8 = new Int8Array(b); + Module['HEAP16'] = HEAP16 = new Int16Array(b); + Module['HEAP32'] = HEAP32 = new Int32Array(b); + Module['HEAPU8'] = HEAPU8 = new Uint8Array(b); + Module['HEAPU16'] = HEAPU16 = new Uint16Array(b); + Module['HEAPU32'] = HEAPU32 = new Uint32Array(b); + Module['HEAPF32'] = HEAPF32 = new Float32Array(b); + Module['HEAPF64'] = HEAPF64 = new Float64Array(b); +} + +// include: runtime_init_table.js +// In regular non-RELOCATABLE mode the table is exported +// from the wasm module and this will be assigned once +// the exports are available. +var wasmTable; +// end include: runtime_init_table.js +// include: runtime_stack_check.js +// end include: runtime_stack_check.js +// include: runtime_assertions.js +// end include: runtime_assertions.js +var __ATPRERUN__ = []; // functions called before the runtime is initialized +var __ATINIT__ = []; // functions called during startup +var __ATEXIT__ = []; // functions called during shutdown +var __ATPOSTRUN__ = []; // functions called after the main() is called + +var runtimeInitialized = false; + +var runtimeExited = false; + +var runtimeKeepaliveCounter = 0; + +function keepRuntimeAlive() { + return noExitRuntime || runtimeKeepaliveCounter > 0; +} + +function preRun() { + if (Module['preRun']) { + if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; + while (Module['preRun'].length) { + addOnPreRun(Module['preRun'].shift()); + } + } + callRuntimeCallbacks(__ATPRERUN__); +} + +function initRuntime() { + runtimeInitialized = true; + + SOCKFS.root = FS.mount(SOCKFS, {}, null); + +if (!Module["noFSInit"] && !FS.init.initialized) + FS.init(); +FS.ignorePermissions = false; + +TTY.init(); +PIPEFS.root = FS.mount(PIPEFS, {}, null); + callRuntimeCallbacks(__ATINIT__); +} + +function exitRuntime() { + ___funcs_on_exit(); // Native atexit() functions + callRuntimeCallbacks(__ATEXIT__); + FS.quit(); +TTY.shutdown(); + runtimeExited = true; +} + +function postRun() { + + if (Module['postRun']) { + if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; + while (Module['postRun'].length) { + addOnPostRun(Module['postRun'].shift()); + } + } + + callRuntimeCallbacks(__ATPOSTRUN__); +} + +function addOnPreRun(cb) { + __ATPRERUN__.unshift(cb); +} + +function addOnInit(cb) { + __ATINIT__.unshift(cb); +} + +function addOnExit(cb) { + __ATEXIT__.unshift(cb); +} + +function addOnPostRun(cb) { + __ATPOSTRUN__.unshift(cb); +} + +// include: runtime_math.js +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc + +// end include: runtime_math.js +// A counter of dependencies for calling run(). If we need to +// do asynchronous work before running, increment this and +// decrement it. Incrementing must happen in a place like +// Module.preRun (used by emcc to add file preloading). +// Note that you can add dependencies in preRun, even though +// it happens right before run - run will be postponed until +// the dependencies are met. +var runDependencies = 0; +var runDependencyWatcher = null; +var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled + +function getUniqueRunDependency(id) { + return id; +} + +function addRunDependency(id) { + runDependencies++; + + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + +} + +function removeRunDependency(id) { + runDependencies--; + + if (Module['monitorRunDependencies']) { + Module['monitorRunDependencies'](runDependencies); + } + + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + if (dependenciesFulfilled) { + var callback = dependenciesFulfilled; + dependenciesFulfilled = null; + callback(); // can add another dependenciesFulfilled + } + } +} + +/** @param {string|number=} what */ +function abort(what) { + if (Module['onAbort']) { + Module['onAbort'](what); + } + + what = 'Aborted(' + what + ')'; + // TODO(sbc): Should we remove printing and leave it up to whoever + // catches the exception? + err(what); + + ABORT = true; + EXITSTATUS = 1; + + what += '. Build with -sASSERTIONS for more info.'; + + // Use a wasm runtime error, because a JS error might be seen as a foreign + // exception, which means we'd run destructors on it. We need the error to + // simply make the program stop. + // FIXME This approach does not work in Wasm EH because it currently does not assume + // all RuntimeErrors are from traps; it decides whether a RuntimeError is from + // a trap or not based on a hidden field within the object. So at the moment + // we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that + // allows this in the wasm spec. + + // Suppress closure compiler warning here. Closure compiler's builtin extern + // defintion for WebAssembly.RuntimeError claims it takes no arguments even + // though it can. + // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed. + /** @suppress {checkTypes} */ + var e = new WebAssembly.RuntimeError(what); + + // Throw the error whether or not MODULARIZE is set because abort is used + // in code paths apart from instantiation where an exception is expected + // to be thrown when abort is called. + throw e; +} + +// include: memoryprofiler.js +// end include: memoryprofiler.js +// include: URIUtils.js +// Prefix of data URIs emitted by SINGLE_FILE and related options. +var dataURIPrefix = 'data:application/octet-stream;base64,'; + +// Indicates whether filename is a base64 data URI. +function isDataURI(filename) { + // Prefix of data URIs emitted by SINGLE_FILE and related options. + return filename.startsWith(dataURIPrefix); +} + +// Indicates whether filename is delivered via file protocol (as opposed to http/https) +function isFileURI(filename) { + return filename.startsWith('file://'); +} +// end include: URIUtils.js +// include: runtime_exceptions.js +// end include: runtime_exceptions.js +var wasmBinaryFile; + wasmBinaryFile = dependencyFilename; + if (!isDataURI(wasmBinaryFile)) { + wasmBinaryFile = locateFile(wasmBinaryFile); + } + +function getBinarySync(file) { + if (file == wasmBinaryFile && wasmBinary) { + return new Uint8Array(wasmBinary); + } + if (readBinary) { + return readBinary(file); + } + throw "both async and sync fetching of the wasm failed"; +} + +function getBinaryPromise(binaryFile) { + // If we don't have the binary yet, try to load it asynchronously. + // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url. + // See https://github.com/github/fetch/pull/92#issuecomment-140665932 + // Cordova or Electron apps are typically loaded from a file:// url. + // So use fetch if it is available and the url is not a file, otherwise fall back to XHR. + if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) { + if (typeof fetch == 'function' + ) { + return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { + if (!response['ok']) { + throw "failed to load wasm binary file at '" + binaryFile + "'"; + } + return response['arrayBuffer'](); + }).catch(() => getBinarySync(binaryFile)); + } + } + + // Otherwise, getBinarySync should be able to get it synchronously + return Promise.resolve().then(() => getBinarySync(binaryFile)); +} + +function instantiateArrayBuffer(binaryFile, imports, receiver) { + return getBinaryPromise(binaryFile).then((binary) => { + return WebAssembly.instantiate(binary, imports); + }).then((instance) => { + return instance; + }).then(receiver, (reason) => { + err('failed to asynchronously prepare wasm: ' + reason); + + abort(reason); + }); +} + +function instantiateAsync(binary, binaryFile, imports, callback) { + if (!binary && + typeof WebAssembly.instantiateStreaming == 'function' && + !isDataURI(binaryFile) && + typeof fetch == 'function') { + return fetch(binaryFile, { credentials: 'same-origin' }).then((response) => { + // Suppress closure warning here since the upstream definition for + // instantiateStreaming only allows Promise rather than + // an actual Response. + // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed. + /** @suppress {checkTypes} */ + var result = WebAssembly.instantiateStreaming(response, imports); + + return result.then( + callback, + function(reason) { + // We expect the most common failure cause to be a bad MIME type for the binary, + // in which case falling back to ArrayBuffer instantiation should work. + err('wasm streaming compile failed: ' + reason); + err('falling back to ArrayBuffer instantiation'); + return instantiateArrayBuffer(binaryFile, imports, callback); + }); + }); + } + return instantiateArrayBuffer(binaryFile, imports, callback); +} + +// Create the wasm instance. +// Receives the wasm imports, returns the exports. +function createWasm() { + // prepare imports + var info = { + 'env': wasmImports, + 'wasi_snapshot_preview1': wasmImports, + }; + // Load the wasm module and create an instance of using native support in the JS engine. + // handle a generated wasm instance, receiving its exports and + // performing other necessary setup + /** @param {WebAssembly.Module=} module*/ + function receiveInstance(instance, module) { + var exports = instance.exports; + + exports = Asyncify.instrumentWasmExports(exports); + + Module['asm'] = exports; + + wasmMemory = Module['asm']['memory']; + updateMemoryViews(); + + wasmTable = Module['asm']['__indirect_function_table']; + + addOnInit(Module['asm']['__wasm_call_ctors']); + + removeRunDependency('wasm-instantiate'); + return exports; + } + // wait for the pthread pool (if any) + addRunDependency('wasm-instantiate'); + + // Prefer streaming instantiation if available. + function receiveInstantiationResult(result) { + // 'result' is a ResultObject object which has both the module and instance. + // receiveInstance() will swap in the exports (to Module.asm) so they can be called + // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line. + // When the regression is fixed, can restore the above PTHREADS-enabled path. + receiveInstance(result['instance']); + } + + // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback + // to manually instantiate the Wasm module themselves. This allows pages to + // run the instantiation parallel to any other async startup actions they are + // performing. + // Also pthreads and wasm workers initialize the wasm instance through this + // path. + if (Module['instantiateWasm']) { + + try { + return Module['instantiateWasm'](info, receiveInstance); + } catch(e) { + err('Module.instantiateWasm callback failed with error: ' + e); + return false; + } + } + + instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult); + return {}; // no exports yet; we'll fill them in later +} + +// Globals used by JS i64 conversions (see makeSetValue) +var tempDouble; +var tempI64; + +// include: runtime_debug.js +// end include: runtime_debug.js +// === Body === + +// end include: preamble.js + + /** @constructor */ + function ExitStatus(status) { + this.name = 'ExitStatus'; + this.message = `Program terminated with exit(${status})`; + this.status = status; + } + + var callRuntimeCallbacks = (callbacks) => { + while (callbacks.length > 0) { + // Pass the module as the first argument. + callbacks.shift()(Module); + } + }; + + + /** + * @param {number} ptr + * @param {string} type + */ + function getValue(ptr, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': return HEAP8[((ptr)>>0)]; + case 'i8': return HEAP8[((ptr)>>0)]; + case 'i16': return HEAP16[((ptr)>>1)]; + case 'i32': return HEAP32[((ptr)>>2)]; + case 'i64': abort('to do getValue(i64) use WASM_BIGINT'); + case 'float': return HEAPF32[((ptr)>>2)]; + case 'double': return HEAPF64[((ptr)>>3)]; + case '*': return HEAPU32[((ptr)>>2)]; + default: abort(`invalid type for getValue: ${type}`); + } + } + + + /** + * @param {number} ptr + * @param {number} value + * @param {string} type + */ + function setValue(ptr, value, type = 'i8') { + if (type.endsWith('*')) type = '*'; + switch (type) { + case 'i1': HEAP8[((ptr)>>0)] = value; break; + case 'i8': HEAP8[((ptr)>>0)] = value; break; + case 'i16': HEAP16[((ptr)>>1)] = value; break; + case 'i32': HEAP32[((ptr)>>2)] = value; break; + case 'i64': abort('to do setValue(i64) use WASM_BIGINT'); + case 'float': HEAPF32[((ptr)>>2)] = value; break; + case 'double': HEAPF64[((ptr)>>3)] = value; break; + case '*': HEAPU32[((ptr)>>2)] = value; break; + default: abort(`invalid type for setValue: ${type}`); + } + } + + var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined; + + /** + * Given a pointer 'idx' to a null-terminated UTF8-encoded string in the given + * array that contains uint8 values, returns a copy of that string as a + * Javascript String object. + * heapOrArray is either a regular array, or a JavaScript typed array view. + * @param {number} idx + * @param {number=} maxBytesToRead + * @return {string} + */ + var UTF8ArrayToString = (heapOrArray, idx, maxBytesToRead) => { + var endIdx = idx + maxBytesToRead; + var endPtr = idx; + // TextDecoder needs to know the byte length in advance, it doesn't stop on + // null terminator by itself. Also, use the length info to avoid running tiny + // strings through TextDecoder, since .subarray() allocates garbage. + // (As a tiny code save trick, compare endPtr against endIdx using a negation, + // so that undefined means Infinity) + while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr; + + if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { + return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr)); + } + var str = ''; + // If building with TextDecoder, we have already computed the string length + // above, so test loop end condition against that + while (idx < endPtr) { + // For UTF8 byte structure, see: + // http://en.wikipedia.org/wiki/UTF-8#Description + // https://www.ietf.org/rfc/rfc2279.txt + // https://tools.ietf.org/html/rfc3629 + var u0 = heapOrArray[idx++]; + if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } + var u1 = heapOrArray[idx++] & 63; + if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } + var u2 = heapOrArray[idx++] & 63; + if ((u0 & 0xF0) == 0xE0) { + u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; + } else { + u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63); + } + + if (u0 < 0x10000) { + str += String.fromCharCode(u0); + } else { + var ch = u0 - 0x10000; + str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); + } + } + return str; + }; + + /** + * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the + * emscripten HEAP, returns a copy of that string as a Javascript String object. + * + * @param {number} ptr + * @param {number=} maxBytesToRead - An optional length that specifies the + * maximum number of bytes to read. You can omit this parameter to scan the + * string until the first 0 byte. If maxBytesToRead is passed, and the string + * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the + * string will cut short at that byte index (i.e. maxBytesToRead will not + * produce a string of exact length [ptr, ptr+maxBytesToRead[) N.B. mixing + * frequent uses of UTF8ToString() with and without maxBytesToRead may throw + * JS JIT optimizations off, so it is worth to consider consistently using one + * @return {string} + */ + var UTF8ToString = (ptr, maxBytesToRead) => { + return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''; + }; + Module['UTF8ToString'] = UTF8ToString; + var ___assert_fail = (condition, filename, line, func) => { + abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']); + }; + + var ___call_sighandler = (fp, sig) => ((a1) => dynCall_vi.apply(null, [fp, a1]))(sig); + + var initRandomFill = () => { + if (typeof crypto == 'object' && typeof crypto['getRandomValues'] == 'function') { + // for modern web browsers + return (view) => crypto.getRandomValues(view); + } else + // we couldn't find a proper implementation, as Math.random() is not suitable for /dev/random, see emscripten-core/emscripten/pull/7096 + abort("initRandomDevice"); + }; + var randomFill = (view) => { + // Lazily init on the first invocation. + return (randomFill = initRandomFill())(view); + }; + + var PATH = { + isAbs:(path) => path.charAt(0) === '/', + splitPath:(filename) => { + var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; + return splitPathRe.exec(filename).slice(1); + }, + normalizeArray:(parts, allowAboveRoot) => { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up; up--) { + parts.unshift('..'); + } + } + return parts; + }, + normalize:(path) => { + var isAbsolute = PATH.isAbs(path), + trailingSlash = path.substr(-1) === '/'; + // Normalize the path + path = PATH.normalizeArray(path.split('/').filter((p) => !!p), !isAbsolute).join('/'); + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + return (isAbsolute ? '/' : '') + path; + }, + dirname:(path) => { + var result = PATH.splitPath(path), + root = result[0], + dir = result[1]; + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + return root + dir; + }, + basename:(path) => { + // EMSCRIPTEN return '/'' for '/', not an empty string + if (path === '/') return '/'; + path = PATH.normalize(path); + path = path.replace(/\/$/, ""); + var lastSlash = path.lastIndexOf('/'); + if (lastSlash === -1) return path; + return path.substr(lastSlash+1); + }, + join:function() { + var paths = Array.prototype.slice.call(arguments); + return PATH.normalize(paths.join('/')); + }, + join2:(l, r) => { + return PATH.normalize(l + '/' + r); + }, + }; + + + var PATH_FS = { + resolve:function() { + var resolvedPath = '', + resolvedAbsolute = false; + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : FS.cwd(); + // Skip empty and invalid entries + if (typeof path != 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + return ''; // an invalid portion invalidates the whole thing + } + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = PATH.isAbs(path); + } + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter((p) => !!p), !resolvedAbsolute).join('/'); + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; + }, + relative:(from, to) => { + from = PATH_FS.resolve(from).substr(1); + to = PATH_FS.resolve(to).substr(1); + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + return outputParts.join('/'); + }, + }; + + + + var FS_stdin_getChar_buffer = []; + + var lengthBytesUTF8 = (str) => { + var len = 0; + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code + // unit, not a Unicode code point of the character! So decode + // UTF16->UTF32->UTF8. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + var c = str.charCodeAt(i); // possibly a lead surrogate + if (c <= 0x7F) { + len++; + } else if (c <= 0x7FF) { + len += 2; + } else if (c >= 0xD800 && c <= 0xDFFF) { + len += 4; ++i; + } else { + len += 3; + } + } + return len; + }; + Module['lengthBytesUTF8'] = lengthBytesUTF8; + + var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { + // Parameter maxBytesToWrite is not optional. Negative values, 0, null, + // undefined and false each don't write out any bytes. + if (!(maxBytesToWrite > 0)) + return 0; + + var startIdx = outIdx; + var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. + for (var i = 0; i < str.length; ++i) { + // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code + // unit, not a Unicode code point of the character! So decode + // UTF16->UTF32->UTF8. + // See http://unicode.org/faq/utf_bom.html#utf16-3 + // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description + // and https://www.ietf.org/rfc/rfc2279.txt + // and https://tools.ietf.org/html/rfc3629 + var u = str.charCodeAt(i); // possibly a lead surrogate + if (u >= 0xD800 && u <= 0xDFFF) { + var u1 = str.charCodeAt(++i); + u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF); + } + if (u <= 0x7F) { + if (outIdx >= endIdx) break; + heap[outIdx++] = u; + } else if (u <= 0x7FF) { + if (outIdx + 1 >= endIdx) break; + heap[outIdx++] = 0xC0 | (u >> 6); + heap[outIdx++] = 0x80 | (u & 63); + } else if (u <= 0xFFFF) { + if (outIdx + 2 >= endIdx) break; + heap[outIdx++] = 0xE0 | (u >> 12); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } else { + if (outIdx + 3 >= endIdx) break; + heap[outIdx++] = 0xF0 | (u >> 18); + heap[outIdx++] = 0x80 | ((u >> 12) & 63); + heap[outIdx++] = 0x80 | ((u >> 6) & 63); + heap[outIdx++] = 0x80 | (u & 63); + } + } + // Null-terminate the pointer to the buffer. + heap[outIdx] = 0; + return outIdx - startIdx; + }; + /** @type {function(string, boolean=, number=)} */ + function intArrayFromString(stringy, dontAddNull, length) { + var len = length > 0 ? length : lengthBytesUTF8(stringy)+1; + var u8array = new Array(len); + var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length); + if (dontAddNull) u8array.length = numBytesWritten; + return u8array; + } + var FS_stdin_getChar = () => { + if (!FS_stdin_getChar_buffer.length) { + var result = null; + if (typeof window != 'undefined' && + typeof window.prompt == 'function') { + // Browser. + result = window.prompt('Input: '); // returns null on cancel + if (result !== null) { + result += '\n'; + } + } else if (typeof readline == 'function') { + // Command line. + result = readline(); + if (result !== null) { + result += '\n'; + } + } + if (!result) { + return null; + } + FS_stdin_getChar_buffer = intArrayFromString(result, true); + } + return FS_stdin_getChar_buffer.shift(); + }; + var TTY = { + ttys:[], + init:function () { + // https://github.com/emscripten-core/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // currently, FS.init does not distinguish if process.stdin is a file or TTY + // // device, it always assumes it's a TTY device. because of this, we're forcing + // // process.stdin to UTF8 encoding to at least make stdin reading compatible + // // with text files until FS.init can be refactored. + // process.stdin.setEncoding('utf8'); + // } + }, + shutdown:function() { + // https://github.com/emscripten-core/emscripten/pull/1555 + // if (ENVIRONMENT_IS_NODE) { + // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)? + // // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation + // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists? + // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle + // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call + // process.stdin.pause(); + // } + }, + register:function(dev, ops) { + TTY.ttys[dev] = { input: [], output: [], ops: ops }; + FS.registerDevice(dev, TTY.stream_ops); + }, + stream_ops:{ + open:function(stream) { + var tty = TTY.ttys[stream.node.rdev]; + if (!tty) { + throw new FS.ErrnoError(43); + } + stream.tty = tty; + stream.seekable = false; + }, + close:function(stream) { + // flush any pending line data + stream.tty.ops.fsync(stream.tty); + }, + fsync:function(stream) { + stream.tty.ops.fsync(stream.tty); + }, + read:function(stream, buffer, offset, length, pos /* ignored */) { + if (!stream.tty || !stream.tty.ops.get_char) { + throw new FS.ErrnoError(60); + } + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = stream.tty.ops.get_char(stream.tty); + } catch (e) { + throw new FS.ErrnoError(29); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(6); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + }, + write:function(stream, buffer, offset, length, pos) { + if (!stream.tty || !stream.tty.ops.put_char) { + throw new FS.ErrnoError(60); + } + try { + for (var i = 0; i < length; i++) { + stream.tty.ops.put_char(stream.tty, buffer[offset+i]); + } + } catch (e) { + throw new FS.ErrnoError(29); + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + }, + }, + default_tty_ops:{ + get_char:function(tty) { + return FS_stdin_getChar(); + }, + put_char:function(tty, val) { + if (val === null || val === 10) { + out(UTF8ArrayToString(tty.output, 0)); + tty.output = []; + } else { + if (val != 0) tty.output.push(val); // val == 0 would cut text output off in the middle. + } + }, + fsync:function(tty) { + if (tty.output && tty.output.length > 0) { + out(UTF8ArrayToString(tty.output, 0)); + tty.output = []; + } + }, + ioctl_tcgets:function(tty) { + // typical setting + return { + c_iflag: 25856, + c_oflag: 5, + c_cflag: 191, + c_lflag: 35387, + c_cc: [ + 0x03, 0x1c, 0x7f, 0x15, 0x04, 0x00, 0x01, 0x00, 0x11, 0x13, 0x1a, 0x00, + 0x12, 0x0f, 0x17, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ] + }; + }, + ioctl_tcsets:function(tty, optional_actions, data) { + // currently just ignore + return 0; + }, + ioctl_tiocgwinsz:function(tty) { + return [24, 80]; + }, + }, + default_tty1_ops:{ + put_char:function(tty, val) { + if (val === null || val === 10) { + err(UTF8ArrayToString(tty.output, 0)); + tty.output = []; + } else { + if (val != 0) tty.output.push(val); + } + }, + fsync:function(tty) { + if (tty.output && tty.output.length > 0) { + err(UTF8ArrayToString(tty.output, 0)); + tty.output = []; + } + }, + }, + }; + + + var zeroMemory = (address, size) => { + HEAPU8.fill(0, address, address + size); + return address; + }; + + var alignMemory = (size, alignment) => { + return Math.ceil(size / alignment) * alignment; + }; + var mmapAlloc = (size) => { + size = alignMemory(size, 65536); + var ptr = _emscripten_builtin_memalign(65536, size); + if (!ptr) return 0; + return zeroMemory(ptr, size); + }; + var MEMFS = { + ops_table:null, + mount(mount) { + return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + }, + createNode(parent, name, mode, dev) { + if (FS.isBlkdev(mode) || FS.isFIFO(mode)) { + // no supported + throw new FS.ErrnoError(63); + } + if (!MEMFS.ops_table) { + MEMFS.ops_table = { + dir: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr, + lookup: MEMFS.node_ops.lookup, + mknod: MEMFS.node_ops.mknod, + rename: MEMFS.node_ops.rename, + unlink: MEMFS.node_ops.unlink, + rmdir: MEMFS.node_ops.rmdir, + readdir: MEMFS.node_ops.readdir, + symlink: MEMFS.node_ops.symlink + }, + stream: { + llseek: MEMFS.stream_ops.llseek + } + }, + file: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr + }, + stream: { + llseek: MEMFS.stream_ops.llseek, + read: MEMFS.stream_ops.read, + write: MEMFS.stream_ops.write, + allocate: MEMFS.stream_ops.allocate, + mmap: MEMFS.stream_ops.mmap, + msync: MEMFS.stream_ops.msync + } + }, + link: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr, + readlink: MEMFS.node_ops.readlink + }, + stream: {} + }, + chrdev: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr + }, + stream: FS.chrdev_stream_ops + } + }; + } + var node = FS.createNode(parent, name, mode, dev); + if (FS.isDir(node.mode)) { + node.node_ops = MEMFS.ops_table.dir.node; + node.stream_ops = MEMFS.ops_table.dir.stream; + node.contents = {}; + } else if (FS.isFile(node.mode)) { + node.node_ops = MEMFS.ops_table.file.node; + node.stream_ops = MEMFS.ops_table.file.stream; + node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity. + // When the byte data of the file is populated, this will point to either a typed array, or a normal JS array. Typed arrays are preferred + // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size + // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme. + node.contents = null; + } else if (FS.isLink(node.mode)) { + node.node_ops = MEMFS.ops_table.link.node; + node.stream_ops = MEMFS.ops_table.link.stream; + } else if (FS.isChrdev(node.mode)) { + node.node_ops = MEMFS.ops_table.chrdev.node; + node.stream_ops = MEMFS.ops_table.chrdev.stream; + } + node.timestamp = Date.now(); + // add the new node to the parent + if (parent) { + parent.contents[name] = node; + parent.timestamp = node.timestamp; + } + return node; + }, + getFileDataAsTypedArray(node) { + if (!node.contents) return new Uint8Array(0); + if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes. + return new Uint8Array(node.contents); + }, + expandFileStorage(node, newCapacity) { + var prevCapacity = node.contents ? node.contents.length : 0; + if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough. + // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity. + // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to + // avoid overshooting the allocation cap by a very large margin. + var CAPACITY_DOUBLING_MAX = 1024 * 1024; + newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0); + if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding. + var oldContents = node.contents; + node.contents = new Uint8Array(newCapacity); // Allocate new storage. + if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); // Copy old data over to the new storage. + }, + resizeFileStorage(node, newSize) { + if (node.usedBytes == newSize) return; + if (newSize == 0) { + node.contents = null; // Fully decommit when requesting a resize to zero. + node.usedBytes = 0; + } else { + var oldContents = node.contents; + node.contents = new Uint8Array(newSize); // Allocate new storage. + if (oldContents) { + node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage. + } + node.usedBytes = newSize; + } + }, + node_ops:{ + getattr(node) { + var attr = {}; + // device numbers reuse inode numbers. + attr.dev = FS.isChrdev(node.mode) ? node.id : 1; + attr.ino = node.id; + attr.mode = node.mode; + attr.nlink = 1; + attr.uid = 0; + attr.gid = 0; + attr.rdev = node.rdev; + if (FS.isDir(node.mode)) { + attr.size = 4096; + } else if (FS.isFile(node.mode)) { + attr.size = node.usedBytes; + } else if (FS.isLink(node.mode)) { + attr.size = node.link.length; + } else { + attr.size = 0; + } + attr.atime = new Date(node.timestamp); + attr.mtime = new Date(node.timestamp); + attr.ctime = new Date(node.timestamp); + // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize), + // but this is not required by the standard. + attr.blksize = 4096; + attr.blocks = Math.ceil(attr.size / attr.blksize); + return attr; + }, + setattr(node, attr) { + if (attr.mode !== undefined) { + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + node.timestamp = attr.timestamp; + } + if (attr.size !== undefined) { + MEMFS.resizeFileStorage(node, attr.size); + } + }, + lookup(parent, name) { + throw FS.genericErrors[44]; + }, + mknod(parent, name, mode, dev) { + return MEMFS.createNode(parent, name, mode, dev); + }, + rename(old_node, new_dir, new_name) { + // if we're overwriting a directory at new_name, make sure it's empty. + if (FS.isDir(old_node.mode)) { + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + } + if (new_node) { + for (var i in new_node.contents) { + throw new FS.ErrnoError(55); + } + } + } + // do the internal rewiring + delete old_node.parent.contents[old_node.name]; + old_node.parent.timestamp = Date.now() + old_node.name = new_name; + new_dir.contents[new_name] = old_node; + new_dir.timestamp = old_node.parent.timestamp; + old_node.parent = new_dir; + }, + unlink(parent, name) { + delete parent.contents[name]; + parent.timestamp = Date.now(); + }, + rmdir(parent, name) { + var node = FS.lookupNode(parent, name); + for (var i in node.contents) { + throw new FS.ErrnoError(55); + } + delete parent.contents[name]; + parent.timestamp = Date.now(); + }, + readdir(node) { + var entries = ['.', '..']; + for (var key in node.contents) { + if (!node.contents.hasOwnProperty(key)) { + continue; + } + entries.push(key); + } + return entries; + }, + symlink(parent, newname, oldpath) { + var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0); + node.link = oldpath; + return node; + }, + readlink(node) { + if (!FS.isLink(node.mode)) { + throw new FS.ErrnoError(28); + } + return node.link; + }, + }, + stream_ops:{ + read(stream, buffer, offset, length, position) { + var contents = stream.node.contents; + if (position >= stream.node.usedBytes) return 0; + var size = Math.min(stream.node.usedBytes - position, length); + if (size > 8 && contents.subarray) { // non-trivial, and typed array + buffer.set(contents.subarray(position, position + size), offset); + } else { + for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i]; + } + return size; + }, + write(stream, buffer, offset, length, position, canOwn) { + // If the buffer is located in main memory (HEAP), and if + // memory can grow, we can't hold on to references of the + // memory buffer, as they may get invalidated. That means we + // need to do copy its contents. + if (buffer.buffer === HEAP8.buffer) { + canOwn = false; + } + + if (!length) return 0; + var node = stream.node; + node.timestamp = Date.now(); + + if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array? + if (canOwn) { + node.contents = buffer.subarray(offset, offset + length); + node.usedBytes = length; + return length; + } else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data. + node.contents = buffer.slice(offset, offset + length); + node.usedBytes = length; + return length; + } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file? + node.contents.set(buffer.subarray(offset, offset + length), position); + return length; + } + } + + // Appending to an existing file and we need to reallocate, or source data did not come as a typed array. + MEMFS.expandFileStorage(node, position+length); + if (node.contents.subarray && buffer.subarray) { + // Use typed array write which is available. + node.contents.set(buffer.subarray(offset, offset + length), position); + } else { + for (var i = 0; i < length; i++) { + node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not. + } + } + node.usedBytes = Math.max(node.usedBytes, position + length); + return length; + }, + llseek(stream, offset, whence) { + var position = offset; + if (whence === 1) { + position += stream.position; + } else if (whence === 2) { + if (FS.isFile(stream.node.mode)) { + position += stream.node.usedBytes; + } + } + if (position < 0) { + throw new FS.ErrnoError(28); + } + return position; + }, + allocate(stream, offset, length) { + MEMFS.expandFileStorage(stream.node, offset + length); + stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length); + }, + mmap(stream, length, position, prot, flags) { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(43); + } + var ptr; + var allocated; + var contents = stream.node.contents; + // Only make a new copy when MAP_PRIVATE is specified. + if (!(flags & 2) && contents.buffer === HEAP8.buffer) { + // We can't emulate MAP_SHARED when the file is not backed by the + // buffer we're mapping to (e.g. the HEAP buffer). + allocated = false; + ptr = contents.byteOffset; + } else { + // Try to avoid unnecessary slices. + if (position > 0 || position + length < contents.length) { + if (contents.subarray) { + contents = contents.subarray(position, position + length); + } else { + contents = Array.prototype.slice.call(contents, position, position + length); + } + } + allocated = true; + ptr = mmapAlloc(length); + if (!ptr) { + throw new FS.ErrnoError(48); + } + HEAP8.set(contents, ptr); + } + return { ptr, allocated }; + }, + msync(stream, buffer, offset, length, mmapFlags) { + MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false); + // should we check if bytesWritten and length are the same? + return 0; + }, + }, + }; + + /** @param {boolean=} noRunDep */ + var asyncLoad = (url, onload, onerror, noRunDep) => { + var dep = !noRunDep ? getUniqueRunDependency(`al ${url}`) : ''; + readAsync(url, (arrayBuffer) => { + assert(arrayBuffer, `Loading data file "${url}" failed (no arrayBuffer).`); + onload(new Uint8Array(arrayBuffer)); + if (dep) removeRunDependency(dep); + }, (event) => { + if (onerror) { + onerror(); + } else { + throw `Loading data file "${url}" failed.`; + } + }); + if (dep) addRunDependency(dep); + }; + + + var preloadPlugins = Module['preloadPlugins'] || []; + function FS_handledByPreloadPlugin(byteArray, fullname, finish, onerror) { + // Ensure plugins are ready. + if (typeof Browser != 'undefined') Browser.init(); + + var handled = false; + preloadPlugins.forEach(function(plugin) { + if (handled) return; + if (plugin['canHandle'](fullname)) { + plugin['handle'](byteArray, fullname, finish, onerror); + handled = true; + } + }); + return handled; + } + function FS_createPreloadedFile(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) { + // TODO we should allow people to just pass in a complete filename instead + // of parent and name being that we just join them anyways + var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent; + var dep = getUniqueRunDependency(`cp ${fullname}`); // might have several active requests for the same fullname + function processData(byteArray) { + function finish(byteArray) { + if (preFinish) preFinish(); + if (!dontCreateFile) { + FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); + } + if (onload) onload(); + removeRunDependency(dep); + } + if (FS_handledByPreloadPlugin(byteArray, fullname, finish, () => { + if (onerror) onerror(); + removeRunDependency(dep); + })) { + return; + } + finish(byteArray); + } + addRunDependency(dep); + if (typeof url == 'string') { + asyncLoad(url, (byteArray) => processData(byteArray), onerror); + } else { + processData(url); + } + } + + function FS_modeStringToFlags(str) { + var flagModes = { + 'r': 0, + 'r+': 2, + 'w': 512 | 64 | 1, + 'w+': 512 | 64 | 2, + 'a': 1024 | 64 | 1, + 'a+': 1024 | 64 | 2, + }; + var flags = flagModes[str]; + if (typeof flags == 'undefined') { + throw new Error(`Unknown file open mode: ${str}`); + } + return flags; + } + + function FS_getMode(canRead, canWrite) { + var mode = 0; + if (canRead) mode |= 292 | 73; + if (canWrite) mode |= 146; + return mode; + } + + + + + + + var ERRNO_CODES = { + }; + var PROXYFS = { + mount(mount) { + return PROXYFS.createNode(null, '/', mount.opts.fs.lstat(mount.opts.root).mode, 0); + }, + createNode(parent, name, mode, dev) { + if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var node = FS.createNode(parent, name, mode); + node.node_ops = PROXYFS.node_ops; + node.stream_ops = PROXYFS.stream_ops; + return node; + }, + realPath(node) { + var parts = []; + while (node.parent !== node) { + parts.push(node.name); + node = node.parent; + } + parts.push(node.mount.opts.root); + parts.reverse(); + return PATH.join.apply(null, parts); + }, + node_ops:{ + getattr(node) { + var path = PROXYFS.realPath(node); + var stat; + try { + stat = node.mount.opts.fs.lstat(path); + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return { + dev: stat.dev, + ino: stat.ino, + mode: stat.mode, + nlink: stat.nlink, + uid: stat.uid, + gid: stat.gid, + rdev: stat.rdev, + size: stat.size, + atime: stat.atime, + mtime: stat.mtime, + ctime: stat.ctime, + blksize: stat.blksize, + blocks: stat.blocks + }; + }, + setattr(node, attr) { + var path = PROXYFS.realPath(node); + try { + if (attr.mode !== undefined) { + node.mount.opts.fs.chmod(path, attr.mode); + // update the common node structure mode as well + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + var date = new Date(attr.timestamp); + node.mount.opts.fs.utime(path, date, date); + } + if (attr.size !== undefined) { + node.mount.opts.fs.truncate(path, attr.size); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, + lookup(parent, name) { + try { + var path = PATH.join2(PROXYFS.realPath(parent), name); + var mode = parent.mount.opts.fs.lstat(path).mode; + var node = PROXYFS.createNode(parent, name, mode); + return node; + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, + mknod(parent, name, mode, dev) { + var node = PROXYFS.createNode(parent, name, mode, dev); + // create the backing node for this in the fs root as well + var path = PROXYFS.realPath(node); + try { + if (FS.isDir(node.mode)) { + node.mount.opts.fs.mkdir(path, node.mode); + } else { + node.mount.opts.fs.writeFile(path, '', { mode: node.mode }); + } + } catch (e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return node; + }, + rename(oldNode, newDir, newName) { + var oldPath = PROXYFS.realPath(oldNode); + var newPath = PATH.join2(PROXYFS.realPath(newDir), newName); + try { + oldNode.mount.opts.fs.rename(oldPath, newPath); + oldNode.name = newName; + oldNode.parent = newDir; + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, + unlink(parent, name) { + var path = PATH.join2(PROXYFS.realPath(parent), name); + try { + parent.mount.opts.fs.unlink(path); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, + rmdir(parent, name) { + var path = PATH.join2(PROXYFS.realPath(parent), name); + try { + parent.mount.opts.fs.rmdir(path); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, + readdir(node) { + var path = PROXYFS.realPath(node); + try { + return node.mount.opts.fs.readdir(path); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, + symlink(parent, newName, oldPath) { + var newPath = PATH.join2(PROXYFS.realPath(parent), newName); + try { + parent.mount.opts.fs.symlink(oldPath, newPath); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, + readlink(node) { + var path = PROXYFS.realPath(node); + try { + return node.mount.opts.fs.readlink(path); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, + }, + stream_ops:{ + open(stream) { + var path = PROXYFS.realPath(stream.node); + try { + stream.nfd = stream.node.mount.opts.fs.open(path,stream.flags); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, + close(stream) { + try { + stream.node.mount.opts.fs.close(stream.nfd); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, + read(stream, buffer, offset, length, position) { + try { + return stream.node.mount.opts.fs.read(stream.nfd, buffer, offset, length, position); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, + write(stream, buffer, offset, length, position) { + try { + return stream.node.mount.opts.fs.write(stream.nfd, buffer, offset, length, position); + } catch(e) { + if (!e.code) throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }, + llseek(stream, offset, whence) { + var position = offset; + if (whence === 1) { + position += stream.position; + } else if (whence === 2) { + if (FS.isFile(stream.node.mode)) { + try { + var stat = stream.node.node_ops.getattr(stream.node); + position += stat.size; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + } + } + + if (position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + + return position; + }, + }, + }; + var FS = { + root:null, + mounts:[], + devices:{ + }, + streams:[], + nextInode:1, + nameTable:null, + currentPath:"/", + initialized:false, + ignorePermissions:true, + ErrnoError:null, + genericErrors:{ + }, + filesystems:null, + syncFSRequests:0, + lookupPath:(path, opts = {}) => { + path = PATH_FS.resolve(path); + + if (!path) return { path: '', node: null }; + + var defaults = { + follow_mount: true, + recurse_count: 0 + }; + opts = Object.assign(defaults, opts) + + if (opts.recurse_count > 8) { // max recursive lookup of 8 + throw new FS.ErrnoError(32); + } + + // split the absolute path + var parts = path.split('/').filter((p) => !!p); + + // start at the root + var current = FS.root; + var current_path = '/'; + + for (var i = 0; i < parts.length; i++) { + var islast = (i === parts.length-1); + if (islast && opts.parent) { + // stop resolving + break; + } + + current = FS.lookupNode(current, parts[i]); + current_path = PATH.join2(current_path, parts[i]); + + // jump to the mount's root node if this is a mountpoint + if (FS.isMountpoint(current)) { + if (!islast || (islast && opts.follow_mount)) { + current = current.mounted.root; + } + } + + // by default, lookupPath will not follow a symlink if it is the final path component. + // setting opts.follow = true will override this behavior. + if (!islast || opts.follow) { + var count = 0; + while (FS.isLink(current.mode)) { + var link = FS.readlink(current_path); + current_path = PATH_FS.resolve(PATH.dirname(current_path), link); + + var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count + 1 }); + current = lookup.node; + + if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX). + throw new FS.ErrnoError(32); + } + } + } + } + + return { path: current_path, node: current }; + }, + getPath:(node) => { + var path; + while (true) { + if (FS.isRoot(node)) { + var mount = node.mount.mountpoint; + if (!path) return mount; + return mount[mount.length-1] !== '/' ? `${mount}/${path}` : mount + path; + } + path = path ? `${node.name}/${path}` : node.name; + node = node.parent; + } + }, + hashName:(parentid, name) => { + var hash = 0; + + for (var i = 0; i < name.length; i++) { + hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0; + } + return ((parentid + hash) >>> 0) % FS.nameTable.length; + }, + hashAddNode:(node) => { + var hash = FS.hashName(node.parent.id, node.name); + node.name_next = FS.nameTable[hash]; + FS.nameTable[hash] = node; + }, + hashRemoveNode:(node) => { + var hash = FS.hashName(node.parent.id, node.name); + if (FS.nameTable[hash] === node) { + FS.nameTable[hash] = node.name_next; + } else { + var current = FS.nameTable[hash]; + while (current) { + if (current.name_next === node) { + current.name_next = node.name_next; + break; + } + current = current.name_next; + } + } + }, + lookupNode:(parent, name) => { + var errCode = FS.mayLookup(parent); + if (errCode) { + throw new FS.ErrnoError(errCode, parent); + } + var hash = FS.hashName(parent.id, name); + for (var node = FS.nameTable[hash]; node; node = node.name_next) { + var nodeName = node.name; + if (node.parent.id === parent.id && nodeName === name) { + return node; + } + } + // if we failed to find it in the cache, call into the VFS + return FS.lookup(parent, name); + }, + createNode:(parent, name, mode, rdev) => { + var node = new FS.FSNode(parent, name, mode, rdev); + + FS.hashAddNode(node); + + return node; + }, + destroyNode:(node) => { + FS.hashRemoveNode(node); + }, + isRoot:(node) => { + return node === node.parent; + }, + isMountpoint:(node) => { + return !!node.mounted; + }, + isFile:(mode) => { + return (mode & 61440) === 32768; + }, + isDir:(mode) => { + return (mode & 61440) === 16384; + }, + isLink:(mode) => { + return (mode & 61440) === 40960; + }, + isChrdev:(mode) => { + return (mode & 61440) === 8192; + }, + isBlkdev:(mode) => { + return (mode & 61440) === 24576; + }, + isFIFO:(mode) => { + return (mode & 61440) === 4096; + }, + isSocket:(mode) => { + return (mode & 49152) === 49152; + }, + flagsToPermissionString:(flag) => { + var perms = ['r', 'w', 'rw'][flag & 3]; + if ((flag & 512)) { + perms += 'w'; + } + return perms; + }, + nodePermissions:(node, perms) => { + if (FS.ignorePermissions) { + return 0; + } + // return 0 if any user, group or owner bits are set. + if (perms.includes('r') && !(node.mode & 292)) { + return 2; + } else if (perms.includes('w') && !(node.mode & 146)) { + return 2; + } else if (perms.includes('x') && !(node.mode & 73)) { + return 2; + } + return 0; + }, + mayLookup:(dir) => { + var errCode = FS.nodePermissions(dir, 'x'); + if (errCode) return errCode; + if (!dir.node_ops.lookup) return 2; + return 0; + }, + mayCreate:(dir, name) => { + try { + var node = FS.lookupNode(dir, name); + return 20; + } catch (e) { + } + return FS.nodePermissions(dir, 'wx'); + }, + mayDelete:(dir, name, isdir) => { + var node; + try { + node = FS.lookupNode(dir, name); + } catch (e) { + return e.errno; + } + var errCode = FS.nodePermissions(dir, 'wx'); + if (errCode) { + return errCode; + } + if (isdir) { + if (!FS.isDir(node.mode)) { + return 54; + } + if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) { + return 10; + } + } else { + if (FS.isDir(node.mode)) { + return 31; + } + } + return 0; + }, + mayOpen:(node, flags) => { + if (!node) { + return 44; + } + if (FS.isLink(node.mode)) { + return 32; + } else if (FS.isDir(node.mode)) { + if (FS.flagsToPermissionString(flags) !== 'r' || // opening for write + (flags & 512)) { // TODO: check for O_SEARCH? (== search for dir only) + return 31; + } + } + return FS.nodePermissions(node, FS.flagsToPermissionString(flags)); + }, + MAX_OPEN_FDS:4096, + nextfd:() => { + for (var fd = 0; fd <= FS.MAX_OPEN_FDS; fd++) { + if (!FS.streams[fd]) { + return fd; + } + } + throw new FS.ErrnoError(33); + }, + getStreamChecked:(fd) => { + var stream = FS.getStream(fd); + if (!stream) { + throw new FS.ErrnoError(8); + } + return stream; + }, + getStream:(fd) => FS.streams[fd], + createStream:(stream, fd = -1) => { + if (!FS.FSStream) { + FS.FSStream = /** @constructor */ function() { + this.shared = { }; + }; + FS.FSStream.prototype = {}; + Object.defineProperties(FS.FSStream.prototype, { + object: { + /** @this {FS.FSStream} */ + get() { return this.node; }, + /** @this {FS.FSStream} */ + set(val) { this.node = val; } + }, + isRead: { + /** @this {FS.FSStream} */ + get() { return (this.flags & 2097155) !== 1; } + }, + isWrite: { + /** @this {FS.FSStream} */ + get() { return (this.flags & 2097155) !== 0; } + }, + isAppend: { + /** @this {FS.FSStream} */ + get() { return (this.flags & 1024); } + }, + flags: { + /** @this {FS.FSStream} */ + get() { return this.shared.flags; }, + /** @this {FS.FSStream} */ + set(val) { this.shared.flags = val; }, + }, + position : { + /** @this {FS.FSStream} */ + get() { return this.shared.position; }, + /** @this {FS.FSStream} */ + set(val) { this.shared.position = val; }, + }, + }); + } + // clone it, so we can return an instance of FSStream + stream = Object.assign(new FS.FSStream(), stream); + if (fd == -1) { + fd = FS.nextfd(); + } + stream.fd = fd; + FS.streams[fd] = stream; + return stream; + }, + closeStream:(fd) => { + FS.streams[fd] = null; + }, + chrdev_stream_ops:{ + open:(stream) => { + var device = FS.getDevice(stream.node.rdev); + // override node's stream ops with the device's + stream.stream_ops = device.stream_ops; + // forward the open call + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + }, + llseek:() => { + throw new FS.ErrnoError(70); + }, + }, + major:(dev) => ((dev) >> 8), + minor:(dev) => ((dev) & 0xff), + makedev:(ma, mi) => ((ma) << 8 | (mi)), + registerDevice:(dev, ops) => { + FS.devices[dev] = { stream_ops: ops }; + }, + getDevice:(dev) => FS.devices[dev], + getMounts:(mount) => { + var mounts = []; + var check = [mount]; + + while (check.length) { + var m = check.pop(); + + mounts.push(m); + + check.push.apply(check, m.mounts); + } + + return mounts; + }, + syncfs:(populate, callback) => { + if (typeof populate == 'function') { + callback = populate; + populate = false; + } + + FS.syncFSRequests++; + + if (FS.syncFSRequests > 1) { + err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`); + } + + var mounts = FS.getMounts(FS.root.mount); + var completed = 0; + + function doCallback(errCode) { + FS.syncFSRequests--; + return callback(errCode); + } + + function done(errCode) { + if (errCode) { + if (!done.errored) { + done.errored = true; + return doCallback(errCode); + } + return; + } + if (++completed >= mounts.length) { + doCallback(null); + } + }; + + // sync all mounts + mounts.forEach((mount) => { + if (!mount.type.syncfs) { + return done(null); + } + mount.type.syncfs(mount, populate, done); + }); + }, + mount:(type, opts, mountpoint) => { + var root = mountpoint === '/'; + var pseudo = !mountpoint; + var node; + + if (root && FS.root) { + throw new FS.ErrnoError(10); + } else if (!root && !pseudo) { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + mountpoint = lookup.path; // use the absolute path + node = lookup.node; + + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(10); + } + + if (!FS.isDir(node.mode)) { + throw new FS.ErrnoError(54); + } + } + + var mount = { + type, + opts, + mountpoint, + mounts: [] + }; + + // create a root node for the fs + var mountRoot = type.mount(mount); + mountRoot.mount = mount; + mount.root = mountRoot; + + if (root) { + FS.root = mountRoot; + } else if (node) { + // set as a mountpoint + node.mounted = mount; + + // add the new mount to the current mount's children + if (node.mount) { + node.mount.mounts.push(mount); + } + } + + return mountRoot; + }, + unmount:(mountpoint) => { + var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); + + if (!FS.isMountpoint(lookup.node)) { + throw new FS.ErrnoError(28); + } + + // destroy the nodes for this mount, and all its child mounts + var node = lookup.node; + var mount = node.mounted; + var mounts = FS.getMounts(mount); + + Object.keys(FS.nameTable).forEach((hash) => { + var current = FS.nameTable[hash]; + + while (current) { + var next = current.name_next; + + if (mounts.includes(current.mount)) { + FS.destroyNode(current); + } + + current = next; + } + }); + + // no longer a mountpoint + node.mounted = null; + + // remove this mount from the child mounts + var idx = node.mount.mounts.indexOf(mount); + node.mount.mounts.splice(idx, 1); + }, + lookup:(parent, name) => { + return parent.node_ops.lookup(parent, name); + }, + mknod:(path, mode, dev) => { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + if (!name || name === '.' || name === '..') { + throw new FS.ErrnoError(28); + } + var errCode = FS.mayCreate(parent, name); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.mknod) { + throw new FS.ErrnoError(63); + } + return parent.node_ops.mknod(parent, name, mode, dev); + }, + create:(path, mode) => { + mode = mode !== undefined ? mode : 438 /* 0666 */; + mode &= 4095; + mode |= 32768; + return FS.mknod(path, mode, 0); + }, + mkdir:(path, mode) => { + mode = mode !== undefined ? mode : 511 /* 0777 */; + mode &= 511 | 512; + mode |= 16384; + return FS.mknod(path, mode, 0); + }, + mkdirTree:(path, mode) => { + var dirs = path.split('/'); + var d = ''; + for (var i = 0; i < dirs.length; ++i) { + if (!dirs[i]) continue; + d += '/' + dirs[i]; + try { + FS.mkdir(d, mode); + } catch(e) { + if (e.errno != 20) throw e; + } + } + }, + mkdev:(path, mode, dev) => { + if (typeof dev == 'undefined') { + dev = mode; + mode = 438 /* 0666 */; + } + mode |= 8192; + return FS.mknod(path, mode, dev); + }, + symlink:(oldpath, newpath) => { + if (!PATH_FS.resolve(oldpath)) { + throw new FS.ErrnoError(44); + } + var lookup = FS.lookupPath(newpath, { parent: true }); + var parent = lookup.node; + if (!parent) { + throw new FS.ErrnoError(44); + } + var newname = PATH.basename(newpath); + var errCode = FS.mayCreate(parent, newname); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.symlink) { + throw new FS.ErrnoError(63); + } + return parent.node_ops.symlink(parent, newname, oldpath); + }, + rename:(old_path, new_path) => { + var old_dirname = PATH.dirname(old_path); + var new_dirname = PATH.dirname(new_path); + var old_name = PATH.basename(old_path); + var new_name = PATH.basename(new_path); + // parents must exist + var lookup, old_dir, new_dir; + + // let the errors from non existant directories percolate up + lookup = FS.lookupPath(old_path, { parent: true }); + old_dir = lookup.node; + lookup = FS.lookupPath(new_path, { parent: true }); + new_dir = lookup.node; + + if (!old_dir || !new_dir) throw new FS.ErrnoError(44); + // need to be part of the same mount + if (old_dir.mount !== new_dir.mount) { + throw new FS.ErrnoError(75); + } + // source must exist + var old_node = FS.lookupNode(old_dir, old_name); + // old path should not be an ancestor of the new path + var relative = PATH_FS.relative(old_path, new_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(28); + } + // new path should not be an ancestor of the old path + relative = PATH_FS.relative(new_path, old_dirname); + if (relative.charAt(0) !== '.') { + throw new FS.ErrnoError(55); + } + // see if the new path already exists + var new_node; + try { + new_node = FS.lookupNode(new_dir, new_name); + } catch (e) { + // not fatal + } + // early out if nothing needs to change + if (old_node === new_node) { + return; + } + // we'll need to delete the old entry + var isdir = FS.isDir(old_node.mode); + var errCode = FS.mayDelete(old_dir, old_name, isdir); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + // need delete permissions if we'll be overwriting. + // need create permissions if new doesn't already exist. + errCode = new_node ? + FS.mayDelete(new_dir, new_name, isdir) : + FS.mayCreate(new_dir, new_name); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!old_dir.node_ops.rename) { + throw new FS.ErrnoError(63); + } + if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) { + throw new FS.ErrnoError(10); + } + // if we are going to change the parent, check write permissions + if (new_dir !== old_dir) { + errCode = FS.nodePermissions(old_dir, 'w'); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + } + // remove the node from the lookup hash + FS.hashRemoveNode(old_node); + // do the underlying fs rename + try { + old_dir.node_ops.rename(old_node, new_dir, new_name); + } catch (e) { + throw e; + } finally { + // add the node back to the hash (in case node_ops.rename + // changed its name) + FS.hashAddNode(old_node); + } + }, + rmdir:(path) => { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var errCode = FS.mayDelete(parent, name, true); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.rmdir) { + throw new FS.ErrnoError(63); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(10); + } + parent.node_ops.rmdir(parent, name); + FS.destroyNode(node); + }, + readdir:(path) => { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + if (!node.node_ops.readdir) { + throw new FS.ErrnoError(54); + } + return node.node_ops.readdir(node); + }, + unlink:(path) => { + var lookup = FS.lookupPath(path, { parent: true }); + var parent = lookup.node; + if (!parent) { + throw new FS.ErrnoError(44); + } + var name = PATH.basename(path); + var node = FS.lookupNode(parent, name); + var errCode = FS.mayDelete(parent, name, false); + if (errCode) { + // According to POSIX, we should map EISDIR to EPERM, but + // we instead do what Linux does (and we must, as we use + // the musl linux libc). + throw new FS.ErrnoError(errCode); + } + if (!parent.node_ops.unlink) { + throw new FS.ErrnoError(63); + } + if (FS.isMountpoint(node)) { + throw new FS.ErrnoError(10); + } + parent.node_ops.unlink(parent, name); + FS.destroyNode(node); + }, + readlink:(path) => { + var lookup = FS.lookupPath(path); + var link = lookup.node; + if (!link) { + throw new FS.ErrnoError(44); + } + if (!link.node_ops.readlink) { + throw new FS.ErrnoError(28); + } + return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link)); + }, + stat:(path, dontFollow) => { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + var node = lookup.node; + if (!node) { + throw new FS.ErrnoError(44); + } + if (!node.node_ops.getattr) { + throw new FS.ErrnoError(63); + } + return node.node_ops.getattr(node); + }, + lstat:(path) => { + return FS.stat(path, true); + }, + chmod:(path, mode, dontFollow) => { + var node; + if (typeof path == 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(63); + } + node.node_ops.setattr(node, { + mode: (mode & 4095) | (node.mode & ~4095), + timestamp: Date.now() + }); + }, + lchmod:(path, mode) => { + FS.chmod(path, mode, true); + }, + fchmod:(fd, mode) => { + var stream = FS.getStreamChecked(fd); + FS.chmod(stream.node, mode); + }, + chown:(path, uid, gid, dontFollow) => { + var node; + if (typeof path == 'string') { + var lookup = FS.lookupPath(path, { follow: !dontFollow }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(63); + } + node.node_ops.setattr(node, { + timestamp: Date.now() + // we ignore the uid / gid for now + }); + }, + lchown:(path, uid, gid) => { + FS.chown(path, uid, gid, true); + }, + fchown:(fd, uid, gid) => { + var stream = FS.getStreamChecked(fd); + FS.chown(stream.node, uid, gid); + }, + truncate:(path, len) => { + if (len < 0) { + throw new FS.ErrnoError(28); + } + var node; + if (typeof path == 'string') { + var lookup = FS.lookupPath(path, { follow: true }); + node = lookup.node; + } else { + node = path; + } + if (!node.node_ops.setattr) { + throw new FS.ErrnoError(63); + } + if (FS.isDir(node.mode)) { + throw new FS.ErrnoError(31); + } + if (!FS.isFile(node.mode)) { + throw new FS.ErrnoError(28); + } + var errCode = FS.nodePermissions(node, 'w'); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + node.node_ops.setattr(node, { + size: len, + timestamp: Date.now() + }); + }, + ftruncate:(fd, len) => { + var stream = FS.getStreamChecked(fd); + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(28); + } + FS.truncate(stream.node, len); + }, + utime:(path, atime, mtime) => { + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + node.node_ops.setattr(node, { + timestamp: Math.max(atime, mtime) + }); + }, + open:(path, flags, mode) => { + if (path === "") { + throw new FS.ErrnoError(44); + } + flags = typeof flags == 'string' ? FS_modeStringToFlags(flags) : flags; + mode = typeof mode == 'undefined' ? 438 /* 0666 */ : mode; + if ((flags & 64)) { + mode = (mode & 4095) | 32768; + } else { + mode = 0; + } + var node; + if (typeof path == 'object') { + node = path; + } else { + path = PATH.normalize(path); + try { + var lookup = FS.lookupPath(path, { + follow: !(flags & 131072) + }); + node = lookup.node; + } catch (e) { + // ignore + } + } + // perhaps we need to create the node + var created = false; + if ((flags & 64)) { + if (node) { + // if O_CREAT and O_EXCL are set, error out if the node already exists + if ((flags & 128)) { + throw new FS.ErrnoError(20); + } + } else { + // node doesn't exist, try to create it + node = FS.mknod(path, mode, 0); + created = true; + } + } + if (!node) { + throw new FS.ErrnoError(44); + } + // can't truncate a device + if (FS.isChrdev(node.mode)) { + flags &= ~512; + } + // if asked only for a directory, then this must be one + if ((flags & 65536) && !FS.isDir(node.mode)) { + throw new FS.ErrnoError(54); + } + // check permissions, if this is not a file we just created now (it is ok to + // create and write to a file with read-only permissions; it is read-only + // for later use) + if (!created) { + var errCode = FS.mayOpen(node, flags); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + } + // do truncation if necessary + if ((flags & 512) && !created) { + FS.truncate(node, 0); + } + // we've already handled these, don't pass down to the underlying vfs + flags &= ~(128 | 512 | 131072); + + // register the stream with the filesystem + var stream = FS.createStream({ + node, + path: FS.getPath(node), // we want the absolute path to the node + flags, + seekable: true, + position: 0, + stream_ops: node.stream_ops, + // used by the file family libc calls (fopen, fwrite, ferror, etc.) + ungotten: [], + error: false + }); + // call the new stream's open function + if (stream.stream_ops.open) { + stream.stream_ops.open(stream); + } + if (Module['logReadFiles'] && !(flags & 1)) { + if (!FS.readFiles) FS.readFiles = {}; + if (!(path in FS.readFiles)) { + FS.readFiles[path] = 1; + } + } + return stream; + }, + close:(stream) => { + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if (stream.getdents) stream.getdents = null; // free readdir state + try { + if (stream.stream_ops.close) { + stream.stream_ops.close(stream); + } + } catch (e) { + throw e; + } finally { + FS.closeStream(stream.fd); + } + stream.fd = null; + }, + isClosed:(stream) => { + return stream.fd === null; + }, + llseek:(stream, offset, whence) => { + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if (!stream.seekable || !stream.stream_ops.llseek) { + throw new FS.ErrnoError(70); + } + if (whence != 0 && whence != 1 && whence != 2) { + throw new FS.ErrnoError(28); + } + stream.position = stream.stream_ops.llseek(stream, offset, whence); + stream.ungotten = []; + return stream.position; + }, + read:(stream, buffer, offset, length, position) => { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(28); + } + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(8); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(31); + } + if (!stream.stream_ops.read) { + throw new FS.ErrnoError(28); + } + var seeking = typeof position != 'undefined'; + if (!seeking) { + position = stream.position; + } else if (!stream.seekable) { + throw new FS.ErrnoError(70); + } + var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position); + if (!seeking) stream.position += bytesRead; + return bytesRead; + }, + write:(stream, buffer, offset, length, position, canOwn) => { + if (length < 0 || position < 0) { + throw new FS.ErrnoError(28); + } + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(8); + } + if (FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(31); + } + if (!stream.stream_ops.write) { + throw new FS.ErrnoError(28); + } + if (stream.seekable && stream.flags & 1024) { + // seek to the end before writing in append mode + FS.llseek(stream, 0, 2); + } + var seeking = typeof position != 'undefined'; + if (!seeking) { + position = stream.position; + } else if (!stream.seekable) { + throw new FS.ErrnoError(70); + } + var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn); + if (!seeking) stream.position += bytesWritten; + return bytesWritten; + }, + allocate:(stream, offset, length) => { + if (FS.isClosed(stream)) { + throw new FS.ErrnoError(8); + } + if (offset < 0 || length <= 0) { + throw new FS.ErrnoError(28); + } + if ((stream.flags & 2097155) === 0) { + throw new FS.ErrnoError(8); + } + if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) { + throw new FS.ErrnoError(43); + } + if (!stream.stream_ops.allocate) { + throw new FS.ErrnoError(138); + } + stream.stream_ops.allocate(stream, offset, length); + }, + mmap:(stream, length, position, prot, flags) => { + // User requests writing to file (prot & PROT_WRITE != 0). + // Checking if we have permissions to write to the file unless + // MAP_PRIVATE flag is set. According to POSIX spec it is possible + // to write to file opened in read-only mode with MAP_PRIVATE flag, + // as all modifications will be visible only in the memory of + // the current process. + if ((prot & 2) !== 0 + && (flags & 2) === 0 + && (stream.flags & 2097155) !== 2) { + throw new FS.ErrnoError(2); + } + if ((stream.flags & 2097155) === 1) { + throw new FS.ErrnoError(2); + } + if (!stream.stream_ops.mmap) { + throw new FS.ErrnoError(43); + } + return stream.stream_ops.mmap(stream, length, position, prot, flags); + }, + msync:(stream, buffer, offset, length, mmapFlags) => { + if (!stream.stream_ops.msync) { + return 0; + } + return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags); + }, + munmap:(stream) => 0, + ioctl:(stream, cmd, arg) => { + if (!stream.stream_ops.ioctl) { + throw new FS.ErrnoError(59); + } + return stream.stream_ops.ioctl(stream, cmd, arg); + }, + readFile:(path, opts = {}) => { + opts.flags = opts.flags || 0; + opts.encoding = opts.encoding || 'binary'; + if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { + throw new Error(`Invalid encoding type "${opts.encoding}"`); + } + var ret; + var stream = FS.open(path, opts.flags); + var stat = FS.stat(path); + var length = stat.size; + var buf = new Uint8Array(length); + FS.read(stream, buf, 0, length, 0); + if (opts.encoding === 'utf8') { + ret = UTF8ArrayToString(buf, 0); + } else if (opts.encoding === 'binary') { + ret = buf; + } + FS.close(stream); + return ret; + }, + writeFile:(path, data, opts = {}) => { + opts.flags = opts.flags || 577; + var stream = FS.open(path, opts.flags, opts.mode); + if (typeof data == 'string') { + var buf = new Uint8Array(lengthBytesUTF8(data)+1); + var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length); + FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn); + } else if (ArrayBuffer.isView(data)) { + FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn); + } else { + throw new Error('Unsupported data type'); + } + FS.close(stream); + }, + cwd:() => FS.currentPath, + chdir:(path) => { + var lookup = FS.lookupPath(path, { follow: true }); + if (lookup.node === null) { + throw new FS.ErrnoError(44); + } + if (!FS.isDir(lookup.node.mode)) { + throw new FS.ErrnoError(54); + } + var errCode = FS.nodePermissions(lookup.node, 'x'); + if (errCode) { + throw new FS.ErrnoError(errCode); + } + FS.currentPath = lookup.path; + }, + createDefaultDirectories:() => { + FS.mkdir('/tmp'); + FS.mkdir('/home'); + FS.mkdir('/home/web_user'); + }, + createDefaultDevices:() => { + // create /dev + FS.mkdir('/dev'); + // setup /dev/null + FS.registerDevice(FS.makedev(1, 3), { + read: () => 0, + write: (stream, buffer, offset, length, pos) => length, + }); + FS.mkdev('/dev/null', FS.makedev(1, 3)); + // setup /dev/tty and /dev/tty1 + // stderr needs to print output using err() rather than out() + // so we register a second tty just for it. + TTY.register(FS.makedev(5, 0), TTY.default_tty_ops); + TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops); + FS.mkdev('/dev/tty', FS.makedev(5, 0)); + FS.mkdev('/dev/tty1', FS.makedev(6, 0)); + // setup /dev/[u]random + // use a buffer to avoid overhead of individual crypto calls per byte + var randomBuffer = new Uint8Array(1024), randomLeft = 0; + var randomByte = () => { + if (randomLeft === 0) { + randomLeft = randomFill(randomBuffer).byteLength; + } + return randomBuffer[--randomLeft]; + }; + FS.createDevice('/dev', 'random', randomByte); + FS.createDevice('/dev', 'urandom', randomByte); + // we're not going to emulate the actual shm device, + // just create the tmp dirs that reside in it commonly + FS.mkdir('/dev/shm'); + FS.mkdir('/dev/shm/tmp'); + }, + createSpecialDirectories:() => { + // create /proc/self/fd which allows /proc/self/fd/6 => readlink gives the + // name of the stream for fd 6 (see test_unistd_ttyname) + FS.mkdir('/proc'); + var proc_self = FS.mkdir('/proc/self'); + FS.mkdir('/proc/self/fd'); + FS.mount({ + mount: () => { + var node = FS.createNode(proc_self, 'fd', 16384 | 511 /* 0777 */, 73); + node.node_ops = { + lookup: (parent, name) => { + var fd = +name; + var stream = FS.getStreamChecked(fd); + var ret = { + parent: null, + mount: { mountpoint: 'fake' }, + node_ops: { readlink: () => stream.path }, + }; + ret.parent = ret; // make it look like a simple root node + return ret; + } + }; + return node; + } + }, {}, '/proc/self/fd'); + }, + createStandardStreams:() => { + // TODO deprecate the old functionality of a single + // input / output callback and that utilizes FS.createDevice + // and instead require a unique set of stream ops + + // by default, we symlink the standard streams to the + // default tty devices. however, if the standard streams + // have been overwritten we create a unique device for + // them instead. + if (Module['stdin']) { + FS.createDevice('/dev', 'stdin', Module['stdin']); + } else { + FS.symlink('/dev/tty', '/dev/stdin'); + } + if (Module['stdout']) { + FS.createDevice('/dev', 'stdout', null, Module['stdout']); + } else { + FS.symlink('/dev/tty', '/dev/stdout'); + } + if (Module['stderr']) { + FS.createDevice('/dev', 'stderr', null, Module['stderr']); + } else { + FS.symlink('/dev/tty1', '/dev/stderr'); + } + + // open default streams for the stdin, stdout and stderr devices + var stdin = FS.open('/dev/stdin', 0); + var stdout = FS.open('/dev/stdout', 1); + var stderr = FS.open('/dev/stderr', 1); + }, + ensureErrnoError:() => { + if (FS.ErrnoError) return; + FS.ErrnoError = /** @this{Object} */ function ErrnoError(errno, node) { + // We set the `name` property to be able to identify `FS.ErrnoError` + // - the `name` is a standard ECMA-262 property of error objects. Kind of good to have it anyway. + // - when using PROXYFS, an error can come from an underlying FS + // as different FS objects have their own FS.ErrnoError each, + // the test `err instanceof FS.ErrnoError` won't detect an error coming from another filesystem, causing bugs. + // we'll use the reliable test `err.name == "ErrnoError"` instead + this.name = 'ErrnoError'; + this.node = node; + this.setErrno = /** @this{Object} */ function(errno) { + this.errno = errno; + }; + this.setErrno(errno); + this.message = 'FS error'; + + }; + FS.ErrnoError.prototype = new Error(); + FS.ErrnoError.prototype.constructor = FS.ErrnoError; + // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info) + [44].forEach((code) => { + FS.genericErrors[code] = new FS.ErrnoError(code); + FS.genericErrors[code].stack = ''; + }); + }, + staticInit:() => { + FS.ensureErrnoError(); + + FS.nameTable = new Array(4096); + + FS.mount(MEMFS, {}, '/'); + + FS.createDefaultDirectories(); + FS.createDefaultDevices(); + FS.createSpecialDirectories(); + + FS.filesystems = { + 'MEMFS': MEMFS, + 'PROXYFS': PROXYFS, + }; + }, + init:(input, output, error) => { + FS.init.initialized = true; + + FS.ensureErrnoError(); + + // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here + Module['stdin'] = input || Module['stdin']; + Module['stdout'] = output || Module['stdout']; + Module['stderr'] = error || Module['stderr']; + + FS.createStandardStreams(); + }, + quit:() => { + FS.init.initialized = false; + // force-flush all streams, so we get musl std streams printed out + _fflush(0); + // close all of our streams + for (var i = 0; i < FS.streams.length; i++) { + var stream = FS.streams[i]; + if (!stream) { + continue; + } + FS.close(stream); + } + }, + findObject:(path, dontResolveLastLink) => { + var ret = FS.analyzePath(path, dontResolveLastLink); + if (!ret.exists) { + return null; + } + return ret.object; + }, + analyzePath:(path, dontResolveLastLink) => { + // operate from within the context of the symlink's target + try { + var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); + path = lookup.path; + } catch (e) { + } + var ret = { + isRoot: false, exists: false, error: 0, name: null, path: null, object: null, + parentExists: false, parentPath: null, parentObject: null + }; + try { + var lookup = FS.lookupPath(path, { parent: true }); + ret.parentExists = true; + ret.parentPath = lookup.path; + ret.parentObject = lookup.node; + ret.name = PATH.basename(path); + lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); + ret.exists = true; + ret.path = lookup.path; + ret.object = lookup.node; + ret.name = lookup.node.name; + ret.isRoot = lookup.path === '/'; + } catch (e) { + ret.error = e.errno; + }; + return ret; + }, + createPath:(parent, path, canRead, canWrite) => { + parent = typeof parent == 'string' ? parent : FS.getPath(parent); + var parts = path.split('/').reverse(); + while (parts.length) { + var part = parts.pop(); + if (!part) continue; + var current = PATH.join2(parent, part); + try { + FS.mkdir(current); + } catch (e) { + // ignore EEXIST + } + parent = current; + } + return current; + }, + createFile:(parent, name, properties, canRead, canWrite) => { + var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name); + var mode = FS_getMode(canRead, canWrite); + return FS.create(path, mode); + }, + createDataFile:(parent, name, data, canRead, canWrite, canOwn) => { + var path = name; + if (parent) { + parent = typeof parent == 'string' ? parent : FS.getPath(parent); + path = name ? PATH.join2(parent, name) : parent; + } + var mode = FS_getMode(canRead, canWrite); + var node = FS.create(path, mode); + if (data) { + if (typeof data == 'string') { + var arr = new Array(data.length); + for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i); + data = arr; + } + // make sure we can write to the file + FS.chmod(node, mode | 146); + var stream = FS.open(node, 577); + FS.write(stream, data, 0, data.length, 0, canOwn); + FS.close(stream); + FS.chmod(node, mode); + } + return node; + }, + createDevice:(parent, name, input, output) => { + var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name); + var mode = FS_getMode(!!input, !!output); + if (!FS.createDevice.major) FS.createDevice.major = 64; + var dev = FS.makedev(FS.createDevice.major++, 0); + // Create a fake device that a set of stream ops to emulate + // the old behavior. + FS.registerDevice(dev, { + open: (stream) => { + stream.seekable = false; + }, + close: (stream) => { + // flush any pending line data + if (output && output.buffer && output.buffer.length) { + output(10); + } + }, + read: (stream, buffer, offset, length, pos /* ignored */) => { + var bytesRead = 0; + for (var i = 0; i < length; i++) { + var result; + try { + result = input(); + } catch (e) { + throw new FS.ErrnoError(29); + } + if (result === undefined && bytesRead === 0) { + throw new FS.ErrnoError(6); + } + if (result === null || result === undefined) break; + bytesRead++; + buffer[offset+i] = result; + } + if (bytesRead) { + stream.node.timestamp = Date.now(); + } + return bytesRead; + }, + write: (stream, buffer, offset, length, pos) => { + for (var i = 0; i < length; i++) { + try { + output(buffer[offset+i]); + } catch (e) { + throw new FS.ErrnoError(29); + } + } + if (length) { + stream.node.timestamp = Date.now(); + } + return i; + } + }); + return FS.mkdev(path, mode, dev); + }, + forceLoadFile:(obj) => { + if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; + if (typeof XMLHttpRequest != 'undefined') { + throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); + } else if (read_) { + // Command-line. + try { + // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as + // read() will try to parse UTF8. + obj.contents = intArrayFromString(read_(obj.url), true); + obj.usedBytes = obj.contents.length; + } catch (e) { + throw new FS.ErrnoError(29); + } + } else { + throw new Error('Cannot load without read() or XMLHttpRequest.'); + } + }, + createLazyFile:(parent, name, url, canRead, canWrite) => { + // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse. + /** @constructor */ + function LazyUint8Array() { + this.lengthKnown = false; + this.chunks = []; // Loaded chunks. Index is the chunk number + } + LazyUint8Array.prototype.get = /** @this{Object} */ function LazyUint8Array_get(idx) { + if (idx > this.length-1 || idx < 0) { + return undefined; + } + var chunkOffset = idx % this.chunkSize; + var chunkNum = (idx / this.chunkSize)|0; + return this.getter(chunkNum)[chunkOffset]; + }; + LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) { + this.getter = getter; + }; + LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() { + // Find length + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', url, false); + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + var datalength = Number(xhr.getResponseHeader("Content-length")); + var header; + var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes"; + var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip"; + + var chunkSize = 1024*1024; // Chunk size in bytes + + if (!hasByteServing) chunkSize = datalength; + + // Function to get a range from the remote URL. + var doXHR = (from, to) => { + if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!"); + if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!"); + + // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available. + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, false); + if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to); + + // Some hints to the browser that we want binary data. + xhr.responseType = 'arraybuffer'; + if (xhr.overrideMimeType) { + xhr.overrideMimeType('text/plain; charset=x-user-defined'); + } + + xhr.send(null); + if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status); + if (xhr.response !== undefined) { + return new Uint8Array(/** @type{Array} */(xhr.response || [])); + } + return intArrayFromString(xhr.responseText || '', true); + }; + var lazyArray = this; + lazyArray.setDataGetter((chunkNum) => { + var start = chunkNum * chunkSize; + var end = (chunkNum+1) * chunkSize - 1; // including this byte + end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block + if (typeof lazyArray.chunks[chunkNum] == 'undefined') { + lazyArray.chunks[chunkNum] = doXHR(start, end); + } + if (typeof lazyArray.chunks[chunkNum] == 'undefined') throw new Error('doXHR failed!'); + return lazyArray.chunks[chunkNum]; + }); + + if (usesGzip || !datalength) { + // if the server uses gzip or doesn't supply the length, we have to download the whole file to get the (uncompressed) length + chunkSize = datalength = 1; // this will force getter(0)/doXHR do download the whole file + datalength = this.getter(0).length; + chunkSize = datalength; + out("LazyFiles on gzip forces download of the whole file when length is accessed"); + } + + this._length = datalength; + this._chunkSize = chunkSize; + this.lengthKnown = true; + }; + if (typeof XMLHttpRequest != 'undefined') { + if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc'; + var lazyArray = new LazyUint8Array(); + Object.defineProperties(lazyArray, { + length: { + get: /** @this{Object} */ function() { + if (!this.lengthKnown) { + this.cacheLength(); + } + return this._length; + } + }, + chunkSize: { + get: /** @this{Object} */ function() { + if (!this.lengthKnown) { + this.cacheLength(); + } + return this._chunkSize; + } + } + }); + + var properties = { isDevice: false, contents: lazyArray }; + } else { + var properties = { isDevice: false, url: url }; + } + + var node = FS.createFile(parent, name, properties, canRead, canWrite); + // This is a total hack, but I want to get this lazy file code out of the + // core of MEMFS. If we want to keep this lazy file concept I feel it should + // be its own thin LAZYFS proxying calls to MEMFS. + if (properties.contents) { + node.contents = properties.contents; + } else if (properties.url) { + node.contents = null; + node.url = properties.url; + } + // Add a function that defers querying the file size until it is asked the first time. + Object.defineProperties(node, { + usedBytes: { + get: /** @this {FSNode} */ function() { return this.contents.length; } + } + }); + // override each stream op with one that tries to force load the lazy file first + var stream_ops = {}; + var keys = Object.keys(node.stream_ops); + keys.forEach((key) => { + var fn = node.stream_ops[key]; + stream_ops[key] = function forceLoadLazyFile() { + FS.forceLoadFile(node); + return fn.apply(null, arguments); + }; + }); + function writeChunks(stream, buffer, offset, length, position) { + var contents = stream.node.contents; + if (position >= contents.length) + return 0; + var size = Math.min(contents.length - position, length); + if (contents.slice) { // normal array + for (var i = 0; i < size; i++) { + buffer[offset + i] = contents[position + i]; + } + } else { + for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR + buffer[offset + i] = contents.get(position + i); + } + } + return size; + } + // use a custom read function + stream_ops.read = (stream, buffer, offset, length, position) => { + FS.forceLoadFile(node); + return writeChunks(stream, buffer, offset, length, position) + }; + // use a custom mmap function + stream_ops.mmap = (stream, length, position, prot, flags) => { + FS.forceLoadFile(node); + var ptr = mmapAlloc(length); + if (!ptr) { + throw new FS.ErrnoError(48); + } + writeChunks(stream, HEAP8, ptr, length, position); + return { ptr, allocated: true }; + }; + node.stream_ops = stream_ops; + return node; + }, + }; + Module['FS'] = FS; + var SOCKFS = { + mount(mount) { + // If Module['websocket'] has already been defined (e.g. for configuring + // the subprotocol/url) use that, if not initialise it to a new object. + Module['websocket'] = (Module['websocket'] && + ('object' === typeof Module['websocket'])) ? Module['websocket'] : {}; + + // Add the Event registration mechanism to the exported websocket configuration + // object so we can register network callbacks from native JavaScript too. + // For more documentation see system/include/emscripten/emscripten.h + Module['websocket']._callbacks = {}; + Module['websocket']['on'] = /** @this{Object} */ function(event, callback) { + if ('function' === typeof callback) { + this._callbacks[event] = callback; + } + return this; + }; + + Module['websocket'].emit = /** @this{Object} */ function(event, param) { + if ('function' === typeof this._callbacks[event]) { + this._callbacks[event].call(this, param); + } + }; + + // If debug is enabled register simple default logging callbacks for each Event. + + return FS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + }, + createSocket(family, type, protocol) { + type &= ~526336; // Some applications may pass it; it makes no sense for a single process. + var streaming = type == 1; + if (streaming && protocol && protocol != 6) { + throw new FS.ErrnoError(66); // if SOCK_STREAM, must be tcp or 0. + } + + // create our internal socket structure + var sock = { + family, + type, + protocol, + server: null, + error: null, // Used in getsockopt for SOL_SOCKET/SO_ERROR test + peers: {}, + pending: [], + recv_queue: [], + sock_ops: SOCKFS.websocket_sock_ops + }; + + // create the filesystem node to store the socket structure + var name = SOCKFS.nextname(); + var node = FS.createNode(SOCKFS.root, name, 49152, 0); + node.sock = sock; + + // and the wrapping stream that enables library functions such + // as read and write to indirectly interact with the socket + var stream = FS.createStream({ + path: name, + node, + flags: 2, + seekable: false, + stream_ops: SOCKFS.stream_ops + }); + + // map the new stream to the socket structure (sockets have a 1:1 + // relationship with a stream) + sock.stream = stream; + + return sock; + }, + getSocket(fd) { + var stream = FS.getStream(fd); + if (!stream || !FS.isSocket(stream.node.mode)) { + return null; + } + return stream.node.sock; + }, + stream_ops:{ + poll(stream) { + var sock = stream.node.sock; + return sock.sock_ops.poll(sock); + }, + ioctl(stream, request, varargs) { + var sock = stream.node.sock; + return sock.sock_ops.ioctl(sock, request, varargs); + }, + read(stream, buffer, offset, length, position /* ignored */) { + var sock = stream.node.sock; + var msg = sock.sock_ops.recvmsg(sock, length); + if (!msg) { + // socket is closed + return 0; + } + buffer.set(msg.buffer, offset); + return msg.buffer.length; + }, + write(stream, buffer, offset, length, position /* ignored */) { + var sock = stream.node.sock; + return sock.sock_ops.sendmsg(sock, buffer, offset, length); + }, + close(stream) { + var sock = stream.node.sock; + sock.sock_ops.close(sock); + }, + }, + nextname() { + if (!SOCKFS.nextname.current) { + SOCKFS.nextname.current = 0; + } + return 'socket[' + (SOCKFS.nextname.current++) + ']'; + }, + websocket_sock_ops:{ + createPeer(sock, addr, port) { + var ws; + + if (typeof addr == 'object') { + ws = addr; + addr = null; + port = null; + } + + if (ws) { + // for sockets that've already connected (e.g. we're the server) + // we can inspect the _socket property for the address + if (ws._socket) { + addr = ws._socket.remoteAddress; + port = ws._socket.remotePort; + } + // if we're just now initializing a connection to the remote, + // inspect the url property + else { + var result = /ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url); + if (!result) { + throw new Error('WebSocket URL must be in the format ws(s)://address:port'); + } + addr = result[1]; + port = parseInt(result[2], 10); + } + } else { + // create the actual websocket object and connect + try { + // runtimeConfig gets set to true if WebSocket runtime configuration is available. + var runtimeConfig = (Module['websocket'] && ('object' === typeof Module['websocket'])); + + // The default value is 'ws://' the replace is needed because the compiler replaces '//' comments with '#' + // comments without checking context, so we'd end up with ws:#, the replace swaps the '#' for '//' again. + var url = 'ws:#'.replace('#', '//'); + + if (runtimeConfig) { + if("function"===typeof Module["websocket"]["url"]) { url = Module["websocket"]["url"](...arguments); -}else if ("string" === typeof Module["websocket"]["url"]){url=Module["websocket"]["url"]}}if(url==="ws://"||url==="wss://"){var parts=addr.split("/");url=url+parts[0]+":"+port+"/"+parts.slice(1).join("/")}var subProtocols="binary";if(runtimeConfig){if("string"===typeof Module["websocket"]["subprotocol"]){subProtocols=Module["websocket"]["subprotocol"]}}var opts=undefined;if(subProtocols!=="null"){subProtocols=subProtocols.replace(/^ +| +$/g,"").split(/ *, */);opts=subProtocols}if(runtimeConfig&&null===Module["websocket"]["subprotocol"]){subProtocols="null";opts=undefined}var WebSocketConstructor;{WebSocketConstructor=WebSocket}if (Module['websocket']['decorator']) {WebSocketConstructor = Module['websocket']['decorator'](WebSocketConstructor);}ws = new WebSocketConstructor(url,opts);ws.binaryType="arraybuffer"}catch(e){throw new FS.ErrnoError(23)}}var peer={addr:addr,port:port,socket:ws,dgram_send_queue:[]};SOCKFS.websocket_sock_ops.addPeer(sock,peer);SOCKFS.websocket_sock_ops.handlePeerEvents(sock,peer);if(sock.type===2&&typeof sock.sport!="undefined"){peer.dgram_send_queue.push(new Uint8Array([255,255,255,255,"p".charCodeAt(0),"o".charCodeAt(0),"r".charCodeAt(0),"t".charCodeAt(0),(sock.sport&65280)>>8,sock.sport&255]))}return peer},getPeer(sock,addr,port){return sock.peers[addr+":"+port]},addPeer(sock,peer){sock.peers[peer.addr+":"+peer.port]=peer},removePeer(sock,peer){delete sock.peers[peer.addr+":"+peer.port]},handlePeerEvents(sock,peer){var first=true;var handleOpen=function(){Module["websocket"].emit("open",sock.stream.fd);try{var queued=peer.dgram_send_queue.shift();while(queued){peer.socket.send(queued);queued=peer.dgram_send_queue.shift()}}catch(e){peer.socket.close()}};function handleMessage(data){if(typeof data=="string"){var encoder=new TextEncoder;data=encoder.encode(data)}else{assert(data.byteLength!==undefined);if(data.byteLength==0){return}data=new Uint8Array(data)}var wasfirst=first;first=false;if(wasfirst&&data.length===10&&data[0]===255&&data[1]===255&&data[2]===255&&data[3]===255&&data[4]==="p".charCodeAt(0)&&data[5]==="o".charCodeAt(0)&&data[6]==="r".charCodeAt(0)&&data[7]==="t".charCodeAt(0)){var newport=data[8]<<8|data[9];SOCKFS.websocket_sock_ops.removePeer(sock,peer);peer.port=newport;SOCKFS.websocket_sock_ops.addPeer(sock,peer);return}sock.recv_queue.push({addr:peer.addr,port:peer.port,data:data});Module["websocket"].emit("message",sock.stream.fd)}if(ENVIRONMENT_IS_NODE){peer.socket.on("open",handleOpen);peer.socket.on("message",(function(data,isBinary){if(!isBinary){return}handleMessage(new Uint8Array(data).buffer)}));peer.socket.on("close",(function(){Module["websocket"].emit("close",sock.stream.fd)}));peer.socket.on("error",(function(error){sock.error=14;Module["websocket"].emit("error",[sock.stream.fd,sock.error,"ECONNREFUSED: Connection refused"])}))}else{peer.socket.onopen=handleOpen;peer.socket.onclose=function(){Module["websocket"].emit("close",sock.stream.fd)};peer.socket.onmessage=function peer_socket_onmessage(event){handleMessage(event.data)};peer.socket.onerror=function(error){sock.error=14;Module["websocket"].emit("error",[sock.stream.fd,sock.error,"ECONNREFUSED: Connection refused"])}}},poll(sock){if(sock.type===1&&sock.server){return sock.pending.length?64|1:0}var mask=0;var dest=sock.type===1?SOCKFS.websocket_sock_ops.getPeer(sock,sock.daddr,sock.dport):null;if(sock.recv_queue.length||!dest||dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){mask|=64|1}if(!dest||dest&&dest.socket.readyState===dest.socket.OPEN){mask|=4}if(dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){mask|=16}return mask},ioctl(sock,request,arg){switch(request){case 21531:var bytes=0;if(sock.recv_queue.length){bytes=sock.recv_queue[0].data.length}HEAP32[arg>>2]=bytes;return 0;default:return 28}},close(sock){if(sock.server){try{sock.server.close()}catch(e){}sock.server=null}var peers=Object.keys(sock.peers);for(var i=0;i{HEAP32[___errno_location()>>2]=value;return value};var inetPton4=str=>{var b=str.split(".");for(var i=0;i<4;i++){var tmp=Number(b[i]);if(isNaN(tmp))return null;b[i]=tmp}return(b[0]|b[1]<<8|b[2]<<16|b[3]<<24)>>>0};var jstoi_q=str=>parseInt(str);var inetPton6=str=>{var words;var w,offset,z;var valid6regx=/^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i;var parts=[];if(!valid6regx.test(str)){return null}if(str==="::"){return[0,0,0,0,0,0,0,0]}if(str.startsWith("::")){str=str.replace("::","Z:")}else{str=str.replace("::",":Z:")}if(str.indexOf(".")>0){str=str.replace(new RegExp("[.]","g"),":");words=str.split(":");words[words.length-4]=jstoi_q(words[words.length-4])+jstoi_q(words[words.length-3])*256;words[words.length-3]=jstoi_q(words[words.length-2])+jstoi_q(words[words.length-1])*256;words=words.slice(0,words.length-2)}else{words=str.split(":")}offset=0;z=0;for(w=0;w{switch(family){case 2:addr=inetPton4(addr);zeroMemory(sa,16);if(addrlen){HEAP32[addrlen>>2]=16}HEAP16[sa>>1]=family;HEAP32[sa+4>>2]=addr;HEAP16[sa+2>>1]=_htons(port);break;case 10:addr=inetPton6(addr);zeroMemory(sa,28);if(addrlen){HEAP32[addrlen>>2]=28}HEAP32[sa>>2]=family;HEAP32[sa+8>>2]=addr[0];HEAP32[sa+12>>2]=addr[1];HEAP32[sa+16>>2]=addr[2];HEAP32[sa+20>>2]=addr[3];HEAP16[sa+2>>1]=_htons(port);break;default:return 5}return 0};var DNS={address_map:{id:1,addrs:{},names:{}},lookup_name:name=>{var res=inetPton4(name);if(res!==null){return name}res=inetPton6(name);if(res!==null){return name}var addr;if(DNS.address_map.addrs[name]){addr=DNS.address_map.addrs[name]}else{var id=DNS.address_map.id++;assert(id<65535,"exceeded max address mappings of 65535");addr="172.29."+(id&255)+"."+(id&65280);DNS.address_map.names[addr]=name;DNS.address_map.addrs[name]=addr}return addr},lookup_addr:addr=>{if(DNS.address_map.names[addr]){return DNS.address_map.names[addr]}return null}};function ___syscall_accept4(fd,addr,addrlen,flags,d1,d2){try{var sock=getSocketFromFD(fd);var newsock=sock.sock_ops.accept(sock);if(addr){var errno=writeSockaddr(addr,newsock.family,DNS.lookup_name(newsock.daddr),newsock.dport,addrlen)}return newsock.stream.fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var inetNtop4=addr=>(addr&255)+"."+(addr>>8&255)+"."+(addr>>16&255)+"."+(addr>>24&255);var inetNtop6=ints=>{var str="";var word=0;var longest=0;var lastzero=0;var zstart=0;var len=0;var i=0;var parts=[ints[0]&65535,ints[0]>>16,ints[1]&65535,ints[1]>>16,ints[2]&65535,ints[2]>>16,ints[3]&65535,ints[3]>>16];var hasipv4=true;var v4part="";for(i=0;i<5;i++){if(parts[i]!==0){hasipv4=false;break}}if(hasipv4){v4part=inetNtop4(parts[6]|parts[7]<<16);if(parts[5]===-1){str="::ffff:";str+=v4part;return str}if(parts[5]===0){str="::";if(v4part==="0.0.0.0")v4part="";if(v4part==="0.0.0.1")v4part="1";str+=v4part;return str}}for(word=0;word<8;word++){if(parts[word]===0){if(word-lastzero>1){len=0}lastzero=word;len++}if(len>longest){longest=len;zstart=word-longest+1}}for(word=0;word<8;word++){if(longest>1){if(parts[word]===0&&word>=zstart&&word{var family=HEAP16[sa>>1];var port=_ntohs(HEAPU16[sa+2>>1]);var addr;switch(family){case 2:if(salen!==16){return{errno:28}}addr=HEAP32[sa+4>>2];addr=inetNtop4(addr);break;case 10:if(salen!==28){return{errno:28}}addr=[HEAP32[sa+8>>2],HEAP32[sa+12>>2],HEAP32[sa+16>>2],HEAP32[sa+20>>2]];addr=inetNtop6(addr);break;default:return{errno:5}}return{family:family,addr:addr,port:port}};function getSocketAddress(addrp,addrlen,allowNull){if(allowNull&&addrp===0)return null;var info=readSockaddr(addrp,addrlen);if(info.errno)throw new FS.ErrnoError(info.errno);info.addr=DNS.lookup_addr(info.addr)||info.addr;return info}function ___syscall_bind(fd,addr,addrlen,d1,d2,d3){try{var sock=getSocketFromFD(fd);var info=getSocketAddress(addr,addrlen);sock.sock_ops.bind(sock,info.addr,info.port);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_chdir(path){try{path=SYSCALLS.getStr(path);FS.chdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_chmod(path,mode){try{path=SYSCALLS.getStr(path);FS.chmod(path,mode);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_connect(fd,addr,addrlen,d1,d2,d3){try{var sock=getSocketFromFD(fd);var info=getSocketAddress(addr,addrlen);sock.sock_ops.connect(sock,info.addr,info.port);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_dup(fd){try{var old=SYSCALLS.getStreamFromFD(fd);return FS.createStream(old).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_dup3(fd,newfd,flags){try{var old=SYSCALLS.getStreamFromFD(fd);if(old.fd===newfd)return-28;var existing=FS.getStream(newfd);if(existing)FS.close(existing);return FS.createStream(old,newfd).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_faccessat(dirfd,path,amode,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(amode&~7){return-28}var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node){return-44}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-2}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function convertI32PairToI53Checked(lo,hi){return hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN}function ___syscall_fallocate(fd,mode,offset_low,offset_high,len_low,len_high){var offset=convertI32PairToI53Checked(offset_low,offset_high);var len=convertI32PairToI53Checked(len_low,len_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.allocate(stream,offset,len);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fchmod(fd,mode){try{FS.fchmod(fd,mode);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fchown32(fd,owner,group){try{FS.fchown(fd,owner,group);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fchownat(dirfd,path,owner,group,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;flags=flags&~256;path=SYSCALLS.calculateAt(dirfd,path);(nofollow?FS.lchown:FS.chown)(path,owner,group);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-28}var newStream;newStream=FS.createStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0}case 5:{var arg=SYSCALLS.get();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 6:case 7:return 0;case 16:case 8:return-28;case 9:setErrNo(28);return-1;default:{return-28}}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fdatasync(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ftruncate64(fd,length_low,length_high){var length=convertI32PairToI53Checked(length_low,length_high);try{if(isNaN(length))return 61;FS.ftruncate(fd,length);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);Module["stringToUTF8"]=stringToUTF8;function ___syscall_getcwd(buf,size){try{if(size===0)return-28;var cwd=FS.cwd();var cwdLengthInBytes=lengthBytesUTF8(cwd)+1;if(size>>0,(tempDouble=id,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos>>2]=tempI64[0],HEAP32[dirp+pos+4>>2]=tempI64[1];tempI64=[(idx+1)*struct_size>>>0,(tempDouble=(idx+1)*struct_size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos+8>>2]=tempI64[0],HEAP32[dirp+pos+12>>2]=tempI64[1];HEAP16[dirp+pos+16>>1]=280;HEAP8[dirp+pos+18>>0]=type;stringToUTF8(name,dirp+pos+19,256);pos+=struct_size;idx+=1}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_getpeername(fd,addr,addrlen,d1,d2,d3){try{var sock=getSocketFromFD(fd);if(!sock.daddr){return-53}var errno=writeSockaddr(addr,sock.family,DNS.lookup_name(sock.daddr),sock.dport,addrlen);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_getsockname(fd,addr,addrlen,d1,d2,d3){try{var sock=getSocketFromFD(fd);var errno=writeSockaddr(addr,sock.family,DNS.lookup_name(sock.saddr||"0.0.0.0"),sock.sport,addrlen);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_getsockopt(fd,level,optname,optval,optlen,d1){try{var sock=getSocketFromFD(fd);if(level===1){if(optname===4){HEAP32[optval>>2]=sock.error;HEAP32[optlen>>2]=4;sock.error=null;return 0}}return-50}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=SYSCALLS.get();HEAP32[argp>>2]=termios.c_iflag||0;HEAP32[argp+4>>2]=termios.c_oflag||0;HEAP32[argp+8>>2]=termios.c_cflag||0;HEAP32[argp+12>>2]=termios.c_lflag||0;for(var i=0;i<32;i++){HEAP8[argp+i+17>>0]=termios.c_cc[i]||0}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=SYSCALLS.get();var c_iflag=HEAP32[argp>>2];var c_oflag=HEAP32[argp+4>>2];var c_cflag=HEAP32[argp+8>>2];var c_lflag=HEAP32[argp+12>>2];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(HEAP8[argp+i+17>>0])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag:c_iflag,c_oflag:c_oflag,c_cflag:c_cflag,c_lflag:c_lflag,c_cc:c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=SYSCALLS.get();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=SYSCALLS.get();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=SYSCALLS.get();HEAP16[argp>>1]=winsize[0];HEAP16[argp+2>>1]=winsize[1]}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_listen(fd,backlog){try{var sock=getSocketFromFD(fd);sock.sock_ops.listen(sock,backlog);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_mkdirat(dirfd,path,mode){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.doStat(nofollow?FS.lstat:FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?SYSCALLS.get():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var PIPEFS={BUCKET_BUFFER_SIZE:8192,mount(mount){return FS.createNode(null,"/",16384|511,0)},createPipe(){var pipe={buckets:[],refcnt:2};pipe.buckets.push({buffer:new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),offset:0,roffset:0});var rName=PIPEFS.nextname();var wName=PIPEFS.nextname();var rNode=FS.createNode(PIPEFS.root,rName,4096,0);var wNode=FS.createNode(PIPEFS.root,wName,4096,0);rNode.pipe=pipe;wNode.pipe=pipe;var readableStream=FS.createStream({path:rName,node:rNode,flags:0,seekable:false,stream_ops:PIPEFS.stream_ops});rNode.stream=readableStream;var writableStream=FS.createStream({path:wName,node:wNode,flags:1,seekable:false,stream_ops:PIPEFS.stream_ops});wNode.stream=writableStream;return{readable_fd:readableStream.fd,writable_fd:writableStream.fd}},stream_ops:{poll(stream){var pipe=stream.node.pipe;if((stream.flags&2097155)===1){return 256|4}if(pipe.buckets.length>0){for(var i=0;i0){return 64|1}}}return 0},ioctl(stream,request,varargs){return 28},fsync(stream){return 28},read(stream,buffer,offset,length,position){var pipe=stream.node.pipe;var currentLength=0;for(var i=0;i=dataLen){currBucket.buffer.set(data,currBucket.offset);currBucket.offset+=dataLen;return dataLen}else if(freeBytesInCurrBuffer>0){currBucket.buffer.set(data.subarray(0,freeBytesInCurrBuffer),currBucket.offset);currBucket.offset+=freeBytesInCurrBuffer;data=data.subarray(freeBytesInCurrBuffer,data.byteLength)}var numBuckets=data.byteLength/PIPEFS.BUCKET_BUFFER_SIZE|0;var remElements=data.byteLength%PIPEFS.BUCKET_BUFFER_SIZE;for(var i=0;i0){var newBucket={buffer:new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE),offset:data.byteLength,roffset:0};pipe.buckets.push(newBucket);newBucket.buffer.set(data)}return dataLen},close(stream){var pipe=stream.node.pipe;pipe.refcnt--;if(pipe.refcnt===0){pipe.buckets=null}}},nextname(){if(!PIPEFS.nextname.current){PIPEFS.nextname.current=0}return"pipe["+PIPEFS.nextname.current+++"]"}};function ___syscall_pipe(fdPtr){try{if(fdPtr==0){throw new FS.ErrnoError(21)}var res=PIPEFS.createPipe();HEAP32[fdPtr>>2]=res.readable_fd;HEAP32[fdPtr+4>>2]=res.writable_fd;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_poll(fds,nfds,timeout){try{var nonzero=0;for(var i=0;i>2];var events=HEAP16[pollfd+4>>1];var mask=32;var stream=FS.getStream(fd);if(stream){mask=SYSCALLS.DEFAULT_POLLMASK;if (stream.stream_ops?.poll){mask=stream.stream_ops.poll(stream,-1)}}mask&=events|8|16;if(mask)nonzero++;HEAP16[pollfd+6>>1]=mask}return nonzero}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_readlinkat(dirfd,path,buf,bufsize){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_recvfrom(fd,buf,len,flags,addr,addrlen){try{var sock=getSocketFromFD(fd);var msg=sock.sock_ops.recvmsg(sock,len);if(!msg)return 0;if(addr){var errno=writeSockaddr(addr,sock.family,DNS.lookup_name(msg.addr),msg.port,addrlen)}HEAPU8.set(msg.buffer,buf);return msg.buffer.byteLength}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_renameat(olddirfd,oldpath,newdirfd,newpath){try{oldpath=SYSCALLS.getStr(oldpath);newpath=SYSCALLS.getStr(newpath);oldpath=SYSCALLS.calculateAt(olddirfd,oldpath);newpath=SYSCALLS.calculateAt(newdirfd,newpath);FS.rename(oldpath,newpath);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_rmdir(path){try{path=SYSCALLS.getStr(path);FS.rmdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_sendto(fd,message,length,flags,addr,addr_len){try{var sock=getSocketFromFD(fd);var dest=getSocketAddress(addr,addr_len,true);if(!dest){return FS.write(sock.stream,HEAP8,message,length)}return sock.sock_ops.sendmsg(sock,HEAP8,message,length,dest.addr,dest.port)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_socket(domain,type,protocol){try{var sock=SOCKFS.createSocket(domain,type,protocol);return sock.stream.fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_statfs64(path,size,buf){try{path=SYSCALLS.getStr(path);HEAP32[buf+4>>2]=4096;HEAP32[buf+40>>2]=4096;HEAP32[buf+8>>2]=1e6;HEAP32[buf+12>>2]=5e5;HEAP32[buf+16>>2]=5e5;HEAP32[buf+20>>2]=FS.nextInode;HEAP32[buf+24>>2]=1e6;HEAP32[buf+28>>2]=42;HEAP32[buf+44>>2]=2;HEAP32[buf+36>>2]=255;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_symlink(target,linkpath){try{target=SYSCALLS.getStr(target);linkpath=SYSCALLS.getStr(linkpath);FS.symlink(target,linkpath);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_unlinkat(dirfd,path,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(flags===0){FS.unlink(path)}else if(flags===512){FS.rmdir(path)}else{abort("Invalid flags passed to unlinkat")}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function readI53FromI64(ptr){return HEAPU32[ptr>>2]+HEAP32[ptr+4>>2]*4294967296}function ___syscall_utimensat(dirfd,path,times,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path,true);if(!times){var atime=Date.now();var mtime=atime}else{var seconds=readI53FromI64(times);var nanoseconds=HEAP32[times+8>>2];atime=seconds*1e3+nanoseconds/(1e3*1e3);times+=16;seconds=readI53FromI64(times);nanoseconds=HEAP32[times+8>>2];mtime=seconds*1e3+nanoseconds/(1e3*1e3)}FS.utime(path,atime,mtime);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var nowIsMonotonic=true;var __emscripten_get_now_is_monotonic=()=>nowIsMonotonic;var __emscripten_throw_longjmp=()=>{throw Infinity};function __gmtime_js(time_low,time_high,tmPtr){var time=convertI32PairToI53Checked(time_low,time_high);var date=new Date(time*1e3);HEAP32[tmPtr>>2]=date.getUTCSeconds();HEAP32[tmPtr+4>>2]=date.getUTCMinutes();HEAP32[tmPtr+8>>2]=date.getUTCHours();HEAP32[tmPtr+12>>2]=date.getUTCDate();HEAP32[tmPtr+16>>2]=date.getUTCMonth();HEAP32[tmPtr+20>>2]=date.getUTCFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getUTCDay();var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday}var isLeapYear=year=>year%4===0&&(year%100!==0||year%400===0);var MONTH_DAYS_LEAP_CUMULATIVE=[0,31,60,91,121,152,182,213,244,274,305,335];var MONTH_DAYS_REGULAR_CUMULATIVE=[0,31,59,90,120,151,181,212,243,273,304,334];var ydayFromDate=date=>{var leap=isLeapYear(date.getFullYear());var monthDaysCumulative=leap?MONTH_DAYS_LEAP_CUMULATIVE:MONTH_DAYS_REGULAR_CUMULATIVE;var yday=monthDaysCumulative[date.getMonth()]+date.getDate()-1;return yday};function __localtime_js(time_low,time_high,tmPtr){var time=convertI32PairToI53Checked(time_low,time_high);var date=new Date(time*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst}var __mktime_js=function(tmPtr){var ret=(()=>{var date=new Date(HEAP32[tmPtr+20>>2]+1900,HEAP32[tmPtr+16>>2],HEAP32[tmPtr+12>>2],HEAP32[tmPtr+8>>2],HEAP32[tmPtr+4>>2],HEAP32[tmPtr>>2],0);var dst=HEAP32[tmPtr+32>>2];var guessedOffset=date.getTimezoneOffset();var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dstOffset=Math.min(winterOffset,summerOffset);if(dst<0){HEAP32[tmPtr+32>>2]=Number(summerOffset!=winterOffset&&dstOffset==guessedOffset)}else if(dst>0!=(dstOffset==guessedOffset)){var nonDstOffset=Math.max(winterOffset,summerOffset);var trueOffset=dst>0?dstOffset:nonDstOffset;date.setTime(date.getTime()+(trueOffset-guessedOffset)*6e4)}HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getYear();return date.getTime()/1e3})();return setTempRet0((tempDouble=ret,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)),ret>>>0};function __mmap_js(len,prot,flags,fd,offset_low,offset_high,allocated,addr){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,offset,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;HEAPU32[addr>>2]=ptr;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset_low,offset_high){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}FS.munmap(stream)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){if(Module["onExit"])Module["onExit"](code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;if(!keepRuntimeAlive()){exitRuntime()}_proc_exit(status)};var _exit=exitJS;Module["_exit"]=_exit;var maybeExit=()=>{if(runtimeExited){return}if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(runtimeExited||ABORT){return}try{func();maybeExit()}catch(e){handleException(e)}};var _emscripten_get_now;_emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which]}if(!timeout_ms)return 0;var id=setTimeout((()=>{delete timers[which];callUserCallback((()=>__emscripten_timeout(which,_emscripten_get_now())))}),timeout_ms);timers[which]={id:id,timeout_ms:timeout_ms};return 0};var stringToNewUTF8=str=>{var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8(str,ret,size);return ret};var __tzset_js=(timezone,daylight,tzname)=>{var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);function extractZone(date){var match=date.toTimeString().match(/\(([A-Za-z ]+)\)$/);return match?match[1]:"GMT"}var winterName=extractZone(winter);var summerName=extractZone(summer);var winterNamePtr=stringToNewUTF8(winterName);var summerNamePtr=stringToNewUTF8(summerName);if(summerOffset>2]=winterNamePtr;HEAPU32[tzname+4>>2]=summerNamePtr}else{HEAPU32[tzname>>2]=summerNamePtr;HEAPU32[tzname+4>>2]=winterNamePtr}};var _abort=()=>{abort("")};function _emscripten_date_now(){return Date.now()}var getHeapMax=()=>2147483648;var _emscripten_get_heap_max=()=>getHeapMax();var _emscripten_memcpy_big=(dest,src,num)=>HEAPU8.copyWithin(dest,src,src+num);var growMemory=size=>{var b=wasmMemory.buffer;var pages=size-b.byteLength+65535>>>16;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var runtimeKeepalivePush=()=>{runtimeKeepaliveCounter+=1};var runtimeKeepalivePop=()=>{runtimeKeepaliveCounter-=1};var safeSetTimeout=(func,timeout)=>{runtimeKeepalivePush();return setTimeout((()=>{runtimeKeepalivePop();callUserCallback(func)}),timeout)};var _emscripten_sleep=function(ms){return Asyncify.handleSleep((wakeUp=>safeSetTimeout(wakeUp,ms)))};Module["_emscripten_sleep"]=_emscripten_sleep;_emscripten_sleep.isAsync=true;var ENV = PHPLoader.ENV || {};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={"USER":"web_user","LOGNAME":"web_user","PATH":"/","PWD":"/","HOME":"/home/web_user","LANG":lang,"_":getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var stringToAscii=(str,buffer)=>{for(var i=0;i>0]=str.charCodeAt(i)}HEAP8[buffer>>0]=0};var _environ_get=(__environ,environ_buf)=>{var bufSize=0;getEnvStrings().forEach((function(string,i){var ptr=environ_buf+bufSize;HEAPU32[__environ+i*4>>2]=ptr;stringToAscii(string,ptr);bufSize+=string.length+1}));return 0};var _environ_sizes_get=(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach((function(string){bufSize+=string.length+1}));HEAPU32[penviron_buf_size>>2]=bufSize;return 0};function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_fdstat_get(fd,pbuf){try{var rightsBase=0;var rightsInheriting=0;var flags=0;{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4}HEAP8[pbuf>>0]=type;HEAP16[pbuf+2>>1]=flags;tempI64=[rightsBase>>>0,(tempDouble=rightsBase,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+8>>2]=tempI64[0],HEAP32[pbuf+12>>2]=tempI64[1];tempI64=[rightsInheriting>>>0,(tempDouble=rightsInheriting,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+16>>2]=tempI64[0],HEAP32[pbuf+20>>2]=tempI64[1];return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(typeof offset!=="undefined"){offset+=curr}}return ret};function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var _getaddrinfo=(node,service,hint,out)=>{var addr=0;var port=0;var flags=0;var family=0;var type=0;var proto=0;var ai;function allocaddrinfo(family,type,proto,canon,addr,port){var sa,salen,ai;var errno;salen=family===10?28:16;addr=family===10?inetNtop6(addr):inetNtop4(addr);sa=_malloc(salen);errno=writeSockaddr(sa,family,addr,port);assert(!errno);ai=_malloc(32);HEAP32[ai+4>>2]=family;HEAP32[ai+8>>2]=type;HEAP32[ai+12>>2]=proto;HEAPU32[ai+24>>2]=canon;HEAPU32[ai+20>>2]=sa;if(family===10){HEAP32[ai+16>>2]=28}else{HEAP32[ai+16>>2]=16}HEAP32[ai+28>>2]=0;return ai}if(hint){flags=HEAP32[hint>>2];family=HEAP32[hint+4>>2];type=HEAP32[hint+8>>2];proto=HEAP32[hint+12>>2]}if(type&&!proto){proto=type===2?17:6}if(!type&&proto){type=proto===17?2:1}if(proto===0){proto=6}if(type===0){type=1}if(!node&&!service){return-2}if(flags&~(1|2|4|1024|8|16|32)){return-1}if(hint!==0&&HEAP32[hint>>2]&2&&!node){return-1}if(flags&32){return-2}if(type!==0&&type!==1&&type!==2){return-7}if(family!==0&&family!==2&&family!==10){return-6}if(service){service=UTF8ToString(service);port=parseInt(service,10);if(isNaN(port)){if(flags&1024){return-2}return-8}}if(!node){if(family===0){family=2}if((flags&1)===0){if(family===2){addr=_htonl(2130706433)}else{addr=[0,0,0,1]}}ai=allocaddrinfo(family,type,proto,null,addr,port);HEAPU32[out>>2]=ai;return 0}node=UTF8ToString(node);addr=inetPton4(node);if(addr!==null){if(family===0||family===2){family=2}else if(family===10&&flags&8){addr=[0,0,_htonl(65535),addr];family=10}else{return-2}}else{addr=inetPton6(node);if(addr!==null){if(family===0||family===10){family=10}else{return-2}}}if(addr!=null){ai=allocaddrinfo(family,type,proto,node,addr,port);HEAPU32[out>>2]=ai;return 0}if(flags&4){return-2}node=DNS.lookup_name(node);addr=inetPton4(node);if(family===0){family=2}else if(family===10){addr=[0,0,_htonl(65535),addr]}ai=allocaddrinfo(family,type,proto,null,addr,port);HEAPU32[out>>2]=ai;return 0};var getHostByName=name=>{var ret=_malloc(20);var nameBuf=stringToNewUTF8(name);HEAPU32[ret>>2]=nameBuf;var aliasesBuf=_malloc(4);HEAPU32[aliasesBuf>>2]=0;HEAPU32[ret+4>>2]=aliasesBuf;var afinet=2;HEAP32[ret+8>>2]=afinet;HEAP32[ret+12>>2]=4;var addrListBuf=_malloc(12);HEAPU32[addrListBuf>>2]=addrListBuf+8;HEAPU32[addrListBuf+4>>2]=0;HEAP32[addrListBuf+8>>2]=inetPton4(DNS.lookup_name(name));HEAPU32[ret+16>>2]=addrListBuf;return ret};var _gethostbyaddr=(addr,addrlen,type)=>{if(type!==2){setErrNo(5);return null}addr=HEAP32[addr>>2];var host=inetNtop4(addr);var lookup=DNS.lookup_addr(host);if(lookup){host=lookup}return getHostByName(host)};var _gethostbyname=name=>getHostByName(UTF8ToString(name));var _gethostbyname_r=(name,ret,buf,buflen,out,err)=>{var data=_gethostbyname(name);_memcpy(ret,data,20);_free(data);HEAP32[err>>2]=0;HEAPU32[out>>2]=ret;return 0};var _getloadavg=(loadavg,nelem)=>{var limit=Math.min(nelem,3);var doubleSize=8;for(var i=0;i>3]=.1}return limit};var _getnameinfo=(sa,salen,node,nodelen,serv,servlen,flags)=>{var info=readSockaddr(sa,salen);if(info.errno){return-6}var port=info.port;var addr=info.addr;var overflowed=false;if(node&&nodelen){var lookup;if(flags&1||!(lookup=DNS.lookup_addr(addr))){if(flags&8){return-2}}else{addr=lookup}var numBytesWrittenExclNull=stringToUTF8(addr,node,nodelen);if(numBytesWrittenExclNull+1>=nodelen){overflowed=true}}if(serv&&servlen){port=""+port;var numBytesWrittenExclNull=stringToUTF8(port,serv,servlen);if(numBytesWrittenExclNull+1>=servlen){overflowed=true}}if(overflowed){return-12}return 0};var Protocols={list:[],map:{}};var _setprotoent=stayopen=>{function allocprotoent(name,proto,aliases){var nameBuf=_malloc(name.length+1);stringToAscii(name,nameBuf);var j=0;var length=aliases.length;var aliasListBuf=_malloc((length+1)*4);for(var i=0;i>2]=aliasBuf}HEAPU32[aliasListBuf+j>>2]=0;var pe=_malloc(12);HEAPU32[pe>>2]=nameBuf;HEAPU32[pe+4>>2]=aliasListBuf;HEAP32[pe+8>>2]=proto;return pe}var list=Protocols.list;var map=Protocols.map;if(list.length===0){var entry=allocprotoent("tcp",6,["TCP"]);list.push(entry);map["tcp"]=map["6"]=entry;entry=allocprotoent("udp",17,["UDP"]);list.push(entry);map["udp"]=map["17"]=entry}_setprotoent.index=0};var _getprotobyname=name=>{name=UTF8ToString(name);_setprotoent(true);var result=Protocols.map[name];return result};var _getprotobynumber=number=>{_setprotoent(true);var result=Protocols.map[number];return result};var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var allocateUTF8OnStack=stringToUTF8OnStack;var PHPWASM={init:function(){FS.mkdir("/internal");PHPWASM.EventEmitter=ENVIRONMENT_IS_NODE?require("events").EventEmitter:class EventEmitter{constructor(){this.listeners={}}emit(eventName,data){if(this.listeners[eventName]){this.listeners[eventName].forEach((callback=>{callback(data)}))}}once(eventName,callback){const self=this;function removedCallback(){callback(...arguments);self.removeListener(eventName,removedCallback)}this.on(eventName,removedCallback)}removeAllListeners(eventName){if(eventName){delete this.listeners[eventName]}else{this.listeners={}}}removeListener(eventName,callback){if(this.listeners[eventName]){const idx=this.listeners[eventName].indexOf(callback);if(idx!==-1){this.listeners[eventName].splice(idx,1)}}}};PHPWASM.child_proc_by_fd={};PHPWASM.child_proc_by_pid={};PHPWASM.input_devices={}},getAllWebSockets:function(sock){const webSockets=new Set;if(sock.server){sock.server.clients.forEach((ws=>{webSockets.add(ws)}))}for(const peer of PHPWASM.getAllPeers(sock)){webSockets.add(peer.socket)}return Array.from(webSockets)},getAllPeers:function(sock){const peers=new Set;if(sock.server){sock.pending.filter((pending=>pending.peers)).forEach((pending=>{for(const peer of Object.values(pending.peers)){peers.add(peer)}}))}if(sock.peers){for(const peer of Object.values(sock.peers)){peers.add(peer)}}return Array.from(peers)},awaitData:function(ws){return PHPWASM.awaitEvent(ws,"message")},awaitConnection:function(ws){if(ws.OPEN===ws.readyState){return[Promise.resolve(),PHPWASM.noop]}return PHPWASM.awaitEvent(ws,"open")},awaitClose:function(ws){if([ws.CLOSING,ws.CLOSED].includes(ws.readyState)){return[Promise.resolve(),PHPWASM.noop]}return PHPWASM.awaitEvent(ws,"close")},awaitError:function(ws){if([ws.CLOSING,ws.CLOSED].includes(ws.readyState)){return[Promise.resolve(),PHPWASM.noop]}return PHPWASM.awaitEvent(ws,"error")},awaitEvent:function(ws,event){let resolve;const listener=()=>{resolve()};const promise=new Promise((function(_resolve){resolve=_resolve;ws.once(event,listener)}));const cancel=()=>{ws.removeListener(event,listener);setTimeout(resolve)};return[promise,cancel]},noop:function(){},spawnProcess:function(command,args,options){if(Module["spawnProcess"]){const spawnedPromise=Module["spawnProcess"](command,args,options);return Promise.resolve(spawnedPromise).then((function(spawned){if(!spawned||!spawned.on){throw new Error("spawnProcess() must return an EventEmitter but returned a different type.")}return spawned}))}if(ENVIRONMENT_IS_NODE){return require("child_process").spawn(command,args,{...options,shell:true,stdio:["pipe","pipe","pipe"],timeout:100})}const e=new Error("popen(), proc_open() etc. are unsupported in the browser. Call php.setSpawnHandler() "+"and provide a callback to handle spawning processes, or disable a popen(), proc_open() "+"and similar functions via php.ini.");e.code="SPAWN_UNSUPPORTED";throw e},shutdownSocket:function(socketd,how){const sock=getSocketFromFD(socketd);const peer=Object.values(sock.peers)[0];if(!peer){return-1}try{peer.socket.close();SOCKFS.websocket_sock_ops.removePeer(sock,peer);return 0}catch(e){console.log("Socket shutdown error",e);return-1}}};function _js_create_input_device(deviceId){let dataBuffer=[];let dataCallback;const filename="proc_id_"+deviceId;const device=FS.createDevice("/dev",filename,(function(){}),(function(byte){try{dataBuffer.push(byte);if(dataCallback){dataCallback(new Uint8Array(dataBuffer));dataBuffer=[]}}catch(e){console.error(e);throw e}}));const devicePath="/dev/"+filename;PHPWASM.input_devices[deviceId]={devicePath:devicePath,onData:function(cb){dataCallback=cb;dataBuffer.forEach((function(data){cb(data)}));dataBuffer.length=0}};return allocateUTF8OnStack(devicePath)}function _js_fd_read(fd,iov,iovcnt,pnum){if(Asyncify.state===Asyncify.State.Normal){var returnCode;var stream;let num=0;try{stream=SYSCALLS.getStreamFromFD(fd);const num=doReadv(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError")){throw e}if(e.errno!==6||!(stream?.fd in PHPWASM.child_proc_by_fd)){HEAPU32[pnum>>2]=0;return returnCode}}}return Asyncify.handleSleep((function(wakeUp){var retries=0;var interval=50;var timeout=5e3;var maxRetries=timeout/interval;function poll(){var returnCode;var stream;let num;try{stream=SYSCALLS.getStreamFromFD(fd);num=doReadv(stream,iov,iovcnt);returnCode=0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError")){console.error(e);throw e}returnCode=e.errno}const success=returnCode===0;const failure=++retries>maxRetries||!(fd in PHPWASM.child_proc_by_fd)||PHPWASM.child_proc_by_fd[fd]?.exited||FS.isClosed(stream);if(success){HEAPU32[pnum>>2]=num;wakeUp(0)}else if(failure){HEAPU32[pnum>>2]=0;wakeUp(returnCode===6?0:returnCode)}else{setTimeout(poll,interval)}}poll()}))}function _js_module_onMessage(data,bufPtr){if(typeof Asyncify==="undefined"){return}if(Module["onMessage"]){const dataStr=UTF8ToString(data);return Asyncify.handleSleep((wakeUp=>{Module["onMessage"](dataStr).then((response=>{const responseBytes=typeof response==="string"?(new TextEncoder).encode(response):response;const responseSize=responseBytes.byteLength;const responsePtr=_malloc(responseSize+1);HEAPU8.set(responseBytes,responsePtr);HEAPU8[responsePtr+responseSize]=0;HEAPU8[bufPtr]=responsePtr;HEAPU8[bufPtr+1]=responsePtr>>8;HEAPU8[bufPtr+2]=responsePtr>>16;HEAPU8[bufPtr+3]=responsePtr>>24;wakeUp(responseSize)})).catch((e=>{console.error(e);wakeUp(-1)}))}))}}function _js_open_process(command,argsPtr,argsLength,descriptorsPtr,descriptorsLength,cwdPtr,cwdLength,envPtr,envLength){if(!command){return 1}const cmdstr=UTF8ToString(command);if(!cmdstr.length){return 0}let argsArray=[];if(argsLength){for(var i=0;i>2]))}}const cwdstr=cwdPtr?UTF8ToString(cwdPtr):null;let envObject=null;if(envLength){envObject={};for(var i=0;i>2]);const splitAt=envEntry.indexOf("=");if(splitAt===-1){continue}const key=envEntry.substring(0,splitAt);const value=envEntry.substring(splitAt+1);envObject[key]=value}}var std={};for(var i=0;i>2];std[HEAPU32[descriptorPtr>>2]]={child:HEAPU32[descriptorPtr+4>>2],parent:HEAPU32[descriptorPtr+8>>2]}}return Asyncify.handleSleep((async wakeUp=>{let cp;try{const options={};if(cwdstr!==null){options.cwd=cwdstr}if(envObject!==null){options.env=envObject}cp=PHPWASM.spawnProcess(cmdstr,argsArray,options);if(cp instanceof Promise){cp=await cp}}catch(e){if(e.code==="SPAWN_UNSUPPORTED"){wakeUp(1);return}console.error(e);wakeUp(1);throw e}const ProcInfo={pid:cp.pid,exited:false,stdinFd:std[0]?.child,stdinIsDevice:std[0]?.child in PHPWASM.input_devices,stdoutChildFd:std[1]?.child,stdoutParentFd:std[1]?.parent,stderrChildFd:std[2]?.child,stderrParentFd:std[2]?.parent,stdout:new PHPWASM.EventEmitter,stderr:new PHPWASM.EventEmitter};if(ProcInfo.stdoutChildFd)PHPWASM.child_proc_by_fd[ProcInfo.stdoutChildFd]=ProcInfo;if(ProcInfo.stderrChildFd)PHPWASM.child_proc_by_fd[ProcInfo.stderrChildFd]=ProcInfo;if(ProcInfo.stdoutParentFd)PHPWASM.child_proc_by_fd[ProcInfo.stdoutParentFd]=ProcInfo;if(ProcInfo.stderrParentFd)PHPWASM.child_proc_by_fd[ProcInfo.stderrParentFd]=ProcInfo;PHPWASM.child_proc_by_pid[ProcInfo.pid]=ProcInfo;cp.on("exit",(function(code){ProcInfo.exitCode=code;ProcInfo.exited=true;ProcInfo.stdout.emit("data");ProcInfo.stderr.emit("data")}));if(ProcInfo.stdoutChildFd){const stdoutStream=SYSCALLS.getStreamFromFD(ProcInfo.stdoutChildFd);let stdoutAt=0;cp.stdout.on("data",(function(data){ProcInfo.stdout.emit("data",data);stdoutStream.stream_ops.write(stdoutStream,data,0,data.length,stdoutAt);stdoutAt+=data.length}))}if(ProcInfo.stderrChildFd){const stderrStream=SYSCALLS.getStreamFromFD(ProcInfo.stderrChildFd);let stderrAt=0;cp.stderr.on("data",(function(data){ProcInfo.stderr.emit("data",data);stderrStream.stream_ops.write(stderrStream,data,0,data.length,stderrAt);stderrAt+=data.length}))}try{await new Promise(((resolve,reject)=>{cp.on("spawn",resolve);cp.on("error",reject)}))}catch(e){console.error(e);wakeUp(1);return}if(ProcInfo.stdinIsDevice){PHPWASM.input_devices[ProcInfo.stdinFd].onData((function(data){if(!data)return;const dataStr=new TextDecoder("utf-8").decode(data);cp.stdin.write(dataStr)}));wakeUp(ProcInfo.pid);return}if(ProcInfo.stdinFd){const stdinStream=SYSCALLS.getStreamFromFD(ProcInfo.stdinFd);if(stdinStream.node){const CHUNK_SIZE=1024;const buffer=new Uint8Array(CHUNK_SIZE);let offset=0;while(true){const bytesRead=stdinStream.stream_ops.read(stdinStream,buffer,0,CHUNK_SIZE,offset);if(bytesRead===null||bytesRead===0){break}try{cp.stdin.write(buffer.subarray(0,bytesRead))}catch(e){console.error(e);return 1}if(bytesRead{let cp;try{cp=PHPWASM.spawnProcess(cmdstr,[]);if(cp instanceof Promise){cp=await cp}}catch(e){console.error(e);if(e.code==="SPAWN_UNSUPPORTED"){return 1}throw e}const outByteArrays=[];cp.stdout.on("data",(function(data){outByteArrays.push(data)}));const outputPath="/tmp/popen_output";cp.on("exit",(function(exitCode){const outBytes=new Uint8Array(outByteArrays.reduce(((acc,curr)=>acc+curr.length),0));let offset=0;for(const byteArray of outByteArrays){outBytes.set(byteArray,offset);offset+=byteArray.length}FS.writeFile(outputPath,outBytes);HEAPU8[exitCodePtr]=exitCode;wakeUp(allocateUTF8OnStack(outputPath))}))}))}function _js_process_status(pid,exitCodePtr){if(!PHPWASM.child_proc_by_pid[pid]){return-1}if(PHPWASM.child_proc_by_pid[pid].exited){HEAPU32[exitCodePtr>>2]=PHPWASM.child_proc_by_pid[pid].exitCode;return 1}return 0}function _js_waitpid(pid,exitCodePtr){if(!PHPWASM.child_proc_by_pid[pid]){return-1}return Asyncify.handleSleep((wakeUp=>{const poll=function(){if(PHPWASM.child_proc_by_pid[pid]?.exited){HEAPU32[exitCodePtr>>2]=PHPWASM.child_proc_by_pid[pid].exitCode;wakeUp(pid)}else{setTimeout(poll,50)}};poll()}))}var arraySum=(array,index)=>{var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum};var MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];var addDays=(date,days)=>{var newDate=new Date(date.getTime());while(days>0){var leap=isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate};var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};var _strftime=(s,maxsize,format,tm)=>{var tm_zone=HEAP32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):""};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_1[rule])}var WEEKDAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var MONTHS=["January","February","March","April","May","June","July","August","September","October","November","December"];function leadingSomething(value,digits,character){var str=typeof value=="number"?value.toString():value||"";while(str.length0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}return thisDate.getFullYear()}return thisDate.getFullYear()-1}var EXPANSION_RULES_2={"%a":date=>WEEKDAYS[date.tm_wday].substring(0,3),"%A":date=>WEEKDAYS[date.tm_wday],"%b":date=>MONTHS[date.tm_mon].substring(0,3),"%B":date=>MONTHS[date.tm_mon],"%C":date=>{var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},"%d":date=>leadingNulls(date.tm_mday,2),"%e":date=>leadingSomething(date.tm_mday,2," "),"%g":date=>getWeekBasedYear(date).toString().substring(2),"%G":date=>getWeekBasedYear(date),"%H":date=>leadingNulls(date.tm_hour,2),"%I":date=>{var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},"%j":date=>leadingNulls(date.tm_mday+arraySum(isLeapYear(date.tm_year+1900)?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,date.tm_mon-1),3),"%m":date=>leadingNulls(date.tm_mon+1,2),"%M":date=>leadingNulls(date.tm_min,2),"%n":()=>"\n","%p":date=>{if(date.tm_hour>=0&&date.tm_hour<12){return"AM"}return"PM"},"%S":date=>leadingNulls(date.tm_sec,2),"%t":()=>"\t","%u":date=>date.tm_wday||7,"%U":date=>{var days=date.tm_yday+7-date.tm_wday;return leadingNulls(Math.floor(days/7),2)},"%V":date=>{var val=Math.floor((date.tm_yday+7-(date.tm_wday+6)%7)/7);if((date.tm_wday+371-date.tm_yday-2)%7<=2){val++}if(!val){val=52;var dec31=(date.tm_wday+7-date.tm_yday-1)%7;if(dec31==4||dec31==5&&isLeapYear(date.tm_year%400-1)){val++}}else if(val==53){var jan1=(date.tm_wday+371-date.tm_yday)%7;if(jan1!=4&&(jan1!=3||!isLeapYear(date.tm_year)))val=1}return leadingNulls(val,2)},"%w":date=>date.tm_wday,"%W":date=>{var days=date.tm_yday+7-(date.tm_wday+6)%7;return leadingNulls(Math.floor(days/7),2)},"%y":date=>(date.tm_year+1900).toString().substring(2),"%Y":date=>date.tm_year+1900,"%z":date=>{var off=date.tm_gmtoff;var ahead=off>=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?"+":"-")+String("0000"+off).slice(-4)},"%Z":date=>date.tm_zone,"%%":()=>"%"};pattern=pattern.replace(/%%/g,"\0\0");for(var rule in EXPANSION_RULES_2){if(pattern.includes(rule)){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_2[rule](date))}}pattern=pattern.replace(/\0\0/g,"%");var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1};var _strptime=(buf,format,tm)=>{var pattern=UTF8ToString(format);var SPECIAL_CHARS="\\!@#$^&*()+=-[]/{}|:<>?,.";for(var i=0,ii=SPECIAL_CHARS.length;i=0;i=pattern.indexOf("%")){capture.push(pattern[i+1]);pattern=pattern.replace(new RegExp("\\%"+pattern[i+1],"g"),"")}var matches=new RegExp("^"+pattern,"i").exec(UTF8ToString(buf));function initDate(){function fixup(value,min,max){return typeof value!="number"||isNaN(value)?min:value>=min?value<=max?value:max:min}return{year:fixup(HEAP32[tm+20>>2]+1900,1970,9999),month:fixup(HEAP32[tm+16>>2],0,11),day:fixup(HEAP32[tm+12>>2],1,31),hour:fixup(HEAP32[tm+8>>2],0,23),min:fixup(HEAP32[tm+4>>2],0,59),sec:fixup(HEAP32[tm>>2],0,59)}}if(matches){var date=initDate();var value;var getMatch=symbol=>{var pos=capture.indexOf(symbol);if(pos>=0){return matches[pos+1]}return};if(value=getMatch("S")){date.sec=jstoi_q(value)}if(value=getMatch("M")){date.min=jstoi_q(value)}if(value=getMatch("H")){date.hour=jstoi_q(value)}else if(value=getMatch("I")){var hour=jstoi_q(value);if(value=getMatch("p")){hour+=value.toUpperCase()[0]==="P"?12:0}date.hour=hour}if(value=getMatch("Y")){date.year=jstoi_q(value)}else if(value=getMatch("y")){var year=jstoi_q(value);if(value=getMatch("C")){year+=jstoi_q(value)*100}else{year+=year<69?2e3:1900}date.year=year}if(value=getMatch("m")){date.month=jstoi_q(value)-1}else if(value=getMatch("b")){date.month=MONTH_NUMBERS[value.substring(0,3).toUpperCase()]||0}if(value=getMatch("d")){date.day=jstoi_q(value)}else if(value=getMatch("j")){var day=jstoi_q(value);var leapYear=isLeapYear(date.year);for(var month=0;month<12;++month){var daysUntilMonth=arraySum(leapYear?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,month-1);if(day<=daysUntilMonth+(leapYear?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[month]){date.day=day-daysUntilMonth}}}else if(value=getMatch("a")){var weekDay=value.substring(0,3).toUpperCase();if(value=getMatch("U")){var weekDayNumber=DAY_NUMBERS_SUN_FIRST[weekDay];var weekNumber=jstoi_q(value);var janFirst=new Date(date.year,0,1);var endDate;if(janFirst.getDay()===0){endDate=addDays(janFirst,weekDayNumber+7*(weekNumber-1))}else{endDate=addDays(janFirst,7-janFirst.getDay()+weekDayNumber+7*(weekNumber-1))}date.day=endDate.getDate();date.month=endDate.getMonth()}else if(value=getMatch("W")){var weekDayNumber=DAY_NUMBERS_MON_FIRST[weekDay];var weekNumber=jstoi_q(value);var janFirst=new Date(date.year,0,1);var endDate;if(janFirst.getDay()===1){endDate=addDays(janFirst,weekDayNumber+7*(weekNumber-1))}else{endDate=addDays(janFirst,7-janFirst.getDay()+1+weekDayNumber+7*(weekNumber-1))}date.day=endDate.getDate();date.month=endDate.getMonth()}}var fullDate=new Date(date.year,date.month,date.day,date.hour,date.min,date.sec,0);HEAP32[tm>>2]=fullDate.getSeconds();HEAP32[tm+4>>2]=fullDate.getMinutes();HEAP32[tm+8>>2]=fullDate.getHours();HEAP32[tm+12>>2]=fullDate.getDate();HEAP32[tm+16>>2]=fullDate.getMonth();HEAP32[tm+20>>2]=fullDate.getFullYear()-1900;HEAP32[tm+24>>2]=fullDate.getDay();HEAP32[tm+28>>2]=arraySum(isLeapYear(fullDate.getFullYear())?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,fullDate.getMonth()-1)+fullDate.getDate()-1;HEAP32[tm+32>>2]=0;return buf+intArrayFromString(matches[0]).length-1}return 0};function _wasm_poll_socket(socketd,events,timeout){if(typeof Asyncify==="undefined"){return 0}const POLLIN=1;const POLLPRI=2;const POLLOUT=4;const POLLERR=8;const POLLHUP=16;const POLLNVAL=32;return Asyncify.handleSleep((wakeUp=>{const polls=[];if(socketd in PHPWASM.child_proc_by_fd){const procInfo=PHPWASM.child_proc_by_fd[socketd];if(procInfo.exited){wakeUp(0);return}polls.push(PHPWASM.awaitEvent(procInfo.stdout,"data"))}else{const sock=getSocketFromFD(socketd);if(!sock){wakeUp(0);return}const lookingFor=new Set;if(events&POLLIN||events&POLLPRI){if(sock.server){for(const client of sock.pending){if((client.recv_queue||[]).length>0){wakeUp(1);return}}}else if((sock.recv_queue||[]).length>0){wakeUp(1);return}}const webSockets=PHPWASM.getAllWebSockets(sock);if(!webSockets.length){wakeUp(0);return}for(const ws of webSockets){if(events&POLLIN||events&POLLPRI){polls.push(PHPWASM.awaitData(ws));lookingFor.add("POLLIN")}if(events&POLLOUT){polls.push(PHPWASM.awaitConnection(ws));lookingFor.add("POLLOUT")}if(events&POLLHUP){polls.push(PHPWASM.awaitClose(ws));lookingFor.add("POLLHUP")}if(events&POLLERR||events&POLLNVAL){polls.push(PHPWASM.awaitError(ws));lookingFor.add("POLLERR")}}}if(polls.length===0){console.warn("Unsupported poll event "+events+", defaulting to setTimeout().");setTimeout((function(){wakeUp(0)}),timeout);return}const promises=polls.map((([promise])=>promise));const clearPolling=()=>polls.forEach((([,clear])=>clear()));let awaken=false;let timeoutId;Promise.race(promises).then((function(results){if(!awaken){awaken=true;wakeUp(1);if(timeoutId){clearTimeout(timeoutId)}clearPolling()}}));if(timeout!==-1){timeoutId=setTimeout((function(){if(!awaken){awaken=true;wakeUp(0);clearPolling()}}),timeout)}}))}function _wasm_setsockopt(socketd,level,optionName,optionValuePtr,optionLen){const optionValue=HEAPU8[optionValuePtr];const SOL_SOCKET=1;const SO_KEEPALIVE=9;const IPPROTO_TCP=6;const TCP_NODELAY=1;const isSupported=level===SOL_SOCKET&&optionName===SO_KEEPALIVE||level===IPPROTO_TCP&&optionName===TCP_NODELAY;if(!isSupported){console.warn(`Unsupported socket option: ${level}, ${optionName}, ${optionValue}`);return-1}const ws=PHPWASM.getAllWebSockets(socketd)[0];if(!ws){return-1}ws.setSocketOpt(level,optionName,optionValuePtr);return 0}function runAndAbortIfError(func){try{return func()}catch(e){abort(e)}}var Asyncify={instrumentWasmImports:function(imports){var importPatterns=[/^_dlopen_js$/,/^invoke_i$/,/^invoke_ii$/,/^invoke_iii$/,/^invoke_iiii$/,/^invoke_iiiii$/,/^invoke_iiiiii$/,/^invoke_iiiiiii$/,/^invoke_iiiiiiii$/,/^invoke_iiiiiiiiii$/,/^invoke_v$/,/^invoke_vi$/,/^invoke_vii$/,/^invoke_viidii$/,/^invoke_viii$/,/^invoke_viiii$/,/^invoke_viiiii$/,/^invoke_viiiiii$/,/^invoke_viiiiiii$/,/^invoke_viiiiiiiii$/,/^js_open_process$/,/^js_popen_to_file$/,/^js_fd_read$/,/^js_module_onMessage$/,/^js_waitpid$/,/^wasm_poll_socket$/,/^wasm_shutdown$/,/^fd_sync$/,/^__wasi_fd_sync$/,/^__asyncjs__.*$/,/^emscripten_promise_await$/,/^emscripten_idb_load$/,/^emscripten_idb_store$/,/^emscripten_idb_delete$/,/^emscripten_idb_exists$/,/^emscripten_idb_load_blob$/,/^emscripten_idb_store_blob$/,/^emscripten_sleep$/,/^emscripten_wget_data$/,/^emscripten_scan_registers$/,/^emscripten_lazy_load_code$/,/^_load_secondary_module$/,/^emscripten_fiber_swap$/,/^SDL_Delay$/];for(var x in imports){(function(x){var original=imports[x];var sig=original.sig;if(typeof original=="function"){var isAsyncifyImport=original.isAsync||importPatterns.some((pattern=>!!x.match(pattern)))}})(x)}},instrumentWasmExports:function(exports){var ret={};for(var x in exports){(function(x){var original=exports[x];if(typeof original=="function"){ret[x]=function(){Asyncify.exportCallStack.push(x);try{return original.apply(null,arguments)}finally{if(!ABORT){var y=Asyncify.exportCallStack.pop();assert(y===x);Asyncify.maybeStopUnwind()}}}}else{ret[x]=original}})(x)}return ret},State:{Normal:0,Unwinding:1,Rewinding:2,Disabled:3},state:0,StackSize:4096,currData:null,handleSleepReturnValue:0,exportCallStack:[],callStackNameToId:{},callStackIdToName:{},callStackId:0,asyncPromiseHandlers:null,sleepCallbacks:[],getCallStackId:function(funcName){var id=Asyncify.callStackNameToId[funcName];if(id===undefined){id=Asyncify.callStackId++;Asyncify.callStackNameToId[funcName]=id;Asyncify.callStackIdToName[id]=funcName}return id},maybeStopUnwind:function(){if(Asyncify.currData&&Asyncify.state===Asyncify.State.Unwinding&&Asyncify.exportCallStack.length===0){Asyncify.state=Asyncify.State.Normal;runtimeKeepalivePush();runAndAbortIfError(_asyncify_stop_unwind);if(typeof Fibers!="undefined"){Fibers.trampoline()}}},whenDone:function(){return new Promise(((resolve,reject)=>{Asyncify.asyncPromiseHandlers={resolve:resolve,reject:reject}}))},allocateData:function(){var ptr=_malloc(12+Asyncify.StackSize);Asyncify.setDataHeader(ptr,ptr+12,Asyncify.StackSize);Asyncify.setDataRewindFunc(ptr);return ptr},setDataHeader:function(ptr,stack,stackSize){HEAP32[ptr>>2]=stack;HEAP32[ptr+4>>2]=stack+stackSize},setDataRewindFunc:function(ptr){var bottomOfCallStack=Asyncify.exportCallStack[0];var rewindId=Asyncify.getCallStackId(bottomOfCallStack);HEAP32[ptr+8>>2]=rewindId},getDataRewindFunc:function(ptr){var id=HEAP32[ptr+8>>2];var name=Asyncify.callStackIdToName[id];var func=Module["asm"][name];return func},doRewind:function(ptr){var start=Asyncify.getDataRewindFunc(ptr);runtimeKeepalivePop();return start()},handleSleep:function(startAsync){if(ABORT)return;if(Asyncify.state===Asyncify.State.Normal){var reachedCallback=false;var reachedAfterCallback=false;startAsync(((handleSleepReturnValue=0)=>{if(ABORT)return;Asyncify.handleSleepReturnValue=handleSleepReturnValue;reachedCallback=true;if(!reachedAfterCallback){return}Asyncify.state=Asyncify.State.Rewinding;runAndAbortIfError((()=>_asyncify_start_rewind(Asyncify.currData)));if(typeof Browser!="undefined"&&Browser.mainLoop.func){Browser.mainLoop.resume()}var asyncWasmReturnValue,isError=false;try{asyncWasmReturnValue=Asyncify.doRewind(Asyncify.currData)}catch(err){asyncWasmReturnValue=err;isError=true}var handled=false;if(!Asyncify.currData){var asyncPromiseHandlers=Asyncify.asyncPromiseHandlers;if(asyncPromiseHandlers){Asyncify.asyncPromiseHandlers=null;(isError?asyncPromiseHandlers.reject:asyncPromiseHandlers.resolve)(asyncWasmReturnValue);handled=true}}if(isError&&!handled){throw asyncWasmReturnValue}}));reachedAfterCallback=true;if(!reachedCallback){Asyncify.state=Asyncify.State.Unwinding;Asyncify.currData=Asyncify.allocateData();if(typeof Browser!="undefined"&&Browser.mainLoop.func){Browser.mainLoop.pause()}runAndAbortIfError((()=>_asyncify_start_unwind(Asyncify.currData)))}}else if(Asyncify.state===Asyncify.State.Rewinding){Asyncify.state=Asyncify.State.Normal;runAndAbortIfError(_asyncify_stop_rewind);_free(Asyncify.currData);Asyncify.currData=null;Asyncify.sleepCallbacks.forEach((func=>callUserCallback(func)))}else{abort(`invalid state: ${Asyncify.state}`)}return Asyncify.handleSleepReturnValue},handleAsync:function(startAsync){return Asyncify.handleSleep((wakeUp=>{startAsync().then(wakeUp)}))}};function getCFunc(ident){var func=Module["_"+ident];return func}var ccall=function(ident,returnType,argTypes,args,opts){var toC={"string":str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},"array":arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout((function(){setTimeout((function(){Module["setStatus"]("")}),1);doRun()}),1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run(); +}else if ("string" === typeof Module["websocket"]["url"]) { + url = Module['websocket']['url']; // Fetch runtime WebSocket URL config. + } + } + + if (url === 'ws://' || url === 'wss://') { // Is the supplied URL config just a prefix, if so complete it. + var parts = addr.split('/'); + url = url + parts[0] + ":" + port + "/" + parts.slice(1).join('/'); + } + + // Make the WebSocket subprotocol (Sec-WebSocket-Protocol) default to binary if no configuration is set. + var subProtocols = 'binary'; // The default value is 'binary' + + if (runtimeConfig) { + if ('string' === typeof Module['websocket']['subprotocol']) { + subProtocols = Module['websocket']['subprotocol']; // Fetch runtime WebSocket subprotocol config. + } + } + + // The default WebSocket options + var opts = undefined; + + if (subProtocols !== 'null') { + // The regex trims the string (removes spaces at the beginning and end, then splits the string by + // , into an Array. Whitespace removal is important for Websockify and ws. + subProtocols = subProtocols.replace(/^ +| +$/g,"").split(/ *, */); + + opts = subProtocols; + } + + // some webservers (azure) does not support subprotocol header + if (runtimeConfig && null === Module['websocket']['subprotocol']) { + subProtocols = 'null'; + opts = undefined; + } + + // If node we use the ws library. + var WebSocketConstructor; + { + WebSocketConstructor = WebSocket; + } + if (Module['websocket']['decorator']) {WebSocketConstructor = Module['websocket']['decorator'](WebSocketConstructor);}ws = new WebSocketConstructor(url, opts); + ws.binaryType = 'arraybuffer'; + } catch (e) { + throw new FS.ErrnoError(23); + } + } + + var peer = { + addr, + port, + socket: ws, + dgram_send_queue: [] + }; + + SOCKFS.websocket_sock_ops.addPeer(sock, peer); + SOCKFS.websocket_sock_ops.handlePeerEvents(sock, peer); + + // if this is a bound dgram socket, send the port number first to allow + // us to override the ephemeral port reported to us by remotePort on the + // remote end. + if (sock.type === 2 && typeof sock.sport != 'undefined') { + peer.dgram_send_queue.push(new Uint8Array([ + 255, 255, 255, 255, + 'p'.charCodeAt(0), 'o'.charCodeAt(0), 'r'.charCodeAt(0), 't'.charCodeAt(0), + ((sock.sport & 0xff00) >> 8) , (sock.sport & 0xff) + ])); + } + + return peer; + }, + getPeer(sock, addr, port) { + return sock.peers[addr + ':' + port]; + }, + addPeer(sock, peer) { + sock.peers[peer.addr + ':' + peer.port] = peer; + }, + removePeer(sock, peer) { + delete sock.peers[peer.addr + ':' + peer.port]; + }, + handlePeerEvents(sock, peer) { + var first = true; + + var handleOpen = function () { + + Module['websocket'].emit('open', sock.stream.fd); + + try { + var queued = peer.dgram_send_queue.shift(); + while (queued) { + peer.socket.send(queued); + queued = peer.dgram_send_queue.shift(); + } + } catch (e) { + // not much we can do here in the way of proper error handling as we've already + // lied and said this data was sent. shut it down. + peer.socket.close(); + } + }; + + function handleMessage(data) { + if (typeof data == 'string') { + var encoder = new TextEncoder(); // should be utf-8 + data = encoder.encode(data); // make a typed array from the string + } else { + assert(data.byteLength !== undefined); // must receive an ArrayBuffer + if (data.byteLength == 0) { + // An empty ArrayBuffer will emit a pseudo disconnect event + // as recv/recvmsg will return zero which indicates that a socket + // has performed a shutdown although the connection has not been disconnected yet. + return; + } + data = new Uint8Array(data); // make a typed array view on the array buffer + } + + // if this is the port message, override the peer's port with it + var wasfirst = first; + first = false; + if (wasfirst && + data.length === 10 && + data[0] === 255 && data[1] === 255 && data[2] === 255 && data[3] === 255 && + data[4] === 'p'.charCodeAt(0) && data[5] === 'o'.charCodeAt(0) && data[6] === 'r'.charCodeAt(0) && data[7] === 't'.charCodeAt(0)) { + // update the peer's port and it's key in the peer map + var newport = ((data[8] << 8) | data[9]); + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + peer.port = newport; + SOCKFS.websocket_sock_ops.addPeer(sock, peer); + return; + } + + sock.recv_queue.push({ addr: peer.addr, port: peer.port, data: data }); + Module['websocket'].emit('message', sock.stream.fd); + }; + + if (ENVIRONMENT_IS_NODE) { + peer.socket.on('open', handleOpen); + peer.socket.on('message', function(data, isBinary) { + if (!isBinary) { + return; + } + handleMessage((new Uint8Array(data)).buffer); // copy from node Buffer -> ArrayBuffer + }); + peer.socket.on('close', function() { + Module['websocket'].emit('close', sock.stream.fd); + }); + peer.socket.on('error', function(error) { + // Although the ws library may pass errors that may be more descriptive than + // ECONNREFUSED they are not necessarily the expected error code e.g. + // ENOTFOUND on getaddrinfo seems to be node.js specific, so using ECONNREFUSED + // is still probably the most useful thing to do. + sock.error = 14; // Used in getsockopt for SOL_SOCKET/SO_ERROR test. + Module['websocket'].emit('error', [sock.stream.fd, sock.error, 'ECONNREFUSED: Connection refused']); + // don't throw + }); + } else { + peer.socket.onopen = handleOpen; + peer.socket.onclose = function() { + Module['websocket'].emit('close', sock.stream.fd); + }; + peer.socket.onmessage = function peer_socket_onmessage(event) { + handleMessage(event.data); + }; + peer.socket.onerror = function(error) { + // The WebSocket spec only allows a 'simple event' to be thrown on error, + // so we only really know as much as ECONNREFUSED. + sock.error = 14; // Used in getsockopt for SOL_SOCKET/SO_ERROR test. + Module['websocket'].emit('error', [sock.stream.fd, sock.error, 'ECONNREFUSED: Connection refused']); + }; + } + }, + poll(sock) { + if (sock.type === 1 && sock.server) { + // listen sockets should only say they're available for reading + // if there are pending clients. + return sock.pending.length ? (64 | 1) : 0; + } + + var mask = 0; + var dest = sock.type === 1 ? // we only care about the socket state for connection-based sockets + SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport) : + null; + + if (sock.recv_queue.length || + !dest || // connection-less sockets are always ready to read + (dest && dest.socket.readyState === dest.socket.CLOSING) || + (dest && dest.socket.readyState === dest.socket.CLOSED)) { // let recv return 0 once closed + mask |= (64 | 1); + } + + if (!dest || // connection-less sockets are always ready to write + (dest && dest.socket.readyState === dest.socket.OPEN)) { + mask |= 4; + } + + if ((dest && dest.socket.readyState === dest.socket.CLOSING) || + (dest && dest.socket.readyState === dest.socket.CLOSED)) { + mask |= 16; + } + + return mask; + }, + ioctl(sock, request, arg) { + switch (request) { + case 21531: + var bytes = 0; + if (sock.recv_queue.length) { + bytes = sock.recv_queue[0].data.length; + } + HEAP32[((arg)>>2)] = bytes; + return 0; + default: + return 28; + } + }, + close(sock) { + // if we've spawned a listen server, close it + if (sock.server) { + try { + sock.server.close(); + } catch (e) { + } + sock.server = null; + } + // close any peer connections + var peers = Object.keys(sock.peers); + for (var i = 0; i < peers.length; i++) { + var peer = sock.peers[peers[i]]; + try { + peer.socket.close(); + } catch (e) { + } + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + } + return 0; + }, + bind(sock, addr, port) { + if (typeof sock.saddr != 'undefined' || typeof sock.sport != 'undefined') { + throw new FS.ErrnoError(28); // already bound + } + sock.saddr = addr; + sock.sport = port; + // in order to emulate dgram sockets, we need to launch a listen server when + // binding on a connection-less socket + // note: this is only required on the server side + if (sock.type === 2) { + // close the existing server if it exists + if (sock.server) { + sock.server.close(); + sock.server = null; + } + // swallow error operation not supported error that occurs when binding in the + // browser where this isn't supported + try { + sock.sock_ops.listen(sock, 0); + } catch (e) { + if (!(e.name === 'ErrnoError')) throw e; + if (e.errno !== 138) throw e; + } + } + }, + connect(sock, addr, port) { + if (sock.server) { + throw new FS.ErrnoError(138); + } + + // TODO autobind + // if (!sock.addr && sock.type == 2) { + // } + + // early out if we're already connected / in the middle of connecting + if (typeof sock.daddr != 'undefined' && typeof sock.dport != 'undefined') { + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); + if (dest) { + if (dest.socket.readyState === dest.socket.CONNECTING) { + throw new FS.ErrnoError(7); + } else { + throw new FS.ErrnoError(30); + } + } + } + + // add the socket to our peer list and set our + // destination address / port to match + var peer = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); + sock.daddr = peer.addr; + sock.dport = peer.port; + + // always "fail" in non-blocking mode + throw new FS.ErrnoError(26); + }, + listen(sock, backlog) { + if (!ENVIRONMENT_IS_NODE) { + throw new FS.ErrnoError(138); + } + }, + accept(listensock) { + if (!listensock.server || !listensock.pending.length) { + throw new FS.ErrnoError(28); + } + var newsock = listensock.pending.shift(); + newsock.stream.flags = listensock.stream.flags; + return newsock; + }, + getname(sock, peer) { + var addr, port; + if (peer) { + if (sock.daddr === undefined || sock.dport === undefined) { + throw new FS.ErrnoError(53); + } + addr = sock.daddr; + port = sock.dport; + } else { + // TODO saddr and sport will be set for bind()'d UDP sockets, but what + // should we be returning for TCP sockets that've been connect()'d? + addr = sock.saddr || 0; + port = sock.sport || 0; + } + return { addr, port }; + }, + sendmsg(sock, buffer, offset, length, addr, port) { + if (sock.type === 2) { + // connection-less sockets will honor the message address, + // and otherwise fall back to the bound destination address + if (addr === undefined || port === undefined) { + addr = sock.daddr; + port = sock.dport; + } + // if there was no address to fall back to, error out + if (addr === undefined || port === undefined) { + throw new FS.ErrnoError(17); + } + } else { + // connection-based sockets will only use the bound + addr = sock.daddr; + port = sock.dport; + } + + // find the peer for the destination address + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, addr, port); + + // early out if not connected with a connection-based socket + if (sock.type === 1) { + if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + throw new FS.ErrnoError(53); + } else if (dest.socket.readyState === dest.socket.CONNECTING) { + throw new FS.ErrnoError(6); + } + } + + // create a copy of the incoming data to send, as the WebSocket API + // doesn't work entirely with an ArrayBufferView, it'll just send + // the entire underlying buffer + if (ArrayBuffer.isView(buffer)) { + offset += buffer.byteOffset; + buffer = buffer.buffer; + } + + var data; + data = buffer.slice(offset, offset + length); + + // if we're emulating a connection-less dgram socket and don't have + // a cached connection, queue the buffer to send upon connect and + // lie, saying the data was sent now. + if (sock.type === 2) { + if (!dest || dest.socket.readyState !== dest.socket.OPEN) { + // if we're not connected, open a new connection + if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port); + } + dest.dgram_send_queue.push(data); + return length; + } + } + + try { + // send the actual data + dest.socket.send(data); + return length; + } catch (e) { + throw new FS.ErrnoError(28); + } + }, + recvmsg(sock, length, flags) { + // http://pubs.opengroup.org/onlinepubs/7908799/xns/recvmsg.html + if (sock.type === 1 && sock.server) { + // tcp servers should not be recv()'ing on the listen socket + throw new FS.ErrnoError(53); + } + + var queued = sock.recv_queue.shift(); + if (!queued) { + if (sock.type === 1) { + var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport); + + if (!dest) { + // if we have a destination address but are not connected, error out + throw new FS.ErrnoError(53); + } + if (dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) { + // return null if the socket has closed + return null; + } + // else, our socket is in a valid state but truly has nothing available + throw new FS.ErrnoError(6); + } + throw new FS.ErrnoError(6); + } + + // queued.data will be an ArrayBuffer if it's unadulterated, but if it's + // requeued TCP data it'll be an ArrayBufferView + var queuedLength = queued.data.byteLength || queued.data.length; + var queuedOffset = queued.data.byteOffset || 0; + var queuedBuffer = queued.data.buffer || queued.data; + var bytesRead = Math.min(length, queuedLength); + var res = { + buffer: new Uint8Array(queuedBuffer, queuedOffset, bytesRead), + addr: queued.addr, + port: queued.port + }; + + // push back any unread data for TCP connections + if (flags&2) {bytesRead = 0;} if (sock.type === 1 && bytesRead < queuedLength) { + var bytesRemaining = queuedLength - bytesRead; + queued.data = new Uint8Array(queuedBuffer, queuedOffset + bytesRead, bytesRemaining); + sock.recv_queue.unshift(queued); + } + + return res; + }, + }, + }; + + function getSocketFromFD(fd) { + var socket = SOCKFS.getSocket(fd); + if (!socket) throw new FS.ErrnoError(8); + return socket; + } + + var setErrNo = (value) => { + HEAP32[((___errno_location())>>2)] = value; + return value; + }; + var Sockets = { + BUFFER_SIZE:10240, + MAX_BUFFER_SIZE:10485760, + nextFd:1, + fds:{ + }, + nextport:1, + maxport:65535, + peer:null, + connections:{ + }, + portmap:{ + }, + localAddr:4261412874, + addrPool:[33554442,50331658,67108874,83886090,100663306,117440522,134217738,150994954,167772170,184549386,201326602,218103818,234881034], + }; + + var inetPton4 = (str) => { + var b = str.split('.'); + for (var i = 0; i < 4; i++) { + var tmp = Number(b[i]); + if (isNaN(tmp)) return null; + b[i] = tmp; + } + return (b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)) >>> 0; + }; + + + /** @suppress {checkTypes} */ + var jstoi_q = (str) => parseInt(str); + var inetPton6 = (str) => { + var words; + var w, offset, z, i; + /* http://home.deds.nl/~aeron/regex/ */ + var valid6regx = /^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i + var parts = []; + if (!valid6regx.test(str)) { + return null; + } + if (str === "::") { + return [0, 0, 0, 0, 0, 0, 0, 0]; + } + // Z placeholder to keep track of zeros when splitting the string on ":" + if (str.startsWith("::")) { + str = str.replace("::", "Z:"); // leading zeros case + } else { + str = str.replace("::", ":Z:"); + } + + if (str.indexOf(".") > 0) { + // parse IPv4 embedded stress + str = str.replace(new RegExp('[.]', 'g'), ":"); + words = str.split(":"); + words[words.length-4] = jstoi_q(words[words.length-4]) + jstoi_q(words[words.length-3])*256; + words[words.length-3] = jstoi_q(words[words.length-2]) + jstoi_q(words[words.length-1])*256; + words = words.slice(0, words.length-2); + } else { + words = str.split(":"); + } + + offset = 0; z = 0; + for (w=0; w < words.length; w++) { + if (typeof words[w] == 'string') { + if (words[w] === 'Z') { + // compressed zeros - write appropriate number of zero words + for (z = 0; z < (8 - words.length+1); z++) { + parts[w+z] = 0; + } + offset = z-1; + } else { + // parse hex to field to 16-bit value and write it in network byte-order + parts[w+offset] = _htons(parseInt(words[w],16)); + } + } else { + // parsed IPv4 words + parts[w+offset] = words[w]; + } + } + return [ + (parts[1] << 16) | parts[0], + (parts[3] << 16) | parts[2], + (parts[5] << 16) | parts[4], + (parts[7] << 16) | parts[6] + ]; + }; + + + /** @param {number=} addrlen */ + var writeSockaddr = (sa, family, addr, port, addrlen) => { + switch (family) { + case 2: + addr = inetPton4(addr); + zeroMemory(sa, 16); + if (addrlen) { + HEAP32[((addrlen)>>2)] = 16; + } + HEAP16[((sa)>>1)] = family; + HEAP32[(((sa)+(4))>>2)] = addr; + HEAP16[(((sa)+(2))>>1)] = _htons(port); + break; + case 10: + addr = inetPton6(addr); + zeroMemory(sa, 28); + if (addrlen) { + HEAP32[((addrlen)>>2)] = 28; + } + HEAP32[((sa)>>2)] = family; + HEAP32[(((sa)+(8))>>2)] = addr[0]; + HEAP32[(((sa)+(12))>>2)] = addr[1]; + HEAP32[(((sa)+(16))>>2)] = addr[2]; + HEAP32[(((sa)+(20))>>2)] = addr[3]; + HEAP16[(((sa)+(2))>>1)] = _htons(port); + break; + default: + return 5; + } + return 0; + }; + + + var DNS = { + address_map:{ + id:1, + addrs:{ + }, + names:{ + }, + }, + lookup_name:(name) => { + // If the name is already a valid ipv4 / ipv6 address, don't generate a fake one. + var res = inetPton4(name); + if (res !== null) { + return name; + } + res = inetPton6(name); + if (res !== null) { + return name; + } + + // See if this name is already mapped. + var addr; + + if (DNS.address_map.addrs[name]) { + addr = DNS.address_map.addrs[name]; + } else { + var id = DNS.address_map.id++; + assert(id < 65535, 'exceeded max address mappings of 65535'); + + addr = '172.29.' + (id & 0xff) + '.' + (id & 0xff00); + + DNS.address_map.names[addr] = name; + DNS.address_map.addrs[name] = addr; + } + + return addr; + }, + lookup_addr:(addr) => { + if (DNS.address_map.names[addr]) { + return DNS.address_map.names[addr]; + } + + return null; + }, + }; + + + + var SYSCALLS = { + DEFAULT_POLLMASK:5, + calculateAt:function(dirfd, path, allowEmpty) { + if (PATH.isAbs(path)) { + return path; + } + // relative path + var dir; + if (dirfd === -100) { + dir = FS.cwd(); + } else { + var dirstream = SYSCALLS.getStreamFromFD(dirfd); + dir = dirstream.path; + } + if (path.length == 0) { + if (!allowEmpty) { + throw new FS.ErrnoError(44);; + } + return dir; + } + return PATH.join2(dir, path); + }, + doStat:function(func, path, buf) { + try { + var stat = func(path); + } catch (e) { + if (e && e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) { + // an error occurred while trying to look up the path; we should just report ENOTDIR + return -54; + } + throw e; + } + HEAP32[((buf)>>2)] = stat.dev; + HEAP32[(((buf)+(4))>>2)] = stat.mode; + HEAPU32[(((buf)+(8))>>2)] = stat.nlink; + HEAP32[(((buf)+(12))>>2)] = stat.uid; + HEAP32[(((buf)+(16))>>2)] = stat.gid; + HEAP32[(((buf)+(20))>>2)] = stat.rdev; + (tempI64 = [stat.size>>>0,(tempDouble=stat.size,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(24))>>2)] = tempI64[0],HEAP32[(((buf)+(28))>>2)] = tempI64[1]); + HEAP32[(((buf)+(32))>>2)] = 4096; + HEAP32[(((buf)+(36))>>2)] = stat.blocks; + var atime = stat.atime.getTime(); + var mtime = stat.mtime.getTime(); + var ctime = stat.ctime.getTime(); + (tempI64 = [Math.floor(atime / 1000)>>>0,(tempDouble=Math.floor(atime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(40))>>2)] = tempI64[0],HEAP32[(((buf)+(44))>>2)] = tempI64[1]); + HEAPU32[(((buf)+(48))>>2)] = (atime % 1000) * 1000; + (tempI64 = [Math.floor(mtime / 1000)>>>0,(tempDouble=Math.floor(mtime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(56))>>2)] = tempI64[0],HEAP32[(((buf)+(60))>>2)] = tempI64[1]); + HEAPU32[(((buf)+(64))>>2)] = (mtime % 1000) * 1000; + (tempI64 = [Math.floor(ctime / 1000)>>>0,(tempDouble=Math.floor(ctime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(72))>>2)] = tempI64[0],HEAP32[(((buf)+(76))>>2)] = tempI64[1]); + HEAPU32[(((buf)+(80))>>2)] = (ctime % 1000) * 1000; + (tempI64 = [stat.ino>>>0,(tempDouble=stat.ino,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(88))>>2)] = tempI64[0],HEAP32[(((buf)+(92))>>2)] = tempI64[1]); + return 0; + }, + doMsync:function(addr, stream, len, flags, offset) { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(43); + } + if (flags & 2) { + // MAP_PRIVATE calls need not to be synced back to underlying fs + return 0; + } + var buffer = HEAPU8.slice(addr, addr + len); + FS.msync(stream, buffer, offset, len, flags); + }, + varargs:undefined, + get() { + SYSCALLS.varargs += 4; + var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)]; + return ret; + }, + getStr(ptr) { + var ret = UTF8ToString(ptr); + return ret; + }, + getStreamFromFD:function(fd) { + var stream = FS.getStreamChecked(fd); + return stream; + }, + }; + function ___syscall_accept4(fd, addr, addrlen, flags, d1, d2) { + try { + + var sock = getSocketFromFD(fd); + var newsock = sock.sock_ops.accept(sock); + if (addr) { + var errno = writeSockaddr(addr, newsock.family, DNS.lookup_name(newsock.daddr), newsock.dport, addrlen); + } + return newsock.stream.fd; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + + var inetNtop4 = (addr) => { + return (addr & 0xff) + '.' + ((addr >> 8) & 0xff) + '.' + ((addr >> 16) & 0xff) + '.' + ((addr >> 24) & 0xff) + }; + + + var inetNtop6 = (ints) => { + // ref: http://www.ietf.org/rfc/rfc2373.txt - section 2.5.4 + // Format for IPv4 compatible and mapped 128-bit IPv6 Addresses + // 128-bits are split into eight 16-bit words + // stored in network byte order (big-endian) + // | 80 bits | 16 | 32 bits | + // +-----------------------------------------------------------------+ + // | 10 bytes | 2 | 4 bytes | + // +--------------------------------------+--------------------------+ + // + 5 words | 1 | 2 words | + // +--------------------------------------+--------------------------+ + // |0000..............................0000|0000| IPv4 ADDRESS | (compatible) + // +--------------------------------------+----+---------------------+ + // |0000..............................0000|FFFF| IPv4 ADDRESS | (mapped) + // +--------------------------------------+----+---------------------+ + var str = ""; + var word = 0; + var longest = 0; + var lastzero = 0; + var zstart = 0; + var len = 0; + var i = 0; + var parts = [ + ints[0] & 0xffff, + (ints[0] >> 16), + ints[1] & 0xffff, + (ints[1] >> 16), + ints[2] & 0xffff, + (ints[2] >> 16), + ints[3] & 0xffff, + (ints[3] >> 16) + ]; + + // Handle IPv4-compatible, IPv4-mapped, loopback and any/unspecified addresses + + var hasipv4 = true; + var v4part = ""; + // check if the 10 high-order bytes are all zeros (first 5 words) + for (i = 0; i < 5; i++) { + if (parts[i] !== 0) { hasipv4 = false; break; } + } + + if (hasipv4) { + // low-order 32-bits store an IPv4 address (bytes 13 to 16) (last 2 words) + v4part = inetNtop4(parts[6] | (parts[7] << 16)); + // IPv4-mapped IPv6 address if 16-bit value (bytes 11 and 12) == 0xFFFF (6th word) + if (parts[5] === -1) { + str = "::ffff:"; + str += v4part; + return str; + } + // IPv4-compatible IPv6 address if 16-bit value (bytes 11 and 12) == 0x0000 (6th word) + if (parts[5] === 0) { + str = "::"; + //special case IPv6 addresses + if (v4part === "0.0.0.0") v4part = ""; // any/unspecified address + if (v4part === "0.0.0.1") v4part = "1";// loopback address + str += v4part; + return str; + } + } + + // Handle all other IPv6 addresses + + // first run to find the longest contiguous zero words + for (word = 0; word < 8; word++) { + if (parts[word] === 0) { + if (word - lastzero > 1) { + len = 0; + } + lastzero = word; + len++; + } + if (len > longest) { + longest = len; + zstart = word - longest + 1; + } + } + + for (word = 0; word < 8; word++) { + if (longest > 1) { + // compress contiguous zeros - to produce "::" + if (parts[word] === 0 && word >= zstart && word < (zstart + longest) ) { + if (word === zstart) { + str += ":"; + if (zstart === 0) str += ":"; //leading zeros case + } + continue; + } + } + // converts 16-bit words from big-endian to little-endian before converting to hex string + str += Number(_ntohs(parts[word] & 0xffff)).toString(16); + str += word < 7 ? ":" : ""; + } + return str; + }; + + var readSockaddr = (sa, salen) => { + // family / port offsets are common to both sockaddr_in and sockaddr_in6 + var family = HEAP16[((sa)>>1)]; + var port = _ntohs(HEAPU16[(((sa)+(2))>>1)]); + var addr; + + switch (family) { + case 2: + if (salen !== 16) { + return { errno: 28 }; + } + addr = HEAP32[(((sa)+(4))>>2)]; + addr = inetNtop4(addr); + break; + case 10: + if (salen !== 28) { + return { errno: 28 }; + } + addr = [ + HEAP32[(((sa)+(8))>>2)], + HEAP32[(((sa)+(12))>>2)], + HEAP32[(((sa)+(16))>>2)], + HEAP32[(((sa)+(20))>>2)] + ]; + addr = inetNtop6(addr); + break; + default: + return { errno: 5 }; + } + + return { family: family, addr: addr, port: port }; + }; + + + /** @param {boolean=} allowNull */ + function getSocketAddress(addrp, addrlen, allowNull) { + if (allowNull && addrp === 0) return null; + var info = readSockaddr(addrp, addrlen); + if (info.errno) throw new FS.ErrnoError(info.errno); + info.addr = DNS.lookup_addr(info.addr) || info.addr; + return info; + } + + function ___syscall_bind(fd, addr, addrlen, d1, d2, d3) { + try { + + var sock = getSocketFromFD(fd); + var info = getSocketAddress(addr, addrlen); + sock.sock_ops.bind(sock, info.addr, info.port); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_chdir(path) { + try { + + path = SYSCALLS.getStr(path); + FS.chdir(path); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_chmod(path, mode) { + try { + + path = SYSCALLS.getStr(path); + FS.chmod(path, mode); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + + function ___syscall_connect(fd, addr, addrlen, d1, d2, d3) { + try { + + var sock = getSocketFromFD(fd); + var info = getSocketAddress(addr, addrlen); + sock.sock_ops.connect(sock, info.addr, info.port); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_dup(fd) { + try { + + var old = SYSCALLS.getStreamFromFD(fd); + return FS.createStream(old).fd; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_dup3(fd, newfd, flags) { + try { + + var old = SYSCALLS.getStreamFromFD(fd); + if (old.fd === newfd) return -28; + var existing = FS.getStream(newfd); + if (existing) FS.close(existing); + return FS.createStream(old, newfd).fd; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_faccessat(dirfd, path, amode, flags) { + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + if (amode & ~7) { + // need a valid mode + return -28; + } + var lookup = FS.lookupPath(path, { follow: true }); + var node = lookup.node; + if (!node) { + return -44; + } + var perms = ''; + if (amode & 4) perms += 'r'; + if (amode & 2) perms += 'w'; + if (amode & 1) perms += 'x'; + if (perms /* otherwise, they've just passed F_OK */ && FS.nodePermissions(node, perms)) { + return -2; + } + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function convertI32PairToI53Checked(lo, hi) { + return ((hi + 0x200000) >>> 0 < 0x400001 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN; + } + function ___syscall_fallocate(fd,mode,offset_low, offset_high,len_low, len_high) { + var offset = convertI32PairToI53Checked(offset_low, offset_high);; + var len = convertI32PairToI53Checked(len_low, len_high);; + + + try { + + if (isNaN(offset)) return 61; + var stream = SYSCALLS.getStreamFromFD(fd) + FS.allocate(stream, offset, len); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + ; + } + + function ___syscall_fchmod(fd, mode) { + try { + + FS.fchmod(fd, mode); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_fchown32(fd, owner, group) { + try { + + FS.fchown(fd, owner, group); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_fchownat(dirfd, path, owner, group, flags) { + try { + + path = SYSCALLS.getStr(path); + var nofollow = flags & 256; + flags = flags & (~256); + path = SYSCALLS.calculateAt(dirfd, path); + (nofollow ? FS.lchown : FS.chown)(path, owner, group); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_fcntl64(fd, cmd, varargs) { + SYSCALLS.varargs = varargs; + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + switch (cmd) { + case 0: { + var arg = SYSCALLS.get(); + if (arg < 0) { + return -28; + } + var newStream; + newStream = FS.createStream(stream, arg); + return newStream.fd; + } + case 1: + case 2: + return 0; // FD_CLOEXEC makes no sense for a single process. + case 3: + return stream.flags; + case 4: { + var arg = SYSCALLS.get(); + stream.flags |= arg; + return 0; + } + case 5: + /* case 5: Currently in musl F_GETLK64 has same value as F_GETLK, so omitted to avoid duplicate case blocks. If that changes, uncomment this */ { + + var arg = SYSCALLS.get(); + var offset = 0; + // We're always unlocked. + HEAP16[(((arg)+(offset))>>1)] = 2; + return 0; + } + case 6: + case 7: + /* case 6: Currently in musl F_SETLK64 has same value as F_SETLK, so omitted to avoid duplicate case blocks. If that changes, uncomment this */ + /* case 7: Currently in musl F_SETLKW64 has same value as F_SETLKW, so omitted to avoid duplicate case blocks. If that changes, uncomment this */ + + + return 0; // Pretend that the locking is successful. + case 16: + case 8: + return -28; // These are for sockets. We don't have them fully implemented yet. + case 9: + // musl trusts getown return values, due to a bug where they must be, as they overlap with errors. just return -1 here, so fcntl() returns that, and we set errno ourselves. + setErrNo(28); + return -1; + default: { + return -28; + } + } + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_fdatasync(fd) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + return 0; // we can't do anything synchronously; the in-memory FS is already synced to + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_fstat64(fd, buf) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + return SYSCALLS.doStat(FS.stat, stream.path, buf); + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_ftruncate64(fd,length_low, length_high) { + var length = convertI32PairToI53Checked(length_low, length_high);; + + + try { + + if (isNaN(length)) return 61; + FS.ftruncate(fd, length); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + ; + } + + + var stringToUTF8 = (str, outPtr, maxBytesToWrite) => { + return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite); + }; + Module['stringToUTF8'] = stringToUTF8; + + function ___syscall_getcwd(buf, size) { + try { + + if (size === 0) return -28; + var cwd = FS.cwd(); + var cwdLengthInBytes = lengthBytesUTF8(cwd) + 1; + if (size < cwdLengthInBytes) return -68; + stringToUTF8(cwd, buf, size); + return cwdLengthInBytes; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_getdents64(fd, dirp, count) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd) + if (!stream.getdents) { + stream.getdents = FS.readdir(stream.path); + } + + var struct_size = 280; + var pos = 0; + var off = FS.llseek(stream, 0, 1); + + var idx = Math.floor(off / struct_size); + + while (idx < stream.getdents.length && pos + struct_size <= count) { + var id; + var type; + var name = stream.getdents[idx]; + if (name === '.') { + id = stream.node.id; + type = 4; // DT_DIR + } + else if (name === '..') { + var lookup = FS.lookupPath(stream.path, { parent: true }); + id = lookup.node.id; + type = 4; // DT_DIR + } + else { + var child = FS.lookupNode(stream.node, name); + id = child.id; + type = FS.isChrdev(child.mode) ? 2 : // DT_CHR, character device. + FS.isDir(child.mode) ? 4 : // DT_DIR, directory. + FS.isLink(child.mode) ? 10 : // DT_LNK, symbolic link. + 8; // DT_REG, regular file. + } + (tempI64 = [id>>>0,(tempDouble=id,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[((dirp + pos)>>2)] = tempI64[0],HEAP32[(((dirp + pos)+(4))>>2)] = tempI64[1]); + (tempI64 = [(idx + 1) * struct_size>>>0,(tempDouble=(idx + 1) * struct_size,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((dirp + pos)+(8))>>2)] = tempI64[0],HEAP32[(((dirp + pos)+(12))>>2)] = tempI64[1]); + HEAP16[(((dirp + pos)+(16))>>1)] = 280; + HEAP8[(((dirp + pos)+(18))>>0)] = type; + stringToUTF8(name, dirp + pos + 19, 256); + pos += struct_size; + idx += 1; + } + FS.llseek(stream, idx * struct_size, 0); + return pos; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + + + function ___syscall_getpeername(fd, addr, addrlen, d1, d2, d3) { + try { + + var sock = getSocketFromFD(fd); + if (!sock.daddr) { + return -53; // The socket is not connected. + } + var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(sock.daddr), sock.dport, addrlen); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + + + function ___syscall_getsockname(fd, addr, addrlen, d1, d2, d3) { + try { + + var sock = getSocketFromFD(fd); + // TODO: sock.saddr should never be undefined, see TODO in websocket_sock_ops.getname + var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(sock.saddr || '0.0.0.0'), sock.sport, addrlen); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_getsockopt(fd, level, optname, optval, optlen, d1) { + try { + + var sock = getSocketFromFD(fd); + // Minimal getsockopt aimed at resolving https://github.com/emscripten-core/emscripten/issues/2211 + // so only supports SOL_SOCKET with SO_ERROR. + if (level === 1) { + if (optname === 4) { + HEAP32[((optval)>>2)] = sock.error; + HEAP32[((optlen)>>2)] = 4; + sock.error = null; // Clear the error (The SO_ERROR option obtains and then clears this field). + return 0; + } + } + return -50; // The option is unknown at the level indicated. + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_ioctl(fd, op, varargs) { + SYSCALLS.varargs = varargs; + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + switch (op) { + case 21509: { + if (!stream.tty) return -59; + return 0; + } + case 21505: { + if (!stream.tty) return -59; + if (stream.tty.ops.ioctl_tcgets) { + var termios = stream.tty.ops.ioctl_tcgets(stream); + var argp = SYSCALLS.get(); + HEAP32[((argp)>>2)] = termios.c_iflag || 0; + HEAP32[(((argp)+(4))>>2)] = termios.c_oflag || 0; + HEAP32[(((argp)+(8))>>2)] = termios.c_cflag || 0; + HEAP32[(((argp)+(12))>>2)] = termios.c_lflag || 0; + for (var i = 0; i < 32; i++) { + HEAP8[(((argp + i)+(17))>>0)] = termios.c_cc[i] || 0; + } + return 0; + } + return 0; + } + case 21510: + case 21511: + case 21512: { + if (!stream.tty) return -59; + return 0; // no-op, not actually adjusting terminal settings + } + case 21506: + case 21507: + case 21508: { + if (!stream.tty) return -59; + if (stream.tty.ops.ioctl_tcsets) { + var argp = SYSCALLS.get(); + var c_iflag = HEAP32[((argp)>>2)]; + var c_oflag = HEAP32[(((argp)+(4))>>2)]; + var c_cflag = HEAP32[(((argp)+(8))>>2)]; + var c_lflag = HEAP32[(((argp)+(12))>>2)]; + var c_cc = [] + for (var i = 0; i < 32; i++) { + c_cc.push(HEAP8[(((argp + i)+(17))>>0)]); + } + return stream.tty.ops.ioctl_tcsets(stream.tty, op, { c_iflag, c_oflag, c_cflag, c_lflag, c_cc }); + } + return 0; // no-op, not actually adjusting terminal settings + } + case 21519: { + if (!stream.tty) return -59; + var argp = SYSCALLS.get(); + HEAP32[((argp)>>2)] = 0; + return 0; + } + case 21520: { + if (!stream.tty) return -59; + return -28; // not supported + } + case 21531: { + var argp = SYSCALLS.get(); + return FS.ioctl(stream, op, argp); + } + case 21523: { + // TODO: in theory we should write to the winsize struct that gets + // passed in, but for now musl doesn't read anything on it + if (!stream.tty) return -59; + if (stream.tty.ops.ioctl_tiocgwinsz) { + var winsize = stream.tty.ops.ioctl_tiocgwinsz(stream.tty); + var argp = SYSCALLS.get(); + HEAP16[((argp)>>1)] = winsize[0]; + HEAP16[(((argp)+(2))>>1)] = winsize[1]; + } + return 0; + } + case 21524: { + // TODO: technically, this ioctl call should change the window size. + // but, since emscripten doesn't have any concept of a terminal window + // yet, we'll just silently throw it away as we do TIOCGWINSZ + if (!stream.tty) return -59; + return 0; + } + case 21515: { + if (!stream.tty) return -59; + return 0; + } + default: return -28; // not supported + } + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_listen(fd, backlog) { + try { + + var sock = getSocketFromFD(fd); + sock.sock_ops.listen(sock, backlog); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_lstat64(path, buf) { + try { + + path = SYSCALLS.getStr(path); + return SYSCALLS.doStat(FS.lstat, path, buf); + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_mkdirat(dirfd, path, mode) { + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + // remove a trailing slash, if one - /a/b/ has basename of '', but + // we want to create b in the context of this function + path = PATH.normalize(path); + if (path[path.length-1] === '/') path = path.substr(0, path.length-1); + FS.mkdir(path, mode, 0); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_newfstatat(dirfd, path, buf, flags) { + try { + + path = SYSCALLS.getStr(path); + var nofollow = flags & 256; + var allowEmpty = flags & 4096; + flags = flags & (~6400); + path = SYSCALLS.calculateAt(dirfd, path, allowEmpty); + return SYSCALLS.doStat(nofollow ? FS.lstat : FS.stat, path, buf); + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_openat(dirfd, path, flags, varargs) { + SYSCALLS.varargs = varargs; + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + var mode = varargs ? SYSCALLS.get() : 0; + return FS.open(path, flags, mode).fd; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + var PIPEFS = { + BUCKET_BUFFER_SIZE:8192, + mount(mount) { + // Do not pollute the real root directory or its child nodes with pipes + // Looks like it is OK to create another pseudo-root node not linked to the FS.root hierarchy this way + return FS.createNode(null, '/', 16384 | 511 /* 0777 */, 0); + }, + createPipe() { + var pipe = { + buckets: [], + // refcnt 2 because pipe has a read end and a write end. We need to be + // able to read from the read end after write end is closed. + refcnt : 2, + }; + + pipe.buckets.push({ + buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE), + offset: 0, + roffset: 0 + }); + + var rName = PIPEFS.nextname(); + var wName = PIPEFS.nextname(); + var rNode = FS.createNode(PIPEFS.root, rName, 4096, 0); + var wNode = FS.createNode(PIPEFS.root, wName, 4096, 0); + + rNode.pipe = pipe; + wNode.pipe = pipe; + + var readableStream = FS.createStream({ + path: rName, + node: rNode, + flags: 0, + seekable: false, + stream_ops: PIPEFS.stream_ops + }); + rNode.stream = readableStream; + + var writableStream = FS.createStream({ + path: wName, + node: wNode, + flags: 1, + seekable: false, + stream_ops: PIPEFS.stream_ops + }); + wNode.stream = writableStream; + + return { + readable_fd: readableStream.fd, + writable_fd: writableStream.fd + }; + }, + stream_ops:{ + poll(stream) { + var pipe = stream.node.pipe; + + if ((stream.flags & 2097155) === 1) { + return (256 | 4); + } + if (pipe.buckets.length > 0) { + for (var i = 0; i < pipe.buckets.length; i++) { + var bucket = pipe.buckets[i]; + if (bucket.offset - bucket.roffset > 0) { + return (64 | 1); + } + } + } + + return 0; + }, + ioctl(stream, request, varargs) { + return 28; + }, + fsync(stream) { + return 28; + }, + read(stream, buffer, offset, length, position /* ignored */) { + var pipe = stream.node.pipe; + var currentLength = 0; + + for (var i = 0; i < pipe.buckets.length; i++) { + var bucket = pipe.buckets[i]; + currentLength += bucket.offset - bucket.roffset; + } + + assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer)); + var data = buffer.subarray(offset, offset + length); + + if (length <= 0) { + return 0; + } + if (currentLength == 0) { + // Behave as if the read end is always non-blocking + throw new FS.ErrnoError(6); + } + var toRead = Math.min(currentLength, length); + + var totalRead = toRead; + var toRemove = 0; + + for (var i = 0; i < pipe.buckets.length; i++) { + var currBucket = pipe.buckets[i]; + var bucketSize = currBucket.offset - currBucket.roffset; + + if (toRead <= bucketSize) { + var tmpSlice = currBucket.buffer.subarray(currBucket.roffset, currBucket.offset); + if (toRead < bucketSize) { + tmpSlice = tmpSlice.subarray(0, toRead); + currBucket.roffset += toRead; + } else { + toRemove++; + } + data.set(tmpSlice); + break; + } else { + var tmpSlice = currBucket.buffer.subarray(currBucket.roffset, currBucket.offset); + data.set(tmpSlice); + data = data.subarray(tmpSlice.byteLength); + toRead -= tmpSlice.byteLength; + toRemove++; + } + } + + if (toRemove && toRemove == pipe.buckets.length) { + // Do not generate excessive garbage in use cases such as + // write several bytes, read everything, write several bytes, read everything... + toRemove--; + pipe.buckets[toRemove].offset = 0; + pipe.buckets[toRemove].roffset = 0; + } + + pipe.buckets.splice(0, toRemove); + + return totalRead; + }, + write(stream, buffer, offset, length, position /* ignored */) { + var pipe = stream.node.pipe; + + assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer)); + var data = buffer.subarray(offset, offset + length); + + var dataLen = data.byteLength; + if (dataLen <= 0) { + return 0; + } + + var currBucket = null; + + if (pipe.buckets.length == 0) { + currBucket = { + buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE), + offset: 0, + roffset: 0 + }; + pipe.buckets.push(currBucket); + } else { + currBucket = pipe.buckets[pipe.buckets.length - 1]; + } + + assert(currBucket.offset <= PIPEFS.BUCKET_BUFFER_SIZE); + + var freeBytesInCurrBuffer = PIPEFS.BUCKET_BUFFER_SIZE - currBucket.offset; + if (freeBytesInCurrBuffer >= dataLen) { + currBucket.buffer.set(data, currBucket.offset); + currBucket.offset += dataLen; + return dataLen; + } else if (freeBytesInCurrBuffer > 0) { + currBucket.buffer.set(data.subarray(0, freeBytesInCurrBuffer), currBucket.offset); + currBucket.offset += freeBytesInCurrBuffer; + data = data.subarray(freeBytesInCurrBuffer, data.byteLength); + } + + var numBuckets = (data.byteLength / PIPEFS.BUCKET_BUFFER_SIZE) | 0; + var remElements = data.byteLength % PIPEFS.BUCKET_BUFFER_SIZE; + + for (var i = 0; i < numBuckets; i++) { + var newBucket = { + buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE), + offset: PIPEFS.BUCKET_BUFFER_SIZE, + roffset: 0 + }; + pipe.buckets.push(newBucket); + newBucket.buffer.set(data.subarray(0, PIPEFS.BUCKET_BUFFER_SIZE)); + data = data.subarray(PIPEFS.BUCKET_BUFFER_SIZE, data.byteLength); + } + + if (remElements > 0) { + var newBucket = { + buffer: new Uint8Array(PIPEFS.BUCKET_BUFFER_SIZE), + offset: data.byteLength, + roffset: 0 + }; + pipe.buckets.push(newBucket); + newBucket.buffer.set(data); + } + + return dataLen; + }, + close(stream) { + var pipe = stream.node.pipe; + pipe.refcnt--; + if (pipe.refcnt === 0) { + pipe.buckets = null; + } + }, + }, + nextname() { + if (!PIPEFS.nextname.current) { + PIPEFS.nextname.current = 0; + } + return 'pipe[' + (PIPEFS.nextname.current++) + ']'; + }, + }; + + function ___syscall_pipe(fdPtr) { + try { + + if (fdPtr == 0) { + throw new FS.ErrnoError(21); + } + + var res = PIPEFS.createPipe(); + + HEAP32[((fdPtr)>>2)] = res.readable_fd; + HEAP32[(((fdPtr)+(4))>>2)] = res.writable_fd; + + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_poll(fds, nfds, timeout) { + try { + + var nonzero = 0; + for (var i = 0; i < nfds; i++) { + var pollfd = fds + 8 * i; + var fd = HEAP32[((pollfd)>>2)]; + var events = HEAP16[(((pollfd)+(4))>>1)]; + var mask = 32; + var stream = FS.getStream(fd); + if (stream) { + mask = SYSCALLS.DEFAULT_POLLMASK; + if (stream.stream_ops?.poll) { + mask = stream.stream_ops.poll(stream, -1); + } + } + mask &= events | 8 | 16; + if (mask) nonzero++; + HEAP16[(((pollfd)+(6))>>1)] = mask; + } + return nonzero; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + + function ___syscall_readlinkat(dirfd, path, buf, bufsize) { + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + if (bufsize <= 0) return -28; + var ret = FS.readlink(path); + + var len = Math.min(bufsize, lengthBytesUTF8(ret)); + var endChar = HEAP8[buf+len]; + stringToUTF8(ret, buf, bufsize+1); + // readlink is one of the rare functions that write out a C string, but does never append a null to the output buffer(!) + // stringToUTF8() always appends a null byte, so restore the character under the null byte after the write. + HEAP8[buf+len] = endChar; + return len; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + + + function ___syscall_recvfrom(fd, buf, len, flags, addr, addrlen) { + try { + + var sock = getSocketFromFD(fd); + var msg = sock.sock_ops.recvmsg(sock, len, typeof flags !== "undefined" ? flags : 0); + if (!msg) return 0; // socket is closed + if (addr) { + var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(msg.addr), msg.port, addrlen); + } + HEAPU8.set(msg.buffer, buf); + return msg.buffer.byteLength; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) { + try { + + oldpath = SYSCALLS.getStr(oldpath); + newpath = SYSCALLS.getStr(newpath); + oldpath = SYSCALLS.calculateAt(olddirfd, oldpath); + newpath = SYSCALLS.calculateAt(newdirfd, newpath); + FS.rename(oldpath, newpath); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_rmdir(path) { + try { + + path = SYSCALLS.getStr(path); + FS.rmdir(path); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + + function ___syscall_sendto(fd, message, length, flags, addr, addr_len) { + try { + + var sock = getSocketFromFD(fd); + var dest = getSocketAddress(addr, addr_len, true); + if (!dest) { + // send, no address provided + return FS.write(sock.stream, HEAP8,message, length); + } + // sendto an address + return sock.sock_ops.sendmsg(sock, HEAP8,message, length, dest.addr, dest.port); + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + + function ___syscall_socket(domain, type, protocol) { + try { + + var sock = SOCKFS.createSocket(domain, type, protocol); + return sock.stream.fd; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_stat64(path, buf) { + try { + + path = SYSCALLS.getStr(path); + return SYSCALLS.doStat(FS.stat, path, buf); + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_statfs64(path, size, buf) { + try { + + path = SYSCALLS.getStr(path); + // NOTE: None of the constants here are true. We're just returning safe and + // sane values. + HEAP32[(((buf)+(4))>>2)] = 4096; + HEAP32[(((buf)+(40))>>2)] = 4096; + HEAP32[(((buf)+(8))>>2)] = 1000000; + HEAP32[(((buf)+(12))>>2)] = 500000; + HEAP32[(((buf)+(16))>>2)] = 500000; + HEAP32[(((buf)+(20))>>2)] = FS.nextInode; + HEAP32[(((buf)+(24))>>2)] = 1000000; + HEAP32[(((buf)+(28))>>2)] = 42; + HEAP32[(((buf)+(44))>>2)] = 2; // ST_NOSUID + HEAP32[(((buf)+(36))>>2)] = 255; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_symlink(target, linkpath) { + try { + + target = SYSCALLS.getStr(target); + linkpath = SYSCALLS.getStr(linkpath); + FS.symlink(target, linkpath); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function ___syscall_unlinkat(dirfd, path, flags) { + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path); + if (flags === 0) { + FS.unlink(path); + } else if (flags === 512) { + FS.rmdir(path); + } else { + abort('Invalid flags passed to unlinkat'); + } + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + function readI53FromI64(ptr) { + return HEAPU32[ptr>>2] + HEAP32[ptr+4>>2] * 4294967296; + } + + function ___syscall_utimensat(dirfd, path, times, flags) { + try { + + path = SYSCALLS.getStr(path); + path = SYSCALLS.calculateAt(dirfd, path, true); + if (!times) { + var atime = Date.now(); + var mtime = atime; + } else { + var seconds = readI53FromI64(times); + var nanoseconds = HEAP32[(((times)+(8))>>2)]; + atime = (seconds*1000) + (nanoseconds/(1000*1000)); + times += 16; + seconds = readI53FromI64(times); + nanoseconds = HEAP32[(((times)+(8))>>2)]; + mtime = (seconds*1000) + (nanoseconds/(1000*1000)); + } + FS.utime(path, atime, mtime); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + } + + var nowIsMonotonic = true;; + var __emscripten_get_now_is_monotonic = () => nowIsMonotonic; + + var __emscripten_throw_longjmp = () => { + throw Infinity; + }; + + function __gmtime_js(time_low, time_high,tmPtr) { + var time = convertI32PairToI53Checked(time_low, time_high);; + + + var date = new Date(time * 1000); + HEAP32[((tmPtr)>>2)] = date.getUTCSeconds(); + HEAP32[(((tmPtr)+(4))>>2)] = date.getUTCMinutes(); + HEAP32[(((tmPtr)+(8))>>2)] = date.getUTCHours(); + HEAP32[(((tmPtr)+(12))>>2)] = date.getUTCDate(); + HEAP32[(((tmPtr)+(16))>>2)] = date.getUTCMonth(); + HEAP32[(((tmPtr)+(20))>>2)] = date.getUTCFullYear()-1900; + HEAP32[(((tmPtr)+(24))>>2)] = date.getUTCDay(); + var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0); + var yday = ((date.getTime() - start) / (1000 * 60 * 60 * 24))|0; + HEAP32[(((tmPtr)+(28))>>2)] = yday; + ; + } + + var isLeapYear = (year) => { + return year%4 === 0 && (year%100 !== 0 || year%400 === 0); + }; + + var MONTH_DAYS_LEAP_CUMULATIVE = [0,31,60,91,121,152,182,213,244,274,305,335]; + + var MONTH_DAYS_REGULAR_CUMULATIVE = [0,31,59,90,120,151,181,212,243,273,304,334]; + var ydayFromDate = (date) => { + var leap = isLeapYear(date.getFullYear()); + var monthDaysCumulative = (leap ? MONTH_DAYS_LEAP_CUMULATIVE : MONTH_DAYS_REGULAR_CUMULATIVE); + var yday = monthDaysCumulative[date.getMonth()] + date.getDate() - 1; // -1 since it's days since Jan 1 + + return yday; + }; + + function __localtime_js(time_low, time_high,tmPtr) { + var time = convertI32PairToI53Checked(time_low, time_high);; + + + var date = new Date(time*1000); + HEAP32[((tmPtr)>>2)] = date.getSeconds(); + HEAP32[(((tmPtr)+(4))>>2)] = date.getMinutes(); + HEAP32[(((tmPtr)+(8))>>2)] = date.getHours(); + HEAP32[(((tmPtr)+(12))>>2)] = date.getDate(); + HEAP32[(((tmPtr)+(16))>>2)] = date.getMonth(); + HEAP32[(((tmPtr)+(20))>>2)] = date.getFullYear()-1900; + HEAP32[(((tmPtr)+(24))>>2)] = date.getDay(); + + var yday = ydayFromDate(date)|0; + HEAP32[(((tmPtr)+(28))>>2)] = yday; + HEAP32[(((tmPtr)+(36))>>2)] = -(date.getTimezoneOffset() * 60); + + // Attention: DST is in December in South, and some regions don't have DST at all. + var start = new Date(date.getFullYear(), 0, 1); + var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset(); + var winterOffset = start.getTimezoneOffset(); + var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset))|0; + HEAP32[(((tmPtr)+(32))>>2)] = dst; + ; + } + + + + var __mktime_js = function(tmPtr) { + + var ret = (() => { + var date = new Date(HEAP32[(((tmPtr)+(20))>>2)] + 1900, + HEAP32[(((tmPtr)+(16))>>2)], + HEAP32[(((tmPtr)+(12))>>2)], + HEAP32[(((tmPtr)+(8))>>2)], + HEAP32[(((tmPtr)+(4))>>2)], + HEAP32[((tmPtr)>>2)], + 0); + + // There's an ambiguous hour when the time goes back; the tm_isdst field is + // used to disambiguate it. Date() basically guesses, so we fix it up if it + // guessed wrong, or fill in tm_isdst with the guess if it's -1. + var dst = HEAP32[(((tmPtr)+(32))>>2)]; + var guessedOffset = date.getTimezoneOffset(); + var start = new Date(date.getFullYear(), 0, 1); + var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset(); + var winterOffset = start.getTimezoneOffset(); + var dstOffset = Math.min(winterOffset, summerOffset); // DST is in December in South + if (dst < 0) { + // Attention: some regions don't have DST at all. + HEAP32[(((tmPtr)+(32))>>2)] = Number(summerOffset != winterOffset && dstOffset == guessedOffset); + } else if ((dst > 0) != (dstOffset == guessedOffset)) { + var nonDstOffset = Math.max(winterOffset, summerOffset); + var trueOffset = dst > 0 ? dstOffset : nonDstOffset; + // Don't try setMinutes(date.getMinutes() + ...) -- it's messed up. + date.setTime(date.getTime() + (trueOffset - guessedOffset)*60000); + } + + HEAP32[(((tmPtr)+(24))>>2)] = date.getDay(); + var yday = ydayFromDate(date)|0; + HEAP32[(((tmPtr)+(28))>>2)] = yday; + // To match expected behavior, update fields from date + HEAP32[((tmPtr)>>2)] = date.getSeconds(); + HEAP32[(((tmPtr)+(4))>>2)] = date.getMinutes(); + HEAP32[(((tmPtr)+(8))>>2)] = date.getHours(); + HEAP32[(((tmPtr)+(12))>>2)] = date.getDate(); + HEAP32[(((tmPtr)+(16))>>2)] = date.getMonth(); + HEAP32[(((tmPtr)+(20))>>2)] = date.getYear(); + + return date.getTime() / 1000; + })(); + return (setTempRet0((tempDouble=ret,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)), ret>>>0); + }; + + + + + + + function __mmap_js(len,prot,flags,fd,offset_low, offset_high,allocated,addr) { + var offset = convertI32PairToI53Checked(offset_low, offset_high);; + + + try { + + if (isNaN(offset)) return 61; + var stream = SYSCALLS.getStreamFromFD(fd); + var res = FS.mmap(stream, len, offset, prot, flags); + var ptr = res.ptr; + HEAP32[((allocated)>>2)] = res.allocated; + HEAPU32[((addr)>>2)] = ptr; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + ; + } + + + + + function __munmap_js(addr,len,prot,flags,fd,offset_low, offset_high) { + var offset = convertI32PairToI53Checked(offset_low, offset_high);; + + + try { + + if (isNaN(offset)) return 61; + var stream = SYSCALLS.getStreamFromFD(fd); + if (prot & 2) { + SYSCALLS.doMsync(addr, stream, len, flags, offset); + } + FS.munmap(stream); + // implicitly return 0 + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return -e.errno; + } + ; + } + + var timers = { + }; + + var handleException = (e) => { + // Certain exception types we do not treat as errors since they are used for + // internal control flow. + // 1. ExitStatus, which is thrown by exit() + // 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others + // that wish to return to JS event loop. + if (e instanceof ExitStatus || e == 'unwind') { + return EXITSTATUS; + } + quit_(1, e); + }; + + + var _proc_exit = (code) => { + EXITSTATUS = code; + if (!keepRuntimeAlive()) { + if (Module['onExit']) Module['onExit'](code); + ABORT = true; + } + quit_(code, new ExitStatus(code)); + }; + /** @suppress {duplicate } */ + /** @param {boolean|number=} implicit */ + var exitJS = (status, implicit) => { + EXITSTATUS = status; + + if (!keepRuntimeAlive()) { + exitRuntime(); + } + + _proc_exit(status); + }; + var _exit = exitJS; + Module['_exit'] = _exit; + + var maybeExit = () => { + if (runtimeExited) { + return; + } + if (!keepRuntimeAlive()) { + try { + _exit(EXITSTATUS); + } catch (e) { + handleException(e); + } + } + }; + var callUserCallback = (func) => { + if (runtimeExited || ABORT) { + return; + } + try { + func(); + maybeExit(); + } catch (e) { + handleException(e); + } + }; + + + var _emscripten_get_now; + // Modern environment where performance.now() is supported: + // N.B. a shorter form "_emscripten_get_now = performance.now;" is + // unfortunately not allowed even in current browsers (e.g. FF Nightly 75). + _emscripten_get_now = () => performance.now(); + ; + var __setitimer_js = (which, timeout_ms) => { + // First, clear any existing timer. + if (timers[which]) { + clearTimeout(timers[which].id); + delete timers[which]; + } + + // A timeout of zero simply cancels the current timeout so we have nothing + // more to do. + if (!timeout_ms) return 0; + + var id = setTimeout(() => { + delete timers[which]; + callUserCallback(() => __emscripten_timeout(which, _emscripten_get_now())); + }, timeout_ms); + timers[which] = { id, timeout_ms }; + return 0; + }; + + + + var stringToNewUTF8 = (str) => { + var size = lengthBytesUTF8(str) + 1; + var ret = _malloc(size); + if (ret) stringToUTF8(str, ret, size); + return ret; + }; + var __tzset_js = (timezone, daylight, tzname) => { + // TODO: Use (malleable) environment variables instead of system settings. + var currentYear = new Date().getFullYear(); + var winter = new Date(currentYear, 0, 1); + var summer = new Date(currentYear, 6, 1); + var winterOffset = winter.getTimezoneOffset(); + var summerOffset = summer.getTimezoneOffset(); + + // Local standard timezone offset. Local standard time is not adjusted for daylight savings. + // This code uses the fact that getTimezoneOffset returns a greater value during Standard Time versus Daylight Saving Time (DST). + // Thus it determines the expected output during Standard Time, and it compares whether the output of the given date the same (Standard) or less (DST). + var stdTimezoneOffset = Math.max(winterOffset, summerOffset); + + // timezone is specified as seconds west of UTC ("The external variable + // `timezone` shall be set to the difference, in seconds, between + // Coordinated Universal Time (UTC) and local standard time."), the same + // as returned by stdTimezoneOffset. + // See http://pubs.opengroup.org/onlinepubs/009695399/functions/tzset.html + HEAPU32[((timezone)>>2)] = stdTimezoneOffset * 60; + + HEAP32[((daylight)>>2)] = Number(winterOffset != summerOffset); + + function extractZone(date) { + var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/); + return match ? match[1] : "GMT"; + }; + var winterName = extractZone(winter); + var summerName = extractZone(summer); + var winterNamePtr = stringToNewUTF8(winterName); + var summerNamePtr = stringToNewUTF8(summerName); + if (summerOffset < winterOffset) { + // Northern hemisphere + HEAPU32[((tzname)>>2)] = winterNamePtr; + HEAPU32[(((tzname)+(4))>>2)] = summerNamePtr; + } else { + HEAPU32[((tzname)>>2)] = summerNamePtr; + HEAPU32[(((tzname)+(4))>>2)] = winterNamePtr; + } + }; + + var _abort = () => { + abort(''); + }; + + function _emscripten_date_now() { + return Date.now(); + } + + var getHeapMax = () => + // Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate + // full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side + // for any code that deals with heap sizes, which would require special + // casing all heap size related code to treat 0 specially. + 2147483648; + var _emscripten_get_heap_max = () => getHeapMax(); + + + var _emscripten_memcpy_big = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num); + + + var growMemory = (size) => { + var b = wasmMemory.buffer; + var pages = (size - b.byteLength + 65535) >>> 16; + try { + // round size grow request up to wasm page size (fixed 64KB per spec) + wasmMemory.grow(pages); // .grow() takes a delta compared to the previous size + updateMemoryViews(); + return 1 /*success*/; + } catch(e) { + } + // implicit 0 return to save code size (caller will cast "undefined" into 0 + // anyhow) + }; + var _emscripten_resize_heap = (requestedSize) => { + var oldSize = HEAPU8.length; + // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned. + requestedSize >>>= 0; + // With multithreaded builds, races can happen (another thread might increase the size + // in between), so return a failure, and let the caller retry. + + // Memory resize rules: + // 1. Always increase heap size to at least the requested size, rounded up + // to next page multiple. + // 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap + // geometrically: increase the heap size according to + // MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most + // overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB). + // 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap + // linearly: increase the heap size by at least + // MEMORY_GROWTH_LINEAR_STEP bytes. + // 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by + // MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest + // 4. If we were unable to allocate as much memory, it may be due to + // over-eager decision to excessively reserve due to (3) above. + // Hence if an allocation fails, cut down on the amount of excess + // growth, in an attempt to succeed to perform a smaller allocation. + + // A limit is set for how much we can grow. We should not exceed that + // (the wasm binary specifies it, so if we tried, we'd fail anyhow). + var maxHeapSize = getHeapMax(); + if (requestedSize > maxHeapSize) { + return false; + } + + var alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple; + + // Loop through potential heap size increases. If we attempt a too eager + // reservation that fails, cut down on the attempted size and reserve a + // smaller bump instead. (max 3 times, chosen somewhat arbitrarily) + for (var cutDown = 1; cutDown <= 4; cutDown *= 2) { + var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); // ensure geometric growth + // but limit overreserving (default to capping at +96MB overgrowth at most) + overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 ); + + var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536)); + + var replacement = growMemory(newSize); + if (replacement) { + + return true; + } + } + return false; + }; + + + var runtimeKeepalivePush = () => { + runtimeKeepaliveCounter += 1; + }; + + var runtimeKeepalivePop = () => { + runtimeKeepaliveCounter -= 1; + }; + /** @param {number=} timeout */ + var safeSetTimeout = (func, timeout) => { + runtimeKeepalivePush(); + return setTimeout(() => { + runtimeKeepalivePop(); + callUserCallback(func); + }, timeout); + }; + var _emscripten_sleep = function(ms) { + // emscripten_sleep() does not return a value, but we still need a |return| + // here for stack switching support (ASYNCIFY=2). In that mode this function + // returns a Promise instead of nothing, and that Promise is what tells the + // wasm VM to pause the stack. + return Asyncify.handleSleep((wakeUp) => safeSetTimeout(wakeUp, ms)); + }; + Module['_emscripten_sleep'] = _emscripten_sleep; + _emscripten_sleep.isAsync = true; + + var ENV = PHPLoader.ENV || { + }; + + var getExecutableName = () => { + return thisProgram || './this.program'; + }; + var getEnvStrings = () => { + if (!getEnvStrings.strings) { + // Default values. + // Browser language detection #8751 + var lang = ((typeof navigator == 'object' && navigator.languages && navigator.languages[0]) || 'C').replace('-', '_') + '.UTF-8'; + var env = { + 'USER': 'web_user', + 'LOGNAME': 'web_user', + 'PATH': '/', + 'PWD': '/', + 'HOME': '/home/web_user', + 'LANG': lang, + '_': getExecutableName() + }; + // Apply the user-provided values, if any. + for (var x in ENV) { + // x is a key in ENV; if ENV[x] is undefined, that means it was + // explicitly set to be so. We allow user code to do that to + // force variables with default values to remain unset. + if (ENV[x] === undefined) delete env[x]; + else env[x] = ENV[x]; + } + var strings = []; + for (var x in env) { + strings.push(`${x}=${env[x]}`); + } + getEnvStrings.strings = strings; + } + return getEnvStrings.strings; + }; + + var stringToAscii = (str, buffer) => { + for (var i = 0; i < str.length; ++i) { + HEAP8[((buffer++)>>0)] = str.charCodeAt(i); + } + // Null-terminate the string + HEAP8[((buffer)>>0)] = 0; + }; + + var _environ_get = (__environ, environ_buf) => { + var bufSize = 0; + getEnvStrings().forEach(function(string, i) { + var ptr = environ_buf + bufSize; + HEAPU32[(((__environ)+(i*4))>>2)] = ptr; + stringToAscii(string, ptr); + bufSize += string.length + 1; + }); + return 0; + }; + + + var _environ_sizes_get = (penviron_count, penviron_buf_size) => { + var strings = getEnvStrings(); + HEAPU32[((penviron_count)>>2)] = strings.length; + var bufSize = 0; + strings.forEach(function(string) { + bufSize += string.length + 1; + }); + HEAPU32[((penviron_buf_size)>>2)] = bufSize; + return 0; + }; + + + function _fd_close(fd) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + FS.close(stream); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + function _fd_fdstat_get(fd, pbuf) { + try { + + var rightsBase = 0; + var rightsInheriting = 0; + var flags = 0; + { + var stream = SYSCALLS.getStreamFromFD(fd); + // All character devices are terminals (other things a Linux system would + // assume is a character device, like the mouse, we have special APIs for). + var type = stream.tty ? 2 : + FS.isDir(stream.mode) ? 3 : + FS.isLink(stream.mode) ? 7 : + 4; + } + HEAP8[((pbuf)>>0)] = type; + HEAP16[(((pbuf)+(2))>>1)] = flags; + (tempI64 = [rightsBase>>>0,(tempDouble=rightsBase,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((pbuf)+(8))>>2)] = tempI64[0],HEAP32[(((pbuf)+(12))>>2)] = tempI64[1]); + (tempI64 = [rightsInheriting>>>0,(tempDouble=rightsInheriting,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((pbuf)+(16))>>2)] = tempI64[0],HEAP32[(((pbuf)+(20))>>2)] = tempI64[1]); + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + /** @param {number=} offset */ + var doReadv = (stream, iov, iovcnt, offset) => { + var ret = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[((iov)>>2)]; + var len = HEAPU32[(((iov)+(4))>>2)]; + iov += 8; + var curr = FS.read(stream, HEAP8,ptr, len, offset); + if (curr < 0) return -1; + ret += curr; + if (curr < len) break; // nothing more to read + if (typeof offset !== 'undefined') { + offset += curr; + } + } + return ret; + }; + + function _fd_read(fd, iov, iovcnt, pnum) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + var num = doReadv(stream, iov, iovcnt); + HEAPU32[((pnum)>>2)] = num; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + + function _fd_seek(fd,offset_low, offset_high,whence,newOffset) { + var offset = convertI32PairToI53Checked(offset_low, offset_high);; + + + try { + + if (isNaN(offset)) return 61; + var stream = SYSCALLS.getStreamFromFD(fd); + FS.llseek(stream, offset, whence); + (tempI64 = [stream.position>>>0,(tempDouble=stream.position,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[((newOffset)>>2)] = tempI64[0],HEAP32[(((newOffset)+(4))>>2)] = tempI64[1]); + if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + ; + } + + /** @param {number=} offset */ + var doWritev = (stream, iov, iovcnt, offset) => { + var ret = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[((iov)>>2)]; + var len = HEAPU32[(((iov)+(4))>>2)]; + iov += 8; + var curr = FS.write(stream, HEAP8,ptr, len, offset); + if (curr < 0) return -1; + ret += curr; + if (typeof offset !== 'undefined') { + offset += curr; + } + } + return ret; + }; + + function _fd_write(fd, iov, iovcnt, pnum) { + try { + + var stream = SYSCALLS.getStreamFromFD(fd); + var num = doWritev(stream, iov, iovcnt); + HEAPU32[((pnum)>>2)] = num; + return 0; + } catch (e) { + if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e; + return e.errno; + } + } + + + + + + + + + + + var _getaddrinfo = (node, service, hint, out) => { + // Note getaddrinfo currently only returns a single addrinfo with ai_next defaulting to NULL. When NULL + // hints are specified or ai_family set to AF_UNSPEC or ai_socktype or ai_protocol set to 0 then we + // really should provide a linked list of suitable addrinfo values. + var addrs = []; + var canon = null; + var addr = 0; + var port = 0; + var flags = 0; + var family = 0; + var type = 0; + var proto = 0; + var ai, last; + + function allocaddrinfo(family, type, proto, canon, addr, port) { + var sa, salen, ai; + var errno; + + salen = family === 10 ? + 28 : + 16; + addr = family === 10 ? + inetNtop6(addr) : + inetNtop4(addr); + sa = _malloc(salen); + errno = writeSockaddr(sa, family, addr, port); + assert(!errno); + + ai = _malloc(32); + HEAP32[(((ai)+(4))>>2)] = family; + HEAP32[(((ai)+(8))>>2)] = type; + HEAP32[(((ai)+(12))>>2)] = proto; + HEAPU32[(((ai)+(24))>>2)] = canon; + HEAPU32[(((ai)+(20))>>2)] = sa; + if (family === 10) { + HEAP32[(((ai)+(16))>>2)] = 28; + } else { + HEAP32[(((ai)+(16))>>2)] = 16; + } + HEAP32[(((ai)+(28))>>2)] = 0; + + return ai; + } + + if (hint) { + flags = HEAP32[((hint)>>2)]; + family = HEAP32[(((hint)+(4))>>2)]; + type = HEAP32[(((hint)+(8))>>2)]; + proto = HEAP32[(((hint)+(12))>>2)]; + } + if (type && !proto) { + proto = type === 2 ? 17 : 6; + } + if (!type && proto) { + type = proto === 17 ? 2 : 1; + } + + // If type or proto are set to zero in hints we should really be returning multiple addrinfo values, but for + // now default to a TCP STREAM socket so we can at least return a sensible addrinfo given NULL hints. + if (proto === 0) { + proto = 6; + } + if (type === 0) { + type = 1; + } + + if (!node && !service) { + return -2; + } + if (flags & ~(1|2|4| + 1024|8|16|32)) { + return -1; + } + if (hint !== 0 && (HEAP32[((hint)>>2)] & 2) && !node) { + return -1; + } + if (flags & 32) { + // TODO + return -2; + } + if (type !== 0 && type !== 1 && type !== 2) { + return -7; + } + if (family !== 0 && family !== 2 && family !== 10) { + return -6; + } + + if (service) { + service = UTF8ToString(service); + port = parseInt(service, 10); + + if (isNaN(port)) { + if (flags & 1024) { + return -2; + } + // TODO support resolving well-known service names from: + // http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt + return -8; + } + } + + if (!node) { + if (family === 0) { + family = 2; + } + if ((flags & 1) === 0) { + if (family === 2) { + addr = _htonl(2130706433); + } else { + addr = [0, 0, 0, 1]; + } + } + ai = allocaddrinfo(family, type, proto, null, addr, port); + HEAPU32[((out)>>2)] = ai; + return 0; + } + + // + // try as a numeric address + // + node = UTF8ToString(node); + addr = inetPton4(node); + if (addr !== null) { + // incoming node is a valid ipv4 address + if (family === 0 || family === 2) { + family = 2; + } + else if (family === 10 && (flags & 8)) { + addr = [0, 0, _htonl(0xffff), addr]; + family = 10; + } else { + return -2; + } + } else { + addr = inetPton6(node); + if (addr !== null) { + // incoming node is a valid ipv6 address + if (family === 0 || family === 10) { + family = 10; + } else { + return -2; + } + } + } + if (addr != null) { + ai = allocaddrinfo(family, type, proto, node, addr, port); + HEAPU32[((out)>>2)] = ai; + return 0; + } + if (flags & 4) { + return -2; + } + + // + // try as a hostname + // + // resolve the hostname to a temporary fake address + node = DNS.lookup_name(node); + addr = inetPton4(node); + if (family === 0) { + family = 2; + } else if (family === 10) { + addr = [0, 0, _htonl(0xffff), addr]; + } + ai = allocaddrinfo(family, type, proto, null, addr, port); + HEAPU32[((out)>>2)] = ai; + return 0; + }; + + + + + + var getHostByName = (name) => { + // generate hostent + var ret = _malloc(20); // XXX possibly leaked, as are others here + var nameBuf = stringToNewUTF8(name); + HEAPU32[((ret)>>2)] = nameBuf; + var aliasesBuf = _malloc(4); + HEAPU32[((aliasesBuf)>>2)] = 0; + HEAPU32[(((ret)+(4))>>2)] = aliasesBuf; + var afinet = 2; + HEAP32[(((ret)+(8))>>2)] = afinet; + HEAP32[(((ret)+(12))>>2)] = 4; + var addrListBuf = _malloc(12); + HEAPU32[((addrListBuf)>>2)] = addrListBuf+8; + HEAPU32[(((addrListBuf)+(4))>>2)] = 0; + HEAP32[(((addrListBuf)+(8))>>2)] = inetPton4(DNS.lookup_name(name)); + HEAPU32[(((ret)+(16))>>2)] = addrListBuf; + return ret; + }; + + + var _gethostbyaddr = (addr, addrlen, type) => { + if (type !== 2) { + setErrNo(5); + // TODO: set h_errno + return null; + } + addr = HEAP32[((addr)>>2)]; // addr is in_addr + var host = inetNtop4(addr); + var lookup = DNS.lookup_addr(host); + if (lookup) { + host = lookup; + } + return getHostByName(host); + }; + + + var _gethostbyname = (name) => { + return getHostByName(UTF8ToString(name)); + }; + + + var _gethostbyname_r = (name, ret, buf, buflen, out, err) => { + var data = _gethostbyname(name); + _memcpy(ret, data, 20); + _free(data); + HEAP32[((err)>>2)] = 0; + HEAPU32[((out)>>2)] = ret; + return 0; + }; + + var _getloadavg = (loadavg, nelem) => { + // int getloadavg(double loadavg[], int nelem); + // http://linux.die.net/man/3/getloadavg + var limit = Math.min(nelem, 3); + var doubleSize = 8; + for (var i = 0; i < limit; i++) { + HEAPF64[(((loadavg)+(i * doubleSize))>>3)] = 0.1; + } + return limit; + }; + + + + + var _getnameinfo = (sa, salen, node, nodelen, serv, servlen, flags) => { + var info = readSockaddr(sa, salen); + if (info.errno) { + return -6; + } + var port = info.port; + var addr = info.addr; + + var overflowed = false; + + if (node && nodelen) { + var lookup; + if ((flags & 1) || !(lookup = DNS.lookup_addr(addr))) { + if (flags & 8) { + return -2; + } + } else { + addr = lookup; + } + var numBytesWrittenExclNull = stringToUTF8(addr, node, nodelen); + + if (numBytesWrittenExclNull+1 >= nodelen) { + overflowed = true; + } + } + + if (serv && servlen) { + port = '' + port; + var numBytesWrittenExclNull = stringToUTF8(port, serv, servlen); + + if (numBytesWrittenExclNull+1 >= servlen) { + overflowed = true; + } + } + + if (overflowed) { + // Note: even when we overflow, getnameinfo() is specced to write out the truncated results. + return -12; + } + + return 0; + }; + + var Protocols = { + list:[], + map:{ + }, + }; + + + var _setprotoent = (stayopen) => { + // void setprotoent(int stayopen); + + // Allocate and populate a protoent structure given a name, protocol number and array of aliases + function allocprotoent(name, proto, aliases) { + // write name into buffer + var nameBuf = _malloc(name.length + 1); + stringToAscii(name, nameBuf); + + // write aliases into buffer + var j = 0; + var length = aliases.length; + var aliasListBuf = _malloc((length + 1) * 4); // Use length + 1 so we have space for the terminating NULL ptr. + + for (var i = 0; i < length; i++, j += 4) { + var alias = aliases[i]; + var aliasBuf = _malloc(alias.length + 1); + stringToAscii(alias, aliasBuf); + HEAPU32[(((aliasListBuf)+(j))>>2)] = aliasBuf; + } + HEAPU32[(((aliasListBuf)+(j))>>2)] = 0; // Terminating NULL pointer. + + // generate protoent + var pe = _malloc(12); + HEAPU32[((pe)>>2)] = nameBuf; + HEAPU32[(((pe)+(4))>>2)] = aliasListBuf; + HEAP32[(((pe)+(8))>>2)] = proto; + return pe; + }; + + // Populate the protocol 'database'. The entries are limited to tcp and udp, though it is fairly trivial + // to add extra entries from /etc/protocols if desired - though not sure if that'd actually be useful. + var list = Protocols.list; + var map = Protocols.map; + if (list.length === 0) { + var entry = allocprotoent('tcp', 6, ['TCP']); + list.push(entry); + map['tcp'] = map['6'] = entry; + entry = allocprotoent('udp', 17, ['UDP']); + list.push(entry); + map['udp'] = map['17'] = entry; + } + + _setprotoent.index = 0; + }; + + + var _getprotobyname = (name) => { + // struct protoent *getprotobyname(const char *); + name = UTF8ToString(name); + _setprotoent(true); + var result = Protocols.map[name]; + return result; + }; + + + var _getprotobynumber = (number) => { + // struct protoent *getprotobynumber(int proto); + _setprotoent(true); + var result = Protocols.map[number]; + return result; + }; + + + /** @suppress {duplicate } */ + var stringToUTF8OnStack = (str) => { + var size = lengthBytesUTF8(str) + 1; + var ret = stackAlloc(size); + stringToUTF8(str, ret, size); + return ret; + }; + var allocateUTF8OnStack = stringToUTF8OnStack; + + var PHPWASM = { + init:function () { + // The /internal directory is required by the C module. It's where the + // stdout, stderr, and headers information are written for the JavaScript + // code to read later on. + FS.mkdir("/internal"); + + PHPWASM.EventEmitter = ENVIRONMENT_IS_NODE + ? require('events').EventEmitter + : class EventEmitter { + constructor() { + this.listeners = {}; + } + emit(eventName, data) { + if (this.listeners[eventName]) { + this.listeners[eventName].forEach( + (callback) => { + callback(data); + } + ); + } + } + once(eventName, callback) { + const self = this; + function removedCallback() { + callback(...arguments); + self.removeListener(eventName, removedCallback); + } + this.on(eventName, removedCallback); + } + removeAllListeners(eventName) { + if (eventName) { + delete this.listeners[eventName]; + } else { + this.listeners = {}; + } + } + removeListener(eventName, callback) { + if (this.listeners[eventName]) { + const idx = + this.listeners[eventName].indexOf(callback); + if (idx !== -1) { + this.listeners[eventName].splice(idx, 1); + } + } + } + }; + PHPWASM.child_proc_by_fd = {}; + PHPWASM.child_proc_by_pid = {}; + PHPWASM.input_devices = {}; + }, + getAllWebSockets:function (sock) { + const webSockets = /* @__PURE__ */ new Set(); + if (sock.server) { + sock.server.clients.forEach((ws) => { + webSockets.add(ws); + }); + } + for (const peer of PHPWASM.getAllPeers(sock)) { + webSockets.add(peer.socket); + } + return Array.from(webSockets); + }, + getAllPeers:function (sock) { + const peers = new Set(); + if (sock.server) { + sock.pending + .filter((pending) => pending.peers) + .forEach((pending) => { + for (const peer of Object.values(pending.peers)) { + peers.add(peer); + } + }); + } + if (sock.peers) { + for (const peer of Object.values(sock.peers)) { + peers.add(peer); + } + } + return Array.from(peers); + }, + awaitData:function (ws) { + return PHPWASM.awaitEvent(ws, 'message'); + }, + awaitConnection:function (ws) { + if (ws.OPEN === ws.readyState) { + return [Promise.resolve(), PHPWASM.noop]; + } + return PHPWASM.awaitEvent(ws, 'open'); + }, + awaitClose:function (ws) { + if ([ws.CLOSING, ws.CLOSED].includes(ws.readyState)) { + return [Promise.resolve(), PHPWASM.noop]; + } + return PHPWASM.awaitEvent(ws, 'close'); + }, + awaitError:function (ws) { + if ([ws.CLOSING, ws.CLOSED].includes(ws.readyState)) { + return [Promise.resolve(), PHPWASM.noop]; + } + return PHPWASM.awaitEvent(ws, 'error'); + }, + awaitEvent:function (ws, event) { + let resolve; + const listener = () => { + resolve(); + }; + const promise = new Promise(function (_resolve) { + resolve = _resolve; + ws.once(event, listener); + }); + const cancel = () => { + ws.removeListener(event, listener); + // Rejecting the promises bubbles up and kills the entire + // node process. Let's resolve them on the next tick instead + // to give the caller some space to unbind any handlers. + setTimeout(resolve); + }; + return [promise, cancel]; + }, + noop:function () { }, + spawnProcess:function (command, args, options) { + if (Module['spawnProcess']) { + const spawnedPromise = Module['spawnProcess'](command, args, options); + return Promise.resolve(spawnedPromise).then(function (spawned) { + if (!spawned || !spawned.on) { + throw new Error( + 'spawnProcess() must return an EventEmitter but returned a different type.' + ); + } + return spawned; + }); + } + + if (ENVIRONMENT_IS_NODE) { + return require('child_process').spawn(command, args, { + ...options, + shell: true, + stdio: ['pipe', 'pipe', 'pipe'], + timeout: 100, + }); + } + const e = new Error( + 'popen(), proc_open() etc. are unsupported in the browser. Call php.setSpawnHandler() ' + + 'and provide a callback to handle spawning processes, or disable a popen(), proc_open() ' + + 'and similar functions via php.ini.' + ); + e.code = 'SPAWN_UNSUPPORTED'; + throw e; + }, + shutdownSocket:function (socketd, how) { + // This implementation only supports websockets at the moment + const sock = getSocketFromFD(socketd); + const peer = Object.values(sock.peers)[0]; + + if (!peer) { + return -1; + } + + try { + peer.socket.close(); + SOCKFS.websocket_sock_ops.removePeer(sock, peer); + return 0; + } catch (e) { + console.log('Socket shutdown error', e); + return -1; + } + }, + }; + function _js_create_input_device(deviceId) { + let dataBuffer = []; + let dataCallback; + const filename = 'proc_id_' + deviceId; + const device = FS.createDevice( + '/dev', + filename, + function () { }, + function (byte) { + try { + dataBuffer.push(byte); + if (dataCallback) { + dataCallback(new Uint8Array(dataBuffer)); + dataBuffer = []; + } + } catch (e) { + console.error(e); + throw e; + } + } + ); + + const devicePath = '/dev/' + filename; + PHPWASM.input_devices[deviceId] = { + devicePath: devicePath, + onData: function (cb) { + dataCallback = cb; + dataBuffer.forEach(function (data) { + cb(data); + }); + dataBuffer.length = 0; + }, + }; + return allocateUTF8OnStack(devicePath); + } + + function _js_fd_read(fd, iov, iovcnt, pnum) { + // Only run the read operation on a regular call, + // never when rewinding the stack. + if (Asyncify.state === Asyncify.State.Normal) { + var returnCode; + var stream; + let num = 0; + try { + stream = SYSCALLS.getStreamFromFD(fd); + const num = doReadv(stream, iov, iovcnt); + HEAPU32[pnum >> 2] = num; + return 0; + } catch (e) { + // Rethrow any unexpected non-filesystem errors. + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) { + throw e; + } + // Only return synchronously if this isn't an asynchronous pipe. + // Error code 6 indicates EWOULDBLOCK – this is our signal to wait. + // We also need to distinguish between a process pipe and a file pipe, otherwise + // reading from an empty file would block until the timeout. + if (e.errno !== 6 || !(stream?.fd in PHPWASM.child_proc_by_fd)) { + // On failure, yield 0 bytes read to indicate EOF. + HEAPU32[pnum >> 2] = 0; + return returnCode + } + } + } + + // At this point we know we have to poll. + // You might wonder why we duplicate the code here instead of always using + // Asyncify.handleSleep(). The reason is performance. Most of the time, + // the read operation will work synchronously and won't require yielding + // back to JS. In these cases we don't want to pay the Asyncify overhead, + // save the stack, yield back to JS, restore the stack etc. + return Asyncify.handleSleep(function (wakeUp) { + var retries = 0; + var interval = 50; + var timeout = 5000; + // We poll for data and give up after a timeout. + // We can't simply rely on PHP timeout here because we don't want + // to, say, block the entire PHPUnit test suite without any visible + // feedback. + var maxRetries = timeout / interval; + function poll() { + var returnCode; + var stream; + let num; + try { + stream = SYSCALLS.getStreamFromFD(fd); + num = doReadv(stream, iov, iovcnt); + returnCode = 0; + } catch (e) { + if ( + typeof FS == 'undefined' || + !(e.name === 'ErrnoError') + ) { + console.error(e); + throw e; + } + returnCode = e.errno; + } + + const success = returnCode === 0; + const failure = ( + ++retries > maxRetries || + !(fd in PHPWASM.child_proc_by_fd) || + PHPWASM.child_proc_by_fd[fd]?.exited || + FS.isClosed(stream) + ); + + if (success) { + HEAPU32[pnum >> 2] = num; + wakeUp(0); + } else if (failure) { + // On failure, yield 0 bytes read to indicate EOF. + HEAPU32[pnum >> 2] = 0; + // If the failure is due to a timeout, return 0 to indicate that we + // reached EOF. Otherwise, propagate the error code. + wakeUp(returnCode === 6 ? 0 : returnCode); + } else { + setTimeout(poll, interval); + } + } + poll(); + }); + } + + + function _js_module_onMessage(data, bufPtr) { + if (typeof Asyncify === 'undefined') { + return; + } + + if (Module['onMessage']) { + const dataStr = UTF8ToString(data); + + return Asyncify.handleSleep((wakeUp) => { + Module['onMessage'](dataStr) + .then((response) => { + const responseBytes = + typeof response === 'string' + ? new TextEncoder().encode(response) + : response; + + // Copy the response bytes to heap + const responseSize = responseBytes.byteLength; + const responsePtr = _malloc(responseSize + 1); + HEAPU8.set(responseBytes, responsePtr); + HEAPU8[responsePtr + responseSize] = 0; + HEAPU8[bufPtr] = responsePtr; + HEAPU8[bufPtr + 1] = responsePtr >> 8; + HEAPU8[bufPtr + 2] = responsePtr >> 16; + HEAPU8[bufPtr + 3] = responsePtr >> 24; + + wakeUp(responseSize); + }) + .catch((e) => { + // Log the error and return NULL. Message passing + // separates JS context from the PHP context so we + // don't let PHP crash here. + console.error(e); + wakeUp(-1); + }); + }); + } + } + + + function _js_open_process( + command, + argsPtr, + argsLength, + descriptorsPtr, + descriptorsLength, + cwdPtr, + cwdLength, + envPtr, + envLength + ) { + if (!command) { + return 1; + } + + const cmdstr = UTF8ToString(command); + if (!cmdstr.length) { + return 0; + } + + let argsArray = []; + if (argsLength) { + for (var i = 0; i < argsLength; i++) { + const charPointer = argsPtr + i * 4; + argsArray.push(UTF8ToString(HEAPU32[charPointer >> 2])); + } + } + + const cwdstr = cwdPtr ? UTF8ToString(cwdPtr) : null; + let envObject = null; + + if (envLength) { + envObject = {}; + for (var i = 0; i < envLength; i++) { + const envPointer = envPtr + i * 4; + const envEntry = UTF8ToString(HEAPU32[envPointer >> 2]); + const splitAt = envEntry.indexOf('='); + if (splitAt === -1) { + continue; + } + const key = envEntry.substring(0, splitAt); + const value = envEntry.substring(splitAt + 1); + envObject[key] = value; + } + } + + var std = {}; + // Extracts an array of available descriptors that should be dispatched to streams. + // On the C side, the descriptors are expressed as `**int` so we must go read + // each of the `descriptorsLength` `*int` pointers and convert the associated data into + // a JavaScript object { descriptor : { child : fd, parent : fd } }. + for (var i = 0; i < descriptorsLength; i++) { + const descriptorPtr = HEAPU32[(descriptorsPtr + i * 4) >> 2]; + std[HEAPU32[descriptorPtr >> 2]] = { + child: HEAPU32[(descriptorPtr + 4) >> 2], + parent: HEAPU32[(descriptorPtr + 8) >> 2], + }; + } + + return Asyncify.handleSleep(async (wakeUp) => { + let cp; + try { + const options = {}; + if (cwdstr !== null) { + options.cwd = cwdstr; + } + if (envObject !== null) { + options.env = envObject; + } + cp = PHPWASM.spawnProcess(cmdstr, argsArray, options); + if (cp instanceof Promise) { + cp = await cp; + } + } catch (e) { + if (e.code === 'SPAWN_UNSUPPORTED') { + wakeUp(1); + return; + } + console.error(e); + wakeUp(1); + throw e; + } + + const ProcInfo = { + pid: cp.pid, + exited: false, + stdinFd: std[0]?.child, + stdinIsDevice: std[0]?.child in PHPWASM.input_devices, + stdoutChildFd: std[1]?.child, + stdoutParentFd: std[1]?.parent, + stderrChildFd: std[2]?.child, + stderrParentFd: std[2]?.parent, + stdout: new PHPWASM.EventEmitter(), + stderr: new PHPWASM.EventEmitter(), + }; + if (ProcInfo.stdoutChildFd) + PHPWASM.child_proc_by_fd[ProcInfo.stdoutChildFd] = ProcInfo; + if (ProcInfo.stderrChildFd) + PHPWASM.child_proc_by_fd[ProcInfo.stderrChildFd] = ProcInfo; + if (ProcInfo.stdoutParentFd) + PHPWASM.child_proc_by_fd[ProcInfo.stdoutParentFd] = ProcInfo; + if (ProcInfo.stderrParentFd) + PHPWASM.child_proc_by_fd[ProcInfo.stderrParentFd] = ProcInfo; + PHPWASM.child_proc_by_pid[ProcInfo.pid] = ProcInfo; + + cp.on('exit', function (code) { + ProcInfo.exitCode = code; + ProcInfo.exited = true; + // Emit events for the wasm_poll_socket function. + ProcInfo.stdout.emit('data'); + ProcInfo.stderr.emit('data'); + }); + + // Pass data from child process's stdout to PHP's end of the stdout pipe. + if (ProcInfo.stdoutChildFd) { + const stdoutStream = SYSCALLS.getStreamFromFD( + ProcInfo.stdoutChildFd + ); + let stdoutAt = 0; + cp.stdout.on('data', function (data) { + ProcInfo.stdout.emit('data', data); + stdoutStream.stream_ops.write( + stdoutStream, + data, + 0, + data.length, + stdoutAt + ); + stdoutAt += data.length; + }); + } + + // Pass data from child process's stderr to PHP's end of the stdout pipe. + if (ProcInfo.stderrChildFd) { + const stderrStream = SYSCALLS.getStreamFromFD( + ProcInfo.stderrChildFd + ); + let stderrAt = 0; + cp.stderr.on('data', function (data) { + ProcInfo.stderr.emit('data', data); + stderrStream.stream_ops.write( + stderrStream, + data, + 0, + data.length, + stderrAt + ); + stderrAt += data.length; + }); + } + + /** + * Wait until the child process has been spawned. + * Unfortunately there is no Node.js API to check whether + * the process has already been spawned. We can only listen + * to the 'spawn' event and if it has already been spawned, + * listen to the 'exit' event. + */ + try { + await new Promise((resolve, reject) => { + cp.on('spawn', resolve); + cp.on('error', reject); + }); + } catch (e) { + console.error(e); + wakeUp(1); + return; + } + + // Now we want to pass data from the STDIN source supplied by PHP + // to the child process. + + // PHP will write STDIN data to a device. + if (ProcInfo.stdinIsDevice) { + // We use Emscripten devices as pipes. This is a bit of a hack + // but it works as we get a callback when the device is written to. + // Let's listen to anything it outputs and pass it to the child process. + PHPWASM.input_devices[ProcInfo.stdinFd].onData(function (data) { + if (!data) return; + const dataStr = new TextDecoder('utf-8').decode(data); + cp.stdin.write(dataStr); + }); + wakeUp(ProcInfo.pid); + return; + } + + if (ProcInfo.stdinFd) { + // PHP will write STDIN data to a file descriptor. + const stdinStream = SYSCALLS.getStreamFromFD(ProcInfo.stdinFd); + if (stdinStream.node) { + // Pipe the entire stdinStream to cp.stdin + const CHUNK_SIZE = 1024; + const buffer = new Uint8Array(CHUNK_SIZE); + let offset = 0; + + while (true) { + const bytesRead = stdinStream.stream_ops.read( + stdinStream, + buffer, + 0, + CHUNK_SIZE, + offset + ); + if (bytesRead === null || bytesRead === 0) { + break; + } + try { + cp.stdin.write(buffer.subarray(0, bytesRead)); + } catch (e) { + console.error(e); + return 1; + } + if (bytesRead < CHUNK_SIZE) { + break; + } + offset += bytesRead; + } + + wakeUp(ProcInfo.pid); + return; + } + } + + wakeUp(ProcInfo.pid); + }); + } + + + function _js_popen_to_file(command, mode, exitCodePtr) { + // Parse args + if (!command) return 1; // shell is available + + const cmdstr = UTF8ToString(command); + if (!cmdstr.length) return 0; // this is what glibc seems to do (shell works test?) + + const modestr = UTF8ToString(mode); + if (!modestr.length) return 0; // this is what glibc seems to do (shell works test?) + if (modestr === 'w') { + console.error('popen($cmd, "w") is not implemented yet'); + } + + return Asyncify.handleSleep(async (wakeUp) => { + let cp; + try { + cp = PHPWASM.spawnProcess(cmdstr, []); + if (cp instanceof Promise) { + cp = await cp; + } + } catch (e) { + console.error(e); + if (e.code === 'SPAWN_UNSUPPORTED') { + return 1; + } + throw e; + } + + const outByteArrays = []; + cp.stdout.on('data', function (data) { + outByteArrays.push(data); + }); + + const outputPath = '/tmp/popen_output'; + cp.on('exit', function (exitCode) { + // Concat outByteArrays, an array of UInt8Arrays + // into a single Uint8Array. + const outBytes = new Uint8Array( + outByteArrays.reduce((acc, curr) => acc + curr.length, 0) + ); + let offset = 0; + for (const byteArray of outByteArrays) { + outBytes.set(byteArray, offset); + offset += byteArray.length; + } + + FS.writeFile(outputPath, outBytes); + + HEAPU8[exitCodePtr] = exitCode; + wakeUp(allocateUTF8OnStack(outputPath)); // 2 is SIGINT + }); + }); + } + + function _js_process_status(pid, exitCodePtr) { + if (!PHPWASM.child_proc_by_pid[pid]) { + return -1; + } + if (PHPWASM.child_proc_by_pid[pid].exited) { + HEAPU32[exitCodePtr >> 2] = + PHPWASM.child_proc_by_pid[pid].exitCode; + return 1; + } + return 0; + } + + function _js_waitpid(pid, exitCodePtr) { + if (!PHPWASM.child_proc_by_pid[pid]) { + return -1; + } + return Asyncify.handleSleep((wakeUp) => { + const poll = function () { + if (PHPWASM.child_proc_by_pid[pid]?.exited) { + HEAPU32[exitCodePtr >> 2] = + PHPWASM.child_proc_by_pid[pid].exitCode; + wakeUp(pid); + } else { + setTimeout(poll, 50); + } + }; + poll(); + }); + } + + + + var arraySum = (array, index) => { + var sum = 0; + for (var i = 0; i <= index; sum += array[i++]) { + // no-op + } + return sum; + }; + + + var MONTH_DAYS_LEAP = [31,29,31,30,31,30,31,31,30,31,30,31]; + + var MONTH_DAYS_REGULAR = [31,28,31,30,31,30,31,31,30,31,30,31]; + var addDays = (date, days) => { + var newDate = new Date(date.getTime()); + while (days > 0) { + var leap = isLeapYear(newDate.getFullYear()); + var currentMonth = newDate.getMonth(); + var daysInCurrentMonth = (leap ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR)[currentMonth]; + + if (days > daysInCurrentMonth-newDate.getDate()) { + // we spill over to next month + days -= (daysInCurrentMonth-newDate.getDate()+1); + newDate.setDate(1); + if (currentMonth < 11) { + newDate.setMonth(currentMonth+1) + } else { + newDate.setMonth(0); + newDate.setFullYear(newDate.getFullYear()+1); + } + } else { + // we stay in current month + newDate.setDate(newDate.getDate()+days); + return newDate; + } + } + + return newDate; + }; + + + + + var writeArrayToMemory = (array, buffer) => { + HEAP8.set(array, buffer); + }; + + var _strftime = (s, maxsize, format, tm) => { + // size_t strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct tm *restrict timeptr); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html + + var tm_zone = HEAP32[(((tm)+(40))>>2)]; + + var date = { + tm_sec: HEAP32[((tm)>>2)], + tm_min: HEAP32[(((tm)+(4))>>2)], + tm_hour: HEAP32[(((tm)+(8))>>2)], + tm_mday: HEAP32[(((tm)+(12))>>2)], + tm_mon: HEAP32[(((tm)+(16))>>2)], + tm_year: HEAP32[(((tm)+(20))>>2)], + tm_wday: HEAP32[(((tm)+(24))>>2)], + tm_yday: HEAP32[(((tm)+(28))>>2)], + tm_isdst: HEAP32[(((tm)+(32))>>2)], + tm_gmtoff: HEAP32[(((tm)+(36))>>2)], + tm_zone: tm_zone ? UTF8ToString(tm_zone) : '' + }; + + var pattern = UTF8ToString(format); + + // expand format + var EXPANSION_RULES_1 = { + '%c': '%a %b %d %H:%M:%S %Y', // Replaced by the locale's appropriate date and time representation - e.g., Mon Aug 3 14:02:01 2013 + '%D': '%m/%d/%y', // Equivalent to %m / %d / %y + '%F': '%Y-%m-%d', // Equivalent to %Y - %m - %d + '%h': '%b', // Equivalent to %b + '%r': '%I:%M:%S %p', // Replaced by the time in a.m. and p.m. notation + '%R': '%H:%M', // Replaced by the time in 24-hour notation + '%T': '%H:%M:%S', // Replaced by the time + '%x': '%m/%d/%y', // Replaced by the locale's appropriate date representation + '%X': '%H:%M:%S', // Replaced by the locale's appropriate time representation + // Modified Conversion Specifiers + '%Ec': '%c', // Replaced by the locale's alternative appropriate date and time representation. + '%EC': '%C', // Replaced by the name of the base year (period) in the locale's alternative representation. + '%Ex': '%m/%d/%y', // Replaced by the locale's alternative date representation. + '%EX': '%H:%M:%S', // Replaced by the locale's alternative time representation. + '%Ey': '%y', // Replaced by the offset from %EC (year only) in the locale's alternative representation. + '%EY': '%Y', // Replaced by the full alternative year representation. + '%Od': '%d', // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading zeros if there is any alternative symbol for zero; otherwise, with leading characters. + '%Oe': '%e', // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading characters. + '%OH': '%H', // Replaced by the hour (24-hour clock) using the locale's alternative numeric symbols. + '%OI': '%I', // Replaced by the hour (12-hour clock) using the locale's alternative numeric symbols. + '%Om': '%m', // Replaced by the month using the locale's alternative numeric symbols. + '%OM': '%M', // Replaced by the minutes using the locale's alternative numeric symbols. + '%OS': '%S', // Replaced by the seconds using the locale's alternative numeric symbols. + '%Ou': '%u', // Replaced by the weekday as a number in the locale's alternative representation (Monday=1). + '%OU': '%U', // Replaced by the week number of the year (Sunday as the first day of the week, rules corresponding to %U ) using the locale's alternative numeric symbols. + '%OV': '%V', // Replaced by the week number of the year (Monday as the first day of the week, rules corresponding to %V ) using the locale's alternative numeric symbols. + '%Ow': '%w', // Replaced by the number of the weekday (Sunday=0) using the locale's alternative numeric symbols. + '%OW': '%W', // Replaced by the week number of the year (Monday as the first day of the week) using the locale's alternative numeric symbols. + '%Oy': '%y', // Replaced by the year (offset from %C ) using the locale's alternative numeric symbols. + }; + for (var rule in EXPANSION_RULES_1) { + pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_1[rule]); + } + + var WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; + var MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + + function leadingSomething(value, digits, character) { + var str = typeof value == 'number' ? value.toString() : (value || ''); + while (str.length < digits) { + str = character[0]+str; + } + return str; + } + + function leadingNulls(value, digits) { + return leadingSomething(value, digits, '0'); + } + + function compareByDay(date1, date2) { + function sgn(value) { + return value < 0 ? -1 : (value > 0 ? 1 : 0); + } + + var compare; + if ((compare = sgn(date1.getFullYear()-date2.getFullYear())) === 0) { + if ((compare = sgn(date1.getMonth()-date2.getMonth())) === 0) { + compare = sgn(date1.getDate()-date2.getDate()); + } + } + return compare; + } + + function getFirstWeekStartDate(janFourth) { + switch (janFourth.getDay()) { + case 0: // Sunday + return new Date(janFourth.getFullYear()-1, 11, 29); + case 1: // Monday + return janFourth; + case 2: // Tuesday + return new Date(janFourth.getFullYear(), 0, 3); + case 3: // Wednesday + return new Date(janFourth.getFullYear(), 0, 2); + case 4: // Thursday + return new Date(janFourth.getFullYear(), 0, 1); + case 5: // Friday + return new Date(janFourth.getFullYear()-1, 11, 31); + case 6: // Saturday + return new Date(janFourth.getFullYear()-1, 11, 30); + } + } + + function getWeekBasedYear(date) { + var thisDate = addDays(new Date(date.tm_year+1900, 0, 1), date.tm_yday); + + var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4); + var janFourthNextYear = new Date(thisDate.getFullYear()+1, 0, 4); + + var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear); + var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear); + + if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) { + // this date is after the start of the first week of this year + if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) { + return thisDate.getFullYear()+1; + } + return thisDate.getFullYear(); + } + return thisDate.getFullYear()-1; + } + + var EXPANSION_RULES_2 = { + '%a': (date) => WEEKDAYS[date.tm_wday].substring(0,3) , + '%A': (date) => WEEKDAYS[date.tm_wday], + '%b': (date) => MONTHS[date.tm_mon].substring(0,3), + '%B': (date) => MONTHS[date.tm_mon], + '%C': (date) => { + var year = date.tm_year+1900; + return leadingNulls((year/100)|0,2); + }, + '%d': (date) => leadingNulls(date.tm_mday, 2), + '%e': (date) => leadingSomething(date.tm_mday, 2, ' '), + '%g': (date) => { + // %g, %G, and %V give values according to the ISO 8601:2000 standard week-based year. + // In this system, weeks begin on a Monday and week 1 of the year is the week that includes + // January 4th, which is also the week that includes the first Thursday of the year, and + // is also the first week that contains at least four days in the year. + // If the first Monday of January is the 2nd, 3rd, or 4th, the preceding days are part of + // the last week of the preceding year; thus, for Saturday 2nd January 1999, + // %G is replaced by 1998 and %V is replaced by 53. If December 29th, 30th, + // or 31st is a Monday, it and any following days are part of week 1 of the following year. + // Thus, for Tuesday 30th December 1997, %G is replaced by 1998 and %V is replaced by 01. + + return getWeekBasedYear(date).toString().substring(2); + }, + '%G': (date) => getWeekBasedYear(date), + '%H': (date) => leadingNulls(date.tm_hour, 2), + '%I': (date) => { + var twelveHour = date.tm_hour; + if (twelveHour == 0) twelveHour = 12; + else if (twelveHour > 12) twelveHour -= 12; + return leadingNulls(twelveHour, 2); + }, + '%j': (date) => { + // Day of the year (001-366) + return leadingNulls(date.tm_mday + arraySum(isLeapYear(date.tm_year+1900) ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, date.tm_mon-1), 3); + }, + '%m': (date) => leadingNulls(date.tm_mon+1, 2), + '%M': (date) => leadingNulls(date.tm_min, 2), + '%n': () => '\n', + '%p': (date) => { + if (date.tm_hour >= 0 && date.tm_hour < 12) { + return 'AM'; + } + return 'PM'; + }, + '%S': (date) => leadingNulls(date.tm_sec, 2), + '%t': () => '\t', + '%u': (date) => date.tm_wday || 7, + '%U': (date) => { + var days = date.tm_yday + 7 - date.tm_wday; + return leadingNulls(Math.floor(days / 7), 2); + }, + '%V': (date) => { + // Replaced by the week number of the year (Monday as the first day of the week) + // as a decimal number [01,53]. If the week containing 1 January has four + // or more days in the new year, then it is considered week 1. + // Otherwise, it is the last week of the previous year, and the next week is week 1. + // Both January 4th and the first Thursday of January are always in week 1. [ tm_year, tm_wday, tm_yday] + var val = Math.floor((date.tm_yday + 7 - (date.tm_wday + 6) % 7 ) / 7); + // If 1 Jan is just 1-3 days past Monday, the previous week + // is also in this year. + if ((date.tm_wday + 371 - date.tm_yday - 2) % 7 <= 2) { + val++; + } + if (!val) { + val = 52; + // If 31 December of prev year a Thursday, or Friday of a + // leap year, then the prev year has 53 weeks. + var dec31 = (date.tm_wday + 7 - date.tm_yday - 1) % 7; + if (dec31 == 4 || (dec31 == 5 && isLeapYear(date.tm_year%400-1))) { + val++; + } + } else if (val == 53) { + // If 1 January is not a Thursday, and not a Wednesday of a + // leap year, then this year has only 52 weeks. + var jan1 = (date.tm_wday + 371 - date.tm_yday) % 7; + if (jan1 != 4 && (jan1 != 3 || !isLeapYear(date.tm_year))) + val = 1; + } + return leadingNulls(val, 2); + }, + '%w': (date) => date.tm_wday, + '%W': (date) => { + var days = date.tm_yday + 7 - ((date.tm_wday + 6) % 7); + return leadingNulls(Math.floor(days / 7), 2); + }, + '%y': (date) => { + // Replaced by the last two digits of the year as a decimal number [00,99]. [ tm_year] + return (date.tm_year+1900).toString().substring(2); + }, + // Replaced by the year as a decimal number (for example, 1997). [ tm_year] + '%Y': (date) => date.tm_year+1900, + '%z': (date) => { + // Replaced by the offset from UTC in the ISO 8601:2000 standard format ( +hhmm or -hhmm ). + // For example, "-0430" means 4 hours 30 minutes behind UTC (west of Greenwich). + var off = date.tm_gmtoff; + var ahead = off >= 0; + off = Math.abs(off) / 60; + // convert from minutes into hhmm format (which means 60 minutes = 100 units) + off = (off / 60)*100 + (off % 60); + return (ahead ? '+' : '-') + String("0000" + off).slice(-4); + }, + '%Z': (date) => date.tm_zone, + '%%': () => '%' + }; + + // Replace %% with a pair of NULLs (which cannot occur in a C string), then + // re-inject them after processing. + pattern = pattern.replace(/%%/g, '\0\0') + for (var rule in EXPANSION_RULES_2) { + if (pattern.includes(rule)) { + pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_2[rule](date)); + } + } + pattern = pattern.replace(/\0\0/g, '%') + + var bytes = intArrayFromString(pattern, false); + if (bytes.length > maxsize) { + return 0; + } + + writeArrayToMemory(bytes, s); + return bytes.length-1; + }; + + + + + + + + + var _strptime = (buf, format, tm) => { + // char *strptime(const char *restrict buf, const char *restrict format, struct tm *restrict tm); + // http://pubs.opengroup.org/onlinepubs/009695399/functions/strptime.html + var pattern = UTF8ToString(format); + + // escape special characters + // TODO: not sure we really need to escape all of these in JS regexps + var SPECIAL_CHARS = '\\!@#$^&*()+=-[]/{}|:<>?,.'; + for (var i=0, ii=SPECIAL_CHARS.length; i=0; i=pattern.indexOf('%')) { + capture.push(pattern[i+1]); + pattern = pattern.replace(new RegExp('\\%'+pattern[i+1], 'g'), ''); + } + + var matches = new RegExp('^'+pattern, "i").exec(UTF8ToString(buf)) + // out(UTF8ToString(buf)+ ' is matched by '+((new RegExp('^'+pattern)).source)+' into: '+JSON.stringify(matches)); + + function initDate() { + function fixup(value, min, max) { + return (typeof value != 'number' || isNaN(value)) ? min : (value>=min ? (value<=max ? value: max): min); + }; + return { + year: fixup(HEAP32[(((tm)+(20))>>2)] + 1900 , 1970, 9999), + month: fixup(HEAP32[(((tm)+(16))>>2)], 0, 11), + day: fixup(HEAP32[(((tm)+(12))>>2)], 1, 31), + hour: fixup(HEAP32[(((tm)+(8))>>2)], 0, 23), + min: fixup(HEAP32[(((tm)+(4))>>2)], 0, 59), + sec: fixup(HEAP32[((tm)>>2)], 0, 59) + }; + }; + + if (matches) { + var date = initDate(); + var value; + + var getMatch = (symbol) => { + var pos = capture.indexOf(symbol); + // check if symbol appears in regexp + if (pos >= 0) { + // return matched value or null (falsy!) for non-matches + return matches[pos+1]; + } + return; + }; + + // seconds + if ((value=getMatch('S'))) { + date.sec = jstoi_q(value); + } + + // minutes + if ((value=getMatch('M'))) { + date.min = jstoi_q(value); + } + + // hours + if ((value=getMatch('H'))) { + // 24h clock + date.hour = jstoi_q(value); + } else if ((value = getMatch('I'))) { + // AM/PM clock + var hour = jstoi_q(value); + if ((value=getMatch('p'))) { + hour += value.toUpperCase()[0] === 'P' ? 12 : 0; + } + date.hour = hour; + } + + // year + if ((value=getMatch('Y'))) { + // parse from four-digit year + date.year = jstoi_q(value); + } else if ((value=getMatch('y'))) { + // parse from two-digit year... + var year = jstoi_q(value); + if ((value=getMatch('C'))) { + // ...and century + year += jstoi_q(value)*100; + } else { + // ...and rule-of-thumb + year += year<69 ? 2000 : 1900; + } + date.year = year; + } + + // month + if ((value=getMatch('m'))) { + // parse from month number + date.month = jstoi_q(value)-1; + } else if ((value=getMatch('b'))) { + // parse from month name + date.month = MONTH_NUMBERS[value.substring(0,3).toUpperCase()] || 0; + // TODO: derive month from day in year+year, week number+day of week+year + } + + // day + if ((value=getMatch('d'))) { + // get day of month directly + date.day = jstoi_q(value); + } else if ((value=getMatch('j'))) { + // get day of month from day of year ... + var day = jstoi_q(value); + var leapYear = isLeapYear(date.year); + for (var month=0; month<12; ++month) { + var daysUntilMonth = arraySum(leapYear ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, month-1); + if (day<=daysUntilMonth+(leapYear ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR)[month]) { + date.day = day-daysUntilMonth; + } + } + } else if ((value=getMatch('a'))) { + // get day of month from weekday ... + var weekDay = value.substring(0,3).toUpperCase(); + if ((value=getMatch('U'))) { + // ... and week number (Sunday being first day of week) + // Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. + // All days in a new year preceding the first Sunday are considered to be in week 0. + var weekDayNumber = DAY_NUMBERS_SUN_FIRST[weekDay]; + var weekNumber = jstoi_q(value); + + // January 1st + var janFirst = new Date(date.year, 0, 1); + var endDate; + if (janFirst.getDay() === 0) { + // Jan 1st is a Sunday, and, hence in the 1st CW + endDate = addDays(janFirst, weekDayNumber+7*(weekNumber-1)); + } else { + // Jan 1st is not a Sunday, and, hence still in the 0th CW + endDate = addDays(janFirst, 7-janFirst.getDay()+weekDayNumber+7*(weekNumber-1)); + } + date.day = endDate.getDate(); + date.month = endDate.getMonth(); + } else if ((value=getMatch('W'))) { + // ... and week number (Monday being first day of week) + // Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. + // All days in a new year preceding the first Monday are considered to be in week 0. + var weekDayNumber = DAY_NUMBERS_MON_FIRST[weekDay]; + var weekNumber = jstoi_q(value); + + // January 1st + var janFirst = new Date(date.year, 0, 1); + var endDate; + if (janFirst.getDay()===1) { + // Jan 1st is a Monday, and, hence in the 1st CW + endDate = addDays(janFirst, weekDayNumber+7*(weekNumber-1)); + } else { + // Jan 1st is not a Monday, and, hence still in the 0th CW + endDate = addDays(janFirst, 7-janFirst.getDay()+1+weekDayNumber+7*(weekNumber-1)); + } + + date.day = endDate.getDate(); + date.month = endDate.getMonth(); + } + } + + /* + tm_sec int seconds after the minute 0-61* + tm_min int minutes after the hour 0-59 + tm_hour int hours since midnight 0-23 + tm_mday int day of the month 1-31 + tm_mon int months since January 0-11 + tm_year int years since 1900 + tm_wday int days since Sunday 0-6 + tm_yday int days since January 1 0-365 + tm_isdst int Daylight Saving Time flag + */ + + var fullDate = new Date(date.year, date.month, date.day, date.hour, date.min, date.sec, 0); + HEAP32[((tm)>>2)] = fullDate.getSeconds(); + HEAP32[(((tm)+(4))>>2)] = fullDate.getMinutes(); + HEAP32[(((tm)+(8))>>2)] = fullDate.getHours(); + HEAP32[(((tm)+(12))>>2)] = fullDate.getDate(); + HEAP32[(((tm)+(16))>>2)] = fullDate.getMonth(); + HEAP32[(((tm)+(20))>>2)] = fullDate.getFullYear()-1900; + HEAP32[(((tm)+(24))>>2)] = fullDate.getDay(); + HEAP32[(((tm)+(28))>>2)] = arraySum(isLeapYear(fullDate.getFullYear()) ? MONTH_DAYS_LEAP : MONTH_DAYS_REGULAR, fullDate.getMonth()-1)+fullDate.getDate()-1; + HEAP32[(((tm)+(32))>>2)] = 0; + + // we need to convert the matched sequence into an integer array to take care of UTF-8 characters > 0x7F + // TODO: not sure that intArrayFromString handles all unicode characters correctly + return buf+intArrayFromString(matches[0]).length-1; + } + + return 0; + }; + + function _wasm_poll_socket(socketd, events, timeout) { + if (typeof Asyncify === 'undefined') { + return 0; + } + + const POLLIN = 0x0001; /* There is data to read */ + const POLLPRI = 0x0002; /* There is urgent data to read */ + const POLLOUT = 0x0004; /* Writing now will not block */ + const POLLERR = 0x0008; /* Error condition */ + const POLLHUP = 0x0010; /* Hung up */ + const POLLNVAL = 0x0020; /* Invalid request: fd not open */ + + return Asyncify.handleSleep((wakeUp) => { + const polls = []; + if (socketd in PHPWASM.child_proc_by_fd) { + // This is a child process-related socket. + const procInfo = PHPWASM.child_proc_by_fd[socketd]; + if (procInfo.exited) { + wakeUp(0); + return; + } + polls.push(PHPWASM.awaitEvent(procInfo.stdout, 'data')); + } else { + // This is, most likely, a websocket. Let's make sure. + const sock = getSocketFromFD(socketd); + if (!sock) { + wakeUp(0); + return; + } + const lookingFor = new Set(); + + if (events & POLLIN || events & POLLPRI) { + if (sock.server) { + for (const client of sock.pending) { + if ((client.recv_queue || []).length > 0) { + wakeUp(1); + return; + } + } + } else if ((sock.recv_queue || []).length > 0) { + wakeUp(1); + return; + } + } + + const webSockets = PHPWASM.getAllWebSockets(sock); + if (!webSockets.length) { + wakeUp(0); + return; + } + for (const ws of webSockets) { + if (events & POLLIN || events & POLLPRI) { + polls.push(PHPWASM.awaitData(ws)); + lookingFor.add('POLLIN'); + } + if (events & POLLOUT) { + polls.push(PHPWASM.awaitConnection(ws)); + lookingFor.add('POLLOUT'); + } + if (events & POLLHUP) { + polls.push(PHPWASM.awaitClose(ws)); + lookingFor.add('POLLHUP'); + } + if (events & POLLERR || events & POLLNVAL) { + polls.push(PHPWASM.awaitError(ws)); + lookingFor.add('POLLERR'); + } + } + } + if (polls.length === 0) { + console.warn( + 'Unsupported poll event ' + + events + + ', defaulting to setTimeout().' + ); + setTimeout(function () { + wakeUp(0); + }, timeout); + return; + } + + const promises = polls.map(([promise]) => promise); + const clearPolling = () => polls.forEach(([, clear]) => clear()); + let awaken = false; + let timeoutId; + Promise.race(promises).then(function (results) { + if (!awaken) { + awaken = true; + wakeUp(1); + if (timeoutId) { + clearTimeout(timeoutId); + } + clearPolling(); + } + }); + + if (timeout !== -1) { + timeoutId = setTimeout(function () { + if (!awaken) { + awaken = true; + wakeUp(0); + clearPolling(); + } + }, timeout); + } + }); + } + + function _wasm_setsockopt( + socketd, + level, + optionName, + optionValuePtr, + optionLen + ) { + const optionValue = HEAPU8[optionValuePtr]; + const SOL_SOCKET = 1; + const SO_KEEPALIVE = 9; + const IPPROTO_TCP = 6; + const TCP_NODELAY = 1; + const isSupported = + (level === SOL_SOCKET && optionName === SO_KEEPALIVE) || + (level === IPPROTO_TCP && optionName === TCP_NODELAY); + if (!isSupported) { + console.warn( + `Unsupported socket option: ${level}, ${optionName}, ${optionValue}` + ); + return -1; + } + const ws = PHPWASM.getAllWebSockets(socketd)[0]; + if (!ws) { + return -1; + } + ws.setSocketOpt(level, optionName, optionValuePtr); + return 0; + } + + var wasmTableMirror = []; + var getWasmTableEntry = (funcPtr) => { + var func = wasmTableMirror[funcPtr]; + if (!func) { + if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1; + wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr); + } + return func; + }; + + + function runAndAbortIfError(func) { + try { + return func(); + } catch (e) { + abort(e); + } + } + + + function sigToWasmTypes(sig) { + var typeNames = { + 'i': 'i32', + 'j': 'i64', + 'f': 'f32', + 'd': 'f64', + 'p': 'i32', + }; + var type = { + parameters: [], + results: sig[0] == 'v' ? [] : [typeNames[sig[0]]] + }; + for (var i = 1; i < sig.length; ++i) { + type.parameters.push(typeNames[sig[i]]); + } + return type; + } + + + + + + + var Asyncify = { + instrumentWasmImports:function(imports) { + var importPatterns = [/^_dlopen_js$/,/^invoke_i$/,/^invoke_ii$/,/^invoke_iii$/,/^invoke_iiii$/,/^invoke_iiiii$/,/^invoke_iiiiii$/,/^invoke_iiiiiii$/,/^invoke_iiiiiiii$/,/^invoke_iiiiiiiiii$/,/^invoke_v$/,/^invoke_vi$/,/^invoke_vii$/,/^invoke_viidii$/,/^invoke_viii$/,/^invoke_viiii$/,/^invoke_viiiii$/,/^invoke_viiiiii$/,/^invoke_viiiiiii$/,/^invoke_viiiiiiiii$/,/^js_open_process$/,/^js_popen_to_file$/,/^js_fd_read$/,/^js_module_onMessage$/,/^js_waitpid$/,/^wasm_poll_socket$/,/^wasm_shutdown$/,/^fd_sync$/,/^__wasi_fd_sync$/,/^__asyncjs__.*$/,/^emscripten_promise_await$/,/^emscripten_idb_load$/,/^emscripten_idb_store$/,/^emscripten_idb_delete$/,/^emscripten_idb_exists$/,/^emscripten_idb_load_blob$/,/^emscripten_idb_store_blob$/,/^emscripten_sleep$/,/^emscripten_wget_data$/,/^emscripten_scan_registers$/,/^emscripten_lazy_load_code$/,/^_load_secondary_module$/,/^emscripten_fiber_swap$/,/^SDL_Delay$/]; + + for (var x in imports) { + (function(x) { + var original = imports[x]; + var sig = original.sig; + if (typeof original == 'function') { + var isAsyncifyImport = original.isAsync || + importPatterns.some(pattern => !!x.match(pattern)); + } + })(x); + } + }, + instrumentWasmExports:function(exports) { + var ret = {}; + for (var x in exports) { + (function(x) { + var original = exports[x]; + if (typeof original == 'function') { + ret[x] = function() { + Asyncify.exportCallStack.push(x); + try { + return original.apply(null, arguments); + } finally { + if (!ABORT) { + var y = Asyncify.exportCallStack.pop(); + assert(y === x); + Asyncify.maybeStopUnwind(); + } + } + }; + } else { + ret[x] = original; + } + })(x); + } + return ret; + }, + State:{ + Normal:0, + Unwinding:1, + Rewinding:2, + Disabled:3, + }, + state:0, + StackSize:4096, + currData:null, + handleSleepReturnValue:0, + exportCallStack:[], + callStackNameToId:{ + }, + callStackIdToName:{ + }, + callStackId:0, + asyncPromiseHandlers:null, + sleepCallbacks:[], + getCallStackId:function(funcName) { + var id = Asyncify.callStackNameToId[funcName]; + if (id === undefined) { + id = Asyncify.callStackId++; + Asyncify.callStackNameToId[funcName] = id; + Asyncify.callStackIdToName[id] = funcName; + } + return id; + }, + maybeStopUnwind:function() { + if (Asyncify.currData && + Asyncify.state === Asyncify.State.Unwinding && + Asyncify.exportCallStack.length === 0) { + // We just finished unwinding. + // Be sure to set the state before calling any other functions to avoid + // possible infinite recursion here (For example in debug pthread builds + // the dbg() function itself can call back into WebAssembly to get the + // current pthread_self() pointer). + Asyncify.state = Asyncify.State.Normal; + runtimeKeepalivePush(); + // Keep the runtime alive so that a re-wind can be done later. + runAndAbortIfError(_asyncify_stop_unwind); + if (typeof Fibers != 'undefined') { + Fibers.trampoline(); + } + } + }, + whenDone:function() { + return new Promise((resolve, reject) => { + Asyncify.asyncPromiseHandlers = { resolve, reject }; + }); + }, + allocateData:function() { + // An asyncify data structure has three fields: + // 0 current stack pos + // 4 max stack pos + // 8 id of function at bottom of the call stack (callStackIdToName[id] == name of js function) + // + // The Asyncify ABI only interprets the first two fields, the rest is for the runtime. + // We also embed a stack in the same memory region here, right next to the structure. + // This struct is also defined as asyncify_data_t in emscripten/fiber.h + var ptr = _malloc(12 + Asyncify.StackSize); + Asyncify.setDataHeader(ptr, ptr + 12, Asyncify.StackSize); + Asyncify.setDataRewindFunc(ptr); + return ptr; + }, + setDataHeader:function(ptr, stack, stackSize) { + HEAP32[((ptr)>>2)] = stack; + HEAP32[(((ptr)+(4))>>2)] = stack + stackSize; + }, + setDataRewindFunc:function(ptr) { + var bottomOfCallStack = Asyncify.exportCallStack[0]; + var rewindId = Asyncify.getCallStackId(bottomOfCallStack); + HEAP32[(((ptr)+(8))>>2)] = rewindId; + }, + getDataRewindFunc:function(ptr) { + var id = HEAP32[(((ptr)+(8))>>2)]; + var name = Asyncify.callStackIdToName[id]; + var func = Module['asm'][name]; + return func; + }, + doRewind:function(ptr) { + var start = Asyncify.getDataRewindFunc(ptr); + // Once we have rewound and the stack we no longer need to artificially + // keep the runtime alive. + runtimeKeepalivePop(); + return start(); + }, + handleSleep:function(startAsync) { + if (ABORT) return; + if (Asyncify.state === Asyncify.State.Normal) { + // Prepare to sleep. Call startAsync, and see what happens: + // if the code decided to call our callback synchronously, + // then no async operation was in fact begun, and we don't + // need to do anything. + var reachedCallback = false; + var reachedAfterCallback = false; + startAsync((handleSleepReturnValue = 0) => { + if (ABORT) return; + Asyncify.handleSleepReturnValue = handleSleepReturnValue; + reachedCallback = true; + if (!reachedAfterCallback) { + // We are happening synchronously, so no need for async. + return; + } + Asyncify.state = Asyncify.State.Rewinding; + runAndAbortIfError(() => _asyncify_start_rewind(Asyncify.currData)); + if (typeof Browser != 'undefined' && Browser.mainLoop.func) { + Browser.mainLoop.resume(); + } + var asyncWasmReturnValue, isError = false; + try { + asyncWasmReturnValue = Asyncify.doRewind(Asyncify.currData); + } catch (err) { + asyncWasmReturnValue = err; + isError = true; + } + // Track whether the return value was handled by any promise handlers. + var handled = false; + if (!Asyncify.currData) { + // All asynchronous execution has finished. + // `asyncWasmReturnValue` now contains the final + // return value of the exported async WASM function. + // + // Note: `asyncWasmReturnValue` is distinct from + // `Asyncify.handleSleepReturnValue`. + // `Asyncify.handleSleepReturnValue` contains the return + // value of the last C function to have executed + // `Asyncify.handleSleep()`, where as `asyncWasmReturnValue` + // contains the return value of the exported WASM function + // that may have called C functions that + // call `Asyncify.handleSleep()`. + var asyncPromiseHandlers = Asyncify.asyncPromiseHandlers; + if (asyncPromiseHandlers) { + Asyncify.asyncPromiseHandlers = null; + (isError ? asyncPromiseHandlers.reject : asyncPromiseHandlers.resolve)(asyncWasmReturnValue); + handled = true; + } + } + if (isError && !handled) { + // If there was an error and it was not handled by now, we have no choice but to + // rethrow that error into the global scope where it can be caught only by + // `onerror` or `onunhandledpromiserejection`. + throw asyncWasmReturnValue; + } + }); + reachedAfterCallback = true; + if (!reachedCallback) { + // A true async operation was begun; start a sleep. + Asyncify.state = Asyncify.State.Unwinding; + // TODO: reuse, don't alloc/free every sleep + Asyncify.currData = Asyncify.allocateData(); + if (typeof Browser != 'undefined' && Browser.mainLoop.func) { + Browser.mainLoop.pause(); + } + runAndAbortIfError(() => _asyncify_start_unwind(Asyncify.currData)); + } + } else if (Asyncify.state === Asyncify.State.Rewinding) { + // Stop a resume. + Asyncify.state = Asyncify.State.Normal; + runAndAbortIfError(_asyncify_stop_rewind); + _free(Asyncify.currData); + Asyncify.currData = null; + // Call all sleep callbacks now that the sleep-resume is all done. + Asyncify.sleepCallbacks.forEach((func) => callUserCallback(func)); + } else { + abort(`invalid state: ${Asyncify.state}`); + } + return Asyncify.handleSleepReturnValue; + }, + handleAsync:function(startAsync) { + return Asyncify.handleSleep((wakeUp) => { + // TODO: add error handling as a second param when handleSleep implements it. + startAsync().then(wakeUp); + }); + }, + }; + + function getCFunc(ident) { + var func = Module['_' + ident]; // closure exported function + return func; + } + + + + + + + /** + * @param {string|null=} returnType + * @param {Array=} argTypes + * @param {Arguments|Array=} args + * @param {Object=} opts + */ + var ccall = function(ident, returnType, argTypes, args, opts) { + // For fast lookup of conversion functions + var toC = { + 'string': (str) => { + var ret = 0; + if (str !== null && str !== undefined && str !== 0) { // null string + // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0' + ret = stringToUTF8OnStack(str); + } + return ret; + }, + 'array': (arr) => { + var ret = stackAlloc(arr.length); + writeArrayToMemory(arr, ret); + return ret; + } + }; + + function convertReturnValue(ret) { + if (returnType === 'string') { + + return UTF8ToString(ret); + } + if (returnType === 'boolean') return Boolean(ret); + return ret; + } + + var func = getCFunc(ident); + var cArgs = []; + var stack = 0; + if (args) { + for (var i = 0; i < args.length; i++) { + var converter = toC[argTypes[i]]; + if (converter) { + if (stack === 0) stack = stackSave(); + cArgs[i] = converter(args[i]); + } else { + cArgs[i] = args[i]; + } + } + } + // Data for a previous async operation that was in flight before us. + var previousAsync = Asyncify.currData; + var ret = func.apply(null, cArgs); + function onDone(ret) { + runtimeKeepalivePop(); + if (stack !== 0) stackRestore(stack); + return convertReturnValue(ret); + } + var asyncMode = opts && opts.async; + + // Keep the runtime alive through all calls. Note that this call might not be + // async, but for simplicity we push and pop in all calls. + runtimeKeepalivePush(); + if (Asyncify.currData != previousAsync) { + // This is a new async operation. The wasm is paused and has unwound its stack. + // We need to return a Promise that resolves the return value + // once the stack is rewound and execution finishes. + return Asyncify.whenDone().then(onDone); + } + + ret = onDone(ret); + // If this is an async ccall, ensure we return a promise + if (asyncMode) return Promise.resolve(ret); + return ret; + }; + + + + var FSNode = /** @constructor */ function(parent, name, mode, rdev) { + if (!parent) { + parent = this; // root node sets parent to itself + } + this.parent = parent; + this.mount = parent.mount; + this.mounted = null; + this.id = FS.nextInode++; + this.name = name; + this.mode = mode; + this.node_ops = {}; + this.stream_ops = {}; + this.rdev = rdev; + }; + var readMode = 292/*292*/ | 73/*73*/; + var writeMode = 146/*146*/; + Object.defineProperties(FSNode.prototype, { + read: { + get: /** @this{FSNode} */function() { + return (this.mode & readMode) === readMode; + }, + set: /** @this{FSNode} */function(val) { + val ? this.mode |= readMode : this.mode &= ~readMode; + } + }, + write: { + get: /** @this{FSNode} */function() { + return (this.mode & writeMode) === writeMode; + }, + set: /** @this{FSNode} */function(val) { + val ? this.mode |= writeMode : this.mode &= ~writeMode; + } + }, + isFolder: { + get: /** @this{FSNode} */function() { + return FS.isDir(this.mode); + } + }, + isDevice: { + get: /** @this{FSNode} */function() { + return FS.isChrdev(this.mode); + } + } + }); + FS.FSNode = FSNode; + FS.createPreloadedFile = FS_createPreloadedFile; + FS.staticInit();Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_unlink"] = FS.unlink;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createDevice"] = FS.createDevice;; +ERRNO_CODES = { + 'EPERM': 63, + 'ENOENT': 44, + 'ESRCH': 71, + 'EINTR': 27, + 'EIO': 29, + 'ENXIO': 60, + 'E2BIG': 1, + 'ENOEXEC': 45, + 'EBADF': 8, + 'ECHILD': 12, + 'EAGAIN': 6, + 'EWOULDBLOCK': 6, + 'ENOMEM': 48, + 'EACCES': 2, + 'EFAULT': 21, + 'ENOTBLK': 105, + 'EBUSY': 10, + 'EEXIST': 20, + 'EXDEV': 75, + 'ENODEV': 43, + 'ENOTDIR': 54, + 'EISDIR': 31, + 'EINVAL': 28, + 'ENFILE': 41, + 'EMFILE': 33, + 'ENOTTY': 59, + 'ETXTBSY': 74, + 'EFBIG': 22, + 'ENOSPC': 51, + 'ESPIPE': 70, + 'EROFS': 69, + 'EMLINK': 34, + 'EPIPE': 64, + 'EDOM': 18, + 'ERANGE': 68, + 'ENOMSG': 49, + 'EIDRM': 24, + 'ECHRNG': 106, + 'EL2NSYNC': 156, + 'EL3HLT': 107, + 'EL3RST': 108, + 'ELNRNG': 109, + 'EUNATCH': 110, + 'ENOCSI': 111, + 'EL2HLT': 112, + 'EDEADLK': 16, + 'ENOLCK': 46, + 'EBADE': 113, + 'EBADR': 114, + 'EXFULL': 115, + 'ENOANO': 104, + 'EBADRQC': 103, + 'EBADSLT': 102, + 'EDEADLOCK': 16, + 'EBFONT': 101, + 'ENOSTR': 100, + 'ENODATA': 116, + 'ETIME': 117, + 'ENOSR': 118, + 'ENONET': 119, + 'ENOPKG': 120, + 'EREMOTE': 121, + 'ENOLINK': 47, + 'EADV': 122, + 'ESRMNT': 123, + 'ECOMM': 124, + 'EPROTO': 65, + 'EMULTIHOP': 36, + 'EDOTDOT': 125, + 'EBADMSG': 9, + 'ENOTUNIQ': 126, + 'EBADFD': 127, + 'EREMCHG': 128, + 'ELIBACC': 129, + 'ELIBBAD': 130, + 'ELIBSCN': 131, + 'ELIBMAX': 132, + 'ELIBEXEC': 133, + 'ENOSYS': 52, + 'ENOTEMPTY': 55, + 'ENAMETOOLONG': 37, + 'ELOOP': 32, + 'EOPNOTSUPP': 138, + 'EPFNOSUPPORT': 139, + 'ECONNRESET': 15, + 'ENOBUFS': 42, + 'EAFNOSUPPORT': 5, + 'EPROTOTYPE': 67, + 'ENOTSOCK': 57, + 'ENOPROTOOPT': 50, + 'ESHUTDOWN': 140, + 'ECONNREFUSED': 14, + 'EADDRINUSE': 3, + 'ECONNABORTED': 13, + 'ENETUNREACH': 40, + 'ENETDOWN': 38, + 'ETIMEDOUT': 73, + 'EHOSTDOWN': 142, + 'EHOSTUNREACH': 23, + 'EINPROGRESS': 26, + 'EALREADY': 7, + 'EDESTADDRREQ': 17, + 'EMSGSIZE': 35, + 'EPROTONOSUPPORT': 66, + 'ESOCKTNOSUPPORT': 137, + 'EADDRNOTAVAIL': 4, + 'ENETRESET': 39, + 'EISCONN': 30, + 'ENOTCONN': 53, + 'ETOOMANYREFS': 141, + 'EUSERS': 136, + 'EDQUOT': 19, + 'ESTALE': 72, + 'ENOTSUP': 138, + 'ENOMEDIUM': 148, + 'EILSEQ': 25, + 'EOVERFLOW': 61, + 'ECANCELED': 11, + 'ENOTRECOVERABLE': 56, + 'EOWNERDEAD': 62, + 'ESTRPIPE': 135, + };; +PHPWASM.init();; +var wasmImports = { + __assert_fail: ___assert_fail, + __call_sighandler: ___call_sighandler, + __syscall_accept4: ___syscall_accept4, + __syscall_bind: ___syscall_bind, + __syscall_chdir: ___syscall_chdir, + __syscall_chmod: ___syscall_chmod, + __syscall_connect: ___syscall_connect, + __syscall_dup: ___syscall_dup, + __syscall_dup3: ___syscall_dup3, + __syscall_faccessat: ___syscall_faccessat, + __syscall_fallocate: ___syscall_fallocate, + __syscall_fchmod: ___syscall_fchmod, + __syscall_fchown32: ___syscall_fchown32, + __syscall_fchownat: ___syscall_fchownat, + __syscall_fcntl64: ___syscall_fcntl64, + __syscall_fdatasync: ___syscall_fdatasync, + __syscall_fstat64: ___syscall_fstat64, + __syscall_ftruncate64: ___syscall_ftruncate64, + __syscall_getcwd: ___syscall_getcwd, + __syscall_getdents64: ___syscall_getdents64, + __syscall_getpeername: ___syscall_getpeername, + __syscall_getsockname: ___syscall_getsockname, + __syscall_getsockopt: ___syscall_getsockopt, + __syscall_ioctl: ___syscall_ioctl, + __syscall_listen: ___syscall_listen, + __syscall_lstat64: ___syscall_lstat64, + __syscall_mkdirat: ___syscall_mkdirat, + __syscall_newfstatat: ___syscall_newfstatat, + __syscall_openat: ___syscall_openat, + __syscall_pipe: ___syscall_pipe, + __syscall_poll: ___syscall_poll, + __syscall_readlinkat: ___syscall_readlinkat, + __syscall_recvfrom: ___syscall_recvfrom, + __syscall_renameat: ___syscall_renameat, + __syscall_rmdir: ___syscall_rmdir, + __syscall_sendto: ___syscall_sendto, + __syscall_socket: ___syscall_socket, + __syscall_stat64: ___syscall_stat64, + __syscall_statfs64: ___syscall_statfs64, + __syscall_symlink: ___syscall_symlink, + __syscall_unlinkat: ___syscall_unlinkat, + __syscall_utimensat: ___syscall_utimensat, + _emscripten_get_now_is_monotonic: __emscripten_get_now_is_monotonic, + _emscripten_throw_longjmp: __emscripten_throw_longjmp, + _gmtime_js: __gmtime_js, + _localtime_js: __localtime_js, + _mktime_js: __mktime_js, + _mmap_js: __mmap_js, + _munmap_js: __munmap_js, + _setitimer_js: __setitimer_js, + _tzset_js: __tzset_js, + abort: _abort, + emscripten_date_now: _emscripten_date_now, + emscripten_get_heap_max: _emscripten_get_heap_max, + emscripten_get_now: _emscripten_get_now, + emscripten_memcpy_big: _emscripten_memcpy_big, + emscripten_resize_heap: _emscripten_resize_heap, + emscripten_sleep: _emscripten_sleep, + environ_get: _environ_get, + environ_sizes_get: _environ_sizes_get, + exit: _exit, + fd_close: _fd_close, + fd_fdstat_get: _fd_fdstat_get, + fd_read: _fd_read, + fd_seek: _fd_seek, + fd_write: _fd_write, + getaddrinfo: _getaddrinfo, + gethostbyaddr: _gethostbyaddr, + gethostbyname_r: _gethostbyname_r, + getloadavg: _getloadavg, + getnameinfo: _getnameinfo, + getprotobyname: _getprotobyname, + getprotobynumber: _getprotobynumber, + invoke_i: invoke_i, + invoke_ii: invoke_ii, + invoke_iii: invoke_iii, + invoke_iiii: invoke_iiii, + invoke_iiiii: invoke_iiiii, + invoke_iiiiii: invoke_iiiiii, + invoke_iiiiiii: invoke_iiiiiii, + invoke_iiiiiiii: invoke_iiiiiiii, + invoke_iiiiiiiiii: invoke_iiiiiiiiii, + invoke_jii: invoke_jii, + invoke_v: invoke_v, + invoke_vi: invoke_vi, + invoke_vii: invoke_vii, + invoke_viidii: invoke_viidii, + invoke_viii: invoke_viii, + invoke_viiii: invoke_viiii, + invoke_viiiii: invoke_viiiii, + invoke_viiiiii: invoke_viiiiii, + invoke_viiiiiiiii: invoke_viiiiiiiii, + js_create_input_device: _js_create_input_device, + js_fd_read: _js_fd_read, + js_module_onMessage: _js_module_onMessage, + js_open_process: _js_open_process, + js_popen_to_file: _js_popen_to_file, + js_process_status: _js_process_status, + js_waitpid: _js_waitpid, + proc_exit: _proc_exit, + strftime: _strftime, + strptime: _strptime, + wasm_poll_socket: _wasm_poll_socket, + wasm_setsockopt: _wasm_setsockopt +}; +var asm = createWasm(); +/** @type {function(...*):?} */ +var ___wasm_call_ctors = function() { + return (___wasm_call_ctors = Module['asm']['__wasm_call_ctors']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _free = function() { + return (_free = Module['asm']['free']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _memcpy = function() { + return (_memcpy = Module['asm']['memcpy']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _malloc = function() { + return (_malloc = Module['asm']['malloc']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var setTempRet0 = function() { + return (setTempRet0 = Module['asm']['setTempRet0']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var ___errno_location = function() { + return (___errno_location = Module['asm']['__errno_location']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_read = Module['_wasm_read'] = function() { + return (_wasm_read = Module['_wasm_read'] = Module['asm']['wasm_read']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _fflush = Module['_fflush'] = function() { + return (_fflush = Module['_fflush'] = Module['asm']['fflush']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_popen = Module['_wasm_popen'] = function() { + return (_wasm_popen = Module['_wasm_popen'] = Module['asm']['wasm_popen']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_php_exec = Module['_wasm_php_exec'] = function() { + return (_wasm_php_exec = Module['_wasm_php_exec'] = Module['asm']['wasm_php_exec']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _php_pollfd_for = Module['_php_pollfd_for'] = function() { + return (_php_pollfd_for = Module['_php_pollfd_for'] = Module['asm']['php_pollfd_for']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _htons = function() { + return (_htons = Module['asm']['htons']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _ntohs = function() { + return (_ntohs = Module['asm']['ntohs']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _htonl = function() { + return (_htonl = Module['asm']['htonl']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_sleep = Module['_wasm_sleep'] = function() { + return (_wasm_sleep = Module['_wasm_sleep'] = Module['asm']['wasm_sleep']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var ___wrap_select = Module['___wrap_select'] = function() { + return (___wrap_select = Module['___wrap_select'] = Module['asm']['__wrap_select']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_set_sapi_name = Module['_wasm_set_sapi_name'] = function() { + return (_wasm_set_sapi_name = Module['_wasm_set_sapi_name'] = Module['asm']['wasm_set_sapi_name']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_set_phpini_path = Module['_wasm_set_phpini_path'] = function() { + return (_wasm_set_phpini_path = Module['_wasm_set_phpini_path'] = Module['asm']['wasm_set_phpini_path']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_set_phpini_entries = Module['_wasm_set_phpini_entries'] = function() { + return (_wasm_set_phpini_entries = Module['_wasm_set_phpini_entries'] = Module['asm']['wasm_set_phpini_entries']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_add_SERVER_entry = Module['_wasm_add_SERVER_entry'] = function() { + return (_wasm_add_SERVER_entry = Module['_wasm_add_SERVER_entry'] = Module['asm']['wasm_add_SERVER_entry']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_add_ENV_entry = Module['_wasm_add_ENV_entry'] = function() { + return (_wasm_add_ENV_entry = Module['_wasm_add_ENV_entry'] = Module['asm']['wasm_add_ENV_entry']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_set_query_string = Module['_wasm_set_query_string'] = function() { + return (_wasm_set_query_string = Module['_wasm_set_query_string'] = Module['asm']['wasm_set_query_string']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_set_path_translated = Module['_wasm_set_path_translated'] = function() { + return (_wasm_set_path_translated = Module['_wasm_set_path_translated'] = Module['asm']['wasm_set_path_translated']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_set_skip_shebang = Module['_wasm_set_skip_shebang'] = function() { + return (_wasm_set_skip_shebang = Module['_wasm_set_skip_shebang'] = Module['asm']['wasm_set_skip_shebang']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_set_request_uri = Module['_wasm_set_request_uri'] = function() { + return (_wasm_set_request_uri = Module['_wasm_set_request_uri'] = Module['asm']['wasm_set_request_uri']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_set_request_method = Module['_wasm_set_request_method'] = function() { + return (_wasm_set_request_method = Module['_wasm_set_request_method'] = Module['asm']['wasm_set_request_method']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_set_request_host = Module['_wasm_set_request_host'] = function() { + return (_wasm_set_request_host = Module['_wasm_set_request_host'] = Module['asm']['wasm_set_request_host']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_set_content_type = Module['_wasm_set_content_type'] = function() { + return (_wasm_set_content_type = Module['_wasm_set_content_type'] = Module['asm']['wasm_set_content_type']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_set_request_body = Module['_wasm_set_request_body'] = function() { + return (_wasm_set_request_body = Module['_wasm_set_request_body'] = Module['asm']['wasm_set_request_body']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_set_content_length = Module['_wasm_set_content_length'] = function() { + return (_wasm_set_content_length = Module['_wasm_set_content_length'] = Module['asm']['wasm_set_content_length']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_set_cookies = Module['_wasm_set_cookies'] = function() { + return (_wasm_set_cookies = Module['_wasm_set_cookies'] = Module['asm']['wasm_set_cookies']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_set_php_code = Module['_wasm_set_php_code'] = function() { + return (_wasm_set_php_code = Module['_wasm_set_php_code'] = Module['asm']['wasm_set_php_code']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_set_request_port = Module['_wasm_set_request_port'] = function() { + return (_wasm_set_request_port = Module['_wasm_set_request_port'] = Module['asm']['wasm_set_request_port']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_sapi_request_shutdown = Module['_wasm_sapi_request_shutdown'] = function() { + return (_wasm_sapi_request_shutdown = Module['_wasm_sapi_request_shutdown'] = Module['asm']['wasm_sapi_request_shutdown']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _wasm_sapi_handle_request = Module['_wasm_sapi_handle_request'] = function() { + return (_wasm_sapi_handle_request = Module['_wasm_sapi_handle_request'] = Module['asm']['wasm_sapi_handle_request']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _php_wasm_init = Module['_php_wasm_init'] = function() { + return (_php_wasm_init = Module['_php_wasm_init'] = Module['asm']['php_wasm_init']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var ___funcs_on_exit = function() { + return (___funcs_on_exit = Module['asm']['__funcs_on_exit']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _emscripten_builtin_memalign = function() { + return (_emscripten_builtin_memalign = Module['asm']['emscripten_builtin_memalign']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var __emscripten_timeout = function() { + return (__emscripten_timeout = Module['asm']['_emscripten_timeout']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _setThrew = function() { + return (_setThrew = Module['asm']['setThrew']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _emscripten_stack_set_limits = function() { + return (_emscripten_stack_set_limits = Module['asm']['emscripten_stack_set_limits']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _emscripten_stack_get_base = function() { + return (_emscripten_stack_get_base = Module['asm']['emscripten_stack_get_base']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _emscripten_stack_get_end = function() { + return (_emscripten_stack_get_end = Module['asm']['emscripten_stack_get_end']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var stackSave = function() { + return (stackSave = Module['asm']['stackSave']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var stackRestore = function() { + return (stackRestore = Module['asm']['stackRestore']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var stackAlloc = function() { + return (stackAlloc = Module['asm']['stackAlloc']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiii = Module['dynCall_iiii'] = function() { + return (dynCall_iiii = Module['dynCall_iiii'] = Module['asm']['dynCall_iiii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_ii = Module['dynCall_ii'] = function() { + return (dynCall_ii = Module['dynCall_ii'] = Module['asm']['dynCall_ii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_vi = Module['dynCall_vi'] = function() { + return (dynCall_vi = Module['dynCall_vi'] = Module['asm']['dynCall_vi']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_viiiii = Module['dynCall_viiiii'] = function() { + return (dynCall_viiiii = Module['dynCall_viiiii'] = Module['asm']['dynCall_viiiii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iii = Module['dynCall_iii'] = function() { + return (dynCall_iii = Module['dynCall_iii'] = Module['asm']['dynCall_iii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiiii = Module['dynCall_iiiii'] = function() { + return (dynCall_iiiii = Module['dynCall_iiiii'] = Module['asm']['dynCall_iiiii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiiiiii = Module['dynCall_iiiiiii'] = function() { + return (dynCall_iiiiiii = Module['dynCall_iiiiiii'] = Module['asm']['dynCall_iiiiiii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiiiii = Module['dynCall_iiiiii'] = function() { + return (dynCall_iiiiii = Module['dynCall_iiiiii'] = Module['asm']['dynCall_iiiiii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_i = Module['dynCall_i'] = function() { + return (dynCall_i = Module['dynCall_i'] = Module['asm']['dynCall_i']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_vii = Module['dynCall_vii'] = function() { + return (dynCall_vii = Module['dynCall_vii'] = Module['asm']['dynCall_vii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_viii = Module['dynCall_viii'] = function() { + return (dynCall_viii = Module['dynCall_viii'] = Module['asm']['dynCall_viii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_viiii = Module['dynCall_viiii'] = function() { + return (dynCall_viiii = Module['dynCall_viiii'] = Module['asm']['dynCall_viiii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_viiiiiiii = Module['dynCall_viiiiiiii'] = function() { + return (dynCall_viiiiiiii = Module['dynCall_viiiiiiii'] = Module['asm']['dynCall_viiiiiiii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_v = Module['dynCall_v'] = function() { + return (dynCall_v = Module['dynCall_v'] = Module['asm']['dynCall_v']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_viiiiiiiii = Module['dynCall_viiiiiiiii'] = function() { + return (dynCall_viiiiiiiii = Module['dynCall_viiiiiiiii'] = Module['asm']['dynCall_viiiiiiiii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_viiiiiii = Module['dynCall_viiiiiii'] = function() { + return (dynCall_viiiiiii = Module['dynCall_viiiiiii'] = Module['asm']['dynCall_viiiiiii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_viiiiii = Module['dynCall_viiiiii'] = function() { + return (dynCall_viiiiii = Module['dynCall_viiiiii'] = Module['asm']['dynCall_viiiiii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiiiiiii = Module['dynCall_iiiiiiii'] = function() { + return (dynCall_iiiiiiii = Module['dynCall_iiiiiiii'] = Module['asm']['dynCall_iiiiiiii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiid = Module['dynCall_iiid'] = function() { + return (dynCall_iiid = Module['dynCall_iiid'] = Module['asm']['dynCall_iiid']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiiiiiiii = Module['dynCall_iiiiiiiii'] = function() { + return (dynCall_iiiiiiiii = Module['dynCall_iiiiiiiii'] = Module['asm']['dynCall_iiiiiiiii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiiiiiiiii = Module['dynCall_iiiiiiiiii'] = function() { + return (dynCall_iiiiiiiiii = Module['dynCall_iiiiiiiiii'] = Module['asm']['dynCall_iiiiiiiiii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiiij = Module['dynCall_iiiij'] = function() { + return (dynCall_iiiij = Module['dynCall_iiiij'] = Module['asm']['dynCall_iiiij']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_vijii = Module['dynCall_vijii'] = function() { + return (dynCall_vijii = Module['dynCall_vijii'] = Module['asm']['dynCall_vijii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iijj = Module['dynCall_iijj'] = function() { + return (dynCall_iijj = Module['dynCall_iijj'] = Module['asm']['dynCall_iijj']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iij = Module['dynCall_iij'] = function() { + return (dynCall_iij = Module['dynCall_iij'] = Module['asm']['dynCall_iij']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iijii = Module['dynCall_iijii'] = function() { + return (dynCall_iijii = Module['dynCall_iijii'] = Module['asm']['dynCall_iijii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiji = Module['dynCall_iiji'] = function() { + return (dynCall_iiji = Module['dynCall_iiji'] = Module['asm']['dynCall_iiji']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiiiiij = Module['dynCall_iiiiiij'] = function() { + return (dynCall_iiiiiij = Module['dynCall_iiiiiij'] = Module['asm']['dynCall_iiiiiij']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiij = Module['dynCall_iiij'] = function() { + return (dynCall_iiij = Module['dynCall_iiij'] = Module['asm']['dynCall_iiij']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_dii = Module['dynCall_dii'] = function() { + return (dynCall_dii = Module['dynCall_dii'] = Module['asm']['dynCall_dii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_jii = Module['dynCall_jii'] = function() { + return (dynCall_jii = Module['dynCall_jii'] = Module['asm']['dynCall_jii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_ji = Module['dynCall_ji'] = function() { + return (dynCall_ji = Module['dynCall_ji'] = Module['asm']['dynCall_ji']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_vid = Module['dynCall_vid'] = function() { + return (dynCall_vid = Module['dynCall_vid'] = Module['asm']['dynCall_vid']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_vij = Module['dynCall_vij'] = function() { + return (dynCall_vij = Module['dynCall_vij'] = Module['asm']['dynCall_vij']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_di = Module['dynCall_di'] = function() { + return (dynCall_di = Module['dynCall_di'] = Module['asm']['dynCall_di']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiiiijii = Module['dynCall_iiiiijii'] = function() { + return (dynCall_iiiiijii = Module['dynCall_iiiiijii'] = Module['asm']['dynCall_iiiiijii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_j = Module['dynCall_j'] = function() { + return (dynCall_j = Module['dynCall_j'] = Module['asm']['dynCall_j']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_jj = Module['dynCall_jj'] = function() { + return (dynCall_jj = Module['dynCall_jj'] = Module['asm']['dynCall_jj']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_jiij = Module['dynCall_jiij'] = function() { + return (dynCall_jiij = Module['dynCall_jiij'] = Module['asm']['dynCall_jiij']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiiiji = Module['dynCall_iiiiji'] = function() { + return (dynCall_iiiiji = Module['dynCall_iiiiji'] = Module['asm']['dynCall_iiiiji']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiiijii = Module['dynCall_iiiijii'] = function() { + return (dynCall_iiiijii = Module['dynCall_iiiijii'] = Module['asm']['dynCall_iiiijii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_ij = Module['dynCall_ij'] = function() { + return (dynCall_ij = Module['dynCall_ij'] = Module['asm']['dynCall_ij']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_viiji = Module['dynCall_viiji'] = function() { + return (dynCall_viiji = Module['dynCall_viiji'] = Module['asm']['dynCall_viiji']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_viijii = Module['dynCall_viijii'] = function() { + return (dynCall_viijii = Module['dynCall_viijii'] = Module['asm']['dynCall_viijii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiiiiiiiiii = Module['dynCall_iiiiiiiiiii'] = function() { + return (dynCall_iiiiiiiiiii = Module['dynCall_iiiiiiiiiii'] = Module['asm']['dynCall_iiiiiiiiiii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiiijji = Module['dynCall_iiiijji'] = function() { + return (dynCall_iiiijji = Module['dynCall_iiiijji'] = Module['asm']['dynCall_iiiijji']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_dd = Module['dynCall_dd'] = function() { + return (dynCall_dd = Module['dynCall_dd'] = Module['asm']['dynCall_dd']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_ddd = Module['dynCall_ddd'] = function() { + return (dynCall_ddd = Module['dynCall_ddd'] = Module['asm']['dynCall_ddd']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iidddd = Module['dynCall_iidddd'] = function() { + return (dynCall_iidddd = Module['dynCall_iidddd'] = Module['asm']['dynCall_iidddd']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_viidii = Module['dynCall_viidii'] = function() { + return (dynCall_viidii = Module['dynCall_viidii'] = Module['asm']['dynCall_viidii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_jiiji = Module['dynCall_jiiji'] = function() { + return (dynCall_jiiji = Module['dynCall_jiiji'] = Module['asm']['dynCall_jiiji']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_jiiiji = Module['dynCall_jiiiji'] = function() { + return (dynCall_jiiiji = Module['dynCall_jiiiji'] = Module['asm']['dynCall_jiiiji']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iiiji = Module['dynCall_iiiji'] = function() { + return (dynCall_iiiji = Module['dynCall_iiiji'] = Module['asm']['dynCall_iiiji']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_jiji = Module['dynCall_jiji'] = function() { + return (dynCall_jiji = Module['dynCall_jiji'] = Module['asm']['dynCall_jiji']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var dynCall_iidiiii = Module['dynCall_iidiiii'] = function() { + return (dynCall_iidiiii = Module['dynCall_iidiiii'] = Module['asm']['dynCall_iidiiii']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _asyncify_start_unwind = function() { + return (_asyncify_start_unwind = Module['asm']['asyncify_start_unwind']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _asyncify_stop_unwind = function() { + return (_asyncify_stop_unwind = Module['asm']['asyncify_stop_unwind']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _asyncify_start_rewind = function() { + return (_asyncify_start_rewind = Module['asm']['asyncify_start_rewind']).apply(null, arguments); +}; + +/** @type {function(...*):?} */ +var _asyncify_stop_rewind = function() { + return (_asyncify_stop_rewind = Module['asm']['asyncify_stop_rewind']).apply(null, arguments); +}; + + +function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6) { + var sp = stackSave(); + try { + return dynCall_iiiiiii(index,a1,a2,a3,a4,a5,a6); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_vi(index,a1) { + var sp = stackSave(); + try { + dynCall_vi(index,a1); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_iii(index,a1,a2) { + var sp = stackSave(); + try { + return dynCall_iii(index,a1,a2); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_iiiii(index,a1,a2,a3,a4) { + var sp = stackSave(); + try { + return dynCall_iiiii(index,a1,a2,a3,a4); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_ii(index,a1) { + var sp = stackSave(); + try { + return dynCall_ii(index,a1); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_iiii(index,a1,a2,a3) { + var sp = stackSave(); + try { + return dynCall_iiii(index,a1,a2,a3); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_viiii(index,a1,a2,a3,a4) { + var sp = stackSave(); + try { + dynCall_viiii(index,a1,a2,a3,a4); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9) { + var sp = stackSave(); + try { + return dynCall_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_vii(index,a1,a2) { + var sp = stackSave(); + try { + dynCall_vii(index,a1,a2); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_i(index) { + var sp = stackSave(); + try { + return dynCall_i(index); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_viii(index,a1,a2,a3) { + var sp = stackSave(); + try { + dynCall_viii(index,a1,a2,a3); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_v(index) { + var sp = stackSave(); + try { + dynCall_v(index); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6) { + var sp = stackSave(); + try { + dynCall_viiiiii(index,a1,a2,a3,a4,a5,a6); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_viiiii(index,a1,a2,a3,a4,a5) { + var sp = stackSave(); + try { + dynCall_viiiii(index,a1,a2,a3,a4,a5); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_viidii(index,a1,a2,a3,a4,a5) { + var sp = stackSave(); + try { + dynCall_viidii(index,a1,a2,a3,a4,a5); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_iiiiii(index,a1,a2,a3,a4,a5) { + var sp = stackSave(); + try { + return dynCall_iiiiii(index,a1,a2,a3,a4,a5); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9) { + var sp = stackSave(); + try { + dynCall_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7) { + var sp = stackSave(); + try { + return dynCall_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + +function invoke_jii(index,a1,a2) { + var sp = stackSave(); + try { + return dynCall_jii(index,a1,a2); + } catch(e) { + stackRestore(sp); + if (e !== e+0) throw e; + _setThrew(1, 0); + } +} + + +// include: postamble.js +// === Auto-generated postamble setup entry stuff === + +// include: base64Utils.js +// Converts a string of base64 into a byte array. +// Throws error on invalid input. +function intArrayFromBase64(s) { + + try { + var decoded = atob(s); + var bytes = new Uint8Array(decoded.length); + for (var i = 0 ; i < decoded.length ; ++i) { + bytes[i] = decoded.charCodeAt(i); + } + return bytes; + } catch (_) { + throw new Error('Converting base64 string to bytes failed.'); + } +} + +// If filename is a base64 data URI, parses and returns data (Buffer on node, +// Uint8Array otherwise). If filename is not a base64 data URI, returns undefined. +function tryParseAsDataURI(filename) { + if (!isDataURI(filename)) { + return; + } + + return intArrayFromBase64(filename.slice(dataURIPrefix.length)); +} +// end include: base64Utils.js +Module['addRunDependency'] = addRunDependency; +Module['removeRunDependency'] = removeRunDependency; +Module['FS_createPath'] = FS.createPath; +Module['FS_createDataFile'] = FS.createDataFile; +Module['FS_createLazyFile'] = FS.createLazyFile; +Module['FS_createDevice'] = FS.createDevice; +Module['FS_unlink'] = FS.unlink; +Module['ccall'] = ccall; +Module['FS_createPreloadedFile'] = FS.createPreloadedFile; +Module['PROXYFS'] = PROXYFS; + + +var calledRun; + +dependenciesFulfilled = function runCaller() { + // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) + if (!calledRun) run(); + if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled +}; + +function run() { + + if (runDependencies > 0) { + return; + } + + preRun(); + + // a preRun added a dependency, run will be called later + if (runDependencies > 0) { + return; + } + + function doRun() { + // run may have just been called through dependencies being fulfilled just in this very frame, + // or while the async setStatus time below was happening + if (calledRun) return; + calledRun = true; + Module['calledRun'] = true; + + if (ABORT) return; + + initRuntime(); + + if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized'](); + + postRun(); + } + + if (Module['setStatus']) { + Module['setStatus']('Running...'); + setTimeout(function() { + setTimeout(function() { + Module['setStatus'](''); + }, 1); + doRun(); + }, 1); + } else + { + doRun(); + } +} + +if (Module['preInit']) { + if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; + while (Module['preInit'].length > 0) { + Module['preInit'].pop()(); + } +} + +run(); + + +// end include: postamble.js /** * Emscripten resolves `localhost` to a random IP address. Let's * make it always resolve to 127.0.0.1. diff --git a/packages/php-wasm/web/src/lib/index.ts b/packages/php-wasm/web/src/lib/index.ts index 780062297a..cab6a78de2 100644 --- a/packages/php-wasm/web/src/lib/index.ts +++ b/packages/php-wasm/web/src/lib/index.ts @@ -2,7 +2,7 @@ export * from './api'; export type { WithAPIState as WithIsReady } from './api'; export type { PHPWebLoaderOptions } from './web-php'; -export { WebPHP } from './web-php'; +export { CAPem, WebPHP } from './web-php'; export { WebPHPEndpoint } from './web-php-endpoint'; export { getPHPLoaderModule } from './get-php-loader-module'; export { registerServiceWorker } from './register-service-worker'; diff --git a/packages/php-wasm/web/src/lib/web-php.ts b/packages/php-wasm/web/src/lib/web-php.ts index 27b976a236..3d8a256a81 100644 --- a/packages/php-wasm/web/src/lib/web-php.ts +++ b/packages/php-wasm/web/src/lib/web-php.ts @@ -8,6 +8,8 @@ import { } from '@php-wasm/universal'; import { EmscriptenDownloadMonitor } from '@php-wasm/progress'; import { getPHPLoaderModule } from './get-php-loader-module'; +import * as forge from 'node-forge'; +import { Certificate } from 'crypto'; export interface PHPWebLoaderOptions { emscriptenOptions?: EmscriptenOptions; @@ -28,6 +30,7 @@ const fakeWebsocket = () => { decorator: (WebSocketConstructor: any) => { return class FakeWebsocketConstructor extends WebSocketConstructor { constructor() { + console.log('Called constructor()!'); try { super(); } catch (e) { @@ -36,6 +39,7 @@ const fakeWebsocket = () => { } send() { + console.log('Called send()!'); return null; } }; @@ -44,6 +48,564 @@ const fakeWebsocket = () => { }; }; +async function generateKeys() { + const keyPair = await crypto.subtle.generateKey( + { + name: 'ECDH', + namedCurve: 'P-256', + }, + true, + ['deriveKey'] + ); + return keyPair; +} + +function createCertificate({ commonName }) { + // create certificate + var pki = forge.pki; + var keys = pki.rsa.generateKeyPair(2048); + var cert = pki.createCertificate(); + cert.publicKey = keys.publicKey; + // alternatively set public key from a csr + //cert.publicKey = csr.publicKey; + // NOTE: serialNumber is the hex encoded value of an ASN.1 INTEGER. + // Conforming CAs should ensure serialNumber is: + // - no more than 20 octets + // - non-negative (prefix a '00' if your value starts with a '1' bit) + cert.serialNumber = '01'; + cert.validity.notBefore = new Date(); + cert.validity.notAfter = new Date(); + cert.validity.notAfter.setFullYear( + cert.validity.notBefore.getFullYear() + 1 + ); + var attrs = [ + { + name: 'commonName', + value: commonName, + }, + { + name: 'countryName', + value: 'US', + }, + { + shortName: 'ST', + value: 'Virginia', + }, + { + name: 'localityName', + value: 'Blacksburg', + }, + { + name: 'organizationName', + value: 'Test', + }, + { + shortName: 'OU', + value: 'Test', + }, + ]; + cert.setSubject(attrs); + // alternatively set subject from a csr + //cert.setSubject(csr.subject.attributes); + cert.setIssuer(attrs); + cert.setExtensions([ + { + name: 'basicConstraints', + cA: true, + }, + { + name: 'keyUsage', + keyCertSign: true, + digitalSignature: true, + nonRepudiation: true, + keyEncipherment: true, + dataEncipherment: true, + }, + { + name: 'extKeyUsage', + serverAuth: true, + clientAuth: true, + codeSigning: true, + emailProtection: true, + timeStamping: true, + }, + { + name: 'nsCertType', + client: true, + server: true, + email: true, + objsign: true, + sslCA: true, + emailCA: true, + objCA: true, + }, + { + name: 'subjectAltName', + altNames: [ + { + type: 6, // URI + value: '*.org', + }, + { + type: 7, // IP + ip: '127.0.0.1', + }, + ], + }, + { + name: 'subjectKeyIdentifier', + }, + ]); + // FIXME: add subjectKeyIdentifier extension + // FIXME: add authorityKeyIdentifier extension + cert.publicKey = keys.publicKey; + + // self-sign certificate + cert.sign(keys.privateKey); + + // console.log('certificate created for \"' + forge.pki.certificateToPem(cert) + '\": \n' + forge.pki.privateKeyToPem(keys.privateKey)); + return { certificate: cert, privateKey: keys.privateKey }; +} + +// Introduce artificial delay to test the race +// condition when initializing the Playground client. +// for (let i = 0; i < 2; i++) { +// createCertificate(); +// } + +// @TODO: Create these certificates in FetchWebsocketConstructor based on the requested host +const { certificate, privateKey } = createCertificate({ + commonName: 'downloads.wordpress.org', //wsUrl.searchParams.get('host') || '' +}); +const CAPair = { certificate, privateKey }; +// const CAPair = createCertificate({ +// commonName: '' +// }); +export const CAPem = forge.pki.certificateToPem(CAPair.certificate); +/** + * Websocket that buffers the received bytes and translates them into + * a fetch() call. + */ +const fetchingWebsocket = (phpModuleArgs: EmscriptenOptions = {}) => { + return { + websocket: { + ...(phpModuleArgs['websocket'] || {}), + url: (_: any, host: string, port: string) => { + const query = new URLSearchParams({ + host, + port, + }).toString(); + return `ws://playground.internal/?${query}`; + }, + subprotocol: 'binary', + decorator: () => { + return class FetchWebsocketConstructor { + CONNECTING = 0; + OPEN = 1; + CLOSING = 2; + CLOSED = 3; + readyState = this.CONNECTING; + binaryType = 'blob'; + bufferedAmount = 0; + extensions = ''; + protocol = 'ws'; + host = ''; + port = 0; + listeners = new Map(); + sslServer: any; + isPlaintext: boolean | null = null; + + constructor(public url: string, public options: string[]) { + const wsUrl = new URL(url); + this.host = wsUrl.searchParams.get('host')!; + this.port = parseInt( + wsUrl.searchParams.get('port')!, + 10 + ); + console.log('====> FetchWebsocketConstructor', { + url, + options, + }); + + const ws = this; + try { + this.sslServer = forge.tls.createConnection({ + server: true, + caStore: forge.pki.createCaStore([ + CAPair.certificate, + ]), + sessionCache: {}, + // supported cipher suites in order of preference + cipherSuites: [ + forge.tls.CipherSuites + .TLS_RSA_WITH_AES_128_CBC_SHA, + forge.tls.CipherSuites + .TLS_RSA_WITH_AES_256_CBC_SHA, + ], + // require a client-side certificate if you want + verifyClient: false, + verify: function ( + connection, + verified, + depth, + certs + ) { + console.log('Verify '); + if (depth === 0) { + var cn = + certs[0].subject.getField( + 'CN' + ).value; + if (cn !== 'the-client') { + verified = { + alert: forge.tls.Alert + .Description + .bad_certificate, + message: + 'Certificate common name does not match expected client.', + }; + } + } + return verified; + }, + connected: function (connection) { + console.log( + 'Sending an encrypted message back to the client!' + ); + // send message to client + + console.log({ connection }); + + // connection.prepare(forge.util.encodeUtf8( + // `HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nHello World!` + // )); + + /* NOTE: experimental, start heartbeat retransmission timer + myHeartbeatTimer = setInterval(function() { + connection.prepareHeartbeatRequest(forge.util.createBuffer('1234')); + }, 5*60*1000);*/ + }, + getCertificate: function (connection, hint) { + console.log('====> getCertificate'); + // return certificate; + // This should return Pem, I think + return forge.pki.certificateToPem( + certificate + ); + }, + getPrivateKey: function (connection, cert) { + console.log('====> getPrivateKey'); + // return privateKey; + // This should return Pem, I think + return forge.pki.privateKeyToPem( + privateKey + ); + }, + tlsDataReady: function (connection) { + console.log('TLS data ready to be sent'); + console.log({ connection }); + const byteString = + connection.tlsData.getBytes(); + const byteArray = new Uint8Array( + byteString.length + ); + for ( + let i = 0; + i < byteString.length; + i++ + ) { + byteArray[i] = byteString.charCodeAt(i); + } + // TLS data (encrypted) is ready to be sent to the client + ws.emit('message', { data: byteArray }); + // if you were communicating with the client above you'd do: + // client.process(connection.tlsData.getBytes()); + }, + dataReady: function (connection) { + // clear data from the client is ready + const receivedData = forge.util.decodeUtf8( + connection.data.getBytes() + ); + if (receivedData === '') { + return; + } + console.log( + 'Clear data received: ' + receivedData + ); + + // @TODO: stream data from multiple dataReady calls in case the + // client, say, uploads a large file + setTimeout(() => { + httpRequestToFetch( + ws.host, + ws.port, + receivedData, + (data) => + connection.prepare( + uint8ArrayToBinaryString( + new Uint8Array(data) + ) + ), + () => connection.close() + ); + }); + console.log({ connection }); + + // close connection + // connection.close(); + }, + /* NOTE: experimental + heartbeatReceived: function(connection, payload) { + // restart retransmission timer, look at payload + clearInterval(myHeartbeatTimer); + myHeartbeatTimer = setInterval(function() { + connection.prepareHeartbeatRequest(forge.util.createBuffer('1234')); + }, 5*60*1000); + payload.getBytes(); + },*/ + closed: function (connection) { + console.log('disconnected'); + }, + error: function (connection, error) { + console.log(connection); + console.log('uh oh', error); + }, + }); + } catch (e) { + console.error(e); + } + setTimeout(() => { + this.readyState = this.OPEN; + this.emit('open'); + }); + } + + on(eventName: string, callback: (e: any) => void) { + this.addEventListener(eventName, callback); + } + + once(eventName: string, callback: (e: any) => void) { + const wrapper = (e: any) => { + callback(e); + this.removeEventListener(eventName, wrapper); + }; + this.addEventListener(eventName, wrapper); + } + + addEventListener( + eventName: string, + callback: (e: any) => void + ) { + // console.log("Adding listener for ", eventName, " event"); + if (!this.listeners.has(eventName)) { + this.listeners.set(eventName, new Set()); + } + this.listeners.get(eventName).add(callback); + } + + removeListener( + eventName: string, + callback: (e: any) => void + ) { + this.removeEventListener(eventName, callback); + } + + removeEventListener( + eventName: string, + callback: (e: any) => void + ) { + const listeners = this.listeners.get(eventName); + if (listeners) { + listeners.delete(callback); + } + } + + emit(eventName: string, data: any = {}) { + // console.log("dispatching ", eventName, " event"); + if (eventName === 'message') { + this.onmessage(data); + } else if (eventName === 'close') { + this.onclose(data); + } else if (eventName === 'error') { + this.onerror(data); + } else if (eventName === 'open') { + this.onopen(data); + } + const listeners = this.listeners.get(eventName); + if (listeners) { + for (const listener of listeners) { + listener(eventName, data); + } + } + } + + onclose(data: any) {} + onerror(data: any) {} + onmessage(data: any) {} + onopen(data: any) {} + + send(data: ArrayBuffer) { + console.log('Send called with ', data); + try { + if (this.isPlaintext === null) { + // If it's a HTTP request, we can just fetch it + // @TODO: This is very naive. Let's find a more robust way of detecting if + // it's a HTTP request + const string = new TextDecoder().decode(data); + const firstLine = string.split('\n')[0]; + const [, , version] = firstLine.split(' '); + this.isPlaintext = version?.startsWith('HTTP'); + } + if (this.isPlaintext) { + this.close(); + // httpRequestToFetch( + // this.host, + // this.port, + // new TextDecoder().decode(data), + // (data) => this.emit('message', { data }), + // () => this.close() + // ); + // console.log('fetch() sent'); + return; + } else { + // If it's a HTTPS request, we'll pretend to be the server + // and negotiate a secure connection + console.log(new TextDecoder().decode(data)); + this.sslServer.process( + uint8ArrayToBinaryString( + new Uint8Array(data) + ) + ); + } + return null; + } catch (e) { + console.log('Failed to fetch'); + console.error(e); + } + } + + close() { + console.log('Called close()!'); + this.readyState = this.CLOSING; + this.emit('close'); + this.readyState = this.CLOSED; + } + }; + }, + }, + }; +}; + +function httpRequestToFetch( + host: string, + port: number, + httpRequest: string, + onData: (data: ArrayBuffer) => void, + onDone: () => void +) { + const firstLine = httpRequest.split('\n')[0]; + const [method, path] = firstLine.split(' '); + + const headers = new Headers(); + for (const line of httpRequest.split('\r\n').slice(1)) { + if (line === '') { + break; + } + const [name, value] = line.split(': '); + console.log({ name, value }); + headers.set(name, value); + } + // This is a naive implementation that doesn't handle + // PHP writing arbitrary Host headers to IP addresses, + // but it's the best we can do in the browser. + const protocol = port === 443 ? 'https' : 'http'; + // @TODO: Decide which host to use. The header is less reliable, + // but in some cases it's more useful. E.g. the Host header + // may be `localhost` when `host` is 127.0.0.1, and, to + // run the fetch() request, we need to use the former since + // the latter may not respond to requests. Similarly, + // PHP may run requests to arbitrary IP addresses with + // the Host header set to a domain name, and we need to + // pass a valid domain to fetch(). + const hostname = headers.get('Host') + ? headers.get('Host') + : [80, 443].includes(port) + ? host + : `${host}:${port}`; + const url = new URL(path, protocol + '://' + hostname).toString(); + console.log({ httpRequest, method, url }); + + return fetch(url, { + method, + headers, + }) + .then((response) => { + console.log('====> Got fetch() response!', response); + const reader = response.body?.getReader(); + if (reader) { + const responseHeader = new TextEncoder().encode( + `HTTP/1.1 ${response.status} ${response.statusText}\r\n${[ + ...response.headers, + ] + .map(([name, value]) => `${name}: ${value}`) + .join('\r\n')}\r\n\r\n` + ); + + // @TODO: calling onData() and waiting for more reader chunks + // passes the control back to PHP.wasm and never yields + // the control back to JavaScript. It's likely a polling + // issue, or perhaps something specific to a Symfony HTTP + // client. Either way, PHP blocks the thread and the + // read().then() callback is never called. + // We should find a way to yield the control back to + // JavaScript after each onData() call. + // + // One clue is PHP runs out of memory when onData() blocks + // the event loop. Then it fails with a regular PHP fatal error + // message. Perhaps there's an infinite loop somewhere that + // fails to correctly poll and increases the memory usage indefinitely. + const buffer = [responseHeader.buffer]; + const read = () => { + console.log('Attempt to read the response stream'); + reader + .read() + .then(({ done, value }) => { + // console.log("got some data", value); + if (done) { + // @TODO let's stream the chunks as they + // arrive without buffering them + for (const chunk of buffer) { + onData(chunk); + } + onDone(); + return; + } + buffer.push(value.buffer); + read(); + }) + .catch((e) => { + console.error(e); + }); + }; + read(); + } + }) + .catch((e) => { + console.log('Could not fetch ', url); + console.error(e); + throw e; + }); +} + +function uint8ArrayToBinaryString(bytes: Uint8Array) { + const binary = []; + const len = bytes.byteLength; + for (let i = 0; i < len; i++) { + binary.push(String.fromCharCode(bytes[i])); + } + return binary.join(''); +} + export class WebPHP extends BasePHP { /** * Creates a new PHP instance. @@ -81,7 +643,7 @@ export class WebPHP extends BasePHP { }); return await loadPHPRuntime(phpLoaderModule, { ...(options.emscriptenOptions || {}), - ...fakeWebsocket(), + ...fetchingWebsocket(), }); } } diff --git a/packages/playground/remote/src/lib/worker-thread.ts b/packages/playground/remote/src/lib/worker-thread.ts index 9fca360ad2..e8eabfd7e7 100644 --- a/packages/playground/remote/src/lib/worker-thread.ts +++ b/packages/playground/remote/src/lib/worker-thread.ts @@ -1,4 +1,4 @@ -import { WebPHP, WebPHPEndpoint, exposeAPI } from '@php-wasm/web'; +import { CAPem, WebPHP, WebPHPEndpoint, exposeAPI } from '@php-wasm/web'; import { EmscriptenDownloadMonitor } from '@php-wasm/progress'; import { setURLScope } from '@php-wasm/scopes'; import { DOCROOT, wordPressSiteUrl } from './config'; @@ -241,10 +241,15 @@ const [setApiReady, setAPIError] = exposeAPI( try { php.initializeRuntime(await recreateRuntime()); + php.setPhpIniEntry('disable_functions', ''); if (startupOptions.sapiName) { await php.setSapiName(startupOptions.sapiName); } + php.setPhpIniEntry('allow_url_fopen', 'On'); + php.setPhpIniEntry('openssl.cafile', '/tmp/ca-bundle.crt'); + // @TODO: Do not import the CA bundle like this. + php.writeFile('/tmp/ca-bundle.crt', CAPem); const docroot = php.documentRoot; // If WordPress isn't already installed, download and extract it from @@ -276,6 +281,36 @@ try { }); } + php.writeFile( + joinPaths(docroot, 'curl-info.php'), + `'; + $ch = curl_init(); + curl_setopt( $ch, CURLOPT_URL, 'https://wordpress.org' ); + curl_setopt($ch, CURLOPT_VERBOSE, 1); + curl_setopt($ch, CURLOPT_TCP_NODELAY, 0); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); + curl_setopt($ch, CURLOPT_TIMEOUT, 25); + curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); + $streamVerboseHandle = fopen('php://stdout', 'w+'); + curl_setopt($ch, CURLOPT_STDERR, $streamVerboseHandle); + echo "Before curl_exec\n\n"; + + $output = curl_exec($ch); + echo "\n\nAfter curl_exec\n"; + var_dump($output); + var_dump(curl_error($ch)); + curl_close($ch); + ` + ); + // Always install the playground mu-plugin, even if WordPress is loaded // from the OPFS. This ensures: // * The mu-plugin is always there, even when a custom WordPress directory