@zenfs/core 2.6.6 → 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.
@@ -9,7 +9,7 @@ export declare class InMemoryStore extends Map<number, Uint8Array> implements Sy
9
9
  readonly maxSize: number;
10
10
  readonly label?: string | undefined;
11
11
  readonly flags: readonly [];
12
- readonly name = "tmpfs";
12
+ readonly name: string;
13
13
  constructor(maxSize?: number, label?: string | undefined);
14
14
  sync(): Promise<void>;
15
15
  transaction(): SyncMapTransaction;
@@ -234,7 +234,7 @@ export class StoreFS extends FileSystem {
234
234
  const [path, ino] = queue.shift();
235
235
  const inode = new Inode(await tx.get(ino));
236
236
  index.set(path, inode);
237
- if (inode.mode & S_IFDIR) {
237
+ if (isDirectory(inode)) {
238
238
  const dir = decodeDirListing((await tx.get(inode.data)) ?? _throw(withErrno('ENODATA')));
239
239
  for (const [name, id] of Object.entries(dir)) {
240
240
  queue.push([join(path, name), id]);
@@ -265,7 +265,7 @@ export class StoreFS extends FileSystem {
265
265
  const [path, ino] = queue.shift();
266
266
  const inode = new Inode(tx.getSync(ino));
267
267
  index.set(path, inode);
268
- if (inode.mode & S_IFDIR) {
268
+ if (isDirectory(inode)) {
269
269
  const dir = decodeDirListing(tx.getSync(inode.data) ?? _throw(withErrno('ENODATA')));
270
270
  for (const [name, id] of Object.entries(dir)) {
271
271
  queue.push([join(path, name), id]);
@@ -780,7 +780,7 @@ export class StoreFS extends FileSystem {
780
780
  // Parse the raw data into our Inode object
781
781
  const inode = new Inode(inodeData);
782
782
  // If it is a directory and not yet visited, read its directory listing
783
- if ((inode.mode & S_IFDIR) != S_IFDIR || visitedDirectories.has(ino)) {
783
+ if (!isDirectory(inode) || visitedDirectories.has(ino)) {
784
784
  continue;
785
785
  }
786
786
  visitedDirectories.add(ino);
@@ -847,7 +847,7 @@ export class StoreFS extends FileSystem {
847
847
  continue;
848
848
  }
849
849
  const inode = new Inode(inodeData);
850
- if ((inode.mode & S_IFDIR) != S_IFDIR || visitedDirectories.has(ino)) {
850
+ if (!isDirectory(inode) || visitedDirectories.has(ino)) {
851
851
  continue;
852
852
  }
853
853
  visitedDirectories.add(ino);
package/dist/config.js CHANGED
@@ -7,7 +7,7 @@ import { FileSystem } from './internal/filesystem.js';
7
7
  import { exists, mkdir, stat } from './node/promises.js';
8
8
  import { existsSync, mkdirSync, statSync } from './node/sync.js';
9
9
  import { _setAccessChecks } from './vfs/config.js';
10
- import { mount, mounts, umount } from './vfs/shared.js';
10
+ import { mount, umount } from './vfs/shared.js';
11
11
  /**
12
12
  * Update the configuration of a file system.
13
13
  * @category Backends and Configuration
@@ -191,7 +191,7 @@ function mountWithMkdirSync(path, fs) {
191
191
  * @category Backends and Configuration
192
192
  */
193
193
  export function addDevice(driver, options) {
194
- const devfs = mounts.get('/dev');
194
+ const devfs = defaultContext.mounts.get('/dev');
195
195
  if (!(devfs instanceof DeviceFS))
196
196
  throw log.crit(withErrno('ENOTSUP', '/dev does not exist or is not a device file system'));
197
197
  return devfs._createDevice(driver, options);
@@ -223,10 +223,10 @@ export async function configure(configuration) {
223
223
  await mountWithMkdir(point, await resolveMountConfig(mountConfig));
224
224
  }
225
225
  }
226
- for (const fs of mounts.values()) {
226
+ for (const fs of defaultContext.mounts.values()) {
227
227
  configureFileSystem(fs, configuration);
228
228
  }
229
- if (configuration.addDevices && !mounts.has('/dev')) {
229
+ if (configuration.addDevices && !defaultContext.mounts.has('/dev')) {
230
230
  const devfs = new DeviceFS();
231
231
  devfs.addDefaults();
232
232
  await devfs.ready();
@@ -270,10 +270,10 @@ export function configureSync(configuration) {
270
270
  mountWithMkdirSync(point, resolveMountConfigSync(mountConfig));
271
271
  }
272
272
  }
273
- for (const fs of mounts.values()) {
273
+ for (const fs of defaultContext.mounts.values()) {
274
274
  configureFileSystem(fs, configuration);
275
275
  }
276
- if (configuration.addDevices && !mounts.has('/dev')) {
276
+ if (configuration.addDevices && !defaultContext.mounts.has('/dev')) {
277
277
  const devfs = new DeviceFS();
278
278
  devfs.addDefaults();
279
279
  devfs.readySync();
@@ -292,6 +292,6 @@ export function configureSync(configuration) {
292
292
  }
293
293
  }
294
294
  export async function sync() {
295
- for (const fs of mounts.values())
295
+ for (const fs of defaultContext.mounts.values())
296
296
  await fs.sync();
297
297
  }
@@ -4,6 +4,7 @@ import type * as path from '../path.js';
4
4
  import type { Handle } from '../vfs/file.js';
5
5
  import type * as xattr from '../vfs/xattr.js';
6
6
  import type { Credentials, CredentialsInit } from './credentials.js';
7
+ import type { FileSystem } from './filesystem.js';
7
8
  /**
8
9
  * Symbol used for context branding
9
10
  * @internal @hidden
@@ -34,6 +35,8 @@ export interface FSContext {
34
35
  readonly parent: FSContext | null;
35
36
  /** The child contexts */
36
37
  readonly children: FSContext[];
38
+ /** The mount table for this context */
39
+ readonly mounts: Map<string, FileSystem>;
37
40
  }
38
41
  export declare function isContext(obj: unknown): obj is FSContext;
39
42
  export declare function assertContext(ctx: unknown): asserts ctx is FSContext;
@@ -64,6 +67,7 @@ export interface ContextInit {
64
67
  root?: string;
65
68
  pwd?: string;
66
69
  credentials?: CredentialsInit;
70
+ mounts?: Record<string, FileSystem>;
67
71
  }
68
72
  /**
69
73
  * The default/global context.
@@ -1,6 +1,8 @@
1
- import { createCredentials } from './credentials.js';
2
- import { warn } from 'kerium/log';
1
+ // SPDX-License-Identifier: LGPL-3.0-or-later
2
+ // This needs to be in a separate file to avoid circular dependencies
3
3
  import { withErrno } from 'kerium';
4
+ import { warn } from 'kerium/log';
5
+ import { createCredentials } from './credentials.js';
4
6
  /**
5
7
  * Symbol used for context branding
6
8
  * @internal @hidden
@@ -20,19 +22,20 @@ export function assertContext(ctx) {
20
22
  */
21
23
  export const defaultContext = {
22
24
  [kIsContext]: true,
23
- id: 0,
25
+ id: 1,
24
26
  root: '/',
25
27
  pwd: '/',
26
28
  credentials: createCredentials({ uid: 0, gid: 0 }),
27
29
  descriptors: new Map(),
28
30
  parent: null,
29
31
  children: [],
32
+ mounts: new Map(),
30
33
  };
31
34
  export function contextOf($) {
32
35
  return isContext($) ? $ : defaultContext;
33
36
  }
34
- // 0 is reserved for the global/default context
35
- let _nextId = 1;
37
+ // 1 is reserved for the global/default context
38
+ let _nextId = 2;
36
39
  /**
37
40
  * Create a blank FS Context
38
41
  * @internal
@@ -43,7 +46,7 @@ let _nextId = 1;
43
46
  */
44
47
  export function createChildContext(parent, init = {}) {
45
48
  assertContext(parent);
46
- const { root = parent.root, pwd = parent.pwd, credentials = structuredClone(parent.credentials) } = init;
49
+ const { root = parent.root, pwd = parent.pwd, credentials = structuredClone(parent.credentials), mounts = Object.fromEntries(parent.mounts), } = init;
47
50
  const ctx = {
48
51
  [kIsContext]: true,
49
52
  id: _nextId++,
@@ -53,6 +56,7 @@ export function createChildContext(parent, init = {}) {
53
56
  descriptors: new Map(),
54
57
  parent: parent,
55
58
  children: [],
59
+ mounts: new Map(Object.entries(mounts)),
56
60
  };
57
61
  Object.defineProperties(ctx, {
58
62
  id: { configurable: false, writable: false },
@@ -1,6 +1,7 @@
1
1
  import type { UUID } from 'node:crypto';
2
2
  import type { ConstMap } from 'utilium';
3
3
  import type { InodeLike } from './inode.js';
4
+ import type { IoctlContext } from './ioctl.js';
4
5
  /**
5
6
  * Usage information about a file system
6
7
  * @category Internals
@@ -244,4 +245,8 @@ export declare abstract class FileSystem {
244
245
  * @privateRemarks The default implementation of `streamWrite` uses "chunked" `write`s
245
246
  */
246
247
  streamWrite(path: string, options: StreamOptions): WritableStream;
248
+ /** @internal */
249
+ ioctl(context: IoctlContext, command: number, ...args: any[]): Promise<any>;
250
+ /** @internal */
251
+ ioctlSync(context: IoctlContext, command: number, ...args: any[]): any;
247
252
  }
@@ -1,4 +1,6 @@
1
+ // SPDX-License-Identifier: LGPL-3.0-or-later
1
2
  import { withErrno } from 'kerium';
3
+ import { ioctl_default_ops_async, ioctl_default_ops_sync } from './ioctl.js';
2
4
  const _chunkSize = 0x1000;
3
5
  /**
4
6
  * Provides a consistent and easy to use internal API.
@@ -132,4 +134,20 @@ export class FileSystem {
132
134
  },
133
135
  });
134
136
  }
137
+ /** @internal */
138
+ async ioctl(context, command, ...args) {
139
+ // eslint-disable-next-line @typescript-eslint/unbound-method, @typescript-eslint/no-unnecessary-type-assertion
140
+ const cmd = ioctl_default_ops_async[command];
141
+ if (!cmd)
142
+ throw withErrno('ENOTTY');
143
+ return await cmd(this, context, ...args);
144
+ }
145
+ /** @internal */
146
+ ioctlSync(context, command, ...args) {
147
+ // eslint-disable-next-line @typescript-eslint/unbound-method, @typescript-eslint/no-unnecessary-type-assertion
148
+ const cmd = ioctl_default_ops_sync[command];
149
+ if (!cmd)
150
+ throw withErrno('ENOTTY');
151
+ return cmd(this, context, ...args);
152
+ }
135
153
  }
@@ -79,6 +79,10 @@ export interface InodeLike<T extends number | bigint = number> extends InodeFiel
79
79
  * Number of hard links
80
80
  */
81
81
  nlink: T;
82
+ /**
83
+ * Device ID for special files
84
+ */
85
+ rdev: T;
82
86
  /**
83
87
  * Extended attributes
84
88
  */
@@ -87,7 +91,7 @@ export interface InodeLike<T extends number | bigint = number> extends InodeFiel
87
91
  /**
88
92
  * @internal @hidden
89
93
  */
90
- export declare const _inode_fields: readonly ["ino", "data", "size", "mode", "flags", "nlink", "uid", "gid", "atimeMs", "birthtimeMs", "mtimeMs", "ctimeMs", "version"];
94
+ export declare const _inode_fields: readonly ["ino", "data", "size", "mode", "flags", "nlink", "uid", "gid", "atimeMs", "birthtimeMs", "mtimeMs", "ctimeMs", "version", "rdev"];
91
95
  /**
92
96
  * Represents which version of the `Inode` format we are on.
93
97
  * 1. 58 bytes. The first member was called `ino` but used as the ID for data.
@@ -182,6 +186,7 @@ export declare class Inode extends Inode_base implements InodeLike {
182
186
  * Unrelated to the inode format!
183
187
  */
184
188
  accessor version: number;
189
+ accessor rdev: number;
185
190
  /**
186
191
  * Padding up to 128 bytes.
187
192
  * This ensures there is enough room for expansion without breaking the ABI.
@@ -270,6 +270,7 @@ export const _inode_fields = [
270
270
  'mtimeMs',
271
271
  'ctimeMs',
272
272
  'version',
273
+ 'rdev',
273
274
  ];
274
275
  /**
275
276
  * Represents which version of the `Inode` format we are on.
@@ -335,7 +336,7 @@ export const userModifiableFlags = 0x000380ff;
335
336
  * @internal
336
337
  */
337
338
  let Inode = (() => {
338
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
339
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
339
340
  let _classDecorators = [struct.packed()];
340
341
  let _classDescriptor;
341
342
  let _classExtraInitializers = [];
@@ -389,6 +390,9 @@ let Inode = (() => {
389
390
  let _version_decorators;
390
391
  let _version_initializers = [];
391
392
  let _version_extraInitializers = [];
393
+ let _rdev_decorators;
394
+ let _rdev_initializers = [];
395
+ let _rdev_extraInitializers = [];
392
396
  let ___padding_decorators;
393
397
  let ___padding_initializers = [];
394
398
  let ___padding_extraInitializers = [];
@@ -418,7 +422,8 @@ let Inode = (() => {
418
422
  _flags_decorators = [(_p = t).uint32.bind(_p)];
419
423
  ___after_flags_decorators = [(_q = t).uint16.bind(_q)];
420
424
  _version_decorators = [(_r = t).uint32.bind(_r)];
421
- ___padding_decorators = [t.uint8(48)];
425
+ _rdev_decorators = [(_s = t).uint32.bind(_s)];
426
+ ___padding_decorators = [t.uint8(44)];
422
427
  _attributes_decorators = [field(Attributes)];
423
428
  ___data_decorators = [t.uint8(maxDynamicData)];
424
429
  __esDecorate(this, null, _data_decorators, { kind: "accessor", name: "data", static: false, private: false, access: { has: obj => "data" in obj, get: obj => obj.data, set: (obj, value) => { obj.data = value; } }, metadata: _metadata }, _data_initializers, _data_extraInitializers);
@@ -437,6 +442,7 @@ let Inode = (() => {
437
442
  __esDecorate(this, null, _flags_decorators, { kind: "accessor", name: "flags", static: false, private: false, access: { has: obj => "flags" in obj, get: obj => obj.flags, set: (obj, value) => { obj.flags = value; } }, metadata: _metadata }, _flags_initializers, _flags_extraInitializers);
438
443
  __esDecorate(this, null, ___after_flags_decorators, { kind: "accessor", name: "__after_flags", static: false, private: false, access: { has: obj => "__after_flags" in obj, get: obj => obj.__after_flags, set: (obj, value) => { obj.__after_flags = value; } }, metadata: _metadata }, ___after_flags_initializers, ___after_flags_extraInitializers);
439
444
  __esDecorate(this, null, _version_decorators, { kind: "accessor", 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);
445
+ __esDecorate(this, null, _rdev_decorators, { kind: "accessor", name: "rdev", static: false, private: false, access: { has: obj => "rdev" in obj, get: obj => obj.rdev, set: (obj, value) => { obj.rdev = value; } }, metadata: _metadata }, _rdev_initializers, _rdev_extraInitializers);
440
446
  __esDecorate(this, null, ___padding_decorators, { kind: "accessor", name: "__padding", static: false, private: false, access: { has: obj => "__padding" in obj, get: obj => obj.__padding, set: (obj, value) => { obj.__padding = value; } }, metadata: _metadata }, ___padding_initializers, ___padding_extraInitializers);
441
447
  __esDecorate(this, null, _attributes_decorators, { kind: "accessor", name: "attributes", static: false, private: false, access: { has: obj => "attributes" in obj, get: obj => obj.attributes, set: (obj, value) => { obj.attributes = value; } }, metadata: _metadata }, _attributes_initializers, _attributes_extraInitializers);
442
448
  __esDecorate(this, null, ___data_decorators, { kind: "accessor", name: "__data", static: false, private: false, access: { has: obj => "__data" in obj, get: obj => obj.__data, set: (obj, value) => { obj.__data = value; } }, metadata: _metadata }, ___data_initializers, ___data_extraInitializers);
@@ -528,7 +534,10 @@ let Inode = (() => {
528
534
  */
529
535
  get version() { return this.#version_accessor_storage; }
530
536
  set version(value) { this.#version_accessor_storage = value; }
531
- #__padding_accessor_storage = (__runInitializers(this, _version_extraInitializers), __runInitializers(this, ___padding_initializers, void 0));
537
+ #rdev_accessor_storage = (__runInitializers(this, _version_extraInitializers), __runInitializers(this, _rdev_initializers, void 0));
538
+ get rdev() { return this.#rdev_accessor_storage; }
539
+ set rdev(value) { this.#rdev_accessor_storage = value; }
540
+ #__padding_accessor_storage = (__runInitializers(this, _rdev_extraInitializers), __runInitializers(this, ___padding_initializers, void 0));
532
541
  /**
533
542
  * Padding up to 128 bytes.
534
543
  * This ensures there is enough room for expansion without breaking the ABI.
@@ -0,0 +1,148 @@
1
+ import { BufferView } from 'utilium/buffer';
2
+ import type { FileSystem } from './filesystem.js';
3
+ import type { InodeLike } from './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?: Readonly<InodeLike>);
19
+ }
20
+ /**
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
24
+ */
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
+ }
38
+ /**
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
42
+ */
43
+ export declare enum IOC32 {
44
+ GetFlags = 2147771905,
45
+ SetFlags = 1074030082,
46
+ GetVersion = 2147776001,
47
+ SetVersion = 1074034178
48
+ }
49
+ /**
50
+ * @category ioctl
51
+ */
52
+ export interface IoctlContext {
53
+ fs: FileSystem;
54
+ inode: InodeLike;
55
+ path: string;
56
+ file?: {
57
+ position: number;
58
+ flag: number;
59
+ };
60
+ }
61
+ /**
62
+ * @category ioctl
63
+ */
64
+ export type Ioctl = (context: IoctlContext, ...args: any[]) => any;
65
+ /**
66
+ * What an ioctl takes from whoever is calling it, which is everything but the context it is given.
67
+ * @category ioctl
68
+ */
69
+ export type IoctlArgs<T extends Ioctl> = T extends (context: IoctlContext, ...args: infer A) => any ? A : never;
70
+ /**
71
+ * @category ioctl
72
+ */
73
+ export interface IoctlOps extends Record<number, Ioctl> {
74
+ }
75
+ /**
76
+ * @internal
77
+ * @category ioctl
78
+ */
79
+ export declare const ioctl_default_ops: {
80
+ 2148034049($: IoctlContext): number;
81
+ 2147771905($: IoctlContext): number;
82
+ 2148038145($: IoctlContext): number;
83
+ 2147776001($: IoctlContext): number;
84
+ 3223348747(): never;
85
+ 2149341215($: IoctlContext, _name: string): fsxattr;
86
+ 1075599392($: IoctlContext, _name: string, _value: fsxattr): never;
87
+ 2164298801($: IoctlContext): string | undefined;
88
+ 1090556978($: IoctlContext, label: string): void;
89
+ 2148603136($: IoctlContext): string;
90
+ 2155943169($: IoctlContext): string;
91
+ };
92
+ /**
93
+ * @internal
94
+ * @category ioctl
95
+ */
96
+ export declare const ioctl_default_ops_async: {
97
+ 1074292226($: IoctlContext, flags: number): Promise<void>;
98
+ 1074030082($: IoctlContext, flags: number): Promise<void>;
99
+ 1074296322($: IoctlContext, version: number): Promise<void>;
100
+ 1074034178($: IoctlContext, version: number): Promise<void>;
101
+ 2148034049($: IoctlContext): number;
102
+ 2147771905($: IoctlContext): number;
103
+ 2148038145($: IoctlContext): number;
104
+ 2147776001($: IoctlContext): number;
105
+ 3223348747(): never;
106
+ 2149341215($: IoctlContext, _name: string): fsxattr;
107
+ 1075599392($: IoctlContext, _name: string, _value: fsxattr): never;
108
+ 2164298801($: IoctlContext): string | undefined;
109
+ 1090556978($: IoctlContext, label: string): void;
110
+ 2148603136($: IoctlContext): string;
111
+ 2155943169($: IoctlContext): string;
112
+ };
113
+ type _IoctlOpsAsync = typeof ioctl_default_ops_async;
114
+ /**
115
+ * @internal
116
+ * @category ioctl
117
+ */
118
+ export interface IoctlDefaultAsyncOps extends _IoctlOpsAsync {
119
+ }
120
+ /**
121
+ * @internal
122
+ * @category ioctl
123
+ */
124
+ export declare const ioctl_default_ops_sync: {
125
+ 1074292226($: IoctlContext, flags: number): void;
126
+ 1074030082($: IoctlContext, flags: number): void;
127
+ 1074296322($: IoctlContext, version: number): void;
128
+ 1074034178($: IoctlContext, version: number): void;
129
+ 2148034049($: IoctlContext): number;
130
+ 2147771905($: IoctlContext): number;
131
+ 2148038145($: IoctlContext): number;
132
+ 2147776001($: IoctlContext): number;
133
+ 3223348747(): never;
134
+ 2149341215($: IoctlContext, _name: string): fsxattr;
135
+ 1075599392($: IoctlContext, _name: string, _value: fsxattr): never;
136
+ 2164298801($: IoctlContext): string | undefined;
137
+ 1090556978($: IoctlContext, label: string): void;
138
+ 2148603136($: IoctlContext): string;
139
+ 2155943169($: IoctlContext): string;
140
+ };
141
+ type _IoctlOpsSync = typeof ioctl_default_ops_sync;
142
+ /**
143
+ * @internal
144
+ * @category ioctl
145
+ */
146
+ export interface IoctlDefaultSyncOps extends _IoctlOpsSync {
147
+ }
148
+ export {};