/**
 * @license
 * Copyright 2019 The Emscripten Authors
 * SPDX-License-Identifier: MIT
 */

var WasiLibrary = {
#if !MINIMAL_RUNTIME
  $ExitStatus__docs: '/** @constructor */',
  $ExitStatus: function(status) {
    this.name = 'ExitStatus';
    this.message = `Program terminated with exit(${status})`;
    this.status = status;
  },
  proc_exit__deps: ['$ExitStatus'],
#endif

  proc_exit__nothrow: true,
  proc_exit: function(code) {
#if MINIMAL_RUNTIME
    throw `exit(${code})`;
#else
#if RUNTIME_DEBUG
    dbg(`proc_exit: ${code}`);
#endif
    EXITSTATUS = code;
    if (!keepRuntimeAlive()) {
#if PTHREADS
      PThread.terminateAllThreads();
#endif
#if expectToReceiveOnModule('onExit')
      if (Module['onExit']) Module['onExit'](code);
#endif
      ABORT = true;
    }
    quit_(code, new ExitStatus(code));
#endif // MINIMAL_RUNTIME
  },

  sched_yield__nothrow: true,
  sched_yield: function() {
    return 0;
  },

  random_get__deps: ['getentropy'],
  random_get: function(buf, buf_len) {
    _getentropy(buf, buf_len);
    return 0;
  },

  $getEnvStrings__deps: ['$ENV', '$getExecutableName'],
  $getEnvStrings: function() {
    if (!getEnvStrings.strings) {
      // Default values.
#if !DETERMINISTIC
      // Browser language detection #8751
      var lang = ((typeof navigator == 'object' && navigator.languages && navigator.languages[0]) || 'C').replace('-', '_') + '.UTF-8';
#else
      // Deterministic language detection, ignore the browser's language.
      var lang = 'C.UTF-8';
#endif
      var env = {
#if !PURE_WASI
        'USER': 'web_user',
        'LOGNAME': 'web_user',
        'PATH': '/',
        'PWD': '/',
        'HOME': '/home/web_user',
        'LANG': lang,
        '_': getExecutableName()
#endif
      };
      // 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;
  },

  environ_sizes_get__deps: ['$getEnvStrings'],
  environ_sizes_get__nothrow: true,
  environ_sizes_get: function(penviron_count, penviron_buf_size) {
    var strings = getEnvStrings();
    {{{ makeSetValue('penviron_count', 0, 'strings.length', SIZE_TYPE) }}};
    var bufSize = 0;
    strings.forEach(function(string) {
      bufSize += string.length + 1;
    });
    {{{ makeSetValue('penviron_buf_size', 0, 'bufSize', SIZE_TYPE) }}};
    return 0;
  },

  environ_get__deps: ['$getEnvStrings', '$stringToAscii'],
  environ_get__nothrow: true,
  environ_get: function(__environ, environ_buf) {
    var bufSize = 0;
    getEnvStrings().forEach(function(string, i) {
      var ptr = environ_buf + bufSize;
      {{{ makeSetValue('__environ', `i*${POINTER_SIZE}`, 'ptr', POINTER_TYPE) }}};
      stringToAscii(string, ptr);
      bufSize += string.length + 1;
    });
    return 0;
  },

  // In normal (non-standalone) mode arguments are passed direclty
  // to main, and the `mainArgs` global does not exist.
#if STANDALONE_WASM
  args_sizes_get__nothrow: true,
  args_sizes_get: function(pargc, pargv_buf_size) {
#if MAIN_READS_PARAMS
    {{{ makeSetValue('pargc', 0, 'mainArgs.length', SIZE_TYPE) }}};
    var bufSize = 0;
    mainArgs.forEach(function(arg) {
      bufSize += arg.length + 1;
    });
    {{{ makeSetValue('pargv_buf_size', 0, 'bufSize', SIZE_TYPE) }}};
#else
    {{{ makeSetValue('pargc', 0, '0', SIZE_TYPE) }}};
#endif
    return 0;
  },

  args_get__nothrow: true,
  args_get__deps: ['$stringToAscii'],
  args_get: function(argv, argv_buf) {
#if MAIN_READS_PARAMS
    var bufSize = 0;
    mainArgs.forEach(function(arg, i) {
      var ptr = argv_buf + bufSize;
      {{{ makeSetValue('argv', `i*${POINTER_SIZE}`, 'ptr', POINTER_TYPE) }}};
      stringToAscii(arg, ptr);
      bufSize += arg.length + 1;
    });
#endif
    return 0;
  },
#endif

  $checkWasiClock: function(clock_id) {
    return clock_id == {{{ cDefs.__WASI_CLOCKID_REALTIME }}} ||
           clock_id == {{{ cDefs.__WASI_CLOCKID_MONOTONIC }}} ||
           clock_id == {{{ cDefs.__WASI_CLOCKID_PROCESS_CPUTIME_ID }}} ||
           clock_id == {{{ cDefs.__WASI_CLOCKID_THREAD_CPUTIME_ID }}};
  },

  // TODO: the i64 in the API here must be legalized for this JS code to run,
  // but the wasm file can't be legalized in standalone mode, which is where
  // this is needed. To get this code to be usable as a JS shim we need to
  // either wait for BigInt support or to legalize on the client.
  clock_time_get__nothrow: true,
  clock_time_get__deps: ['emscripten_get_now', '$nowIsMonotonic', '$checkWasiClock'],
  clock_time_get: function(clk_id, {{{ defineI64Param('ignored_precision') }}}, ptime) {
    if (!checkWasiClock(clk_id)) {
      return {{{ cDefs.EINVAL }}};
    }
    var now;
    // all wasi clocks but realtime are monotonic
    if (clk_id === {{{ cDefs.__WASI_CLOCKID_REALTIME }}}) {
      now = Date.now();
    } else if (nowIsMonotonic) {
      now = _emscripten_get_now();
    } else {
      return {{{ cDefs.ENOSYS }}};
    }
    // "now" is in ms, and wasi times are in ns.
    var nsec = Math.round(now * 1000 * 1000);
    {{{ makeSetValue('ptime', 0, 'nsec >>> 0', 'i32') }}};
    {{{ makeSetValue('ptime', 4, '(nsec / Math.pow(2, 32)) >>> 0', 'i32') }}};
    return 0;
  },

  clock_res_get__nothrow: true,
  clock_res_get__deps: ['emscripten_get_now', 'emscripten_get_now_res', '$nowIsMonotonic', '$checkWasiClock'],
  clock_res_get: function(clk_id, pres) {
    if (!checkWasiClock(clk_id)) {
      return {{{ cDefs.EINVAL }}};
    }
    var nsec;
    // all wasi clocks but realtime are monotonic
    if (clk_id === {{{ cDefs.CLOCK_REALTIME }}}) {
      nsec = 1000 * 1000; // educated guess that it's milliseconds
    } else if (nowIsMonotonic) {
      nsec = _emscripten_get_now_res();
    } else {
      return {{{ cDefs.ENOSYS }}};
    }
    {{{ makeSetValue('pres', 0, 'nsec >>> 0', 'i32') }}};
    {{{ makeSetValue('pres', 4, '(nsec / Math.pow(2, 32)) >>> 0', 'i32') }}};
    return 0;
  },

#if SYSCALLS_REQUIRE_FILESYSTEM
  $doReadv__docs: '/** @param {number=} offset */',
  $doReadv: function(stream, iov, iovcnt, offset) {
    var ret = 0;
    for (var i = 0; i < iovcnt; i++) {
      var ptr = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_base, '*') }}};
      var len = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_len, '*') }}};
      iov += {{{ C_STRUCTS.iovec.__size__ }}};
      var curr = FS.read(stream, {{{ heapAndOffset('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;
  },
  $doWritev__docs: '/** @param {number=} offset */',
  $doWritev: function(stream, iov, iovcnt, offset) {
    var ret = 0;
    for (var i = 0; i < iovcnt; i++) {
      var ptr = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_base, '*') }}};
      var len = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_len, '*') }}};
      iov += {{{ C_STRUCTS.iovec.__size__ }}};
      var curr = FS.write(stream, {{{ heapAndOffset('HEAP8', 'ptr') }}}, len, offset);
      if (curr < 0) return -1;
      ret += curr;
      if (typeof offset !== 'undefined') {
        offset += curr;
      }
    }
    return ret;
  },
#else
  // MEMFS filesystem disabled lite handling of stdout and stderr:
  $printCharBuffers: [null, [], []], // 1 => stdout, 2 => stderr
  $printCharBuffers__internal: true,
  $printChar__internal: true,
  $printChar__deps: ['$printCharBuffers', '$UTF8ArrayToString'],
  $printChar: function(stream, curr) {
    var buffer = printCharBuffers[stream];
#if ASSERTIONS
    assert(buffer);
#endif
    if (curr === 0 || curr === {{{ charCode('\n') }}}) {
      (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0));
      buffer.length = 0;
    } else {
      buffer.push(curr);
    }
  },
#endif // SYSCALLS_REQUIRE_FILESYSTEM

#if SYSCALLS_REQUIRE_FILESYSTEM
  fd_write__deps: ['$doWritev'],
#elif (!MINIMAL_RUNTIME || EXIT_RUNTIME)
  $flush_NO_FILESYSTEM__deps: ['$printChar', '$printCharBuffers'],
  $flush_NO_FILESYSTEM: function() {
    // flush anything remaining in the buffers during shutdown
#if hasExportedSymbol('fflush')
    _fflush(0);
#endif
    if (printCharBuffers[1].length) printChar(1, {{{ charCode("\n") }}});
    if (printCharBuffers[2].length) printChar(2, {{{ charCode("\n") }}});
  },
  fd_write__deps: ['$flush_NO_FILESYSTEM', '$printChar'],
  fd_write__postset: function() {
    addAtExit('flush_NO_FILESYSTEM()');
  },
#else
  fd_write__deps: ['$printChar'],
#endif
  fd_write: function(fd, iov, iovcnt, pnum) {
#if SYSCALLS_REQUIRE_FILESYSTEM
    var stream = SYSCALLS.getStreamFromFD(fd);
    var num = doWritev(stream, iov, iovcnt);
#else
    // hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0
    var num = 0;
    for (var i = 0; i < iovcnt; i++) {
      var ptr = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_base, '*') }}};
      var len = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_len, '*') }}};
      iov += {{{ C_STRUCTS.iovec.__size__ }}};
      for (var j = 0; j < len; j++) {
        printChar(fd, HEAPU8[ptr+j]);
      }
      num += len;
    }
#endif // SYSCALLS_REQUIRE_FILESYSTEM
    {{{ makeSetValue('pnum', 0, 'num', SIZE_TYPE) }}};
    return 0;
  },

  fd_pwrite__deps: [
#if SYSCALLS_REQUIRE_FILESYSTEM
    '$doWritev',
#endif
  ].concat(i53ConversionDeps),
  fd_pwrite: function(fd, iov, iovcnt, {{{ defineI64Param('offset') }}}, pnum) {
#if SYSCALLS_REQUIRE_FILESYSTEM
    {{{ receiveI64ParamAsI53('offset', cDefs.EOVERFLOW) }}}
    var stream = SYSCALLS.getStreamFromFD(fd)
    var num = doWritev(stream, iov, iovcnt, offset);
    {{{ makeSetValue('pnum', 0, 'num', SIZE_TYPE) }}};
    return 0;
#elif ASSERTIONS
    abort('fd_pwrite called without SYSCALLS_REQUIRE_FILESYSTEM');
#else
    return {{{ cDefs.ENOSYS }}};
#endif
  },

  fd_close: function(fd) {
#if SYSCALLS_REQUIRE_FILESYSTEM
    var stream = SYSCALLS.getStreamFromFD(fd);
    FS.close(stream);
    return 0;
#elif PROXY_POSIX_SOCKETS
    // close() is a tricky function because it can be used to close both regular file descriptors
    // and POSIX network socket handles, hence an implementation would need to track for each
    // file descriptor which kind of item it is. To simplify, when using PROXY_POSIX_SOCKETS
    // option, use shutdown() to close a socket, and this function should behave like a no-op.
    warnOnce('To close sockets with PROXY_POSIX_SOCKETS bridge, prefer to use the function shutdown() that is proxied, instead of close()')
    return 0;
#elif ASSERTIONS
    abort('fd_close called without SYSCALLS_REQUIRE_FILESYSTEM');
#else
    return {{{ cDefs.ENOSYS }}};
#endif // SYSCALLS_REQUIRE_FILESYSTEM
  },

#if SYSCALLS_REQUIRE_FILESYSTEM
  fd_read__deps: ['$doReadv'],
#endif
  fd_read: function(fd, iov, iovcnt, pnum) {
#if SYSCALLS_REQUIRE_FILESYSTEM
    var stream = SYSCALLS.getStreamFromFD(fd);
    var num = doReadv(stream, iov, iovcnt);
    {{{ makeSetValue('pnum', 0, 'num', SIZE_TYPE) }}};
    return 0;
#elif ASSERTIONS
    abort('fd_read called without SYSCALLS_REQUIRE_FILESYSTEM');
#else
    return {{{ cDefs.ENOSYS }}};
#endif // SYSCALLS_REQUIRE_FILESYSTEM
  },

  fd_pread__deps: [
#if SYSCALLS_REQUIRE_FILESYSTEM
    '$doReadv',
#endif
  ].concat(i53ConversionDeps),
  fd_pread: function(fd, iov, iovcnt, {{{ defineI64Param('offset') }}}, pnum) {
#if SYSCALLS_REQUIRE_FILESYSTEM
    {{{ receiveI64ParamAsI53('offset', cDefs.EOVERFLOW) }}}
    var stream = SYSCALLS.getStreamFromFD(fd)
    var num = doReadv(stream, iov, iovcnt, offset);
    {{{ makeSetValue('pnum', 0, 'num', SIZE_TYPE) }}};
    return 0;
#elif ASSERTIONS
    abort('fd_pread called without SYSCALLS_REQUIRE_FILESYSTEM');
#else
    return {{{ cDefs.ENOSYS }}};
#endif
  },

  fd_seek__deps: i53ConversionDeps,
  fd_seek: function(fd, {{{ defineI64Param('offset') }}}, whence, newOffset) {
#if SYSCALLS_REQUIRE_FILESYSTEM
    {{{ receiveI64ParamAsI53('offset', cDefs.EOVERFLOW) }}}
    var stream = SYSCALLS.getStreamFromFD(fd);
    FS.llseek(stream, offset, whence);
    {{{ makeSetValue('newOffset', '0', 'stream.position', 'i64') }}};
    if (stream.getdents && offset === 0 && whence === {{{ cDefs.SEEK_SET }}}) stream.getdents = null; // reset readdir state
    return 0;
#else
    return {{{ cDefs.ESPIPE }}};
#endif
  },

  $wasiRightsToMuslOFlags: function(rights) {
#if SYSCALL_DEBUG
    dbg(`wasiRightsToMuslOFlags: ${rights}`);
#endif
    if ((rights & {{{ cDefs.__WASI_RIGHTS_FD_READ }}}) && (rights & {{{ cDefs.__WASI_RIGHTS_FD_WRITE }}})) {
      return {{{ cDefs.O_RDWR }}};
    }
    if (rights & {{{ cDefs.__WASI_RIGHTS_FD_READ }}}) {
      return {{{ cDefs.O_RDONLY }}};
    }
    if (rights & {{{ cDefs.__WASI_RIGHTS_FD_WRITE }}}) {
      return {{{ cDefs.O_WRONLY }}};
    }
    throw new FS.ErrnoError({{{ cDefs.EINVAL }}});
  },

  $wasiOFlagsToMuslOFlags: function(oflags) {
    var musl_oflags = 0;
    if (oflags & {{{ cDefs.__WASI_OFLAGS_CREAT }}}) {
      musl_oflags |= {{{ cDefs.O_CREAT }}};
    }
    if (oflags & {{{ cDefs.__WASI_OFLAGS_TRUNC }}}) {
      musl_oflags |= {{{ cDefs.O_TRUNC }}};
    }
    if (oflags & {{{ cDefs.__WASI_OFLAGS_DIRECTORY }}}) {
      musl_oflags |= {{{ cDefs.O_DIRECTORY }}};
    }
    if (oflags & {{{ cDefs.__WASI_OFLAGS_EXCL }}}) {
      musl_oflags |= {{{ cDefs.O_EXCL }}};
    }
    return musl_oflags;
  },

#if PURE_WASI
  // preopen maps open file descriptors to pathname.
  // In emscripten we already have a VFS layer so (for now) we expose the entire
  // VFS to the wasi API.
  $preopens: "{3: '/'}",

  path_open__sig: 'iiiiiiiiii',
  path_open__deps: ['$wasiRightsToMuslOFlags', '$wasiOFlagsToMuslOFlags', '$preopens'],
  path_open: function(fd, dirflags, path, path_len, oflags,
                      fs_rights_base, fs_rights_inherting,
                      fdflags, opened_fd) {
    if (!(fd in preopens)) {
      return {{{ cDefs.EBADF }}};
    }
    var pathname = UTF8ToString(path, path_len);
    var musl_oflags = wasiRightsToMuslOFlags(Number(fs_rights_base));
#if SYSCALL_DEBUG
    dbg(`oflags1: ${ptrToString(musl_oflags)}`);
#endif
    musl_oflags |= wasiOFlagsToMuslOFlags(Number(oflags));
#if SYSCALL_DEBUG
    dbg(`oflags2: ${ptrToString(musl_oflags)}`);
#endif
    var stream = FS.open(pathname, musl_oflags);
    {{{ makeSetValue('opened_fd', '0', 'stream.fd', 'i32') }}};
    return 0;
  },

  fd_prestat_dir_name__deps: ['$preopens'],
  fd_prestat_dir_name__sig: 'iiii',
  fd_prestat_dir_name__nothrow: true,
  fd_prestat_dir_name: function(fd, path, path_len) {
    if (!(fd in preopens)) {
      return {{{ cDefs.EBADF }}};
    }
    var preopen_path = preopens[fd];
    stringToUTF8Array(preopen_path, HEAP8, path, path_len)
#if SYSCALL_DEBUG
    dbg(`fd_prestat_dir_name -> "${preopen_path}"`);
#endif
    return 0;
  },

  fd_prestat_get__deps: ['$preopens'],
  fd_prestat_get__sig: 'iii',
  fd_prestat_get__nothrow: true,
  fd_prestat_get: function(fd, stat_buf) {
    if (!(fd in preopens)) {
      return {{{ cDefs.EBADF }}};
    }
    var preopen = preopens[fd];
    {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_prestat_t.pr_type, cDefs.__WASI_PREOPENTYPE_DIR, 'i8') }}};
    {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_prestat_t.u + C_STRUCTS.__wasi_prestat_dir_t.pr_name_len, 'preopen.length', 'i64') }}};
    return 0;
  },

  fd_fdstat_set_flags__sig: 'iii',
  fd_fdstat_set_flags: function(fd, flags) {
    // TODO(sbc): implement
    var stream = SYSCALLS.getStreamFromFD(fd);
    return 0;
  },

  fd_filestat_get__sig: 'iii',
  fd_filestat_get: function(fd, stat_buf) {
    // TODO(sbc): implement
    var stream = SYSCALLS.getStreamFromFD(fd);
    {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.dev, '0', 'i64') }}};
    {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.ino, '0', 'i64') }}};
    {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.filetype, '0', 'i8') }}};
    {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.nlink, '0', 'i64') }}};
    {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.size, '0', 'i64') }}};
    {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.atim, '0', 'i64') }}};
    {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.mtim, '0', 'i64') }}};
    {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.ctim, '0', 'i64') }}};
    return 0;
  },
#endif

#if PURE_WASI
  fd_fdstat_get__deps: ['$preopens'],
#endif
  fd_fdstat_get: function(fd, pbuf) {
    var rightsBase = 0;
    var rightsInheriting = 0;
    var flags = 0;
#if PURE_WASI
    if (fd in preopens) {
      var type = {{{ cDefs.__WASI_FILETYPE_DIRECTORY }}};
      rightsBase =  {{{ cDefs.__WASI_RIGHTS_PATH_CREATE_FILE |
                             cDefs.__WASI_RIGHTS_PATH_OPEN }}};
      rightsInheriting =  {{{ cDefs.__WASI_RIGHTS_FD_READ |
                                   cDefs.__WASI_RIGHTS_FD_WRITE }}}
    } else
#endif
    {
#if SYSCALLS_REQUIRE_FILESYSTEM
      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 ? {{{ cDefs.__WASI_FILETYPE_CHARACTER_DEVICE }}} :
                 FS.isDir(stream.mode) ? {{{ cDefs.__WASI_FILETYPE_DIRECTORY }}} :
                 FS.isLink(stream.mode) ? {{{ cDefs.__WASI_FILETYPE_SYMBOLIC_LINK }}} :
                 {{{ cDefs.__WASI_FILETYPE_REGULAR_FILE }}};
#else
      // Hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0. We support at
      // least stdin, stdout, stderr in a simple way.
#if ASSERTIONS
      assert(fd == 0 || fd == 1 || fd == 2);
#endif
      var type = {{{ cDefs.__WASI_FILETYPE_CHARACTER_DEVICE }}};
      if (fd == 0) {
        rightsBase = {{{ cDefs.__WASI_RIGHTS_FD_READ }}};
      } else if (fd == 1 || fd == 2) {
        rightsBase = {{{ cDefs.__WASI_RIGHTS_FD_WRITE }}};
      }
      flags = {{{ cDefs.__WASI_FDFLAGS_APPEND }}};
#endif
    }
    {{{ makeSetValue('pbuf', C_STRUCTS.__wasi_fdstat_t.fs_filetype, 'type', 'i8') }}};
    {{{ makeSetValue('pbuf', C_STRUCTS.__wasi_fdstat_t.fs_flags, 'flags', 'i16') }}};
    {{{ makeSetValue('pbuf', C_STRUCTS.__wasi_fdstat_t.fs_rights_base, 'rightsBase', 'i64') }}};
    {{{ makeSetValue('pbuf', C_STRUCTS.__wasi_fdstat_t.fs_rights_inheriting, 'rightsInheriting', 'i64') }}};
    return 0;
  },

  fd_sync: function(fd) {
#if SYSCALLS_REQUIRE_FILESYSTEM
    var stream = SYSCALLS.getStreamFromFD(fd);
#if ASYNCIFY
    return Asyncify.handleSleep(function(wakeUp) {
      var mount = stream.node.mount;
      if (!mount.type.syncfs) {
        // We write directly to the file system, so there's nothing to do here.
        wakeUp(0);
        return;
      }
      mount.type.syncfs(mount, false, function(err) {
        if (err) {
          wakeUp(function() { return {{{ cDefs.EIO }}} });
          return;
        }
        wakeUp(0);
      });
    });
#else
    if (stream.stream_ops && stream.stream_ops.fsync) {
      return stream.stream_ops.fsync(stream);
    }
    return 0; // we can't do anything synchronously; the in-memory FS is already synced to
#endif // ASYNCIFY
#elif ASSERTIONS
    abort('fd_sync called without SYSCALLS_REQUIRE_FILESYSTEM');
#else
    return {{{ cDefs.ENOSYS }}};
#endif // SYSCALLS_REQUIRE_FILESYSTEM
  },
};

for (var x in WasiLibrary) {
  wrapSyscallFunction(x, WasiLibrary, true);
}

mergeInto(LibraryManager.library, WasiLibrary);
