@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.
@@ -0,0 +1,368 @@
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
+ import { Errno, Exception, withErrno } from 'kerium';
36
+ import { sizeof } from 'memium';
37
+ import { $from, struct, types as t } from 'memium/decorators';
38
+ import { _throw } from 'utilium';
39
+ import { BufferView } from 'utilium/buffer';
40
+ import { InodeFlags } from './inode.js';
41
+ /*
42
+ * Flags for the fsxattr.xflags field
43
+ */
44
+ var XFlag;
45
+ (function (XFlag) {
46
+ /** data in realtime volume */
47
+ XFlag[XFlag["RealTime"] = 1] = "RealTime";
48
+ /** preallocated file extents */
49
+ XFlag[XFlag["PreAlloc"] = 2] = "PreAlloc";
50
+ /** file cannot be modified */
51
+ XFlag[XFlag["Immutable"] = 8] = "Immutable";
52
+ /** all writes append */
53
+ XFlag[XFlag["Append"] = 16] = "Append";
54
+ /** all writes synchronous */
55
+ XFlag[XFlag["Sync"] = 32] = "Sync";
56
+ /** do not update access time */
57
+ XFlag[XFlag["NoAtime"] = 64] = "NoAtime";
58
+ /** do not include in backups */
59
+ XFlag[XFlag["NoDump"] = 128] = "NoDump";
60
+ /** create with rt bit set */
61
+ XFlag[XFlag["RtInherit"] = 256] = "RtInherit";
62
+ /** create with parents projid */
63
+ XFlag[XFlag["ProjInherit"] = 512] = "ProjInherit";
64
+ /** disallow symlink creation */
65
+ XFlag[XFlag["NoSymlinks"] = 1024] = "NoSymlinks";
66
+ /** extent size allocator hint */
67
+ XFlag[XFlag["ExtSize"] = 2048] = "ExtSize";
68
+ /** inherit inode extent size */
69
+ XFlag[XFlag["ExtSzInherit"] = 4096] = "ExtSzInherit";
70
+ /** do not defragment */
71
+ XFlag[XFlag["NoDefrag"] = 8192] = "NoDefrag";
72
+ /** use filestream allocator */
73
+ XFlag[XFlag["FileStream"] = 16384] = "FileStream";
74
+ /** use DAX for IO */
75
+ XFlag[XFlag["Dax"] = 32768] = "Dax";
76
+ /** CoW extent size allocator hint */
77
+ XFlag[XFlag["CowExtSize"] = 65536] = "CowExtSize";
78
+ /** no DIFLAG for this */
79
+ XFlag[XFlag["HasAttr"] = 2147483648] = "HasAttr";
80
+ })(XFlag || (XFlag = {}));
81
+ let fsxattr = (() => {
82
+ var _a, _b, _c, _d, _e;
83
+ let _classDecorators = [struct()];
84
+ let _classDescriptor;
85
+ let _classExtraInitializers = [];
86
+ let _classThis;
87
+ let _classSuper = $from(BufferView);
88
+ let _xflags_decorators;
89
+ let _xflags_initializers = [];
90
+ let _xflags_extraInitializers = [];
91
+ let _extsize_decorators;
92
+ let _extsize_initializers = [];
93
+ let _extsize_extraInitializers = [];
94
+ let _nextents_decorators;
95
+ let _nextents_initializers = [];
96
+ let _nextents_extraInitializers = [];
97
+ let _projid_decorators;
98
+ let _projid_initializers = [];
99
+ let _projid_extraInitializers = [];
100
+ let _cowextsize_decorators;
101
+ let _cowextsize_initializers = [];
102
+ let _cowextsize_extraInitializers = [];
103
+ let _pad_decorators;
104
+ let _pad_initializers = [];
105
+ let _pad_extraInitializers = [];
106
+ var fsxattr = class extends _classSuper {
107
+ static { _classThis = this; }
108
+ static {
109
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
110
+ _xflags_decorators = [(_a = t).uint32.bind(_a)];
111
+ _extsize_decorators = [(_b = t).uint32.bind(_b)];
112
+ _nextents_decorators = [(_c = t).uint32.bind(_c)];
113
+ _projid_decorators = [(_d = t).uint32.bind(_d)];
114
+ _cowextsize_decorators = [(_e = t).uint32.bind(_e)];
115
+ _pad_decorators = [t.char(8)];
116
+ __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);
117
+ __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);
118
+ __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);
119
+ __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);
120
+ __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);
121
+ __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);
122
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
123
+ fsxattr = _classThis = _classDescriptor.value;
124
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
125
+ }
126
+ static name = 'fsxattr';
127
+ #xflags_accessor_storage = __runInitializers(this, _xflags_initializers, void 0);
128
+ /** xflags field value */
129
+ get xflags() { return this.#xflags_accessor_storage; }
130
+ set xflags(value) { this.#xflags_accessor_storage = value; }
131
+ #extsize_accessor_storage = (__runInitializers(this, _xflags_extraInitializers), __runInitializers(this, _extsize_initializers, void 0));
132
+ /** extsize field value */
133
+ get extsize() { return this.#extsize_accessor_storage; }
134
+ set extsize(value) { this.#extsize_accessor_storage = value; }
135
+ #nextents_accessor_storage = (__runInitializers(this, _extsize_extraInitializers), __runInitializers(this, _nextents_initializers, void 0));
136
+ /** nextents field value */
137
+ get nextents() { return this.#nextents_accessor_storage; }
138
+ set nextents(value) { this.#nextents_accessor_storage = value; }
139
+ #projid_accessor_storage = (__runInitializers(this, _nextents_extraInitializers), __runInitializers(this, _projid_initializers, void 0));
140
+ /** project identifier */
141
+ get projid() { return this.#projid_accessor_storage; }
142
+ set projid(value) { this.#projid_accessor_storage = value; }
143
+ #cowextsize_accessor_storage = (__runInitializers(this, _projid_extraInitializers), __runInitializers(this, _cowextsize_initializers, void 0));
144
+ /** CoW extsize field value */
145
+ get cowextsize() { return this.#cowextsize_accessor_storage; }
146
+ set cowextsize(value) { this.#cowextsize_accessor_storage = value; }
147
+ #pad_accessor_storage = (__runInitializers(this, _cowextsize_extraInitializers), __runInitializers(this, _pad_initializers, []));
148
+ get pad() { return this.#pad_accessor_storage; }
149
+ set pad(value) { this.#pad_accessor_storage = value; }
150
+ constructor(inode = _throw(new Exception(Errno.EINVAL, 'fsxattr must be initialized with an inode'))) {
151
+ super(new ArrayBuffer(sizeof(fsxattr)));
152
+ __runInitializers(this, _pad_extraInitializers);
153
+ this.extsize = inode.size;
154
+ this.nextents = 1;
155
+ this.projid = inode.uid;
156
+ this.cowextsize = inode.size;
157
+ for (const name of Object.keys(InodeFlags)) {
158
+ if (!((inode.flags || 0) & InodeFlags[name]))
159
+ continue;
160
+ if (name in XFlag)
161
+ this.xflags |= XFlag[name];
162
+ }
163
+ }
164
+ static {
165
+ __runInitializers(_classThis, _classExtraInitializers);
166
+ }
167
+ };
168
+ return fsxattr = _classThis;
169
+ })();
170
+ /**
171
+ * Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS)
172
+ * @see `FS_*_FL` in `include/uapi/linux/fs.h` (around L250)
173
+ * @experimental
174
+ */
175
+ var FileFlag;
176
+ (function (FileFlag) {
177
+ /** Secure deletion */
178
+ FileFlag[FileFlag["SecureRm"] = 1] = "SecureRm";
179
+ /** Undelete */
180
+ FileFlag[FileFlag["Undelete"] = 2] = "Undelete";
181
+ /** Compress file */
182
+ FileFlag[FileFlag["Compress"] = 4] = "Compress";
183
+ /** Synchronous updates */
184
+ FileFlag[FileFlag["Sync"] = 8] = "Sync";
185
+ /** Immutable file */
186
+ FileFlag[FileFlag["Immutable"] = 16] = "Immutable";
187
+ /** Writes to file may only append */
188
+ FileFlag[FileFlag["Append"] = 32] = "Append";
189
+ /** do not dump file */
190
+ FileFlag[FileFlag["NoDump"] = 64] = "NoDump";
191
+ /** do not update atime */
192
+ FileFlag[FileFlag["NoAtime"] = 128] = "NoAtime";
193
+ // Reserved for compression usage...
194
+ FileFlag[FileFlag["Dirty"] = 256] = "Dirty";
195
+ /** One or more compressed clusters */
196
+ FileFlag[FileFlag["CompressBlk"] = 512] = "CompressBlk";
197
+ /** Don't compress */
198
+ FileFlag[FileFlag["NoCompress"] = 1024] = "NoCompress";
199
+ // End compression flags --- maybe not all used
200
+ /** Encrypted file */
201
+ FileFlag[FileFlag["Encrypt"] = 2048] = "Encrypt";
202
+ /** btree format dir */
203
+ FileFlag[FileFlag["Btree"] = 4096] = "Btree";
204
+ /** hash-indexed directory */
205
+ // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
206
+ FileFlag[FileFlag["Index"] = 4096] = "Index";
207
+ /** AFS directory */
208
+ FileFlag[FileFlag["IMagic"] = 8192] = "IMagic";
209
+ /** Reserved for ext3 */
210
+ FileFlag[FileFlag["JournalData"] = 16384] = "JournalData";
211
+ /** file tail should not be merged */
212
+ FileFlag[FileFlag["NoTail"] = 32768] = "NoTail";
213
+ /** dirsync behaviour (directories only) */
214
+ FileFlag[FileFlag["DirSync"] = 65536] = "DirSync";
215
+ /** Top of directory hierarchies*/
216
+ FileFlag[FileFlag["TopDir"] = 131072] = "TopDir";
217
+ /** Reserved for ext4 */
218
+ FileFlag[FileFlag["HugeFile"] = 262144] = "HugeFile";
219
+ /** Extents */
220
+ FileFlag[FileFlag["Extent"] = 524288] = "Extent";
221
+ /** Verity protected inode */
222
+ FileFlag[FileFlag["Verity"] = 1048576] = "Verity";
223
+ /** Inode used for large EA */
224
+ FileFlag[FileFlag["EaInode"] = 2097152] = "EaInode";
225
+ /** Reserved for ext4 */
226
+ FileFlag[FileFlag["EofBlocks"] = 4194304] = "EofBlocks";
227
+ /** Do not cow file */
228
+ FileFlag[FileFlag["NoCow"] = 8388608] = "NoCow";
229
+ /** Inode is DAX */
230
+ FileFlag[FileFlag["Dax"] = 33554432] = "Dax";
231
+ /** Reserved for ext4 */
232
+ FileFlag[FileFlag["InlineData"] = 268435456] = "InlineData";
233
+ /** Create with parents projid */
234
+ FileFlag[FileFlag["ProjInherit"] = 536870912] = "ProjInherit";
235
+ /** Folder is case insensitive */
236
+ FileFlag[FileFlag["CaseFold"] = 1073741824] = "CaseFold";
237
+ /** reserved for ext2 lib */
238
+ FileFlag[FileFlag["Reserved"] = 2147483648] = "Reserved";
239
+ })(FileFlag || (FileFlag = {}));
240
+ /**
241
+ * `FS_IOC_*` commands for {@link ioctl | `ioctl`}
242
+ * @remarks
243
+ * These are computed from a script since constant values are needed for enum member types
244
+ */
245
+ export var IOC;
246
+ (function (IOC) {
247
+ IOC[IOC["GetFlags"] = 2148034049] = "GetFlags";
248
+ IOC[IOC["SetFlags"] = 1074292226] = "SetFlags";
249
+ IOC[IOC["GetVersion"] = 2148038145] = "GetVersion";
250
+ IOC[IOC["SetVersion"] = 1074296322] = "SetVersion";
251
+ IOC[IOC["Fiemap"] = 3223348747] = "Fiemap";
252
+ IOC[IOC["GetXattr"] = 2149341215] = "GetXattr";
253
+ IOC[IOC["SetXattr"] = 1075599392] = "SetXattr";
254
+ IOC[IOC["GetLabel"] = 2164298801] = "GetLabel";
255
+ IOC[IOC["SetLabel"] = 1090556978] = "SetLabel";
256
+ IOC[IOC["GetUUID"] = 2148603136] = "GetUUID";
257
+ IOC[IOC["GetSysfsPath"] = 2155943169] = "GetSysfsPath";
258
+ })(IOC || (IOC = {}));
259
+ /**
260
+ * `FS_IOC32_*` commands for {@link ioctl | `ioctl`}
261
+ * @remarks
262
+ * These are computed from a script since constant values are needed for enum member types
263
+ */
264
+ export var IOC32;
265
+ (function (IOC32) {
266
+ IOC32[IOC32["GetFlags"] = 2147771905] = "GetFlags";
267
+ IOC32[IOC32["SetFlags"] = 1074030082] = "SetFlags";
268
+ IOC32[IOC32["GetVersion"] = 2147776001] = "GetVersion";
269
+ IOC32[IOC32["SetVersion"] = 1074034178] = "SetVersion";
270
+ })(IOC32 || (IOC32 = {}));
271
+ /**
272
+ * @internal
273
+ * @category ioctl
274
+ */
275
+ export const ioctl_default_ops = {
276
+ [IOC.GetFlags]($) {
277
+ if (typeof $.inode.flags !== 'number')
278
+ throw withErrno('ENOTTY');
279
+ return $.inode.flags;
280
+ },
281
+ [IOC32.GetFlags]($) {
282
+ if (typeof $.inode.flags !== 'number')
283
+ throw withErrno('ENOTTY');
284
+ return $.inode.flags;
285
+ },
286
+ [IOC.GetVersion]($) {
287
+ if (typeof $.inode.version !== 'number')
288
+ throw withErrno('ENOTTY');
289
+ return $.inode.version;
290
+ },
291
+ [IOC32.GetVersion]($) {
292
+ if (typeof $.inode.version !== 'number')
293
+ throw withErrno('ENOTTY');
294
+ return $.inode.version;
295
+ },
296
+ [IOC.Fiemap]() {
297
+ throw withErrno('ENOTSUP');
298
+ },
299
+ [IOC.GetXattr]($, _name) {
300
+ return new fsxattr($.inode);
301
+ },
302
+ [IOC.SetXattr]($, _name, _value) {
303
+ throw withErrno('ENOTSUP');
304
+ },
305
+ [IOC.GetLabel]($) {
306
+ return $.fs.label;
307
+ },
308
+ [IOC.SetLabel]($, label) {
309
+ $.fs.label = label;
310
+ },
311
+ [IOC.GetUUID]($) {
312
+ return $.fs.uuid;
313
+ },
314
+ [IOC.GetSysfsPath]($) {
315
+ /**
316
+ * Returns the path component under /sys/fs/ that refers to this filesystem;
317
+ * also /sys/kernel/debug/ for filesystems with debugfs exports
318
+ * @todo Implement sysfs and have each FS implement the /sys/fs/<name> tree
319
+ */
320
+ return `/sys/fs/${$.fs.name}/${$.fs.uuid}`;
321
+ },
322
+ };
323
+ /**
324
+ * @internal
325
+ * @category ioctl
326
+ */
327
+ export const ioctl_default_ops_async = {
328
+ ...ioctl_default_ops,
329
+ async [IOC.SetFlags]($, flags) {
330
+ $.inode.flags = flags;
331
+ await $.fs.touch($.path, $.inode);
332
+ },
333
+ async [IOC32.SetFlags]($, flags) {
334
+ $.inode.flags = flags;
335
+ await $.fs.touch($.path, $.inode);
336
+ },
337
+ async [IOC.SetVersion]($, version) {
338
+ $.inode.version = version;
339
+ await $.fs.touch($.path, $.inode);
340
+ },
341
+ async [IOC32.SetVersion]($, version) {
342
+ $.inode.version = version;
343
+ await $.fs.touch($.path, $.inode);
344
+ },
345
+ };
346
+ /**
347
+ * @internal
348
+ * @category ioctl
349
+ */
350
+ export const ioctl_default_ops_sync = {
351
+ ...ioctl_default_ops,
352
+ [IOC.SetFlags]($, flags) {
353
+ $.inode.flags = flags;
354
+ $.fs.touchSync($.path, $.inode);
355
+ },
356
+ [IOC32.SetFlags]($, flags) {
357
+ $.inode.flags = flags;
358
+ $.fs.touchSync($.path, $.inode);
359
+ },
360
+ [IOC.SetVersion]($, version) {
361
+ $.inode.version = version;
362
+ $.fs.touchSync($.path, $.inode);
363
+ },
364
+ [IOC32.SetVersion]($, version) {
365
+ $.inode.version = version;
366
+ $.fs.touchSync($.path, $.inode);
367
+ },
368
+ };
@@ -1,9 +1,10 @@
1
- import { _asyncFSKeys } from './shared.js';
1
+ // SPDX-License-Identifier: LGPL-3.0-or-later
2
2
  import { withErrno } from 'kerium';
3
3
  import { crit, debug, err } from 'kerium/log';
4
4
  import { StoreFS } from '../backends/store/fs.js';
5
5
  import { isDirectory } from '../internal/inode.js';
6
6
  import { join } from '../path.js';
7
+ import { _asyncFSKeys } from './shared.js';
7
8
  /**
8
9
  * Async() implements synchronous methods on an asynchronous file system
9
10
  *
@@ -143,6 +144,10 @@ export function Async(FS) {
143
144
  this._sync.writeSync(path, buffer, offset);
144
145
  this._async(() => this.write(path, buffer, offset));
145
146
  }
147
+ ioctlSync(context, command, ...args) {
148
+ this.checkSync();
149
+ return this._sync.ioctlSync(context, command, ...args);
150
+ }
146
151
  streamWrite(path, options) {
147
152
  this.checkSync();
148
153
  const sync = this._sync.streamWrite(path, options).getWriter();
@@ -2,6 +2,7 @@ import type { UUID } from 'node:crypto';
2
2
  import type { Concrete } from 'utilium';
3
3
  import type { CreationOptions, FileSystem, StreamOptions, UsageInfo } from '../internal/filesystem.js';
4
4
  import type { InodeLike } from '../internal/inode.js';
5
+ import type { IoctlContext } from '../internal/ioctl.js';
5
6
  import '../polyfills.js';
6
7
  /**
7
8
  * @category Internals
@@ -90,6 +91,8 @@ export declare class _MutexedFS<T extends FileSystem> implements FileSystem {
90
91
  writeSync(path: string, buffer: Uint8Array, offset: number): void;
91
92
  streamRead(path: string, options: StreamOptions): ReadableStream;
92
93
  streamWrite(path: string, options: StreamOptions): WritableStream;
94
+ ioctl(context: IoctlContext, command: number, ...args: any[]): Promise<any>;
95
+ ioctlSync(context: IoctlContext, command: number, ...args: any[]): any;
93
96
  }
94
97
  /**
95
98
  * This serializes access to an underlying async filesystem.
@@ -50,6 +50,7 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
50
50
  var e = new Error(message);
51
51
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
52
  });
53
+ // SPDX-License-Identifier: LGPL-3.0-or-later
53
54
  import { withErrno } from 'kerium';
54
55
  import { err } from 'kerium/log';
55
56
  import '../polyfills.js';
@@ -170,7 +171,6 @@ export class _MutexedFS {
170
171
  get isLocked() {
171
172
  return !!this.currentLock?.isLocked;
172
173
  }
173
- /* eslint-disable @typescript-eslint/no-unused-vars */
174
174
  async rename(oldPath, newPath) {
175
175
  const env_1 = { stack: [], error: void 0, hasError: false };
176
176
  try {
@@ -563,6 +563,34 @@ export class _MutexedFS {
563
563
  __disposeResources(env_28);
564
564
  }
565
565
  }
566
+ async ioctl(context, command, ...args) {
567
+ const env_29 = { stack: [], error: void 0, hasError: false };
568
+ try {
569
+ const _ = __addDisposableResource(env_29, await this.lock(), false);
570
+ return await this._fs.ioctl({ ...context, fs: this._fs }, command, ...args);
571
+ }
572
+ catch (e_29) {
573
+ env_29.error = e_29;
574
+ env_29.hasError = true;
575
+ }
576
+ finally {
577
+ __disposeResources(env_29);
578
+ }
579
+ }
580
+ ioctlSync(context, command, ...args) {
581
+ const env_30 = { stack: [], error: void 0, hasError: false };
582
+ try {
583
+ const _ = __addDisposableResource(env_30, this.lockSync(), false);
584
+ return this._fs.ioctlSync({ ...context, fs: this._fs }, command, ...args);
585
+ }
586
+ catch (e_30) {
587
+ env_30.error = e_30;
588
+ env_30.hasError = true;
589
+ }
590
+ finally {
591
+ __disposeResources(env_30);
592
+ }
593
+ }
566
594
  }
567
595
  /**
568
596
  * This serializes access to an underlying async filesystem.
@@ -18,7 +18,7 @@ export type _SyncFSKeys = Exclude<Extract<keyof FileSystem, `${string}Sync`>, '_
18
18
  export type _AsyncFSKeys = {
19
19
  [K in _SyncFSKeys]: K extends `${infer T}Sync` ? T : never;
20
20
  }[_SyncFSKeys];
21
- export declare const _asyncFSKeys: ["rename", "stat", "touch", "createFile", "unlink", "rmdir", "mkdir", "readdir", "exists", "link", "sync", "read", "write"];
21
+ export declare const _asyncFSKeys: ["rename", "stat", "touch", "createFile", "unlink", "rmdir", "mkdir", "readdir", "exists", "link", "sync", "read", "write", "ioctl"];
22
22
  /**
23
23
  * Asynchronous `FileSystem` methods. This is a convenience type for all of the async operations.
24
24
  * @category Internals
@@ -13,4 +13,5 @@ export const _asyncFSKeys = [
13
13
  'sync',
14
14
  'read',
15
15
  'write',
16
+ 'ioctl',
16
17
  ];
@@ -44,6 +44,9 @@ export function Sync(FS) {
44
44
  async write(path, buffer, offset) {
45
45
  return this.writeSync(path, buffer, offset);
46
46
  }
47
+ async ioctl(context, command, ...args) {
48
+ return this.ioctlSync(context, command, ...args);
49
+ }
47
50
  }
48
51
  return SyncFS;
49
52
  }
package/dist/node/sync.js CHANGED
@@ -117,7 +117,7 @@ lstatSync;
117
117
  export function truncateSync(path, len = 0) {
118
118
  const env_1 = { stack: [], error: void 0, hasError: false };
119
119
  try {
120
- const file = __addDisposableResource(env_1, _sync.open.call(this, path, { flag: 'r+' }), false);
120
+ const file = __addDisposableResource(env_1, _sync.open(this, path, { flag: 'r+' }), false);
121
121
  len ||= 0;
122
122
  if (len < 0)
123
123
  throw UV('EINVAL', 'truncate', path.toString());
@@ -165,7 +165,7 @@ unlinkSync;
165
165
  * @param flag {@link https://nodejs.org/api/fs.html#file-system-flags}
166
166
  */
167
167
  export function openSync(path, flag, mode = constants.F_OK) {
168
- return toFD(_sync.open.call(this, path, { flag, mode }));
168
+ return toFD(_sync.open(this, path, { flag, mode }));
169
169
  }
170
170
  openSync;
171
171
  /**
@@ -173,7 +173,7 @@ openSync;
173
173
  * @internal
174
174
  */
175
175
  export function lopenSync(path, flag, mode) {
176
- return toFD(_sync.open.call(this, path, { flag, mode, preserveSymlinks: true }));
176
+ return toFD(_sync.open(this, path, { flag, mode, preserveSymlinks: true }));
177
177
  }
178
178
  export function readFileSync(path, _options = {}) {
179
179
  const env_3 = { stack: [], error: void 0, hasError: false };
@@ -184,7 +184,7 @@ export function readFileSync(path, _options = {}) {
184
184
  throw UV('EBADF', 'read', path.toString());
185
185
  const file = __addDisposableResource(env_3, typeof path == 'number'
186
186
  ? fromFD(this, path)
187
- : _sync.open.call(this, path.toString(), { flag: options.flag, mode: 0o644, preserveSymlinks: false }), false);
187
+ : _sync.open(this, path.toString(), { flag: options.flag, mode: 0o644, preserveSymlinks: false }), false);
188
188
  const { size } = file.stat();
189
189
  const data = Buffer.alloc(size);
190
190
  file.readSync(data, 0, size, 0);
@@ -216,7 +216,7 @@ export function writeFileSync(path, data, _options = {}) {
216
216
  }
217
217
  const file = __addDisposableResource(env_4, typeof path == 'number'
218
218
  ? fromFD(this, path)
219
- : _sync.open.call(this, path.toString(), {
219
+ : _sync.open(this, path.toString(), {
220
220
  flag,
221
221
  mode: options.mode,
222
222
  }), false);
@@ -250,7 +250,7 @@ export function appendFileSync(filename, data, _options = {}) {
250
250
  const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
251
251
  const file = typeof filename == 'number'
252
252
  ? fromFD(this, filename)
253
- : _sync.open.call(this, normalizePath(filename), {
253
+ : _sync.open(this, normalizePath(filename), {
254
254
  flag,
255
255
  mode: options.mode,
256
256
  });
@@ -416,7 +416,7 @@ export function symlinkSync(target, path, type = 'file') {
416
416
  if (!['file', 'dir', 'junction'].includes(type))
417
417
  throw new TypeError('Invalid symlink type: ' + type);
418
418
  path = normalizePath(path);
419
- const file = __addDisposableResource(env_6, _sync.open.call(this, path, { flag: 'wx', mode: 0o644 }), false);
419
+ const file = __addDisposableResource(env_6, _sync.open(this, path, { flag: 'wx', mode: 0o644 }), false);
420
420
  file.writeSync(encodeUTF8(normalizePath(target, true)));
421
421
  file.chmodSync(constants.S_IFLNK);
422
422
  }
@@ -442,7 +442,7 @@ readlinkSync;
442
442
  export function chownSync(path, uid, gid) {
443
443
  const env_7 = { stack: [], error: void 0, hasError: false };
444
444
  try {
445
- const handle = __addDisposableResource(env_7, _sync.open.call(this, path, { flag: 'r+', mode: constants.F_OK }), false);
445
+ const handle = __addDisposableResource(env_7, _sync.open(this, path, { flag: 'r+', mode: constants.F_OK }), false);
446
446
  handle.chownSync(uid, gid);
447
447
  }
448
448
  catch (e_7) {
package/dist/vfs/async.js CHANGED
@@ -131,7 +131,7 @@ export async function open($, path, opt) {
131
131
  throw UV('EACCES', 'open', dirname(path));
132
132
  if (!isDirectory(parentStats))
133
133
  throw UV('ENOTDIR', 'open', dirname(path));
134
- if (!opt.allowDirectory && mode & constants.S_IFDIR)
134
+ if (!opt.allowDirectory && isDirectory({ mode }))
135
135
  throw UV('EISDIR', 'open', path);
136
136
  // Serialize entry creation with other operations on the parent directory
137
137
  const _ = __addDisposableResource(env_1, await lockPath(fs, parentPath, 'rw', parentStats), false);
@@ -161,7 +161,7 @@ export async function open($, path, opt) {
161
161
  throw UV('EACCES', $ex);
162
162
  if (flag & constants.O_EXCL)
163
163
  throw UV('EEXIST', $ex);
164
- if (!opt.allowDirectory && mode & constants.S_IFDIR)
164
+ if (!opt.allowDirectory && isDirectory({ mode }))
165
165
  throw UV('EISDIR', 'open', path);
166
166
  const handle = new Handle($, path, resolved, flag, cacheOf(fs).ref(resolved, stats));
167
167
  if (flag & constants.O_TRUNC)
package/dist/vfs/file.js CHANGED
@@ -675,7 +675,8 @@ export { Handle };
675
675
  */
676
676
  export function toFD(file) {
677
677
  const map = contextOf(file.context).descriptors;
678
- const fd = Math.max(map.size ? Math.max(...map.keys()) + 1 : 0, 4);
678
+ // @todo use `Iterator` helper #296
679
+ const fd = Array.from(map.keys()).reduce((next, k) => Math.max(next, k + 1), 4);
679
680
  map.set(fd, file);
680
681
  return fd;
681
682
  }