@zenfs/core 1.11.3 → 2.0.0

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.
Files changed (116) hide show
  1. package/dist/backends/backend.d.ts +19 -15
  2. package/dist/backends/backend.js +31 -15
  3. package/dist/backends/cow.d.ts +20 -30
  4. package/dist/backends/cow.js +52 -142
  5. package/dist/backends/fetch.d.ts +1 -0
  6. package/dist/backends/fetch.js +3 -1
  7. package/dist/backends/index.d.ts +1 -1
  8. package/dist/backends/index.js +1 -1
  9. package/dist/backends/memory.d.ts +5 -7
  10. package/dist/backends/memory.js +2 -3
  11. package/dist/backends/passthrough.d.ts +19 -22
  12. package/dist/backends/passthrough.js +85 -160
  13. package/dist/backends/port.d.ts +207 -0
  14. package/dist/backends/port.js +297 -0
  15. package/dist/backends/single_buffer.d.ts +11 -5
  16. package/dist/backends/single_buffer.js +18 -12
  17. package/dist/backends/store/fs.d.ts +11 -27
  18. package/dist/backends/store/fs.js +67 -91
  19. package/dist/backends/store/store.d.ts +7 -12
  20. package/dist/config.d.ts +1 -10
  21. package/dist/config.js +7 -8
  22. package/dist/context.d.ts +8 -21
  23. package/dist/context.js +33 -10
  24. package/dist/index.d.ts +2 -1
  25. package/dist/index.js +2 -1
  26. package/dist/internal/contexts.d.ts +63 -0
  27. package/dist/internal/contexts.js +15 -0
  28. package/dist/internal/credentials.d.ts +2 -11
  29. package/dist/internal/credentials.js +0 -19
  30. package/dist/internal/devices.d.ts +18 -80
  31. package/dist/internal/devices.js +76 -279
  32. package/dist/internal/file_index.js +3 -3
  33. package/dist/internal/filesystem.d.ts +31 -89
  34. package/dist/internal/filesystem.js +21 -20
  35. package/dist/internal/index.d.ts +0 -1
  36. package/dist/internal/index.js +0 -1
  37. package/dist/internal/index_fs.d.ts +12 -30
  38. package/dist/internal/index_fs.js +23 -55
  39. package/dist/internal/inode.d.ts +147 -9
  40. package/dist/internal/inode.js +333 -25
  41. package/dist/internal/log.d.ts +19 -13
  42. package/dist/internal/log.js +81 -80
  43. package/dist/mixins/async.js +26 -90
  44. package/dist/mixins/mutexed.d.ts +17 -16
  45. package/dist/mixins/mutexed.js +29 -31
  46. package/dist/mixins/readonly.d.ts +7 -6
  47. package/dist/mixins/readonly.js +6 -0
  48. package/dist/mixins/sync.js +8 -8
  49. package/dist/{vfs/path.d.ts → path.d.ts} +3 -4
  50. package/dist/{vfs/path.js → path.js} +6 -9
  51. package/dist/readline.d.ts +134 -0
  52. package/dist/readline.js +623 -0
  53. package/dist/utils.d.ts +4 -35
  54. package/dist/utils.js +8 -73
  55. package/dist/vfs/acl.d.ts +42 -0
  56. package/dist/vfs/acl.js +249 -0
  57. package/dist/vfs/async.d.ts +7 -21
  58. package/dist/vfs/async.js +19 -19
  59. package/dist/vfs/config.d.ts +6 -18
  60. package/dist/vfs/config.js +8 -18
  61. package/dist/vfs/dir.d.ts +3 -3
  62. package/dist/vfs/dir.js +9 -8
  63. package/dist/vfs/file.d.ts +106 -0
  64. package/dist/vfs/file.js +235 -0
  65. package/dist/vfs/flags.d.ts +19 -0
  66. package/dist/vfs/flags.js +62 -0
  67. package/dist/vfs/index.d.ts +4 -10
  68. package/dist/vfs/index.js +4 -13
  69. package/dist/vfs/ioctl.d.ts +87 -0
  70. package/dist/vfs/ioctl.js +304 -0
  71. package/dist/vfs/promises.d.ts +78 -16
  72. package/dist/vfs/promises.js +273 -122
  73. package/dist/vfs/shared.d.ts +7 -26
  74. package/dist/vfs/shared.js +25 -53
  75. package/dist/{stats.d.ts → vfs/stats.d.ts} +14 -28
  76. package/dist/{stats.js → vfs/stats.js} +11 -66
  77. package/dist/vfs/streams.d.ts +1 -0
  78. package/dist/vfs/streams.js +24 -19
  79. package/dist/vfs/sync.d.ts +4 -3
  80. package/dist/vfs/sync.js +143 -128
  81. package/dist/vfs/watchers.d.ts +2 -2
  82. package/dist/vfs/watchers.js +6 -6
  83. package/dist/vfs/xattr.d.ts +116 -0
  84. package/dist/vfs/xattr.js +218 -0
  85. package/package.json +3 -3
  86. package/readme.md +1 -1
  87. package/tests/backend/config.worker.js +4 -1
  88. package/tests/backend/fetch.test.ts +3 -0
  89. package/tests/backend/port.test.ts +21 -35
  90. package/tests/backend/remote.worker.js +4 -1
  91. package/tests/backend/single-buffer.test.ts +24 -0
  92. package/tests/common/context.test.ts +1 -1
  93. package/tests/common/handle.test.ts +17 -12
  94. package/tests/common/path.test.ts +1 -1
  95. package/tests/common/readline.test.ts +104 -0
  96. package/tests/common.ts +4 -19
  97. package/tests/fetch/fetch.ts +1 -1
  98. package/tests/fs/links.test.ts +1 -1
  99. package/tests/fs/permissions.test.ts +7 -6
  100. package/tests/fs/readFile.test.ts +3 -3
  101. package/tests/fs/stat.test.ts +6 -6
  102. package/tests/fs/streams.test.ts +2 -11
  103. package/tests/fs/times.test.ts +1 -1
  104. package/tests/fs/xattr.test.ts +85 -0
  105. package/tests/logs.js +22 -0
  106. package/tests/setup/context.ts +1 -1
  107. package/tests/setup/index.ts +3 -3
  108. package/tests/setup/port.ts +1 -1
  109. package/dist/backends/port/fs.d.ts +0 -84
  110. package/dist/backends/port/fs.js +0 -151
  111. package/dist/backends/port/rpc.d.ts +0 -77
  112. package/dist/backends/port/rpc.js +0 -100
  113. package/dist/backends/store/simple.d.ts +0 -20
  114. package/dist/backends/store/simple.js +0 -13
  115. package/dist/internal/file.d.ts +0 -351
  116. package/dist/internal/file.js +0 -739
package/dist/utils.js CHANGED
@@ -1,56 +1,6 @@
1
+ import { decodeUTF8, encodeUTF8 } from 'utilium';
1
2
  import { Errno, ErrnoError } from './internal/error.js';
2
- import { log_deprecated } from './internal/log.js';
3
- import { resolve } from './vfs/path.js';
4
- /**
5
- * Encodes a string into a buffer
6
- * @internal
7
- */
8
- export function encodeRaw(input) {
9
- if (typeof input != 'string') {
10
- throw new ErrnoError(Errno.EINVAL, 'Can not encode a non-string');
11
- }
12
- return new Uint8Array(Array.from(input).map(char => char.charCodeAt(0)));
13
- }
14
- /**
15
- * Decodes a string from a buffer
16
- * @internal
17
- */
18
- export function decodeRaw(input) {
19
- if (!(input instanceof Uint8Array)) {
20
- throw new ErrnoError(Errno.EINVAL, 'Can not decode a non-Uint8Array');
21
- }
22
- return Array.from(input)
23
- .map(char => String.fromCharCode(char))
24
- .join('');
25
- }
26
- const encoder = new TextEncoder();
27
- /**
28
- * Encodes a string into a buffer
29
- * @internal
30
- */
31
- export function encodeUTF8(input) {
32
- if (typeof input != 'string') {
33
- throw new ErrnoError(Errno.EINVAL, 'Can not encode a non-string');
34
- }
35
- return encoder.encode(input);
36
- }
37
- /* node:coverage disable */
38
- export { /** @deprecated @hidden */ encodeUTF8 as encode };
39
- /* node:coverage enable */
40
- const decoder = new TextDecoder();
41
- /**
42
- * Decodes a string from a buffer
43
- * @internal
44
- */
45
- export function decodeUTF8(input) {
46
- if (!(input instanceof Uint8Array)) {
47
- throw new ErrnoError(Errno.EINVAL, 'Can not decode a non-Uint8Array');
48
- }
49
- return decoder.decode(input);
50
- }
51
- /* node:coverage disable */
52
- export { /** @deprecated @hidden */ decodeUTF8 as decode };
53
- /* node:coverage enable */
3
+ import { resolve } from './path.js';
54
4
  /**
55
5
  * Decodes a directory listing
56
6
  * @hidden
@@ -117,6 +67,7 @@ export function normalizePath(p, noResolve = false) {
117
67
  throw new ErrnoError(Errno.EINVAL, 'Path can not be empty');
118
68
  }
119
69
  p = p.replaceAll(/[/\\]+/g, '/');
70
+ // Note: PWD is not resolved here, it is resolved later.
120
71
  return noResolve ? p : resolve(p);
121
72
  }
122
73
  /**
@@ -141,26 +92,10 @@ export function normalizeOptions(options, encoding = 'utf8', flag, mode = 0) {
141
92
  mode: normalizeMode('mode' in options ? options === null || options === void 0 ? void 0 : options.mode : null, mode),
142
93
  };
143
94
  }
144
- /* node:coverage disable */
145
- import { randomHex } from 'utilium';
146
- /**
147
- * Generate a random ino
148
- * @internal @deprecated @hidden
149
- */
150
- export function randomBigInt() {
151
- log_deprecated('randomBigInt');
152
- return BigInt('0x' + randomHex(8));
95
+ export function stringifyUUID(uuid) {
96
+ const hex = uuid.toString(16).padStart(32, '0');
97
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
153
98
  }
154
- /**
155
- * Prevents infinite loops
156
- * @internal
157
- * @deprecated Use `canary` from Utilium
158
- */
159
- export function canary(path, syscall) {
160
- log_deprecated('canary');
161
- const timeout = setTimeout(() => {
162
- throw ErrnoError.With('EDEADLK', path, syscall);
163
- }, 5000);
164
- return () => clearTimeout(timeout);
99
+ export function parseUUID(uuid) {
100
+ return BigInt(`0x${uuid.replace(/-/g, '')}`);
165
101
  }
166
- /* node:coverage enable */
@@ -0,0 +1,42 @@
1
+ import { type V_Context } from '../internal/contexts.js';
2
+ import { type InodeLike } from '../internal/inode.js';
3
+ export declare const enum Type {
4
+ Access = 32768,
5
+ Default = 16384
6
+ }
7
+ export declare const enum Tag {
8
+ UserObj = 1,
9
+ User = 2,
10
+ GroupObj = 4,
11
+ Group = 8,
12
+ Mask = 16,
13
+ Other = 32,
14
+ /**
15
+ * @internal @hidden
16
+ */
17
+ _None = 0
18
+ }
19
+ export declare class Entry {
20
+ tag: Tag;
21
+ perm: number;
22
+ id: number;
23
+ constructor(data?: Partial<Entry> | Uint8Array);
24
+ }
25
+ export declare class ACL {
26
+ version: number;
27
+ entries: Entry[];
28
+ constructor(data?: Uint8Array | Entry[]);
29
+ }
30
+ export declare function fromMode(mode: number): ACL;
31
+ export declare function toMode(acl: ACL): number;
32
+ export declare function get($: V_Context, path: string): Promise<ACL>;
33
+ export declare function getSync($: V_Context, path: string): ACL;
34
+ export declare function set($: V_Context, path: string, acl: ACL): Promise<void>;
35
+ export declare function setSync($: V_Context, path: string, acl: ACL): void;
36
+ export declare let shouldCheck: boolean;
37
+ export declare function setChecks(enabled: boolean): void;
38
+ /**
39
+ * Checks if a given user/group has access to this item
40
+ * @param access The requested access, combination of `W_OK`, `R_OK`, and `X_OK`
41
+ */
42
+ export declare function check($: V_Context, inode: InodeLike, access: number): boolean;
@@ -0,0 +1,249 @@
1
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
2
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
3
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
4
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
5
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
6
+ var _, done = false;
7
+ for (var i = decorators.length - 1; i >= 0; i--) {
8
+ var context = {};
9
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
10
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
11
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
12
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
13
+ if (kind === "accessor") {
14
+ if (result === void 0) continue;
15
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
16
+ if (_ = accept(result.get)) descriptor.get = _;
17
+ if (_ = accept(result.set)) descriptor.set = _;
18
+ if (_ = accept(result.init)) initializers.unshift(_);
19
+ }
20
+ else if (_ = accept(result)) {
21
+ if (kind === "field") initializers.unshift(_);
22
+ else descriptor[key] = _;
23
+ }
24
+ }
25
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
26
+ done = true;
27
+ };
28
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
29
+ var useValue = arguments.length > 2;
30
+ for (var i = 0; i < initializers.length; i++) {
31
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
32
+ }
33
+ return useValue ? value : void 0;
34
+ };
35
+ var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
36
+ if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
37
+ return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
38
+ };
39
+ /*
40
+ Access Control Lists.
41
+ At the moment, they are only intended for internal use.
42
+ They also are not checked for permissions yet.
43
+ Please use a namespace import for the best experience.
44
+ */
45
+ import { assignWithDefaults, deserialize, serialize, sizeof, struct, types as t } from 'utilium';
46
+ import { defaultContext } from '../internal/contexts.js';
47
+ import { Errno, ErrnoError } from '../internal/error.js';
48
+ import { Attributes } from '../internal/inode.js';
49
+ import { err } from '../internal/log.js';
50
+ import { S_IRWXG, S_IRWXO, S_IRWXU, W_OK, X_OK, R_OK } from './constants.js';
51
+ import * as xattr from './xattr.js';
52
+ const version = 2;
53
+ export var Type;
54
+ (function (Type) {
55
+ Type[Type["Access"] = 32768] = "Access";
56
+ Type[Type["Default"] = 16384] = "Default";
57
+ })(Type || (Type = {}));
58
+ export var Tag;
59
+ (function (Tag) {
60
+ Tag[Tag["UserObj"] = 1] = "UserObj";
61
+ Tag[Tag["User"] = 2] = "User";
62
+ Tag[Tag["GroupObj"] = 4] = "GroupObj";
63
+ Tag[Tag["Group"] = 8] = "Group";
64
+ Tag[Tag["Mask"] = 16] = "Mask";
65
+ Tag[Tag["Other"] = 32] = "Other";
66
+ /**
67
+ * @internal @hidden
68
+ */
69
+ Tag[Tag["_None"] = 0] = "_None";
70
+ })(Tag || (Tag = {}));
71
+ let Entry = (() => {
72
+ var _a, _b, _c;
73
+ let _classDecorators = [struct()];
74
+ let _classDescriptor;
75
+ let _classExtraInitializers = [];
76
+ let _classThis;
77
+ let _tag_decorators;
78
+ let _tag_initializers = [];
79
+ let _tag_extraInitializers = [];
80
+ let _perm_decorators;
81
+ let _perm_initializers = [];
82
+ let _perm_extraInitializers = [];
83
+ let _id_decorators;
84
+ let _id_initializers = [];
85
+ let _id_extraInitializers = [];
86
+ var Entry = _classThis = class {
87
+ constructor(data) {
88
+ this.tag = __runInitializers(this, _tag_initializers, 0);
89
+ this.perm = (__runInitializers(this, _tag_extraInitializers), __runInitializers(this, _perm_initializers, 0));
90
+ this.id = (__runInitializers(this, _perm_extraInitializers), __runInitializers(this, _id_initializers, 0));
91
+ __runInitializers(this, _id_extraInitializers);
92
+ if (data instanceof Uint8Array)
93
+ deserialize(this, data);
94
+ else if (typeof data == 'object')
95
+ assignWithDefaults(this, data);
96
+ }
97
+ };
98
+ __setFunctionName(_classThis, "Entry");
99
+ (() => {
100
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
101
+ _tag_decorators = [(_a = t).uint16.bind(_a)];
102
+ _perm_decorators = [(_b = t).uint16.bind(_b)];
103
+ _id_decorators = [(_c = t).uint32.bind(_c)];
104
+ __esDecorate(null, null, _tag_decorators, { kind: "field", name: "tag", static: false, private: false, access: { has: obj => "tag" in obj, get: obj => obj.tag, set: (obj, value) => { obj.tag = value; } }, metadata: _metadata }, _tag_initializers, _tag_extraInitializers);
105
+ __esDecorate(null, null, _perm_decorators, { kind: "field", name: "perm", static: false, private: false, access: { has: obj => "perm" in obj, get: obj => obj.perm, set: (obj, value) => { obj.perm = value; } }, metadata: _metadata }, _perm_initializers, _perm_extraInitializers);
106
+ __esDecorate(null, null, _id_decorators, { kind: "field", name: "id", static: false, private: false, access: { has: obj => "id" in obj, get: obj => obj.id, set: (obj, value) => { obj.id = value; } }, metadata: _metadata }, _id_initializers, _id_extraInitializers);
107
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
108
+ Entry = _classThis = _classDescriptor.value;
109
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
110
+ __runInitializers(_classThis, _classExtraInitializers);
111
+ })();
112
+ return Entry = _classThis;
113
+ })();
114
+ export { Entry };
115
+ let ACL = (() => {
116
+ var _a;
117
+ let _classDecorators = [struct()];
118
+ let _classDescriptor;
119
+ let _classExtraInitializers = [];
120
+ let _classThis;
121
+ let _version_decorators;
122
+ let _version_initializers = [];
123
+ let _version_extraInitializers = [];
124
+ var ACL = _classThis = class {
125
+ constructor(data) {
126
+ this.version = __runInitializers(this, _version_initializers, version);
127
+ this.entries = (__runInitializers(this, _version_extraInitializers), []);
128
+ if (!data)
129
+ return;
130
+ if (!(data instanceof Uint8Array)) {
131
+ this.entries.push(...data);
132
+ return;
133
+ }
134
+ deserialize(this, data);
135
+ if (this.version != version)
136
+ throw err(new ErrnoError(Errno.EINVAL, 'Invalid ACL version'));
137
+ for (let offset = sizeof(ACL); offset < data.length; offset += sizeof(Entry)) {
138
+ if (offset + sizeof(Entry) > data.length)
139
+ throw err(new ErrnoError(Errno.EIO, 'Invalid ACL data'));
140
+ const slice = data.subarray(offset, offset + sizeof(Entry));
141
+ this.entries.push(new Entry(slice));
142
+ }
143
+ }
144
+ };
145
+ __setFunctionName(_classThis, "ACL");
146
+ (() => {
147
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
148
+ _version_decorators = [(_a = t).uint32.bind(_a)];
149
+ __esDecorate(null, null, _version_decorators, { kind: "field", name: "version", static: false, private: false, access: { has: obj => "version" in obj, get: obj => obj.version, set: (obj, value) => { obj.version = value; } }, metadata: _metadata }, _version_initializers, _version_extraInitializers);
150
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
151
+ ACL = _classThis = _classDescriptor.value;
152
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
153
+ __runInitializers(_classThis, _classExtraInitializers);
154
+ })();
155
+ return ACL = _classThis;
156
+ })();
157
+ export { ACL };
158
+ export function fromMode(mode) {
159
+ return new ACL([
160
+ new Entry({ tag: Tag.UserObj, perm: (mode & S_IRWXU) >> 6 }),
161
+ new Entry({ tag: Tag.GroupObj, perm: (mode & S_IRWXG) >> 3 }),
162
+ new Entry({ tag: Tag.Other, perm: mode & S_IRWXO }),
163
+ ]);
164
+ }
165
+ export function toMode(acl) {
166
+ let mode = 0;
167
+ for (const entry of acl.entries) {
168
+ switch (entry.tag) {
169
+ case Tag.UserObj:
170
+ mode |= entry.perm << 6;
171
+ break;
172
+ case Tag.GroupObj:
173
+ mode |= entry.perm << 3;
174
+ break;
175
+ case Tag.Other:
176
+ mode |= entry.perm;
177
+ break;
178
+ case Tag.User:
179
+ case Tag.Group:
180
+ case Tag.Mask:
181
+ case Tag._None:
182
+ continue;
183
+ }
184
+ }
185
+ return mode;
186
+ }
187
+ export async function get($, path) {
188
+ return new ACL(await xattr.get.call($, path, 'system.posix_acl_access'));
189
+ }
190
+ export function getSync($, path) {
191
+ return new ACL(xattr.getSync.call($, path, 'system.posix_acl_access'));
192
+ }
193
+ export async function set($, path, acl) {
194
+ await xattr.set.call($, path, 'system.posix_acl_access', serialize(acl));
195
+ }
196
+ export function setSync($, path, acl) {
197
+ xattr.setSync.call($, path, 'system.posix_acl_access', serialize(acl));
198
+ }
199
+ export let shouldCheck = true;
200
+ export function setChecks(enabled) {
201
+ shouldCheck = enabled;
202
+ }
203
+ /**
204
+ * Checks if a given user/group has access to this item
205
+ * @param access The requested access, combination of `W_OK`, `R_OK`, and `X_OK`
206
+ */
207
+ export function check($, inode, access) {
208
+ var _a, _b;
209
+ if (!shouldCheck)
210
+ return true;
211
+ (_a = inode.attributes) !== null && _a !== void 0 ? _a : (inode.attributes = new Attributes());
212
+ const { euid, egid } = (_b = $ === null || $ === void 0 ? void 0 : $.credentials) !== null && _b !== void 0 ? _b : defaultContext.credentials;
213
+ const attr = inode.attributes.get('system.posix_acl_access');
214
+ if (!attr)
215
+ return true;
216
+ const acl = new ACL(attr.value);
217
+ let mask = R_OK | W_OK | X_OK;
218
+ let result = false;
219
+ for (const entry of acl.entries) {
220
+ switch (entry.tag) {
221
+ case Tag.UserObj:
222
+ if (inode.uid == euid && (entry.perm & access) === access)
223
+ result = true;
224
+ break;
225
+ case Tag.User:
226
+ if (entry.id == euid && (entry.perm & mask & access) === access)
227
+ result = true;
228
+ break;
229
+ case Tag.GroupObj:
230
+ if (inode.gid == egid && (entry.perm & mask & access) === access)
231
+ result = true;
232
+ break;
233
+ case Tag.Group:
234
+ if (entry.id == egid && (entry.perm & mask & access) === access)
235
+ result = true;
236
+ break;
237
+ case Tag.Mask:
238
+ mask = entry.perm;
239
+ break;
240
+ case Tag.Other:
241
+ if ((entry.perm & mask & access) === access)
242
+ result = true;
243
+ break;
244
+ case Tag._None:
245
+ continue;
246
+ }
247
+ }
248
+ return result;
249
+ }
@@ -1,12 +1,12 @@
1
1
  import type * as fs from 'node:fs';
2
2
  import type { V_Context } from '../context.js';
3
- import type { Stats } from '../stats.js';
4
3
  import type { Callback } from '../utils.js';
5
4
  import type { Dir, Dirent } from './dir.js';
5
+ import type { Stats } from './stats.js';
6
6
  import type { FileContents } from './types.js';
7
7
  import { Buffer } from 'buffer';
8
8
  import { ErrnoError } from '../internal/error.js';
9
- import { BigIntStats } from '../stats.js';
9
+ import { BigIntStats } from './stats.js';
10
10
  import { ReadStream, WriteStream, type ReadStreamOptions, type WriteStreamOptions } from './streams.js';
11
11
  import { FSWatcher } from './watchers.js';
12
12
  /**
@@ -16,7 +16,7 @@ export declare function rename(this: V_Context, oldPath: fs.PathLike, newPath: f
16
16
  /**
17
17
  * Test whether or not `path` exists by checking with the file system.
18
18
  * Then call the callback argument with either true or false.
19
- * @deprecated Use {@link stat} or {@link access} instead.
19
+ * According to Node.js: deprecated Use {@link stat} or {@link access} instead.
20
20
  */
21
21
  export declare function exists(this: V_Context, path: fs.PathLike, cb?: (exists: boolean) => unknown): void;
22
22
  export declare function stat(this: V_Context, path: fs.PathLike, callback: Callback<[Stats]>): void;
@@ -48,25 +48,11 @@ export declare function unlink(this: V_Context, path: fs.PathLike, cb?: Callback
48
48
  * Exclusive mode ensures that path is newly created.
49
49
  * Mode defaults to `0644`
50
50
  *
51
- * `flags` can be:
52
- *
53
- * * `'r'` - Open file for reading. An exception occurs if the file does not exist.
54
- * * `'r+'` - Open file for reading and writing. An exception occurs if the file does not exist.
55
- * * `'rs'` - Open file for reading in synchronous mode. Instructs the filesystem to not cache writes.
56
- * * `'rs+'` - Open file for reading and writing, and opens the file in synchronous mode.
57
- * * `'w'` - Open file for writing. The file is created (if it does not exist) or truncated (if it exists).
58
- * * `'wx'` - Like 'w' but opens the file in exclusive mode.
59
- * * `'w+'` - Open file for reading and writing. The file is created (if it does not exist) or truncated (if it exists).
60
- * * `'wx+'` - Like 'w+' but opens the file in exclusive mode.
61
- * * `'a'` - Open file for appending. The file is created if it does not exist.
62
- * * `'ax'` - Like 'a' but opens the file in exclusive mode.
63
- * * `'a+'` - Open file for reading and appending. The file is created if it does not exist.
64
- * * `'ax+'` - Like 'a+' but opens the file in exclusive mode.
65
- *
66
- * @see http://www.manpagez.com/man/2/open/
51
+ * @see https://nodejs.org/api/fs.html#fsopenpath-flags-mode-callback
52
+ * @param flags {@link https://nodejs.org/api/fs.html#file-system-flags}
67
53
  */
68
- export declare function open(this: V_Context, path: fs.PathLike, flag: string, cb?: Callback<[number]>): void;
69
- export declare function open(this: V_Context, path: fs.PathLike, flag: string, mode: number | string, cb?: Callback<[number]>): void;
54
+ export declare function open(this: V_Context, path: fs.PathLike, flag: fs.OpenMode, cb?: Callback<[number]>): void;
55
+ export declare function open(this: V_Context, path: fs.PathLike, flag: fs.OpenMode, mode: number | string, cb?: Callback<[number]>): void;
70
56
  /**
71
57
  * Asynchronously reads the entire contents of a file.
72
58
  * @option encoding The string encoding for the file contents. Defaults to `null`.
package/dist/vfs/async.js CHANGED
@@ -1,10 +1,9 @@
1
1
  import { Buffer } from 'buffer';
2
2
  import { Errno, ErrnoError } from '../internal/error.js';
3
- import { BigIntStats } from '../stats.js';
4
3
  import { normalizeMode, normalizePath } from '../utils.js';
5
4
  import { R_OK } from './constants.js';
6
5
  import * as promises from './promises.js';
7
- import { fd2file, fdMap } from './shared.js';
6
+ import { BigIntStats } from './stats.js';
8
7
  import { ReadStream, WriteStream } from './streams.js';
9
8
  import { FSWatcher, StatWatcher } from './watchers.js';
10
9
  const nop = () => { };
@@ -31,7 +30,7 @@ rename;
31
30
  /**
32
31
  * Test whether or not `path` exists by checking with the file system.
33
32
  * Then call the callback argument with either true or false.
34
- * @deprecated Use {@link stat} or {@link access} instead.
33
+ * According to Node.js: deprecated Use {@link stat} or {@link access} instead.
35
34
  */
36
35
  export function exists(path, cb = nop) {
37
36
  promises.exists
@@ -108,22 +107,23 @@ export function appendFile(filename, data, cbEncOpts, cb = nop) {
108
107
  appendFile;
109
108
  export function fstat(fd, options, cb = nop) {
110
109
  cb = typeof options == 'function' ? options : cb;
111
- fd2file(fd)
110
+ new promises.FileHandle(this, fd)
112
111
  .stat()
113
112
  .then(stats => cb(undefined, typeof options == 'object' && (options === null || options === void 0 ? void 0 : options.bigint) ? new BigIntStats(stats) : stats))
114
113
  .catch(cb);
115
114
  }
116
115
  fstat;
117
116
  export function close(fd, cb = nop) {
118
- const close = fd2file(fd).close();
119
- fdMap.delete(fd);
120
- close.then(() => cb()).catch(cb);
117
+ new promises.FileHandle(this, fd)
118
+ .close()
119
+ .then(() => cb())
120
+ .catch(cb);
121
121
  }
122
122
  close;
123
123
  export function ftruncate(fd, lenOrCB, cb = nop) {
124
124
  const length = typeof lenOrCB === 'number' ? lenOrCB : 0;
125
125
  cb = typeof lenOrCB === 'function' ? lenOrCB : cb;
126
- const file = fd2file(fd);
126
+ const file = new promises.FileHandle(this, fd);
127
127
  if (length < 0) {
128
128
  throw new ErrnoError(Errno.EINVAL);
129
129
  }
@@ -133,14 +133,14 @@ export function ftruncate(fd, lenOrCB, cb = nop) {
133
133
  }
134
134
  ftruncate;
135
135
  export function fsync(fd, cb = nop) {
136
- fd2file(fd)
136
+ new promises.FileHandle(this, fd)
137
137
  .sync()
138
138
  .then(() => cb())
139
139
  .catch(cb);
140
140
  }
141
141
  fsync;
142
142
  export function fdatasync(fd, cb = nop) {
143
- fd2file(fd)
143
+ new promises.FileHandle(this, fd)
144
144
  .datasync()
145
145
  .then(() => cb())
146
146
  .catch(cb);
@@ -148,7 +148,7 @@ export function fdatasync(fd, cb = nop) {
148
148
  fdatasync;
149
149
  export function write(fd, data, cbPosOff, cbLenEnc, cbPosEnc, cb = nop) {
150
150
  let buffer, offset, length, position, encoding;
151
- const handle = new promises.FileHandle(fd, this);
151
+ const handle = new promises.FileHandle(this, fd);
152
152
  if (typeof data === 'string') {
153
153
  // Signature 1: (fd, string, [position?, [encoding?]], cb?)
154
154
  encoding = 'utf8';
@@ -202,21 +202,21 @@ write;
202
202
  * @param cb The number is the number of bytes read
203
203
  */
204
204
  export function read(fd, buffer, offset, length, position, cb = nop) {
205
- new promises.FileHandle(fd, this)
205
+ new promises.FileHandle(this, fd)
206
206
  .read(buffer, offset, length, position)
207
207
  .then(({ bytesRead, buffer }) => cb(undefined, bytesRead, buffer))
208
208
  .catch(cb);
209
209
  }
210
210
  read;
211
211
  export function fchown(fd, uid, gid, cb = nop) {
212
- new promises.FileHandle(fd, this)
212
+ new promises.FileHandle(this, fd)
213
213
  .chown(uid, gid)
214
214
  .then(() => cb())
215
215
  .catch(cb);
216
216
  }
217
217
  fchown;
218
218
  export function fchmod(fd, mode, cb) {
219
- new promises.FileHandle(fd, this)
219
+ new promises.FileHandle(this, fd)
220
220
  .chmod(mode)
221
221
  .then(() => cb())
222
222
  .catch(cb);
@@ -226,7 +226,7 @@ fchmod;
226
226
  * Change the file timestamps of a file referenced by the supplied file descriptor.
227
227
  */
228
228
  export function futimes(fd, atime, mtime, cb = nop) {
229
- new promises.FileHandle(fd, this)
229
+ new promises.FileHandle(this, fd)
230
230
  .utimes(atime, mtime)
231
231
  .then(() => cb())
232
232
  .catch(cb);
@@ -350,7 +350,7 @@ export function access(path, cbMode, cb = nop) {
350
350
  access;
351
351
  const statWatchers = new Map();
352
352
  export function watchFile(path, options, listener) {
353
- const normalizedPath = normalizePath(path.toString());
353
+ const normalizedPath = normalizePath(path);
354
354
  const opts = typeof options != 'function' ? options : {};
355
355
  if (typeof options == 'function') {
356
356
  listener = options;
@@ -388,7 +388,7 @@ watchFile;
388
388
  * @param listener Optional listener to remove.
389
389
  */
390
390
  export function unwatchFile(path, listener = nop) {
391
- const normalizedPath = normalizePath(path.toString());
391
+ const normalizedPath = normalizePath(path);
392
392
  const entry = statWatchers.get(normalizedPath);
393
393
  if (entry) {
394
394
  if (listener && listener !== nop) {
@@ -465,7 +465,7 @@ export function copyFile(src, dest, flags, callback = nop) {
465
465
  copyFile;
466
466
  export function readv(fd, buffers, position, cb = nop) {
467
467
  cb = typeof position === 'function' ? position : cb;
468
- new promises.FileHandle(fd, this)
468
+ new promises.FileHandle(this, fd)
469
469
  .readv(buffers, typeof position === 'function' ? undefined : position)
470
470
  .then(({ buffers, bytesRead }) => cb(undefined, bytesRead, buffers))
471
471
  .catch(cb);
@@ -473,7 +473,7 @@ export function readv(fd, buffers, position, cb = nop) {
473
473
  readv;
474
474
  export function writev(fd, buffers, position, cb = nop) {
475
475
  cb = typeof position === 'function' ? position : cb;
476
- new promises.FileHandle(fd, this)
476
+ new promises.FileHandle(this, fd)
477
477
  .writev(buffers, typeof position === 'function' ? undefined : position)
478
478
  .then(({ buffers, bytesWritten }) => cb(undefined, bytesWritten, buffers))
479
479
  .catch(cb);
@@ -1,18 +1,6 @@
1
- export declare const config: {
2
- /**
3
- * Whether to perform access checks
4
- */
5
- checkAccess: boolean;
6
- /**
7
- * Whether to mark a file as dirty after updating its `atime` when read from
8
- */
9
- updateOnRead: boolean;
10
- /**
11
- * Whether to immediately sync when files are changed
12
- */
13
- syncImmediately: boolean;
14
- /**
15
- * If a file's buffer is not large enough to store content when writing and the buffer can't be resized, reuse the buffer passed to write()
16
- */
17
- unsafeBufferReplace: boolean;
18
- };
1
+ /** Whether to perform access checks */
2
+ export declare let checkAccess: boolean;
3
+ /**
4
+ * @internal @hidden
5
+ */
6
+ export declare function _setAccessChecks(value: boolean): void;
@@ -1,18 +1,8 @@
1
- export const config = {
2
- /**
3
- * Whether to perform access checks
4
- */
5
- checkAccess: true,
6
- /**
7
- * Whether to mark a file as dirty after updating its `atime` when read from
8
- */
9
- updateOnRead: true,
10
- /**
11
- * Whether to immediately sync when files are changed
12
- */
13
- syncImmediately: true,
14
- /**
15
- * If a file's buffer is not large enough to store content when writing and the buffer can't be resized, reuse the buffer passed to write()
16
- */
17
- unsafeBufferReplace: false,
18
- };
1
+ /** Whether to perform access checks */
2
+ export let checkAccess = true;
3
+ /**
4
+ * @internal @hidden
5
+ */
6
+ export function _setAccessChecks(value) {
7
+ checkAccess = value;
8
+ }
package/dist/vfs/dir.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import type { Dir as _Dir, Dirent as _Dirent } from 'node:fs';
2
2
  import type { V_Context } from '../context.js';
3
- import type { Stats } from '../stats.js';
3
+ import { type InodeLike } from '../internal/inode.js';
4
4
  import type { Callback } from '../utils.js';
5
5
  export declare class Dirent implements _Dirent {
6
6
  path: string;
7
- protected stats: Stats;
7
+ protected stats: InodeLike;
8
8
  get name(): string;
9
- constructor(path: string, stats: Stats);
9
+ constructor(path: string, stats: InodeLike);
10
10
  get parentPath(): string;
11
11
  isFile(): boolean;
12
12
  isDirectory(): boolean;