@zenfs/dom 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FileSystemAccess.d.ts +7 -7
- package/dist/browser.min.js +1 -1
- package/dist/browser.min.js.map +4 -4
- package/license.md +1 -1
- package/package.json +55 -54
package/dist/browser.min.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/index.ts", "../node_modules/@zenfs/core/dist/emulation/path.js", "../node_modules/@zenfs/core/dist/ApiError.js", "../node_modules/@zenfs/core/dist/
|
|
4
|
-
"sourcesContent": ["export * from './FileSystemAccess.js';\nexport * from './IndexedDB.js';\nexport * from './Storage.js';\n", "/*\nCopyright Joyent, Inc. and other Node contributors.\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to permit\npersons to whom the Software is furnished to do so, subject to the\nfollowing conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\nNO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\nDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\nUSE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\nexport const cwd = '/';\nexport const sep = '/';\nfunction validateString(str, name) {\n if (typeof str != 'string') {\n throw new TypeError(`\"${name}\" is not a string`);\n }\n}\nfunction validateObject(str, name) {\n if (typeof str != 'object') {\n throw new TypeError(`\"${name}\" is not an object`);\n }\n}\n// Resolves . and .. elements in a path with directory names\nexport function normalizeString(path, allowAboveRoot) {\n let res = '';\n let lastSegmentLength = 0;\n let lastSlash = -1;\n let dots = 0;\n let char = '\\x00';\n for (let i = 0; i <= path.length; ++i) {\n if (i < path.length) {\n char = path[i];\n }\n else if (char == '/') {\n break;\n }\n else {\n char = '/';\n }\n if (char == '/') {\n if (lastSlash === i - 1 || dots === 1) {\n // NOOP\n }\n else if (dots === 2) {\n if (res.length < 2 || lastSegmentLength !== 2 || res.at(-1) !== '.' || res.at(-2) !== '.') {\n if (res.length > 2) {\n const lastSlashIndex = res.lastIndexOf('/');\n if (lastSlashIndex === -1) {\n res = '';\n lastSegmentLength = 0;\n }\n else {\n res = res.slice(0, lastSlashIndex);\n lastSegmentLength = res.length - 1 - res.lastIndexOf('/');\n }\n lastSlash = i;\n dots = 0;\n continue;\n }\n else if (res.length !== 0) {\n res = '';\n lastSegmentLength = 0;\n lastSlash = i;\n dots = 0;\n continue;\n }\n }\n if (allowAboveRoot) {\n res += res.length > 0 ? '/..' : '..';\n lastSegmentLength = 2;\n }\n }\n else {\n if (res.length > 0)\n res += '/' + path.slice(lastSlash + 1, i);\n else\n res = path.slice(lastSlash + 1, i);\n lastSegmentLength = i - lastSlash - 1;\n }\n lastSlash = i;\n dots = 0;\n }\n else if (char === '.' && dots !== -1) {\n ++dots;\n }\n else {\n dots = -1;\n }\n }\n return res;\n}\nexport function formatExt(ext) {\n return ext ? `${ext[0] === '.' ? '' : '.'}${ext}` : '';\n}\nexport function resolve(...args) {\n let resolvedPath = '';\n let resolvedAbsolute = false;\n for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n const path = i >= 0 ? args[i] : cwd;\n validateString(path, `paths[${i}]`);\n // Skip empty entries\n if (path.length === 0) {\n continue;\n }\n resolvedPath = `${path}/${resolvedPath}`;\n resolvedAbsolute = path[0] === '/';\n }\n // At this point the path should be resolved to a full absolute path, but\n // handle relative paths to be safe (might happen when process.cwd() fails)\n // Normalize the path\n resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);\n if (resolvedAbsolute) {\n return `/${resolvedPath}`;\n }\n return resolvedPath.length > 0 ? resolvedPath : '.';\n}\nexport function normalize(path) {\n validateString(path, 'path');\n if (path.length === 0)\n return '.';\n const isAbsolute = path[0] === '/';\n const trailingSeparator = path.at(-1) === '/';\n // Normalize the path\n path = normalizeString(path, !isAbsolute);\n if (path.length === 0) {\n if (isAbsolute)\n return '/';\n return trailingSeparator ? './' : '.';\n }\n if (trailingSeparator)\n path += '/';\n return isAbsolute ? `/${path}` : path;\n}\nexport function isAbsolute(path) {\n validateString(path, 'path');\n return path.length > 0 && path[0] === '/';\n}\nexport function join(...args) {\n if (args.length === 0)\n return '.';\n let joined;\n for (let i = 0; i < args.length; ++i) {\n const arg = args[i];\n validateString(arg, 'path');\n if (arg.length > 0) {\n if (joined === undefined)\n joined = arg;\n else\n joined += `/${arg}`;\n }\n }\n if (joined === undefined)\n return '.';\n return normalize(joined);\n}\nexport function relative(from, to) {\n validateString(from, 'from');\n validateString(to, 'to');\n if (from === to)\n return '';\n // Trim leading forward slashes.\n from = resolve(from);\n to = resolve(to);\n if (from === to)\n return '';\n const fromStart = 1;\n const fromEnd = from.length;\n const fromLen = fromEnd - fromStart;\n const toStart = 1;\n const toLen = to.length - toStart;\n // Compare paths to find the longest common path from root\n const length = fromLen < toLen ? fromLen : toLen;\n let lastCommonSep = -1;\n let i = 0;\n for (; i < length; i++) {\n const fromCode = from[fromStart + i];\n if (fromCode !== to[toStart + i])\n break;\n else if (fromCode === '/')\n lastCommonSep = i;\n }\n if (i === length) {\n if (toLen > length) {\n if (to[toStart + i] === '/') {\n // We get here if `from` is the exact base path for `to`.\n // For example: from='/foo/bar'; to='/foo/bar/baz'\n return to.slice(toStart + i + 1);\n }\n if (i === 0) {\n // We get here if `from` is the root\n // For example: from='/'; to='/foo'\n return to.slice(toStart + i);\n }\n }\n else if (fromLen > length) {\n if (from[fromStart + i] === '/') {\n // We get here if `to` is the exact base path for `from`.\n // For example: from='/foo/bar/baz'; to='/foo/bar'\n lastCommonSep = i;\n }\n else if (i === 0) {\n // We get here if `to` is the root.\n // For example: from='/foo/bar'; to='/'\n lastCommonSep = 0;\n }\n }\n }\n let out = '';\n // Generate the relative path based on the path difference between `to`\n // and `from`.\n for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {\n if (i === fromEnd || from[i] === '/') {\n out += out.length === 0 ? '..' : '/..';\n }\n }\n // Lastly, append the rest of the destination (`to`) path that comes after\n // the common path parts.\n return `${out}${to.slice(toStart + lastCommonSep)}`;\n}\nexport function dirname(path) {\n validateString(path, 'path');\n if (path.length === 0)\n return '.';\n const hasRoot = path[0] === '/';\n let end = -1;\n let matchedSlash = true;\n for (let i = path.length - 1; i >= 1; --i) {\n if (path[i] === '/') {\n if (!matchedSlash) {\n end = i;\n break;\n }\n }\n else {\n // We saw the first non-path separator\n matchedSlash = false;\n }\n }\n if (end === -1)\n return hasRoot ? '/' : '.';\n if (hasRoot && end === 1)\n return '//';\n return path.slice(0, end);\n}\nexport function basename(path, suffix) {\n if (suffix !== undefined)\n validateString(suffix, 'ext');\n validateString(path, 'path');\n let start = 0;\n let end = -1;\n let matchedSlash = true;\n if (suffix !== undefined && suffix.length > 0 && suffix.length <= path.length) {\n if (suffix === path)\n return '';\n let extIdx = suffix.length - 1;\n let firstNonSlashEnd = -1;\n for (let i = path.length - 1; i >= 0; --i) {\n if (path[i] === '/') {\n // If we reached a path separator that was not part of a set of path\n // separators at the end of the string, stop now\n if (!matchedSlash) {\n start = i + 1;\n break;\n }\n }\n else {\n if (firstNonSlashEnd === -1) {\n // We saw the first non-path separator, remember this index in case\n // we need it if the extension ends up not matching\n matchedSlash = false;\n firstNonSlashEnd = i + 1;\n }\n if (extIdx >= 0) {\n // Try to match the explicit extension\n if (path[i] === suffix[extIdx]) {\n if (--extIdx === -1) {\n // We matched the extension, so mark this as the end of our path\n // component\n end = i;\n }\n }\n else {\n // Extension does not match, so our result is the entire path\n // component\n extIdx = -1;\n end = firstNonSlashEnd;\n }\n }\n }\n }\n if (start === end)\n end = firstNonSlashEnd;\n else if (end === -1)\n end = path.length;\n return path.slice(start, end);\n }\n for (let i = path.length - 1; i >= 0; --i) {\n if (path[i] === '/') {\n // If we reached a path separator that was not part of a set of path\n // separators at the end of the string, stop now\n if (!matchedSlash) {\n start = i + 1;\n break;\n }\n }\n else if (end === -1) {\n // We saw the first non-path separator, mark this as the end of our\n // path component\n matchedSlash = false;\n end = i + 1;\n }\n }\n if (end === -1)\n return '';\n return path.slice(start, end);\n}\nexport function extname(path) {\n validateString(path, 'path');\n let startDot = -1;\n let startPart = 0;\n let end = -1;\n let matchedSlash = true;\n // Track the state of characters (if any) we see before our first dot and\n // after any path separator we find\n let preDotState = 0;\n for (let i = path.length - 1; i >= 0; --i) {\n if (path[i] === '/') {\n // If we reached a path separator that was not part of a set of path\n // separators at the end of the string, stop now\n if (!matchedSlash) {\n startPart = i + 1;\n break;\n }\n continue;\n }\n if (end === -1) {\n // We saw the first non-path separator, mark this as the end of our\n // extension\n matchedSlash = false;\n end = i + 1;\n }\n if (path[i] === '.') {\n // If this is our first dot, mark it as the start of our extension\n if (startDot === -1)\n startDot = i;\n else if (preDotState !== 1)\n preDotState = 1;\n }\n else if (startDot !== -1) {\n // We saw a non-dot and non-path separator before our dot, so we should\n // have a good chance at having a non-empty extension\n preDotState = -1;\n }\n }\n if (startDot === -1 ||\n end === -1 ||\n // We saw a non-dot character immediately before the dot\n preDotState === 0 ||\n // The (right-most) trimmed path component is exactly '..'\n (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)) {\n return '';\n }\n return path.slice(startDot, end);\n}\nexport function format(pathObject) {\n validateObject(pathObject, 'pathObject');\n const dir = pathObject.dir || pathObject.root;\n const base = pathObject.base || `${pathObject.name || ''}${formatExt(pathObject.ext)}`;\n if (!dir) {\n return base;\n }\n return dir === pathObject.root ? `${dir}${base}` : `${dir}/${base}`;\n}\nexport function parse(path) {\n validateString(path, 'path');\n const isAbsolute = path[0] === '/';\n const ret = { root: isAbsolute ? '/' : '', dir: '', base: '', ext: '', name: '' };\n if (path.length === 0)\n return ret;\n const start = isAbsolute ? 1 : 0;\n let startDot = -1;\n let startPart = 0;\n let end = -1;\n let matchedSlash = true;\n let i = path.length - 1;\n // Track the state of characters (if any) we see before our first dot and\n // after any path separator we find\n let preDotState = 0;\n // Get non-dir info\n for (; i >= start; --i) {\n if (path[i] === '/') {\n // If we reached a path separator that was not part of a set of path\n // separators at the end of the string, stop now\n if (!matchedSlash) {\n startPart = i + 1;\n break;\n }\n continue;\n }\n if (end === -1) {\n // We saw the first non-path separator, mark this as the end of our\n // extension\n matchedSlash = false;\n end = i + 1;\n }\n if (path[i] === '.') {\n // If this is our first dot, mark it as the start of our extension\n if (startDot === -1)\n startDot = i;\n else if (preDotState !== 1)\n preDotState = 1;\n }\n else if (startDot !== -1) {\n // We saw a non-dot and non-path separator before our dot, so we should\n // have a good chance at having a non-empty extension\n preDotState = -1;\n }\n }\n if (end !== -1) {\n const start = startPart === 0 && isAbsolute ? 1 : startPart;\n if (startDot === -1 ||\n // We saw a non-dot character immediately before the dot\n preDotState === 0 ||\n // The (right-most) trimmed path component is exactly '..'\n (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)) {\n ret.base = ret.name = path.slice(start, end);\n }\n else {\n ret.name = path.slice(start, startDot);\n ret.base = path.slice(start, end);\n ret.ext = path.slice(startDot, end);\n }\n }\n if (startPart > 0)\n ret.dir = path.slice(0, startPart - 1);\n else if (isAbsolute)\n ret.dir = '/';\n return ret;\n}\n", "/**\n * Standard libc error codes. More will be added to this enum and ErrorStrings as they are\n * needed.\n * @url http://www.gnu.org/software/libc/manual/html_node/Error-Codes.html\n */\nexport var ErrorCode;\n(function (ErrorCode) {\n /**\n * Operation not permitted\n */\n ErrorCode[ErrorCode[\"EPERM\"] = 1] = \"EPERM\";\n /**\n * No such file or directory\n */\n ErrorCode[ErrorCode[\"ENOENT\"] = 2] = \"ENOENT\";\n /**\n * Input/output error\n */\n ErrorCode[ErrorCode[\"EIO\"] = 5] = \"EIO\";\n /**\n * Bad file descriptor\n */\n ErrorCode[ErrorCode[\"EBADF\"] = 9] = \"EBADF\";\n /**\n * Permission denied\n */\n ErrorCode[ErrorCode[\"EACCES\"] = 13] = \"EACCES\";\n /**\n * Resource busy or locked\n */\n ErrorCode[ErrorCode[\"EBUSY\"] = 16] = \"EBUSY\";\n /**\n * File exists\n */\n ErrorCode[ErrorCode[\"EEXIST\"] = 17] = \"EEXIST\";\n /**\n * File is not a directory\n */\n ErrorCode[ErrorCode[\"ENOTDIR\"] = 20] = \"ENOTDIR\";\n /**\n * File is a directory\n */\n ErrorCode[ErrorCode[\"EISDIR\"] = 21] = \"EISDIR\";\n /**\n * Invalid argument\n */\n ErrorCode[ErrorCode[\"EINVAL\"] = 22] = \"EINVAL\";\n /**\n * File is too big\n */\n ErrorCode[ErrorCode[\"EFBIG\"] = 27] = \"EFBIG\";\n /**\n * No space left on disk\n */\n ErrorCode[ErrorCode[\"ENOSPC\"] = 28] = \"ENOSPC\";\n /**\n * Cannot modify a read-only file system\n */\n ErrorCode[ErrorCode[\"EROFS\"] = 30] = \"EROFS\";\n /**\n * Directory is not empty\n */\n ErrorCode[ErrorCode[\"ENOTEMPTY\"] = 39] = \"ENOTEMPTY\";\n /**\n * Operation is not supported\n */\n ErrorCode[ErrorCode[\"ENOTSUP\"] = 95] = \"ENOTSUP\";\n})(ErrorCode = ErrorCode || (ErrorCode = {}));\n/**\n * Strings associated with each error code.\n * @internal\n */\nexport const ErrorStrings = {\n [ErrorCode.EPERM]: 'Operation not permitted.',\n [ErrorCode.ENOENT]: 'No such file or directory.',\n [ErrorCode.EIO]: 'Input/output error.',\n [ErrorCode.EBADF]: 'Bad file descriptor.',\n [ErrorCode.EACCES]: 'Permission denied.',\n [ErrorCode.EBUSY]: 'Resource busy or locked.',\n [ErrorCode.EEXIST]: 'File exists.',\n [ErrorCode.ENOTDIR]: 'File is not a directory.',\n [ErrorCode.EISDIR]: 'File is a directory.',\n [ErrorCode.EINVAL]: 'Invalid argument.',\n [ErrorCode.EFBIG]: 'File is too big.',\n [ErrorCode.ENOSPC]: 'No space left on disk.',\n [ErrorCode.EROFS]: 'Cannot modify a read-only file system.',\n [ErrorCode.ENOTEMPTY]: 'Directory is not empty.',\n [ErrorCode.ENOTSUP]: 'Operation is not supported.',\n};\n/**\n * Represents a BrowserFS error. Passed back to applications after a failed\n * call to the BrowserFS API.\n */\nexport class ApiError extends Error {\n static fromJSON(json) {\n const err = new ApiError(json.errno, json.message, json.path);\n err.code = json.code;\n err.stack = json.stack;\n return err;\n }\n static OnPath(code, path) {\n return new ApiError(code, ErrorStrings[code], path);\n }\n static EACCES(path) {\n return this.OnPath(ErrorCode.EACCES, path);\n }\n static ENOENT(path) {\n return this.OnPath(ErrorCode.ENOENT, path);\n }\n static EEXIST(path) {\n return this.OnPath(ErrorCode.EEXIST, path);\n }\n static EISDIR(path) {\n return this.OnPath(ErrorCode.EISDIR, path);\n }\n static ENOTDIR(path) {\n return this.OnPath(ErrorCode.ENOTDIR, path);\n }\n static EPERM(path) {\n return this.OnPath(ErrorCode.EPERM, path);\n }\n static ENOTEMPTY(path) {\n return this.OnPath(ErrorCode.ENOTEMPTY, path);\n }\n /**\n * Represents a BrowserFS error. Passed back to applications after a failed\n * call to the BrowserFS API.\n *\n * Error codes mirror those returned by regular Unix file operations, which is\n * what Node returns.\n * @constructor ApiError\n * @param type The type of the error.\n * @param message A descriptive error message.\n */\n constructor(errno, message = ErrorStrings[errno], path) {\n super(message);\n this.errno = errno;\n this.path = path;\n // Unsupported.\n this.syscall = '';\n this.code = ErrorCode[errno];\n this.message = `${this.code}: ${message}${this.path ? `, '${this.path}'` : ''}`;\n }\n /**\n * @return A friendly error message.\n */\n toString() {\n return this.message;\n }\n toJSON() {\n return {\n errno: this.errno,\n code: this.code,\n path: this.path,\n stack: this.stack,\n message: this.message,\n };\n }\n /**\n * The size of the API error in buffer-form in bytes.\n */\n bufferSize() {\n // 4 bytes for string length.\n return 4 + JSON.stringify(this.toJSON()).length;\n }\n}\n", "/**\n * Credentials used for various operations.\n * Similar to Linux's cred struct. See https://github.com/torvalds/linux/blob/master/include/linux/cred.h\n */\nexport class Cred {\n constructor(uid, gid, suid, sgid, euid, egid) {\n this.uid = uid;\n this.gid = gid;\n this.suid = suid;\n this.sgid = sgid;\n this.euid = euid;\n this.egid = egid;\n }\n}\nCred.Root = new Cred(0, 0, 0, 0, 0, 0);\n", "import { Cred } from './cred.js';\nimport { S_IFDIR, S_IFLNK, S_IFMT, S_IFREG } from './emulation/constants.js';\n/**\n * Indicates the type of the given file. Applied to 'mode'.\n */\nexport var FileType;\n(function (FileType) {\n FileType[FileType[\"FILE\"] = S_IFREG] = \"FILE\";\n FileType[FileType[\"DIRECTORY\"] = S_IFDIR] = \"DIRECTORY\";\n FileType[FileType[\"SYMLINK\"] = S_IFLNK] = \"SYMLINK\";\n})(FileType = FileType || (FileType = {}));\n/**\n * Provides information about a particular entry in the file system.\n * Common code used by both Stats and BigIntStats.\n */\nexport class StatsCommon {\n get _typename() {\n return this._isBigint ? 'bigint' : 'number';\n }\n get _typename_inverse() {\n return this._isBigint ? 'number' : 'bigint';\n }\n _convert(arg) {\n return (this._isBigint ? BigInt(arg) : Number(arg));\n }\n get atime() {\n return new Date(Number(this.atimeMs));\n }\n set atime(value) {\n this.atimeMs = this._convert(value.getTime());\n }\n get mtime() {\n return new Date(Number(this.mtimeMs));\n }\n set mtime(value) {\n this.mtimeMs = this._convert(value.getTime());\n }\n get ctime() {\n return new Date(Number(this.ctimeMs));\n }\n set ctime(value) {\n this.ctimeMs = this._convert(value.getTime());\n }\n get birthtime() {\n return new Date(Number(this.birthtimeMs));\n }\n set birthtime(value) {\n this.birthtimeMs = this._convert(value.getTime());\n }\n /**\n * Creates a new stats instance from a stats-like object. Can be used to copy stats (note)\n */\n constructor({ atimeMs, mtimeMs, ctimeMs, birthtimeMs, uid, gid, size, mode } = {}) {\n /**\n * ID of device containing file\n */\n this.dev = this._convert(0);\n /**\n * inode number\n */\n this.ino = this._convert(0);\n /**\n * device ID (if special file)\n */\n this.rdev = this._convert(0);\n /**\n * number of hard links\n */\n this.nlink = this._convert(1);\n /**\n * blocksize for file system I/O\n */\n this.blksize = this._convert(4096);\n /**\n * user ID of owner\n */\n this.uid = this._convert(0);\n /**\n * group ID of owner\n */\n this.gid = this._convert(0);\n /**\n * Some file systems stash data on stats objects.\n */\n this.fileData = null;\n const currentTime = Date.now();\n const resolveT = (val, _default) => (typeof val == this._typename ? val : this._convert(typeof val == this._typename_inverse ? val : _default));\n this.atimeMs = resolveT(atimeMs, currentTime);\n this.mtimeMs = resolveT(mtimeMs, currentTime);\n this.ctimeMs = resolveT(ctimeMs, currentTime);\n this.birthtimeMs = resolveT(birthtimeMs, currentTime);\n this.uid = resolveT(uid, 0);\n this.gid = resolveT(gid, 0);\n this.size = this._convert(size);\n const itemType = Number(mode) & S_IFMT || FileType.FILE;\n if (mode) {\n this.mode = this._convert(mode);\n }\n else {\n switch (itemType) {\n case FileType.FILE:\n this.mode = this._convert(0o644);\n break;\n case FileType.DIRECTORY:\n default:\n this.mode = this._convert(0o777);\n }\n }\n // number of 512B blocks allocated\n this.blocks = this._convert(Math.ceil(Number(size) / 512));\n // Check if mode also includes top-most bits, which indicate the file's type.\n if ((this.mode & S_IFMT) == 0) {\n this.mode = (this.mode | this._convert(itemType));\n }\n }\n /**\n * @returns true if this item is a file.\n */\n isFile() {\n return (this.mode & S_IFMT) === S_IFREG;\n }\n /**\n * @returns True if this item is a directory.\n */\n isDirectory() {\n return (this.mode & S_IFMT) === S_IFDIR;\n }\n /**\n * @returns true if this item is a symbolic link\n */\n isSymbolicLink() {\n return (this.mode & S_IFMT) === S_IFLNK;\n }\n // Currently unsupported\n isSocket() {\n return false;\n }\n isBlockDevice() {\n return false;\n }\n isCharacterDevice() {\n return false;\n }\n isFIFO() {\n return false;\n }\n /**\n * Checks if a given user/group has access to this item\n * @param mode The request access as 4 bits (unused, read, write, execute)\n * @param uid The requesting UID\n * @param gid The requesting GID\n * @returns True if the request has access, false if the request does not\n * @internal\n */\n hasAccess(mode, cred) {\n if (cred.euid === 0 || cred.egid === 0) {\n //Running as root\n return true;\n }\n const perms = this.mode & ~S_IFMT;\n let uMode = 0xf, gMode = 0xf, wMode = 0xf;\n if (cred.euid == this.uid) {\n const uPerms = (0xf00 & perms) >> 8;\n uMode = (mode ^ uPerms) & mode;\n }\n if (cred.egid == this.gid) {\n const gPerms = (0xf0 & perms) >> 4;\n gMode = (mode ^ gPerms) & mode;\n }\n const wPerms = 0xf & perms;\n wMode = (mode ^ wPerms) & mode;\n /*\n Result = 0b0xxx (read, write, execute)\n If any bits are set that means the request does not have that permission.\n */\n const result = uMode & gMode & wMode;\n return !result;\n }\n /**\n * Convert the current stats object into a cred object\n * @internal\n */\n getCred(uid = Number(this.uid), gid = Number(this.gid)) {\n return new Cred(uid, gid, Number(this.uid), Number(this.gid), uid, gid);\n }\n /**\n * Change the mode of the file. We use this helper function to prevent messing\n * up the type of the file, which is encoded in mode.\n * @internal\n */\n chmod(mode) {\n this.mode = this._convert((this.mode & S_IFMT) | mode);\n }\n /**\n * Change the owner user/group of the file.\n * This function makes sure it is a valid UID/GID (that is, a 32 unsigned int)\n * @internal\n */\n chown(uid, gid) {\n uid = Number(uid);\n gid = Number(gid);\n if (!isNaN(uid) && 0 <= uid && uid < 2 ** 32) {\n this.uid = this._convert(uid);\n }\n if (!isNaN(gid) && 0 <= gid && gid < 2 ** 32) {\n this.gid = this._convert(gid);\n }\n }\n}\n/**\n * Implementation of Node's `Stats`.\n *\n * Attribute descriptions are from `man 2 stat'\n * @see http://nodejs.org/api/fs.html#fs_class_fs_stats\n * @see http://man7.org/linux/man-pages/man2/stat.2.html\n */\nexport class Stats extends StatsCommon {\n constructor() {\n super(...arguments);\n this._isBigint = false;\n }\n /**\n * Clones the stats object.\n * @deprecated use `new Stats(stats)`\n */\n static clone(stats) {\n return new Stats(stats);\n }\n}\nStats;\n/**\n * Stats with bigint\n * @todo Implement with bigint instead of wrapping Stats\n */\nexport class BigIntStats extends StatsCommon {\n constructor() {\n super(...arguments);\n this._isBigint = true;\n }\n /**\n * Clone a stats object.\n * @deprecated use `new BigIntStats(stats)`\n */\n static clone(stats) {\n return new BigIntStats(stats);\n }\n}\nBigIntStats;\n", "import { Stats } from './stats.js';\n/**\n * Max 32-bit integer\n * @hidden\n */\nexport const size_max = 2 ** 32 - 1;\n/**\n * Room inode\n * @hidden\n */\nexport const rootIno = 0n;\n/**\n * Generates a random 32 bit integer, then converts to a hex string\n */\nfunction _random() {\n return Math.round(Math.random() * 2 ** 32).toString(16);\n}\n/**\n * Generate a random ino\n * @internal\n */\nexport function randomIno() {\n return BigInt('0x' + _random() + _random());\n}\n/**\n * Offsets for inode members\n */\nvar Offset;\n(function (Offset) {\n Offset[Offset[\"ino\"] = 0] = \"ino\";\n Offset[Offset[\"size\"] = 8] = \"size\";\n Offset[Offset[\"mode\"] = 12] = \"mode\";\n Offset[Offset[\"nlink\"] = 14] = \"nlink\";\n Offset[Offset[\"uid\"] = 18] = \"uid\";\n Offset[Offset[\"gid\"] = 22] = \"gid\";\n Offset[Offset[\"atime\"] = 26] = \"atime\";\n Offset[Offset[\"birthtime\"] = 34] = \"birthtime\";\n Offset[Offset[\"mtime\"] = 42] = \"mtime\";\n Offset[Offset[\"ctime\"] = 50] = \"ctime\";\n Offset[Offset[\"end\"] = 58] = \"end\";\n})(Offset || (Offset = {}));\n/**\n * Generic inode definition that can easily be serialized.\n */\nexport class Inode {\n get data() {\n return new Uint8Array(this.buffer);\n }\n constructor(buffer) {\n const setDefaults = !buffer;\n buffer ?? (buffer = new ArrayBuffer(Offset.end));\n if (buffer?.byteLength < Offset.end) {\n throw new RangeError(`Can not create an inode from a buffer less than ${Offset.end} bytes`);\n }\n this.view = new DataView(buffer);\n this.buffer = buffer;\n if (!setDefaults) {\n return;\n }\n // set defaults on a fresh inode\n this.ino = randomIno();\n this.nlink = 1;\n this.size = 4096;\n const now = Date.now();\n this.atimeMs = now;\n this.mtimeMs = now;\n this.ctimeMs = now;\n this.birthtimeMs = now;\n }\n get ino() {\n return this.view.getBigUint64(Offset.ino, true);\n }\n set ino(value) {\n this.view.setBigUint64(Offset.ino, value, true);\n }\n get size() {\n return this.view.getUint32(Offset.size, true);\n }\n set size(value) {\n this.view.setUint32(Offset.size, value, true);\n }\n get mode() {\n return this.view.getUint16(Offset.mode, true);\n }\n set mode(value) {\n this.view.setUint16(Offset.mode, value, true);\n }\n get nlink() {\n return this.view.getUint32(Offset.nlink, true);\n }\n set nlink(value) {\n this.view.setUint32(Offset.nlink, value, true);\n }\n get uid() {\n return this.view.getUint32(Offset.uid, true);\n }\n set uid(value) {\n this.view.setUint32(Offset.uid, value, true);\n }\n get gid() {\n return this.view.getUint32(Offset.gid, true);\n }\n set gid(value) {\n this.view.setUint32(Offset.gid, value, true);\n }\n get atimeMs() {\n return this.view.getFloat64(Offset.atime, true);\n }\n set atimeMs(value) {\n this.view.setFloat64(Offset.atime, value, true);\n }\n get birthtimeMs() {\n return this.view.getFloat64(Offset.birthtime, true);\n }\n set birthtimeMs(value) {\n this.view.setFloat64(Offset.birthtime, value, true);\n }\n get mtimeMs() {\n return this.view.getFloat64(Offset.mtime, true);\n }\n set mtimeMs(value) {\n this.view.setFloat64(Offset.mtime, value, true);\n }\n get ctimeMs() {\n return this.view.getFloat64(Offset.ctime, true);\n }\n set ctimeMs(value) {\n this.view.setFloat64(Offset.ctime, value, true);\n }\n /**\n * Handy function that converts the Inode to a Node Stats object.\n */\n toStats() {\n return new Stats(this);\n }\n /**\n * Updates the Inode using information from the stats object. Used by file\n * systems at sync time, e.g.:\n * - Program opens file and gets a File object.\n * - Program mutates file. File object is responsible for maintaining\n * metadata changes locally -- typically in a Stats object.\n * - Program closes file. File object's metadata changes are synced with the\n * file system.\n * @return True if any changes have occurred.\n */\n update(stats) {\n let hasChanged = false;\n if (this.size !== stats.size) {\n this.size = stats.size;\n hasChanged = true;\n }\n if (this.mode !== stats.mode) {\n this.mode = stats.mode;\n hasChanged = true;\n }\n if (this.nlink !== stats.nlink) {\n this.nlink = stats.nlink;\n hasChanged = true;\n }\n if (this.uid !== stats.uid) {\n this.uid = stats.uid;\n hasChanged = true;\n }\n if (this.uid !== stats.uid) {\n this.uid = stats.uid;\n hasChanged = true;\n }\n if (this.atimeMs !== stats.atimeMs) {\n this.atimeMs = stats.atimeMs;\n hasChanged = true;\n }\n if (this.mtimeMs !== stats.mtimeMs) {\n this.mtimeMs = stats.mtimeMs;\n hasChanged = true;\n }\n if (this.ctimeMs !== stats.ctimeMs) {\n this.ctimeMs = stats.ctimeMs;\n hasChanged = true;\n }\n return hasChanged;\n }\n}\n", "import { ApiError, ErrorCode } from './ApiError.js';\nimport { O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY, S_IFMT } from './emulation/constants.js';\nimport { size_max } from './inode.js';\nimport { Stats } from './stats.js';\n/**\n * @hidden\n */\nexport var ActionType;\n(function (ActionType) {\n // Indicates that the code should not do anything.\n ActionType[ActionType[\"NOP\"] = 0] = \"NOP\";\n // Indicates that the code should throw an exception.\n ActionType[ActionType[\"THROW\"] = 1] = \"THROW\";\n // Indicates that the code should truncate the file, but only if it is a file.\n ActionType[ActionType[\"TRUNCATE\"] = 2] = \"TRUNCATE\";\n // Indicates that the code should create the file.\n ActionType[ActionType[\"CREATE\"] = 3] = \"CREATE\";\n})(ActionType = ActionType || (ActionType = {}));\n/**\n * Represents one of the following file flags. A convenience object.\n *\n * - r: \tOpen file for reading. An exception occurs if the file does not exist.\n * - r+: \tOpen file for reading and writing. An exception occurs if the file does not exist.\n * - rs: \tOpen file for reading in synchronous mode. Instructs the filesystem to not cache writes.\n * - rs+: \tOpen file for reading and writing, and opens the file in synchronous mode.\n * - w: \tOpen file for writing. The file is created (if it does not exist) or truncated (if it exists).\n * - wx: \tLike 'w' but opens the file in exclusive mode.\n * - w+: \tOpen file for reading and writing. The file is created (if it does not exist) or truncated (if it exists).\n * - wx+: \tLike 'w+' but opens the file in exclusive mode.\n * - a: \tOpen file for appending. The file is created if it does not exist.\n * - ax: \tLike 'a' but opens the file in exclusive mode.\n * - a+: \tOpen file for reading and appending. The file is created if it does not exist.\n * - ax+: \tLike 'a+' but opens the file in exclusive mode.\n *\n * Exclusive mode ensures that the file path is newly created.\n */\nexport class FileFlag {\n /**\n * Get an object representing the given file flag.\n * @param flag The string or number representing the flag\n * @return The FileFlag object representing the flag\n * @throw when the flag string is invalid\n */\n static Get(flag) {\n // Check cache first.\n if (!FileFlag.cache.has(flag)) {\n FileFlag.cache.set(flag, new FileFlag(flag));\n }\n return FileFlag.cache.get(flag);\n }\n /**\n * @param flag The string or number representing the flag\n * @throw when the flag is invalid\n */\n constructor(flag) {\n if (typeof flag == 'number') {\n flag = FileFlag.StringOf(flag);\n }\n if (!FileFlag.validStrings.includes(flag)) {\n throw new ApiError(ErrorCode.EINVAL, 'Invalid flag string: ' + flag);\n }\n this._flag = flag;\n }\n /**\n * @param flag The number representing the flag\n * @returns The string representing the flag\n * @throws when the flag number is invalid\n */\n static StringOf(flag) {\n // based on https://github.com/nodejs/node/blob/abbdc3efaa455e6c907ebef5409ac8b0f222f969/lib/internal/fs/utils.js#L619\n switch (flag) {\n case O_RDONLY:\n return 'r';\n case O_RDONLY | O_SYNC:\n return 'rs';\n case O_RDWR:\n return 'r+';\n case O_RDWR | O_SYNC:\n return 'rs+';\n case O_TRUNC | O_CREAT | O_WRONLY:\n return 'w';\n case O_TRUNC | O_CREAT | O_WRONLY | O_EXCL:\n return 'wx';\n case O_TRUNC | O_CREAT | O_RDWR:\n return 'w+';\n case O_TRUNC | O_CREAT | O_RDWR | O_EXCL:\n return 'wx+';\n case O_APPEND | O_CREAT | O_WRONLY:\n return 'a';\n case O_APPEND | O_CREAT | O_WRONLY | O_EXCL:\n return 'ax';\n case O_APPEND | O_CREAT | O_RDWR:\n return 'a+';\n case O_APPEND | O_CREAT | O_RDWR | O_EXCL:\n return 'ax+';\n default:\n throw new ApiError(ErrorCode.EINVAL, 'Invalid flag number: ' + flag);\n }\n }\n /**\n * @param flag The string representing the flag\n * @returns The number representing the flag\n * @throws when the flag string is invalid\n */\n static NumberOf(flag) {\n switch (flag) {\n case 'r':\n return O_RDONLY;\n case 'rs':\n return O_RDONLY | O_SYNC;\n case 'r+':\n return O_RDWR;\n case 'rs+':\n return O_RDWR | O_SYNC;\n case 'w':\n return O_TRUNC | O_CREAT | O_WRONLY;\n case 'wx':\n return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL;\n case 'w+':\n return O_TRUNC | O_CREAT | O_RDWR;\n case 'wx+':\n return O_TRUNC | O_CREAT | O_RDWR | O_EXCL;\n case 'a':\n return O_APPEND | O_CREAT | O_WRONLY;\n case 'ax':\n return O_APPEND | O_CREAT | O_WRONLY | O_EXCL;\n case 'a+':\n return O_APPEND | O_CREAT | O_RDWR;\n case 'ax+':\n return O_APPEND | O_CREAT | O_RDWR | O_EXCL;\n default:\n throw new ApiError(ErrorCode.EINVAL, 'Invalid flag string: ' + flag);\n }\n }\n /**\n * Get the underlying flag string for this flag.\n */\n toString() {\n return this._flag;\n }\n /**\n * Get the equivalent mode (0b0xxx: read, write, execute)\n * Note: Execute will always be 0\n */\n get mode() {\n let mode = 0;\n mode <<= 1;\n mode += +this.isReadable();\n mode <<= 1;\n mode += +this.isWriteable();\n mode <<= 1;\n return mode;\n }\n /**\n * Returns true if the file is readable.\n */\n isReadable() {\n return this._flag.indexOf('r') != -1 || this._flag.indexOf('+') != -1;\n }\n /**\n * Returns true if the file is writeable.\n */\n isWriteable() {\n return this._flag.indexOf('w') != -1 || this._flag.indexOf('a') != -1 || this._flag.indexOf('+') != -1;\n }\n /**\n * Returns true if the file mode should truncate.\n */\n isTruncating() {\n return this._flag.indexOf('w') !== -1;\n }\n /**\n * Returns true if the file is appendable.\n */\n isAppendable() {\n return this._flag.indexOf('a') !== -1;\n }\n /**\n * Returns true if the file is open in synchronous mode.\n */\n isSynchronous() {\n return this._flag.indexOf('s') !== -1;\n }\n /**\n * Returns true if the file is open in exclusive mode.\n */\n isExclusive() {\n return this._flag.indexOf('x') !== -1;\n }\n /**\n * Returns one of the static fields on this object that indicates the\n * appropriate response to the path existing.\n */\n pathExistsAction() {\n if (this.isExclusive()) {\n return ActionType.THROW;\n }\n if (this.isTruncating()) {\n return ActionType.TRUNCATE;\n }\n return ActionType.NOP;\n }\n /**\n * Returns one of the static fields on this object that indicates the\n * appropriate response to the path not existing.\n */\n pathNotExistsAction() {\n if ((this.isWriteable() || this.isAppendable()) && this._flag != 'r+') {\n return ActionType.CREATE;\n }\n return ActionType.THROW;\n }\n}\n/**\n * Contains cached FileMode instances.\n */\nFileFlag.cache = new Map();\n/**\n * Array of valid mode strings.\n */\nFileFlag.validStrings = ['r', 'r+', 'rs', 'rs+', 'w', 'wx', 'w+', 'wx+', 'a', 'ax', 'a+', 'ax+'];\nexport class File {\n /**\n * Asynchronous `datasync`.\n *\n * Default implementation maps to `sync`.\n */\n datasync() {\n return this.sync();\n }\n /**\n * Synchronous `datasync`.\n *\n * Default implementation maps to `syncSync`.\n */\n datasyncSync() {\n return this.syncSync();\n }\n}\n/**\n * An implementation of the File interface that operates on a file that is\n * completely in-memory. PreloadFiles are backed by a Uint8Array.\n *\n * This is also an abstract class, as it lacks an implementation of 'sync' and\n * 'close'. Each filesystem that wishes to use this file representation must\n * extend this class and implement those two methods.\n * @todo 'close' lever that disables functionality once closed.\n */\nexport class PreloadFile extends File {\n /**\n * Creates a file with the given path and, optionally, the given contents. Note\n * that, if contents is specified, it will be mutated by the file!\n * @param _mode The mode that the file was opened using.\n * Dictates permissions and where the file pointer starts.\n * @param stats The stats object for the given file.\n * PreloadFile will mutate this object. Note that this object must contain\n * the appropriate mode that the file was opened as.\n * @param buffer A buffer containing the entire\n * contents of the file. PreloadFile will mutate this buffer. If not\n * specified, we assume it is a new file.\n */\n constructor(\n /**\n * The file system that created the file.\n */\n fs, \n /**\n * Path to the file\n */\n path, flag, stats, _buffer = new Uint8Array(new ArrayBuffer(0, { maxByteLength: size_max }))) {\n super();\n this.fs = fs;\n this.path = path;\n this.flag = flag;\n this.stats = stats;\n this._buffer = _buffer;\n this._position = 0;\n this._dirty = false;\n /*\n Note:\n This invariant is *not* maintained once the file starts getting modified.\n It only actually matters if file is readable, as writeable modes may truncate/append to file.\n */\n if (this.stats.size == _buffer.byteLength) {\n return;\n }\n if (this.flag.isReadable()) {\n throw new Error(`Size mismatch: buffer length ${_buffer.byteLength}, stats size ${this.stats.size}`);\n }\n this._dirty = true;\n }\n /**\n * Get the underlying buffer for this file. Mutating not recommended and will mess up dirty tracking.\n */\n get buffer() {\n return this._buffer;\n }\n /**\n * Get the current file position.\n *\n * We emulate the following bug mentioned in the Node documentation:\n * > On Linux, positional writes don't work when the file is opened in append\n * mode. The kernel ignores the position argument and always appends the data\n * to the end of the file.\n * @return The current file position.\n */\n get position() {\n if (this.flag.isAppendable()) {\n return this.stats.size;\n }\n return this._position;\n }\n /**\n * Set the file position.\n * @param newPos new position\n */\n set position(newPos) {\n this._position = newPos;\n }\n /**\n * Asynchronous `stat`.\n */\n async stat() {\n return new Stats(this.stats);\n }\n /**\n * Synchronous `stat`.\n */\n statSync() {\n return new Stats(this.stats);\n }\n /**\n * Asynchronous truncate.\n * @param len\n */\n truncate(len) {\n this.truncateSync(len);\n if (this.flag.isSynchronous() && !this.fs.metadata().synchronous) {\n return this.sync();\n }\n }\n /**\n * Synchronous truncate.\n * @param len\n */\n truncateSync(len) {\n this._dirty = true;\n if (!this.flag.isWriteable()) {\n throw new ApiError(ErrorCode.EPERM, 'File not opened with a writeable mode.');\n }\n this.stats.mtimeMs = Date.now();\n if (len > this._buffer.length) {\n const buf = new Uint8Array(len - this._buffer.length);\n // Write will set stats.size for us.\n this.writeSync(buf, 0, buf.length, this._buffer.length);\n if (this.flag.isSynchronous() && this.fs.metadata().synchronous) {\n this.syncSync();\n }\n return;\n }\n this.stats.size = len;\n // Truncate buffer to 'len'.\n this._buffer = this._buffer.subarray(0, len);\n if (this.flag.isSynchronous() && this.fs.metadata().synchronous) {\n this.syncSync();\n }\n }\n /**\n * Write buffer to the file.\n * Note that it is unsafe to use fs.write multiple times on the same file\n * without waiting for the callback.\n * @param buffer Uint8Array containing the data to write to\n * the file.\n * @param offset Offset in the buffer to start reading data from.\n * @param length The amount of bytes to write to the file.\n * @param position Offset from the beginning of the file where this\n * data should be written. If position is null, the data will be written at\n * the current position.\n */\n async write(buffer, offset = 0, length = this.stats.size, position = 0) {\n return this.writeSync(buffer, offset, length, position);\n }\n /**\n * Write buffer to the file.\n * Note that it is unsafe to use fs.writeSync multiple times on the same file\n * without waiting for the callback.\n * @param buffer Uint8Array containing the data to write to\n * the file.\n * @param offset Offset in the buffer to start reading data from.\n * @param length The amount of bytes to write to the file.\n * @param position Offset from the beginning of the file where this\n * data should be written. If position is null, the data will be written at\n * the current position.\n * @returns bytes written\n */\n writeSync(buffer, offset = 0, length = this.stats.size, position = 0) {\n this._dirty = true;\n position ?? (position = this.position);\n if (!this.flag.isWriteable()) {\n throw new ApiError(ErrorCode.EPERM, 'File not opened with a writeable mode.');\n }\n const endFp = position + length;\n if (endFp > this.stats.size) {\n this.stats.size = endFp;\n if (endFp > this._buffer.byteLength) {\n if (this._buffer.buffer.resizable && this._buffer.buffer.maxByteLength <= endFp) {\n this._buffer.buffer.resize(endFp);\n }\n else {\n // Extend the buffer!\n const newBuffer = new Uint8Array(new ArrayBuffer(endFp, { maxByteLength: size_max }));\n newBuffer.set(this._buffer);\n this._buffer = newBuffer;\n }\n }\n }\n this._buffer.set(buffer.slice(offset, offset + length), position);\n const len = this._buffer.byteOffset;\n this.stats.mtimeMs = Date.now();\n if (this.flag.isSynchronous()) {\n this.syncSync();\n return len;\n }\n this.position = position + len;\n return len;\n }\n /**\n * Read data from the file.\n * @param buffer The buffer that the data will be\n * written to.\n * @param offset The offset within the buffer where writing will\n * start.\n * @param length An integer specifying the number of bytes to read.\n * @param position An integer specifying where to begin reading from\n * in the file. If position is null, data will be read from the current file\n * position.\n */\n async read(buffer, offset = 0, length = this.stats.size, position = 0) {\n return { bytesRead: this.readSync(buffer, offset, length, position), buffer };\n }\n /**\n * Read data from the file.\n * @param buffer The buffer that the data will be\n * written to.\n * @param offset The offset within the buffer where writing will start.\n * @param length An integer specifying the number of bytes to read.\n * @param position An integer specifying where to begin reading from\n * in the file. If position is null, data will be read from the current file\n * position.\n * @returns number of bytes written\n */\n readSync(buffer, offset = 0, length = this.stats.size, position = 0) {\n if (!this.flag.isReadable()) {\n throw new ApiError(ErrorCode.EPERM, 'File not opened with a readable mode.');\n }\n position ?? (position = this.position);\n let end = position + length;\n if (end > this.stats.size) {\n end = position + Math.max(this.stats.size - position, 0);\n }\n this.stats.atimeMs = Date.now();\n this._position = end;\n const bytesRead = end - position;\n if (bytesRead == 0) {\n // No copy/read. Return immediatly for better performance\n return bytesRead;\n }\n buffer.set(this._buffer.slice(position, end), offset);\n return bytesRead;\n }\n /**\n * Asynchronous `fchmod`.\n * @param mode the mode\n */\n async chmod(mode) {\n this.chmodSync(mode);\n }\n /**\n * Synchronous `fchmod`.\n * @param mode\n */\n chmodSync(mode) {\n if (!this.fs.metadata().supportsProperties) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n this._dirty = true;\n this.stats.chmod(mode);\n this.syncSync();\n }\n /**\n * Asynchronous `fchown`.\n * @param uid\n * @param gid\n */\n async chown(uid, gid) {\n this.chownSync(uid, gid);\n }\n /**\n * Synchronous `fchown`.\n * @param uid\n * @param gid\n */\n chownSync(uid, gid) {\n if (!this.fs.metadata().supportsProperties) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n this._dirty = true;\n this.stats.chown(uid, gid);\n this.syncSync();\n }\n async utimes(atime, mtime) {\n this.utimesSync(atime, mtime);\n }\n utimesSync(atime, mtime) {\n if (!this.fs.metadata().supportsProperties) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n this._dirty = true;\n this.stats.atime = atime;\n this.stats.mtime = mtime;\n this.syncSync();\n }\n isDirty() {\n return this._dirty;\n }\n /**\n * Resets the dirty bit. Should only be called after a sync has completed successfully.\n */\n resetDirty() {\n this._dirty = false;\n }\n _setType(type) {\n this._dirty = true;\n this.stats.mode = (this.stats.mode & ~S_IFMT) | type;\n return this.sync();\n }\n _setTypeSync(type) {\n this._dirty = true;\n this.stats.mode = (this.stats.mode & ~S_IFMT) | type;\n this.syncSync();\n }\n}\n/**\n * For synchronous file systems\n */\nexport class SyncFile extends PreloadFile {\n constructor(_fs, _path, _flag, _stat, contents) {\n super(_fs, _path, _flag, _stat, contents);\n }\n async sync() {\n this.syncSync();\n }\n syncSync() {\n if (this.isDirty()) {\n this.fs.syncSync(this.path, this._buffer, this.stats);\n this.resetDirty();\n }\n }\n async close() {\n this.closeSync();\n }\n closeSync() {\n this.syncSync();\n }\n}\n/**\n * For the filesystems which do not sync to anything..\n */\nexport class NoSyncFile extends PreloadFile {\n constructor(_fs, _path, _flag, _stat, contents) {\n super(_fs, _path, _flag, _stat, contents);\n }\n /**\n * Asynchronous sync. Doesn't do anything, simply calls the cb.\n */\n async sync() {\n return;\n }\n /**\n * Synchronous sync. Doesn't do anything.\n */\n syncSync() {\n // NOP.\n }\n /**\n * Asynchronous close. Doesn't do anything, simply calls the cb.\n */\n async close() {\n return;\n }\n /**\n * Synchronous close. Doesn't do anything.\n */\n closeSync() {\n // NOP.\n }\n}\n", "import { ApiError, ErrorCode } from './ApiError.js';\n/**\n * Structure for a filesystem. All BrowserFS FileSystems must implement this.\n *\n * This class includes some default implementations\n *\n * Assume the following about arguments passed to each API method:\n *\n * - Every path is an absolute path. `.`, `..`, and other items are resolved into an absolute form.\n * - All arguments are present. Any optional arguments at the Node API level have been passed in with their default values.\n */\nexport class FileSystem {\n metadata() {\n return {\n name: this.constructor.name,\n readonly: false,\n synchronous: false,\n supportsProperties: false,\n totalSpace: 0,\n freeSpace: 0,\n };\n }\n /* eslint-disable-next-line @typescript-eslint/no-unused-vars */\n constructor(options) {\n // unused\n }\n /**\n * Test whether or not the given path exists by checking with the file system.\n */\n async exists(path, cred) {\n try {\n await this.stat(path, cred);\n return true;\n }\n catch (e) {\n return false;\n }\n }\n /**\n * Test whether or not the given path exists by checking with the file system.\n */\n existsSync(path, cred) {\n try {\n this.statSync(path, cred);\n return true;\n }\n catch (e) {\n return false;\n }\n }\n}\n/**\n * Implements the asynchronous API in terms of the synchronous API.\n */\nexport function Sync(FS) {\n /**\n * Implements the asynchronous API in terms of the synchronous API.\n */\n class _SyncFileSystem extends FS {\n metadata() {\n return { ...super.metadata(), synchronous: true };\n }\n async ready() {\n return this;\n }\n async exists(path, cred) {\n return this.existsSync(path, cred);\n }\n async rename(oldPath, newPath, cred) {\n return this.renameSync(oldPath, newPath, cred);\n }\n async stat(path, cred) {\n return this.statSync(path, cred);\n }\n async createFile(path, flag, mode, cred) {\n return this.createFileSync(path, flag, mode, cred);\n }\n async openFile(path, flag, cred) {\n return this.openFileSync(path, flag, cred);\n }\n async unlink(path, cred) {\n return this.unlinkSync(path, cred);\n }\n async rmdir(path, cred) {\n return this.rmdirSync(path, cred);\n }\n async mkdir(path, mode, cred) {\n return this.mkdirSync(path, mode, cred);\n }\n async readdir(path, cred) {\n return this.readdirSync(path, cred);\n }\n async link(srcpath, dstpath, cred) {\n return this.linkSync(srcpath, dstpath, cred);\n }\n async sync(path, data, stats) {\n return this.syncSync(path, data, stats);\n }\n }\n return _SyncFileSystem;\n}\nexport function Async(FS) {\n class _AsyncFileSystem extends FS {\n metadata() {\n return { ...super.metadata(), synchronous: false };\n }\n /* eslint-disable @typescript-eslint/no-unused-vars */\n renameSync(oldPath, newPath, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n statSync(path, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n createFileSync(path, flag, mode, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n openFileSync(path, flag, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n unlinkSync(path, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n rmdirSync(path, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n mkdirSync(path, mode, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n readdirSync(path, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n linkSync(srcpath, dstpath, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n syncSync(path, data, stats) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n }\n /* eslint-enable @typescript-eslint/no-unused-vars */\n return _AsyncFileSystem;\n}\nexport function Readonly(FS) {\n class _ReadonlyFileSystem extends FS {\n metadata() {\n return { ...super.metadata(), readonly: true };\n }\n /* eslint-disable @typescript-eslint/no-unused-vars */\n async rename(oldPath, newPath, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n renameSync(oldPath, newPath, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n async createFile(path, flag, mode, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n createFileSync(path, flag, mode, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n async unlink(path, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n unlinkSync(path, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n async rmdir(path, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n rmdirSync(path, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n async mkdir(path, mode, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n mkdirSync(path, mode, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n async link(srcpath, dstpath, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n linkSync(srcpath, dstpath, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n async sync(path, data, stats) {\n throw new ApiError(ErrorCode.EROFS);\n }\n syncSync(path, data, stats) {\n throw new ApiError(ErrorCode.EROFS);\n }\n }\n return _ReadonlyFileSystem;\n}\n", "import { basename, dirname, join } from '@zenfs/core/emulation/path.js';\nimport { ApiError, ErrorCode } from '@zenfs/core/ApiError.js';\nimport { FileFlag, PreloadFile } from '@zenfs/core/file.js';\nimport { FileSystem, Async, type FileSystemMetadata } from '@zenfs/core/filesystem.js';\nimport { Stats, FileType } from '@zenfs/core/stats.js';\nimport type { Backend } from '@zenfs/core/backends/backend.js';\n\ndeclare global {\n\tinterface FileSystemDirectoryHandle {\n\t\t[Symbol.iterator](): IterableIterator<[string, FileSystemHandle]>;\n\t\tentries(): IterableIterator<[string, FileSystemHandle]>;\n\t\tkeys(): IterableIterator<string>;\n\t\tvalues(): IterableIterator<FileSystemHandle>;\n\t}\n}\n\ninterface FileSystemAccessOptions {\n\thandle: FileSystemDirectoryHandle;\n}\n\nconst handleError = (path = '', error: Error) => {\n\tif (error.name === 'NotFoundError') {\n\t\tthrow ApiError.ENOENT(path);\n\t}\n\n\tthrow error as ApiError;\n};\n\nexport class FileSystemAccessFile extends PreloadFile<FileSystemAccessFS> {\n\tconstructor(_fs: FileSystemAccessFS, _path: string, _flag: FileFlag, _stat: Stats, contents?: Uint8Array) {\n\t\tsuper(_fs, _path, _flag, _stat, contents);\n\t}\n\n\tpublic syncSync(): void {\n\t\tthrow new ApiError(ErrorCode.ENOTSUP);\n\t}\n\n\tpublic async sync(): Promise<void> {\n\t\tif (this.isDirty()) {\n\t\t\tawait this.fs.sync(this.path, this.buffer, this.stats);\n\t\t\tthis.resetDirty();\n\t\t}\n\t}\n\n\tpublic async close(): Promise<void> {\n\t\tawait this.sync();\n\t}\n\n\tpublic closeSync(): void {\n\t\tthrow new ApiError(ErrorCode.ENOTSUP);\n\t}\n}\n\nexport class FileSystemAccessFS extends Async(FileSystem) {\n\tprivate _handles: Map<string, FileSystemHandle> = new Map();\n\n\tpublic async ready(): Promise<this> {\n\t\treturn this;\n\t}\n\n\tpublic constructor({ handle }: FileSystemAccessOptions) {\n\t\tsuper();\n\t\tthis._handles.set('/', handle);\n\t}\n\n\tpublic metadata(): FileSystemMetadata {\n\t\treturn {\n\t\t\t...super.metadata(),\n\t\t\tname: 'FileSystemAccess',\n\t\t};\n\t}\n\n\tpublic async sync(p: string, data: Uint8Array, stats: Stats): Promise<void> {\n\t\tconst currentStats = await this.stat(p);\n\t\tif (stats.mtime !== currentStats!.mtime) {\n\t\t\tawait this.writeFile(p, data);\n\t\t}\n\t}\n\n\tpublic async rename(oldPath: string, newPath: string): Promise<void> {\n\t\ttry {\n\t\t\tconst handle = await this.getHandle(oldPath);\n\t\t\tif (handle instanceof FileSystemDirectoryHandle) {\n\t\t\t\tconst files = await this.readdir(oldPath);\n\n\t\t\t\tawait this.mkdir(newPath);\n\t\t\t\tif (files.length == 0) {\n\t\t\t\t\tawait this.unlink(oldPath);\n\t\t\t\t} else {\n\t\t\t\t\tfor (const file of files) {\n\t\t\t\t\t\tawait this.rename(join(oldPath, file), join(newPath, file));\n\t\t\t\t\t\tawait this.unlink(oldPath);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!(handle instanceof FileSystemFileHandle)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst oldFile = await handle.getFile(),\n\t\t\t\tdestFolder = await this.getHandle(dirname(newPath));\n\t\t\tif (!(destFolder instanceof FileSystemDirectoryHandle)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst newFile = await destFolder.getFileHandle(basename(newPath), { create: true });\n\t\t\tconst writable = await newFile.createWritable();\n\t\t\tconst buffer = await oldFile.arrayBuffer();\n\t\t\tawait writable.write(buffer);\n\n\t\t\twritable.close();\n\t\t\tawait this.unlink(oldPath);\n\t\t} catch (err) {\n\t\t\thandleError(oldPath, err);\n\t\t}\n\t}\n\n\tpublic async writeFile(fname: string, data: Uint8Array): Promise<void> {\n\t\tconst handle = await this.getHandle(dirname(fname));\n\t\tif (!(handle instanceof FileSystemDirectoryHandle)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst file = await handle.getFileHandle(basename(fname), { create: true });\n\t\tconst writable = await file.createWritable();\n\t\tawait writable.write(data);\n\t\tawait writable.close();\n\t}\n\n\tpublic async createFile(path: string, flag: FileFlag): Promise<FileSystemAccessFile> {\n\t\tawait this.writeFile(path, new Uint8Array());\n\t\treturn this.openFile(path, flag);\n\t}\n\n\tpublic async stat(path: string): Promise<Stats> {\n\t\tconst handle = await this.getHandle(path);\n\t\tif (!handle) {\n\t\t\tthrow ApiError.OnPath(ErrorCode.ENOENT, path);\n\t\t}\n\t\tif (handle instanceof FileSystemDirectoryHandle) {\n\t\t\treturn new Stats({ mode: 0o777 | FileType.DIRECTORY, size: 4096 });\n\t\t}\n\t\tif (handle instanceof FileSystemFileHandle) {\n\t\t\tconst { lastModified, size } = await handle.getFile();\n\t\t\treturn new Stats({ mode: 0o777 | FileType.FILE, size, mtimeMs: lastModified });\n\t\t}\n\t}\n\n\tpublic async openFile(path: string, flag: FileFlag): Promise<FileSystemAccessFile> {\n\t\tconst handle = await this.getHandle(path);\n\t\tif (handle instanceof FileSystemFileHandle) {\n\t\t\tconst file = await handle.getFile();\n\t\t\tconst data = new Uint8Array(await file.arrayBuffer());\n\t\t\tconst stats = new Stats({ mode: 0o777 | FileType.FILE, size: file.size, mtimeMs: file.lastModified });\n\t\t\treturn new FileSystemAccessFile(this, path, flag, stats, data);\n\t\t}\n\t}\n\n\tpublic async unlink(path: string): Promise<void> {\n\t\tconst handle = await this.getHandle(dirname(path));\n\t\tif (handle instanceof FileSystemDirectoryHandle) {\n\t\t\ttry {\n\t\t\t\tawait handle.removeEntry(basename(path), { recursive: true });\n\t\t\t} catch (e) {\n\t\t\t\thandleError(path, e);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async link(): Promise<void> {\n\t\tthrow new ApiError(ErrorCode.ENOTSUP);\n\t}\n\n\tpublic async rmdir(path: string): Promise<void> {\n\t\treturn this.unlink(path);\n\t}\n\n\tpublic async mkdir(path: string): Promise<void> {\n\t\tconst existingHandle = await this.getHandle(path);\n\t\tif (existingHandle) {\n\t\t\tthrow ApiError.EEXIST(path);\n\t\t}\n\n\t\tconst handle = await this.getHandle(dirname(path));\n\t\tif (handle instanceof FileSystemDirectoryHandle) {\n\t\t\tawait handle.getDirectoryHandle(basename(path), { create: true });\n\t\t}\n\t}\n\n\tpublic async readdir(path: string): Promise<string[]> {\n\t\tconst handle = await this.getHandle(path);\n\t\tif (!(handle instanceof FileSystemDirectoryHandle)) {\n\t\t\tthrow ApiError.ENOTDIR(path);\n\t\t}\n\t\tconst _keys: string[] = [];\n\t\tfor await (const key of handle.keys()) {\n\t\t\t_keys.push(join(path, key));\n\t\t}\n\t\treturn _keys;\n\t}\n\n\tprotected async getHandle(path: string): Promise<FileSystemHandle> {\n\t\tif (this._handles.has(path)) {\n\t\t\treturn this._handles.get(path);\n\t\t}\n\n\t\tlet walkedPath = '/';\n\t\tconst [, ...pathParts] = path.split('/');\n\t\tconst getHandleParts = async ([pathPart, ...remainingPathParts]: string[]) => {\n\t\t\tconst walkingPath = join(walkedPath, pathPart);\n\t\t\tconst continueWalk = (handle: FileSystemHandle) => {\n\t\t\t\twalkedPath = walkingPath;\n\t\t\t\tthis._handles.set(walkedPath, handle);\n\n\t\t\t\tif (remainingPathParts.length === 0) {\n\t\t\t\t\treturn this._handles.get(path);\n\t\t\t\t}\n\n\t\t\t\tgetHandleParts(remainingPathParts);\n\t\t\t};\n\t\t\tconst handle = this._handles.get(walkedPath) as FileSystemDirectoryHandle;\n\n\t\t\ttry {\n\t\t\t\treturn continueWalk(await handle.getDirectoryHandle(pathPart));\n\t\t\t} catch (error) {\n\t\t\t\tif (error.name === 'TypeMismatchError') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn continueWalk(await handle.getFileHandle(pathPart));\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\thandleError(walkingPath, err);\n\t\t\t\t\t}\n\t\t\t\t} else if (error.message === 'Name is not allowed.') {\n\t\t\t\t\tthrow new ApiError(ErrorCode.ENOENT, error.message, walkingPath);\n\t\t\t\t} else {\n\t\t\t\t\thandleError(walkingPath, error);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\treturn await getHandleParts(pathParts);\n\t}\n}\n\nexport const FileSystemAccess: Backend = {\n\tname: 'FileSystemAccess',\n\n\toptions: {\n\t\thandle: {\n\t\t\ttype: 'object',\n\t\t\trequired: true,\n\t\t\tdescription: 'The directory handle to use for the root',\n\t\t},\n\t},\n\n\tisAvailable(): boolean {\n\t\treturn typeof FileSystemHandle == 'function';\n\t},\n\n\tcreate(options: FileSystemAccessOptions) {\n\t\treturn new FileSystemAccessFS(options);\n\t},\n};\n", "import { ApiError, ErrorCode } from './ApiError.js';\nimport { dirname } from './emulation/path.js';\n/**\n * Synchronous recursive makedir.\n * @hidden\n */\nexport function mkdirpSync(p, mode, cred, fs) {\n if (!fs.existsSync(p, cred)) {\n mkdirpSync(dirname(p), mode, cred, fs);\n fs.mkdirSync(p, mode, cred);\n }\n}\nfunction _min(d0, d1, d2, bx, ay) {\n return Math.min(d0 + 1, d1 + 1, d2 + 1, bx === ay ? d1 : d1 + 1);\n}\n/**\n * Calculates levenshtein distance.\n * @hidden\n */\nexport function levenshtein(a, b) {\n if (a === b) {\n return 0;\n }\n if (a.length > b.length) {\n [a, b] = [b, a]; // Swap a and b\n }\n let la = a.length;\n let lb = b.length;\n // Trim common suffix\n while (la > 0 && a.charCodeAt(la - 1) === b.charCodeAt(lb - 1)) {\n la--;\n lb--;\n }\n let offset = 0;\n // Trim common prefix\n while (offset < la && a.charCodeAt(offset) === b.charCodeAt(offset)) {\n offset++;\n }\n la -= offset;\n lb -= offset;\n if (la === 0 || lb === 1) {\n return lb;\n }\n const vector = new Array(la << 1);\n for (let y = 0; y < la;) {\n vector[la + y] = a.charCodeAt(offset + y);\n vector[y] = ++y;\n }\n let x;\n let d0;\n let d1;\n let d2;\n let d3;\n for (x = 0; x + 3 < lb;) {\n const bx0 = b.charCodeAt(offset + (d0 = x));\n const bx1 = b.charCodeAt(offset + (d1 = x + 1));\n const bx2 = b.charCodeAt(offset + (d2 = x + 2));\n const bx3 = b.charCodeAt(offset + (d3 = x + 3));\n let dd = (x += 4);\n for (let y = 0; y < la;) {\n const ay = vector[la + y];\n const dy = vector[y];\n d0 = _min(dy, d0, d1, bx0, ay);\n d1 = _min(d0, d1, d2, bx1, ay);\n d2 = _min(d1, d2, d3, bx2, ay);\n dd = _min(d2, d3, dd, bx3, ay);\n vector[y++] = dd;\n d3 = d2;\n d2 = d1;\n d1 = d0;\n d0 = dy;\n }\n }\n let dd = 0;\n for (; x < lb;) {\n const bx0 = b.charCodeAt(offset + (d0 = x));\n dd = ++x;\n for (let y = 0; y < la; y++) {\n const dy = vector[y];\n vector[y] = dd = dy < d0 || dd < d0 ? (dy > dd ? dd + 1 : dy + 1) : bx0 === vector[la + y] ? d0 : d0 + 1;\n d0 = dy;\n }\n }\n return dd;\n}\n/** Waits n ms. */\nexport function wait(ms) {\n return new Promise(resolve => {\n setTimeout(resolve, ms);\n });\n}\n/**\n * @hidden\n */\nexport const setImmediate = typeof globalThis.setImmediate == 'function' ? globalThis.setImmediate : cb => setTimeout(cb, 0);\n/**\n * Encodes a string into a buffer\n * @internal\n */\nexport function encode(input, encoding = 'utf8') {\n if (typeof input != 'string') {\n throw new ApiError(ErrorCode.EINVAL, 'Can not encode a non-string');\n }\n switch (encoding) {\n case 'ascii':\n case 'latin1':\n case 'binary':\n return new Uint8Array(Array.from(input).map(char => char.charCodeAt(0)));\n case 'utf8':\n case 'utf-8':\n return new Uint8Array(Array.from(input).flatMap(char => {\n const code = char.charCodeAt(0);\n if (code < 0x80) {\n return code;\n }\n const a = (code & 0x3f) | 0x80;\n if (code < 0x800) {\n return [(code >> 6) | 0xc0, a];\n }\n const b = ((code >> 6) & 0x3f) | 0x80;\n if (code < 0x10000) {\n return [(code >> 12) | 0xe0, b, a];\n }\n return [(code >> 18) | 0xf0, ((code >> 12) & 0x3f) | 0x80, b, a];\n }));\n case 'base64':\n return encode(atob(input), 'utf-8');\n case 'base64url':\n return encode(input.replace('_', '/').replace('-', '+'), 'base64');\n case 'hex':\n return new Uint8Array(input.match(/.{1,2}/g).map(e => parseInt(e, 16)));\n case 'utf16le':\n case 'ucs2':\n case 'ucs-2':\n const u16 = new Uint16Array(new ArrayBuffer(input.length * 2));\n for (let i = 0; i < input.length; i++) {\n u16[i] = input.charCodeAt(i);\n }\n return new Uint8Array(u16.buffer);\n default:\n throw new ApiError(ErrorCode.EINVAL, 'Invalid encoding: ' + encoding);\n }\n}\n/**\n * Decodes a string from a buffer\n * @internal\n */\nexport function decode(input, encoding = 'utf8') {\n if (!(input instanceof Uint8Array)) {\n throw new ApiError(ErrorCode.EINVAL, 'Can not decode a non-Uint8Array');\n }\n switch (encoding) {\n case 'ascii':\n case 'latin1':\n case 'binary':\n return Array.from(input)\n .map(char => String.fromCharCode(char))\n .join('');\n case 'utf8':\n case 'utf-8':\n let utf8String = '';\n for (let i = 0; i < input.length; i++) {\n let code;\n if (input[i] < 0x80) {\n code = input[i];\n }\n else if (input[i] < 0xe0) {\n code = ((input[i] & 0x1f) << 6) | (input[++i] & 0x3f);\n }\n else if (input[i] < 0xf0) {\n code = ((input[i] & 0x0f) << 12) | ((input[++i] & 0x3f) << 6) | (input[++i] & 0x3f);\n }\n else {\n code = ((input[i] & 0x07) << 18) | ((input[++i] & 0x3f) << 12) | ((input[++i] & 0x3f) << 6) | (input[++i] & 0x3f);\n }\n utf8String += String.fromCharCode(code);\n }\n return utf8String;\n case 'utf16le':\n case 'ucs2':\n case 'ucs-2':\n let utf16leString = '';\n for (let i = 0; i < input.length; i += 2) {\n const code = input[i] | (input[i + 1] << 8);\n utf16leString += String.fromCharCode(code);\n }\n return utf16leString;\n case 'base64':\n return btoa(decode(input, 'utf-8'));\n case 'base64url':\n return decode(input, 'base64').replace('/', '_').replace('+', '-');\n case 'hex':\n return Array.from(input)\n .map(e => e.toString(16).padStart(2, '0'))\n .join('');\n default:\n throw new ApiError(ErrorCode.EINVAL, 'Invalid encoding: ' + encoding);\n }\n}\n/**\n * Decodes a directory listing\n * @internal\n */\nexport function decodeDirListing(data) {\n return JSON.parse(decode(data), (k, v) => {\n if (k == '') {\n return v;\n }\n return BigInt(v);\n });\n}\n/**\n * Encodes a directory listing\n * @internal\n */\nexport function encodeDirListing(data) {\n return encode(JSON.stringify(data, (k, v) => {\n if (k == '') {\n return v;\n }\n return v.toString();\n }));\n}\n", "import { dirname, basename, join, resolve } from '../emulation/path.js';\nimport { ApiError, ErrorCode } from '../ApiError.js';\nimport { W_OK, R_OK } from '../emulation/constants.js';\nimport { PreloadFile } from '../file.js';\nimport { Async, FileSystem } from '../filesystem.js';\nimport { randomIno, Inode } from '../inode.js';\nimport { FileType } from '../stats.js';\nimport { encode, decodeDirListing, encodeDirListing } from '../utils.js';\nimport { rootIno } from '../inode.js';\n/**\n * Last Recently Used cache\n */\nclass LRUCache {\n constructor(limit) {\n this.limit = limit;\n this.cache = [];\n }\n set(key, value) {\n const existingIndex = this.cache.findIndex(node => node.key === key);\n if (existingIndex != -1) {\n this.cache.splice(existingIndex, 1);\n }\n else if (this.cache.length >= this.limit) {\n this.cache.shift();\n }\n this.cache.push({ key, value });\n }\n get(key) {\n const node = this.cache.find(n => n.key === key);\n if (!node) {\n return;\n }\n // Move the accessed item to the end of the cache (most recently used)\n this.set(key, node.value);\n return node.value;\n }\n remove(key) {\n const index = this.cache.findIndex(node => node.key === key);\n if (index !== -1) {\n this.cache.splice(index, 1);\n }\n }\n reset() {\n this.cache = [];\n }\n}\n/**\n * Async preload file for usage with AsyncStore\n * @internal\n */\nexport class AsyncFile extends PreloadFile {\n constructor(_fs, _path, _flag, _stat, contents) {\n super(_fs, _path, _flag, _stat, contents);\n }\n async sync() {\n if (!this.isDirty()) {\n return;\n }\n await this.fs.sync(this.path, this._buffer, this.stats);\n this.resetDirty();\n }\n syncSync() {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n async close() {\n this.sync();\n }\n closeSync() {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n}\n/**\n * An asynchronous file system which uses an async store to store its data.\n * @see AsyncStore\n * @internal\n */\nexport class AsyncStoreFS extends Async(FileSystem) {\n ready() {\n return this._ready;\n }\n metadata() {\n return {\n ...super.metadata(),\n name: this.store.name,\n };\n }\n constructor({ store, cacheSize }) {\n super();\n if (cacheSize > 0) {\n this._cache = new LRUCache(cacheSize);\n }\n this._ready = this._initialize(store);\n }\n /**\n * Initializes the file system. Typically called by subclasses' async\n * constructors.\n */\n async _initialize(store) {\n this.store = await store;\n // INVARIANT: Ensure that the root exists.\n await this.makeRootDirectory();\n return this;\n }\n /**\n * Delete all contents stored in the file system.\n */\n async empty() {\n if (this._cache) {\n this._cache.reset();\n }\n await this.store.clear();\n // INVARIANT: Root always exists.\n await this.makeRootDirectory();\n }\n /**\n * @todo Make rename compatible with the cache.\n */\n async rename(oldPath, newPath, cred) {\n const c = this._cache;\n if (this._cache) {\n // Clear and disable cache during renaming process.\n this._cache = null;\n c.reset();\n }\n try {\n const tx = this.store.beginTransaction('readwrite'), oldParent = dirname(oldPath), oldName = basename(oldPath), newParent = dirname(newPath), newName = basename(newPath), \n // Remove oldPath from parent's directory listing.\n oldDirNode = await this.findINode(tx, oldParent), oldDirList = await this.getDirListing(tx, oldDirNode, oldParent);\n if (!oldDirNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(oldPath);\n }\n if (!oldDirList[oldName]) {\n throw ApiError.ENOENT(oldPath);\n }\n const nodeId = oldDirList[oldName];\n delete oldDirList[oldName];\n // Invariant: Can't move a folder inside itself.\n // This funny little hack ensures that the check passes only if oldPath\n // is a subpath of newParent. We append '/' to avoid matching folders that\n // are a substring of the bottom-most folder in the path.\n if ((newParent + '/').indexOf(oldPath + '/') === 0) {\n throw new ApiError(ErrorCode.EBUSY, oldParent);\n }\n // Add newPath to parent's directory listing.\n let newDirNode, newDirList;\n if (newParent === oldParent) {\n // Prevent us from re-grabbing the same directory listing, which still\n // contains oldName.\n newDirNode = oldDirNode;\n newDirList = oldDirList;\n }\n else {\n newDirNode = await this.findINode(tx, newParent);\n newDirList = await this.getDirListing(tx, newDirNode, newParent);\n }\n if (newDirList[newName]) {\n // If it's a file, delete it.\n const newNameNode = await this.getINode(tx, newDirList[newName], newPath);\n if (newNameNode.toStats().isFile()) {\n try {\n await tx.remove(newNameNode.ino);\n await tx.remove(newDirList[newName]);\n }\n catch (e) {\n await tx.abort();\n throw e;\n }\n }\n else {\n // If it's a directory, throw a permissions error.\n throw ApiError.EPERM(newPath);\n }\n }\n newDirList[newName] = nodeId;\n // Commit the two changed directory listings.\n try {\n await tx.put(oldDirNode.ino, encodeDirListing(oldDirList), true);\n await tx.put(newDirNode.ino, encodeDirListing(newDirList), true);\n }\n catch (e) {\n await tx.abort();\n throw e;\n }\n await tx.commit();\n }\n finally {\n if (c) {\n this._cache = c;\n }\n }\n }\n async stat(p, cred) {\n const tx = this.store.beginTransaction('readonly');\n const inode = await this.findINode(tx, p);\n if (!inode) {\n throw ApiError.ENOENT(p);\n }\n const stats = inode.toStats();\n if (!stats.hasAccess(R_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n return stats;\n }\n async createFile(p, flag, mode, cred) {\n const tx = this.store.beginTransaction('readwrite'), data = new Uint8Array(0), newFile = await this.commitNewFile(tx, p, FileType.FILE, mode, cred, data);\n // Open the file.\n return new AsyncFile(this, p, flag, newFile.toStats(), data);\n }\n async openFile(p, flag, cred) {\n const tx = this.store.beginTransaction('readonly'), node = await this.findINode(tx, p), data = await tx.get(node.ino);\n if (!node.toStats().hasAccess(flag.mode, cred)) {\n throw ApiError.EACCES(p);\n }\n if (!data) {\n throw ApiError.ENOENT(p);\n }\n return new AsyncFile(this, p, flag, node.toStats(), data);\n }\n async unlink(p, cred) {\n return this.removeEntry(p, false, cred);\n }\n async rmdir(p, cred) {\n // Check first if directory is empty.\n const list = await this.readdir(p, cred);\n if (list.length > 0) {\n throw ApiError.ENOTEMPTY(p);\n }\n await this.removeEntry(p, true, cred);\n }\n async mkdir(p, mode, cred) {\n const tx = this.store.beginTransaction('readwrite'), data = encode('{}');\n await this.commitNewFile(tx, p, FileType.DIRECTORY, mode, cred, data);\n }\n async readdir(p, cred) {\n const tx = this.store.beginTransaction('readonly');\n const node = await this.findINode(tx, p);\n if (!node.toStats().hasAccess(R_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n return Object.keys(await this.getDirListing(tx, node, p));\n }\n /**\n * Updated the inode and data node at the given path\n * @todo Ensure mtime updates properly, and use that to determine if a data update is required.\n */\n async sync(p, data, stats) {\n const tx = this.store.beginTransaction('readwrite'), \n // We use the _findInode helper because we actually need the INode id.\n fileInodeId = await this._findINode(tx, dirname(p), basename(p)), fileInode = await this.getINode(tx, fileInodeId, p), inodeChanged = fileInode.update(stats);\n try {\n // Sync data.\n await tx.put(fileInode.ino, data, true);\n // Sync metadata.\n if (inodeChanged) {\n await tx.put(fileInodeId, fileInode.data, true);\n }\n }\n catch (e) {\n await tx.abort();\n throw e;\n }\n await tx.commit();\n }\n async link(existing, newpath, cred) {\n const tx = this.store.beginTransaction('readwrite'), existingDir = dirname(existing), existingDirNode = await this.findINode(tx, existingDir);\n if (!existingDirNode.toStats().hasAccess(R_OK, cred)) {\n throw ApiError.EACCES(existingDir);\n }\n const newDir = dirname(newpath), newDirNode = await this.findINode(tx, newDir), newListing = await this.getDirListing(tx, newDirNode, newDir);\n if (!newDirNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(newDir);\n }\n const ino = await this._findINode(tx, existingDir, basename(existing));\n const node = await this.getINode(tx, ino, existing);\n if (!node.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(newpath);\n }\n node.nlink++;\n newListing[basename(newpath)] = ino;\n try {\n tx.put(ino, node.data, true);\n tx.put(newDirNode.ino, encodeDirListing(newListing), true);\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n tx.commit();\n }\n /**\n * Checks if the root directory exists. Creates it if it doesn't.\n */\n async makeRootDirectory() {\n const tx = this.store.beginTransaction('readwrite');\n if ((await tx.get(rootIno)) === undefined) {\n // Create new inode. o777, owned by root:root\n const dirInode = new Inode();\n dirInode.mode = 0o777 | FileType.DIRECTORY;\n // If the root doesn't exist, the first random ID shouldn't exist,\n // either.\n await tx.put(dirInode.ino, encode('{}'), false);\n await tx.put(rootIno, dirInode.data, false);\n await tx.commit();\n }\n }\n /**\n * Helper function for findINode.\n * @param parent The parent directory of the file we are attempting to find.\n * @param filename The filename of the inode we are attempting to find, minus\n * the parent.\n */\n async _findINode(tx, parent, filename, visited = new Set()) {\n const currentPath = join(parent, filename);\n if (visited.has(currentPath)) {\n throw new ApiError(ErrorCode.EIO, 'Infinite loop detected while finding inode', currentPath);\n }\n visited.add(currentPath);\n if (this._cache) {\n const id = this._cache.get(currentPath);\n if (id) {\n return id;\n }\n }\n if (parent === '/') {\n if (filename === '') {\n // BASE CASE #1: Return the root's ID.\n if (this._cache) {\n this._cache.set(currentPath, rootIno);\n }\n return rootIno;\n }\n else {\n // BASE CASE #2: Find the item in the root node.\n const inode = await this.getINode(tx, rootIno, parent);\n const dirList = await this.getDirListing(tx, inode, parent);\n if (dirList[filename]) {\n const id = dirList[filename];\n if (this._cache) {\n this._cache.set(currentPath, id);\n }\n return id;\n }\n else {\n throw ApiError.ENOENT(resolve(parent, filename));\n }\n }\n }\n else {\n // Get the parent directory's INode, and find the file in its directory\n // listing.\n const inode = await this.findINode(tx, parent, visited);\n const dirList = await this.getDirListing(tx, inode, parent);\n if (dirList[filename]) {\n const id = dirList[filename];\n if (this._cache) {\n this._cache.set(currentPath, id);\n }\n return id;\n }\n else {\n throw ApiError.ENOENT(resolve(parent, filename));\n }\n }\n }\n /**\n * Finds the Inode of the given path.\n * @param p The path to look up.\n * @todo memoize/cache\n */\n async findINode(tx, p, visited = new Set()) {\n const id = await this._findINode(tx, dirname(p), basename(p), visited);\n return this.getINode(tx, id, p);\n }\n /**\n * Given the ID of a node, retrieves the corresponding Inode.\n * @param tx The transaction to use.\n * @param p The corresponding path to the file (used for error messages).\n * @param id The ID to look up.\n */\n async getINode(tx, id, p) {\n const data = await tx.get(id);\n if (!data) {\n throw ApiError.ENOENT(p);\n }\n return new Inode(data.buffer);\n }\n /**\n * Given the Inode of a directory, retrieves the corresponding directory\n * listing.\n */\n async getDirListing(tx, inode, p) {\n if (!inode.toStats().isDirectory()) {\n throw ApiError.ENOTDIR(p);\n }\n const data = await tx.get(inode.ino);\n if (!data) {\n /*\n Occurs when data is undefined, or corresponds to something other\n than a directory listing. The latter should never occur unless\n the file system is corrupted.\n */\n throw ApiError.ENOENT(p);\n }\n return decodeDirListing(data);\n }\n /**\n * Adds a new node under a random ID. Retries 5 times before giving up in\n * the exceedingly unlikely chance that we try to reuse a random ino.\n */\n async addNewNode(tx, data) {\n let retries = 0;\n const reroll = async () => {\n if (++retries === 5) {\n // Max retries hit. Return with an error.\n throw new ApiError(ErrorCode.EIO, 'Unable to commit data to key-value store.');\n }\n else {\n // Try again.\n const ino = randomIno();\n const committed = await tx.put(ino, data, false);\n if (!committed) {\n return reroll();\n }\n else {\n return ino;\n }\n }\n };\n return reroll();\n }\n /**\n * Commits a new file (well, a FILE or a DIRECTORY) to the file system with\n * the given mode.\n * Note: This will commit the transaction.\n * @param p The path to the new file.\n * @param type The type of the new file.\n * @param mode The mode to create the new file with.\n * @param cred The UID/GID to create the file with\n * @param data The data to store at the file's data node.\n */\n async commitNewFile(tx, p, type, mode, cred, data) {\n const parentDir = dirname(p), fname = basename(p), parentNode = await this.findINode(tx, parentDir), dirListing = await this.getDirListing(tx, parentNode, parentDir);\n //Check that the creater has correct access\n if (!parentNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n // Invariant: The root always exists.\n // If we don't check this prior to taking steps below, we will create a\n // file with name '' in root should p == '/'.\n if (p === '/') {\n throw ApiError.EEXIST(p);\n }\n // Check if file already exists.\n if (dirListing[fname]) {\n await tx.abort();\n throw ApiError.EEXIST(p);\n }\n try {\n // Commit data.\n const inode = new Inode();\n inode.ino = await this.addNewNode(tx, data);\n inode.mode = mode | type;\n inode.uid = cred.uid;\n inode.gid = cred.gid;\n inode.size = data.length;\n // Update and commit parent directory listing.\n dirListing[fname] = await this.addNewNode(tx, inode.data);\n await tx.put(parentNode.ino, encodeDirListing(dirListing), true);\n await tx.commit();\n return inode;\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n }\n /**\n * Remove all traces of the given path from the file system.\n * @param p The path to remove from the file system.\n * @param isDir Does the path belong to a directory, or a file?\n * @todo Update mtime.\n */\n /**\n * Remove all traces of the given path from the file system.\n * @param p The path to remove from the file system.\n * @param isDir Does the path belong to a directory, or a file?\n * @todo Update mtime.\n */\n async removeEntry(p, isDir, cred) {\n if (this._cache) {\n this._cache.remove(p);\n }\n const tx = this.store.beginTransaction('readwrite'), parent = dirname(p), parentNode = await this.findINode(tx, parent), parentListing = await this.getDirListing(tx, parentNode, parent), fileName = basename(p);\n if (!parentListing[fileName]) {\n throw ApiError.ENOENT(p);\n }\n const fileIno = parentListing[fileName];\n // Get file inode.\n const fileNode = await this.getINode(tx, fileIno, p);\n if (!fileNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n // Remove from directory listing of parent.\n delete parentListing[fileName];\n if (!isDir && fileNode.toStats().isDirectory()) {\n throw ApiError.EISDIR(p);\n }\n if (isDir && !fileNode.toStats().isDirectory()) {\n throw ApiError.ENOTDIR(p);\n }\n try {\n await tx.put(parentNode.ino, encodeDirListing(parentListing), true);\n if (--fileNode.nlink < 1) {\n // remove file\n await tx.remove(fileNode.ino);\n await tx.remove(fileIno);\n }\n }\n catch (e) {\n await tx.abort();\n throw e;\n }\n // Success.\n await tx.commit();\n }\n}\n", "import { AsyncROTransaction, AsyncRWTransaction, AsyncStore, AsyncStoreFS } from '@zenfs/core/backends/AsyncStore.js';\nimport { ApiError, ErrorCode } from '@zenfs/core/ApiError.js';\nimport type { Backend } from '@zenfs/core/backends/backend.js';\nimport type { Ino } from '@zenfs/core/inode.js';\n\n/**\n * Converts a DOMException or a DOMError from an IndexedDB event into a\n * standardized ZenFS API error.\n * @hidden\n */\nfunction convertError(e: { name: string }, message: string = e.toString()): ApiError {\n\tswitch (e.name) {\n\t\tcase 'NotFoundError':\n\t\t\treturn new ApiError(ErrorCode.ENOENT, message);\n\t\tcase 'QuotaExceededError':\n\t\t\treturn new ApiError(ErrorCode.ENOSPC, message);\n\t\tdefault:\n\t\t\t// The rest do not seem to map cleanly to standard error codes.\n\t\t\treturn new ApiError(ErrorCode.EIO, message);\n\t}\n}\n\n/**\n * @hidden\n */\nexport class IndexedDBROTransaction implements AsyncROTransaction {\n\tconstructor(public tx: IDBTransaction, public store: IDBObjectStore) {}\n\n\tpublic get(key: Ino): Promise<Uint8Array> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tconst req: IDBRequest = this.store.get(key.toString());\n\t\t\t\treq.onerror = e => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\treject(new ApiError(ErrorCode.EIO));\n\t\t\t\t};\n\t\t\t\treq.onsuccess = () => {\n\t\t\t\t\t// IDB returns the value 'undefined' when you try to get keys that\n\t\t\t\t\t// don't exist. The caller expects this behavior.\n\t\t\t\t\tconst result = req.result;\n\t\t\t\t\tif (result === undefined) {\n\t\t\t\t\t\tresolve(result);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// IDB data is stored as an ArrayUint8Array\n\t\t\t\t\t\tresolve(Uint8Array.from(result));\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t} catch (e) {\n\t\t\t\treject(convertError(e));\n\t\t\t}\n\t\t});\n\t}\n}\n\n/**\n * @hidden\n */\nexport class IndexedDBRWTransaction extends IndexedDBROTransaction implements AsyncRWTransaction, AsyncROTransaction {\n\tconstructor(tx: IDBTransaction, store: IDBObjectStore) {\n\t\tsuper(tx, store);\n\t}\n\n\t/**\n\t * @todo return false when add has a key conflict (no error)\n\t */\n\tpublic put(key: Ino, data: Uint8Array, overwrite: boolean): Promise<boolean> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tconst req: IDBRequest = overwrite ? this.store.put(data, key.toString()) : this.store.add(data, key.toString());\n\t\t\t\treq.onerror = e => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\treject(new ApiError(ErrorCode.EIO));\n\t\t\t\t};\n\t\t\t\treq.onsuccess = () => resolve(true);\n\t\t\t} catch (e) {\n\t\t\t\treject(convertError(e));\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic remove(key: Ino): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tconst req: IDBRequest = this.store.delete(key.toString());\n\t\t\t\treq.onerror = e => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\treject(new ApiError(ErrorCode.EIO));\n\t\t\t\t};\n\t\t\t\treq.onsuccess = () => resolve;\n\t\t\t} catch (e) {\n\t\t\t\treject(convertError(e));\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic commit(): Promise<void> {\n\t\treturn new Promise(resolve => setTimeout(resolve, 0));\n\t}\n\n\tpublic async abort(): Promise<void> {\n\t\ttry {\n\t\t\tthis.tx.abort();\n\t\t} catch (e) {\n\t\t\tthrow convertError(e);\n\t\t}\n\t}\n}\n\nexport class IndexedDBStore implements AsyncStore {\n\tpublic static create(storeName: string, indexedDB: IDBFactory): Promise<IndexedDBStore> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst req: IDBOpenDBRequest = indexedDB.open(storeName, 1);\n\n\t\t\treq.onupgradeneeded = () => {\n\t\t\t\tconst db: IDBDatabase = req.result;\n\t\t\t\t// This should never happen; we're at version 1. Why does another database exist?\n\t\t\t\tif (db.objectStoreNames.contains(storeName)) {\n\t\t\t\t\tdb.deleteObjectStore(storeName);\n\t\t\t\t}\n\t\t\t\tdb.createObjectStore(storeName);\n\t\t\t};\n\n\t\t\treq.onsuccess = () => resolve(new IndexedDBStore(req.result, storeName));\n\n\t\t\treq.onerror = e => {\n\t\t\t\te.preventDefault();\n\t\t\t\treject(new ApiError(ErrorCode.EACCES));\n\t\t\t};\n\t\t});\n\t}\n\n\tconstructor(protected db: IDBDatabase, protected storeName: string) {}\n\n\tpublic get name(): string {\n\t\treturn IndexedDB.name + ':' + this.storeName;\n\t}\n\n\tpublic clear(): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tconst req: IDBRequest = this.db.transaction(this.storeName, 'readwrite').objectStore(this.storeName).clear();\n\t\t\t\treq.onsuccess = () => setTimeout(resolve, 0);\n\t\t\t\treq.onerror = e => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\treject(new ApiError(ErrorCode.EIO));\n\t\t\t\t};\n\t\t\t} catch (e) {\n\t\t\t\treject(convertError(e));\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic beginTransaction(type: 'readonly'): AsyncROTransaction;\n\tpublic beginTransaction(type: 'readwrite'): AsyncRWTransaction;\n\tpublic beginTransaction(type: 'readonly' | 'readwrite' = 'readonly'): AsyncROTransaction {\n\t\tconst tx = this.db.transaction(this.storeName, type),\n\t\t\tobjectStore = tx.objectStore(this.storeName);\n\t\tif (type === 'readwrite') {\n\t\t\treturn new IndexedDBRWTransaction(tx, objectStore);\n\t\t}\n\n\t\tif (type === 'readonly') {\n\t\t\treturn new IndexedDBROTransaction(tx, objectStore);\n\t\t}\n\n\t\tthrow new ApiError(ErrorCode.EINVAL, 'Invalid transaction type.');\n\t}\n}\n\n/**\n * Configuration options for the IndexedDB file system.\n */\nexport interface IndexedDBOptions {\n\t/**\n\t * The name of this file system. You can have multiple IndexedDB file systems operating at once, but each must have a different name.\n\t */\n\tstoreName?: string;\n\n\t/**\n\t * The size of the inode cache. Defaults to 100. A size of 0 or below disables caching.\n\t */\n\tcacheSize?: number;\n\n\t/**\n\t * The IDBFactory to use. Defaults to `globalThis.indexedDB`.\n\t */\n\tidbFactory?: IDBFactory;\n}\n\n/**\n * A file system that uses the IndexedDB key value file system.\n */\n\nexport const IndexedDB: Backend = {\n\tname: 'IndexedDB',\n\n\toptions: {\n\t\tstoreName: {\n\t\t\ttype: 'string',\n\t\t\trequired: false,\n\t\t\tdescription: 'The name of this file system. You can have multiple IndexedDB file systems operating at once, but each must have a different name.',\n\t\t},\n\t\tcacheSize: {\n\t\t\ttype: 'number',\n\t\t\trequired: false,\n\t\t\tdescription: 'The size of the inode cache. Defaults to 100. A size of 0 or below disables caching.',\n\t\t},\n\t\tidbFactory: {\n\t\t\ttype: 'object',\n\t\t\trequired: false,\n\t\t\tdescription: 'The IDBFactory to use. Defaults to globalThis.indexedDB.',\n\t\t},\n\t},\n\n\tisAvailable(idbFactory: IDBFactory = globalThis.indexedDB): boolean {\n\t\ttry {\n\t\t\tif (!(idbFactory instanceof IDBFactory)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tconst req = idbFactory.open('__zenfs_test');\n\t\t\tif (!req) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treq.onsuccess = () => idbFactory.deleteDatabase('__zenfs_test');\n\t\t} catch (e) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\tcreate({ cacheSize = 100, storeName = 'zenfs', idbFactory = globalThis.indexedDB }: IndexedDBOptions) {\n\t\tconst store = IndexedDBStore.create(storeName, idbFactory);\n\t\tconst fs = new AsyncStoreFS({ cacheSize, store });\n\t\treturn fs;\n\t},\n};\n", "import { dirname, basename, join, resolve, sep } from '../emulation/path.js';\nimport { ApiError, ErrorCode } from '../ApiError.js';\nimport { W_OK, R_OK } from '../emulation/constants.js';\nimport { PreloadFile } from '../file.js';\nimport { FileSystem, Sync } from '../filesystem.js';\nimport { randomIno, Inode } from '../inode.js';\nimport { FileType } from '../stats.js';\nimport { decodeDirListing, encode, encodeDirListing } from '../utils.js';\nimport { rootIno } from '../inode.js';\n/**\n * A simple RW transaction for simple synchronous key-value stores.\n */\nexport class SimpleSyncRWTransaction {\n constructor(store) {\n this.store = store;\n /**\n * Stores data in the keys we modify prior to modifying them.\n * Allows us to roll back commits.\n */\n this.originalData = new Map();\n /**\n * List of keys modified in this transaction, if any.\n */\n this.modifiedKeys = new Set();\n }\n get(ino) {\n const val = this.store.get(ino);\n this.stashOldValue(ino, val);\n return val;\n }\n put(ino, data, overwrite) {\n this.markModified(ino);\n return this.store.put(ino, data, overwrite);\n }\n remove(ino) {\n this.markModified(ino);\n this.store.remove(ino);\n }\n commit() {\n /* NOP */\n }\n abort() {\n // Rollback old values.\n for (const key of this.modifiedKeys) {\n const value = this.originalData.get(key);\n if (!value) {\n // Key didn't exist.\n this.store.remove(key);\n }\n else {\n // Key existed. Store old value.\n this.store.put(key, value, true);\n }\n }\n }\n /**\n * Stashes given key value pair into `originalData` if it doesn't already\n * exist. Allows us to stash values the program is requesting anyway to\n * prevent needless `get` requests if the program modifies the data later\n * on during the transaction.\n */\n stashOldValue(ino, value) {\n // Keep only the earliest value in the transaction.\n if (!this.originalData.has(ino)) {\n this.originalData.set(ino, value);\n }\n }\n /**\n * Marks the given key as modified, and stashes its value if it has not been\n * stashed already.\n */\n markModified(ino) {\n this.modifiedKeys.add(ino);\n if (!this.originalData.has(ino)) {\n this.originalData.set(ino, this.store.get(ino));\n }\n }\n}\n/**\n * File backend by a SyncStoreFS\n * @internal\n */\nexport class SyncStoreFile extends PreloadFile {\n constructor(_fs, _path, _flag, _stat, contents) {\n super(_fs, _path, _flag, _stat, contents);\n }\n async sync() {\n this.syncSync();\n }\n syncSync() {\n if (this.isDirty()) {\n this.fs.syncSync(this.path, this._buffer, this.stats);\n this.resetDirty();\n }\n }\n async close() {\n this.closeSync();\n }\n closeSync() {\n this.syncSync();\n }\n}\n/**\n * A synchronous key-value file system. Uses a SyncStore to store the data.\n *\n * We use a unique ID for each node in the file system. The root node has a fixed ID.\n * @todo Introduce Node ID caching.\n * @todo Check modes.\n * @internal\n */\nexport class SyncStoreFS extends Sync(FileSystem) {\n constructor(options) {\n super();\n this.store = options.store;\n // INVARIANT: Ensure that the root exists.\n this.makeRootDirectory();\n }\n metadata() {\n return {\n ...super.metadata(),\n name: this.store.name,\n };\n }\n /**\n * Delete all contents stored in the file system.\n */\n empty() {\n this.store.clear();\n // INVARIANT: Root always exists.\n this.makeRootDirectory();\n }\n renameSync(oldPath, newPath, cred) {\n const tx = this.store.beginTransaction('readwrite'), oldParent = dirname(oldPath), oldName = basename(oldPath), newParent = dirname(newPath), newName = basename(newPath), \n // Remove oldPath from parent's directory listing.\n oldDirNode = this.findINode(tx, oldParent), oldDirList = this.getDirListing(tx, oldDirNode, oldParent);\n if (!oldDirNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(oldPath);\n }\n if (!oldDirList[oldName]) {\n throw ApiError.ENOENT(oldPath);\n }\n const ino = oldDirList[oldName];\n delete oldDirList[oldName];\n // Invariant: Can't move a folder inside itself.\n // This funny little hack ensures that the check passes only if oldPath\n // is a subpath of newParent. We append '/' to avoid matching folders that\n // are a substring of the bottom-most folder in the path.\n if ((newParent + '/').indexOf(oldPath + '/') == 0) {\n throw new ApiError(ErrorCode.EBUSY, oldParent);\n }\n // Add newPath to parent's directory listing.\n let newDirNode, newDirList;\n if (newParent === oldParent) {\n // Prevent us from re-grabbing the same directory listing, which still\n // contains oldName.\n newDirNode = oldDirNode;\n newDirList = oldDirList;\n }\n else {\n newDirNode = this.findINode(tx, newParent);\n newDirList = this.getDirListing(tx, newDirNode, newParent);\n }\n if (newDirList[newName]) {\n // If it's a file, delete it.\n const newNameNode = this.getINode(tx, newDirList[newName], newPath);\n if (newNameNode.toStats().isFile()) {\n try {\n tx.remove(newNameNode.ino);\n tx.remove(newDirList[newName]);\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n }\n else {\n // If it's a directory, throw a permissions error.\n throw ApiError.EPERM(newPath);\n }\n }\n newDirList[newName] = ino;\n // Commit the two changed directory listings.\n try {\n tx.put(oldDirNode.ino, encodeDirListing(oldDirList), true);\n tx.put(newDirNode.ino, encodeDirListing(newDirList), true);\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n tx.commit();\n }\n statSync(p, cred) {\n // Get the inode to the item, convert it into a Stats object.\n const stats = this.findINode(this.store.beginTransaction('readonly'), p).toStats();\n if (!stats.hasAccess(R_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n return stats;\n }\n createFileSync(p, flag, mode, cred) {\n this.commitNewFile(p, FileType.FILE, mode, cred);\n return this.openFileSync(p, flag, cred);\n }\n openFileSync(p, flag, cred) {\n const tx = this.store.beginTransaction('readonly'), node = this.findINode(tx, p), data = tx.get(node.ino);\n if (!node.toStats().hasAccess(flag.mode, cred)) {\n throw ApiError.EACCES(p);\n }\n if (data === null) {\n throw ApiError.ENOENT(p);\n }\n return new SyncStoreFile(this, p, flag, node.toStats(), data);\n }\n unlinkSync(p, cred) {\n this.removeEntry(p, false, cred);\n }\n rmdirSync(p, cred) {\n // Check first if directory is empty.\n if (this.readdirSync(p, cred).length > 0) {\n throw ApiError.ENOTEMPTY(p);\n }\n else {\n this.removeEntry(p, true, cred);\n }\n }\n mkdirSync(p, mode, cred) {\n this.commitNewFile(p, FileType.DIRECTORY, mode, cred, encode('{}'));\n }\n readdirSync(p, cred) {\n const tx = this.store.beginTransaction('readonly');\n const node = this.findINode(tx, p);\n if (!node.toStats().hasAccess(R_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n return Object.keys(this.getDirListing(tx, node, p));\n }\n syncSync(p, data, stats) {\n // @todo Ensure mtime updates properly, and use that to determine if a data\n // update is required.\n const tx = this.store.beginTransaction('readwrite'), \n // We use the _findInode helper because we actually need the INode id.\n fileInodeId = this._findINode(tx, dirname(p), basename(p)), fileInode = this.getINode(tx, fileInodeId, p), inodeChanged = fileInode.update(stats);\n try {\n // Sync data.\n tx.put(fileInode.ino, data, true);\n // Sync metadata.\n if (inodeChanged) {\n tx.put(fileInodeId, fileInode.data, true);\n }\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n tx.commit();\n }\n linkSync(existing, newpath, cred) {\n const tx = this.store.beginTransaction('readwrite'), existingDir = dirname(existing), existingDirNode = this.findINode(tx, existingDir);\n if (!existingDirNode.toStats().hasAccess(R_OK, cred)) {\n throw ApiError.EACCES(existingDir);\n }\n const newDir = dirname(newpath), newDirNode = this.findINode(tx, newDir), newListing = this.getDirListing(tx, newDirNode, newDir);\n if (!newDirNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(newDir);\n }\n const ino = this._findINode(tx, existingDir, basename(existing));\n const node = this.getINode(tx, ino, existing);\n if (!node.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(newpath);\n }\n node.nlink++;\n newListing[basename(newpath)] = ino;\n try {\n tx.put(ino, node.data, true);\n tx.put(newDirNode.ino, encodeDirListing(newListing), true);\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n tx.commit();\n }\n /**\n * Checks if the root directory exists. Creates it if it doesn't.\n */\n makeRootDirectory() {\n const tx = this.store.beginTransaction('readwrite');\n if (tx.get(rootIno)) {\n return;\n }\n // Create new inode, mode o777, owned by root:root\n const inode = new Inode();\n inode.mode = 0o777 | FileType.DIRECTORY;\n // If the root doesn't exist, the first random ID shouldn't exist either.\n tx.put(inode.ino, encode('{}'), false);\n tx.put(rootIno, inode.data, false);\n tx.commit();\n }\n /**\n * Helper function for findINode.\n * @param parent The parent directory of the file we are attempting to find.\n * @param filename The filename of the inode we are attempting to find, minus\n * the parent.\n * @return string The ID of the file's inode in the file system.\n */\n _findINode(tx, parent, filename, visited = new Set()) {\n const currentPath = join(parent, filename);\n if (visited.has(currentPath)) {\n throw new ApiError(ErrorCode.EIO, 'Infinite loop detected while finding inode', currentPath);\n }\n visited.add(currentPath);\n if (parent != '/') {\n const ino = this._findINode(tx, dirname(parent), basename(parent), visited);\n const dir = this.getDirListing(tx, this.getINode(tx, ino, parent + sep + filename), parent);\n if (!(filename in dir)) {\n throw ApiError.ENOENT(resolve(parent, filename));\n }\n return dir[filename];\n }\n if (filename != '') {\n // Find the item in the root node.\n const dir = this.getDirListing(tx, this.getINode(tx, rootIno, parent), parent);\n if (!(filename in dir)) {\n throw ApiError.ENOENT(resolve(parent, filename));\n }\n return dir[filename];\n }\n // Return the root's ID.\n return rootIno;\n }\n /**\n * Finds the Inode of the given path.\n * @param p The path to look up.\n * @return The Inode of the path p.\n * @todo memoize/cache\n */\n findINode(tx, p) {\n const ino = this._findINode(tx, dirname(p), basename(p));\n return this.getINode(tx, ino, p);\n }\n /**\n * Given the ID of a node, retrieves the corresponding Inode.\n * @param tx The transaction to use.\n * @param p The corresponding path to the file (used for error messages).\n * @param id The ID to look up.\n */\n getINode(tx, id, p) {\n const data = tx.get(id);\n if (!data) {\n throw ApiError.ENOENT(p);\n }\n const inode = new Inode(data.buffer);\n return inode;\n }\n /**\n * Given the Inode of a directory, retrieves the corresponding directory listing.\n */\n getDirListing(tx, inode, p) {\n if (!inode.toStats().isDirectory()) {\n throw ApiError.ENOTDIR(p);\n }\n const data = tx.get(inode.ino);\n if (!data) {\n throw ApiError.ENOENT(p);\n }\n return decodeDirListing(data);\n }\n /**\n * Creates a new node under a random ID. Retries 5 times before giving up in\n * the exceedingly unlikely chance that we try to reuse a random GUID.\n * @return The GUID that the data was stored under.\n */\n addNewNode(tx, data) {\n const retries = 0;\n let ino;\n while (retries < 5) {\n try {\n ino = randomIno();\n tx.put(ino, data, false);\n return ino;\n }\n catch (e) {\n // Ignore and reroll.\n }\n }\n throw new ApiError(ErrorCode.EIO, 'Unable to commit data to key-value store.');\n }\n /**\n * Commits a new file (well, a FILE or a DIRECTORY) to the file system with the given mode.\n * Note: This will commit the transaction.\n * @param p The path to the new file.\n * @param type The type of the new file.\n * @param mode The mode to create the new file with.\n * @param data The data to store at the file's data node.\n * @return The Inode for the new file.\n */\n commitNewFile(p, type, mode, cred, data = new Uint8Array()) {\n const tx = this.store.beginTransaction('readwrite'), parentDir = dirname(p), fname = basename(p), parentNode = this.findINode(tx, parentDir), dirListing = this.getDirListing(tx, parentNode, parentDir);\n //Check that the creater has correct access\n if (!parentNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n /* Invariant: The root always exists.\n If we don't check this prior to taking steps below,\n we will create a file with name '' in root should p == '/'.\n */\n if (p === '/') {\n throw ApiError.EEXIST(p);\n }\n // Check if file already exists.\n if (dirListing[fname]) {\n throw ApiError.EEXIST(p);\n }\n const fileNode = new Inode();\n try {\n // Commit data.\n fileNode.ino = this.addNewNode(tx, data);\n fileNode.size = data.length;\n fileNode.mode = mode | type;\n fileNode.uid = cred.uid;\n fileNode.gid = cred.gid;\n // Update and commit parent directory listing.\n dirListing[fname] = this.addNewNode(tx, fileNode.data);\n tx.put(parentNode.ino, encodeDirListing(dirListing), true);\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n tx.commit();\n return fileNode;\n }\n /**\n * Remove all traces of the given path from the file system.\n * @param p The path to remove from the file system.\n * @param isDir Does the path belong to a directory, or a file?\n * @todo Update mtime.\n */\n removeEntry(p, isDir, cred) {\n const tx = this.store.beginTransaction('readwrite'), parent = dirname(p), parentNode = this.findINode(tx, parent), parentListing = this.getDirListing(tx, parentNode, parent), fileName = basename(p), fileIno = parentListing[fileName];\n if (!fileIno) {\n throw ApiError.ENOENT(p);\n }\n // Get file inode.\n const fileNode = this.getINode(tx, fileIno, p);\n if (!fileNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n // Remove from directory listing of parent.\n delete parentListing[fileName];\n if (!isDir && fileNode.toStats().isDirectory()) {\n throw ApiError.EISDIR(p);\n }\n if (isDir && !fileNode.toStats().isDirectory()) {\n throw ApiError.ENOTDIR(p);\n }\n try {\n // Update directory listing.\n tx.put(parentNode.ino, encodeDirListing(parentListing), true);\n if (--fileNode.nlink < 1) {\n // remove file\n tx.remove(fileNode.ino);\n tx.remove(fileIno);\n }\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n // Success.\n tx.commit();\n }\n}\n", "import { SyncStore, SimpleSyncStore, SimpleSyncRWTransaction, SyncRWTransaction, SyncStoreFS } from '@zenfs/core/backends/SyncStore.js';\nimport { ApiError, ErrorCode } from '@zenfs/core/ApiError.js';\nimport { type Backend } from '@zenfs/core/backends/backend.js';\nimport { decode, encode } from '@zenfs/core/utils.js';\nimport type { Ino } from '@zenfs/core/inode.js';\n\n/**\n * A synchronous key-value store backed by Storage.\n */\nexport class StorageStore implements SyncStore, SimpleSyncStore {\n\tpublic get name(): string {\n\t\treturn Storage.name;\n\t}\n\n\tconstructor(protected _storage: Storage) {}\n\n\tpublic clear(): void {\n\t\tthis._storage.clear();\n\t}\n\n\tpublic beginTransaction(): SyncRWTransaction {\n\t\t// No need to differentiate.\n\t\treturn new SimpleSyncRWTransaction(this);\n\t}\n\n\tpublic get(key: Ino): Uint8Array | undefined {\n\t\tconst data = this._storage.getItem(key.toString());\n\t\tif (typeof data != 'string') {\n\t\t\treturn;\n\t\t}\n\n\t\treturn encode(data);\n\t}\n\n\tpublic put(key: Ino, data: Uint8Array, overwrite: boolean): boolean {\n\t\ttry {\n\t\t\tif (!overwrite && this._storage.getItem(key.toString()) !== null) {\n\t\t\t\t// Don't want to overwrite the key!\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthis._storage.setItem(key.toString(), decode(data));\n\t\t\treturn true;\n\t\t} catch (e) {\n\t\t\tthrow new ApiError(ErrorCode.ENOSPC, 'Storage is full.');\n\t\t}\n\t}\n\n\tpublic remove(key: Ino): void {\n\t\ttry {\n\t\t\tthis._storage.removeItem(key.toString());\n\t\t} catch (e) {\n\t\t\tthrow new ApiError(ErrorCode.EIO, 'Unable to delete key ' + key + ': ' + e);\n\t\t}\n\t}\n}\n\n/**\n * Options to pass to the StorageFileSystem\n */\nexport interface StorageOptions {\n\t/**\n\t * The Storage to use. Defaults to globalThis.localStorage.\n\t */\n\tstorage: Storage;\n}\n\n/**\n * A synchronous file system backed by a `Storage` (e.g. localStorage).\n */\nexport const Storage: Backend = {\n\tname: 'Storage',\n\n\toptions: {\n\t\tstorage: {\n\t\t\ttype: 'object',\n\t\t\trequired: false,\n\t\t\tdescription: 'The Storage to use. Defaults to globalThis.localStorage.',\n\t\t},\n\t},\n\n\tisAvailable(storage: Storage = globalThis.localStorage): boolean {\n\t\treturn storage instanceof globalThis.Storage;\n\t},\n\n\tcreate({ storage = globalThis.localStorage }: StorageOptions) {\n\t\treturn new SyncStoreFS({ store: new StorageStore(storage) });\n\t},\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["src_exports", "__export", "FileSystemAccess", "FileSystemAccessFS", "FileSystemAccessFile", "IndexedDB", "IndexedDBROTransaction", "IndexedDBRWTransaction", "IndexedDBStore", "Storage", "StorageStore", "cwd", "sep", "validateString", "str", "name", "__name", "normalizeString", "path", "allowAboveRoot", "res", "lastSegmentLength", "lastSlash", "dots", "char", "i", "lastSlashIndex", "__name", "resolve", "args", "resolvedPath", "resolvedAbsolute", "i", "path", "cwd", "validateString", "normalizeString", "__name", "normalize", "isAbsolute", "trailingSeparator", "join", "args", "joined", "i", "arg", "validateString", "normalize", "__name", "dirname", "path", "validateString", "hasRoot", "end", "matchedSlash", "__name", "basename", "suffix", "start", "extIdx", "firstNonSlashEnd", "i", "ErrorCode", "ErrorStrings", "ApiError", "json", "err", "code", "path", "errno", "message", "__name", "
|
|
3
|
+
"sources": ["../src/index.ts", "../node_modules/@zenfs/core/dist/emulation/path.js", "../node_modules/@zenfs/core/dist/ApiError.js", "../node_modules/@zenfs/core/dist/stats.js", "../node_modules/@zenfs/core/dist/inode.js", "../node_modules/@zenfs/core/dist/file.js", "../node_modules/@zenfs/core/dist/filesystem.js", "../src/FileSystemAccess.ts", "../node_modules/@zenfs/core/dist/utils.js", "../node_modules/@zenfs/core/dist/backends/AsyncStore.js", "../src/IndexedDB.ts", "../node_modules/@zenfs/core/dist/backends/SyncStore.js", "../src/Storage.ts"],
|
|
4
|
+
"sourcesContent": ["export * from './FileSystemAccess.js';\nexport * from './IndexedDB.js';\nexport * from './Storage.js';\n", "/*\nCopyright Joyent, Inc. and other Node contributors.\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to permit\npersons to whom the Software is furnished to do so, subject to the\nfollowing conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\nNO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\nDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\nUSE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\nexport const cwd = '/';\nexport const sep = '/';\nfunction validateString(str, name) {\n if (typeof str != 'string') {\n throw new TypeError(`\"${name}\" is not a string`);\n }\n}\nfunction validateObject(str, name) {\n if (typeof str != 'object') {\n throw new TypeError(`\"${name}\" is not an object`);\n }\n}\n// Resolves . and .. elements in a path with directory names\nexport function normalizeString(path, allowAboveRoot) {\n let res = '';\n let lastSegmentLength = 0;\n let lastSlash = -1;\n let dots = 0;\n let char = '\\x00';\n for (let i = 0; i <= path.length; ++i) {\n if (i < path.length) {\n char = path[i];\n }\n else if (char == '/') {\n break;\n }\n else {\n char = '/';\n }\n if (char == '/') {\n if (lastSlash === i - 1 || dots === 1) {\n // NOOP\n }\n else if (dots === 2) {\n if (res.length < 2 || lastSegmentLength !== 2 || res.at(-1) !== '.' || res.at(-2) !== '.') {\n if (res.length > 2) {\n const lastSlashIndex = res.lastIndexOf('/');\n if (lastSlashIndex === -1) {\n res = '';\n lastSegmentLength = 0;\n }\n else {\n res = res.slice(0, lastSlashIndex);\n lastSegmentLength = res.length - 1 - res.lastIndexOf('/');\n }\n lastSlash = i;\n dots = 0;\n continue;\n }\n else if (res.length !== 0) {\n res = '';\n lastSegmentLength = 0;\n lastSlash = i;\n dots = 0;\n continue;\n }\n }\n if (allowAboveRoot) {\n res += res.length > 0 ? '/..' : '..';\n lastSegmentLength = 2;\n }\n }\n else {\n if (res.length > 0)\n res += '/' + path.slice(lastSlash + 1, i);\n else\n res = path.slice(lastSlash + 1, i);\n lastSegmentLength = i - lastSlash - 1;\n }\n lastSlash = i;\n dots = 0;\n }\n else if (char === '.' && dots !== -1) {\n ++dots;\n }\n else {\n dots = -1;\n }\n }\n return res;\n}\nexport function formatExt(ext) {\n return ext ? `${ext[0] === '.' ? '' : '.'}${ext}` : '';\n}\nexport function resolve(...args) {\n let resolvedPath = '';\n let resolvedAbsolute = false;\n for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n const path = i >= 0 ? args[i] : cwd;\n validateString(path, `paths[${i}]`);\n // Skip empty entries\n if (path.length === 0) {\n continue;\n }\n resolvedPath = `${path}/${resolvedPath}`;\n resolvedAbsolute = path[0] === '/';\n }\n // At this point the path should be resolved to a full absolute path, but\n // handle relative paths to be safe (might happen when process.cwd() fails)\n // Normalize the path\n resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);\n if (resolvedAbsolute) {\n return `/${resolvedPath}`;\n }\n return resolvedPath.length > 0 ? resolvedPath : '.';\n}\nexport function normalize(path) {\n validateString(path, 'path');\n if (path.length === 0)\n return '.';\n const isAbsolute = path[0] === '/';\n const trailingSeparator = path.at(-1) === '/';\n // Normalize the path\n path = normalizeString(path, !isAbsolute);\n if (path.length === 0) {\n if (isAbsolute)\n return '/';\n return trailingSeparator ? './' : '.';\n }\n if (trailingSeparator)\n path += '/';\n return isAbsolute ? `/${path}` : path;\n}\nexport function isAbsolute(path) {\n validateString(path, 'path');\n return path.length > 0 && path[0] === '/';\n}\nexport function join(...args) {\n if (args.length === 0)\n return '.';\n let joined;\n for (let i = 0; i < args.length; ++i) {\n const arg = args[i];\n validateString(arg, 'path');\n if (arg.length > 0) {\n if (joined === undefined)\n joined = arg;\n else\n joined += `/${arg}`;\n }\n }\n if (joined === undefined)\n return '.';\n return normalize(joined);\n}\nexport function relative(from, to) {\n validateString(from, 'from');\n validateString(to, 'to');\n if (from === to)\n return '';\n // Trim leading forward slashes.\n from = resolve(from);\n to = resolve(to);\n if (from === to)\n return '';\n const fromStart = 1;\n const fromEnd = from.length;\n const fromLen = fromEnd - fromStart;\n const toStart = 1;\n const toLen = to.length - toStart;\n // Compare paths to find the longest common path from root\n const length = fromLen < toLen ? fromLen : toLen;\n let lastCommonSep = -1;\n let i = 0;\n for (; i < length; i++) {\n const fromCode = from[fromStart + i];\n if (fromCode !== to[toStart + i])\n break;\n else if (fromCode === '/')\n lastCommonSep = i;\n }\n if (i === length) {\n if (toLen > length) {\n if (to[toStart + i] === '/') {\n // We get here if `from` is the exact base path for `to`.\n // For example: from='/foo/bar'; to='/foo/bar/baz'\n return to.slice(toStart + i + 1);\n }\n if (i === 0) {\n // We get here if `from` is the root\n // For example: from='/'; to='/foo'\n return to.slice(toStart + i);\n }\n }\n else if (fromLen > length) {\n if (from[fromStart + i] === '/') {\n // We get here if `to` is the exact base path for `from`.\n // For example: from='/foo/bar/baz'; to='/foo/bar'\n lastCommonSep = i;\n }\n else if (i === 0) {\n // We get here if `to` is the root.\n // For example: from='/foo/bar'; to='/'\n lastCommonSep = 0;\n }\n }\n }\n let out = '';\n // Generate the relative path based on the path difference between `to`\n // and `from`.\n for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {\n if (i === fromEnd || from[i] === '/') {\n out += out.length === 0 ? '..' : '/..';\n }\n }\n // Lastly, append the rest of the destination (`to`) path that comes after\n // the common path parts.\n return `${out}${to.slice(toStart + lastCommonSep)}`;\n}\nexport function dirname(path) {\n validateString(path, 'path');\n if (path.length === 0)\n return '.';\n const hasRoot = path[0] === '/';\n let end = -1;\n let matchedSlash = true;\n for (let i = path.length - 1; i >= 1; --i) {\n if (path[i] === '/') {\n if (!matchedSlash) {\n end = i;\n break;\n }\n }\n else {\n // We saw the first non-path separator\n matchedSlash = false;\n }\n }\n if (end === -1)\n return hasRoot ? '/' : '.';\n if (hasRoot && end === 1)\n return '//';\n return path.slice(0, end);\n}\nexport function basename(path, suffix) {\n if (suffix !== undefined)\n validateString(suffix, 'ext');\n validateString(path, 'path');\n let start = 0;\n let end = -1;\n let matchedSlash = true;\n if (suffix !== undefined && suffix.length > 0 && suffix.length <= path.length) {\n if (suffix === path)\n return '';\n let extIdx = suffix.length - 1;\n let firstNonSlashEnd = -1;\n for (let i = path.length - 1; i >= 0; --i) {\n if (path[i] === '/') {\n // If we reached a path separator that was not part of a set of path\n // separators at the end of the string, stop now\n if (!matchedSlash) {\n start = i + 1;\n break;\n }\n }\n else {\n if (firstNonSlashEnd === -1) {\n // We saw the first non-path separator, remember this index in case\n // we need it if the extension ends up not matching\n matchedSlash = false;\n firstNonSlashEnd = i + 1;\n }\n if (extIdx >= 0) {\n // Try to match the explicit extension\n if (path[i] === suffix[extIdx]) {\n if (--extIdx === -1) {\n // We matched the extension, so mark this as the end of our path\n // component\n end = i;\n }\n }\n else {\n // Extension does not match, so our result is the entire path\n // component\n extIdx = -1;\n end = firstNonSlashEnd;\n }\n }\n }\n }\n if (start === end)\n end = firstNonSlashEnd;\n else if (end === -1)\n end = path.length;\n return path.slice(start, end);\n }\n for (let i = path.length - 1; i >= 0; --i) {\n if (path[i] === '/') {\n // If we reached a path separator that was not part of a set of path\n // separators at the end of the string, stop now\n if (!matchedSlash) {\n start = i + 1;\n break;\n }\n }\n else if (end === -1) {\n // We saw the first non-path separator, mark this as the end of our\n // path component\n matchedSlash = false;\n end = i + 1;\n }\n }\n if (end === -1)\n return '';\n return path.slice(start, end);\n}\nexport function extname(path) {\n validateString(path, 'path');\n let startDot = -1;\n let startPart = 0;\n let end = -1;\n let matchedSlash = true;\n // Track the state of characters (if any) we see before our first dot and\n // after any path separator we find\n let preDotState = 0;\n for (let i = path.length - 1; i >= 0; --i) {\n if (path[i] === '/') {\n // If we reached a path separator that was not part of a set of path\n // separators at the end of the string, stop now\n if (!matchedSlash) {\n startPart = i + 1;\n break;\n }\n continue;\n }\n if (end === -1) {\n // We saw the first non-path separator, mark this as the end of our\n // extension\n matchedSlash = false;\n end = i + 1;\n }\n if (path[i] === '.') {\n // If this is our first dot, mark it as the start of our extension\n if (startDot === -1)\n startDot = i;\n else if (preDotState !== 1)\n preDotState = 1;\n }\n else if (startDot !== -1) {\n // We saw a non-dot and non-path separator before our dot, so we should\n // have a good chance at having a non-empty extension\n preDotState = -1;\n }\n }\n if (startDot === -1 ||\n end === -1 ||\n // We saw a non-dot character immediately before the dot\n preDotState === 0 ||\n // The (right-most) trimmed path component is exactly '..'\n (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)) {\n return '';\n }\n return path.slice(startDot, end);\n}\nexport function format(pathObject) {\n validateObject(pathObject, 'pathObject');\n const dir = pathObject.dir || pathObject.root;\n const base = pathObject.base || `${pathObject.name || ''}${formatExt(pathObject.ext)}`;\n if (!dir) {\n return base;\n }\n return dir === pathObject.root ? `${dir}${base}` : `${dir}/${base}`;\n}\nexport function parse(path) {\n validateString(path, 'path');\n const isAbsolute = path[0] === '/';\n const ret = { root: isAbsolute ? '/' : '', dir: '', base: '', ext: '', name: '' };\n if (path.length === 0)\n return ret;\n const start = isAbsolute ? 1 : 0;\n let startDot = -1;\n let startPart = 0;\n let end = -1;\n let matchedSlash = true;\n let i = path.length - 1;\n // Track the state of characters (if any) we see before our first dot and\n // after any path separator we find\n let preDotState = 0;\n // Get non-dir info\n for (; i >= start; --i) {\n if (path[i] === '/') {\n // If we reached a path separator that was not part of a set of path\n // separators at the end of the string, stop now\n if (!matchedSlash) {\n startPart = i + 1;\n break;\n }\n continue;\n }\n if (end === -1) {\n // We saw the first non-path separator, mark this as the end of our\n // extension\n matchedSlash = false;\n end = i + 1;\n }\n if (path[i] === '.') {\n // If this is our first dot, mark it as the start of our extension\n if (startDot === -1)\n startDot = i;\n else if (preDotState !== 1)\n preDotState = 1;\n }\n else if (startDot !== -1) {\n // We saw a non-dot and non-path separator before our dot, so we should\n // have a good chance at having a non-empty extension\n preDotState = -1;\n }\n }\n if (end !== -1) {\n const start = startPart === 0 && isAbsolute ? 1 : startPart;\n if (startDot === -1 ||\n // We saw a non-dot character immediately before the dot\n preDotState === 0 ||\n // The (right-most) trimmed path component is exactly '..'\n (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)) {\n ret.base = ret.name = path.slice(start, end);\n }\n else {\n ret.name = path.slice(start, startDot);\n ret.base = path.slice(start, end);\n ret.ext = path.slice(startDot, end);\n }\n }\n if (startPart > 0)\n ret.dir = path.slice(0, startPart - 1);\n else if (isAbsolute)\n ret.dir = '/';\n return ret;\n}\n", "/**\n * Standard libc error codes. More will be added to this enum and ErrorStrings as they are\n * needed.\n * @url http://www.gnu.org/software/libc/manual/html_node/Error-Codes.html\n */\nexport var ErrorCode;\n(function (ErrorCode) {\n /**\n * Operation not permitted\n */\n ErrorCode[ErrorCode[\"EPERM\"] = 1] = \"EPERM\";\n /**\n * No such file or directory\n */\n ErrorCode[ErrorCode[\"ENOENT\"] = 2] = \"ENOENT\";\n /**\n * Input/output error\n */\n ErrorCode[ErrorCode[\"EIO\"] = 5] = \"EIO\";\n /**\n * Bad file descriptor\n */\n ErrorCode[ErrorCode[\"EBADF\"] = 9] = \"EBADF\";\n /**\n * Permission denied\n */\n ErrorCode[ErrorCode[\"EACCES\"] = 13] = \"EACCES\";\n /**\n * Resource busy or locked\n */\n ErrorCode[ErrorCode[\"EBUSY\"] = 16] = \"EBUSY\";\n /**\n * File exists\n */\n ErrorCode[ErrorCode[\"EEXIST\"] = 17] = \"EEXIST\";\n /**\n * File is not a directory\n */\n ErrorCode[ErrorCode[\"ENOTDIR\"] = 20] = \"ENOTDIR\";\n /**\n * File is a directory\n */\n ErrorCode[ErrorCode[\"EISDIR\"] = 21] = \"EISDIR\";\n /**\n * Invalid argument\n */\n ErrorCode[ErrorCode[\"EINVAL\"] = 22] = \"EINVAL\";\n /**\n * File is too big\n */\n ErrorCode[ErrorCode[\"EFBIG\"] = 27] = \"EFBIG\";\n /**\n * No space left on disk\n */\n ErrorCode[ErrorCode[\"ENOSPC\"] = 28] = \"ENOSPC\";\n /**\n * Cannot modify a read-only file system\n */\n ErrorCode[ErrorCode[\"EROFS\"] = 30] = \"EROFS\";\n /**\n * Directory is not empty\n */\n ErrorCode[ErrorCode[\"ENOTEMPTY\"] = 39] = \"ENOTEMPTY\";\n /**\n * Operation is not supported\n */\n ErrorCode[ErrorCode[\"ENOTSUP\"] = 95] = \"ENOTSUP\";\n})(ErrorCode = ErrorCode || (ErrorCode = {}));\n/**\n * Strings associated with each error code.\n * @internal\n */\nexport const ErrorStrings = {\n [ErrorCode.EPERM]: 'Operation not permitted.',\n [ErrorCode.ENOENT]: 'No such file or directory.',\n [ErrorCode.EIO]: 'Input/output error.',\n [ErrorCode.EBADF]: 'Bad file descriptor.',\n [ErrorCode.EACCES]: 'Permission denied.',\n [ErrorCode.EBUSY]: 'Resource busy or locked.',\n [ErrorCode.EEXIST]: 'File exists.',\n [ErrorCode.ENOTDIR]: 'File is not a directory.',\n [ErrorCode.EISDIR]: 'File is a directory.',\n [ErrorCode.EINVAL]: 'Invalid argument.',\n [ErrorCode.EFBIG]: 'File is too big.',\n [ErrorCode.ENOSPC]: 'No space left on disk.',\n [ErrorCode.EROFS]: 'Cannot modify a read-only file system.',\n [ErrorCode.ENOTEMPTY]: 'Directory is not empty.',\n [ErrorCode.ENOTSUP]: 'Operation is not supported.',\n};\n/**\n * Represents a ZenFS error. Passed back to applications after a failed\n * call to the ZenFS API.\n */\nexport class ApiError extends Error {\n static fromJSON(json) {\n const err = new ApiError(json.errno, json.message, json.path);\n err.code = json.code;\n err.stack = json.stack;\n return err;\n }\n static OnPath(code, path) {\n return new ApiError(code, ErrorStrings[code], path);\n }\n static EACCES(path) {\n return this.OnPath(ErrorCode.EACCES, path);\n }\n static ENOENT(path) {\n return this.OnPath(ErrorCode.ENOENT, path);\n }\n static EEXIST(path) {\n return this.OnPath(ErrorCode.EEXIST, path);\n }\n static EISDIR(path) {\n return this.OnPath(ErrorCode.EISDIR, path);\n }\n static ENOTDIR(path) {\n return this.OnPath(ErrorCode.ENOTDIR, path);\n }\n static EPERM(path) {\n return this.OnPath(ErrorCode.EPERM, path);\n }\n static ENOTEMPTY(path) {\n return this.OnPath(ErrorCode.ENOTEMPTY, path);\n }\n /**\n * Represents a ZenFS error. Passed back to applications after a failed\n * call to the ZenFS API.\n *\n * Error codes mirror those returned by regular Unix file operations, which is\n * what Node returns.\n * @constructor ApiError\n * @param type The type of the error.\n * @param message A descriptive error message.\n */\n constructor(errno, message = ErrorStrings[errno], path) {\n super(message);\n this.errno = errno;\n this.path = path;\n // Unsupported.\n this.syscall = '';\n this.code = ErrorCode[errno];\n this.message = `${this.code}: ${message}${this.path ? `, '${this.path}'` : ''}`;\n }\n /**\n * @return A friendly error message.\n */\n toString() {\n return this.message;\n }\n toJSON() {\n return {\n errno: this.errno,\n code: this.code,\n path: this.path,\n stack: this.stack,\n message: this.message,\n };\n }\n /**\n * The size of the API error in buffer-form in bytes.\n */\n bufferSize() {\n // 4 bytes for string length.\n return 4 + JSON.stringify(this.toJSON()).length;\n }\n}\n", "import { S_IFDIR, S_IFLNK, S_IFMT, S_IFREG } from './emulation/constants.js';\n/**\n * Indicates the type of the given file. Applied to 'mode'.\n */\nexport var FileType;\n(function (FileType) {\n FileType[FileType[\"FILE\"] = S_IFREG] = \"FILE\";\n FileType[FileType[\"DIRECTORY\"] = S_IFDIR] = \"DIRECTORY\";\n FileType[FileType[\"SYMLINK\"] = S_IFLNK] = \"SYMLINK\";\n})(FileType = FileType || (FileType = {}));\n/**\n * Provides information about a particular entry in the file system.\n * Common code used by both Stats and BigIntStats.\n */\nexport class StatsCommon {\n get _typename() {\n return this._isBigint ? 'bigint' : 'number';\n }\n get _typename_inverse() {\n return this._isBigint ? 'number' : 'bigint';\n }\n _convert(arg) {\n return (this._isBigint ? BigInt(arg) : Number(arg));\n }\n get atime() {\n return new Date(Number(this.atimeMs));\n }\n set atime(value) {\n this.atimeMs = this._convert(value.getTime());\n }\n get mtime() {\n return new Date(Number(this.mtimeMs));\n }\n set mtime(value) {\n this.mtimeMs = this._convert(value.getTime());\n }\n get ctime() {\n return new Date(Number(this.ctimeMs));\n }\n set ctime(value) {\n this.ctimeMs = this._convert(value.getTime());\n }\n get birthtime() {\n return new Date(Number(this.birthtimeMs));\n }\n set birthtime(value) {\n this.birthtimeMs = this._convert(value.getTime());\n }\n /**\n * Creates a new stats instance from a stats-like object. Can be used to copy stats (note)\n */\n constructor({ atimeMs, mtimeMs, ctimeMs, birthtimeMs, uid, gid, size, mode } = {}) {\n /**\n * ID of device containing file\n */\n this.dev = this._convert(0);\n /**\n * inode number\n */\n this.ino = this._convert(0);\n /**\n * device ID (if special file)\n */\n this.rdev = this._convert(0);\n /**\n * number of hard links\n */\n this.nlink = this._convert(1);\n /**\n * blocksize for file system I/O\n */\n this.blksize = this._convert(4096);\n /**\n * user ID of owner\n */\n this.uid = this._convert(0);\n /**\n * group ID of owner\n */\n this.gid = this._convert(0);\n /**\n * Some file systems stash data on stats objects.\n */\n this.fileData = null;\n const currentTime = Date.now();\n const resolveT = (val, _default) => (typeof val == this._typename ? val : this._convert(typeof val == this._typename_inverse ? val : _default));\n this.atimeMs = resolveT(atimeMs, currentTime);\n this.mtimeMs = resolveT(mtimeMs, currentTime);\n this.ctimeMs = resolveT(ctimeMs, currentTime);\n this.birthtimeMs = resolveT(birthtimeMs, currentTime);\n this.uid = resolveT(uid, 0);\n this.gid = resolveT(gid, 0);\n this.size = this._convert(size);\n const itemType = Number(mode) & S_IFMT || FileType.FILE;\n if (mode) {\n this.mode = this._convert(mode);\n }\n else {\n switch (itemType) {\n case FileType.FILE:\n this.mode = this._convert(0o644);\n break;\n case FileType.DIRECTORY:\n default:\n this.mode = this._convert(0o777);\n }\n }\n // number of 512B blocks allocated\n this.blocks = this._convert(Math.ceil(Number(size) / 512));\n // Check if mode also includes top-most bits, which indicate the file's type.\n if ((this.mode & S_IFMT) == 0) {\n this.mode = (this.mode | this._convert(itemType));\n }\n }\n /**\n * @returns true if this item is a file.\n */\n isFile() {\n return (this.mode & S_IFMT) === S_IFREG;\n }\n /**\n * @returns True if this item is a directory.\n */\n isDirectory() {\n return (this.mode & S_IFMT) === S_IFDIR;\n }\n /**\n * @returns true if this item is a symbolic link\n */\n isSymbolicLink() {\n return (this.mode & S_IFMT) === S_IFLNK;\n }\n // Currently unsupported\n isSocket() {\n return false;\n }\n isBlockDevice() {\n return false;\n }\n isCharacterDevice() {\n return false;\n }\n isFIFO() {\n return false;\n }\n /**\n * Checks if a given user/group has access to this item\n * @param mode The request access as 4 bits (unused, read, write, execute)\n * @param uid The requesting UID\n * @param gid The requesting GID\n * @returns True if the request has access, false if the request does not\n * @internal\n */\n hasAccess(mode, cred) {\n if (cred.euid === 0 || cred.egid === 0) {\n //Running as root\n return true;\n }\n const perms = this.mode & ~S_IFMT;\n let uMode = 0xf, gMode = 0xf, wMode = 0xf;\n if (cred.euid == this.uid) {\n const uPerms = (0xf00 & perms) >> 8;\n uMode = (mode ^ uPerms) & mode;\n }\n if (cred.egid == this.gid) {\n const gPerms = (0xf0 & perms) >> 4;\n gMode = (mode ^ gPerms) & mode;\n }\n const wPerms = 0xf & perms;\n wMode = (mode ^ wPerms) & mode;\n /*\n Result = 0b0xxx (read, write, execute)\n If any bits are set that means the request does not have that permission.\n */\n const result = uMode & gMode & wMode;\n return !result;\n }\n /**\n * Convert the current stats object into a credentials object\n * @internal\n */\n cred(uid = Number(this.uid), gid = Number(this.gid)) {\n return {\n uid,\n gid,\n suid: Number(this.uid),\n sgid: Number(this.gid),\n euid: uid,\n egid: gid,\n };\n }\n /**\n * Change the mode of the file. We use this helper function to prevent messing\n * up the type of the file, which is encoded in mode.\n * @internal\n */\n chmod(mode) {\n this.mode = this._convert((this.mode & S_IFMT) | mode);\n }\n /**\n * Change the owner user/group of the file.\n * This function makes sure it is a valid UID/GID (that is, a 32 unsigned int)\n * @internal\n */\n chown(uid, gid) {\n uid = Number(uid);\n gid = Number(gid);\n if (!isNaN(uid) && 0 <= uid && uid < 2 ** 32) {\n this.uid = this._convert(uid);\n }\n if (!isNaN(gid) && 0 <= gid && gid < 2 ** 32) {\n this.gid = this._convert(gid);\n }\n }\n}\n/**\n * Implementation of Node's `Stats`.\n *\n * Attribute descriptions are from `man 2 stat'\n * @see http://nodejs.org/api/fs.html#fs_class_fs_stats\n * @see http://man7.org/linux/man-pages/man2/stat.2.html\n */\nexport class Stats extends StatsCommon {\n constructor() {\n super(...arguments);\n this._isBigint = false;\n }\n /**\n * Clones the stats object.\n * @deprecated use `new Stats(stats)`\n */\n static clone(stats) {\n return new Stats(stats);\n }\n}\nStats;\n/**\n * Stats with bigint\n * @todo Implement with bigint instead of wrapping Stats\n */\nexport class BigIntStats extends StatsCommon {\n constructor() {\n super(...arguments);\n this._isBigint = true;\n }\n /**\n * Clone a stats object.\n * @deprecated use `new BigIntStats(stats)`\n */\n static clone(stats) {\n return new BigIntStats(stats);\n }\n}\nBigIntStats;\n/**\n * @returns true if stats is a file.\n */\nexport function isFile(stats) {\n return (Number(stats.mode) & S_IFMT) === S_IFREG;\n}\n/**\n * @returns True if stats is a directory.\n */\nexport function isDirectory(stats) {\n return (Number(stats.mode) & S_IFMT) === S_IFDIR;\n}\n/**\n * @returns true if stats is a symbolic link\n */\nexport function isSymbolicLink(stats) {\n return (Number(stats.mode) & S_IFMT) === S_IFLNK;\n}\nexport function isSocket() {\n return false;\n}\nexport function isBlockDevice() {\n return false;\n}\nexport function isCharacterDevice() {\n return false;\n}\nexport function isFIFO() {\n return false;\n}\n", "import { Stats } from './stats.js';\n/**\n * Max 32-bit integer\n * @hidden\n */\nexport const size_max = 2 ** 32 - 1;\n/**\n * Room inode\n * @hidden\n */\nexport const rootIno = 0n;\n/**\n * Generates a random 32 bit integer, then converts to a hex string\n */\nfunction _random() {\n return Math.round(Math.random() * 2 ** 32).toString(16);\n}\n/**\n * Generate a random ino\n * @internal\n */\nexport function randomIno() {\n return BigInt('0x' + _random() + _random());\n}\n/**\n * Offsets for inode members\n */\nvar Offset;\n(function (Offset) {\n Offset[Offset[\"ino\"] = 0] = \"ino\";\n Offset[Offset[\"size\"] = 8] = \"size\";\n Offset[Offset[\"mode\"] = 12] = \"mode\";\n Offset[Offset[\"nlink\"] = 14] = \"nlink\";\n Offset[Offset[\"uid\"] = 18] = \"uid\";\n Offset[Offset[\"gid\"] = 22] = \"gid\";\n Offset[Offset[\"atime\"] = 26] = \"atime\";\n Offset[Offset[\"birthtime\"] = 34] = \"birthtime\";\n Offset[Offset[\"mtime\"] = 42] = \"mtime\";\n Offset[Offset[\"ctime\"] = 50] = \"ctime\";\n Offset[Offset[\"end\"] = 58] = \"end\";\n})(Offset || (Offset = {}));\n/**\n * Generic inode definition that can easily be serialized.\n */\nexport class Inode {\n get data() {\n return new Uint8Array(this.buffer);\n }\n constructor(buffer) {\n const setDefaults = !buffer;\n buffer ?? (buffer = new ArrayBuffer(Offset.end));\n if (buffer?.byteLength < Offset.end) {\n throw new RangeError(`Can not create an inode from a buffer less than ${Offset.end} bytes`);\n }\n this.view = new DataView(buffer);\n this.buffer = buffer;\n if (!setDefaults) {\n return;\n }\n // set defaults on a fresh inode\n this.ino = randomIno();\n this.nlink = 1;\n this.size = 4096;\n const now = Date.now();\n this.atimeMs = now;\n this.mtimeMs = now;\n this.ctimeMs = now;\n this.birthtimeMs = now;\n }\n get ino() {\n return this.view.getBigUint64(Offset.ino, true);\n }\n set ino(value) {\n this.view.setBigUint64(Offset.ino, value, true);\n }\n get size() {\n return this.view.getUint32(Offset.size, true);\n }\n set size(value) {\n this.view.setUint32(Offset.size, value, true);\n }\n get mode() {\n return this.view.getUint16(Offset.mode, true);\n }\n set mode(value) {\n this.view.setUint16(Offset.mode, value, true);\n }\n get nlink() {\n return this.view.getUint32(Offset.nlink, true);\n }\n set nlink(value) {\n this.view.setUint32(Offset.nlink, value, true);\n }\n get uid() {\n return this.view.getUint32(Offset.uid, true);\n }\n set uid(value) {\n this.view.setUint32(Offset.uid, value, true);\n }\n get gid() {\n return this.view.getUint32(Offset.gid, true);\n }\n set gid(value) {\n this.view.setUint32(Offset.gid, value, true);\n }\n get atimeMs() {\n return this.view.getFloat64(Offset.atime, true);\n }\n set atimeMs(value) {\n this.view.setFloat64(Offset.atime, value, true);\n }\n get birthtimeMs() {\n return this.view.getFloat64(Offset.birthtime, true);\n }\n set birthtimeMs(value) {\n this.view.setFloat64(Offset.birthtime, value, true);\n }\n get mtimeMs() {\n return this.view.getFloat64(Offset.mtime, true);\n }\n set mtimeMs(value) {\n this.view.setFloat64(Offset.mtime, value, true);\n }\n get ctimeMs() {\n return this.view.getFloat64(Offset.ctime, true);\n }\n set ctimeMs(value) {\n this.view.setFloat64(Offset.ctime, value, true);\n }\n /**\n * Handy function that converts the Inode to a Node Stats object.\n */\n toStats() {\n return new Stats(this);\n }\n /**\n * Updates the Inode using information from the stats object. Used by file\n * systems at sync time, e.g.:\n * - Program opens file and gets a File object.\n * - Program mutates file. File object is responsible for maintaining\n * metadata changes locally -- typically in a Stats object.\n * - Program closes file. File object's metadata changes are synced with the\n * file system.\n * @return True if any changes have occurred.\n */\n update(stats) {\n let hasChanged = false;\n if (this.size !== stats.size) {\n this.size = stats.size;\n hasChanged = true;\n }\n if (this.mode !== stats.mode) {\n this.mode = stats.mode;\n hasChanged = true;\n }\n if (this.nlink !== stats.nlink) {\n this.nlink = stats.nlink;\n hasChanged = true;\n }\n if (this.uid !== stats.uid) {\n this.uid = stats.uid;\n hasChanged = true;\n }\n if (this.uid !== stats.uid) {\n this.uid = stats.uid;\n hasChanged = true;\n }\n if (this.atimeMs !== stats.atimeMs) {\n this.atimeMs = stats.atimeMs;\n hasChanged = true;\n }\n if (this.mtimeMs !== stats.mtimeMs) {\n this.mtimeMs = stats.mtimeMs;\n hasChanged = true;\n }\n if (this.ctimeMs !== stats.ctimeMs) {\n this.ctimeMs = stats.ctimeMs;\n hasChanged = true;\n }\n return hasChanged;\n }\n}\n", "import { ApiError, ErrorCode } from './ApiError.js';\nimport { O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY, S_IFMT } from './emulation/constants.js';\nimport { size_max } from './inode.js';\nimport { Stats } from './stats.js';\n/**\n * @hidden\n */\nexport var ActionType;\n(function (ActionType) {\n // Indicates that the code should not do anything.\n ActionType[ActionType[\"NOP\"] = 0] = \"NOP\";\n // Indicates that the code should throw an exception.\n ActionType[ActionType[\"THROW\"] = 1] = \"THROW\";\n // Indicates that the code should truncate the file, but only if it is a file.\n ActionType[ActionType[\"TRUNCATE\"] = 2] = \"TRUNCATE\";\n // Indicates that the code should create the file.\n ActionType[ActionType[\"CREATE\"] = 3] = \"CREATE\";\n})(ActionType = ActionType || (ActionType = {}));\nconst validFlags = ['r', 'r+', 'rs', 'rs+', 'w', 'wx', 'w+', 'wx+', 'a', 'ax', 'a+', 'ax+'];\nexport function parseFlag(flag) {\n if (typeof flag === 'number') {\n return flagToString(flag);\n }\n if (!validFlags.includes(flag)) {\n throw new Error('Invalid flag string: ' + flag);\n }\n return flag;\n}\nexport function flagToString(flag) {\n switch (flag) {\n case O_RDONLY:\n return 'r';\n case O_RDONLY | O_SYNC:\n return 'rs';\n case O_RDWR:\n return 'r+';\n case O_RDWR | O_SYNC:\n return 'rs+';\n case O_TRUNC | O_CREAT | O_WRONLY:\n return 'w';\n case O_TRUNC | O_CREAT | O_WRONLY | O_EXCL:\n return 'wx';\n case O_TRUNC | O_CREAT | O_RDWR:\n return 'w+';\n case O_TRUNC | O_CREAT | O_RDWR | O_EXCL:\n return 'wx+';\n case O_APPEND | O_CREAT | O_WRONLY:\n return 'a';\n case O_APPEND | O_CREAT | O_WRONLY | O_EXCL:\n return 'ax';\n case O_APPEND | O_CREAT | O_RDWR:\n return 'a+';\n case O_APPEND | O_CREAT | O_RDWR | O_EXCL:\n return 'ax+';\n default:\n throw new Error('Invalid flag number: ' + flag);\n }\n}\nexport function flagToNumber(flag) {\n switch (flag) {\n case 'r':\n return O_RDONLY;\n case 'rs':\n return O_RDONLY | O_SYNC;\n case 'r+':\n return O_RDWR;\n case 'rs+':\n return O_RDWR | O_SYNC;\n case 'w':\n return O_TRUNC | O_CREAT | O_WRONLY;\n case 'wx':\n return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL;\n case 'w+':\n return O_TRUNC | O_CREAT | O_RDWR;\n case 'wx+':\n return O_TRUNC | O_CREAT | O_RDWR | O_EXCL;\n case 'a':\n return O_APPEND | O_CREAT | O_WRONLY;\n case 'ax':\n return O_APPEND | O_CREAT | O_WRONLY | O_EXCL;\n case 'a+':\n return O_APPEND | O_CREAT | O_RDWR;\n case 'ax+':\n return O_APPEND | O_CREAT | O_RDWR | O_EXCL;\n default:\n throw new Error('Invalid flag string: ' + flag);\n }\n}\nexport function flagToMode(flag) {\n let mode = 0;\n mode <<= 1;\n mode += +isReadable(flag);\n mode <<= 1;\n mode += +isWriteable(flag);\n mode <<= 1;\n return mode;\n}\nexport function isReadable(flag) {\n return flag.indexOf('r') !== -1 || flag.indexOf('+') !== -1;\n}\nexport function isWriteable(flag) {\n return flag.indexOf('w') !== -1 || flag.indexOf('a') !== -1 || flag.indexOf('+') !== -1;\n}\nexport function isTruncating(flag) {\n return flag.indexOf('w') !== -1;\n}\nexport function isAppendable(flag) {\n return flag.indexOf('a') !== -1;\n}\nexport function isSynchronous(flag) {\n return flag.indexOf('s') !== -1;\n}\nexport function isExclusive(flag) {\n return flag.indexOf('x') !== -1;\n}\nexport function pathExistsAction(flag) {\n if (isExclusive(flag)) {\n return ActionType.THROW;\n }\n if (isTruncating(flag)) {\n return ActionType.TRUNCATE;\n }\n return ActionType.NOP;\n}\nexport function pathNotExistsAction(flag) {\n if ((isWriteable(flag) || isAppendable(flag)) && flag !== 'r+') {\n return ActionType.CREATE;\n }\n return ActionType.THROW;\n}\nexport class File {\n /**\n * Asynchronous `datasync`.\n *\n * Default implementation maps to `sync`.\n */\n datasync() {\n return this.sync();\n }\n /**\n * Synchronous `datasync`.\n *\n * Default implementation maps to `syncSync`.\n */\n datasyncSync() {\n return this.syncSync();\n }\n}\n/**\n * An implementation of the File interface that operates on a file that is\n * completely in-memory. PreloadFiles are backed by a Uint8Array.\n *\n * This is also an abstract class, as it lacks an implementation of 'sync' and\n * 'close'. Each filesystem that wishes to use this file representation must\n * extend this class and implement those two methods.\n * @todo 'close' lever that disables functionality once closed.\n */\nexport class PreloadFile extends File {\n /**\n * Creates a file with the given path and, optionally, the given contents. Note\n * that, if contents is specified, it will be mutated by the file!\n * @param _mode The mode that the file was opened using.\n * Dictates permissions and where the file pointer starts.\n * @param stats The stats object for the given file.\n * PreloadFile will mutate this object. Note that this object must contain\n * the appropriate mode that the file was opened as.\n * @param buffer A buffer containing the entire\n * contents of the file. PreloadFile will mutate this buffer. If not\n * specified, we assume it is a new file.\n */\n constructor(\n /**\n * The file system that created the file.\n */\n fs, \n /**\n * Path to the file\n */\n path, flag, stats, _buffer = new Uint8Array(new ArrayBuffer(0, { maxByteLength: size_max }))) {\n super();\n this.fs = fs;\n this.path = path;\n this.flag = flag;\n this.stats = stats;\n this._buffer = _buffer;\n this._position = 0;\n this._dirty = false;\n /*\n Note:\n This invariant is *not* maintained once the file starts getting modified.\n It only actually matters if file is readable, as writeable modes may truncate/append to file.\n */\n if (this.stats.size == _buffer.byteLength) {\n return;\n }\n if (isReadable(this.flag)) {\n throw new Error(`Size mismatch: buffer length ${_buffer.byteLength}, stats size ${this.stats.size}`);\n }\n this._dirty = true;\n }\n /**\n * Get the underlying buffer for this file. Mutating not recommended and will mess up dirty tracking.\n */\n get buffer() {\n return this._buffer;\n }\n /**\n * Get the current file position.\n *\n * We emulate the following bug mentioned in the Node documentation:\n * > On Linux, positional writes don't work when the file is opened in append\n * mode. The kernel ignores the position argument and always appends the data\n * to the end of the file.\n * @return The current file position.\n */\n get position() {\n if (isAppendable(this.flag)) {\n return this.stats.size;\n }\n return this._position;\n }\n /**\n * Set the file position.\n * @param newPos new position\n */\n set position(newPos) {\n this._position = newPos;\n }\n /**\n * Asynchronous `stat`.\n */\n async stat() {\n return new Stats(this.stats);\n }\n /**\n * Synchronous `stat`.\n */\n statSync() {\n return new Stats(this.stats);\n }\n /**\n * Asynchronous truncate.\n * @param len\n */\n truncate(len) {\n this.truncateSync(len);\n if (isSynchronous(this.flag) && !this.fs.metadata().synchronous) {\n return this.sync();\n }\n }\n /**\n * Synchronous truncate.\n * @param len\n */\n truncateSync(len) {\n this._dirty = true;\n if (!isWriteable(this.flag)) {\n throw new ApiError(ErrorCode.EPERM, 'File not opened with a writeable mode.');\n }\n this.stats.mtimeMs = Date.now();\n if (len > this._buffer.length) {\n const buf = new Uint8Array(len - this._buffer.length);\n // Write will set stats.size for us.\n this.writeSync(buf, 0, buf.length, this._buffer.length);\n if (isSynchronous(this.flag) && this.fs.metadata().synchronous) {\n this.syncSync();\n }\n return;\n }\n this.stats.size = len;\n // Truncate buffer to 'len'.\n this._buffer = this._buffer.subarray(0, len);\n if (isSynchronous(this.flag) && this.fs.metadata().synchronous) {\n this.syncSync();\n }\n }\n /**\n * Write buffer to the file.\n * Note that it is unsafe to use fs.write multiple times on the same file\n * without waiting for the callback.\n * @param buffer Uint8Array containing the data to write to\n * the file.\n * @param offset Offset in the buffer to start reading data from.\n * @param length The amount of bytes to write to the file.\n * @param position Offset from the beginning of the file where this\n * data should be written. If position is null, the data will be written at\n * the current position.\n */\n async write(buffer, offset = 0, length = this.stats.size, position = 0) {\n return this.writeSync(buffer, offset, length, position);\n }\n /**\n * Write buffer to the file.\n * Note that it is unsafe to use fs.writeSync multiple times on the same file\n * without waiting for the callback.\n * @param buffer Uint8Array containing the data to write to\n * the file.\n * @param offset Offset in the buffer to start reading data from.\n * @param length The amount of bytes to write to the file.\n * @param position Offset from the beginning of the file where this\n * data should be written. If position is null, the data will be written at\n * the current position.\n * @returns bytes written\n */\n writeSync(buffer, offset = 0, length = this.stats.size, position = 0) {\n this._dirty = true;\n position ?? (position = this.position);\n if (!isWriteable(this.flag)) {\n throw new ApiError(ErrorCode.EPERM, 'File not opened with a writeable mode.');\n }\n const endFp = position + length;\n if (endFp > this.stats.size) {\n this.stats.size = endFp;\n if (endFp > this._buffer.byteLength) {\n if (this._buffer.buffer.resizable && this._buffer.buffer.maxByteLength <= endFp) {\n this._buffer.buffer.resize(endFp);\n }\n else {\n // Extend the buffer!\n const newBuffer = new Uint8Array(new ArrayBuffer(endFp, { maxByteLength: size_max }));\n newBuffer.set(this._buffer);\n this._buffer = newBuffer;\n }\n }\n }\n this._buffer.set(buffer.slice(offset, offset + length), position);\n const len = this._buffer.byteOffset;\n this.stats.mtimeMs = Date.now();\n if (isSynchronous(this.flag)) {\n this.syncSync();\n return len;\n }\n this.position = position + len;\n return len;\n }\n /**\n * Read data from the file.\n * @param buffer The buffer that the data will be\n * written to.\n * @param offset The offset within the buffer where writing will\n * start.\n * @param length An integer specifying the number of bytes to read.\n * @param position An integer specifying where to begin reading from\n * in the file. If position is null, data will be read from the current file\n * position.\n */\n async read(buffer, offset = 0, length = this.stats.size, position = 0) {\n return { bytesRead: this.readSync(buffer, offset, length, position), buffer };\n }\n /**\n * Read data from the file.\n * @param buffer The buffer that the data will be\n * written to.\n * @param offset The offset within the buffer where writing will start.\n * @param length An integer specifying the number of bytes to read.\n * @param position An integer specifying where to begin reading from\n * in the file. If position is null, data will be read from the current file\n * position.\n * @returns number of bytes written\n */\n readSync(buffer, offset = 0, length = this.stats.size, position = 0) {\n if (!isReadable(this.flag)) {\n throw new ApiError(ErrorCode.EPERM, 'File not opened with a readable mode.');\n }\n position ?? (position = this.position);\n let end = position + length;\n if (end > this.stats.size) {\n end = position + Math.max(this.stats.size - position, 0);\n }\n this.stats.atimeMs = Date.now();\n this._position = end;\n const bytesRead = end - position;\n if (bytesRead == 0) {\n // No copy/read. Return immediatly for better performance\n return bytesRead;\n }\n buffer.set(this._buffer.slice(position, end), offset);\n return bytesRead;\n }\n /**\n * Asynchronous `fchmod`.\n * @param mode the mode\n */\n async chmod(mode) {\n this.chmodSync(mode);\n }\n /**\n * Synchronous `fchmod`.\n * @param mode\n */\n chmodSync(mode) {\n if (!this.fs.metadata().supportsProperties) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n this._dirty = true;\n this.stats.chmod(mode);\n this.syncSync();\n }\n /**\n * Asynchronous `fchown`.\n * @param uid\n * @param gid\n */\n async chown(uid, gid) {\n this.chownSync(uid, gid);\n }\n /**\n * Synchronous `fchown`.\n * @param uid\n * @param gid\n */\n chownSync(uid, gid) {\n if (!this.fs.metadata().supportsProperties) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n this._dirty = true;\n this.stats.chown(uid, gid);\n this.syncSync();\n }\n async utimes(atime, mtime) {\n this.utimesSync(atime, mtime);\n }\n utimesSync(atime, mtime) {\n if (!this.fs.metadata().supportsProperties) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n this._dirty = true;\n this.stats.atime = atime;\n this.stats.mtime = mtime;\n this.syncSync();\n }\n isDirty() {\n return this._dirty;\n }\n /**\n * Resets the dirty bit. Should only be called after a sync has completed successfully.\n */\n resetDirty() {\n this._dirty = false;\n }\n _setType(type) {\n this._dirty = true;\n this.stats.mode = (this.stats.mode & ~S_IFMT) | type;\n return this.sync();\n }\n _setTypeSync(type) {\n this._dirty = true;\n this.stats.mode = (this.stats.mode & ~S_IFMT) | type;\n this.syncSync();\n }\n}\n/**\n * For synchronous file systems\n */\nexport class SyncFile extends PreloadFile {\n constructor(_fs, _path, _flag, _stat, contents) {\n super(_fs, _path, _flag, _stat, contents);\n }\n async sync() {\n this.syncSync();\n }\n syncSync() {\n if (this.isDirty()) {\n this.fs.syncSync(this.path, this._buffer, this.stats);\n this.resetDirty();\n }\n }\n async close() {\n this.closeSync();\n }\n closeSync() {\n this.syncSync();\n }\n}\n/**\n * For the filesystems which do not sync to anything..\n */\nexport class NoSyncFile extends PreloadFile {\n constructor(_fs, _path, _flag, _stat, contents) {\n super(_fs, _path, _flag, _stat, contents);\n }\n /**\n * Asynchronous sync. Doesn't do anything, simply calls the cb.\n */\n async sync() {\n return;\n }\n /**\n * Synchronous sync. Doesn't do anything.\n */\n syncSync() {\n // NOP.\n }\n /**\n * Asynchronous close. Doesn't do anything, simply calls the cb.\n */\n async close() {\n return;\n }\n /**\n * Synchronous close. Doesn't do anything.\n */\n closeSync() {\n // NOP.\n }\n}\n", "import { ApiError, ErrorCode } from './ApiError.js';\n/**\n * Structure for a filesystem. All ZenFS FileSystems must implement this.\n *\n * This class includes some default implementations\n *\n * Assume the following about arguments passed to each API method:\n *\n * - Every path is an absolute path. `.`, `..`, and other items are resolved into an absolute form.\n * - All arguments are present. Any optional arguments at the Node API level have been passed in with their default values.\n */\nexport class FileSystem {\n metadata() {\n return {\n name: this.constructor.name,\n readonly: false,\n synchronous: false,\n supportsProperties: false,\n totalSpace: 0,\n freeSpace: 0,\n };\n }\n /* eslint-disable-next-line @typescript-eslint/no-unused-vars */\n constructor(options) {\n // unused\n }\n /**\n * Test whether or not the given path exists by checking with the file system.\n */\n async exists(path, cred) {\n try {\n await this.stat(path, cred);\n return true;\n }\n catch (e) {\n return false;\n }\n }\n /**\n * Test whether or not the given path exists by checking with the file system.\n */\n existsSync(path, cred) {\n try {\n this.statSync(path, cred);\n return true;\n }\n catch (e) {\n return false;\n }\n }\n}\n/**\n * Implements the asynchronous API in terms of the synchronous API.\n */\nexport function Sync(FS) {\n /**\n * Implements the asynchronous API in terms of the synchronous API.\n */\n class _SyncFileSystem extends FS {\n metadata() {\n return { ...super.metadata(), synchronous: true };\n }\n async ready() {\n return this;\n }\n async exists(path, cred) {\n return this.existsSync(path, cred);\n }\n async rename(oldPath, newPath, cred) {\n return this.renameSync(oldPath, newPath, cred);\n }\n async stat(path, cred) {\n return this.statSync(path, cred);\n }\n async createFile(path, flag, mode, cred) {\n return this.createFileSync(path, flag, mode, cred);\n }\n async openFile(path, flag, cred) {\n return this.openFileSync(path, flag, cred);\n }\n async unlink(path, cred) {\n return this.unlinkSync(path, cred);\n }\n async rmdir(path, cred) {\n return this.rmdirSync(path, cred);\n }\n async mkdir(path, mode, cred) {\n return this.mkdirSync(path, mode, cred);\n }\n async readdir(path, cred) {\n return this.readdirSync(path, cred);\n }\n async link(srcpath, dstpath, cred) {\n return this.linkSync(srcpath, dstpath, cred);\n }\n async sync(path, data, stats) {\n return this.syncSync(path, data, stats);\n }\n }\n return _SyncFileSystem;\n}\nexport function Async(FS) {\n class _AsyncFileSystem extends FS {\n metadata() {\n return { ...super.metadata(), synchronous: false };\n }\n /* eslint-disable @typescript-eslint/no-unused-vars */\n renameSync(oldPath, newPath, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n statSync(path, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n createFileSync(path, flag, mode, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n openFileSync(path, flag, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n unlinkSync(path, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n rmdirSync(path, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n mkdirSync(path, mode, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n readdirSync(path, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n linkSync(srcpath, dstpath, cred) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n syncSync(path, data, stats) {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n }\n /* eslint-enable @typescript-eslint/no-unused-vars */\n return _AsyncFileSystem;\n}\nexport function Readonly(FS) {\n class _ReadonlyFileSystem extends FS {\n metadata() {\n return { ...super.metadata(), readonly: true };\n }\n /* eslint-disable @typescript-eslint/no-unused-vars */\n async rename(oldPath, newPath, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n renameSync(oldPath, newPath, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n async createFile(path, flag, mode, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n createFileSync(path, flag, mode, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n async unlink(path, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n unlinkSync(path, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n async rmdir(path, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n rmdirSync(path, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n async mkdir(path, mode, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n mkdirSync(path, mode, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n async link(srcpath, dstpath, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n linkSync(srcpath, dstpath, cred) {\n throw new ApiError(ErrorCode.EROFS);\n }\n async sync(path, data, stats) {\n throw new ApiError(ErrorCode.EROFS);\n }\n syncSync(path, data, stats) {\n throw new ApiError(ErrorCode.EROFS);\n }\n }\n return _ReadonlyFileSystem;\n}\n", "import { basename, dirname, join } from '@zenfs/core/emulation/path.js';\nimport { ApiError, ErrorCode } from '@zenfs/core/ApiError.js';\nimport { PreloadFile } from '@zenfs/core/file.js';\nimport { FileSystem, Async, type FileSystemMetadata } from '@zenfs/core/filesystem.js';\nimport { Stats, FileType } from '@zenfs/core/stats.js';\nimport type { Backend } from '@zenfs/core/backends/backend.js';\n\ndeclare global {\n\tinterface FileSystemDirectoryHandle {\n\t\t[Symbol.iterator](): IterableIterator<[string, FileSystemHandle]>;\n\t\tentries(): IterableIterator<[string, FileSystemHandle]>;\n\t\tkeys(): IterableIterator<string>;\n\t\tvalues(): IterableIterator<FileSystemHandle>;\n\t}\n}\n\nexport interface FileSystemAccessOptions {\n\thandle: FileSystemDirectoryHandle;\n}\n\nconst handleError = (path = '', error: Error) => {\n\tif (error.name === 'NotFoundError') {\n\t\tthrow ApiError.ENOENT(path);\n\t}\n\n\tthrow error as ApiError;\n};\n\nexport class FileSystemAccessFile extends PreloadFile<FileSystemAccessFS> {\n\tconstructor(_fs: FileSystemAccessFS, _path: string, _flag: string, _stat: Stats, contents?: Uint8Array) {\n\t\tsuper(_fs, _path, _flag, _stat, contents);\n\t}\n\n\tpublic syncSync(): void {\n\t\tthrow new ApiError(ErrorCode.ENOTSUP);\n\t}\n\n\tpublic async sync(): Promise<void> {\n\t\tif (this.isDirty()) {\n\t\t\tawait this.fs.sync(this.path, this.buffer, this.stats);\n\t\t\tthis.resetDirty();\n\t\t}\n\t}\n\n\tpublic async close(): Promise<void> {\n\t\tawait this.sync();\n\t}\n\n\tpublic closeSync(): void {\n\t\tthrow new ApiError(ErrorCode.ENOTSUP);\n\t}\n}\n\nexport class FileSystemAccessFS extends Async(FileSystem) {\n\tprivate _handles: Map<string, FileSystemHandle> = new Map();\n\n\tpublic async ready(): Promise<this> {\n\t\treturn this;\n\t}\n\n\tpublic constructor({ handle }: FileSystemAccessOptions) {\n\t\tsuper();\n\t\tthis._handles.set('/', handle);\n\t}\n\n\tpublic metadata(): FileSystemMetadata {\n\t\treturn {\n\t\t\t...super.metadata(),\n\t\t\tname: 'FileSystemAccess',\n\t\t};\n\t}\n\n\tpublic async sync(p: string, data: Uint8Array, stats: Stats): Promise<void> {\n\t\tconst currentStats = await this.stat(p);\n\t\tif (stats.mtime !== currentStats!.mtime) {\n\t\t\tawait this.writeFile(p, data);\n\t\t}\n\t}\n\n\tpublic async rename(oldPath: string, newPath: string): Promise<void> {\n\t\ttry {\n\t\t\tconst handle = await this.getHandle(oldPath);\n\t\t\tif (handle instanceof FileSystemDirectoryHandle) {\n\t\t\t\tconst files = await this.readdir(oldPath);\n\n\t\t\t\tawait this.mkdir(newPath);\n\t\t\t\tif (files.length == 0) {\n\t\t\t\t\tawait this.unlink(oldPath);\n\t\t\t\t} else {\n\t\t\t\t\tfor (const file of files) {\n\t\t\t\t\t\tawait this.rename(join(oldPath, file), join(newPath, file));\n\t\t\t\t\t\tawait this.unlink(oldPath);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!(handle instanceof FileSystemFileHandle)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst oldFile = await handle.getFile(),\n\t\t\t\tdestFolder = await this.getHandle(dirname(newPath));\n\t\t\tif (!(destFolder instanceof FileSystemDirectoryHandle)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst newFile = await destFolder.getFileHandle(basename(newPath), { create: true });\n\t\t\tconst writable = await newFile.createWritable();\n\t\t\tconst buffer = await oldFile.arrayBuffer();\n\t\t\tawait writable.write(buffer);\n\n\t\t\twritable.close();\n\t\t\tawait this.unlink(oldPath);\n\t\t} catch (err) {\n\t\t\thandleError(oldPath, err);\n\t\t}\n\t}\n\n\tpublic async writeFile(fname: string, data: Uint8Array): Promise<void> {\n\t\tconst handle = await this.getHandle(dirname(fname));\n\t\tif (!(handle instanceof FileSystemDirectoryHandle)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst file = await handle.getFileHandle(basename(fname), { create: true });\n\t\tconst writable = await file.createWritable();\n\t\tawait writable.write(data);\n\t\tawait writable.close();\n\t}\n\n\tpublic async createFile(path: string, flag: string): Promise<FileSystemAccessFile> {\n\t\tawait this.writeFile(path, new Uint8Array());\n\t\treturn this.openFile(path, flag);\n\t}\n\n\tpublic async stat(path: string): Promise<Stats> {\n\t\tconst handle = await this.getHandle(path);\n\t\tif (!handle) {\n\t\t\tthrow ApiError.OnPath(ErrorCode.ENOENT, path);\n\t\t}\n\t\tif (handle instanceof FileSystemDirectoryHandle) {\n\t\t\treturn new Stats({ mode: 0o777 | FileType.DIRECTORY, size: 4096 });\n\t\t}\n\t\tif (handle instanceof FileSystemFileHandle) {\n\t\t\tconst { lastModified, size } = await handle.getFile();\n\t\t\treturn new Stats({ mode: 0o777 | FileType.FILE, size, mtimeMs: lastModified });\n\t\t}\n\t}\n\n\tpublic async openFile(path: string, flag: string): Promise<FileSystemAccessFile> {\n\t\tconst handle = await this.getHandle(path);\n\t\tif (handle instanceof FileSystemFileHandle) {\n\t\t\tconst file = await handle.getFile();\n\t\t\tconst data = new Uint8Array(await file.arrayBuffer());\n\t\t\tconst stats = new Stats({ mode: 0o777 | FileType.FILE, size: file.size, mtimeMs: file.lastModified });\n\t\t\treturn new FileSystemAccessFile(this, path, flag, stats, data);\n\t\t}\n\t}\n\n\tpublic async unlink(path: string): Promise<void> {\n\t\tconst handle = await this.getHandle(dirname(path));\n\t\tif (handle instanceof FileSystemDirectoryHandle) {\n\t\t\ttry {\n\t\t\t\tawait handle.removeEntry(basename(path), { recursive: true });\n\t\t\t} catch (e) {\n\t\t\t\thandleError(path, e);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic async link(): Promise<void> {\n\t\tthrow new ApiError(ErrorCode.ENOTSUP);\n\t}\n\n\tpublic async rmdir(path: string): Promise<void> {\n\t\treturn this.unlink(path);\n\t}\n\n\tpublic async mkdir(path: string): Promise<void> {\n\t\tconst existingHandle = await this.getHandle(path);\n\t\tif (existingHandle) {\n\t\t\tthrow ApiError.EEXIST(path);\n\t\t}\n\n\t\tconst handle = await this.getHandle(dirname(path));\n\t\tif (handle instanceof FileSystemDirectoryHandle) {\n\t\t\tawait handle.getDirectoryHandle(basename(path), { create: true });\n\t\t}\n\t}\n\n\tpublic async readdir(path: string): Promise<string[]> {\n\t\tconst handle = await this.getHandle(path);\n\t\tif (!(handle instanceof FileSystemDirectoryHandle)) {\n\t\t\tthrow ApiError.ENOTDIR(path);\n\t\t}\n\t\tconst _keys: string[] = [];\n\t\tfor await (const key of handle.keys()) {\n\t\t\t_keys.push(join(path, key));\n\t\t}\n\t\treturn _keys;\n\t}\n\n\tprotected async getHandle(path: string): Promise<FileSystemHandle> {\n\t\tif (this._handles.has(path)) {\n\t\t\treturn this._handles.get(path);\n\t\t}\n\n\t\tlet walkedPath = '/';\n\t\tconst [, ...pathParts] = path.split('/');\n\t\tconst getHandleParts = async ([pathPart, ...remainingPathParts]: string[]) => {\n\t\t\tconst walkingPath = join(walkedPath, pathPart);\n\t\t\tconst continueWalk = (handle: FileSystemHandle) => {\n\t\t\t\twalkedPath = walkingPath;\n\t\t\t\tthis._handles.set(walkedPath, handle);\n\n\t\t\t\tif (remainingPathParts.length === 0) {\n\t\t\t\t\treturn this._handles.get(path);\n\t\t\t\t}\n\n\t\t\t\tgetHandleParts(remainingPathParts);\n\t\t\t};\n\t\t\tconst handle = this._handles.get(walkedPath) as FileSystemDirectoryHandle;\n\n\t\t\ttry {\n\t\t\t\treturn continueWalk(await handle.getDirectoryHandle(pathPart));\n\t\t\t} catch (error) {\n\t\t\t\tif (error.name === 'TypeMismatchError') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn continueWalk(await handle.getFileHandle(pathPart));\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\thandleError(walkingPath, err);\n\t\t\t\t\t}\n\t\t\t\t} else if (error.message === 'Name is not allowed.') {\n\t\t\t\t\tthrow new ApiError(ErrorCode.ENOENT, error.message, walkingPath);\n\t\t\t\t} else {\n\t\t\t\t\thandleError(walkingPath, error);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\treturn await getHandleParts(pathParts);\n\t}\n}\n\nexport const FileSystemAccess: Backend = {\n\tname: 'FileSystemAccess',\n\n\toptions: {\n\t\thandle: {\n\t\t\ttype: 'object',\n\t\t\trequired: true,\n\t\t\tdescription: 'The directory handle to use for the root',\n\t\t},\n\t},\n\n\tisAvailable(): boolean {\n\t\treturn typeof FileSystemHandle == 'function';\n\t},\n\n\tcreate(options: FileSystemAccessOptions) {\n\t\treturn new FileSystemAccessFS(options);\n\t},\n};\n", "import { ApiError, ErrorCode } from './ApiError.js';\nimport { dirname } from './emulation/path.js';\n/**\n * Synchronous recursive makedir.\n * @hidden\n */\nexport function mkdirpSync(p, mode, cred, fs) {\n if (!fs.existsSync(p, cred)) {\n mkdirpSync(dirname(p), mode, cred, fs);\n fs.mkdirSync(p, mode, cred);\n }\n}\nfunction _min(d0, d1, d2, bx, ay) {\n return Math.min(d0 + 1, d1 + 1, d2 + 1, bx === ay ? d1 : d1 + 1);\n}\n/**\n * Calculates levenshtein distance.\n * @hidden\n */\nexport function levenshtein(a, b) {\n if (a === b) {\n return 0;\n }\n if (a.length > b.length) {\n [a, b] = [b, a]; // Swap a and b\n }\n let la = a.length;\n let lb = b.length;\n // Trim common suffix\n while (la > 0 && a.charCodeAt(la - 1) === b.charCodeAt(lb - 1)) {\n la--;\n lb--;\n }\n let offset = 0;\n // Trim common prefix\n while (offset < la && a.charCodeAt(offset) === b.charCodeAt(offset)) {\n offset++;\n }\n la -= offset;\n lb -= offset;\n if (la === 0 || lb === 1) {\n return lb;\n }\n const vector = new Array(la << 1);\n for (let y = 0; y < la;) {\n vector[la + y] = a.charCodeAt(offset + y);\n vector[y] = ++y;\n }\n let x;\n let d0;\n let d1;\n let d2;\n let d3;\n for (x = 0; x + 3 < lb;) {\n const bx0 = b.charCodeAt(offset + (d0 = x));\n const bx1 = b.charCodeAt(offset + (d1 = x + 1));\n const bx2 = b.charCodeAt(offset + (d2 = x + 2));\n const bx3 = b.charCodeAt(offset + (d3 = x + 3));\n let dd = (x += 4);\n for (let y = 0; y < la;) {\n const ay = vector[la + y];\n const dy = vector[y];\n d0 = _min(dy, d0, d1, bx0, ay);\n d1 = _min(d0, d1, d2, bx1, ay);\n d2 = _min(d1, d2, d3, bx2, ay);\n dd = _min(d2, d3, dd, bx3, ay);\n vector[y++] = dd;\n d3 = d2;\n d2 = d1;\n d1 = d0;\n d0 = dy;\n }\n }\n let dd = 0;\n for (; x < lb;) {\n const bx0 = b.charCodeAt(offset + (d0 = x));\n dd = ++x;\n for (let y = 0; y < la; y++) {\n const dy = vector[y];\n vector[y] = dd = dy < d0 || dd < d0 ? (dy > dd ? dd + 1 : dy + 1) : bx0 === vector[la + y] ? d0 : d0 + 1;\n d0 = dy;\n }\n }\n return dd;\n}\n/** Waits n ms. */\nexport function wait(ms) {\n return new Promise(resolve => {\n setTimeout(resolve, ms);\n });\n}\n/**\n * @hidden\n */\nexport const setImmediate = typeof globalThis.setImmediate == 'function' ? globalThis.setImmediate : cb => setTimeout(cb, 0);\n/**\n * Encodes a string into a buffer\n * @internal\n */\nexport function encode(input, encoding = 'utf8') {\n if (typeof input != 'string') {\n throw new ApiError(ErrorCode.EINVAL, 'Can not encode a non-string');\n }\n switch (encoding) {\n case 'ascii':\n case 'latin1':\n case 'binary':\n return new Uint8Array(Array.from(input).map(char => char.charCodeAt(0)));\n case 'utf8':\n case 'utf-8':\n return new Uint8Array(Array.from(input).flatMap(char => {\n const code = char.charCodeAt(0);\n if (code < 0x80) {\n return code;\n }\n const a = (code & 0x3f) | 0x80;\n if (code < 0x800) {\n return [(code >> 6) | 0xc0, a];\n }\n const b = ((code >> 6) & 0x3f) | 0x80;\n if (code < 0x10000) {\n return [(code >> 12) | 0xe0, b, a];\n }\n return [(code >> 18) | 0xf0, ((code >> 12) & 0x3f) | 0x80, b, a];\n }));\n case 'base64':\n return encode(atob(input), 'utf-8');\n case 'base64url':\n return encode(input.replace('_', '/').replace('-', '+'), 'base64');\n case 'hex':\n return new Uint8Array(input.match(/.{1,2}/g).map(e => parseInt(e, 16)));\n case 'utf16le':\n case 'ucs2':\n case 'ucs-2':\n const u16 = new Uint16Array(new ArrayBuffer(input.length * 2));\n for (let i = 0; i < input.length; i++) {\n u16[i] = input.charCodeAt(i);\n }\n return new Uint8Array(u16.buffer);\n default:\n throw new ApiError(ErrorCode.EINVAL, 'Invalid encoding: ' + encoding);\n }\n}\n/**\n * Decodes a string from a buffer\n * @internal\n */\nexport function decode(input, encoding = 'utf8') {\n if (!(input instanceof Uint8Array)) {\n throw new ApiError(ErrorCode.EINVAL, 'Can not decode a non-Uint8Array');\n }\n switch (encoding) {\n case 'ascii':\n case 'latin1':\n case 'binary':\n return Array.from(input)\n .map(char => String.fromCharCode(char))\n .join('');\n case 'utf8':\n case 'utf-8':\n let utf8String = '';\n for (let i = 0; i < input.length; i++) {\n let code;\n if (input[i] < 0x80) {\n code = input[i];\n }\n else if (input[i] < 0xe0) {\n code = ((input[i] & 0x1f) << 6) | (input[++i] & 0x3f);\n }\n else if (input[i] < 0xf0) {\n code = ((input[i] & 0x0f) << 12) | ((input[++i] & 0x3f) << 6) | (input[++i] & 0x3f);\n }\n else {\n code = ((input[i] & 0x07) << 18) | ((input[++i] & 0x3f) << 12) | ((input[++i] & 0x3f) << 6) | (input[++i] & 0x3f);\n }\n utf8String += String.fromCharCode(code);\n }\n return utf8String;\n case 'utf16le':\n case 'ucs2':\n case 'ucs-2':\n let utf16leString = '';\n for (let i = 0; i < input.length; i += 2) {\n const code = input[i] | (input[i + 1] << 8);\n utf16leString += String.fromCharCode(code);\n }\n return utf16leString;\n case 'base64':\n return btoa(decode(input, 'utf-8'));\n case 'base64url':\n return decode(input, 'base64').replace('/', '_').replace('+', '-');\n case 'hex':\n return Array.from(input)\n .map(e => e.toString(16).padStart(2, '0'))\n .join('');\n default:\n throw new ApiError(ErrorCode.EINVAL, 'Invalid encoding: ' + encoding);\n }\n}\n/**\n * Decodes a directory listing\n * @internal\n */\nexport function decodeDirListing(data) {\n return JSON.parse(decode(data), (k, v) => {\n if (k == '') {\n return v;\n }\n return BigInt(v);\n });\n}\n/**\n * Encodes a directory listing\n * @internal\n */\nexport function encodeDirListing(data) {\n return encode(JSON.stringify(data, (k, v) => {\n if (k == '') {\n return v;\n }\n return v.toString();\n }));\n}\n", "import { dirname, basename, join, resolve } from '../emulation/path.js';\nimport { ApiError, ErrorCode } from '../ApiError.js';\nimport { W_OK, R_OK } from '../emulation/constants.js';\nimport { PreloadFile, flagToMode } from '../file.js';\nimport { Async, FileSystem } from '../filesystem.js';\nimport { randomIno, Inode } from '../inode.js';\nimport { FileType } from '../stats.js';\nimport { encode, decodeDirListing, encodeDirListing } from '../utils.js';\nimport { rootIno } from '../inode.js';\n/**\n * Last Recently Used cache\n */\nclass LRUCache {\n constructor(limit) {\n this.limit = limit;\n this.cache = [];\n }\n set(key, value) {\n const existingIndex = this.cache.findIndex(node => node.key === key);\n if (existingIndex != -1) {\n this.cache.splice(existingIndex, 1);\n }\n else if (this.cache.length >= this.limit) {\n this.cache.shift();\n }\n this.cache.push({ key, value });\n }\n get(key) {\n const node = this.cache.find(n => n.key === key);\n if (!node) {\n return;\n }\n // Move the accessed item to the end of the cache (most recently used)\n this.set(key, node.value);\n return node.value;\n }\n remove(key) {\n const index = this.cache.findIndex(node => node.key === key);\n if (index !== -1) {\n this.cache.splice(index, 1);\n }\n }\n reset() {\n this.cache = [];\n }\n}\n/**\n * Async preload file for usage with AsyncStore\n * @internal\n */\nexport class AsyncFile extends PreloadFile {\n constructor(_fs, _path, _flag, _stat, contents) {\n super(_fs, _path, _flag, _stat, contents);\n }\n async sync() {\n if (!this.isDirty()) {\n return;\n }\n await this.fs.sync(this.path, this._buffer, this.stats);\n this.resetDirty();\n }\n syncSync() {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n async close() {\n this.sync();\n }\n closeSync() {\n throw new ApiError(ErrorCode.ENOTSUP);\n }\n}\n/**\n * An asynchronous file system which uses an async store to store its data.\n * @see AsyncStore\n * @internal\n */\nexport class AsyncStoreFS extends Async(FileSystem) {\n ready() {\n return this._ready;\n }\n metadata() {\n return {\n ...super.metadata(),\n name: this.store.name,\n };\n }\n constructor({ store, cacheSize }) {\n super();\n if (cacheSize > 0) {\n this._cache = new LRUCache(cacheSize);\n }\n this._ready = this._initialize(store);\n }\n /**\n * Initializes the file system. Typically called by subclasses' async\n * constructors.\n */\n async _initialize(store) {\n this.store = await store;\n // INVARIANT: Ensure that the root exists.\n await this.makeRootDirectory();\n return this;\n }\n /**\n * Delete all contents stored in the file system.\n */\n async empty() {\n if (this._cache) {\n this._cache.reset();\n }\n await this.store.clear();\n // INVARIANT: Root always exists.\n await this.makeRootDirectory();\n }\n /**\n * @todo Make rename compatible with the cache.\n */\n async rename(oldPath, newPath, cred) {\n const c = this._cache;\n if (this._cache) {\n // Clear and disable cache during renaming process.\n this._cache = null;\n c.reset();\n }\n try {\n const tx = this.store.beginTransaction('readwrite'), oldParent = dirname(oldPath), oldName = basename(oldPath), newParent = dirname(newPath), newName = basename(newPath), \n // Remove oldPath from parent's directory listing.\n oldDirNode = await this.findINode(tx, oldParent), oldDirList = await this.getDirListing(tx, oldDirNode, oldParent);\n if (!oldDirNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(oldPath);\n }\n if (!oldDirList[oldName]) {\n throw ApiError.ENOENT(oldPath);\n }\n const nodeId = oldDirList[oldName];\n delete oldDirList[oldName];\n // Invariant: Can't move a folder inside itself.\n // This funny little hack ensures that the check passes only if oldPath\n // is a subpath of newParent. We append '/' to avoid matching folders that\n // are a substring of the bottom-most folder in the path.\n if ((newParent + '/').indexOf(oldPath + '/') === 0) {\n throw new ApiError(ErrorCode.EBUSY, oldParent);\n }\n // Add newPath to parent's directory listing.\n let newDirNode, newDirList;\n if (newParent === oldParent) {\n // Prevent us from re-grabbing the same directory listing, which still\n // contains oldName.\n newDirNode = oldDirNode;\n newDirList = oldDirList;\n }\n else {\n newDirNode = await this.findINode(tx, newParent);\n newDirList = await this.getDirListing(tx, newDirNode, newParent);\n }\n if (newDirList[newName]) {\n // If it's a file, delete it.\n const newNameNode = await this.getINode(tx, newDirList[newName], newPath);\n if (newNameNode.toStats().isFile()) {\n try {\n await tx.remove(newNameNode.ino);\n await tx.remove(newDirList[newName]);\n }\n catch (e) {\n await tx.abort();\n throw e;\n }\n }\n else {\n // If it's a directory, throw a permissions error.\n throw ApiError.EPERM(newPath);\n }\n }\n newDirList[newName] = nodeId;\n // Commit the two changed directory listings.\n try {\n await tx.put(oldDirNode.ino, encodeDirListing(oldDirList), true);\n await tx.put(newDirNode.ino, encodeDirListing(newDirList), true);\n }\n catch (e) {\n await tx.abort();\n throw e;\n }\n await tx.commit();\n }\n finally {\n if (c) {\n this._cache = c;\n }\n }\n }\n async stat(p, cred) {\n const tx = this.store.beginTransaction('readonly');\n const inode = await this.findINode(tx, p);\n if (!inode) {\n throw ApiError.ENOENT(p);\n }\n const stats = inode.toStats();\n if (!stats.hasAccess(R_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n return stats;\n }\n async createFile(p, flag, mode, cred) {\n const tx = this.store.beginTransaction('readwrite'), data = new Uint8Array(0), newFile = await this.commitNewFile(tx, p, FileType.FILE, mode, cred, data);\n // Open the file.\n return new AsyncFile(this, p, flag, newFile.toStats(), data);\n }\n async openFile(p, flag, cred) {\n const tx = this.store.beginTransaction('readonly'), node = await this.findINode(tx, p), data = await tx.get(node.ino);\n if (!node.toStats().hasAccess(flagToMode(flag), cred)) {\n throw ApiError.EACCES(p);\n }\n if (!data) {\n throw ApiError.ENOENT(p);\n }\n return new AsyncFile(this, p, flag, node.toStats(), data);\n }\n async unlink(p, cred) {\n return this.removeEntry(p, false, cred);\n }\n async rmdir(p, cred) {\n // Check first if directory is empty.\n const list = await this.readdir(p, cred);\n if (list.length > 0) {\n throw ApiError.ENOTEMPTY(p);\n }\n await this.removeEntry(p, true, cred);\n }\n async mkdir(p, mode, cred) {\n const tx = this.store.beginTransaction('readwrite'), data = encode('{}');\n await this.commitNewFile(tx, p, FileType.DIRECTORY, mode, cred, data);\n }\n async readdir(p, cred) {\n const tx = this.store.beginTransaction('readonly');\n const node = await this.findINode(tx, p);\n if (!node.toStats().hasAccess(R_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n return Object.keys(await this.getDirListing(tx, node, p));\n }\n /**\n * Updated the inode and data node at the given path\n * @todo Ensure mtime updates properly, and use that to determine if a data update is required.\n */\n async sync(p, data, stats) {\n const tx = this.store.beginTransaction('readwrite'), \n // We use the _findInode helper because we actually need the INode id.\n fileInodeId = await this._findINode(tx, dirname(p), basename(p)), fileInode = await this.getINode(tx, fileInodeId, p), inodeChanged = fileInode.update(stats);\n try {\n // Sync data.\n await tx.put(fileInode.ino, data, true);\n // Sync metadata.\n if (inodeChanged) {\n await tx.put(fileInodeId, fileInode.data, true);\n }\n }\n catch (e) {\n await tx.abort();\n throw e;\n }\n await tx.commit();\n }\n async link(existing, newpath, cred) {\n const tx = this.store.beginTransaction('readwrite'), existingDir = dirname(existing), existingDirNode = await this.findINode(tx, existingDir);\n if (!existingDirNode.toStats().hasAccess(R_OK, cred)) {\n throw ApiError.EACCES(existingDir);\n }\n const newDir = dirname(newpath), newDirNode = await this.findINode(tx, newDir), newListing = await this.getDirListing(tx, newDirNode, newDir);\n if (!newDirNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(newDir);\n }\n const ino = await this._findINode(tx, existingDir, basename(existing));\n const node = await this.getINode(tx, ino, existing);\n if (!node.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(newpath);\n }\n node.nlink++;\n newListing[basename(newpath)] = ino;\n try {\n tx.put(ino, node.data, true);\n tx.put(newDirNode.ino, encodeDirListing(newListing), true);\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n tx.commit();\n }\n /**\n * Checks if the root directory exists. Creates it if it doesn't.\n */\n async makeRootDirectory() {\n const tx = this.store.beginTransaction('readwrite');\n if ((await tx.get(rootIno)) === undefined) {\n // Create new inode. o777, owned by root:root\n const dirInode = new Inode();\n dirInode.mode = 0o777 | FileType.DIRECTORY;\n // If the root doesn't exist, the first random ID shouldn't exist,\n // either.\n await tx.put(dirInode.ino, encode('{}'), false);\n await tx.put(rootIno, dirInode.data, false);\n await tx.commit();\n }\n }\n /**\n * Helper function for findINode.\n * @param parent The parent directory of the file we are attempting to find.\n * @param filename The filename of the inode we are attempting to find, minus\n * the parent.\n */\n async _findINode(tx, parent, filename, visited = new Set()) {\n const currentPath = join(parent, filename);\n if (visited.has(currentPath)) {\n throw new ApiError(ErrorCode.EIO, 'Infinite loop detected while finding inode', currentPath);\n }\n visited.add(currentPath);\n if (this._cache) {\n const id = this._cache.get(currentPath);\n if (id) {\n return id;\n }\n }\n if (parent === '/') {\n if (filename === '') {\n // BASE CASE #1: Return the root's ID.\n if (this._cache) {\n this._cache.set(currentPath, rootIno);\n }\n return rootIno;\n }\n else {\n // BASE CASE #2: Find the item in the root node.\n const inode = await this.getINode(tx, rootIno, parent);\n const dirList = await this.getDirListing(tx, inode, parent);\n if (dirList[filename]) {\n const id = dirList[filename];\n if (this._cache) {\n this._cache.set(currentPath, id);\n }\n return id;\n }\n else {\n throw ApiError.ENOENT(resolve(parent, filename));\n }\n }\n }\n else {\n // Get the parent directory's INode, and find the file in its directory\n // listing.\n const inode = await this.findINode(tx, parent, visited);\n const dirList = await this.getDirListing(tx, inode, parent);\n if (dirList[filename]) {\n const id = dirList[filename];\n if (this._cache) {\n this._cache.set(currentPath, id);\n }\n return id;\n }\n else {\n throw ApiError.ENOENT(resolve(parent, filename));\n }\n }\n }\n /**\n * Finds the Inode of the given path.\n * @param p The path to look up.\n * @todo memoize/cache\n */\n async findINode(tx, p, visited = new Set()) {\n const id = await this._findINode(tx, dirname(p), basename(p), visited);\n return this.getINode(tx, id, p);\n }\n /**\n * Given the ID of a node, retrieves the corresponding Inode.\n * @param tx The transaction to use.\n * @param p The corresponding path to the file (used for error messages).\n * @param id The ID to look up.\n */\n async getINode(tx, id, p) {\n const data = await tx.get(id);\n if (!data) {\n throw ApiError.ENOENT(p);\n }\n return new Inode(data.buffer);\n }\n /**\n * Given the Inode of a directory, retrieves the corresponding directory\n * listing.\n */\n async getDirListing(tx, inode, p) {\n if (!inode.toStats().isDirectory()) {\n throw ApiError.ENOTDIR(p);\n }\n const data = await tx.get(inode.ino);\n if (!data) {\n /*\n Occurs when data is undefined, or corresponds to something other\n than a directory listing. The latter should never occur unless\n the file system is corrupted.\n */\n throw ApiError.ENOENT(p);\n }\n return decodeDirListing(data);\n }\n /**\n * Adds a new node under a random ID. Retries 5 times before giving up in\n * the exceedingly unlikely chance that we try to reuse a random ino.\n */\n async addNewNode(tx, data) {\n let retries = 0;\n const reroll = async () => {\n if (++retries === 5) {\n // Max retries hit. Return with an error.\n throw new ApiError(ErrorCode.EIO, 'Unable to commit data to key-value store.');\n }\n else {\n // Try again.\n const ino = randomIno();\n const committed = await tx.put(ino, data, false);\n if (!committed) {\n return reroll();\n }\n else {\n return ino;\n }\n }\n };\n return reroll();\n }\n /**\n * Commits a new file (well, a FILE or a DIRECTORY) to the file system with\n * the given mode.\n * Note: This will commit the transaction.\n * @param p The path to the new file.\n * @param type The type of the new file.\n * @param mode The mode to create the new file with.\n * @param cred The UID/GID to create the file with\n * @param data The data to store at the file's data node.\n */\n async commitNewFile(tx, p, type, mode, cred, data) {\n const parentDir = dirname(p), fname = basename(p), parentNode = await this.findINode(tx, parentDir), dirListing = await this.getDirListing(tx, parentNode, parentDir);\n //Check that the creater has correct access\n if (!parentNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n // Invariant: The root always exists.\n // If we don't check this prior to taking steps below, we will create a\n // file with name '' in root should p == '/'.\n if (p === '/') {\n throw ApiError.EEXIST(p);\n }\n // Check if file already exists.\n if (dirListing[fname]) {\n await tx.abort();\n throw ApiError.EEXIST(p);\n }\n try {\n // Commit data.\n const inode = new Inode();\n inode.ino = await this.addNewNode(tx, data);\n inode.mode = mode | type;\n inode.uid = cred.uid;\n inode.gid = cred.gid;\n inode.size = data.length;\n // Update and commit parent directory listing.\n dirListing[fname] = await this.addNewNode(tx, inode.data);\n await tx.put(parentNode.ino, encodeDirListing(dirListing), true);\n await tx.commit();\n return inode;\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n }\n /**\n * Remove all traces of the given path from the file system.\n * @param p The path to remove from the file system.\n * @param isDir Does the path belong to a directory, or a file?\n * @todo Update mtime.\n */\n /**\n * Remove all traces of the given path from the file system.\n * @param p The path to remove from the file system.\n * @param isDir Does the path belong to a directory, or a file?\n * @todo Update mtime.\n */\n async removeEntry(p, isDir, cred) {\n if (this._cache) {\n this._cache.remove(p);\n }\n const tx = this.store.beginTransaction('readwrite'), parent = dirname(p), parentNode = await this.findINode(tx, parent), parentListing = await this.getDirListing(tx, parentNode, parent), fileName = basename(p);\n if (!parentListing[fileName]) {\n throw ApiError.ENOENT(p);\n }\n const fileIno = parentListing[fileName];\n // Get file inode.\n const fileNode = await this.getINode(tx, fileIno, p);\n if (!fileNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n // Remove from directory listing of parent.\n delete parentListing[fileName];\n if (!isDir && fileNode.toStats().isDirectory()) {\n throw ApiError.EISDIR(p);\n }\n if (isDir && !fileNode.toStats().isDirectory()) {\n throw ApiError.ENOTDIR(p);\n }\n try {\n await tx.put(parentNode.ino, encodeDirListing(parentListing), true);\n if (--fileNode.nlink < 1) {\n // remove file\n await tx.remove(fileNode.ino);\n await tx.remove(fileIno);\n }\n }\n catch (e) {\n await tx.abort();\n throw e;\n }\n // Success.\n await tx.commit();\n }\n}\n", "import { AsyncROTransaction, AsyncRWTransaction, AsyncStore, AsyncStoreFS } from '@zenfs/core/backends/AsyncStore.js';\nimport { ApiError, ErrorCode } from '@zenfs/core/ApiError.js';\nimport type { Backend } from '@zenfs/core/backends/backend.js';\nimport type { Ino } from '@zenfs/core/inode.js';\n\n/**\n * Converts a DOMException or a DOMError from an IndexedDB event into a\n * standardized ZenFS API error.\n * @hidden\n */\nfunction convertError(e: { name: string }, message: string = e.toString()): ApiError {\n\tswitch (e.name) {\n\t\tcase 'NotFoundError':\n\t\t\treturn new ApiError(ErrorCode.ENOENT, message);\n\t\tcase 'QuotaExceededError':\n\t\t\treturn new ApiError(ErrorCode.ENOSPC, message);\n\t\tdefault:\n\t\t\t// The rest do not seem to map cleanly to standard error codes.\n\t\t\treturn new ApiError(ErrorCode.EIO, message);\n\t}\n}\n\n/**\n * @hidden\n */\nexport class IndexedDBROTransaction implements AsyncROTransaction {\n\tconstructor(\n\t\tpublic tx: IDBTransaction,\n\t\tpublic store: IDBObjectStore\n\t) {}\n\n\tpublic get(key: Ino): Promise<Uint8Array> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tconst req: IDBRequest = this.store.get(key.toString());\n\t\t\t\treq.onerror = e => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\treject(new ApiError(ErrorCode.EIO));\n\t\t\t\t};\n\t\t\t\treq.onsuccess = () => {\n\t\t\t\t\t// IDB returns the value 'undefined' when you try to get keys that\n\t\t\t\t\t// don't exist. The caller expects this behavior.\n\t\t\t\t\tconst result = req.result;\n\t\t\t\t\tif (result === undefined) {\n\t\t\t\t\t\tresolve(result);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// IDB data is stored as an ArrayUint8Array\n\t\t\t\t\t\tresolve(Uint8Array.from(result));\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t} catch (e) {\n\t\t\t\treject(convertError(e));\n\t\t\t}\n\t\t});\n\t}\n}\n\n/**\n * @hidden\n */\nexport class IndexedDBRWTransaction extends IndexedDBROTransaction implements AsyncRWTransaction, AsyncROTransaction {\n\tconstructor(tx: IDBTransaction, store: IDBObjectStore) {\n\t\tsuper(tx, store);\n\t}\n\n\t/**\n\t * @todo return false when add has a key conflict (no error)\n\t */\n\tpublic put(key: Ino, data: Uint8Array, overwrite: boolean): Promise<boolean> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tconst req: IDBRequest = overwrite ? this.store.put(data, key.toString()) : this.store.add(data, key.toString());\n\t\t\t\treq.onerror = e => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\treject(new ApiError(ErrorCode.EIO));\n\t\t\t\t};\n\t\t\t\treq.onsuccess = () => resolve(true);\n\t\t\t} catch (e) {\n\t\t\t\treject(convertError(e));\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic remove(key: Ino): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tconst req: IDBRequest = this.store.delete(key.toString());\n\t\t\t\treq.onerror = e => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\treject(new ApiError(ErrorCode.EIO));\n\t\t\t\t};\n\t\t\t\treq.onsuccess = () => resolve;\n\t\t\t} catch (e) {\n\t\t\t\treject(convertError(e));\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic commit(): Promise<void> {\n\t\treturn new Promise(resolve => setTimeout(resolve, 0));\n\t}\n\n\tpublic async abort(): Promise<void> {\n\t\ttry {\n\t\t\tthis.tx.abort();\n\t\t} catch (e) {\n\t\t\tthrow convertError(e);\n\t\t}\n\t}\n}\n\nexport class IndexedDBStore implements AsyncStore {\n\tpublic static create(storeName: string, indexedDB: IDBFactory): Promise<IndexedDBStore> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst req: IDBOpenDBRequest = indexedDB.open(storeName, 1);\n\n\t\t\treq.onupgradeneeded = () => {\n\t\t\t\tconst db: IDBDatabase = req.result;\n\t\t\t\t// This should never happen; we're at version 1. Why does another database exist?\n\t\t\t\tif (db.objectStoreNames.contains(storeName)) {\n\t\t\t\t\tdb.deleteObjectStore(storeName);\n\t\t\t\t}\n\t\t\t\tdb.createObjectStore(storeName);\n\t\t\t};\n\n\t\t\treq.onsuccess = () => resolve(new IndexedDBStore(req.result, storeName));\n\n\t\t\treq.onerror = e => {\n\t\t\t\te.preventDefault();\n\t\t\t\treject(new ApiError(ErrorCode.EACCES));\n\t\t\t};\n\t\t});\n\t}\n\n\tconstructor(\n\t\tprotected db: IDBDatabase,\n\t\tprotected storeName: string\n\t) {}\n\n\tpublic get name(): string {\n\t\treturn IndexedDB.name + ':' + this.storeName;\n\t}\n\n\tpublic clear(): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tconst req: IDBRequest = this.db.transaction(this.storeName, 'readwrite').objectStore(this.storeName).clear();\n\t\t\t\treq.onsuccess = () => setTimeout(resolve, 0);\n\t\t\t\treq.onerror = e => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\treject(new ApiError(ErrorCode.EIO));\n\t\t\t\t};\n\t\t\t} catch (e) {\n\t\t\t\treject(convertError(e));\n\t\t\t}\n\t\t});\n\t}\n\n\tpublic beginTransaction(type: 'readonly'): AsyncROTransaction;\n\tpublic beginTransaction(type: 'readwrite'): AsyncRWTransaction;\n\tpublic beginTransaction(type: 'readonly' | 'readwrite' = 'readonly'): AsyncROTransaction {\n\t\tconst tx = this.db.transaction(this.storeName, type),\n\t\t\tobjectStore = tx.objectStore(this.storeName);\n\t\tif (type === 'readwrite') {\n\t\t\treturn new IndexedDBRWTransaction(tx, objectStore);\n\t\t}\n\n\t\tif (type === 'readonly') {\n\t\t\treturn new IndexedDBROTransaction(tx, objectStore);\n\t\t}\n\n\t\tthrow new ApiError(ErrorCode.EINVAL, 'Invalid transaction type.');\n\t}\n}\n\n/**\n * Configuration options for the IndexedDB file system.\n */\nexport interface IndexedDBOptions {\n\t/**\n\t * The name of this file system. You can have multiple IndexedDB file systems operating at once, but each must have a different name.\n\t */\n\tstoreName?: string;\n\n\t/**\n\t * The size of the inode cache. Defaults to 100. A size of 0 or below disables caching.\n\t */\n\tcacheSize?: number;\n\n\t/**\n\t * The IDBFactory to use. Defaults to `globalThis.indexedDB`.\n\t */\n\tidbFactory?: IDBFactory;\n}\n\n/**\n * A file system that uses the IndexedDB key value file system.\n */\n\nexport const IndexedDB: Backend = {\n\tname: 'IndexedDB',\n\n\toptions: {\n\t\tstoreName: {\n\t\t\ttype: 'string',\n\t\t\trequired: false,\n\t\t\tdescription: 'The name of this file system. You can have multiple IndexedDB file systems operating at once, but each must have a different name.',\n\t\t},\n\t\tcacheSize: {\n\t\t\ttype: 'number',\n\t\t\trequired: false,\n\t\t\tdescription: 'The size of the inode cache. Defaults to 100. A size of 0 or below disables caching.',\n\t\t},\n\t\tidbFactory: {\n\t\t\ttype: 'object',\n\t\t\trequired: false,\n\t\t\tdescription: 'The IDBFactory to use. Defaults to globalThis.indexedDB.',\n\t\t},\n\t},\n\n\tisAvailable(idbFactory: IDBFactory = globalThis.indexedDB): boolean {\n\t\ttry {\n\t\t\tif (!(idbFactory instanceof IDBFactory)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tconst req = idbFactory.open('__zenfs_test');\n\t\t\tif (!req) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treq.onsuccess = () => idbFactory.deleteDatabase('__zenfs_test');\n\t\t} catch (e) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\tcreate({ cacheSize = 100, storeName = 'zenfs', idbFactory = globalThis.indexedDB }: IndexedDBOptions) {\n\t\tconst store = IndexedDBStore.create(storeName, idbFactory);\n\t\tconst fs = new AsyncStoreFS({ cacheSize, store });\n\t\treturn fs;\n\t},\n};\n", "import { dirname, basename, join, resolve, sep } from '../emulation/path.js';\nimport { ApiError, ErrorCode } from '../ApiError.js';\nimport { W_OK, R_OK } from '../emulation/constants.js';\nimport { PreloadFile, flagToMode } from '../file.js';\nimport { FileSystem, Sync } from '../filesystem.js';\nimport { randomIno, Inode } from '../inode.js';\nimport { FileType } from '../stats.js';\nimport { decodeDirListing, encode, encodeDirListing } from '../utils.js';\nimport { rootIno } from '../inode.js';\n/**\n * A simple RW transaction for simple synchronous key-value stores.\n */\nexport class SimpleSyncRWTransaction {\n constructor(store) {\n this.store = store;\n /**\n * Stores data in the keys we modify prior to modifying them.\n * Allows us to roll back commits.\n */\n this.originalData = new Map();\n /**\n * List of keys modified in this transaction, if any.\n */\n this.modifiedKeys = new Set();\n }\n get(ino) {\n const val = this.store.get(ino);\n this.stashOldValue(ino, val);\n return val;\n }\n put(ino, data, overwrite) {\n this.markModified(ino);\n return this.store.put(ino, data, overwrite);\n }\n remove(ino) {\n this.markModified(ino);\n this.store.remove(ino);\n }\n commit() {\n /* NOP */\n }\n abort() {\n // Rollback old values.\n for (const key of this.modifiedKeys) {\n const value = this.originalData.get(key);\n if (!value) {\n // Key didn't exist.\n this.store.remove(key);\n }\n else {\n // Key existed. Store old value.\n this.store.put(key, value, true);\n }\n }\n }\n /**\n * Stashes given key value pair into `originalData` if it doesn't already\n * exist. Allows us to stash values the program is requesting anyway to\n * prevent needless `get` requests if the program modifies the data later\n * on during the transaction.\n */\n stashOldValue(ino, value) {\n // Keep only the earliest value in the transaction.\n if (!this.originalData.has(ino)) {\n this.originalData.set(ino, value);\n }\n }\n /**\n * Marks the given key as modified, and stashes its value if it has not been\n * stashed already.\n */\n markModified(ino) {\n this.modifiedKeys.add(ino);\n if (!this.originalData.has(ino)) {\n this.originalData.set(ino, this.store.get(ino));\n }\n }\n}\n/**\n * File backend by a SyncStoreFS\n * @internal\n */\nexport class SyncStoreFile extends PreloadFile {\n constructor(_fs, _path, _flag, _stat, contents) {\n super(_fs, _path, _flag, _stat, contents);\n }\n async sync() {\n this.syncSync();\n }\n syncSync() {\n if (this.isDirty()) {\n this.fs.syncSync(this.path, this._buffer, this.stats);\n this.resetDirty();\n }\n }\n async close() {\n this.closeSync();\n }\n closeSync() {\n this.syncSync();\n }\n}\n/**\n * A synchronous key-value file system. Uses a SyncStore to store the data.\n *\n * We use a unique ID for each node in the file system. The root node has a fixed ID.\n * @todo Introduce Node ID caching.\n * @todo Check modes.\n * @internal\n */\nexport class SyncStoreFS extends Sync(FileSystem) {\n constructor(options) {\n super();\n this.store = options.store;\n // INVARIANT: Ensure that the root exists.\n this.makeRootDirectory();\n }\n metadata() {\n return {\n ...super.metadata(),\n name: this.store.name,\n };\n }\n /**\n * Delete all contents stored in the file system.\n */\n empty() {\n this.store.clear();\n // INVARIANT: Root always exists.\n this.makeRootDirectory();\n }\n renameSync(oldPath, newPath, cred) {\n const tx = this.store.beginTransaction('readwrite'), oldParent = dirname(oldPath), oldName = basename(oldPath), newParent = dirname(newPath), newName = basename(newPath), \n // Remove oldPath from parent's directory listing.\n oldDirNode = this.findINode(tx, oldParent), oldDirList = this.getDirListing(tx, oldDirNode, oldParent);\n if (!oldDirNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(oldPath);\n }\n if (!oldDirList[oldName]) {\n throw ApiError.ENOENT(oldPath);\n }\n const ino = oldDirList[oldName];\n delete oldDirList[oldName];\n // Invariant: Can't move a folder inside itself.\n // This funny little hack ensures that the check passes only if oldPath\n // is a subpath of newParent. We append '/' to avoid matching folders that\n // are a substring of the bottom-most folder in the path.\n if ((newParent + '/').indexOf(oldPath + '/') == 0) {\n throw new ApiError(ErrorCode.EBUSY, oldParent);\n }\n // Add newPath to parent's directory listing.\n let newDirNode, newDirList;\n if (newParent === oldParent) {\n // Prevent us from re-grabbing the same directory listing, which still\n // contains oldName.\n newDirNode = oldDirNode;\n newDirList = oldDirList;\n }\n else {\n newDirNode = this.findINode(tx, newParent);\n newDirList = this.getDirListing(tx, newDirNode, newParent);\n }\n if (newDirList[newName]) {\n // If it's a file, delete it.\n const newNameNode = this.getINode(tx, newDirList[newName], newPath);\n if (newNameNode.toStats().isFile()) {\n try {\n tx.remove(newNameNode.ino);\n tx.remove(newDirList[newName]);\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n }\n else {\n // If it's a directory, throw a permissions error.\n throw ApiError.EPERM(newPath);\n }\n }\n newDirList[newName] = ino;\n // Commit the two changed directory listings.\n try {\n tx.put(oldDirNode.ino, encodeDirListing(oldDirList), true);\n tx.put(newDirNode.ino, encodeDirListing(newDirList), true);\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n tx.commit();\n }\n statSync(p, cred) {\n // Get the inode to the item, convert it into a Stats object.\n const stats = this.findINode(this.store.beginTransaction('readonly'), p).toStats();\n if (!stats.hasAccess(R_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n return stats;\n }\n createFileSync(p, flag, mode, cred) {\n this.commitNewFile(p, FileType.FILE, mode, cred);\n return this.openFileSync(p, flag, cred);\n }\n openFileSync(p, flag, cred) {\n const tx = this.store.beginTransaction('readonly'), node = this.findINode(tx, p), data = tx.get(node.ino);\n if (!node.toStats().hasAccess(flagToMode(flag), cred)) {\n throw ApiError.EACCES(p);\n }\n if (data === null) {\n throw ApiError.ENOENT(p);\n }\n return new SyncStoreFile(this, p, flag, node.toStats(), data);\n }\n unlinkSync(p, cred) {\n this.removeEntry(p, false, cred);\n }\n rmdirSync(p, cred) {\n // Check first if directory is empty.\n if (this.readdirSync(p, cred).length > 0) {\n throw ApiError.ENOTEMPTY(p);\n }\n else {\n this.removeEntry(p, true, cred);\n }\n }\n mkdirSync(p, mode, cred) {\n this.commitNewFile(p, FileType.DIRECTORY, mode, cred, encode('{}'));\n }\n readdirSync(p, cred) {\n const tx = this.store.beginTransaction('readonly');\n const node = this.findINode(tx, p);\n if (!node.toStats().hasAccess(R_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n return Object.keys(this.getDirListing(tx, node, p));\n }\n syncSync(p, data, stats) {\n // @todo Ensure mtime updates properly, and use that to determine if a data\n // update is required.\n const tx = this.store.beginTransaction('readwrite'), \n // We use the _findInode helper because we actually need the INode id.\n fileInodeId = this._findINode(tx, dirname(p), basename(p)), fileInode = this.getINode(tx, fileInodeId, p), inodeChanged = fileInode.update(stats);\n try {\n // Sync data.\n tx.put(fileInode.ino, data, true);\n // Sync metadata.\n if (inodeChanged) {\n tx.put(fileInodeId, fileInode.data, true);\n }\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n tx.commit();\n }\n linkSync(existing, newpath, cred) {\n const tx = this.store.beginTransaction('readwrite'), existingDir = dirname(existing), existingDirNode = this.findINode(tx, existingDir);\n if (!existingDirNode.toStats().hasAccess(R_OK, cred)) {\n throw ApiError.EACCES(existingDir);\n }\n const newDir = dirname(newpath), newDirNode = this.findINode(tx, newDir), newListing = this.getDirListing(tx, newDirNode, newDir);\n if (!newDirNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(newDir);\n }\n const ino = this._findINode(tx, existingDir, basename(existing));\n const node = this.getINode(tx, ino, existing);\n if (!node.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(newpath);\n }\n node.nlink++;\n newListing[basename(newpath)] = ino;\n try {\n tx.put(ino, node.data, true);\n tx.put(newDirNode.ino, encodeDirListing(newListing), true);\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n tx.commit();\n }\n /**\n * Checks if the root directory exists. Creates it if it doesn't.\n */\n makeRootDirectory() {\n const tx = this.store.beginTransaction('readwrite');\n if (tx.get(rootIno)) {\n return;\n }\n // Create new inode, mode o777, owned by root:root\n const inode = new Inode();\n inode.mode = 0o777 | FileType.DIRECTORY;\n // If the root doesn't exist, the first random ID shouldn't exist either.\n tx.put(inode.ino, encode('{}'), false);\n tx.put(rootIno, inode.data, false);\n tx.commit();\n }\n /**\n * Helper function for findINode.\n * @param parent The parent directory of the file we are attempting to find.\n * @param filename The filename of the inode we are attempting to find, minus\n * the parent.\n * @return string The ID of the file's inode in the file system.\n */\n _findINode(tx, parent, filename, visited = new Set()) {\n const currentPath = join(parent, filename);\n if (visited.has(currentPath)) {\n throw new ApiError(ErrorCode.EIO, 'Infinite loop detected while finding inode', currentPath);\n }\n visited.add(currentPath);\n if (parent != '/') {\n const ino = this._findINode(tx, dirname(parent), basename(parent), visited);\n const dir = this.getDirListing(tx, this.getINode(tx, ino, parent + sep + filename), parent);\n if (!(filename in dir)) {\n throw ApiError.ENOENT(resolve(parent, filename));\n }\n return dir[filename];\n }\n if (filename != '') {\n // Find the item in the root node.\n const dir = this.getDirListing(tx, this.getINode(tx, rootIno, parent), parent);\n if (!(filename in dir)) {\n throw ApiError.ENOENT(resolve(parent, filename));\n }\n return dir[filename];\n }\n // Return the root's ID.\n return rootIno;\n }\n /**\n * Finds the Inode of the given path.\n * @param p The path to look up.\n * @return The Inode of the path p.\n * @todo memoize/cache\n */\n findINode(tx, p) {\n const ino = this._findINode(tx, dirname(p), basename(p));\n return this.getINode(tx, ino, p);\n }\n /**\n * Given the ID of a node, retrieves the corresponding Inode.\n * @param tx The transaction to use.\n * @param p The corresponding path to the file (used for error messages).\n * @param id The ID to look up.\n */\n getINode(tx, id, p) {\n const data = tx.get(id);\n if (!data) {\n throw ApiError.ENOENT(p);\n }\n const inode = new Inode(data.buffer);\n return inode;\n }\n /**\n * Given the Inode of a directory, retrieves the corresponding directory listing.\n */\n getDirListing(tx, inode, p) {\n if (!inode.toStats().isDirectory()) {\n throw ApiError.ENOTDIR(p);\n }\n const data = tx.get(inode.ino);\n if (!data) {\n throw ApiError.ENOENT(p);\n }\n return decodeDirListing(data);\n }\n /**\n * Creates a new node under a random ID. Retries 5 times before giving up in\n * the exceedingly unlikely chance that we try to reuse a random GUID.\n * @return The GUID that the data was stored under.\n */\n addNewNode(tx, data) {\n const retries = 0;\n let ino;\n while (retries < 5) {\n try {\n ino = randomIno();\n tx.put(ino, data, false);\n return ino;\n }\n catch (e) {\n // Ignore and reroll.\n }\n }\n throw new ApiError(ErrorCode.EIO, 'Unable to commit data to key-value store.');\n }\n /**\n * Commits a new file (well, a FILE or a DIRECTORY) to the file system with the given mode.\n * Note: This will commit the transaction.\n * @param p The path to the new file.\n * @param type The type of the new file.\n * @param mode The mode to create the new file with.\n * @param data The data to store at the file's data node.\n * @return The Inode for the new file.\n */\n commitNewFile(p, type, mode, cred, data = new Uint8Array()) {\n const tx = this.store.beginTransaction('readwrite'), parentDir = dirname(p), fname = basename(p), parentNode = this.findINode(tx, parentDir), dirListing = this.getDirListing(tx, parentNode, parentDir);\n //Check that the creater has correct access\n if (!parentNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n /* Invariant: The root always exists.\n If we don't check this prior to taking steps below,\n we will create a file with name '' in root should p == '/'.\n */\n if (p === '/') {\n throw ApiError.EEXIST(p);\n }\n // Check if file already exists.\n if (dirListing[fname]) {\n throw ApiError.EEXIST(p);\n }\n const fileNode = new Inode();\n try {\n // Commit data.\n fileNode.ino = this.addNewNode(tx, data);\n fileNode.size = data.length;\n fileNode.mode = mode | type;\n fileNode.uid = cred.uid;\n fileNode.gid = cred.gid;\n // Update and commit parent directory listing.\n dirListing[fname] = this.addNewNode(tx, fileNode.data);\n tx.put(parentNode.ino, encodeDirListing(dirListing), true);\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n tx.commit();\n return fileNode;\n }\n /**\n * Remove all traces of the given path from the file system.\n * @param p The path to remove from the file system.\n * @param isDir Does the path belong to a directory, or a file?\n * @todo Update mtime.\n */\n removeEntry(p, isDir, cred) {\n const tx = this.store.beginTransaction('readwrite'), parent = dirname(p), parentNode = this.findINode(tx, parent), parentListing = this.getDirListing(tx, parentNode, parent), fileName = basename(p), fileIno = parentListing[fileName];\n if (!fileIno) {\n throw ApiError.ENOENT(p);\n }\n // Get file inode.\n const fileNode = this.getINode(tx, fileIno, p);\n if (!fileNode.toStats().hasAccess(W_OK, cred)) {\n throw ApiError.EACCES(p);\n }\n // Remove from directory listing of parent.\n delete parentListing[fileName];\n if (!isDir && fileNode.toStats().isDirectory()) {\n throw ApiError.EISDIR(p);\n }\n if (isDir && !fileNode.toStats().isDirectory()) {\n throw ApiError.ENOTDIR(p);\n }\n try {\n // Update directory listing.\n tx.put(parentNode.ino, encodeDirListing(parentListing), true);\n if (--fileNode.nlink < 1) {\n // remove file\n tx.remove(fileNode.ino);\n tx.remove(fileIno);\n }\n }\n catch (e) {\n tx.abort();\n throw e;\n }\n // Success.\n tx.commit();\n }\n}\n", "import { SyncStore, SimpleSyncStore, SimpleSyncRWTransaction, SyncRWTransaction, SyncStoreFS } from '@zenfs/core/backends/SyncStore.js';\nimport { ApiError, ErrorCode } from '@zenfs/core/ApiError.js';\nimport { type Backend } from '@zenfs/core/backends/backend.js';\nimport { decode, encode } from '@zenfs/core/utils.js';\nimport type { Ino } from '@zenfs/core/inode.js';\n\n/**\n * A synchronous key-value store backed by Storage.\n */\nexport class StorageStore implements SyncStore, SimpleSyncStore {\n\tpublic get name(): string {\n\t\treturn Storage.name;\n\t}\n\n\tconstructor(protected _storage: Storage) {}\n\n\tpublic clear(): void {\n\t\tthis._storage.clear();\n\t}\n\n\tpublic beginTransaction(): SyncRWTransaction {\n\t\t// No need to differentiate.\n\t\treturn new SimpleSyncRWTransaction(this);\n\t}\n\n\tpublic get(key: Ino): Uint8Array | undefined {\n\t\tconst data = this._storage.getItem(key.toString());\n\t\tif (typeof data != 'string') {\n\t\t\treturn;\n\t\t}\n\n\t\treturn encode(data);\n\t}\n\n\tpublic put(key: Ino, data: Uint8Array, overwrite: boolean): boolean {\n\t\ttry {\n\t\t\tif (!overwrite && this._storage.getItem(key.toString()) !== null) {\n\t\t\t\t// Don't want to overwrite the key!\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthis._storage.setItem(key.toString(), decode(data));\n\t\t\treturn true;\n\t\t} catch (e) {\n\t\t\tthrow new ApiError(ErrorCode.ENOSPC, 'Storage is full.');\n\t\t}\n\t}\n\n\tpublic remove(key: Ino): void {\n\t\ttry {\n\t\t\tthis._storage.removeItem(key.toString());\n\t\t} catch (e) {\n\t\t\tthrow new ApiError(ErrorCode.EIO, 'Unable to delete key ' + key + ': ' + e);\n\t\t}\n\t}\n}\n\n/**\n * Options to pass to the StorageFileSystem\n */\nexport interface StorageOptions {\n\t/**\n\t * The Storage to use. Defaults to globalThis.localStorage.\n\t */\n\tstorage: Storage;\n}\n\n/**\n * A synchronous file system backed by a `Storage` (e.g. localStorage).\n */\nexport const Storage: Backend = {\n\tname: 'Storage',\n\n\toptions: {\n\t\tstorage: {\n\t\t\ttype: 'object',\n\t\t\trequired: false,\n\t\t\tdescription: 'The Storage to use. Defaults to globalThis.localStorage.',\n\t\t},\n\t},\n\n\tisAvailable(storage: Storage = globalThis.localStorage): boolean {\n\t\treturn storage instanceof globalThis.Storage;\n\t},\n\n\tcreate({ storage = globalThis.localStorage }: StorageOptions) {\n\t\treturn new SyncStoreFS({ store: new StorageStore(storage) });\n\t},\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["src_exports", "__export", "FileSystemAccess", "FileSystemAccessFS", "FileSystemAccessFile", "IndexedDB", "IndexedDBROTransaction", "IndexedDBRWTransaction", "IndexedDBStore", "Storage", "StorageStore", "cwd", "sep", "validateString", "str", "name", "__name", "normalizeString", "path", "allowAboveRoot", "res", "lastSegmentLength", "lastSlash", "dots", "char", "i", "lastSlashIndex", "__name", "resolve", "args", "resolvedPath", "resolvedAbsolute", "i", "path", "cwd", "validateString", "normalizeString", "__name", "normalize", "isAbsolute", "trailingSeparator", "join", "args", "joined", "i", "arg", "validateString", "normalize", "__name", "dirname", "path", "validateString", "hasRoot", "end", "matchedSlash", "__name", "basename", "suffix", "start", "extIdx", "firstNonSlashEnd", "i", "ErrorCode", "ErrorStrings", "ApiError", "json", "err", "code", "path", "errno", "message", "__name", "FileType", "StatsCommon", "arg", "value", "atimeMs", "mtimeMs", "ctimeMs", "birthtimeMs", "uid", "gid", "size", "mode", "currentTime", "resolveT", "__name", "val", "_default", "itemType", "cred", "perms", "uMode", "gMode", "wMode", "uPerms", "gPerms", "wPerms", "Stats", "stats", "size_max", "rootIno", "_random", "__name", "randomIno", "Offset", "Inode", "buffer", "setDefaults", "now", "value", "Stats", "stats", "hasChanged", "ActionType", "flagToMode", "flag", "mode", "isReadable", "isWriteable", "__name", "isAppendable", "flag", "__name", "isSynchronous", "File", "__name", "PreloadFile", "fs", "path", "flag", "stats", "_buffer", "size_max", "isReadable", "isAppendable", "newPos", "Stats", "len", "isSynchronous", "isWriteable", "ApiError", "ErrorCode", "buf", "buffer", "offset", "length", "position", "endFp", "newBuffer", "end", "bytesRead", "mode", "uid", "gid", "atime", "mtime", "type", "FileSystem", "options", "path", "cred", "__name", "Sync", "FS", "_SyncFileSystem", "oldPath", "newPath", "flag", "mode", "srcpath", "dstpath", "data", "stats", "Async", "_AsyncFileSystem", "ApiError", "ErrorCode", "handleError", "__name", "path", "error", "ApiError", "FileSystemAccessFile", "PreloadFile", "_fs", "_path", "_flag", "_stat", "contents", "ErrorCode", "FileSystemAccessFS", "Async", "FileSystem", "handle", "p", "data", "stats", "currentStats", "oldPath", "newPath", "files", "file", "join", "oldFile", "destFolder", "dirname", "writable", "basename", "buffer", "err", "fname", "flag", "Stats", "FileType", "lastModified", "size", "e", "_keys", "key", "walkedPath", "pathParts", "getHandleParts", "pathPart", "remainingPathParts", "walkingPath", "continueWalk", "FileSystemAccess", "options", "setImmediate", "cb", "encode", "input", "encoding", "ApiError", "ErrorCode", "char", "code", "a", "b", "e", "u16", "i", "__name", "decode", "utf8String", "utf16leString", "decodeDirListing", "data", "k", "v", "encodeDirListing", "LRUCache", "limit", "key", "value", "existingIndex", "node", "n", "index", "__name", "AsyncFile", "PreloadFile", "_fs", "_path", "_flag", "_stat", "contents", "ApiError", "ErrorCode", "AsyncStoreFS", "Async", "FileSystem", "store", "cacheSize", "oldPath", "newPath", "cred", "c", "tx", "oldParent", "dirname", "oldName", "basename", "newParent", "newName", "oldDirNode", "oldDirList", "nodeId", "newDirNode", "newDirList", "newNameNode", "e", "encodeDirListing", "p", "inode", "stats", "flag", "mode", "data", "newFile", "FileType", "flagToMode", "encode", "fileInodeId", "fileInode", "inodeChanged", "existing", "newpath", "existingDir", "newDir", "newListing", "ino", "rootIno", "dirInode", "Inode", "parent", "filename", "visited", "currentPath", "join", "id", "dirList", "resolve", "decodeDirListing", "retries", "reroll", "randomIno", "type", "parentDir", "fname", "parentNode", "dirListing", "isDir", "parentListing", "fileName", "fileIno", "fileNode", "convertError", "e", "message", "ApiError", "ErrorCode", "__name", "IndexedDBROTransaction", "tx", "store", "key", "resolve", "reject", "req", "result", "IndexedDBRWTransaction", "data", "overwrite", "IndexedDBStore", "db", "storeName", "indexedDB", "IndexedDB", "type", "objectStore", "idbFactory", "cacheSize", "AsyncStoreFS", "SimpleSyncRWTransaction", "store", "ino", "val", "data", "overwrite", "key", "value", "__name", "SyncStoreFile", "PreloadFile", "_fs", "_path", "_flag", "_stat", "contents", "SyncStoreFS", "Sync", "FileSystem", "options", "oldPath", "newPath", "cred", "tx", "oldParent", "dirname", "oldName", "basename", "newParent", "newName", "oldDirNode", "oldDirList", "ApiError", "ErrorCode", "newDirNode", "newDirList", "newNameNode", "e", "encodeDirListing", "p", "stats", "flag", "mode", "FileType", "node", "flagToMode", "encode", "fileInodeId", "fileInode", "inodeChanged", "existing", "newpath", "existingDir", "newDir", "newListing", "rootIno", "inode", "Inode", "parent", "filename", "visited", "currentPath", "join", "dir", "sep", "resolve", "id", "decodeDirListing", "randomIno", "type", "parentDir", "fname", "parentNode", "dirListing", "fileNode", "isDir", "parentListing", "fileName", "fileIno", "StorageStore", "_storage", "Storage", "SimpleSyncRWTransaction", "key", "data", "encode", "overwrite", "decode", "ApiError", "ErrorCode", "__name", "storage", "SyncStoreFS"]
|
|
7
7
|
}
|