Buckets:
| /** | |
| * @license | |
| * Copyright 2013 The Emscripten Authors | |
| * SPDX-License-Identifier: MIT | |
| */ | |
| addToLibrary({ | |
| #if WASMFS | |
| $NODEFS__deps: ['$stringToUTF8OnStack', 'wasmfs_create_node_backend'], | |
| $NODEFS: { | |
| createBackend(opts) { | |
| return _wasmfs_create_node_backend(stringToUTF8OnStack(opts.root)); | |
| } | |
| } | |
| #else | |
| $NODEFS__deps: ['$FS', '$PATH', '$ERRNO_CODES', '$mmapAlloc'], | |
| $NODEFS__postset: 'if (ENVIRONMENT_IS_NODE) { NODEFS.staticInit(); }', | |
| $NODEFS: { | |
| isWindows: false, | |
| staticInit() { | |
| NODEFS.isWindows = !!process.platform.match(/^win/); | |
| var flags = process.binding("constants")["fs"]; | |
| NODEFS.flagsForNodeMap = { | |
| "{{{ cDefs.O_APPEND }}}": flags["O_APPEND"], | |
| "{{{ cDefs.O_CREAT }}}": flags["O_CREAT"], | |
| "{{{ cDefs.O_EXCL }}}": flags["O_EXCL"], | |
| "{{{ cDefs.O_NOCTTY }}}": flags["O_NOCTTY"], | |
| "{{{ cDefs.O_RDONLY }}}": flags["O_RDONLY"], | |
| "{{{ cDefs.O_RDWR }}}": flags["O_RDWR"], | |
| "{{{ cDefs.O_DSYNC }}}": flags["O_SYNC"], | |
| "{{{ cDefs.O_TRUNC }}}": flags["O_TRUNC"], | |
| "{{{ cDefs.O_WRONLY }}}": flags["O_WRONLY"], | |
| "{{{ cDefs.O_NOFOLLOW }}}": flags["O_NOFOLLOW"], | |
| }; | |
| #if ASSERTIONS | |
| // The 0 define must match on both sides, as otherwise we would not | |
| // know to add it. | |
| assert(NODEFS.flagsForNodeMap["0"] === 0); | |
| #endif | |
| }, | |
| convertNodeCode(e) { | |
| var code = e.code; | |
| #if ASSERTIONS | |
| assert(code in ERRNO_CODES, `unexpected node error code: ${code} (${e})`); | |
| #endif | |
| return ERRNO_CODES[code]; | |
| }, | |
| tryFSOperation(f) { | |
| try { | |
| return f(); | |
| } 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({{{ cDefs.EINVAL }}}); | |
| throw new FS.ErrnoError(NODEFS.convertNodeCode(e)); | |
| } | |
| }, | |
| mount(mount) { | |
| #if ASSERTIONS | |
| assert(ENVIRONMENT_IS_NODE); | |
| #endif | |
| 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({{{ cDefs.EINVAL }}}); | |
| } | |
| var node = FS.createNode(parent, name, mode); | |
| node.node_ops = NODEFS.node_ops; | |
| node.stream_ops = NODEFS.stream_ops; | |
| return node; | |
| }, | |
| getMode(path) { | |
| return NODEFS.tryFSOperation(() => { | |
| var mode = fs.lstatSync(path).mode; | |
| if (NODEFS.isWindows) { | |
| // Windows does not report the 'x' permission bit, so propagate read | |
| // bits to execute bits. | |
| mode |= (mode & {{{ cDefs.S_IRUGO }}}) >> 2; | |
| } | |
| return 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(...parts); | |
| }, | |
| // This maps the integer permission modes from http://linux.die.net/man/3/open | |
| // to node.js-specific file open permission strings at http://nodejs.org/api/fs.html#fs_fs_open_path_flags_mode_callback | |
| flagsForNode(flags) { | |
| flags &= ~{{{ cDefs.O_PATH }}}; // Ignore this flag from musl, otherwise node.js fails to open the file. | |
| flags &= ~{{{ cDefs.O_NONBLOCK }}}; // Ignore this flag from musl, otherwise node.js fails to open the file. | |
| flags &= ~{{{ cDefs.O_LARGEFILE }}}; // Ignore this flag from musl, otherwise node.js fails to open the file. | |
| flags &= ~{{{ cDefs.O_CLOEXEC }}}; // Some applications may pass it; it makes no sense for a single process. | |
| flags &= ~{{{ cDefs.O_DIRECTORY }}}; // 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({{{ cDefs.EINVAL }}}); | |
| } | |
| return newFlags; | |
| }, | |
| getattr(func, node) { | |
| var stat = NODEFS.tryFSOperation(func); | |
| if (NODEFS.isWindows) { | |
| // 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 (!stat.blksize) { | |
| stat.blksize = 4096; | |
| } | |
| if (!stat.blocks) { | |
| stat.blocks = (stat.size+stat.blksize-1)/stat.blksize|0; | |
| } | |
| // Windows does not report the 'x' permission bit, so propagate read | |
| // bits to execute bits. | |
| stat.mode |= (stat.mode & {{{ cDefs.S_IRUGO }}}) >> 2; | |
| } | |
| return { | |
| dev: stat.dev, | |
| ino: node.id, | |
| 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 | |
| }; | |
| }, | |
| // Common code for both node and stream setattr | |
| // For node getattr: | |
| // - arg is a native path | |
| // - chmod, utimes, truncate are fs.chmodSync, fs.utimesSync, fs.truncateSync | |
| // For stream getattr: | |
| // - arg is a native file descriptor | |
| // - chmod, utimes, truncate are fs.fchmodSync, fs.futimesSync, fs.ftruncateSync | |
| setattr(arg, node, attr, chmod, utimes, truncate, stat) { | |
| NODEFS.tryFSOperation(() => { | |
| if (attr.mode !== undefined) { | |
| var mode = attr.mode; | |
| if (NODEFS.isWindows) { | |
| // Windows only supports S_IREAD / S_IWRITE (S_IRUSR / S_IWUSR) | |
| // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/chmod-wchmod | |
| mode &= {{{ cDefs.S_IRUSR | cDefs.S_IWUSR }}}; | |
| } | |
| chmod(arg, mode); | |
| // update the common node structure mode as well | |
| node.mode = attr.mode; | |
| } | |
| if (typeof (attr.atime ?? attr.mtime) === "number") { | |
| // Unfortunately, we have to stat the current value if we don't want | |
| // to change it. On top of that, since the times don't round trip | |
| // this will only keep the value nearly unchanged not exactly | |
| // unchanged. See: | |
| // https://github.com/nodejs/node/issues/56492 | |
| var atime = new Date(attr.atime ?? stat(arg).atime); | |
| var mtime = new Date(attr.mtime ?? stat(arg).mtime); | |
| utimes(arg, atime, mtime); | |
| } | |
| if (attr.size !== undefined) { | |
| truncate(arg, attr.size); | |
| } | |
| }); | |
| }, | |
| node_ops: { | |
| getattr(node) { | |
| var path = NODEFS.realPath(node); | |
| return NODEFS.getattr(() => fs.lstatSync(path), node); | |
| }, | |
| setattr(node, attr) { | |
| var path = NODEFS.realPath(node); | |
| if (attr.mode != null && attr.dontFollow) { | |
| throw new FS.ErrnoError({{{ cDefs.ENOSYS }}}); | |
| } | |
| NODEFS.setattr(path, node, attr, fs.chmodSync, fs.utimesSync, fs.truncateSync, fs.lstatSync); | |
| }, | |
| 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); | |
| NODEFS.tryFSOperation(() => { | |
| if (FS.isDir(node.mode)) { | |
| fs.mkdirSync(path, node.mode); | |
| } else { | |
| fs.writeFileSync(path, '', { mode: node.mode }); | |
| } | |
| }); | |
| return node; | |
| }, | |
| rename(oldNode, newDir, newName) { | |
| var oldPath = NODEFS.realPath(oldNode); | |
| var newPath = PATH.join2(NODEFS.realPath(newDir), newName); | |
| try { | |
| FS.unlink(newPath); | |
| } catch(e) {} | |
| NODEFS.tryFSOperation(() => fs.renameSync(oldPath, newPath)); | |
| oldNode.name = newName; | |
| }, | |
| unlink(parent, name) { | |
| var path = PATH.join2(NODEFS.realPath(parent), name); | |
| NODEFS.tryFSOperation(() => fs.unlinkSync(path)); | |
| }, | |
| rmdir(parent, name) { | |
| var path = PATH.join2(NODEFS.realPath(parent), name); | |
| NODEFS.tryFSOperation(() => fs.rmdirSync(path)); | |
| }, | |
| readdir(node) { | |
| var path = NODEFS.realPath(node); | |
| return NODEFS.tryFSOperation(() => fs.readdirSync(path)); | |
| }, | |
| symlink(parent, newName, oldPath) { | |
| var newPath = PATH.join2(NODEFS.realPath(parent), newName); | |
| NODEFS.tryFSOperation(() => fs.symlinkSync(oldPath, newPath)); | |
| }, | |
| readlink(node) { | |
| var path = NODEFS.realPath(node); | |
| return NODEFS.tryFSOperation(() => fs.readlinkSync(path)); | |
| }, | |
| statfs(path) { | |
| var stats = NODEFS.tryFSOperation(() => fs.statfsSync(path)); | |
| // Node.js doesn't provide frsize (fragment size). Set it to bsize (block size) | |
| // as they're often the same in many file systems. May not be accurate for all. | |
| stats.frsize = stats.bsize; | |
| return stats; | |
| } | |
| }, | |
| stream_ops: { | |
| getattr(stream) { | |
| return NODEFS.getattr(() => fs.fstatSync(stream.nfd), stream.node); | |
| }, | |
| setattr(stream, attr) { | |
| NODEFS.setattr(stream.nfd, stream.node, attr, fs.fchmodSync, fs.futimesSync, fs.ftruncateSync, fs.fstatSync); | |
| }, | |
| open(stream) { | |
| var path = NODEFS.realPath(stream.node); | |
| NODEFS.tryFSOperation(() => { | |
| stream.shared.refcount = 1; | |
| stream.nfd = fs.openSync(path, NODEFS.flagsForNode(stream.flags)); | |
| }); | |
| }, | |
| close(stream) { | |
| NODEFS.tryFSOperation(() => { | |
| if (stream.nfd && --stream.shared.refcount === 0) { | |
| fs.closeSync(stream.nfd); | |
| } | |
| }); | |
| }, | |
| dup(stream) { | |
| stream.shared.refcount++; | |
| }, | |
| read(stream, buffer, offset, length, position) { | |
| return NODEFS.tryFSOperation(() => | |
| fs.readSync(stream.nfd, buffer, offset, length, position) | |
| ); | |
| }, | |
| write(stream, buffer, offset, length, position) { | |
| return NODEFS.tryFSOperation(() => | |
| fs.writeSync(stream.nfd, buffer, offset, length, position) | |
| ); | |
| }, | |
| llseek(stream, offset, whence) { | |
| var position = offset; | |
| if (whence === {{{ cDefs.SEEK_CUR }}}) { | |
| position += stream.position; | |
| } else if (whence === {{{ cDefs.SEEK_END }}}) { | |
| if (FS.isFile(stream.node.mode)) { | |
| NODEFS.tryFSOperation(() => { | |
| var stat = fs.fstatSync(stream.nfd); | |
| position += stat.size; | |
| }); | |
| } | |
| } | |
| if (position < 0) { | |
| throw new FS.ErrnoError({{{ cDefs.EINVAL }}}); | |
| } | |
| return position; | |
| }, | |
| mmap(stream, length, position, prot, flags) { | |
| if (!FS.isFile(stream.node.mode)) { | |
| throw new FS.ErrnoError({{{ cDefs.ENODEV }}}); | |
| } | |
| 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; | |
| } | |
| } | |
| } | |
| #endif | |
| }); | |
Xet Storage Details
- Size:
- 11.6 kB
- Xet hash:
- 7993d233cbad7dc6ff891d002086c8199611ab41e7ffcd8ec58dffc55f17bebd
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.