@zenfs/core 0.12.0 → 0.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/backends/backend.d.ts +15 -5
  2. package/dist/backends/index/fs.d.ts +1 -0
  3. package/dist/backends/index/index.d.ts +5 -0
  4. package/dist/backends/index/index.js +1 -0
  5. package/dist/backends/overlay.js +1 -1
  6. package/dist/backends/port/fs.d.ts +3 -1
  7. package/dist/browser.min.js +4 -4
  8. package/dist/browser.min.js.map +4 -4
  9. package/dist/config.d.ts +33 -11
  10. package/dist/config.js +16 -7
  11. package/dist/emulation/async.d.ts +5 -4
  12. package/dist/emulation/async.js +3 -2
  13. package/dist/emulation/index.d.ts +1 -1
  14. package/dist/emulation/index.js +1 -1
  15. package/dist/emulation/path.d.ts +4 -1
  16. package/dist/emulation/promises.d.ts +4 -4
  17. package/dist/emulation/promises.js +27 -27
  18. package/dist/emulation/shared.d.ts +6 -0
  19. package/dist/emulation/shared.js +19 -1
  20. package/dist/emulation/sync.d.ts +4 -4
  21. package/dist/emulation/sync.js +76 -38
  22. package/dist/file.d.ts +5 -10
  23. package/dist/file.js +38 -55
  24. package/dist/filesystem.d.ts +45 -3
  25. package/dist/filesystem.js +37 -8
  26. package/dist/stats.d.ts +16 -16
  27. package/dist/stats.js +42 -49
  28. package/package.json +2 -2
  29. package/src/backends/backend.ts +15 -6
  30. package/src/backends/index/index.ts +5 -0
  31. package/src/backends/overlay.ts +1 -1
  32. package/src/config.ts +62 -21
  33. package/src/emulation/async.ts +19 -18
  34. package/src/emulation/index.ts +1 -1
  35. package/src/emulation/path.ts +4 -1
  36. package/src/emulation/promises.ts +33 -31
  37. package/src/emulation/shared.ts +22 -1
  38. package/src/emulation/sync.ts +83 -54
  39. package/src/error.ts +1 -1
  40. package/src/file.ts +39 -57
  41. package/src/filesystem.ts +133 -51
  42. package/src/stats.ts +48 -60
package/dist/file.js CHANGED
@@ -183,7 +183,7 @@ export class PreloadFile extends File {
183
183
  /**
184
184
  * Path to the file
185
185
  */
186
- path, flag, stats, _buffer = new Uint8Array(new ArrayBuffer(0, { maxByteLength: size_max }))) {
186
+ path, flag, stats, _buffer = new Uint8Array(new ArrayBuffer(0, fs.metadata().noResizableBuffers ? {} : { maxByteLength: size_max }))) {
187
187
  super();
188
188
  this.fs = fs;
189
189
  this.path = path;
@@ -191,7 +191,7 @@ export class PreloadFile extends File {
191
191
  this.stats = stats;
192
192
  this._buffer = _buffer;
193
193
  this._position = 0;
194
- this._dirty = false;
194
+ this.dirty = false;
195
195
  /*
196
196
  Note:
197
197
  This invariant is *not* maintained once the file starts getting modified.
@@ -203,7 +203,7 @@ export class PreloadFile extends File {
203
203
  if (isReadable(this.flag)) {
204
204
  throw new Error(`Size mismatch: buffer length ${_buffer.byteLength}, stats size ${this.stats.size}`);
205
205
  }
206
- this._dirty = true;
206
+ this.dirty = true;
207
207
  }
208
208
  /**
209
209
  * Get the underlying buffer for this file. Mutating not recommended and will mess up dirty tracking.
@@ -234,18 +234,18 @@ export class PreloadFile extends File {
234
234
  this._position = newPos;
235
235
  }
236
236
  async sync() {
237
- if (!this.isDirty()) {
237
+ if (!this.dirty) {
238
238
  return;
239
239
  }
240
240
  await this.fs.sync(this.path, this._buffer, this.stats);
241
- this._dirty = false;
241
+ this.dirty = false;
242
242
  }
243
243
  syncSync() {
244
- if (!this.isDirty()) {
244
+ if (!this.dirty) {
245
245
  return;
246
246
  }
247
247
  this.fs.syncSync(this.path, this._buffer, this.stats);
248
- this._dirty = false;
248
+ this.dirty = false;
249
249
  }
250
250
  async close() {
251
251
  await this.sync();
@@ -267,39 +267,32 @@ export class PreloadFile extends File {
267
267
  }
268
268
  /**
269
269
  * Asynchronous truncate.
270
- * @param len
270
+ * @param length
271
271
  */
272
- async truncate(len) {
273
- this.truncateSync(len);
274
- if (isSynchronous(this.flag)) {
275
- return this.sync();
276
- }
272
+ async truncate(length) {
273
+ this.truncateSync(length);
274
+ return this.sync();
277
275
  }
278
276
  /**
279
277
  * Synchronous truncate.
280
- * @param len
278
+ * @param length
281
279
  */
282
- truncateSync(len) {
283
- this._dirty = true;
280
+ truncateSync(length) {
281
+ this.dirty = true;
284
282
  if (!isWriteable(this.flag)) {
285
283
  throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode.');
286
284
  }
287
285
  this.stats.mtimeMs = Date.now();
288
- if (len > this._buffer.length) {
289
- const buf = new Uint8Array(len - this._buffer.length);
290
- // Write will set stats.size for us.
291
- this.writeSync(buf, 0, buf.length, this._buffer.length);
292
- if (isSynchronous(this.flag)) {
293
- this.syncSync();
294
- }
286
+ if (length > this._buffer.length) {
287
+ const data = new Uint8Array(length - this._buffer.length);
288
+ // Write will set stats.size and handle syncing.
289
+ this.writeSync(data, 0, data.length, this._buffer.length);
295
290
  return;
296
291
  }
297
- this.stats.size = len;
298
- // Truncate buffer to 'len'.
299
- this._buffer = this._buffer.subarray(0, len);
300
- if (isSynchronous(this.flag)) {
301
- this.syncSync();
302
- }
292
+ this.stats.size = length;
293
+ // Truncate.
294
+ this._buffer = this._buffer.slice(0, length);
295
+ this.syncSync();
303
296
  }
304
297
  /**
305
298
  * Write buffer to the file.
@@ -332,21 +325,21 @@ export class PreloadFile extends File {
332
325
  * @returns bytes written
333
326
  */
334
327
  writeSync(buffer, offset = 0, length = this.stats.size, position = 0) {
335
- this._dirty = true;
328
+ this.dirty = true;
336
329
  position ?? (position = this.position);
337
330
  if (!isWriteable(this.flag)) {
338
331
  throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode.');
339
332
  }
340
- const endFp = position + length;
341
- if (endFp > this.stats.size) {
342
- this.stats.size = endFp;
343
- if (endFp > this._buffer.byteLength) {
344
- if (this._buffer.buffer.resizable && this._buffer.buffer.maxByteLength <= endFp) {
345
- this._buffer.buffer.resize(endFp);
333
+ const end = position + length;
334
+ if (end > this.stats.size) {
335
+ this.stats.size = end;
336
+ if (end > this._buffer.byteLength) {
337
+ if (this._buffer.buffer.resizable && this._buffer.buffer.maxByteLength <= end) {
338
+ this._buffer.buffer.resize(end);
346
339
  }
347
340
  else {
348
341
  // Extend the buffer!
349
- const newBuffer = new Uint8Array(new ArrayBuffer(endFp, { maxByteLength: size_max }));
342
+ const newBuffer = new Uint8Array(new ArrayBuffer(end, this.fs.metadata().noResizableBuffers ? {} : { maxByteLength: size_max }));
350
343
  newBuffer.set(this._buffer);
351
344
  this._buffer = newBuffer;
352
345
  }
@@ -356,11 +349,8 @@ export class PreloadFile extends File {
356
349
  this._buffer.set(slice, position);
357
350
  const bytesWritten = slice.byteLength;
358
351
  this.stats.mtimeMs = Date.now();
359
- if (isSynchronous(this.flag)) {
360
- this.syncSync();
361
- return bytesWritten;
362
- }
363
352
  this.position = position + bytesWritten;
353
+ this.syncSync();
364
354
  return bytesWritten;
365
355
  }
366
356
  /**
@@ -392,6 +382,7 @@ export class PreloadFile extends File {
392
382
  if (!isReadable(this.flag)) {
393
383
  throw new ErrnoError(Errno.EPERM, 'File not opened with a readable mode.');
394
384
  }
385
+ this.dirty = true;
395
386
  position ?? (position = this.position);
396
387
  let end = position + length;
397
388
  if (end > this.stats.size) {
@@ -400,6 +391,7 @@ export class PreloadFile extends File {
400
391
  this.stats.atimeMs = Date.now();
401
392
  this._position = end;
402
393
  const bytesRead = end - position;
394
+ this.syncSync();
403
395
  if (bytesRead == 0) {
404
396
  // No copy/read. Return immediatly for better performance
405
397
  return bytesRead;
@@ -419,7 +411,7 @@ export class PreloadFile extends File {
419
411
  * @param mode
420
412
  */
421
413
  chmodSync(mode) {
422
- this._dirty = true;
414
+ this.dirty = true;
423
415
  this.stats.chmod(mode);
424
416
  this.syncSync();
425
417
  }
@@ -437,7 +429,7 @@ export class PreloadFile extends File {
437
429
  * @param gid
438
430
  */
439
431
  chownSync(uid, gid) {
440
- this._dirty = true;
432
+ this.dirty = true;
441
433
  this.stats.chown(uid, gid);
442
434
  this.syncSync();
443
435
  }
@@ -445,27 +437,18 @@ export class PreloadFile extends File {
445
437
  this.utimesSync(atime, mtime);
446
438
  }
447
439
  utimesSync(atime, mtime) {
448
- this._dirty = true;
440
+ this.dirty = true;
449
441
  this.stats.atime = atime;
450
442
  this.stats.mtime = mtime;
451
443
  this.syncSync();
452
444
  }
453
- isDirty() {
454
- return this._dirty;
455
- }
456
- /**
457
- * Resets the dirty bit. Should only be called after a sync has completed successfully.
458
- */
459
- resetDirty() {
460
- this._dirty = false;
461
- }
462
445
  _setType(type) {
463
- this._dirty = true;
446
+ this.dirty = true;
464
447
  this.stats.mode = (this.stats.mode & ~S_IFMT) | type;
465
448
  return this.sync();
466
449
  }
467
450
  _setTypeSync(type) {
468
- this._dirty = true;
451
+ this.dirty = true;
469
452
  this.stats.mode = (this.stats.mode & ~S_IFMT) | type;
470
453
  this.syncSync();
471
454
  }
@@ -22,6 +22,35 @@ export interface FileSystemMetadata {
22
22
  * The available space
23
23
  */
24
24
  freeSpace: number;
25
+ /**
26
+ * If set, disables File from using a resizable array buffer.
27
+ * @default false
28
+ */
29
+ noResizableBuffers: boolean;
30
+ /**
31
+ * If set, disables caching on async file systems.
32
+ * This means *sync operations will not work*.
33
+ * It has no affect on sync file systems.
34
+ * @default false
35
+ */
36
+ noAsyncCache: boolean;
37
+ /**
38
+ * The optimal block size to use with the file system
39
+ * @default 4096
40
+ */
41
+ blockSize?: number;
42
+ /**
43
+ * Total number of (file) nodes available
44
+ */
45
+ totalNodes?: number;
46
+ /**
47
+ * Number of free (file) nodes available
48
+ */
49
+ freeNodes?: number;
50
+ /**
51
+ * The type of the FS
52
+ */
53
+ type?: number;
25
54
  }
26
55
  /**
27
56
  * Structure for a filesystem. All ZenFS backends must extend this.
@@ -35,10 +64,15 @@ export interface FileSystemMetadata {
35
64
  */
36
65
  export declare abstract class FileSystem {
37
66
  /**
38
- * Get metadata about the current file syste,
67
+ * Numeric type, used for statfs
68
+ * @internal @protected
69
+ */
70
+ _type?: number;
71
+ /**
72
+ * Get metadata about the current file system
39
73
  */
40
74
  metadata(): FileSystemMetadata;
41
- constructor(options?: object);
75
+ constructor();
42
76
  ready(): Promise<void>;
43
77
  /**
44
78
  * Asynchronous rename. No arguments other than a possible exception
@@ -168,12 +202,20 @@ declare abstract class SyncFS extends FileSystem {
168
202
  export declare function Sync<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => SyncFS) & T;
169
203
  /**
170
204
  * @internal
205
+ * Note: `_*` should be treated like protected.
206
+ * Protected can't be used because of TS quirks however.
171
207
  */
172
208
  declare abstract class AsyncFS extends FileSystem {
173
209
  /**
210
+ * @access protected
211
+ * @hidden
212
+ */
213
+ _disableSync: boolean;
214
+ /**
215
+ * @access protected
174
216
  * @hidden
175
217
  */
176
- abstract _sync: FileSystem;
218
+ abstract _sync?: FileSystem;
177
219
  queueDone(): Promise<void>;
178
220
  metadata(): FileSystemMetadata;
179
221
  ready(): Promise<void>;
@@ -14,7 +14,7 @@ import { PreloadFile, parseFlag } from './file.js';
14
14
  */
15
15
  export class FileSystem {
16
16
  /**
17
- * Get metadata about the current file syste,
17
+ * Get metadata about the current file system
18
18
  */
19
19
  metadata() {
20
20
  return {
@@ -22,11 +22,12 @@ export class FileSystem {
22
22
  readonly: false,
23
23
  totalSpace: 0,
24
24
  freeSpace: 0,
25
+ noResizableBuffers: false,
26
+ noAsyncCache: false,
27
+ type: this._type,
25
28
  };
26
29
  }
27
- constructor(options) {
28
- // unused
29
- }
30
+ constructor() { }
30
31
  async ready() { }
31
32
  /**
32
33
  * Test whether or not the given path exists by checking with the file system.
@@ -37,7 +38,7 @@ export class FileSystem {
37
38
  return true;
38
39
  }
39
40
  catch (e) {
40
- return false;
41
+ return e.code != 'ENOENT';
41
42
  }
42
43
  }
43
44
  /**
@@ -49,7 +50,7 @@ export class FileSystem {
49
50
  return true;
50
51
  }
51
52
  catch (e) {
52
- return false;
53
+ return e.code != 'ENOENT';
53
54
  }
54
55
  }
55
56
  }
@@ -117,6 +118,7 @@ export function Async(FS) {
117
118
  */
118
119
  this._queue = [];
119
120
  this._isInitialized = false;
121
+ this._disableSync = false;
120
122
  }
121
123
  get _queueRunning() {
122
124
  return !!this._queue.length;
@@ -128,11 +130,12 @@ export function Async(FS) {
128
130
  });
129
131
  }
130
132
  async ready() {
131
- await this._sync.ready();
132
133
  await super.ready();
133
- if (this._isInitialized) {
134
+ if (this._isInitialized || this._disableSync) {
134
135
  return;
135
136
  }
137
+ this.checkSync();
138
+ await this._sync.ready();
136
139
  try {
137
140
  await this.crossCopy('/');
138
141
  this._isInitialized = true;
@@ -142,19 +145,37 @@ export function Async(FS) {
142
145
  throw e;
143
146
  }
144
147
  }
148
+ metadata() {
149
+ return {
150
+ ...super.metadata(),
151
+ noAsyncCache: this._disableSync,
152
+ };
153
+ }
154
+ checkSync(path, syscall) {
155
+ if (this._disableSync) {
156
+ throw new ErrnoError(Errno.ENOTSUP, 'Sync caching has been disabled for this async file system', path, syscall);
157
+ }
158
+ if (!this._sync) {
159
+ throw new ErrnoError(Errno.ENOTSUP, 'No sync cache is attached to this async file system', path, syscall);
160
+ }
161
+ }
145
162
  renameSync(oldPath, newPath, cred) {
163
+ this.checkSync(oldPath, 'rename');
146
164
  this._sync.renameSync(oldPath, newPath, cred);
147
165
  this.queue('rename', oldPath, newPath, cred);
148
166
  }
149
167
  statSync(path, cred) {
168
+ this.checkSync(path, 'stat');
150
169
  return this._sync.statSync(path, cred);
151
170
  }
152
171
  createFileSync(path, flag, mode, cred) {
172
+ this.checkSync(path, 'createFile');
153
173
  this._sync.createFileSync(path, flag, mode, cred);
154
174
  this.queue('createFile', path, flag, mode, cred);
155
175
  return this.openFileSync(path, flag, cred);
156
176
  }
157
177
  openFileSync(path, flag, cred) {
178
+ this.checkSync(path, 'openFile');
158
179
  const file = this._sync.openFileSync(path, flag, cred);
159
180
  const stats = file.statSync();
160
181
  const buffer = new Uint8Array(stats.size);
@@ -162,35 +183,43 @@ export function Async(FS) {
162
183
  return new PreloadFile(this, path, flag, stats, buffer);
163
184
  }
164
185
  unlinkSync(path, cred) {
186
+ this.checkSync(path, 'unlinkSync');
165
187
  this._sync.unlinkSync(path, cred);
166
188
  this.queue('unlink', path, cred);
167
189
  }
168
190
  rmdirSync(path, cred) {
191
+ this.checkSync(path, 'rmdir');
169
192
  this._sync.rmdirSync(path, cred);
170
193
  this.queue('rmdir', path, cred);
171
194
  }
172
195
  mkdirSync(path, mode, cred) {
196
+ this.checkSync(path, 'mkdir');
173
197
  this._sync.mkdirSync(path, mode, cred);
174
198
  this.queue('mkdir', path, mode, cred);
175
199
  }
176
200
  readdirSync(path, cred) {
201
+ this.checkSync(path, 'readdir');
177
202
  return this._sync.readdirSync(path, cred);
178
203
  }
179
204
  linkSync(srcpath, dstpath, cred) {
205
+ this.checkSync(srcpath, 'link');
180
206
  this._sync.linkSync(srcpath, dstpath, cred);
181
207
  this.queue('link', srcpath, dstpath, cred);
182
208
  }
183
209
  syncSync(path, data, stats) {
210
+ this.checkSync(path, 'sync');
184
211
  this._sync.syncSync(path, data, stats);
185
212
  this.queue('sync', path, data, stats);
186
213
  }
187
214
  existsSync(path, cred) {
215
+ this.checkSync(path, 'exists');
188
216
  return this._sync.existsSync(path, cred);
189
217
  }
190
218
  /**
191
219
  * @internal
192
220
  */
193
221
  async crossCopy(path) {
222
+ this.checkSync(path, 'crossCopy');
194
223
  const stats = await this.stat(path, rootCred);
195
224
  if (stats.isDirectory()) {
196
225
  if (path !== '/') {
package/dist/stats.d.ts CHANGED
@@ -57,11 +57,9 @@ export interface StatsLike<T extends number | bigint = number | bigint> {
57
57
  * Common code used by both Stats and BigIntStats.
58
58
  */
59
59
  export declare abstract class StatsCommon<T extends number | bigint> implements Node.StatsBase<T>, StatsLike {
60
- protected abstract _isBigint: boolean;
61
- protected get _typename(): string;
62
- protected get _typename_inverse(): string;
60
+ protected abstract _isBigint: T extends bigint ? true : false;
63
61
  protected _convert(arg: number | bigint | string | boolean): T;
64
- blocks: T;
62
+ get blocks(): T;
65
63
  /**
66
64
  * Unix-style file mode (e.g. 0o644) that includes the type of the item.
67
65
  * Type of the item can be FILE, DIRECTORY, SYMLINK, or SOCKET
@@ -184,27 +182,26 @@ export declare abstract class StatsCommon<T extends number | bigint> implements
184
182
  * Attribute descriptions are from `man 2 stat'
185
183
  * @see http://nodejs.org/api/fs.html#fs_class_fs_stats
186
184
  * @see http://man7.org/linux/man-pages/man2/stat.2.html
185
+ * @internal
187
186
  */
188
187
  export declare class Stats extends StatsCommon<number> implements Node.Stats, StatsLike {
189
- protected _isBigint: boolean;
190
- /**
191
- * Clones the stats object.
192
- * @deprecated use `new Stats(stats)`
193
- */
194
- static clone(stats: Stats): Stats;
188
+ protected _isBigint: false;
195
189
  }
196
190
  /**
197
191
  * Stats with bigint
198
192
  * @todo Implement with bigint instead of wrapping Stats
193
+ * @internal
199
194
  */
200
195
  export declare class BigIntStats extends StatsCommon<bigint> implements Node.BigIntStats, StatsLike {
201
- protected _isBigint: boolean;
202
- /**
203
- * Clone a stats object.
204
- * @deprecated use `new BigIntStats(stats)`
205
- */
206
- static clone(stats: BigIntStats | Stats): BigIntStats;
196
+ protected _isBigint: true;
207
197
  }
198
+ /**
199
+ * @internal
200
+ */
201
+ export declare const ZenFsType = 525687744115;
202
+ /**
203
+ * @hidden
204
+ */
208
205
  export declare class StatsFs implements Node.StatsFsBase<number> {
209
206
  /** Type of file system. */
210
207
  type: number;
@@ -221,6 +218,9 @@ export declare class StatsFs implements Node.StatsFsBase<number> {
221
218
  /** Free file nodes in file system. */
222
219
  ffree: number;
223
220
  }
221
+ /**
222
+ * @hidden
223
+ */
224
224
  export declare class BigIntStatsFs implements Node.StatsFsBase<bigint> {
225
225
  /** Type of file system. */
226
226
  type: bigint;
package/dist/stats.js CHANGED
@@ -1,4 +1,5 @@
1
- import { S_IFDIR, S_IFLNK, S_IFMT, S_IFREG, S_IRWXG, S_IRWXO, S_IRWXU } from './emulation/constants.js';
1
+ import { S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK, S_IRWXG, S_IRWXO, S_IRWXU } from './emulation/constants.js';
2
+ import { size_max } from './inode.js';
2
3
  /**
3
4
  * Indicates the type of the given file. Applied to 'mode'.
4
5
  */
@@ -13,15 +14,12 @@ export var FileType;
13
14
  * Common code used by both Stats and BigIntStats.
14
15
  */
15
16
  export class StatsCommon {
16
- get _typename() {
17
- return this._isBigint ? 'bigint' : 'number';
18
- }
19
- get _typename_inverse() {
20
- return this._isBigint ? 'number' : 'bigint';
21
- }
22
17
  _convert(arg) {
23
18
  return (this._isBigint ? BigInt(arg) : Number(arg));
24
19
  }
20
+ get blocks() {
21
+ return this._convert(Math.ceil(Number(this.size) / 512));
22
+ }
25
23
  get atime() {
26
24
  return new Date(Number(this.atimeMs));
27
25
  }
@@ -78,16 +76,15 @@ export class StatsCommon {
78
76
  * group ID of owner
79
77
  */
80
78
  this.gid = this._convert(0);
81
- const currentTime = Date.now();
82
- const resolveT = (val, _default) => (typeof val == this._typename ? val : this._convert(typeof val == this._typename_inverse ? val : _default));
83
- this.atimeMs = resolveT(atimeMs, currentTime);
84
- this.mtimeMs = resolveT(mtimeMs, currentTime);
85
- this.ctimeMs = resolveT(ctimeMs, currentTime);
86
- this.birthtimeMs = resolveT(birthtimeMs, currentTime);
87
- this.uid = resolveT(uid, 0);
88
- this.gid = resolveT(gid, 0);
89
- this.size = resolveT(size, 0);
90
- this.ino = resolveT(ino, 0);
79
+ const now = Date.now();
80
+ this.atimeMs = this._convert(atimeMs ?? now);
81
+ this.mtimeMs = this._convert(mtimeMs ?? now);
82
+ this.ctimeMs = this._convert(ctimeMs ?? now);
83
+ this.birthtimeMs = this._convert(birthtimeMs ?? now);
84
+ this.uid = this._convert(uid ?? 0);
85
+ this.gid = this._convert(gid ?? 0);
86
+ this.size = this._convert(size ?? 0);
87
+ this.ino = this._convert(ino ?? 0);
91
88
  const itemType = Number(mode) & S_IFMT || FileType.FILE;
92
89
  if (mode) {
93
90
  this.mode = this._convert(mode);
@@ -102,8 +99,6 @@ export class StatsCommon {
102
99
  this.mode = this._convert(0o777);
103
100
  }
104
101
  }
105
- // number of 512B blocks allocated
106
- this.blocks = this._convert(Math.ceil(Number(size) / 512));
107
102
  // Check if mode also includes top-most bits, which indicate the file's type.
108
103
  if ((this.mode & S_IFMT) == 0) {
109
104
  this.mode = (this.mode | this._convert(itemType));
@@ -129,16 +124,16 @@ export class StatsCommon {
129
124
  }
130
125
  // Currently unsupported
131
126
  isSocket() {
132
- return false;
127
+ return (this.mode & S_IFMT) === S_IFSOCK;
133
128
  }
134
129
  isBlockDevice() {
135
- return false;
130
+ return (this.mode & S_IFMT) === S_IFBLK;
136
131
  }
137
132
  isCharacterDevice() {
138
- return false;
133
+ return (this.mode & S_IFMT) === S_IFCHR;
139
134
  }
140
135
  isFIFO() {
141
- return false;
136
+ return (this.mode & S_IFMT) === S_IFIFO;
142
137
  }
143
138
  /**
144
139
  * Checks if a given user/group has access to this item
@@ -194,16 +189,16 @@ export class StatsCommon {
194
189
  }
195
190
  }
196
191
  get atimeNs() {
197
- return BigInt(this.atimeMs);
192
+ return BigInt(this.atimeMs) * 1000n;
198
193
  }
199
194
  get mtimeNs() {
200
- return BigInt(this.mtimeMs);
195
+ return BigInt(this.mtimeMs) * 1000n;
201
196
  }
202
197
  get ctimeNs() {
203
- return BigInt(this.ctimeMs);
198
+ return BigInt(this.ctimeMs) * 1000n;
204
199
  }
205
200
  get birthtimeNs() {
206
- return BigInt(this.birthtimeMs);
201
+ return BigInt(this.birthtimeMs) * 1000n;
207
202
  }
208
203
  }
209
204
  /**
@@ -212,44 +207,39 @@ export class StatsCommon {
212
207
  * Attribute descriptions are from `man 2 stat'
213
208
  * @see http://nodejs.org/api/fs.html#fs_class_fs_stats
214
209
  * @see http://man7.org/linux/man-pages/man2/stat.2.html
210
+ * @internal
215
211
  */
216
212
  export class Stats extends StatsCommon {
217
213
  constructor() {
218
214
  super(...arguments);
219
215
  this._isBigint = false;
220
216
  }
221
- /**
222
- * Clones the stats object.
223
- * @deprecated use `new Stats(stats)`
224
- */
225
- static clone(stats) {
226
- return new Stats(stats);
227
- }
228
217
  }
229
218
  Stats;
230
219
  /**
231
220
  * Stats with bigint
232
221
  * @todo Implement with bigint instead of wrapping Stats
222
+ * @internal
233
223
  */
234
224
  export class BigIntStats extends StatsCommon {
235
225
  constructor() {
236
226
  super(...arguments);
237
227
  this._isBigint = true;
238
228
  }
239
- /**
240
- * Clone a stats object.
241
- * @deprecated use `new BigIntStats(stats)`
242
- */
243
- static clone(stats) {
244
- return new BigIntStats(stats);
245
- }
246
229
  }
230
+ /**
231
+ * @internal
232
+ */
233
+ export const ZenFsType = 0x7a656e6673; // 'z' 'e' 'n' 'f' 's'
234
+ /**
235
+ * @hidden
236
+ */
247
237
  export class StatsFs {
248
238
  constructor() {
249
239
  /** Type of file system. */
250
- this.type = 0;
240
+ this.type = 0x7a656e6673;
251
241
  /** Optimal transfer block size. */
252
- this.bsize = 0;
242
+ this.bsize = 4096;
253
243
  /** Total data blocks in file system. */
254
244
  this.blocks = 0;
255
245
  /** Free blocks in file system. */
@@ -257,17 +247,20 @@ export class StatsFs {
257
247
  /** Available blocks for unprivileged users */
258
248
  this.bavail = 0;
259
249
  /** Total file nodes in file system. */
260
- this.files = 0;
250
+ this.files = size_max;
261
251
  /** Free file nodes in file system. */
262
- this.ffree = 0;
252
+ this.ffree = size_max;
263
253
  }
264
254
  }
255
+ /**
256
+ * @hidden
257
+ */
265
258
  export class BigIntStatsFs {
266
259
  constructor() {
267
260
  /** Type of file system. */
268
- this.type = 0n;
261
+ this.type = 0x7a656e6673n;
269
262
  /** Optimal transfer block size. */
270
- this.bsize = 0n;
263
+ this.bsize = 4096n;
271
264
  /** Total data blocks in file system. */
272
265
  this.blocks = 0n;
273
266
  /** Free blocks in file system. */
@@ -275,8 +268,8 @@ export class BigIntStatsFs {
275
268
  /** Available blocks for unprivileged users */
276
269
  this.bavail = 0n;
277
270
  /** Total file nodes in file system. */
278
- this.files = 0n;
271
+ this.files = BigInt(size_max);
279
272
  /** Free file nodes in file system. */
280
- this.ffree = 0n;
273
+ this.ffree = BigInt(size_max);
281
274
  }
282
275
  }