@zenfs/core 2.6.6 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node/sync.js CHANGED
@@ -76,7 +76,7 @@ renameSync;
76
76
  * Test whether or not `path` exists by checking with the file system.
77
77
  */
78
78
  export function existsSync(path) {
79
- path = normalizePath(path);
79
+ path = normalizePath.call(this, path);
80
80
  try {
81
81
  const { fs, path: resolvedPath } = _sync.resolve(this, path);
82
82
  return fs.existsSync(resolvedPath);
@@ -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());
@@ -133,7 +133,7 @@ export function truncateSync(path, len = 0) {
133
133
  }
134
134
  truncateSync;
135
135
  export function unlinkSync(path) {
136
- path = normalizePath(path);
136
+ path = normalizePath.call(this, path);
137
137
  const { fs, path: resolved } = resolveMount(path, this);
138
138
  try {
139
139
  const env_2 = { stack: [], error: void 0, hasError: false };
@@ -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.call(this, filename), {
254
254
  flag,
255
255
  mode: options.mode,
256
256
  });
@@ -354,7 +354,7 @@ futimesSync;
354
354
  export function rmdirSync(path) {
355
355
  const env_5 = { stack: [], error: void 0, hasError: false };
356
356
  try {
357
- path = normalizePath(path);
357
+ path = normalizePath.call(this, path);
358
358
  const { fs, path: resolved } = _sync.resolve(this, path);
359
359
  const stats = wrap(fs, 'statSync', { path, syscall: 'rmdir' })(resolved);
360
360
  if (!isDirectory(stats))
@@ -383,7 +383,7 @@ export function mkdirSync(path, options) {
383
383
  mkdirSync;
384
384
  export function readdirSync(path, options) {
385
385
  options = typeof options === 'object' ? options : { encoding: options };
386
- path = normalizePath(path);
386
+ path = normalizePath.call(this, path);
387
387
  const entries = [];
388
388
  const rawEntries = _sync.readdir.call(this, path, options ?? undefined);
389
389
  for (const raw of rawEntries) {
@@ -415,9 +415,9 @@ export function symlinkSync(target, path, type = 'file') {
415
415
  try {
416
416
  if (!['file', 'dir', 'junction'].includes(type))
417
417
  throw new TypeError('Invalid symlink type: ' + type);
418
- path = normalizePath(path);
419
- const file = __addDisposableResource(env_6, _sync.open.call(this, path, { flag: 'wx', mode: 0o644 }), false);
420
- file.writeSync(encodeUTF8(normalizePath(target, true)));
418
+ path = normalizePath.call(this, path);
419
+ const file = __addDisposableResource(env_6, _sync.open(this, path, { flag: 'wx', mode: 0o644 }), false);
420
+ file.writeSync(encodeUTF8(normalizePath.call(this, target, true)));
421
421
  file.chmodSync(constants.S_IFLNK);
422
422
  }
423
423
  catch (e_6) {
@@ -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) {
@@ -466,7 +466,7 @@ export function chmodSync(path, mode) {
466
466
  fd = openSync.call(this, path, 'r+');
467
467
  }
468
468
  catch (e) {
469
- throw setUVMessage(Object.assign(e, { syscall: 'chmod', path: normalizePath(path) }));
469
+ throw setUVMessage(Object.assign(e, { syscall: 'chmod', path: normalizePath.call(this, path) }));
470
470
  }
471
471
  fchmodSync.call(this, fd, mode);
472
472
  closeSync.call(this, fd);
@@ -498,7 +498,7 @@ export function lutimesSync(path, atime, mtime) {
498
498
  lutimesSync;
499
499
  export function realpathSync(path, options) {
500
500
  const encoding = typeof options == 'string' ? options : (options?.encoding ?? 'utf8');
501
- path = normalizePath(path, true);
501
+ path = normalizePath.call(this, path, true);
502
502
  const { fullPath } = _sync.resolve(this, path);
503
503
  if (encoding == 'utf8' || encoding == 'utf-8')
504
504
  return fullPath;
@@ -521,7 +521,7 @@ accessSync;
521
521
  * @param path The path to the file or directory to remove.
522
522
  */
523
523
  export function rmSync(path, options) {
524
- path = normalizePath(path);
524
+ path = normalizePath.call(this, path);
525
525
  let stats;
526
526
  try {
527
527
  stats = lstatSync.bind(this)(path);
@@ -580,8 +580,8 @@ export function mkdtempDisposableSync(prefix, options) {
580
580
  * - `fs.constants.COPYFILE_EXCL`: If the destination file already exists, the operation fails.
581
581
  */
582
582
  export function copyFileSync(source, destination, flags) {
583
- source = normalizePath(source);
584
- destination = normalizePath(destination);
583
+ source = normalizePath.call(this, source);
584
+ destination = normalizePath.call(this, destination);
585
585
  if (flags && flags & constants.COPYFILE_EXCL && existsSync.call(this, destination))
586
586
  throw UV('EEXIST', 'copyFile', destination);
587
587
  writeFileSync.call(this, destination, readFileSync.call(this, source));
@@ -628,7 +628,7 @@ writevSync;
628
628
  * @todo Handle options
629
629
  */
630
630
  export function opendirSync(path, options) {
631
- path = normalizePath(path);
631
+ path = normalizePath.call(this, path);
632
632
  return new Dir(path, this);
633
633
  }
634
634
  opendirSync;
@@ -645,8 +645,8 @@ opendirSync;
645
645
  * - `recursive`: If `true`, copies directories recursively.
646
646
  */
647
647
  export function cpSync(source, destination, opts) {
648
- source = normalizePath(source);
649
- destination = normalizePath(destination);
648
+ source = normalizePath.call(this, source);
649
+ destination = normalizePath.call(this, destination);
650
650
  const srcStats = lstatSync.call(this, source); // Use lstat to follow symlinks if not dereferencing
651
651
  if (opts?.errorOnExist && existsSync.call(this, destination))
652
652
  throw UV('EEXIST', 'cp', destination);
@@ -688,7 +688,7 @@ export function cpSync(source, destination, opts) {
688
688
  }
689
689
  cpSync;
690
690
  export function statfsSync(path, options) {
691
- path = normalizePath(path);
691
+ path = normalizePath.call(this, path);
692
692
  const { fs } = resolveMount(path, this);
693
693
  return _statfs(fs, options?.bigint);
694
694
  }
package/dist/vfs/async.js CHANGED
@@ -114,7 +114,7 @@ export async function resolve($, path, preserveSymlinks, extra) {
114
114
  * @internal
115
115
  */
116
116
  export async function open($, path, opt) {
117
- path = normalizePath(path);
117
+ path = normalizePath.call($, path);
118
118
  const mode = normalizeMode(opt.mode, 0o644), flag = flags.parse(opt.flag);
119
119
  const $ex = { syscall: 'open', path };
120
120
  // eslint-disable-next-line prefer-const
@@ -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)
@@ -169,7 +169,7 @@ export async function open($, path, opt) {
169
169
  return handle;
170
170
  }
171
171
  export async function readlink(path) {
172
- path = normalizePath(path);
172
+ path = normalizePath.call(this, path);
173
173
  const $ex = { syscall: 'readlink', path };
174
174
  const { fs, stats, path: resolved } = await resolve(this, path, true, $ex);
175
175
  if (!stats)
@@ -184,7 +184,7 @@ export async function readlink(path) {
184
184
  return decodeUTF8(data);
185
185
  }
186
186
  export async function mkdir(path, options = {}) {
187
- const original = normalizePath(path);
187
+ const original = normalizePath.call(this, path);
188
188
  const { euid: uid, egid: gid } = contextOf(this).credentials;
189
189
  const { mode = 0o777, recursive } = options;
190
190
  const $ex = { syscall: 'mkdir', path: original };
@@ -238,7 +238,7 @@ export async function mkdir(path, options = {}) {
238
238
  return firstCreated;
239
239
  }
240
240
  export async function readdir(path, options = {}) {
241
- path = normalizePath(path);
241
+ path = normalizePath.call(this, path);
242
242
  // Node reports `readdir` failures as `scandir`
243
243
  const $ex = { syscall: 'scandir', path };
244
244
  const { fs, path: resolved, stats } = await resolve(this, path, false, $ex);
@@ -290,8 +290,8 @@ export async function readdir(path, options = {}) {
290
290
  export async function rename(oldPath, newPath) {
291
291
  const env_4 = { stack: [], error: void 0, hasError: false };
292
292
  try {
293
- oldPath = normalizePath(oldPath);
294
- newPath = normalizePath(newPath);
293
+ oldPath = normalizePath.call(this, oldPath);
294
+ newPath = normalizePath.call(this, newPath);
295
295
  const $ex = { syscall: 'rename', path: oldPath, dest: newPath };
296
296
  const src = await resolve(this, oldPath, true, $ex);
297
297
  const dst = resolveMount(newPath, this, $ex);
@@ -344,8 +344,8 @@ export async function rename(oldPath, newPath) {
344
344
  export async function link(target, link) {
345
345
  const env_5 = { stack: [], error: void 0, hasError: false };
346
346
  try {
347
- target = normalizePath(target);
348
- link = normalizePath(link);
347
+ target = normalizePath.call(this, target);
348
+ link = normalizePath.call(this, link);
349
349
  const $ex = { syscall: 'link', path: target, dest: link };
350
350
  const { fs, path: resolved } = resolveMount(target, this, $ex);
351
351
  const dst = resolveMount(link, this, $ex);
@@ -45,6 +45,10 @@ export declare class Handle {
45
45
  * Whether the file is open or closed
46
46
  */
47
47
  protected closed: boolean;
48
+ /** How many descriptors refer to this open file */
49
+ protected refs: number;
50
+ /** Take another reference to the open file */
51
+ ref(): this;
48
52
  get isClosed(): boolean;
49
53
  /**
50
54
  * Creates a file handle for the vnode.
@@ -141,11 +145,17 @@ export declare class Handle {
141
145
  streamWrite(options: StreamOptions): WritableStream;
142
146
  }
143
147
  /**
148
+ * Give an open file a descriptor
144
149
  * @internal @hidden
145
150
  */
146
- export declare function toFD(file: Handle): number;
151
+ export declare function toFD(file: Handle, $?: V_Context): number;
147
152
  /**
148
153
  * @internal @hidden
149
154
  */
150
155
  export declare function fromFD($: V_Context, fd: number): Handle;
151
156
  export declare function deleteFD($: V_Context, fd: number): boolean;
157
+ /**
158
+ * Give an open file another descriptor
159
+ * @internal @hidden
160
+ */
161
+ export declare function dupFD($: V_Context, fd: number): number;
package/dist/vfs/file.js CHANGED
@@ -152,6 +152,15 @@ let Handle = (() => {
152
152
  * Whether the file is open or closed
153
153
  */
154
154
  closed = false;
155
+ /** How many descriptors refer to this open file */
156
+ refs = 1;
157
+ /** Take another reference to the open file */
158
+ ref() {
159
+ if (this.closed)
160
+ throw UV('EBADF', 'dup', this.path);
161
+ this.refs++;
162
+ return this;
163
+ }
155
164
  get isClosed() {
156
165
  return this.closed;
157
166
  }
@@ -199,6 +208,8 @@ let Handle = (() => {
199
208
  if (this.closed)
200
209
  throw UV('EBADF', 'close', this.path);
201
210
  this.syncSync();
211
+ if (--this.refs > 0)
212
+ return;
202
213
  this.disposeSync(true);
203
214
  }
204
215
  /**
@@ -406,6 +417,8 @@ let Handle = (() => {
406
417
  if (this.closed)
407
418
  throw UV('EBADF', 'close', this.path);
408
419
  await this.sync();
420
+ if (--this.refs > 0)
421
+ return;
409
422
  this.dispose(true);
410
423
  }
411
424
  /**
@@ -671,12 +684,14 @@ let Handle = (() => {
671
684
  export { Handle };
672
685
  // descriptors
673
686
  /**
687
+ * Give an open file a descriptor
674
688
  * @internal @hidden
675
689
  */
676
- export function toFD(file) {
677
- const map = contextOf(file.context).descriptors;
678
- // @todo use `Iterator` helper #296
679
- const fd = Array.from(map.keys()).reduce((max, k) => Math.max(max, k), 4);
690
+ export function toFD(file, $ = file.context) {
691
+ const map = contextOf($).descriptors;
692
+ let fd = 0;
693
+ while (map.has(fd))
694
+ fd++;
680
695
  map.set(fd, file);
681
696
  return fd;
682
697
  }
@@ -694,3 +709,10 @@ export function fromFD($, fd) {
694
709
  export function deleteFD($, fd) {
695
710
  return contextOf($).descriptors.delete(fd);
696
711
  }
712
+ /**
713
+ * Give an open file another descriptor
714
+ * @internal @hidden
715
+ */
716
+ export function dupFD($, fd) {
717
+ return toFD(fromFD($, fd).ref(), $);
718
+ }
@@ -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]>;