@zenfs/core 2.6.5 → 2.7.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.
@@ -1,90 +1,13 @@
1
- import { BufferView } from 'utilium/buffer';
1
+ import type { PathOrFileDescriptor } from 'node:fs';
2
2
  import type { V_Context } from '../context.js';
3
- import { Inode } from '../internal/inode.js';
4
- declare const fsxattr_base: import("memium").StructConstructor<BufferView<any>>;
5
- declare class fsxattr extends fsxattr_base {
6
- static name: string;
7
- /** xflags field value */
8
- accessor xflags: number;
9
- /** extsize field value */
10
- accessor extsize: number;
11
- /** nextents field value */
12
- accessor nextents: number;
13
- /** project identifier */
14
- accessor projid: number;
15
- /** CoW extsize field value */
16
- accessor cowextsize: number;
17
- protected accessor pad: number[];
18
- constructor(inode?: Inode);
19
- }
3
+ import type { IoctlArgs, IoctlDefaultAsyncOps, IoctlDefaultSyncOps, IoctlOps } from '../internal/ioctl.js';
20
4
  /**
21
- * `FS_IOC_*` commands for {@link ioctl | `ioctl`}
22
- * @remarks
23
- * These are computed from a script since constant values are needed for enum member types
5
+ * Perform an `ioctl` on a file or file system.
6
+ * @category ioctl
24
7
  */
25
- export declare enum IOC {
26
- GetFlags = 2148034049,
27
- SetFlags = 1074292226,
28
- GetVersion = 2148038145,
29
- SetVersion = 1074296322,
30
- Fiemap = 3223348747,
31
- GetXattr = 2149341215,
32
- SetXattr = 1075599392,
33
- GetLabel = 2164298801,
34
- SetLabel = 1090556978,
35
- GetUUID = 2148603136,
36
- GetSysfsPath = 2155943169
37
- }
8
+ export declare function ioctl<const Command extends number, const Ops extends IoctlOps = IoctlDefaultAsyncOps>(this: V_Context, path: PathOrFileDescriptor, command: Command, ...args: IoctlArgs<Ops[Command]>): Promise<ReturnType<Ops[Command]>>;
38
9
  /**
39
- * `FS_IOC32_*` commands for {@link ioctl | `ioctl`}
40
- * @remarks
41
- * These are computed from a script since constant values are needed for enum member types
10
+ * Perform an `ioctl` on a file or file system
11
+ * @category ioctl
42
12
  */
43
- export declare enum IOC32 {
44
- GetFlags = 2147771905,
45
- SetFlags = 1074030082,
46
- GetVersion = 2147776001,
47
- SetVersion = 1074034178
48
- }
49
- /** Used by `ioctl` for type inference */
50
- interface _ioc_ops {
51
- [IOC.GetFlags](): number;
52
- [IOC.SetFlags](flags: number): void;
53
- [IOC.GetVersion](): number;
54
- [IOC.SetVersion](version: number): void;
55
- [IOC.Fiemap](): never;
56
- [IOC.GetXattr](name: string): fsxattr;
57
- [IOC.SetXattr](name: string, value: fsxattr): never;
58
- [IOC.GetLabel](): string;
59
- [IOC.SetLabel](label: string): void;
60
- [IOC.GetUUID](): string;
61
- [IOC.GetSysfsPath](): string;
62
- }
63
- /** Used by `ioctl` for type inference */
64
- interface _ioc32_ops extends Record<keyof IOC32, (...args: any[]) => any> {
65
- [IOC32.GetFlags](): number;
66
- [IOC32.SetFlags](flags: number): void;
67
- [IOC32.GetVersion](): number;
68
- [IOC32.SetVersion](version: number): void;
69
- }
70
- /** Used by `ioctl` for type inference */
71
- type __ioctl_args__<T extends number> = T extends IOC ? Parameters<_ioc_ops[T]> : T extends IOC32 ? Parameters<_ioc32_ops[T]> : any[];
72
- /** Used by `ioctl` for type inference */
73
- type __ioctl_return__<T extends number> = T extends IOC ? ReturnType<_ioc_ops[T]> : T extends IOC32 ? ReturnType<_ioc32_ops[T]> : any;
74
- /** Perform an `ioctl` on a file or file system. */
75
- export declare function ioctl<const Command extends number, const Args extends __ioctl_args__<Command>, const Return extends __ioctl_return__<Command>>(this: V_Context,
76
- /** The path to the file or file system to perform the `ioctl` on */
77
- path: string,
78
- /** The command to perform (uint32) */
79
- command: Command,
80
- /** The arguments to pass to the command */
81
- ...args: Args): Promise<Return>;
82
- /** Perform an `ioctl` on a file or file system */
83
- export declare function ioctlSync<const Command extends number, const Args extends __ioctl_args__<Command>, const Return extends __ioctl_return__<Command>>(this: V_Context,
84
- /** The path to the file or file system to perform the `ioctl` on */
85
- path: string,
86
- /** The command to perform (uint32) */
87
- command: Command,
88
- /** The arguments to pass to the command */
89
- ...args: Args): Return;
90
- export {};
13
+ export declare function ioctlSync<const Command extends number, const Ops extends IoctlOps = IoctlDefaultSyncOps>(this: V_Context, path: PathOrFileDescriptor, command: Command, ...args: IoctlArgs<Ops[Command]>): ReturnType<Ops[Command]>;
package/dist/vfs/ioctl.js CHANGED
@@ -5,387 +5,85 @@
5
5
  - include/uapi/asm-generic/ioctl.h
6
6
  - include/uapi/linux/fs.h (`FS_IOC_*`)
7
7
  */
8
- var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
9
- function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
10
- var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
11
- var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
12
- var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
13
- var _, done = false;
14
- for (var i = decorators.length - 1; i >= 0; i--) {
15
- var context = {};
16
- for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
17
- for (var p in contextIn.access) context.access[p] = contextIn.access[p];
18
- context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
19
- var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
20
- if (kind === "accessor") {
21
- if (result === void 0) continue;
22
- if (result === null || typeof result !== "object") throw new TypeError("Object expected");
23
- if (_ = accept(result.get)) descriptor.get = _;
24
- if (_ = accept(result.set)) descriptor.set = _;
25
- if (_ = accept(result.init)) initializers.unshift(_);
26
- }
27
- else if (_ = accept(result)) {
28
- if (kind === "field") initializers.unshift(_);
29
- else descriptor[key] = _;
30
- }
31
- }
32
- if (target) Object.defineProperty(target, contextIn.name, descriptor);
33
- done = true;
34
- };
35
- var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
36
- var useValue = arguments.length > 2;
37
- for (var i = 0; i < initializers.length; i++) {
38
- value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
39
- }
40
- return useValue ? value : void 0;
41
- };
42
- import { Errno, Exception, setUVMessage, UV } from 'kerium';
43
- import { sizeof } from 'memium';
44
- import { $from, struct, types as t } from 'memium/decorators';
45
- import { _throw } from 'utilium';
46
- import { BufferView } from 'utilium/buffer';
47
- import { Inode, InodeFlags } from '../internal/inode.js';
8
+ import { setUVMessage, UV } from 'kerium';
48
9
  import { normalizePath } from '../utils.js';
49
- import { resolveMount } from './shared.js';
50
- /*
51
- * Flags for the fsxattr.xflags field
52
- */
53
- var XFlag;
54
- (function (XFlag) {
55
- /** data in realtime volume */
56
- XFlag[XFlag["RealTime"] = 1] = "RealTime";
57
- /** preallocated file extents */
58
- XFlag[XFlag["PreAlloc"] = 2] = "PreAlloc";
59
- /** file cannot be modified */
60
- XFlag[XFlag["Immutable"] = 8] = "Immutable";
61
- /** all writes append */
62
- XFlag[XFlag["Append"] = 16] = "Append";
63
- /** all writes synchronous */
64
- XFlag[XFlag["Sync"] = 32] = "Sync";
65
- /** do not update access time */
66
- XFlag[XFlag["NoAtime"] = 64] = "NoAtime";
67
- /** do not include in backups */
68
- XFlag[XFlag["NoDump"] = 128] = "NoDump";
69
- /** create with rt bit set */
70
- XFlag[XFlag["RtInherit"] = 256] = "RtInherit";
71
- /** create with parents projid */
72
- XFlag[XFlag["ProjInherit"] = 512] = "ProjInherit";
73
- /** disallow symlink creation */
74
- XFlag[XFlag["NoSymlinks"] = 1024] = "NoSymlinks";
75
- /** extent size allocator hint */
76
- XFlag[XFlag["ExtSize"] = 2048] = "ExtSize";
77
- /** inherit inode extent size */
78
- XFlag[XFlag["ExtSzInherit"] = 4096] = "ExtSzInherit";
79
- /** do not defragment */
80
- XFlag[XFlag["NoDefrag"] = 8192] = "NoDefrag";
81
- /** use filestream allocator */
82
- XFlag[XFlag["FileStream"] = 16384] = "FileStream";
83
- /** use DAX for IO */
84
- XFlag[XFlag["Dax"] = 32768] = "Dax";
85
- /** CoW extent size allocator hint */
86
- XFlag[XFlag["CowExtSize"] = 65536] = "CowExtSize";
87
- /** no DIFLAG for this */
88
- XFlag[XFlag["HasAttr"] = 2147483648] = "HasAttr";
89
- })(XFlag || (XFlag = {}));
90
- let fsxattr = (() => {
91
- var _a, _b, _c, _d, _e;
92
- let _classDecorators = [struct()];
93
- let _classDescriptor;
94
- let _classExtraInitializers = [];
95
- let _classThis;
96
- let _classSuper = $from(BufferView);
97
- let _xflags_decorators;
98
- let _xflags_initializers = [];
99
- let _xflags_extraInitializers = [];
100
- let _extsize_decorators;
101
- let _extsize_initializers = [];
102
- let _extsize_extraInitializers = [];
103
- let _nextents_decorators;
104
- let _nextents_initializers = [];
105
- let _nextents_extraInitializers = [];
106
- let _projid_decorators;
107
- let _projid_initializers = [];
108
- let _projid_extraInitializers = [];
109
- let _cowextsize_decorators;
110
- let _cowextsize_initializers = [];
111
- let _cowextsize_extraInitializers = [];
112
- let _pad_decorators;
113
- let _pad_initializers = [];
114
- let _pad_extraInitializers = [];
115
- var fsxattr = class extends _classSuper {
116
- static { _classThis = this; }
117
- static {
118
- const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
119
- _xflags_decorators = [(_a = t).uint32.bind(_a)];
120
- _extsize_decorators = [(_b = t).uint32.bind(_b)];
121
- _nextents_decorators = [(_c = t).uint32.bind(_c)];
122
- _projid_decorators = [(_d = t).uint32.bind(_d)];
123
- _cowextsize_decorators = [(_e = t).uint32.bind(_e)];
124
- _pad_decorators = [t.char(8)];
125
- __esDecorate(this, null, _xflags_decorators, { kind: "accessor", name: "xflags", static: false, private: false, access: { has: obj => "xflags" in obj, get: obj => obj.xflags, set: (obj, value) => { obj.xflags = value; } }, metadata: _metadata }, _xflags_initializers, _xflags_extraInitializers);
126
- __esDecorate(this, null, _extsize_decorators, { kind: "accessor", name: "extsize", static: false, private: false, access: { has: obj => "extsize" in obj, get: obj => obj.extsize, set: (obj, value) => { obj.extsize = value; } }, metadata: _metadata }, _extsize_initializers, _extsize_extraInitializers);
127
- __esDecorate(this, null, _nextents_decorators, { kind: "accessor", name: "nextents", static: false, private: false, access: { has: obj => "nextents" in obj, get: obj => obj.nextents, set: (obj, value) => { obj.nextents = value; } }, metadata: _metadata }, _nextents_initializers, _nextents_extraInitializers);
128
- __esDecorate(this, null, _projid_decorators, { kind: "accessor", name: "projid", static: false, private: false, access: { has: obj => "projid" in obj, get: obj => obj.projid, set: (obj, value) => { obj.projid = value; } }, metadata: _metadata }, _projid_initializers, _projid_extraInitializers);
129
- __esDecorate(this, null, _cowextsize_decorators, { kind: "accessor", name: "cowextsize", static: false, private: false, access: { has: obj => "cowextsize" in obj, get: obj => obj.cowextsize, set: (obj, value) => { obj.cowextsize = value; } }, metadata: _metadata }, _cowextsize_initializers, _cowextsize_extraInitializers);
130
- __esDecorate(this, null, _pad_decorators, { kind: "accessor", name: "pad", static: false, private: false, access: { has: obj => "pad" in obj, get: obj => obj.pad, set: (obj, value) => { obj.pad = value; } }, metadata: _metadata }, _pad_initializers, _pad_extraInitializers);
131
- __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
132
- fsxattr = _classThis = _classDescriptor.value;
133
- if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
134
- }
135
- static name = 'fsxattr';
136
- #xflags_accessor_storage = __runInitializers(this, _xflags_initializers, void 0);
137
- /** xflags field value */
138
- get xflags() { return this.#xflags_accessor_storage; }
139
- set xflags(value) { this.#xflags_accessor_storage = value; }
140
- #extsize_accessor_storage = (__runInitializers(this, _xflags_extraInitializers), __runInitializers(this, _extsize_initializers, void 0));
141
- /** extsize field value */
142
- get extsize() { return this.#extsize_accessor_storage; }
143
- set extsize(value) { this.#extsize_accessor_storage = value; }
144
- #nextents_accessor_storage = (__runInitializers(this, _extsize_extraInitializers), __runInitializers(this, _nextents_initializers, void 0));
145
- /** nextents field value */
146
- get nextents() { return this.#nextents_accessor_storage; }
147
- set nextents(value) { this.#nextents_accessor_storage = value; }
148
- #projid_accessor_storage = (__runInitializers(this, _nextents_extraInitializers), __runInitializers(this, _projid_initializers, void 0));
149
- /** project identifier */
150
- get projid() { return this.#projid_accessor_storage; }
151
- set projid(value) { this.#projid_accessor_storage = value; }
152
- #cowextsize_accessor_storage = (__runInitializers(this, _projid_extraInitializers), __runInitializers(this, _cowextsize_initializers, void 0));
153
- /** CoW extsize field value */
154
- get cowextsize() { return this.#cowextsize_accessor_storage; }
155
- set cowextsize(value) { this.#cowextsize_accessor_storage = value; }
156
- #pad_accessor_storage = (__runInitializers(this, _cowextsize_extraInitializers), __runInitializers(this, _pad_initializers, []));
157
- get pad() { return this.#pad_accessor_storage; }
158
- set pad(value) { this.#pad_accessor_storage = value; }
159
- constructor(inode = _throw(new Exception(Errno.EINVAL, 'fsxattr must be initialized with an inode'))) {
160
- super(new ArrayBuffer(sizeof(fsxattr)));
161
- __runInitializers(this, _pad_extraInitializers);
162
- this.extsize = inode.size;
163
- this.nextents = 1;
164
- this.projid = inode.uid;
165
- this.cowextsize = inode.size;
166
- for (const name of Object.keys(InodeFlags)) {
167
- if (!(inode.flags & InodeFlags[name]))
168
- continue;
169
- if (name in XFlag)
170
- this.xflags |= XFlag[name];
171
- }
172
- }
173
- static {
174
- __runInitializers(_classThis, _classExtraInitializers);
175
- }
176
- };
177
- return fsxattr = _classThis;
178
- })();
10
+ import { resolve as resolveAsync } from './async.js';
11
+ import { fromFD } from './file.js';
12
+ import { resolve as resolveSync } from './sync.js';
13
+ import { cacheOf } from './vcache.js';
179
14
  /**
180
- * Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS)
181
- * @see `FS_*_FL` in `include/uapi/linux/fs.h` (around L250)
182
- * @experimental
15
+ * Perform an `ioctl` on a file or file system.
16
+ * @category ioctl
183
17
  */
184
- var FileFlag;
185
- (function (FileFlag) {
186
- /** Secure deletion */
187
- FileFlag[FileFlag["SecureRm"] = 1] = "SecureRm";
188
- /** Undelete */
189
- FileFlag[FileFlag["Undelete"] = 2] = "Undelete";
190
- /** Compress file */
191
- FileFlag[FileFlag["Compress"] = 4] = "Compress";
192
- /** Synchronous updates */
193
- FileFlag[FileFlag["Sync"] = 8] = "Sync";
194
- /** Immutable file */
195
- FileFlag[FileFlag["Immutable"] = 16] = "Immutable";
196
- /** Writes to file may only append */
197
- FileFlag[FileFlag["Append"] = 32] = "Append";
198
- /** do not dump file */
199
- FileFlag[FileFlag["NoDump"] = 64] = "NoDump";
200
- /** do not update atime */
201
- FileFlag[FileFlag["NoAtime"] = 128] = "NoAtime";
202
- // Reserved for compression usage...
203
- FileFlag[FileFlag["Dirty"] = 256] = "Dirty";
204
- /** One or more compressed clusters */
205
- FileFlag[FileFlag["CompressBlk"] = 512] = "CompressBlk";
206
- /** Don't compress */
207
- FileFlag[FileFlag["NoCompress"] = 1024] = "NoCompress";
208
- // End compression flags --- maybe not all used
209
- /** Encrypted file */
210
- FileFlag[FileFlag["Encrypt"] = 2048] = "Encrypt";
211
- /** btree format dir */
212
- FileFlag[FileFlag["Btree"] = 4096] = "Btree";
213
- /** hash-indexed directory */
214
- // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
215
- FileFlag[FileFlag["Index"] = 4096] = "Index";
216
- /** AFS directory */
217
- FileFlag[FileFlag["IMagic"] = 8192] = "IMagic";
218
- /** Reserved for ext3 */
219
- FileFlag[FileFlag["JournalData"] = 16384] = "JournalData";
220
- /** file tail should not be merged */
221
- FileFlag[FileFlag["NoTail"] = 32768] = "NoTail";
222
- /** dirsync behaviour (directories only) */
223
- FileFlag[FileFlag["DirSync"] = 65536] = "DirSync";
224
- /** Top of directory hierarchies*/
225
- FileFlag[FileFlag["TopDir"] = 131072] = "TopDir";
226
- /** Reserved for ext4 */
227
- FileFlag[FileFlag["HugeFile"] = 262144] = "HugeFile";
228
- /** Extents */
229
- FileFlag[FileFlag["Extent"] = 524288] = "Extent";
230
- /** Verity protected inode */
231
- FileFlag[FileFlag["Verity"] = 1048576] = "Verity";
232
- /** Inode used for large EA */
233
- FileFlag[FileFlag["EaInode"] = 2097152] = "EaInode";
234
- /** Reserved for ext4 */
235
- FileFlag[FileFlag["EofBlocks"] = 4194304] = "EofBlocks";
236
- /** Do not cow file */
237
- FileFlag[FileFlag["NoCow"] = 8388608] = "NoCow";
238
- /** Inode is DAX */
239
- FileFlag[FileFlag["Dax"] = 33554432] = "Dax";
240
- /** Reserved for ext4 */
241
- FileFlag[FileFlag["InlineData"] = 268435456] = "InlineData";
242
- /** Create with parents projid */
243
- FileFlag[FileFlag["ProjInherit"] = 536870912] = "ProjInherit";
244
- /** Folder is case insensitive */
245
- FileFlag[FileFlag["CaseFold"] = 1073741824] = "CaseFold";
246
- /** reserved for ext2 lib */
247
- FileFlag[FileFlag["Reserved"] = 2147483648] = "Reserved";
248
- })(FileFlag || (FileFlag = {}));
249
- /**
250
- * `FS_IOC_*` commands for {@link ioctl | `ioctl`}
251
- * @remarks
252
- * These are computed from a script since constant values are needed for enum member types
253
- */
254
- export var IOC;
255
- (function (IOC) {
256
- IOC[IOC["GetFlags"] = 2148034049] = "GetFlags";
257
- IOC[IOC["SetFlags"] = 1074292226] = "SetFlags";
258
- IOC[IOC["GetVersion"] = 2148038145] = "GetVersion";
259
- IOC[IOC["SetVersion"] = 1074296322] = "SetVersion";
260
- IOC[IOC["Fiemap"] = 3223348747] = "Fiemap";
261
- IOC[IOC["GetXattr"] = 2149341215] = "GetXattr";
262
- IOC[IOC["SetXattr"] = 1075599392] = "SetXattr";
263
- IOC[IOC["GetLabel"] = 2164298801] = "GetLabel";
264
- IOC[IOC["SetLabel"] = 1090556978] = "SetLabel";
265
- IOC[IOC["GetUUID"] = 2148603136] = "GetUUID";
266
- IOC[IOC["GetSysfsPath"] = 2155943169] = "GetSysfsPath";
267
- })(IOC || (IOC = {}));
268
- /**
269
- * `FS_IOC32_*` commands for {@link ioctl | `ioctl`}
270
- * @remarks
271
- * These are computed from a script since constant values are needed for enum member types
272
- */
273
- export var IOC32;
274
- (function (IOC32) {
275
- IOC32[IOC32["GetFlags"] = 2147771905] = "GetFlags";
276
- IOC32[IOC32["SetFlags"] = 1074030082] = "SetFlags";
277
- IOC32[IOC32["GetVersion"] = 2147776001] = "GetVersion";
278
- IOC32[IOC32["SetVersion"] = 1074034178] = "SetVersion";
279
- })(IOC32 || (IOC32 = {}));
280
- /** Perform an `ioctl` on a file or file system. */
281
- export async function ioctl(
282
- /** The path to the file or file system to perform the `ioctl` on */
283
- path,
284
- /** The command to perform (uint32) */
285
- command,
286
- /** The arguments to pass to the command */
287
- ...args) {
288
- path = normalizePath(path);
289
- const { fs, path: resolved } = resolveMount(path, this);
18
+ export async function ioctl(path, command, ...args) {
19
+ let vcache, vnode, file;
20
+ if (typeof path == 'number') {
21
+ file = fromFD(this, path);
22
+ vcache = cacheOf(file.fs);
23
+ vnode = file.vnode;
24
+ // In the future we may need to use `vcache.ref(...)`
25
+ // For now this avoids some issues: touching vnode.paths, triggering the "referenced by more paths" error, and inode assignment
26
+ vnode.refs++;
27
+ }
28
+ else {
29
+ path = normalizePath(path);
30
+ const mnt = await resolveAsync(this, path, false, { syscall: 'ioctl', path });
31
+ if (!mnt.stats)
32
+ throw UV('ENOENT', { syscall: 'ioctl', path });
33
+ vcache = cacheOf(mnt.fs);
34
+ vnode = vcache.ref(mnt.path, vcache.get(mnt.path)?.inode ?? mnt.stats);
35
+ }
36
+ const context = {
37
+ fs: vnode.fs,
38
+ inode: vnode.inode,
39
+ path: vnode.path,
40
+ file,
41
+ };
290
42
  try {
291
- const inode = new Inode(await fs.stat(resolved));
292
- switch (command) {
293
- case IOC.GetFlags:
294
- case IOC32.GetFlags:
295
- return inode.flags;
296
- case IOC.SetFlags:
297
- case IOC32.SetFlags:
298
- inode.flags = args[0];
299
- await fs.touch(resolved, inode);
300
- return undefined;
301
- case IOC.GetVersion:
302
- case IOC32.GetVersion:
303
- return inode.version;
304
- case IOC.SetVersion:
305
- case IOC32.SetVersion:
306
- inode.version = args[0];
307
- await fs.touch(resolved, inode);
308
- return undefined;
309
- case IOC.Fiemap:
310
- break;
311
- case IOC.GetXattr:
312
- return new fsxattr(inode);
313
- case IOC.SetXattr:
314
- break;
315
- case IOC.GetLabel:
316
- return fs.label;
317
- case IOC.SetLabel:
318
- fs.label = args[0];
319
- return undefined;
320
- case IOC.GetUUID:
321
- return fs.uuid;
322
- case IOC.GetSysfsPath:
323
- /**
324
- * Returns the path component under /sys/fs/ that refers to this filesystem;
325
- * also /sys/kernel/debug/ for filesystems with debugfs exports
326
- * @todo Implement sysfs and have each FS implement the /sys/fs/<name> tree
327
- */
328
- return `/sys/fs/${fs.name}/${fs.uuid}`;
329
- }
43
+ return await vnode.fs.ioctl(context, command, ...args);
330
44
  }
331
45
  catch (e) {
332
46
  throw setUVMessage(Object.assign(e, { syscall: 'ioctl', path }));
333
47
  }
334
- throw UV('ENOTSUP', 'ioctl', path);
48
+ finally {
49
+ vcache.unref(vnode);
50
+ }
335
51
  }
336
- /** Perform an `ioctl` on a file or file system */
337
- export function ioctlSync(
338
- /** The path to the file or file system to perform the `ioctl` on */
339
- path,
340
- /** The command to perform (uint32) */
341
- command,
342
- /** The arguments to pass to the command */
343
- ...args) {
344
- path = normalizePath(path);
345
- const { fs, path: resolved } = resolveMount(path, this);
52
+ /**
53
+ * Perform an `ioctl` on a file or file system
54
+ * @category ioctl
55
+ */
56
+ export function ioctlSync(path, command, ...args) {
57
+ let vcache, vnode, file;
58
+ if (typeof path == 'number') {
59
+ file = fromFD(this, path);
60
+ vcache = cacheOf(file.fs);
61
+ vnode = file.vnode;
62
+ // In the future we may need to use `vcache.ref(...)`
63
+ // For now this avoids some issues: touching vnode.paths, triggering the "referenced by more paths" error, and inode assignment
64
+ vnode.refs++;
65
+ }
66
+ else {
67
+ path = normalizePath(path);
68
+ const mnt = resolveSync(this, path, false, { syscall: 'ioctl', path });
69
+ if (!mnt.stats)
70
+ throw UV('ENOENT', { syscall: 'ioctl', path });
71
+ vcache = cacheOf(mnt.fs);
72
+ vnode = vcache.ref(mnt.path, vcache.get(mnt.path)?.inode ?? mnt.stats);
73
+ }
74
+ const context = {
75
+ fs: vnode.fs,
76
+ inode: vnode.inode,
77
+ path: vnode.path,
78
+ file,
79
+ };
346
80
  try {
347
- const inode = new Inode(fs.statSync(resolved));
348
- switch (command) {
349
- case IOC.GetFlags:
350
- case IOC32.GetFlags:
351
- return inode.flags;
352
- case IOC.SetFlags:
353
- case IOC32.SetFlags:
354
- inode.flags = args[0];
355
- fs.touchSync(resolved, inode);
356
- return undefined;
357
- case IOC.GetVersion:
358
- case IOC32.GetVersion:
359
- return inode.version;
360
- case IOC.SetVersion:
361
- case IOC32.SetVersion:
362
- inode.version = args[0];
363
- fs.touchSync(resolved, inode);
364
- return undefined;
365
- case IOC.Fiemap:
366
- break;
367
- case IOC.GetXattr:
368
- return new fsxattr(inode);
369
- case IOC.SetXattr:
370
- break;
371
- case IOC.GetLabel:
372
- return fs.label;
373
- case IOC.SetLabel:
374
- fs.label = args[0];
375
- return undefined;
376
- case IOC.GetUUID:
377
- return fs.uuid;
378
- case IOC.GetSysfsPath:
379
- /**
380
- * Returns the path component under /sys/fs/ that refers to this filesystem;
381
- * also /sys/kernel/debug/ for filesystems with debugfs exports
382
- * @todo Implement sysfs and have each FS implement the /sys/fs/<name> tree
383
- */
384
- return `/sys/fs/${fs.name}/${fs.uuid}`;
385
- }
81
+ return vnode.fs.ioctlSync(context, command, ...args);
386
82
  }
387
83
  catch (e) {
388
84
  throw setUVMessage(Object.assign(e, { syscall: 'ioctl', path }));
389
85
  }
390
- throw UV('ENOTSUP', 'ioctl', path);
86
+ finally {
87
+ vcache.unref(vnode);
88
+ }
391
89
  }
@@ -12,6 +12,8 @@ export type MountObject = Record<AbsolutePath, FileSystem>;
12
12
  * The map of mount points
13
13
  * @category Backends and Configuration
14
14
  * @internal
15
+ * @deprecated Use `defaultContext.mounts`.
16
+ * @todo [breaking] remove this
15
17
  */
16
18
  export declare const mounts: Map<string, FileSystem>;
17
19
  /**
@@ -4,7 +4,7 @@ import { Errno, Exception, UV, withErrno } from 'kerium';
4
4
  import { alert, debug, err, info, notice, warn } from 'kerium/log';
5
5
  import { InMemory } from '../backends/memory.js';
6
6
  import { size_max } from '../constants.js';
7
- import { contextOf } from '../internal/contexts.js';
7
+ import { contextOf, defaultContext } from '../internal/contexts.js';
8
8
  import { credentialsAllowRoot } from '../internal/credentials.js';
9
9
  import { withExceptionContext } from '../internal/error.js';
10
10
  import { join, resolve } from '../path.js';
@@ -14,8 +14,10 @@ import { caches, VCache } from './vcache.js';
14
14
  * The map of mount points
15
15
  * @category Backends and Configuration
16
16
  * @internal
17
+ * @deprecated Use `defaultContext.mounts`.
18
+ * @todo [breaking] remove this
17
19
  */
18
- export const mounts = new Map();
20
+ export const mounts = defaultContext.mounts;
19
21
  // Set a default root.
20
22
  mount('/', InMemory.create({ label: 'root' }));
21
23
  /**
@@ -24,13 +26,14 @@ mount('/', InMemory.create({ label: 'root' }));
24
26
  * @internal
25
27
  */
26
28
  export function mount(mountPoint, fs) {
29
+ const $ = contextOf(this);
27
30
  if (mountPoint[0] != '/')
28
31
  mountPoint = '/' + mountPoint;
29
- mountPoint = resolve.call(this, mountPoint);
30
- if (mounts.has(mountPoint))
32
+ mountPoint = resolve.call($, mountPoint);
33
+ if ($.mounts.has(mountPoint))
31
34
  throw err(withErrno('EINVAL', 'Mount point is already in use: ' + mountPoint));
32
35
  fs._mountPoint = mountPoint;
33
- mounts.set(mountPoint, fs);
36
+ $.mounts.set(mountPoint, fs);
34
37
  if (!caches.has(fs.uuid))
35
38
  caches.set(fs.uuid, new VCache(fs));
36
39
  info(`Mounted ${fs.name} on ${mountPoint}`);
@@ -42,10 +45,11 @@ export function mount(mountPoint, fs) {
42
45
  * @todo [BREAKING] make this `async` and `await` vcache sync
43
46
  */
44
47
  export function umount(mountPoint) {
48
+ const $ = contextOf(this);
45
49
  if (mountPoint[0] != '/')
46
50
  mountPoint = '/' + mountPoint;
47
51
  mountPoint = resolve.call(this, mountPoint);
48
- const fs = mounts.get(mountPoint);
52
+ const fs = $.mounts.get(mountPoint);
49
53
  if (!fs) {
50
54
  warn(mountPoint + ' is already unmounted');
51
55
  return;
@@ -62,7 +66,7 @@ export function umount(mountPoint) {
62
66
  warn(`Could not flush to ${mountPoint} synchronously.`);
63
67
  void caches.get(fs.uuid)?.sync().then(_done);
64
68
  }
65
- mounts.delete(mountPoint);
69
+ $.mounts.delete(mountPoint);
66
70
  notice('Unmounted ' + mountPoint);
67
71
  }
68
72
  /**
@@ -70,7 +74,7 @@ export function umount(mountPoint) {
70
74
  * @internal @hidden
71
75
  */
72
76
  export function resolveMount(path, ctx, extra) {
73
- const { root } = contextOf(ctx);
77
+ const { root, mounts } = contextOf(ctx);
74
78
  const _exceptionContext = { path, ...extra };
75
79
  path = normalizePath(join(root, path), true);
76
80
  path = resolve.call(ctx, path);
@@ -16,7 +16,7 @@ export declare function resolve($: V_Context, path: string, preserveSymlinks?: b
16
16
  * @category VFS
17
17
  * @internal
18
18
  */
19
- export declare function open(this: V_Context, path: PathLike, opt: OpenOptions): Handle;
19
+ export declare function open($: V_Context, path: PathLike, opt: OpenOptions): Handle;
20
20
  export declare function readlink(this: V_Context, path: PathLike): string;
21
21
  export declare function mkdir(this: V_Context, path: PathLike, options?: MkdirOptions): string | void;
22
22
  export declare function readdir(this: V_Context, path: PathLike, options?: ReaddirOptions): Dirent[];