memfs 4.55.0 → 4.56.2
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/README.md +75 -2
- package/lib/fsa/index.d.ts +1 -33
- package/lib/fsa/index.js +1 -39
- package/lib/fsa/index.js.map +1 -1
- package/lib/fsa-to-node/index.d.ts +1 -2
- package/lib/fsa-to-node/index.js +2 -5
- package/lib/fsa-to-node/index.js.map +1 -1
- package/lib/index.d.ts +6 -7
- package/lib/index.js +10 -14
- package/lib/index.js.map +1 -1
- package/lib/node-to-fsa/index.d.ts +1 -7
- package/lib/node-to-fsa/index.js +1 -10
- package/lib/node-to-fsa/index.js.map +1 -1
- package/package.json +9 -3
- package/lib/constants.d.ts +0 -67
- package/lib/constants.js +0 -54
- package/lib/constants.js.map +0 -1
- package/lib/consts/AMODE.d.ts +0 -9
- package/lib/consts/AMODE.js +0 -3
- package/lib/consts/AMODE.js.map +0 -1
- package/lib/consts/FLAG.d.ts +0 -53
- package/lib/consts/FLAG.js +0 -36
- package/lib/consts/FLAG.js.map +0 -1
- package/lib/core/File.d.ts +0 -39
- package/lib/core/File.js +0 -72
- package/lib/core/File.js.map +0 -1
- package/lib/core/Link.d.ts +0 -38
- package/lib/core/Link.js +0 -105
- package/lib/core/Link.js.map +0 -1
- package/lib/core/Node.d.ts +0 -85
- package/lib/core/Node.js +0 -287
- package/lib/core/Node.js.map +0 -1
- package/lib/core/Superblock.d.ts +0 -92
- package/lib/core/Superblock.js +0 -689
- package/lib/core/Superblock.js.map +0 -1
- package/lib/core/constants.d.ts +0 -15
- package/lib/core/constants.js +0 -3
- package/lib/core/constants.js.map +0 -1
- package/lib/core/index.d.ts +0 -6
- package/lib/core/index.js +0 -15
- package/lib/core/index.js.map +0 -1
- package/lib/core/json.d.ts +0 -9
- package/lib/core/json.js +0 -35
- package/lib/core/json.js.map +0 -1
- package/lib/core/result.d.ts +0 -11
- package/lib/core/result.js +0 -11
- package/lib/core/result.js.map +0 -1
- package/lib/core/types.d.ts +0 -8
- package/lib/core/types.js +0 -3
- package/lib/core/types.js.map +0 -1
- package/lib/core/util.d.ts +0 -12
- package/lib/core/util.js +0 -74
- package/lib/core/util.js.map +0 -1
- package/lib/encoding.d.ts +0 -6
- package/lib/encoding.js +0 -20
- package/lib/encoding.js.map +0 -1
- package/lib/fsa/CoreFileSystemDirectoryHandle.d.ts +0 -73
- package/lib/fsa/CoreFileSystemDirectoryHandle.js +0 -265
- package/lib/fsa/CoreFileSystemDirectoryHandle.js.map +0 -1
- package/lib/fsa/CoreFileSystemFileHandle.d.ts +0 -25
- package/lib/fsa/CoreFileSystemFileHandle.js +0 -75
- package/lib/fsa/CoreFileSystemFileHandle.js.map +0 -1
- package/lib/fsa/CoreFileSystemHandle.d.ts +0 -34
- package/lib/fsa/CoreFileSystemHandle.js +0 -53
- package/lib/fsa/CoreFileSystemHandle.js.map +0 -1
- package/lib/fsa/CoreFileSystemObserver.d.ts +0 -10
- package/lib/fsa/CoreFileSystemObserver.js +0 -18
- package/lib/fsa/CoreFileSystemObserver.js.map +0 -1
- package/lib/fsa/CoreFileSystemSyncAccessHandle.d.ts +0 -38
- package/lib/fsa/CoreFileSystemSyncAccessHandle.js +0 -123
- package/lib/fsa/CoreFileSystemSyncAccessHandle.js.map +0 -1
- package/lib/fsa/CoreFileSystemWritableFileStream.d.ts +0 -32
- package/lib/fsa/CoreFileSystemWritableFileStream.js +0 -163
- package/lib/fsa/CoreFileSystemWritableFileStream.js.map +0 -1
- package/lib/fsa/CorePermissionStatus.d.ts +0 -9
- package/lib/fsa/CorePermissionStatus.js +0 -14
- package/lib/fsa/CorePermissionStatus.js.map +0 -1
- package/lib/fsa/FileLockManager.d.ts +0 -7
- package/lib/fsa/FileLockManager.js +0 -26
- package/lib/fsa/FileLockManager.js.map +0 -1
- package/lib/fsa/types.d.ts +0 -182
- package/lib/fsa/types.js +0 -3
- package/lib/fsa/types.js.map +0 -1
- package/lib/fsa/util.d.ts +0 -12
- package/lib/fsa/util.js +0 -45
- package/lib/fsa/util.js.map +0 -1
- package/lib/fsa-to-node/FsaNodeCore.d.ts +0 -33
- package/lib/fsa-to-node/FsaNodeCore.js +0 -191
- package/lib/fsa-to-node/FsaNodeCore.js.map +0 -1
- package/lib/fsa-to-node/FsaNodeDirent.d.ts +0 -19
- package/lib/fsa-to-node/FsaNodeDirent.js +0 -39
- package/lib/fsa-to-node/FsaNodeDirent.js.map +0 -1
- package/lib/fsa-to-node/FsaNodeFs.d.ts +0 -187
- package/lib/fsa-to-node/FsaNodeFs.js +0 -831
- package/lib/fsa-to-node/FsaNodeFs.js.map +0 -1
- package/lib/fsa-to-node/FsaNodeFsOpenFile.d.ts +0 -24
- package/lib/fsa-to-node/FsaNodeFsOpenFile.js +0 -37
- package/lib/fsa-to-node/FsaNodeFsOpenFile.js.map +0 -1
- package/lib/fsa-to-node/FsaNodeReadStream.d.ts +0 -23
- package/lib/fsa-to-node/FsaNodeReadStream.js +0 -92
- package/lib/fsa-to-node/FsaNodeReadStream.js.map +0 -1
- package/lib/fsa-to-node/FsaNodeStats.d.ts +0 -30
- package/lib/fsa-to-node/FsaNodeStats.js +0 -53
- package/lib/fsa-to-node/FsaNodeStats.js.map +0 -1
- package/lib/fsa-to-node/FsaNodeWriteStream.d.ts +0 -47
- package/lib/fsa-to-node/FsaNodeWriteStream.js +0 -150
- package/lib/fsa-to-node/FsaNodeWriteStream.js.map +0 -1
- package/lib/fsa-to-node/constants.d.ts +0 -3
- package/lib/fsa-to-node/constants.js +0 -3
- package/lib/fsa-to-node/constants.js.map +0 -1
- package/lib/fsa-to-node/json.d.ts +0 -2
- package/lib/fsa-to-node/json.js +0 -7
- package/lib/fsa-to-node/json.js.map +0 -1
- package/lib/fsa-to-node/types.d.ts +0 -37
- package/lib/fsa-to-node/types.js +0 -3
- package/lib/fsa-to-node/types.js.map +0 -1
- package/lib/fsa-to-node/util.d.ts +0 -4
- package/lib/fsa-to-node/util.js +0 -34
- package/lib/fsa-to-node/util.js.map +0 -1
- package/lib/fsa-to-node/worker/FsaNodeSyncAdapterWorker.d.ts +0 -10
- package/lib/fsa-to-node/worker/FsaNodeSyncAdapterWorker.js +0 -62
- package/lib/fsa-to-node/worker/FsaNodeSyncAdapterWorker.js.map +0 -1
- package/lib/fsa-to-node/worker/FsaNodeSyncWorker.d.ts +0 -20
- package/lib/fsa-to-node/worker/FsaNodeSyncWorker.js +0 -178
- package/lib/fsa-to-node/worker/FsaNodeSyncWorker.js.map +0 -1
- package/lib/fsa-to-node/worker/SyncMessenger.d.ts +0 -24
- package/lib/fsa-to-node/worker/SyncMessenger.js +0 -72
- package/lib/fsa-to-node/worker/SyncMessenger.js.map +0 -1
- package/lib/fsa-to-node/worker/constants.d.ts +0 -8
- package/lib/fsa-to-node/worker/constants.js +0 -3
- package/lib/fsa-to-node/worker/constants.js.map +0 -1
- package/lib/fsa-to-node/worker/types.d.ts +0 -17
- package/lib/fsa-to-node/worker/types.js +0 -3
- package/lib/fsa-to-node/worker/types.js.map +0 -1
- package/lib/node/Dir.d.ts +0 -26
- package/lib/node/Dir.js +0 -186
- package/lib/node/Dir.js.map +0 -1
- package/lib/node/Dirent.d.ts +0 -26
- package/lib/node/Dirent.js +0 -57
- package/lib/node/Dirent.js.map +0 -1
- package/lib/node/FileHandle.d.ts +0 -52
- package/lib/node/FileHandle.js +0 -189
- package/lib/node/FileHandle.js.map +0 -1
- package/lib/node/FsPromises.d.ts +0 -91
- package/lib/node/FsPromises.js +0 -161
- package/lib/node/FsPromises.js.map +0 -1
- package/lib/node/StatFs.d.ts +0 -19
- package/lib/node/StatFs.js +0 -34
- package/lib/node/StatFs.js.map +0 -1
- package/lib/node/Stats.d.ts +0 -41
- package/lib/node/Stats.js +0 -72
- package/lib/node/Stats.js.map +0 -1
- package/lib/node/constants.d.ts +0 -41
- package/lib/node/constants.js +0 -57
- package/lib/node/constants.js.map +0 -1
- package/lib/node/glob.d.ts +0 -5
- package/lib/node/glob.js +0 -94
- package/lib/node/glob.js.map +0 -1
- package/lib/node/lists/fsCallbackApiList.d.ts +0 -2
- package/lib/node/lists/fsCallbackApiList.js +0 -55
- package/lib/node/lists/fsCallbackApiList.js.map +0 -1
- package/lib/node/lists/fsCommonObjectsList.d.ts +0 -2
- package/lib/node/lists/fsCommonObjectsList.js +0 -19
- package/lib/node/lists/fsCommonObjectsList.js.map +0 -1
- package/lib/node/lists/fsSynchronousApiList.d.ts +0 -2
- package/lib/node/lists/fsSynchronousApiList.js +0 -49
- package/lib/node/lists/fsSynchronousApiList.js.map +0 -1
- package/lib/node/options.d.ts +0 -27
- package/lib/node/options.js +0 -112
- package/lib/node/options.js.map +0 -1
- package/lib/node/types/FsCallbackApi.d.ts +0 -143
- package/lib/node/types/FsCallbackApi.js +0 -3
- package/lib/node/types/FsCallbackApi.js.map +0 -1
- package/lib/node/types/FsCommonObjects.d.ts +0 -17
- package/lib/node/types/FsCommonObjects.js +0 -3
- package/lib/node/types/FsCommonObjects.js.map +0 -1
- package/lib/node/types/FsPromisesApi.d.ts +0 -41
- package/lib/node/types/FsPromisesApi.js +0 -3
- package/lib/node/types/FsPromisesApi.js.map +0 -1
- package/lib/node/types/FsSynchronousApi.d.ts +0 -114
- package/lib/node/types/FsSynchronousApi.js +0 -3
- package/lib/node/types/FsSynchronousApi.js.map +0 -1
- package/lib/node/types/index.d.ts +0 -7
- package/lib/node/types/index.js +0 -3
- package/lib/node/types/index.js.map +0 -1
- package/lib/node/types/misc.d.ts +0 -157
- package/lib/node/types/misc.js +0 -3
- package/lib/node/types/misc.js.map +0 -1
- package/lib/node/types/options.d.ts +0 -191
- package/lib/node/types/options.js +0 -3
- package/lib/node/types/options.js.map +0 -1
- package/lib/node/util.d.ts +0 -21
- package/lib/node/util.js +0 -297
- package/lib/node/util.js.map +0 -1
- package/lib/node/volume.d.ts +0 -395
- package/lib/node/volume.js +0 -1641
- package/lib/node/volume.js.map +0 -1
- package/lib/node-to-fsa/NodeFileSystemDirectoryHandle.d.ts +0 -72
- package/lib/node-to-fsa/NodeFileSystemDirectoryHandle.js +0 -217
- package/lib/node-to-fsa/NodeFileSystemDirectoryHandle.js.map +0 -1
- package/lib/node-to-fsa/NodeFileSystemFileHandle.d.ts +0 -28
- package/lib/node-to-fsa/NodeFileSystemFileHandle.js +0 -70
- package/lib/node-to-fsa/NodeFileSystemFileHandle.js.map +0 -1
- package/lib/node-to-fsa/NodeFileSystemHandle.d.ts +0 -37
- package/lib/node-to-fsa/NodeFileSystemHandle.js +0 -68
- package/lib/node-to-fsa/NodeFileSystemHandle.js.map +0 -1
- package/lib/node-to-fsa/NodeFileSystemSyncAccessHandle.d.ts +0 -42
- package/lib/node-to-fsa/NodeFileSystemSyncAccessHandle.js +0 -97
- package/lib/node-to-fsa/NodeFileSystemSyncAccessHandle.js.map +0 -1
- package/lib/node-to-fsa/NodeFileSystemWritableFileStream.d.ts +0 -56
- package/lib/node-to-fsa/NodeFileSystemWritableFileStream.js +0 -191
- package/lib/node-to-fsa/NodeFileSystemWritableFileStream.js.map +0 -1
- package/lib/node-to-fsa/NodePermissionStatus.d.ts +0 -8
- package/lib/node-to-fsa/NodePermissionStatus.js +0 -14
- package/lib/node-to-fsa/NodePermissionStatus.js.map +0 -1
- package/lib/node-to-fsa/types.d.ts +0 -18
- package/lib/node-to-fsa/types.js +0 -3
- package/lib/node-to-fsa/types.js.map +0 -1
- package/lib/node-to-fsa/util.d.ts +0 -12
- package/lib/node-to-fsa/util.js +0 -45
- package/lib/node-to-fsa/util.js.map +0 -1
- package/lib/node.d.ts +0 -3
- package/lib/node.js +0 -10
- package/lib/node.js.map +0 -1
- package/lib/print/index.d.ts +0 -9
- package/lib/print/index.js +0 -49
- package/lib/print/index.js.map +0 -1
- package/lib/process.d.ts +0 -11
- package/lib/process.js +0 -40
- package/lib/process.js.map +0 -1
- package/lib/queueMicrotask.d.ts +0 -2
- package/lib/queueMicrotask.js +0 -6
- package/lib/queueMicrotask.js.map +0 -1
- package/lib/snapshot/async.d.ts +0 -3
- package/lib/snapshot/async.js +0 -59
- package/lib/snapshot/async.js.map +0 -1
- package/lib/snapshot/binary.d.ts +0 -6
- package/lib/snapshot/binary.js +0 -31
- package/lib/snapshot/binary.js.map +0 -1
- package/lib/snapshot/constants.d.ts +0 -5
- package/lib/snapshot/constants.js +0 -3
- package/lib/snapshot/constants.js.map +0 -1
- package/lib/snapshot/index.d.ts +0 -5
- package/lib/snapshot/index.js +0 -8
- package/lib/snapshot/index.js.map +0 -1
- package/lib/snapshot/json.d.ts +0 -10
- package/lib/snapshot/json.js +0 -31
- package/lib/snapshot/json.js.map +0 -1
- package/lib/snapshot/shared.d.ts +0 -2
- package/lib/snapshot/shared.js +0 -6
- package/lib/snapshot/shared.js.map +0 -1
- package/lib/snapshot/sync.d.ts +0 -3
- package/lib/snapshot/sync.js +0 -59
- package/lib/snapshot/sync.js.map +0 -1
- package/lib/snapshot/types.d.ts +0 -30
- package/lib/snapshot/types.js +0 -3
- package/lib/snapshot/types.js.map +0 -1
- package/lib/vendor/node/buffer.d.ts +0 -1
- package/lib/vendor/node/buffer.js +0 -6
- package/lib/vendor/node/buffer.js.map +0 -1
- package/lib/vendor/node/events.d.ts +0 -1
- package/lib/vendor/node/events.js +0 -6
- package/lib/vendor/node/events.js.map +0 -1
- package/lib/vendor/node/fs.d.ts +0 -6
- package/lib/vendor/node/fs.js +0 -4
- package/lib/vendor/node/fs.js.map +0 -1
- package/lib/vendor/node/internal/buffer.d.ts +0 -9
- package/lib/vendor/node/internal/buffer.js +0 -13
- package/lib/vendor/node/internal/buffer.js.map +0 -1
- package/lib/vendor/node/internal/errors.d.ts +0 -31
- package/lib/vendor/node/internal/errors.js +0 -77
- package/lib/vendor/node/internal/errors.js.map +0 -1
- package/lib/vendor/node/path.d.ts +0 -1
- package/lib/vendor/node/path.js +0 -14
- package/lib/vendor/node/path.js.map +0 -1
- package/lib/vendor/node/stream.d.ts +0 -1
- package/lib/vendor/node/stream.js +0 -7
- package/lib/vendor/node/stream.js.map +0 -1
- package/lib/vendor/node/url.d.ts +0 -1
- package/lib/vendor/node/url.js +0 -6
- package/lib/vendor/node/url.js.map +0 -1
- package/lib/vendor/node/util.d.ts +0 -20
- package/lib/vendor/node/util.js +0 -112
- package/lib/vendor/node/util.js.map +0 -1
- package/src/node-to-fsa/README.md +0 -5
package/lib/core/Superblock.js
DELETED
|
@@ -1,689 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Superblock = void 0;
|
|
4
|
-
const path_1 = require("../vendor/node/path");
|
|
5
|
-
const Node_1 = require("./Node");
|
|
6
|
-
const Link_1 = require("./Link");
|
|
7
|
-
const File_1 = require("./File");
|
|
8
|
-
const buffer_1 = require("../vendor/node/internal/buffer");
|
|
9
|
-
const process_1 = require("../process");
|
|
10
|
-
const constants_1 = require("../constants");
|
|
11
|
-
const constants_2 = require("../node/constants");
|
|
12
|
-
const util_1 = require("../node/util");
|
|
13
|
-
const util_2 = require("./util");
|
|
14
|
-
const json_1 = require("./json");
|
|
15
|
-
const result_1 = require("./result");
|
|
16
|
-
const pathSep = path_1.posix ? path_1.posix.sep : path_1.sep;
|
|
17
|
-
const pathRelative = path_1.posix ? path_1.posix.relative : path_1.relative;
|
|
18
|
-
const pathJoin = path_1.posix ? path_1.posix.join : path_1.join;
|
|
19
|
-
const { O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_TRUNC, O_APPEND, O_DIRECTORY } = constants_1.constants;
|
|
20
|
-
/**
|
|
21
|
-
* Represents a filesystem superblock, which is the root of a virtual
|
|
22
|
-
* filesystem in Linux.
|
|
23
|
-
* @see https://lxr.linux.no/linux+v3.11.2/include/linux/fs.h#L1242
|
|
24
|
-
*/
|
|
25
|
-
class Superblock {
|
|
26
|
-
static fromJSON(json, cwd) {
|
|
27
|
-
const vol = new Superblock();
|
|
28
|
-
vol.fromJSON(json, cwd);
|
|
29
|
-
return vol;
|
|
30
|
-
}
|
|
31
|
-
static fromNestedJSON(json, cwd) {
|
|
32
|
-
const vol = new Superblock();
|
|
33
|
-
vol.fromNestedJSON(json, cwd);
|
|
34
|
-
return vol;
|
|
35
|
-
}
|
|
36
|
-
constructor(props = {}) {
|
|
37
|
-
// I-node number counter.
|
|
38
|
-
this.ino = 0;
|
|
39
|
-
// A mapping for i-node numbers to i-nodes (`Node`);
|
|
40
|
-
this.inodes = {};
|
|
41
|
-
// List of released i-node numbers, for reuse.
|
|
42
|
-
this.releasedInos = [];
|
|
43
|
-
// A mapping for file descriptors to `File`s.
|
|
44
|
-
this.fds = {};
|
|
45
|
-
// A list of reusable (opened and closed) file descriptors, that should be
|
|
46
|
-
// used first before creating a new file descriptor.
|
|
47
|
-
this.releasedFds = [];
|
|
48
|
-
// Max number of open files.
|
|
49
|
-
this.maxFiles = 10000;
|
|
50
|
-
// Current number of open files.
|
|
51
|
-
this.openFiles = 0;
|
|
52
|
-
this.open = (filename, flagsNum, modeNum, resolveSymlinks = true) => {
|
|
53
|
-
const file = this.openFile(filename, flagsNum, modeNum, resolveSymlinks);
|
|
54
|
-
if (!file)
|
|
55
|
-
throw (0, util_1.createError)("ENOENT" /* ERROR_CODE.ENOENT */, 'open', filename);
|
|
56
|
-
return file.fd;
|
|
57
|
-
};
|
|
58
|
-
this.writeFile = (id, buf, flagsNum, modeNum) => {
|
|
59
|
-
const isUserFd = typeof id === 'number';
|
|
60
|
-
let fd;
|
|
61
|
-
if (isUserFd)
|
|
62
|
-
fd = id;
|
|
63
|
-
else
|
|
64
|
-
fd = this.open((0, util_1.pathToFilename)(id), flagsNum, modeNum);
|
|
65
|
-
let offset = 0;
|
|
66
|
-
let length = buf.length;
|
|
67
|
-
let position = flagsNum & O_APPEND ? undefined : 0;
|
|
68
|
-
try {
|
|
69
|
-
while (length > 0) {
|
|
70
|
-
const written = this.write(fd, buf, offset, length, position);
|
|
71
|
-
offset += written;
|
|
72
|
-
length -= written;
|
|
73
|
-
if (position !== undefined)
|
|
74
|
-
position += written;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
finally {
|
|
78
|
-
if (!isUserFd)
|
|
79
|
-
this.close(fd);
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
this.read = (fd, buffer, offset, length, position) => {
|
|
83
|
-
if (buffer.byteLength < length) {
|
|
84
|
-
throw (0, util_1.createError)("ERR_OUT_OF_RANGE" /* ERROR_CODE.ERR_OUT_OF_RANGE */, 'read', undefined, undefined, RangeError);
|
|
85
|
-
}
|
|
86
|
-
const file = this.getFileByFdOrThrow(fd);
|
|
87
|
-
if (file.node.isSymlink()) {
|
|
88
|
-
throw (0, util_1.createError)("EPERM" /* ERROR_CODE.EPERM */, 'read', file.link.getPath());
|
|
89
|
-
}
|
|
90
|
-
return file.read(buffer, Number(offset), Number(length), position === -1 || typeof position !== 'number' ? undefined : position);
|
|
91
|
-
};
|
|
92
|
-
this.readv = (fd, buffers, position) => {
|
|
93
|
-
const file = this.getFileByFdOrThrow(fd);
|
|
94
|
-
let p = position ?? undefined;
|
|
95
|
-
if (p === -1)
|
|
96
|
-
p = undefined;
|
|
97
|
-
let bytesRead = 0;
|
|
98
|
-
for (const buffer of buffers) {
|
|
99
|
-
const bytes = file.read(buffer, 0, buffer.byteLength, p);
|
|
100
|
-
p = undefined;
|
|
101
|
-
bytesRead += bytes;
|
|
102
|
-
if (bytes < buffer.byteLength)
|
|
103
|
-
break;
|
|
104
|
-
}
|
|
105
|
-
return bytesRead;
|
|
106
|
-
};
|
|
107
|
-
this.link = (filename1, filename2) => {
|
|
108
|
-
let link1;
|
|
109
|
-
try {
|
|
110
|
-
link1 = this.getLinkOrThrow(filename1, 'link');
|
|
111
|
-
}
|
|
112
|
-
catch (err) {
|
|
113
|
-
if (err.code)
|
|
114
|
-
err = (0, util_1.createError)(err.code, 'link', filename1, filename2);
|
|
115
|
-
throw err;
|
|
116
|
-
}
|
|
117
|
-
const dirname2 = (0, path_1.dirname)(filename2);
|
|
118
|
-
let dir2;
|
|
119
|
-
try {
|
|
120
|
-
dir2 = this.getLinkOrThrow(dirname2, 'link');
|
|
121
|
-
}
|
|
122
|
-
catch (err) {
|
|
123
|
-
// Augment error with filename1
|
|
124
|
-
if (err.code)
|
|
125
|
-
err = (0, util_1.createError)(err.code, 'link', filename1, filename2);
|
|
126
|
-
throw err;
|
|
127
|
-
}
|
|
128
|
-
const name = (0, path_1.basename)(filename2);
|
|
129
|
-
if (dir2.getChild(name))
|
|
130
|
-
throw (0, util_1.createError)("EEXIST" /* ERROR_CODE.EEXIST */, 'link', filename1, filename2);
|
|
131
|
-
const node = link1.getNode();
|
|
132
|
-
node.nlink++;
|
|
133
|
-
dir2.createChild(name, node);
|
|
134
|
-
};
|
|
135
|
-
this.unlink = (filename) => {
|
|
136
|
-
const link = this.getLinkOrThrow(filename, 'unlink');
|
|
137
|
-
// TODO: Check if it is file, dir, other...
|
|
138
|
-
if (link.length)
|
|
139
|
-
throw Error('Dir not empty...');
|
|
140
|
-
this.deleteLink(link);
|
|
141
|
-
const node = link.getNode();
|
|
142
|
-
node.nlink--;
|
|
143
|
-
// When all hard links to i-node are deleted, remove the i-node, too.
|
|
144
|
-
if (node.nlink <= 0) {
|
|
145
|
-
this.deleteNode(node);
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
this.symlink = (targetFilename, pathFilename) => {
|
|
149
|
-
const pathSteps = (0, util_2.filenameToSteps)(pathFilename);
|
|
150
|
-
// Check if directory exists, where we about to create a symlink.
|
|
151
|
-
let dirLink;
|
|
152
|
-
try {
|
|
153
|
-
dirLink = this.getLinkParentAsDirOrThrow(pathSteps);
|
|
154
|
-
}
|
|
155
|
-
catch (err) {
|
|
156
|
-
// Catch error to populate with the correct fields - getLinkParentAsDirOrThrow won't be aware of the second path
|
|
157
|
-
if (err.code)
|
|
158
|
-
err = (0, util_1.createError)(err.code, 'symlink', targetFilename, pathFilename);
|
|
159
|
-
throw err;
|
|
160
|
-
}
|
|
161
|
-
const name = pathSteps[pathSteps.length - 1];
|
|
162
|
-
// Check if new file already exists.
|
|
163
|
-
if (dirLink.getChild(name))
|
|
164
|
-
throw (0, util_1.createError)("EEXIST" /* ERROR_CODE.EEXIST */, 'symlink', targetFilename, pathFilename);
|
|
165
|
-
// Check permissions on the path where we are creating the symlink.
|
|
166
|
-
// Note we're not checking permissions on the target path: It is not an error to create a symlink to a
|
|
167
|
-
// non-existent or inaccessible target
|
|
168
|
-
const node = dirLink.getNode();
|
|
169
|
-
if (!node.canExecute() || !node.canWrite())
|
|
170
|
-
throw (0, util_1.createError)("EACCES" /* ERROR_CODE.EACCES */, 'symlink', targetFilename, pathFilename);
|
|
171
|
-
// Create symlink.
|
|
172
|
-
const symlink = dirLink.createChild(name);
|
|
173
|
-
symlink.getNode().makeSymlink(targetFilename);
|
|
174
|
-
return symlink;
|
|
175
|
-
};
|
|
176
|
-
this.rename = (oldPathFilename, newPathFilename) => {
|
|
177
|
-
let link;
|
|
178
|
-
try {
|
|
179
|
-
link = this.getResolvedLinkOrThrow(oldPathFilename);
|
|
180
|
-
}
|
|
181
|
-
catch (err) {
|
|
182
|
-
// Augment err with newPathFilename
|
|
183
|
-
if (err.code)
|
|
184
|
-
err = (0, util_1.createError)(err.code, 'rename', oldPathFilename, newPathFilename);
|
|
185
|
-
throw err;
|
|
186
|
-
}
|
|
187
|
-
// TODO: Check if it is directory, if non-empty, we cannot move it, right?
|
|
188
|
-
// Check directory exists for the new location.
|
|
189
|
-
let newPathDirLink;
|
|
190
|
-
try {
|
|
191
|
-
newPathDirLink = this.getLinkParentAsDirOrThrow(newPathFilename);
|
|
192
|
-
}
|
|
193
|
-
catch (err) {
|
|
194
|
-
// Augment error with oldPathFilename
|
|
195
|
-
if (err.code)
|
|
196
|
-
err = (0, util_1.createError)(err.code, 'rename', oldPathFilename, newPathFilename);
|
|
197
|
-
throw err;
|
|
198
|
-
}
|
|
199
|
-
// TODO: Also treat cases with directories and symbolic links.
|
|
200
|
-
// TODO: See: http://man7.org/linux/man-pages/man2/rename.2.html
|
|
201
|
-
// Remove hard link from old folder.
|
|
202
|
-
const oldLinkParent = link.parent;
|
|
203
|
-
if (!oldLinkParent)
|
|
204
|
-
throw (0, util_1.createError)("EINVAL" /* ERROR_CODE.EINVAL */, 'rename', oldPathFilename, newPathFilename);
|
|
205
|
-
// Check we have access and write permissions in both places
|
|
206
|
-
const oldParentNode = oldLinkParent.getNode();
|
|
207
|
-
const newPathDirNode = newPathDirLink.getNode();
|
|
208
|
-
if (!oldParentNode.canExecute() ||
|
|
209
|
-
!oldParentNode.canWrite() ||
|
|
210
|
-
!newPathDirNode.canExecute() ||
|
|
211
|
-
!newPathDirNode.canWrite()) {
|
|
212
|
-
throw (0, util_1.createError)("EACCES" /* ERROR_CODE.EACCES */, 'rename', oldPathFilename, newPathFilename);
|
|
213
|
-
}
|
|
214
|
-
oldLinkParent.deleteChild(link);
|
|
215
|
-
// Rename should overwrite the new path, if that exists.
|
|
216
|
-
const name = (0, path_1.basename)(newPathFilename);
|
|
217
|
-
link.name = name;
|
|
218
|
-
link.steps = [...newPathDirLink.steps, name];
|
|
219
|
-
newPathDirLink.setChild(link.getName(), link);
|
|
220
|
-
};
|
|
221
|
-
this.mkdir = (filename, modeNum) => {
|
|
222
|
-
const steps = (0, util_2.filenameToSteps)(filename);
|
|
223
|
-
// This will throw if user tries to create root dir `fs.mkdirSync('/')`.
|
|
224
|
-
if (!steps.length)
|
|
225
|
-
throw (0, util_1.createError)("EEXIST" /* ERROR_CODE.EEXIST */, 'mkdir', filename);
|
|
226
|
-
const dir = this.getLinkParentAsDirOrThrow(filename, 'mkdir');
|
|
227
|
-
// Check path already exists.
|
|
228
|
-
const name = steps[steps.length - 1];
|
|
229
|
-
if (dir.getChild(name))
|
|
230
|
-
throw (0, util_1.createError)("EEXIST" /* ERROR_CODE.EEXIST */, 'mkdir', filename);
|
|
231
|
-
const node = dir.getNode();
|
|
232
|
-
if (!node.canWrite() || !node.canExecute())
|
|
233
|
-
throw (0, util_1.createError)("EACCES" /* ERROR_CODE.EACCES */, 'mkdir', filename);
|
|
234
|
-
dir.createChild(name, this.createNode(constants_1.constants.S_IFDIR | modeNum));
|
|
235
|
-
};
|
|
236
|
-
/**
|
|
237
|
-
* Creates directory tree recursively.
|
|
238
|
-
*/
|
|
239
|
-
this.mkdirp = (filename, modeNum) => {
|
|
240
|
-
let created = false;
|
|
241
|
-
const steps = (0, util_2.filenameToSteps)(filename);
|
|
242
|
-
let curr = null;
|
|
243
|
-
let i = steps.length;
|
|
244
|
-
// Find the longest subpath of filename that still exists:
|
|
245
|
-
for (i = steps.length; i >= 0; i--) {
|
|
246
|
-
curr = this.getResolvedLink(steps.slice(0, i));
|
|
247
|
-
if (curr)
|
|
248
|
-
break;
|
|
249
|
-
}
|
|
250
|
-
if (!curr) {
|
|
251
|
-
curr = this.root;
|
|
252
|
-
i = 0;
|
|
253
|
-
}
|
|
254
|
-
// curr is now the last directory that still exists.
|
|
255
|
-
// (If none of them existed, curr is the root.)
|
|
256
|
-
// Check access the lazy way:
|
|
257
|
-
curr = this.getResolvedLinkOrThrow(path_1.sep + steps.slice(0, i).join(path_1.sep), 'mkdir');
|
|
258
|
-
// Start creating directories:
|
|
259
|
-
for (i; i < steps.length; i++) {
|
|
260
|
-
const node = curr.getNode();
|
|
261
|
-
if (node.isDirectory()) {
|
|
262
|
-
// Check we have permissions
|
|
263
|
-
if (!node.canExecute() || !node.canWrite())
|
|
264
|
-
throw (0, util_1.createError)("EACCES" /* ERROR_CODE.EACCES */, 'mkdir', filename);
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
throw (0, util_1.createError)("ENOTDIR" /* ERROR_CODE.ENOTDIR */, 'mkdir', filename);
|
|
268
|
-
}
|
|
269
|
-
created = true;
|
|
270
|
-
curr = curr.createChild(steps[i], this.createNode(constants_1.constants.S_IFDIR | modeNum));
|
|
271
|
-
}
|
|
272
|
-
return created ? filename : undefined;
|
|
273
|
-
};
|
|
274
|
-
this.rmdir = (filename, recursive = false) => {
|
|
275
|
-
const link = this.getLinkAsDirOrThrow(filename, 'rmdir');
|
|
276
|
-
if (link.length && !recursive)
|
|
277
|
-
throw (0, util_1.createError)("ENOTEMPTY" /* ERROR_CODE.ENOTEMPTY */, 'rmdir', filename);
|
|
278
|
-
this.deleteLink(link);
|
|
279
|
-
};
|
|
280
|
-
this.rm = (filename, force = false, recursive = false) => {
|
|
281
|
-
// "stat" is used to match Node's native error message.
|
|
282
|
-
let link;
|
|
283
|
-
try {
|
|
284
|
-
link = this.getResolvedLinkOrThrow(filename, 'stat');
|
|
285
|
-
}
|
|
286
|
-
catch (err) {
|
|
287
|
-
// Silently ignore missing paths if force option is true
|
|
288
|
-
if (err.code === "ENOENT" /* ERROR_CODE.ENOENT */ && force)
|
|
289
|
-
return;
|
|
290
|
-
else
|
|
291
|
-
throw err;
|
|
292
|
-
}
|
|
293
|
-
if (link.getNode().isDirectory() && !recursive)
|
|
294
|
-
throw (0, util_1.createError)("ERR_FS_EISDIR" /* ERROR_CODE.ERR_FS_EISDIR */, 'rm', filename);
|
|
295
|
-
if (!link.parent?.getNode().canWrite())
|
|
296
|
-
throw (0, util_1.createError)("EACCES" /* ERROR_CODE.EACCES */, 'rm', filename);
|
|
297
|
-
this.deleteLink(link);
|
|
298
|
-
};
|
|
299
|
-
this.close = (fd) => {
|
|
300
|
-
(0, util_2.validateFd)(fd);
|
|
301
|
-
const file = this.getFileByFdOrThrow(fd, 'close');
|
|
302
|
-
this.closeFile(file);
|
|
303
|
-
};
|
|
304
|
-
const root = this.createLink();
|
|
305
|
-
root.setNode(this.createNode(constants_1.constants.S_IFDIR | 0o777));
|
|
306
|
-
root.setChild('.', root);
|
|
307
|
-
root.getNode().nlink++;
|
|
308
|
-
root.setChild('..', root);
|
|
309
|
-
root.getNode().nlink++;
|
|
310
|
-
this.root = root;
|
|
311
|
-
}
|
|
312
|
-
createLink(parent, name, isDirectory = false, mode) {
|
|
313
|
-
if (!parent) {
|
|
314
|
-
return new Link_1.Link(this, void 0, '');
|
|
315
|
-
}
|
|
316
|
-
if (!name) {
|
|
317
|
-
throw new Error('createLink: name cannot be empty');
|
|
318
|
-
}
|
|
319
|
-
// If no explicit permission is provided, use defaults based on type
|
|
320
|
-
const finalPerm = mode ?? (isDirectory ? 0o777 : 0o666);
|
|
321
|
-
// To prevent making a breaking change, `mode` can also just be a permission number
|
|
322
|
-
// and the file type is set based on `isDirectory`
|
|
323
|
-
const hasFileType = mode && mode & constants_1.constants.S_IFMT;
|
|
324
|
-
const modeType = hasFileType ? mode & constants_1.constants.S_IFMT : isDirectory ? constants_1.constants.S_IFDIR : constants_1.constants.S_IFREG;
|
|
325
|
-
const finalMode = (finalPerm & ~constants_1.constants.S_IFMT) | modeType;
|
|
326
|
-
return parent.createChild(name, this.createNode(finalMode));
|
|
327
|
-
}
|
|
328
|
-
deleteLink(link) {
|
|
329
|
-
const parent = link.parent;
|
|
330
|
-
if (parent) {
|
|
331
|
-
parent.deleteChild(link);
|
|
332
|
-
return true;
|
|
333
|
-
}
|
|
334
|
-
return false;
|
|
335
|
-
}
|
|
336
|
-
newInoNumber() {
|
|
337
|
-
const releasedFd = this.releasedInos.pop();
|
|
338
|
-
if (releasedFd)
|
|
339
|
-
return releasedFd;
|
|
340
|
-
else {
|
|
341
|
-
this.ino = (this.ino + 1) % 0xffffffff;
|
|
342
|
-
return this.ino;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
newFdNumber() {
|
|
346
|
-
const releasedFd = this.releasedFds.pop();
|
|
347
|
-
return typeof releasedFd === 'number' ? releasedFd : Superblock.fd--;
|
|
348
|
-
}
|
|
349
|
-
createNode(mode) {
|
|
350
|
-
const node = new Node_1.Node(this.newInoNumber(), mode);
|
|
351
|
-
this.inodes[node.ino] = node;
|
|
352
|
-
return node;
|
|
353
|
-
}
|
|
354
|
-
deleteNode(node) {
|
|
355
|
-
node.del();
|
|
356
|
-
delete this.inodes[node.ino];
|
|
357
|
-
this.releasedInos.push(node.ino);
|
|
358
|
-
}
|
|
359
|
-
walk(stepsOrFilenameOrLink, resolveSymlinks = false, checkExistence = false, checkAccess = false, funcName) {
|
|
360
|
-
let steps;
|
|
361
|
-
let filename;
|
|
362
|
-
if (stepsOrFilenameOrLink instanceof Link_1.Link) {
|
|
363
|
-
steps = stepsOrFilenameOrLink.steps;
|
|
364
|
-
filename = pathSep + steps.join(pathSep);
|
|
365
|
-
}
|
|
366
|
-
else if (typeof stepsOrFilenameOrLink === 'string') {
|
|
367
|
-
steps = (0, util_2.filenameToSteps)(stepsOrFilenameOrLink);
|
|
368
|
-
filename = stepsOrFilenameOrLink;
|
|
369
|
-
}
|
|
370
|
-
else {
|
|
371
|
-
steps = stepsOrFilenameOrLink;
|
|
372
|
-
filename = pathSep + steps.join(pathSep);
|
|
373
|
-
}
|
|
374
|
-
let curr = this.root;
|
|
375
|
-
let i = 0;
|
|
376
|
-
while (i < steps.length) {
|
|
377
|
-
let node = curr.getNode();
|
|
378
|
-
// Check access permissions if current link is a directory
|
|
379
|
-
if (node.isDirectory()) {
|
|
380
|
-
if (checkAccess && !node.canExecute()) {
|
|
381
|
-
return (0, result_1.Err)((0, util_1.createStatError)("EACCES" /* ERROR_CODE.EACCES */, funcName, filename));
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
else {
|
|
385
|
-
if (i < steps.length - 1) {
|
|
386
|
-
return (0, result_1.Err)((0, util_1.createStatError)("ENOTDIR" /* ERROR_CODE.ENOTDIR */, funcName, filename));
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
curr = curr.getChild(steps[i]) ?? null;
|
|
390
|
-
// Check existence of current link
|
|
391
|
-
if (!curr)
|
|
392
|
-
if (checkExistence) {
|
|
393
|
-
return (0, result_1.Err)((0, util_1.createStatError)("ENOENT" /* ERROR_CODE.ENOENT */, funcName, filename));
|
|
394
|
-
}
|
|
395
|
-
else {
|
|
396
|
-
return (0, result_1.Ok)(null);
|
|
397
|
-
}
|
|
398
|
-
node = curr?.getNode();
|
|
399
|
-
// Resolve symlink if we're resolving all symlinks OR if this is an intermediate path component
|
|
400
|
-
// This allows lstat to traverse through symlinks in intermediate directories while not resolving the final component
|
|
401
|
-
if (node.isSymlink() && (resolveSymlinks || i < steps.length - 1)) {
|
|
402
|
-
const resolvedPath = (0, path_1.isAbsolute)(node.symlink) ? node.symlink : pathJoin((0, path_1.dirname)(curr.getPath()), node.symlink); // Relative to symlink's parent
|
|
403
|
-
steps = (0, util_2.filenameToSteps)(resolvedPath).concat(steps.slice(i + 1));
|
|
404
|
-
curr = this.root;
|
|
405
|
-
i = 0;
|
|
406
|
-
continue;
|
|
407
|
-
}
|
|
408
|
-
// After resolving symlinks, check if it's not a directory and we still have more steps
|
|
409
|
-
// This handles the case where we try to traverse through a file
|
|
410
|
-
// Only do this check when we're doing filesystem operations (checkExistence = true)
|
|
411
|
-
if (checkExistence && !node.isDirectory() && i < steps.length - 1) {
|
|
412
|
-
// On Windows, use ENOENT for consistency with Node.js behavior
|
|
413
|
-
// On other platforms, use ENOTDIR which is more semantically correct
|
|
414
|
-
const errorCode = process_1.default.platform === 'win32' ? "ENOENT" /* ERROR_CODE.ENOENT */ : "ENOTDIR" /* ERROR_CODE.ENOTDIR */;
|
|
415
|
-
return (0, result_1.Err)((0, util_1.createStatError)(errorCode, funcName, filename));
|
|
416
|
-
}
|
|
417
|
-
i++;
|
|
418
|
-
}
|
|
419
|
-
return (0, result_1.Ok)(curr);
|
|
420
|
-
}
|
|
421
|
-
// Returns a `Link` (hard link) referenced by path "split" into steps.
|
|
422
|
-
getLink(steps) {
|
|
423
|
-
const result = this.walk(steps, false, false, false);
|
|
424
|
-
if (result.ok) {
|
|
425
|
-
return result.value;
|
|
426
|
-
}
|
|
427
|
-
throw result.err.toError();
|
|
428
|
-
}
|
|
429
|
-
// Just link `getLink`, but throws a correct user error, if link to found.
|
|
430
|
-
getLinkOrThrow(filename, funcName) {
|
|
431
|
-
const result = this.walk(filename, false, true, true, funcName);
|
|
432
|
-
if (result.ok) {
|
|
433
|
-
return result.value;
|
|
434
|
-
}
|
|
435
|
-
throw result.err.toError();
|
|
436
|
-
}
|
|
437
|
-
// Just like `getLink`, but also dereference/resolves symbolic links.
|
|
438
|
-
getResolvedLink(filenameOrSteps) {
|
|
439
|
-
const result = this.walk(filenameOrSteps, true, false, false);
|
|
440
|
-
if (result.ok) {
|
|
441
|
-
return result.value;
|
|
442
|
-
}
|
|
443
|
-
throw result.err.toError();
|
|
444
|
-
}
|
|
445
|
-
/**
|
|
446
|
-
* Just like `getLinkOrThrow`, but also dereference/resolves symbolic links.
|
|
447
|
-
*/
|
|
448
|
-
getResolvedLinkOrThrow(filename, funcName) {
|
|
449
|
-
const result = this.walk(filename, true, true, true, funcName);
|
|
450
|
-
if (result.ok) {
|
|
451
|
-
return result.value;
|
|
452
|
-
}
|
|
453
|
-
throw result.err.toError();
|
|
454
|
-
}
|
|
455
|
-
getResolvedLinkResult(filename, funcName) {
|
|
456
|
-
const result = this.walk(filename, true, true, true, funcName);
|
|
457
|
-
if (result.ok) {
|
|
458
|
-
return (0, result_1.Ok)(result.value);
|
|
459
|
-
}
|
|
460
|
-
return result;
|
|
461
|
-
}
|
|
462
|
-
resolveSymlinks(link) {
|
|
463
|
-
return this.getResolvedLink(link.steps.slice(1));
|
|
464
|
-
}
|
|
465
|
-
/**
|
|
466
|
-
* Just like `getLinkOrThrow`, but also verifies that the link is a directory.
|
|
467
|
-
*/
|
|
468
|
-
getLinkAsDirOrThrow(filename, funcName) {
|
|
469
|
-
const link = this.getLinkOrThrow(filename, funcName);
|
|
470
|
-
if (!link.getNode().isDirectory())
|
|
471
|
-
throw (0, util_1.createError)("ENOTDIR" /* ERROR_CODE.ENOTDIR */, funcName, filename);
|
|
472
|
-
return link;
|
|
473
|
-
}
|
|
474
|
-
// Get the immediate parent directory of the link.
|
|
475
|
-
getLinkParent(steps) {
|
|
476
|
-
return this.getLink(steps.slice(0, -1));
|
|
477
|
-
}
|
|
478
|
-
getLinkParentAsDirOrThrow(filenameOrSteps, funcName) {
|
|
479
|
-
const steps = (filenameOrSteps instanceof Array ? filenameOrSteps : (0, util_2.filenameToSteps)(filenameOrSteps)).slice(0, -1);
|
|
480
|
-
const filename = pathSep + steps.join(pathSep);
|
|
481
|
-
const link = this.getLinkOrThrow(filename, funcName);
|
|
482
|
-
if (!link.getNode().isDirectory())
|
|
483
|
-
throw (0, util_1.createError)("ENOTDIR" /* ERROR_CODE.ENOTDIR */, funcName, filename);
|
|
484
|
-
return link;
|
|
485
|
-
}
|
|
486
|
-
getFileByFd(fd) {
|
|
487
|
-
return this.fds[String(fd)];
|
|
488
|
-
}
|
|
489
|
-
getFileByFdOrThrow(fd, funcName) {
|
|
490
|
-
if (!(0, util_2.isFd)(fd))
|
|
491
|
-
throw TypeError(constants_2.ERRSTR.FD);
|
|
492
|
-
const file = this.getFileByFd(fd);
|
|
493
|
-
if (!file)
|
|
494
|
-
throw (0, util_1.createError)("EBADF" /* ERROR_CODE.EBADF */, funcName);
|
|
495
|
-
return file;
|
|
496
|
-
}
|
|
497
|
-
_toJSON(link = this.root, json = {}, path, asBuffer) {
|
|
498
|
-
let isEmpty = true;
|
|
499
|
-
let children = link.children;
|
|
500
|
-
if (link.getNode().isFile()) {
|
|
501
|
-
children = new Map([[link.getName(), link.parent.getChild(link.getName())]]);
|
|
502
|
-
link = link.parent;
|
|
503
|
-
}
|
|
504
|
-
for (const name of children.keys()) {
|
|
505
|
-
if (name === '.' || name === '..') {
|
|
506
|
-
continue;
|
|
507
|
-
}
|
|
508
|
-
isEmpty = false;
|
|
509
|
-
const child = link.getChild(name);
|
|
510
|
-
if (!child) {
|
|
511
|
-
throw new Error('_toJSON: unexpected undefined');
|
|
512
|
-
}
|
|
513
|
-
const node = child.getNode();
|
|
514
|
-
if (node.isFile()) {
|
|
515
|
-
let filename = child.getPath();
|
|
516
|
-
if (path)
|
|
517
|
-
filename = pathRelative(path, filename);
|
|
518
|
-
json[filename] = asBuffer ? node.getBuffer() : node.getString();
|
|
519
|
-
}
|
|
520
|
-
else if (node.isDirectory()) {
|
|
521
|
-
this._toJSON(child, json, path, asBuffer);
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
let dirPath = link.getPath();
|
|
525
|
-
if (path)
|
|
526
|
-
dirPath = pathRelative(path, dirPath);
|
|
527
|
-
if (dirPath && isEmpty) {
|
|
528
|
-
json[dirPath] = null;
|
|
529
|
-
}
|
|
530
|
-
return json;
|
|
531
|
-
}
|
|
532
|
-
toJSON(paths, json = {}, isRelative = false, asBuffer = false) {
|
|
533
|
-
const links = [];
|
|
534
|
-
if (paths) {
|
|
535
|
-
if (!Array.isArray(paths))
|
|
536
|
-
paths = [paths];
|
|
537
|
-
for (const path of paths) {
|
|
538
|
-
const filename = (0, util_1.pathToFilename)(path);
|
|
539
|
-
const link = this.getResolvedLink(filename);
|
|
540
|
-
if (!link)
|
|
541
|
-
continue;
|
|
542
|
-
links.push(link);
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
else {
|
|
546
|
-
links.push(this.root);
|
|
547
|
-
}
|
|
548
|
-
if (!links.length)
|
|
549
|
-
return json;
|
|
550
|
-
for (const link of links)
|
|
551
|
-
this._toJSON(link, json, isRelative ? link.getPath() : '', asBuffer);
|
|
552
|
-
return json;
|
|
553
|
-
}
|
|
554
|
-
// TODO: `cwd` should probably not invoke `process.cwd()`.
|
|
555
|
-
fromJSON(json, cwd = process_1.default.cwd()) {
|
|
556
|
-
for (let filename in json) {
|
|
557
|
-
const data = json[filename];
|
|
558
|
-
filename = (0, util_2.resolve)(filename, cwd);
|
|
559
|
-
if (typeof data === 'string' || data instanceof buffer_1.Buffer) {
|
|
560
|
-
const dir = (0, path_1.dirname)(filename);
|
|
561
|
-
this.mkdirp(dir, 511 /* MODE.DIR */);
|
|
562
|
-
const buffer = (0, util_2.dataToBuffer)(data);
|
|
563
|
-
this.writeFile(filename, buffer, constants_2.FLAGS.w, 438 /* MODE.DEFAULT */);
|
|
564
|
-
}
|
|
565
|
-
else {
|
|
566
|
-
this.mkdirp(filename, 511 /* MODE.DIR */);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
fromNestedJSON(json, cwd) {
|
|
571
|
-
this.fromJSON((0, json_1.flattenJSON)(json), cwd);
|
|
572
|
-
}
|
|
573
|
-
reset() {
|
|
574
|
-
this.ino = 0;
|
|
575
|
-
this.inodes = {};
|
|
576
|
-
this.releasedInos = [];
|
|
577
|
-
this.fds = {};
|
|
578
|
-
this.releasedFds = [];
|
|
579
|
-
this.openFiles = 0;
|
|
580
|
-
this.root = this.createLink();
|
|
581
|
-
this.root.setNode(this.createNode(constants_1.constants.S_IFDIR | 0o777));
|
|
582
|
-
}
|
|
583
|
-
// Legacy interface
|
|
584
|
-
mountSync(mountpoint, json) {
|
|
585
|
-
this.fromJSON(json, mountpoint);
|
|
586
|
-
}
|
|
587
|
-
openLink(link, flagsNum, resolveSymlinks = true) {
|
|
588
|
-
if (this.openFiles >= this.maxFiles) {
|
|
589
|
-
// Too many open files.
|
|
590
|
-
throw (0, util_1.createError)("EMFILE" /* ERROR_CODE.EMFILE */, 'open', link.getPath());
|
|
591
|
-
}
|
|
592
|
-
// Resolve symlinks.
|
|
593
|
-
//
|
|
594
|
-
// @TODO: This should be superfluous. This method is only ever called by openFile(), which does its own symlink resolution
|
|
595
|
-
// prior to calling.
|
|
596
|
-
let realLink = link;
|
|
597
|
-
if (resolveSymlinks)
|
|
598
|
-
realLink = this.getResolvedLinkOrThrow(link.getPath(), 'open');
|
|
599
|
-
const node = realLink.getNode();
|
|
600
|
-
// Check whether node is a directory
|
|
601
|
-
if (node.isDirectory()) {
|
|
602
|
-
if ((flagsNum & (O_RDONLY | O_RDWR | O_WRONLY)) !== O_RDONLY)
|
|
603
|
-
throw (0, util_1.createError)("EISDIR" /* ERROR_CODE.EISDIR */, 'open', link.getPath());
|
|
604
|
-
}
|
|
605
|
-
else {
|
|
606
|
-
if (flagsNum & O_DIRECTORY)
|
|
607
|
-
throw (0, util_1.createError)("ENOTDIR" /* ERROR_CODE.ENOTDIR */, 'open', link.getPath());
|
|
608
|
-
}
|
|
609
|
-
// Check node permissions
|
|
610
|
-
// For read access: check if flags are O_RDONLY or O_RDWR (i.e., not only O_WRONLY)
|
|
611
|
-
if ((flagsNum & (O_RDONLY | O_RDWR | O_WRONLY)) !== O_WRONLY) {
|
|
612
|
-
if (!node.canRead()) {
|
|
613
|
-
throw (0, util_1.createError)("EACCES" /* ERROR_CODE.EACCES */, 'open', link.getPath());
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
// For write access: check if flags are O_WRONLY or O_RDWR
|
|
617
|
-
if (flagsNum & (O_WRONLY | O_RDWR)) {
|
|
618
|
-
if (!node.canWrite()) {
|
|
619
|
-
throw (0, util_1.createError)("EACCES" /* ERROR_CODE.EACCES */, 'open', link.getPath());
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
const file = new File_1.File(link, node, flagsNum, this.newFdNumber());
|
|
623
|
-
this.fds[file.fd] = file;
|
|
624
|
-
this.openFiles++;
|
|
625
|
-
if (flagsNum & O_TRUNC)
|
|
626
|
-
file.truncate();
|
|
627
|
-
return file;
|
|
628
|
-
}
|
|
629
|
-
openFile(filename, flagsNum, modeNum, resolveSymlinks = true) {
|
|
630
|
-
const steps = (0, util_2.filenameToSteps)(filename);
|
|
631
|
-
let link;
|
|
632
|
-
try {
|
|
633
|
-
link = resolveSymlinks ? this.getResolvedLinkOrThrow(filename, 'open') : this.getLinkOrThrow(filename, 'open');
|
|
634
|
-
// Check if file already existed when trying to create it exclusively (O_CREAT and O_EXCL flags are set).
|
|
635
|
-
// This is an error, see https://pubs.opengroup.org/onlinepubs/009695399/functions/open.html:
|
|
636
|
-
// "If O_CREAT and O_EXCL are set, open() shall fail if the file exists."
|
|
637
|
-
if (link && flagsNum & O_CREAT && flagsNum & O_EXCL)
|
|
638
|
-
throw (0, util_1.createError)("EEXIST" /* ERROR_CODE.EEXIST */, 'open', filename);
|
|
639
|
-
}
|
|
640
|
-
catch (err) {
|
|
641
|
-
// Try creating a new file, if it does not exist and O_CREAT flag is set.
|
|
642
|
-
// Note that this will still throw if the ENOENT came from one of the
|
|
643
|
-
// intermediate directories instead of the file itself.
|
|
644
|
-
if (err.code === "ENOENT" /* ERROR_CODE.ENOENT */ && flagsNum & O_CREAT) {
|
|
645
|
-
const dirName = (0, path_1.dirname)(filename);
|
|
646
|
-
const dirLink = this.getResolvedLinkOrThrow(dirName);
|
|
647
|
-
const dirNode = dirLink.getNode();
|
|
648
|
-
// Check that the place we create the new file is actually a directory and that we are allowed to do so:
|
|
649
|
-
if (!dirNode.isDirectory())
|
|
650
|
-
throw (0, util_1.createError)("ENOTDIR" /* ERROR_CODE.ENOTDIR */, 'open', filename);
|
|
651
|
-
if (!dirNode.canExecute() || !dirNode.canWrite())
|
|
652
|
-
throw (0, util_1.createError)("EACCES" /* ERROR_CODE.EACCES */, 'open', filename);
|
|
653
|
-
// This is a difference to the original implementation, which would simply not create a file unless modeNum was specified.
|
|
654
|
-
// However, current Node versions will default to 0o666.
|
|
655
|
-
modeNum ?? (modeNum = 0o666);
|
|
656
|
-
link = this.createLink(dirLink, steps[steps.length - 1], false, modeNum);
|
|
657
|
-
}
|
|
658
|
-
else
|
|
659
|
-
throw err;
|
|
660
|
-
}
|
|
661
|
-
if (link)
|
|
662
|
-
return this.openLink(link, flagsNum, resolveSymlinks);
|
|
663
|
-
throw (0, util_1.createError)("ENOENT" /* ERROR_CODE.ENOENT */, 'open', filename);
|
|
664
|
-
}
|
|
665
|
-
closeFile(file) {
|
|
666
|
-
if (!this.fds[file.fd])
|
|
667
|
-
return;
|
|
668
|
-
this.openFiles--;
|
|
669
|
-
delete this.fds[file.fd];
|
|
670
|
-
this.releasedFds.push(file.fd);
|
|
671
|
-
}
|
|
672
|
-
write(fd, buf, offset, length, position) {
|
|
673
|
-
const file = this.getFileByFdOrThrow(fd, 'write');
|
|
674
|
-
if (file.node.isSymlink()) {
|
|
675
|
-
throw (0, util_1.createError)("EBADF" /* ERROR_CODE.EBADF */, 'write', file.link.getPath());
|
|
676
|
-
}
|
|
677
|
-
return file.write(buf, offset, length, position === -1 || typeof position !== 'number' ? undefined : position);
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
exports.Superblock = Superblock;
|
|
681
|
-
/**
|
|
682
|
-
* Global file descriptor counter. UNIX file descriptors start from 0 and go sequentially
|
|
683
|
-
* up, so here, in order not to conflict with them, we choose some big number and descrease
|
|
684
|
-
* the file descriptor of every new opened file.
|
|
685
|
-
* @type {number}
|
|
686
|
-
* @todo This should not be static, right?
|
|
687
|
-
*/
|
|
688
|
-
Superblock.fd = 0x7fffffff;
|
|
689
|
-
//# sourceMappingURL=Superblock.js.map
|