@zenfs/core 1.11.3 → 2.0.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.
Files changed (116) hide show
  1. package/dist/backends/backend.d.ts +19 -15
  2. package/dist/backends/backend.js +31 -15
  3. package/dist/backends/cow.d.ts +20 -30
  4. package/dist/backends/cow.js +52 -142
  5. package/dist/backends/fetch.d.ts +1 -0
  6. package/dist/backends/fetch.js +3 -1
  7. package/dist/backends/index.d.ts +1 -1
  8. package/dist/backends/index.js +1 -1
  9. package/dist/backends/memory.d.ts +5 -7
  10. package/dist/backends/memory.js +2 -3
  11. package/dist/backends/passthrough.d.ts +19 -22
  12. package/dist/backends/passthrough.js +85 -160
  13. package/dist/backends/port.d.ts +207 -0
  14. package/dist/backends/port.js +297 -0
  15. package/dist/backends/single_buffer.d.ts +11 -5
  16. package/dist/backends/single_buffer.js +18 -12
  17. package/dist/backends/store/fs.d.ts +11 -27
  18. package/dist/backends/store/fs.js +67 -91
  19. package/dist/backends/store/store.d.ts +7 -12
  20. package/dist/config.d.ts +1 -10
  21. package/dist/config.js +7 -8
  22. package/dist/context.d.ts +8 -21
  23. package/dist/context.js +33 -10
  24. package/dist/index.d.ts +2 -1
  25. package/dist/index.js +2 -1
  26. package/dist/internal/contexts.d.ts +63 -0
  27. package/dist/internal/contexts.js +15 -0
  28. package/dist/internal/credentials.d.ts +2 -11
  29. package/dist/internal/credentials.js +0 -19
  30. package/dist/internal/devices.d.ts +18 -80
  31. package/dist/internal/devices.js +76 -279
  32. package/dist/internal/file_index.js +3 -3
  33. package/dist/internal/filesystem.d.ts +31 -89
  34. package/dist/internal/filesystem.js +21 -20
  35. package/dist/internal/index.d.ts +0 -1
  36. package/dist/internal/index.js +0 -1
  37. package/dist/internal/index_fs.d.ts +12 -30
  38. package/dist/internal/index_fs.js +23 -55
  39. package/dist/internal/inode.d.ts +147 -9
  40. package/dist/internal/inode.js +333 -25
  41. package/dist/internal/log.d.ts +19 -13
  42. package/dist/internal/log.js +81 -80
  43. package/dist/mixins/async.js +26 -90
  44. package/dist/mixins/mutexed.d.ts +17 -16
  45. package/dist/mixins/mutexed.js +29 -31
  46. package/dist/mixins/readonly.d.ts +7 -6
  47. package/dist/mixins/readonly.js +6 -0
  48. package/dist/mixins/sync.js +8 -8
  49. package/dist/{vfs/path.d.ts → path.d.ts} +3 -4
  50. package/dist/{vfs/path.js → path.js} +6 -9
  51. package/dist/readline.d.ts +134 -0
  52. package/dist/readline.js +623 -0
  53. package/dist/utils.d.ts +4 -35
  54. package/dist/utils.js +8 -73
  55. package/dist/vfs/acl.d.ts +42 -0
  56. package/dist/vfs/acl.js +249 -0
  57. package/dist/vfs/async.d.ts +7 -21
  58. package/dist/vfs/async.js +19 -19
  59. package/dist/vfs/config.d.ts +6 -18
  60. package/dist/vfs/config.js +8 -18
  61. package/dist/vfs/dir.d.ts +3 -3
  62. package/dist/vfs/dir.js +9 -8
  63. package/dist/vfs/file.d.ts +106 -0
  64. package/dist/vfs/file.js +235 -0
  65. package/dist/vfs/flags.d.ts +19 -0
  66. package/dist/vfs/flags.js +62 -0
  67. package/dist/vfs/index.d.ts +4 -10
  68. package/dist/vfs/index.js +4 -13
  69. package/dist/vfs/ioctl.d.ts +87 -0
  70. package/dist/vfs/ioctl.js +304 -0
  71. package/dist/vfs/promises.d.ts +78 -16
  72. package/dist/vfs/promises.js +273 -122
  73. package/dist/vfs/shared.d.ts +7 -26
  74. package/dist/vfs/shared.js +25 -53
  75. package/dist/{stats.d.ts → vfs/stats.d.ts} +14 -28
  76. package/dist/{stats.js → vfs/stats.js} +11 -66
  77. package/dist/vfs/streams.d.ts +1 -0
  78. package/dist/vfs/streams.js +24 -19
  79. package/dist/vfs/sync.d.ts +4 -3
  80. package/dist/vfs/sync.js +143 -128
  81. package/dist/vfs/watchers.d.ts +2 -2
  82. package/dist/vfs/watchers.js +6 -6
  83. package/dist/vfs/xattr.d.ts +116 -0
  84. package/dist/vfs/xattr.js +218 -0
  85. package/package.json +3 -3
  86. package/readme.md +1 -1
  87. package/tests/backend/config.worker.js +4 -1
  88. package/tests/backend/fetch.test.ts +3 -0
  89. package/tests/backend/port.test.ts +21 -35
  90. package/tests/backend/remote.worker.js +4 -1
  91. package/tests/backend/single-buffer.test.ts +24 -0
  92. package/tests/common/context.test.ts +1 -1
  93. package/tests/common/handle.test.ts +17 -12
  94. package/tests/common/path.test.ts +1 -1
  95. package/tests/common/readline.test.ts +104 -0
  96. package/tests/common.ts +4 -19
  97. package/tests/fetch/fetch.ts +1 -1
  98. package/tests/fs/links.test.ts +1 -1
  99. package/tests/fs/permissions.test.ts +7 -6
  100. package/tests/fs/readFile.test.ts +3 -3
  101. package/tests/fs/stat.test.ts +6 -6
  102. package/tests/fs/streams.test.ts +2 -11
  103. package/tests/fs/times.test.ts +1 -1
  104. package/tests/fs/xattr.test.ts +85 -0
  105. package/tests/logs.js +22 -0
  106. package/tests/setup/context.ts +1 -1
  107. package/tests/setup/index.ts +3 -3
  108. package/tests/setup/port.ts +1 -1
  109. package/dist/backends/port/fs.d.ts +0 -84
  110. package/dist/backends/port/fs.js +0 -151
  111. package/dist/backends/port/rpc.d.ts +0 -77
  112. package/dist/backends/port/rpc.js +0 -100
  113. package/dist/backends/store/simple.d.ts +0 -20
  114. package/dist/backends/store/simple.js +0 -13
  115. package/dist/internal/file.d.ts +0 -351
  116. package/dist/internal/file.js +0 -739
package/dist/vfs/sync.js CHANGED
@@ -50,24 +50,28 @@ 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
+ import { deleteFD, fromFD, SyncHandle, toFD } from './file.js';
54
+ import { Stats } from './stats.js';
53
55
  import { Buffer } from 'buffer';
54
- import { credentials } from '../internal/credentials.js';
56
+ import { decodeUTF8, encodeUTF8 } from 'utilium';
57
+ import { defaultContext } from '../internal/contexts.js';
55
58
  import { Errno, ErrnoError } from '../internal/error.js';
56
- import { flagToMode, isAppendable, isExclusive, isReadable, isTruncating, isWriteable, parseFlag } from '../internal/file.js';
57
- import { BigIntStats } from '../stats.js';
58
- import { decodeUTF8, normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';
59
- import { config } from './config.js';
59
+ import { hasAccess, isDirectory, isSymbolicLink } from '../internal/inode.js';
60
+ import { dirname, join, parse, resolve } from '../path.js';
61
+ import { normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';
62
+ import { checkAccess } from './config.js';
60
63
  import * as constants from './constants.js';
61
64
  import { Dir, Dirent } from './dir.js';
62
- import { dirname, join, parse, resolve } from './path.js';
63
- import { _statfs, fd2file, fdMap, file2fd, fixError, resolveMount } from './shared.js';
65
+ import * as flags from './flags.js';
66
+ import { _statfs, fixError, resolveMount } from './shared.js';
67
+ import { BigIntStats } from './stats.js';
64
68
  import { emitChange } from './watchers.js';
65
69
  export function renameSync(oldPath, newPath) {
66
70
  oldPath = normalizePath(oldPath);
67
71
  newPath = normalizePath(newPath);
68
72
  const oldMount = resolveMount(oldPath, this);
69
73
  const newMount = resolveMount(newPath, this);
70
- if (config.checkAccess && !statSync.call(this, dirname(oldPath)).hasAccess(constants.W_OK, this)) {
74
+ if (checkAccess && !statSync.call(this, dirname(oldPath)).hasAccess(constants.W_OK, this)) {
71
75
  throw ErrnoError.With('EACCES', oldPath, 'rename');
72
76
  }
73
77
  try {
@@ -108,10 +112,10 @@ export function statSync(path, options) {
108
112
  const { fs, path: resolved } = resolveMount(realpathSync.call(this, path), this);
109
113
  try {
110
114
  const stats = fs.statSync(resolved);
111
- if (config.checkAccess && !stats.hasAccess(constants.R_OK, this)) {
115
+ if (checkAccess && !hasAccess(this, stats, constants.R_OK)) {
112
116
  throw ErrnoError.With('EACCES', resolved, 'stat');
113
117
  }
114
- return (options === null || options === void 0 ? void 0 : options.bigint) ? new BigIntStats(stats) : stats;
118
+ return (options === null || options === void 0 ? void 0 : options.bigint) ? new BigIntStats(stats) : new Stats(stats);
115
119
  }
116
120
  catch (e) {
117
121
  throw fixError(e, { [resolved]: path });
@@ -123,7 +127,10 @@ export function lstatSync(path, options) {
123
127
  const { fs, path: resolved } = resolveMount(path, this);
124
128
  try {
125
129
  const stats = fs.statSync(resolved);
126
- return (options === null || options === void 0 ? void 0 : options.bigint) ? new BigIntStats(stats) : stats;
130
+ if (checkAccess && !hasAccess(this, stats, constants.R_OK)) {
131
+ throw ErrnoError.With('EACCES', resolved, 'lstat');
132
+ }
133
+ return (options === null || options === void 0 ? void 0 : options.bigint) ? new BigIntStats(stats) : new Stats(stats);
127
134
  }
128
135
  catch (e) {
129
136
  throw fixError(e, { [resolved]: path });
@@ -138,7 +145,7 @@ export function truncateSync(path, len = 0) {
138
145
  if (len < 0) {
139
146
  throw new ErrnoError(Errno.EINVAL);
140
147
  }
141
- file.truncateSync(len);
148
+ file.truncate(len);
142
149
  }
143
150
  catch (e_1) {
144
151
  env_1.error = e_1;
@@ -153,7 +160,7 @@ export function unlinkSync(path) {
153
160
  path = normalizePath(path);
154
161
  const { fs, path: resolved } = resolveMount(path, this);
155
162
  try {
156
- if (config.checkAccess && !fs.statSync(resolved).hasAccess(constants.W_OK, this)) {
163
+ if (checkAccess && !hasAccess(this, fs.statSync(resolved), constants.W_OK)) {
157
164
  throw ErrnoError.With('EACCES', resolved, 'unlink');
158
165
  }
159
166
  fs.unlinkSync(resolved);
@@ -164,20 +171,10 @@ export function unlinkSync(path) {
164
171
  }
165
172
  }
166
173
  unlinkSync;
167
- /**
168
- * Manually apply setuid/setgid.
169
- */
170
- function applySetId(file, uid, gid) {
171
- if (file.fs.attributes.has('setid'))
172
- return;
173
- const parent = file.fs.statSync(dirname(file.path));
174
- file.chownSync(parent.mode & constants.S_ISUID ? parent.uid : uid, // manually apply setuid/setgid
175
- parent.mode & constants.S_ISGID ? parent.gid : gid);
176
- }
177
174
  function _openSync(path, opt) {
178
175
  var _a;
179
176
  path = normalizePath(path);
180
- const mode = normalizeMode(opt.mode, 0o644), flag = parseFlag(opt.flag);
177
+ const mode = normalizeMode(opt.mode, 0o644), flag = flags.parse(opt.flag);
181
178
  path = opt.preserveSymlinks ? path : realpathSync.call(this, path);
182
179
  const { fs, path: resolved } = resolveMount(path, this);
183
180
  let stats;
@@ -188,44 +185,49 @@ function _openSync(path, opt) {
188
185
  // nothing
189
186
  }
190
187
  if (!stats) {
191
- if ((!isWriteable(flag) && !isAppendable(flag)) || flag == 'r+') {
188
+ if (!(flag & constants.O_CREAT)) {
192
189
  throw ErrnoError.With('ENOENT', path, '_open');
193
190
  }
194
191
  // Create the file
195
192
  const parentStats = fs.statSync(dirname(resolved));
196
- if (config.checkAccess && !parentStats.hasAccess(constants.W_OK, this)) {
193
+ if (checkAccess && !hasAccess(this, parentStats, constants.W_OK)) {
197
194
  throw ErrnoError.With('EACCES', dirname(path), '_open');
198
195
  }
199
- if (!parentStats.isDirectory()) {
196
+ if (!isDirectory(parentStats)) {
200
197
  throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
201
198
  }
202
- const { euid: uid, egid: gid } = (_a = this === null || this === void 0 ? void 0 : this.credentials) !== null && _a !== void 0 ? _a : credentials;
203
- const file = fs.createFileSync(resolved, flag, mode, { uid, gid });
204
199
  if (!opt.allowDirectory && mode & constants.S_IFDIR)
205
200
  throw ErrnoError.With('EISDIR', path, '_open');
206
- applySetId(file, uid, gid);
207
- return file;
208
- }
209
- if (config.checkAccess && (!stats.hasAccess(mode, this) || !stats.hasAccess(flagToMode(flag), this))) {
201
+ if (checkAccess && !hasAccess(this, parentStats, constants.W_OK)) {
202
+ throw ErrnoError.With('EACCES', dirname(resolved), '_open');
203
+ }
204
+ const { euid: uid, egid: gid } = (_a = this === null || this === void 0 ? void 0 : this.credentials) !== null && _a !== void 0 ? _a : defaultContext.credentials;
205
+ const inode = fs.createFileSync(resolved, {
206
+ mode,
207
+ uid: parentStats.mode & constants.S_ISUID ? parentStats.uid : uid,
208
+ gid: parentStats.mode & constants.S_ISGID ? parentStats.gid : gid,
209
+ });
210
+ return new SyncHandle(this, path, fs, resolved, flag, inode);
211
+ }
212
+ if (checkAccess && (!hasAccess(this, stats, mode) || !hasAccess(this, stats, flags.toMode(flag)))) {
210
213
  throw ErrnoError.With('EACCES', path, '_open');
211
214
  }
212
- if (isExclusive(flag)) {
215
+ if (flag & constants.O_EXCL)
213
216
  throw ErrnoError.With('EEXIST', path, '_open');
214
- }
215
- const file = fs.openFileSync(resolved, flag);
216
- if (isTruncating(flag)) {
217
- file.truncateSync(0);
218
- }
217
+ const file = new SyncHandle(this, path, fs, resolved, flag, stats);
218
+ if (flag & constants.O_TRUNC)
219
+ file.truncate(0);
219
220
  if (!opt.allowDirectory && stats.mode & constants.S_IFDIR)
220
221
  throw ErrnoError.With('EISDIR', path, '_open');
221
222
  return file;
222
223
  }
223
224
  /**
224
225
  * Synchronous file open.
225
- * @see http://www.manpagez.com/man/2/open/
226
+ * @see https://nodejs.org/api/fs.html#fsopensyncpath-flags-mode
227
+ * @param flag {@link https://nodejs.org/api/fs.html#file-system-flags}
226
228
  */
227
229
  export function openSync(path, flag, mode = constants.F_OK) {
228
- return file2fd(_openSync.call(this, path, { flag, mode }));
230
+ return toFD(_openSync.call(this, path, { flag, mode }));
229
231
  }
230
232
  openSync;
231
233
  /**
@@ -233,18 +235,15 @@ openSync;
233
235
  * @internal
234
236
  */
235
237
  export function lopenSync(path, flag, mode) {
236
- return file2fd(_openSync.call(this, path, { flag, mode, preserveSymlinks: true }));
238
+ return toFD(_openSync.call(this, path, { flag, mode, preserveSymlinks: true }));
237
239
  }
238
240
  function _readFileSync(path, flag, preserveSymlinks) {
239
241
  const env_2 = { stack: [], error: void 0, hasError: false };
240
242
  try {
241
- path = normalizePath(path);
242
- // Get file.
243
- const file = __addDisposableResource(env_2, _openSync.call(this, path, { flag, mode: 0o644, preserveSymlinks }), false);
244
- const stat = file.statSync();
245
- // Allocate buffer.
246
- const data = new Uint8Array(stat.size);
247
- file.readSync(data, 0, stat.size, 0);
243
+ const file = __addDisposableResource(env_2, typeof path == 'number' ? fromFD(this, path) : _openSync.call(this, path.toString(), { flag, mode: 0o644, preserveSymlinks }), false);
244
+ const { size } = file.stat();
245
+ const data = new Uint8Array(size);
246
+ file.read(data, 0, size, 0);
248
247
  return data;
249
248
  }
250
249
  catch (e_2) {
@@ -257,11 +256,11 @@ function _readFileSync(path, flag, preserveSymlinks) {
257
256
  }
258
257
  export function readFileSync(path, _options = {}) {
259
258
  const options = normalizeOptions(_options, null, 'r', 0o644);
260
- const flag = parseFlag(options.flag);
261
- if (!isReadable(flag)) {
259
+ const flag = flags.parse(options.flag);
260
+ if (flag & constants.O_WRONLY) {
262
261
  throw new ErrnoError(Errno.EINVAL, 'Flag passed to readFile must allow for reading');
263
262
  }
264
- const data = Buffer.from(_readFileSync.call(this, typeof path == 'number' ? fd2file(path).path : path, options.flag, false));
263
+ const data = Buffer.from(_readFileSync.call(this, path, options.flag, false));
265
264
  return options.encoding ? data.toString(options.encoding) : data;
266
265
  }
267
266
  readFileSync;
@@ -269,8 +268,8 @@ export function writeFileSync(path, data, _options = {}) {
269
268
  const env_3 = { stack: [], error: void 0, hasError: false };
270
269
  try {
271
270
  const options = normalizeOptions(_options, 'utf8', 'w+', 0o644);
272
- const flag = parseFlag(options.flag);
273
- if (!isWriteable(flag)) {
271
+ const flag = flags.parse(options.flag);
272
+ if (!(flag & constants.O_WRONLY || flag & constants.O_RDWR)) {
274
273
  throw new ErrnoError(Errno.EINVAL, 'Flag passed to writeFile must allow for writing');
275
274
  }
276
275
  if (typeof data != 'string' && !options.encoding) {
@@ -280,12 +279,14 @@ export function writeFileSync(path, data, _options = {}) {
280
279
  if (!encodedData) {
281
280
  throw new ErrnoError(Errno.EINVAL, 'Data not specified');
282
281
  }
283
- const file = __addDisposableResource(env_3, _openSync.call(this, typeof path == 'number' ? fd2file(path).path : path.toString(), {
284
- flag,
285
- mode: options.mode,
286
- preserveSymlinks: true,
287
- }), false);
288
- file.writeSync(encodedData, 0, encodedData.byteLength, 0);
282
+ const file = __addDisposableResource(env_3, typeof path == 'number'
283
+ ? fromFD(this, path)
284
+ : _openSync.call(this, path.toString(), {
285
+ flag,
286
+ mode: options.mode,
287
+ preserveSymlinks: true,
288
+ }), false);
289
+ file.write(encodedData, 0, encodedData.byteLength, 0);
289
290
  emitChange(this, 'change', path.toString());
290
291
  }
291
292
  catch (e_3) {
@@ -307,20 +308,20 @@ export function appendFileSync(filename, data, _options = {}) {
307
308
  const env_4 = { stack: [], error: void 0, hasError: false };
308
309
  try {
309
310
  const options = normalizeOptions(_options, 'utf8', 'a+', 0o644);
310
- const flag = parseFlag(options.flag);
311
- if (!isAppendable(flag)) {
311
+ const flag = flags.parse(options.flag);
312
+ if (!(flag & constants.O_APPEND)) {
312
313
  throw new ErrnoError(Errno.EINVAL, 'Flag passed to appendFile must allow for appending');
313
314
  }
314
315
  if (typeof data != 'string' && !options.encoding) {
315
316
  throw new ErrnoError(Errno.EINVAL, 'Encoding not specified');
316
317
  }
317
318
  const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
318
- const file = __addDisposableResource(env_4, _openSync.call(this, typeof filename == 'number' ? fd2file(filename).path : filename.toString(), {
319
+ const file = __addDisposableResource(env_4, _openSync.call(this, typeof filename == 'number' ? fromFD(this, filename).path : filename.toString(), {
319
320
  flag,
320
321
  mode: options.mode,
321
322
  preserveSymlinks: true,
322
323
  }), false);
323
- file.writeSync(encodedData, 0, encodedData.byteLength);
324
+ file.write(encodedData, 0, encodedData.byteLength);
324
325
  }
325
326
  catch (e_4) {
326
327
  env_4.error = e_4;
@@ -332,13 +333,13 @@ export function appendFileSync(filename, data, _options = {}) {
332
333
  }
333
334
  appendFileSync;
334
335
  export function fstatSync(fd, options) {
335
- const stats = fd2file(fd).statSync();
336
- return (options === null || options === void 0 ? void 0 : options.bigint) ? new BigIntStats(stats) : stats;
336
+ const stats = fromFD(this, fd).stat();
337
+ return (options === null || options === void 0 ? void 0 : options.bigint) ? new BigIntStats(stats) : new Stats(stats);
337
338
  }
338
339
  fstatSync;
339
340
  export function closeSync(fd) {
340
- fd2file(fd).closeSync();
341
- fdMap.delete(fd);
341
+ fromFD(this, fd).close();
342
+ deleteFD(this, fd);
342
343
  }
343
344
  closeSync;
344
345
  export function ftruncateSync(fd, len = 0) {
@@ -346,15 +347,15 @@ export function ftruncateSync(fd, len = 0) {
346
347
  if (len < 0) {
347
348
  throw new ErrnoError(Errno.EINVAL);
348
349
  }
349
- fd2file(fd).truncateSync(len);
350
+ fromFD(this, fd).truncate(len);
350
351
  }
351
352
  ftruncateSync;
352
353
  export function fsyncSync(fd) {
353
- fd2file(fd).syncSync();
354
+ fromFD(this, fd).sync();
354
355
  }
355
356
  fsyncSync;
356
357
  export function fdatasyncSync(fd) {
357
- fd2file(fd).datasyncSync();
358
+ fromFD(this, fd).datasync();
358
359
  }
359
360
  fdatasyncSync;
360
361
  export function writeSync(fd, data, posOrOff, lenOrEnc, pos) {
@@ -374,9 +375,9 @@ export function writeSync(fd, data, posOrOff, lenOrEnc, pos) {
374
375
  length = lenOrEnc;
375
376
  position = typeof pos === 'number' ? pos : null;
376
377
  }
377
- const file = fd2file(fd);
378
+ const file = fromFD(this, fd);
378
379
  position !== null && position !== void 0 ? position : (position = file.position);
379
- const bytesWritten = file.writeSync(buffer, offset, length, position);
380
+ const bytesWritten = file.write(buffer, offset, length, position);
380
381
  emitChange(this, 'change', file.path);
381
382
  return bytesWritten;
382
383
  }
@@ -390,7 +391,7 @@ writeSync;
390
391
  * If position is null, data will be read from the current file position.
391
392
  */
392
393
  export function readSync(fd, buffer, options, length, position) {
393
- const file = fd2file(fd);
394
+ const file = fromFD(this, fd);
394
395
  const offset = typeof options == 'object' ? options.offset : options;
395
396
  if (typeof options == 'object') {
396
397
  length = options.length;
@@ -400,11 +401,11 @@ export function readSync(fd, buffer, options, length, position) {
400
401
  if (isNaN(position)) {
401
402
  position = file.position;
402
403
  }
403
- return file.readSync(buffer, offset, length, position);
404
+ return file.read(buffer, offset, length, position);
404
405
  }
405
406
  readSync;
406
407
  export function fchownSync(fd, uid, gid) {
407
- fd2file(fd).chownSync(uid, gid);
408
+ fromFD(this, fd).chown(uid, gid);
408
409
  }
409
410
  fchownSync;
410
411
  export function fchmodSync(fd, mode) {
@@ -412,14 +413,14 @@ export function fchmodSync(fd, mode) {
412
413
  if (numMode < 0) {
413
414
  throw new ErrnoError(Errno.EINVAL, `Invalid mode.`);
414
415
  }
415
- fd2file(fd).chmodSync(numMode);
416
+ fromFD(this, fd).chmod(numMode);
416
417
  }
417
418
  fchmodSync;
418
419
  /**
419
420
  * Change the file timestamps of a file referenced by the supplied file descriptor.
420
421
  */
421
422
  export function futimesSync(fd, atime, mtime) {
422
- fd2file(fd).utimesSync(normalizeTime(atime), normalizeTime(mtime));
423
+ fromFD(this, fd).utimes(normalizeTime(atime), normalizeTime(mtime));
423
424
  }
424
425
  futimesSync;
425
426
  export function rmdirSync(path) {
@@ -427,10 +428,10 @@ export function rmdirSync(path) {
427
428
  const { fs, path: resolved } = resolveMount(realpathSync.call(this, path), this);
428
429
  try {
429
430
  const stats = fs.statSync(resolved);
430
- if (!stats.isDirectory()) {
431
+ if (!isDirectory(stats)) {
431
432
  throw ErrnoError.With('ENOTDIR', resolved, 'rmdir');
432
433
  }
433
- if (config.checkAccess && !stats.hasAccess(constants.W_OK, this)) {
434
+ if (checkAccess && !hasAccess(this, stats, constants.W_OK)) {
434
435
  throw ErrnoError.With('EACCES', resolved, 'rmdir');
435
436
  }
436
437
  fs.rmdirSync(resolved);
@@ -443,19 +444,27 @@ export function rmdirSync(path) {
443
444
  rmdirSync;
444
445
  export function mkdirSync(path, options) {
445
446
  var _a, _b;
446
- const { euid: uid, egid: gid } = (_a = this === null || this === void 0 ? void 0 : this.credentials) !== null && _a !== void 0 ? _a : credentials;
447
+ const { euid: uid, egid: gid } = (_a = this === null || this === void 0 ? void 0 : this.credentials) !== null && _a !== void 0 ? _a : defaultContext.credentials;
447
448
  options = typeof options === 'object' ? options : { mode: options };
448
449
  const mode = normalizeMode(options === null || options === void 0 ? void 0 : options.mode, 0o777);
449
450
  path = realpathSync.call(this, path);
450
451
  const { fs, path: resolved, root } = resolveMount(path, this);
451
452
  const errorPaths = { [resolved]: path };
453
+ const __create = (path, parent) => {
454
+ if (checkAccess && !hasAccess(this, parent, constants.W_OK)) {
455
+ throw ErrnoError.With('EACCES', dirname(path), 'mkdir');
456
+ }
457
+ const inode = fs.mkdirSync(path, {
458
+ mode,
459
+ uid: parent.mode & constants.S_ISUID ? parent.uid : uid,
460
+ gid: parent.mode & constants.S_ISGID ? parent.gid : gid,
461
+ });
462
+ emitChange(this, 'rename', path);
463
+ return inode;
464
+ };
452
465
  try {
453
466
  if (!(options === null || options === void 0 ? void 0 : options.recursive)) {
454
- if (config.checkAccess && !fs.statSync(dirname(resolved)).hasAccess(constants.W_OK, this)) {
455
- throw ErrnoError.With('EACCES', dirname(resolved), 'mkdir');
456
- }
457
- fs.mkdirSync(resolved, mode, { uid, gid });
458
- applySetId(fs.openFileSync(resolved, 'r+'), uid, gid);
467
+ __create(resolved, fs.statSync(dirname(resolved)));
459
468
  return;
460
469
  }
461
470
  const dirs = [];
@@ -463,13 +472,11 @@ export function mkdirSync(path, options) {
463
472
  dirs.unshift(dir);
464
473
  errorPaths[dir] = original;
465
474
  }
466
- for (const dir of dirs) {
467
- if (config.checkAccess && !fs.statSync(dirname(dir)).hasAccess(constants.W_OK, this)) {
468
- throw ErrnoError.With('EACCES', dirname(dir), 'mkdir');
469
- }
470
- fs.mkdirSync(dir, mode, { uid, gid });
471
- applySetId(fs.openFileSync(dir, 'r+'), uid, gid);
472
- emitChange(this, 'rename', dir);
475
+ if (!dirs.length)
476
+ return;
477
+ const stats = [fs.statSync(dirname(dirs[0]))];
478
+ for (const [i, dir] of dirs.entries()) {
479
+ stats.push(__create(dir, stats[i]));
473
480
  }
474
481
  return root.length == 1 ? dirs[0] : (_b = dirs[0]) === null || _b === void 0 ? void 0 : _b.slice(root.length);
475
482
  }
@@ -485,10 +492,10 @@ export function readdirSync(path, options) {
485
492
  let entries;
486
493
  try {
487
494
  const stats = fs.statSync(resolved);
488
- if (config.checkAccess && !stats.hasAccess(constants.R_OK, this)) {
495
+ if (checkAccess && !hasAccess(this, stats, constants.R_OK)) {
489
496
  throw ErrnoError.With('EACCES', resolved, 'readdir');
490
497
  }
491
- if (!stats.isDirectory()) {
498
+ if (!isDirectory(stats)) {
492
499
  throw ErrnoError.With('ENOTDIR', resolved, 'readdir');
493
500
  }
494
501
  entries = fs.readdirSync(resolved);
@@ -515,7 +522,7 @@ export function readdirSync(path, options) {
515
522
  else {
516
523
  values.push(entry);
517
524
  }
518
- if (!entryStat.isDirectory() || !(options === null || options === void 0 ? void 0 : options.recursive))
525
+ if (!isDirectory(entryStat) || !(options === null || options === void 0 ? void 0 : options.recursive))
519
526
  continue;
520
527
  for (const subEntry of readdirSync.call(this, join(path, entry), options)) {
521
528
  if (subEntry instanceof Dirent) {
@@ -535,11 +542,11 @@ export function readdirSync(path, options) {
535
542
  readdirSync;
536
543
  export function linkSync(targetPath, linkPath) {
537
544
  targetPath = normalizePath(targetPath);
538
- if (config.checkAccess && !statSync(dirname(targetPath)).hasAccess(constants.R_OK, this)) {
545
+ if (checkAccess && !statSync(dirname(targetPath)).hasAccess(constants.R_OK, this)) {
539
546
  throw ErrnoError.With('EACCES', dirname(targetPath), 'link');
540
547
  }
541
548
  linkPath = normalizePath(linkPath);
542
- if (config.checkAccess && !statSync(dirname(linkPath)).hasAccess(constants.W_OK, this)) {
549
+ if (checkAccess && !statSync(dirname(linkPath)).hasAccess(constants.W_OK, this)) {
543
550
  throw ErrnoError.With('EACCES', dirname(linkPath), 'link');
544
551
  }
545
552
  const { fs, path } = resolveMount(targetPath, this);
@@ -548,7 +555,7 @@ export function linkSync(targetPath, linkPath) {
548
555
  throw ErrnoError.With('EXDEV', linkPath, 'link');
549
556
  }
550
557
  try {
551
- if (config.checkAccess && !fs.statSync(path).hasAccess(constants.R_OK, this)) {
558
+ if (checkAccess && !hasAccess(this, fs.statSync(path), constants.R_OK)) {
552
559
  throw ErrnoError.With('EACCES', path, 'link');
553
560
  }
554
561
  return fs.linkSync(path, link.path);
@@ -565,15 +572,23 @@ linkSync;
565
572
  * @param type can be either `'dir'` or `'file'` (default is `'file'`)
566
573
  */
567
574
  export function symlinkSync(target, path, type = 'file') {
568
- if (!['file', 'dir', 'junction'].includes(type)) {
569
- throw new ErrnoError(Errno.EINVAL, 'Invalid type: ' + type);
575
+ const env_5 = { stack: [], error: void 0, hasError: false };
576
+ try {
577
+ if (!['file', 'dir', 'junction'].includes(type)) {
578
+ throw new ErrnoError(Errno.EINVAL, 'Invalid type: ' + type);
579
+ }
580
+ path = normalizePath(path);
581
+ const file = __addDisposableResource(env_5, _openSync.call(this, path, { flag: 'wx', mode: 0o644 }), false);
582
+ file.write(encodeUTF8(normalizePath(target, true)));
583
+ file.chmod(constants.S_IFLNK);
570
584
  }
571
- if (existsSync.call(this, path)) {
572
- throw ErrnoError.With('EEXIST', path.toString(), 'symlink');
585
+ catch (e_5) {
586
+ env_5.error = e_5;
587
+ env_5.hasError = true;
588
+ }
589
+ finally {
590
+ __disposeResources(env_5);
573
591
  }
574
- writeFileSync.call(this, path, normalizePath(target, true));
575
- const file = _openSync.call(this, path, { flag: 'r+', mode: 0o644, preserveSymlinks: true });
576
- file.chmodSync(constants.S_IFLNK);
577
592
  }
578
593
  symlinkSync;
579
594
  export function readlinkSync(path, options) {
@@ -588,26 +603,26 @@ export function readlinkSync(path, options) {
588
603
  readlinkSync;
589
604
  export function chownSync(path, uid, gid) {
590
605
  const fd = openSync.call(this, path, 'r+');
591
- fchownSync(fd, uid, gid);
592
- closeSync(fd);
606
+ fchownSync.call(this, fd, uid, gid);
607
+ closeSync.call(this, fd);
593
608
  }
594
609
  chownSync;
595
610
  export function lchownSync(path, uid, gid) {
596
611
  const fd = lopenSync.call(this, path, 'r+');
597
- fchownSync(fd, uid, gid);
598
- closeSync(fd);
612
+ fchownSync.call(this, fd, uid, gid);
613
+ closeSync.call(this, fd);
599
614
  }
600
615
  lchownSync;
601
616
  export function chmodSync(path, mode) {
602
617
  const fd = openSync.call(this, path, 'r+');
603
- fchmodSync(fd, mode);
604
- closeSync(fd);
618
+ fchmodSync.call(this, fd, mode);
619
+ closeSync.call(this, fd);
605
620
  }
606
621
  chmodSync;
607
622
  export function lchmodSync(path, mode) {
608
623
  const fd = lopenSync.call(this, path, 'r+');
609
- fchmodSync(fd, mode);
610
- closeSync(fd);
624
+ fchmodSync.call(this, fd, mode);
625
+ closeSync.call(this, fd);
611
626
  }
612
627
  lchmodSync;
613
628
  /**
@@ -615,8 +630,8 @@ lchmodSync;
615
630
  */
616
631
  export function utimesSync(path, atime, mtime) {
617
632
  const fd = openSync.call(this, path, 'r+');
618
- futimesSync(fd, atime, mtime);
619
- closeSync(fd);
633
+ futimesSync.call(this, fd, atime, mtime);
634
+ closeSync.call(this, fd);
620
635
  }
621
636
  utimesSync;
622
637
  /**
@@ -624,8 +639,8 @@ utimesSync;
624
639
  */
625
640
  export function lutimesSync(path, atime, mtime) {
626
641
  const fd = lopenSync.call(this, path, 'r+');
627
- futimesSync(fd, atime, mtime);
628
- closeSync(fd);
642
+ futimesSync.call(this, fd, atime, mtime);
643
+ closeSync.call(this, fd);
629
644
  }
630
645
  lutimesSync;
631
646
  /**
@@ -645,10 +660,10 @@ function _resolveSync($, path, preserveSymlinks) {
645
660
  const resolved = resolveMount(path, $);
646
661
  // Stat it to make sure it exists
647
662
  const stats = resolved.fs.statSync(resolved.path);
648
- if (!stats.isSymbolicLink()) {
663
+ if (!isSymbolicLink(stats)) {
649
664
  return { ...resolved, fullPath: path, stats };
650
665
  }
651
- const target = resolve(dirname(path), readlinkSync.call($, path).toString());
666
+ const target = resolve.call($, dirname(path), readlinkSync.call($, path).toString());
652
667
  return _resolveSync($, target);
653
668
  }
654
669
  catch {
@@ -660,10 +675,10 @@ function _resolveSync($, path, preserveSymlinks) {
660
675
  const resolved = resolveMount(maybePath, $);
661
676
  try {
662
677
  const stats = resolved.fs.statSync(resolved.path);
663
- if (!stats.isSymbolicLink()) {
678
+ if (!isSymbolicLink(stats)) {
664
679
  return { ...resolved, fullPath: maybePath, stats };
665
680
  }
666
- const target = resolve(realDir, readlinkSync.call($, maybePath).toString());
681
+ const target = resolve.call($, realDir, readlinkSync.call($, maybePath).toString());
667
682
  return _resolveSync($, target);
668
683
  }
669
684
  catch (e) {
@@ -687,9 +702,9 @@ export function realpathSync(path, options) {
687
702
  }
688
703
  realpathSync;
689
704
  export function accessSync(path, mode = 0o600) {
690
- if (!config.checkAccess)
705
+ if (!checkAccess)
691
706
  return;
692
- if (!statSync.call(this, path).hasAccess(mode, this)) {
707
+ if (!hasAccess(this, statSync.call(this, path), mode)) {
693
708
  throw new ErrnoError(Errno.EACCES);
694
709
  }
695
710
  }
@@ -763,10 +778,10 @@ copyFileSync;
763
778
  * @returns The number of bytes read.
764
779
  */
765
780
  export function readvSync(fd, buffers, position) {
766
- const file = fd2file(fd);
781
+ const file = fromFD(this, fd);
767
782
  let bytesRead = 0;
768
783
  for (const buffer of buffers) {
769
- bytesRead += file.readSync(buffer, 0, buffer.byteLength, position + bytesRead);
784
+ bytesRead += file.read(buffer, 0, buffer.byteLength, position + bytesRead);
770
785
  }
771
786
  return bytesRead;
772
787
  }
@@ -779,10 +794,10 @@ readvSync;
779
794
  * @returns The number of bytes written.
780
795
  */
781
796
  export function writevSync(fd, buffers, position) {
782
- const file = fd2file(fd);
797
+ const file = fromFD(this, fd);
783
798
  let bytesWritten = 0;
784
799
  for (const buffer of buffers) {
785
- bytesWritten += file.writeSync(new Uint8Array(buffer.buffer), 0, buffer.byteLength, position + bytesWritten);
800
+ bytesWritten += file.write(new Uint8Array(buffer.buffer), 0, buffer.byteLength, position + bytesWritten);
786
801
  }
787
802
  return bytesWritten;
788
803
  }
@@ -2,7 +2,7 @@ import type { EventEmitter as NodeEventEmitter } from 'node:events';
2
2
  import type * as fs from 'node:fs';
3
3
  import type { V_Context } from '../context.js';
4
4
  import { EventEmitter } from 'eventemitter3';
5
- import { type Stats } from '../stats.js';
5
+ import { type Stats } from './stats.js';
6
6
  /**
7
7
  * Base class for file system watchers.
8
8
  * Provides event handling capabilities for watching file system changes.
@@ -75,5 +75,5 @@ export declare function removeWatcher(path: string, watcher: FSWatcher): void;
75
75
  /**
76
76
  * @internal @hidden
77
77
  */
78
- export declare function emitChange(context: V_Context, eventType: fs.WatchEventType, filename: string): void;
78
+ export declare function emitChange($: V_Context, eventType: fs.WatchEventType, filename: string): void;
79
79
  export {};
@@ -1,8 +1,8 @@
1
1
  import { EventEmitter } from 'eventemitter3';
2
2
  import { ErrnoError } from '../internal/error.js';
3
- import { isStatsEqual } from '../stats.js';
3
+ import { isStatsEqual } from './stats.js';
4
4
  import { normalizePath } from '../utils.js';
5
- import { basename, dirname, join, relative } from './path.js';
5
+ import { basename, dirname, join, relative } from '../path.js';
6
6
  import { statSync } from './sync.js';
7
7
  /**
8
8
  * Base class for file system watchers.
@@ -138,10 +138,10 @@ export function removeWatcher(path, watcher) {
138
138
  /**
139
139
  * @internal @hidden
140
140
  */
141
- export function emitChange(context, eventType, filename) {
141
+ export function emitChange($, eventType, filename) {
142
142
  var _a;
143
- if (context)
144
- filename = join((_a = context.root) !== null && _a !== void 0 ? _a : '/', filename);
143
+ if ($)
144
+ filename = join((_a = $.root) !== null && _a !== void 0 ? _a : '/', filename);
145
145
  filename = normalizePath(filename);
146
146
  // Notify watchers, including ones on parent directories if they are watching recursively
147
147
  for (let path = filename; path != '/'; path = dirname(path)) {
@@ -149,7 +149,7 @@ export function emitChange(context, eventType, filename) {
149
149
  if (!watchersForPath)
150
150
  continue;
151
151
  for (const watcher of watchersForPath) {
152
- watcher.emit('change', eventType, relative(path, filename) || basename(filename));
152
+ watcher.emit('change', eventType, relative.call(watcher._context, path, filename) || basename(filename));
153
153
  }
154
154
  }
155
155
  }