| /** |
| * @license |
| * Copyright 2016 The Emscripten Authors |
| * SPDX-License-Identifier: MIT |
| */ |
| |
| mergeInto(LibraryManager.library, { |
| $PROXYFS__deps: ['$FS', '$PATH', '$ERRNO_CODES'], |
| $PROXYFS: { |
| mount: function (mount) { |
| return PROXYFS.createNode(null, '/', mount.opts.fs.lstat(mount.opts.root).mode, 0); |
| }, |
| createNode: function (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: function (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: function(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: function(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: function (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: function (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: function (oldNode, newDir, newName) { |
| var oldPath = PROXYFS.realPath(oldNode); |
| var newPath = PATH.join2(PROXYFS.realPath(newDir), newName); |
| try { |
| oldNode.mount.opts.fs.rename(oldPath, newPath); |
| } catch(e) { |
| if (!e.code) throw e; |
| throw new FS.ErrnoError(ERRNO_CODES[e.code]); |
| } |
| }, |
| unlink: function(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: function(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: function(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: function(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: function(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: function (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: function (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: function (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: function (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: function (stream, offset, whence) { |
| var position = offset; |
| if (whence === {{{ cDefine('SEEK_CUR') }}}) { |
| position += stream.position; |
| } else if (whence === {{{ cDefine('SEEK_END') }}}) { |
| if (FS.isFile(stream.node.mode)) { |
| try { |
| var stat = stream.node.mount.opts.fs.fstat(stream.nfd); |
| 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; |
| } |
| } |
| } |
| }); |