@zenfs/core 2.4.1 → 2.4.3
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/COPYING.md +24 -0
- package/{readme.md → README.md} +16 -74
- package/dist/backends/backend.d.ts +1 -1
- package/dist/backends/fetch.js +1 -1
- package/dist/backends/memory.js +1 -1
- package/dist/backends/passthrough.d.ts +1 -2
- package/dist/backends/single_buffer.d.ts +1 -1
- package/dist/backends/single_buffer.js +27 -24
- package/dist/backends/store/fs.js +4 -4
- package/dist/config.js +15 -15
- package/dist/context.js +3 -2
- package/dist/index.d.ts +9 -3
- package/dist/index.js +9 -4
- package/dist/internal/contexts.d.ts +5 -4
- package/dist/internal/devices.js +1 -1
- package/dist/internal/error.d.ts +11 -2
- package/dist/internal/error.js +38 -2
- package/dist/internal/file_index.js +1 -1
- package/dist/internal/index.d.ts +1 -0
- package/dist/internal/index.js +2 -1
- package/dist/internal/index_fs.js +1 -1
- package/dist/internal/inode.d.ts +51 -2
- package/dist/internal/inode.js +18 -2
- package/dist/mixins/shared.js +1 -1
- package/dist/node/async.d.ts +278 -0
- package/dist/node/async.js +518 -0
- package/dist/node/compat.d.ts +4 -0
- package/dist/node/compat.js +6 -0
- package/dist/node/dir.d.ts +78 -0
- package/dist/node/dir.js +150 -0
- package/dist/node/index.d.ts +8 -0
- package/dist/node/index.js +8 -0
- package/dist/{vfs → node}/promises.d.ts +10 -66
- package/dist/{vfs → node}/promises.js +141 -478
- package/dist/{vfs → node}/stats.d.ts +0 -4
- package/dist/{vfs → node}/stats.js +1 -16
- package/dist/{vfs → node}/streams.js +2 -2
- package/dist/node/sync.d.ts +252 -0
- package/dist/node/sync.js +682 -0
- package/dist/node/types.d.ts +21 -0
- package/dist/utils.d.ts +1 -7
- package/dist/utils.js +0 -6
- package/dist/vfs/acl.js +1 -1
- package/dist/vfs/async.d.ts +22 -278
- package/dist/vfs/async.js +212 -501
- package/dist/vfs/dir.d.ts +5 -82
- package/dist/vfs/dir.js +5 -233
- package/dist/vfs/file.d.ts +52 -13
- package/dist/vfs/file.js +167 -25
- package/dist/vfs/flags.js +1 -1
- package/dist/vfs/index.d.ts +2 -5
- package/dist/vfs/index.js +2 -5
- package/dist/vfs/shared.d.ts +25 -1
- package/dist/vfs/shared.js +6 -4
- package/dist/vfs/sync.d.ts +17 -245
- package/dist/vfs/sync.js +129 -773
- package/dist/vfs/watchers.d.ts +1 -1
- package/dist/vfs/watchers.js +2 -2
- package/dist/vfs/xattr.js +1 -1
- package/eslint.shared.js +1 -0
- package/package.json +7 -5
- package/scripts/make-index.js +5 -29
- package/scripts/test.js +59 -51
- package/tests/backend/fetch.test.ts +2 -2
- package/tests/backend/port.test.ts +2 -3
- package/tests/backend/single-buffer.test.ts +48 -1
- package/tests/common/casefold.test.ts +1 -1
- package/tests/common/context.test.ts +11 -4
- package/tests/common/devices.test.ts +3 -3
- package/tests/common/handle.test.ts +4 -3
- package/tests/common/inode.test.ts +2 -2
- package/tests/common/mounts.test.ts +1 -3
- package/tests/common/mutex.test.ts +1 -3
- package/tests/common/path.test.ts +2 -2
- package/tests/common/readline.test.ts +1 -1
- package/tests/common.ts +5 -4
- package/tests/fetch/fetch.ts +1 -1
- package/tests/fs/dir.test.ts +3 -43
- package/tests/fs/directory.test.ts +4 -4
- package/tests/fs/errors.test.ts +2 -2
- package/tests/fs/links.test.ts +1 -1
- package/tests/fs/permissions.test.ts +3 -3
- package/tests/fs/read.test.ts +1 -1
- package/tests/fs/scaling.test.ts +1 -1
- package/tests/fs/stat.test.ts +1 -2
- package/tests/fs/times.test.ts +1 -1
- package/tests/fs/watch.test.ts +3 -2
- package/tests/setup/context.ts +1 -2
- package/tests/setup/cow.ts +1 -1
- package/tests/setup/index.ts +2 -2
- package/tests/setup/port.ts +1 -1
- package/tests/setup/single-buffer.ts +1 -1
- package/tests/setup.ts +4 -3
- package/dist/vfs/types.d.ts +0 -24
- package/tests/assignment.ts +0 -21
- /package/dist/{vfs/constants.d.ts → constants.d.ts} +0 -0
- /package/dist/{vfs/constants.js → constants.js} +0 -0
- /package/dist/{readline.d.ts → node/readline.d.ts} +0 -0
- /package/dist/{readline.js → node/readline.js} +0 -0
- /package/dist/{vfs → node}/streams.d.ts +0 -0
- /package/dist/{vfs → node}/types.js +0 -0
|
@@ -51,92 +51,41 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
51
51
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
52
|
});
|
|
53
53
|
import { Buffer } from 'buffer';
|
|
54
|
-
import { Exception, rethrow,
|
|
55
|
-
import {
|
|
56
|
-
import
|
|
57
|
-
import {
|
|
54
|
+
import { Exception, rethrow, UV } from 'kerium';
|
|
55
|
+
import { encodeUTF8 } from 'utilium';
|
|
56
|
+
import * as constants from '../constants.js';
|
|
57
|
+
import { hasAccess, InodeFlags, isDirectory } from '../internal/inode.js';
|
|
58
|
+
import { join, matchesGlob, parse } from '../path.js';
|
|
58
59
|
import '../polyfills.js';
|
|
59
|
-
import {
|
|
60
|
-
import
|
|
61
|
-
import { checkAccess } from '
|
|
62
|
-
import
|
|
60
|
+
import { _tempDirName, globToRegex, normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';
|
|
61
|
+
import * as _async from '../vfs/async.js';
|
|
62
|
+
import { checkAccess } from '../vfs/config.js';
|
|
63
|
+
import { deleteFD, fromFD, toFD } from '../vfs/file.js';
|
|
64
|
+
import * as flags from '../vfs/flags.js';
|
|
65
|
+
import { _statfs, resolveMount } from '../vfs/shared.js';
|
|
66
|
+
import { emitChange, FSWatcher } from '../vfs/watchers.js';
|
|
63
67
|
import { Dir, Dirent } from './dir.js';
|
|
64
|
-
import {
|
|
65
|
-
import
|
|
66
|
-
import { _statfs, resolveMount } from './shared.js';
|
|
67
|
-
import { _chown, BigIntStats, Stats } from './stats.js';
|
|
68
|
+
import { createInterface } from './readline.js';
|
|
69
|
+
import { BigIntStats, Stats } from './stats.js';
|
|
68
70
|
import { ReadStream, WriteStream } from './streams.js';
|
|
69
|
-
|
|
70
|
-
export * as constants from './constants.js';
|
|
71
|
+
export * as constants from '../constants.js';
|
|
71
72
|
export class FileHandle {
|
|
72
73
|
context;
|
|
73
74
|
fd;
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Get the current file position.
|
|
77
|
-
*
|
|
78
|
-
* We emulate the following bug mentioned in the Node documentation:
|
|
79
|
-
*
|
|
80
|
-
* On Linux, positional writes don't work when the file is opened in append mode.
|
|
81
|
-
* The kernel ignores the position argument and always appends the data to the end of the file.
|
|
82
|
-
* @returns The current file position.
|
|
83
|
-
*/
|
|
84
|
-
get position() {
|
|
85
|
-
return this._sync.position;
|
|
86
|
-
}
|
|
87
|
-
set position(value) {
|
|
88
|
-
this._sync.position = value;
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Whether the file has changes which have not been written to the FS
|
|
92
|
-
*/
|
|
93
|
-
dirty = false;
|
|
94
|
-
/**
|
|
95
|
-
* Whether the file is open or closed
|
|
96
|
-
*/
|
|
97
|
-
closed = false;
|
|
98
|
-
/** The path relative to the context's root */
|
|
99
|
-
get path() {
|
|
100
|
-
return this._sync.path;
|
|
101
|
-
}
|
|
102
|
-
/** The internal FS associated with the handle */
|
|
103
|
-
get fs() {
|
|
104
|
-
return this._sync.fs;
|
|
105
|
-
}
|
|
106
|
-
/** The path relative to the `FileSystem`'s root */
|
|
107
|
-
get internalPath() {
|
|
108
|
-
return this._sync.internalPath;
|
|
109
|
-
}
|
|
110
|
-
/** The flag the handle was opened with */
|
|
111
|
-
get flag() {
|
|
112
|
-
return this._sync.flag;
|
|
113
|
-
}
|
|
114
|
-
/** Stats for the handle */
|
|
115
|
-
get inode() {
|
|
116
|
-
return this._sync.inode;
|
|
117
|
-
}
|
|
118
|
-
_sync;
|
|
75
|
+
vfs;
|
|
119
76
|
constructor(context, fd) {
|
|
120
77
|
this.context = context;
|
|
121
78
|
this.fd = fd;
|
|
122
|
-
this.
|
|
123
|
-
}
|
|
124
|
-
get _isSync() {
|
|
125
|
-
return !!(this.flag & constants.O_SYNC || this.inode.flags & InodeFlags.Sync);
|
|
79
|
+
this.vfs = fromFD(context, fd);
|
|
126
80
|
}
|
|
127
81
|
_emitChange() {
|
|
128
|
-
emitChange(this.context, 'change', this.path);
|
|
82
|
+
emitChange(this.context, 'change', this.vfs.path);
|
|
129
83
|
}
|
|
130
84
|
/**
|
|
131
85
|
* Asynchronous fchown(2) - Change ownership of a file.
|
|
132
86
|
*/
|
|
133
87
|
async chown(uid, gid) {
|
|
134
|
-
|
|
135
|
-
throw UV('EBADF', 'chown', this.path);
|
|
136
|
-
this.dirty = true;
|
|
137
|
-
_chown(this.inode, uid, gid);
|
|
138
|
-
if (this._isSync)
|
|
139
|
-
await this.sync();
|
|
88
|
+
await this.vfs.chown(uid, gid);
|
|
140
89
|
this._emitChange();
|
|
141
90
|
}
|
|
142
91
|
/**
|
|
@@ -146,13 +95,8 @@ export class FileHandle {
|
|
|
146
95
|
async chmod(mode) {
|
|
147
96
|
const numMode = normalizeMode(mode, -1);
|
|
148
97
|
if (numMode < 0)
|
|
149
|
-
throw UV('EINVAL', 'chmod', this.path);
|
|
150
|
-
|
|
151
|
-
throw UV('EBADF', 'chmod', this.path);
|
|
152
|
-
this.dirty = true;
|
|
153
|
-
this.inode.mode = (this.inode.mode & (numMode > constants.S_IFMT ? ~constants.S_IFMT : constants.S_IFMT)) | numMode;
|
|
154
|
-
if (this._isSync || numMode > constants.S_IFMT)
|
|
155
|
-
await this.sync();
|
|
98
|
+
throw UV('EINVAL', 'chmod', this.vfs.path);
|
|
99
|
+
await this.vfs.chmod(numMode);
|
|
156
100
|
this._emitChange();
|
|
157
101
|
}
|
|
158
102
|
/**
|
|
@@ -165,36 +109,14 @@ export class FileHandle {
|
|
|
165
109
|
* Asynchronous fsync(2) - synchronize a file's in-core state with the underlying storage device.
|
|
166
110
|
*/
|
|
167
111
|
async sync() {
|
|
168
|
-
|
|
169
|
-
throw UV('EBADF', 'sync', this.path);
|
|
170
|
-
if (!this.dirty)
|
|
171
|
-
return;
|
|
172
|
-
if (!this.fs.attributes.has('no_write'))
|
|
173
|
-
await this.fs.touch(this.internalPath, this.inode);
|
|
174
|
-
this.dirty = false;
|
|
112
|
+
await this.vfs.sync();
|
|
175
113
|
}
|
|
176
114
|
/**
|
|
177
115
|
* Asynchronous ftruncate(2) - Truncate a file to a specified length.
|
|
178
116
|
* @param length If not specified, defaults to `0`.
|
|
179
117
|
*/
|
|
180
118
|
async truncate(length = 0) {
|
|
181
|
-
|
|
182
|
-
throw UV('EBADF', 'truncate', this.path);
|
|
183
|
-
if (length < 0)
|
|
184
|
-
throw UV('EINVAL', 'truncate', this.path);
|
|
185
|
-
if (!(this.flag & constants.O_WRONLY || this.flag & constants.O_RDWR))
|
|
186
|
-
throw UV('EBADF', 'truncate', this.path);
|
|
187
|
-
if (this.fs.attributes.has('readonly'))
|
|
188
|
-
throw UV('EROFS', 'truncate', this.path);
|
|
189
|
-
if (this.inode.flags & InodeFlags.Immutable)
|
|
190
|
-
throw UV('EPERM', 'truncate', this.path);
|
|
191
|
-
this.dirty = true;
|
|
192
|
-
if (!(this.flag & constants.O_WRONLY || this.flag & constants.O_RDWR))
|
|
193
|
-
throw UV('EBADF', 'truncate', this.path);
|
|
194
|
-
this.inode.mtimeMs = Date.now();
|
|
195
|
-
this.inode.size = length;
|
|
196
|
-
if (this._isSync)
|
|
197
|
-
await this.sync();
|
|
119
|
+
await this.vfs.truncate(length);
|
|
198
120
|
this._emitChange();
|
|
199
121
|
}
|
|
200
122
|
/**
|
|
@@ -203,13 +125,9 @@ export class FileHandle {
|
|
|
203
125
|
* @param mtime The last modified time. If a string is provided, it will be coerced to number.
|
|
204
126
|
*/
|
|
205
127
|
async utimes(atime, mtime) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
this.
|
|
209
|
-
this.inode.atimeMs = normalizeTime(atime);
|
|
210
|
-
this.inode.mtimeMs = normalizeTime(mtime);
|
|
211
|
-
if (this._isSync)
|
|
212
|
-
await this.sync();
|
|
128
|
+
atime = normalizeTime(atime);
|
|
129
|
+
mtime = normalizeTime(mtime);
|
|
130
|
+
await this.vfs.utimes(atime, mtime);
|
|
213
131
|
this._emitChange();
|
|
214
132
|
}
|
|
215
133
|
/**
|
|
@@ -225,39 +143,11 @@ export class FileHandle {
|
|
|
225
143
|
const options = normalizeOptions(_options, 'utf8', 'a', 0o644);
|
|
226
144
|
const flag = flags.parse(options.flag);
|
|
227
145
|
if (!(flag & constants.O_APPEND))
|
|
228
|
-
throw UV('EBADF', 'write', this.path);
|
|
146
|
+
throw UV('EBADF', 'write', this.vfs.path);
|
|
229
147
|
const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : data;
|
|
230
|
-
await this.
|
|
148
|
+
await this.vfs.write(encodedData, 0, encodedData.length);
|
|
231
149
|
this._emitChange();
|
|
232
150
|
}
|
|
233
|
-
/**
|
|
234
|
-
* Read data from the file.
|
|
235
|
-
* @param buffer The buffer that the data will be written to.
|
|
236
|
-
* @param offset The offset within the buffer where writing will start.
|
|
237
|
-
* @param length An integer specifying the number of bytes to read.
|
|
238
|
-
* @param position An integer specifying where to begin reading from in the file.
|
|
239
|
-
* If position is unset, data will be read from the current file position.
|
|
240
|
-
*/
|
|
241
|
-
async _read(buffer, offset = 0, length = buffer.byteLength - offset, position = this.position) {
|
|
242
|
-
if (this.closed)
|
|
243
|
-
throw UV('EBADF', 'read', this.path);
|
|
244
|
-
if (this.flag & constants.O_WRONLY)
|
|
245
|
-
throw UV('EBADF', 'read', this.path);
|
|
246
|
-
if (!(this.inode.flags & InodeFlags.NoAtime) && !this.fs.attributes.has('no_atime')) {
|
|
247
|
-
this.dirty = true;
|
|
248
|
-
this.inode.atimeMs = Date.now();
|
|
249
|
-
}
|
|
250
|
-
let end = position + length;
|
|
251
|
-
if (!isCharacterDevice(this.inode) && !isBlockDevice(this.inode) && end > this.inode.size) {
|
|
252
|
-
end = position + Math.max(this.inode.size - position, 0);
|
|
253
|
-
}
|
|
254
|
-
this._sync.position = end;
|
|
255
|
-
const uint8 = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
256
|
-
await this.fs.read(this.internalPath, uint8.subarray(offset, offset + length), position, end);
|
|
257
|
-
if (this._isSync)
|
|
258
|
-
await this.sync();
|
|
259
|
-
return { bytesRead: end - position, buffer };
|
|
260
|
-
}
|
|
261
151
|
async read(buffer, offset, length, position) {
|
|
262
152
|
if (typeof offset == 'object' && offset != null) {
|
|
263
153
|
position = offset.position;
|
|
@@ -270,19 +160,24 @@ export class FileHandle {
|
|
|
270
160
|
offset = buffer.offset;
|
|
271
161
|
buffer = buffer.buffer;
|
|
272
162
|
}
|
|
273
|
-
|
|
274
|
-
|
|
163
|
+
if (position && position > Number.MAX_SAFE_INTEGER)
|
|
164
|
+
throw UV('EINVAL');
|
|
165
|
+
if (typeof position == 'bigint')
|
|
166
|
+
position = Number(position);
|
|
167
|
+
position = Number.isSafeInteger(position) ? position : this.vfs.position;
|
|
168
|
+
buffer ||= new Uint8Array(this.vfs.inode.size);
|
|
275
169
|
offset ??= 0;
|
|
276
|
-
|
|
170
|
+
const bytesRead = await this.vfs.read(buffer, offset, length ?? buffer.byteLength - offset, position);
|
|
171
|
+
return { bytesRead, buffer };
|
|
277
172
|
}
|
|
278
173
|
async readFile(_options) {
|
|
279
174
|
const options = normalizeOptions(_options, null, 'r', 0o444);
|
|
280
175
|
const flag = flags.parse(options.flag);
|
|
281
176
|
if (flag & constants.O_WRONLY)
|
|
282
|
-
throw UV('EBADF', 'read', this.path);
|
|
177
|
+
throw UV('EBADF', 'read', this.vfs.path);
|
|
283
178
|
const { size } = await this.stat();
|
|
284
179
|
const data = new Uint8Array(size);
|
|
285
|
-
await this.
|
|
180
|
+
await this.vfs.read(data, 0, size, 0);
|
|
286
181
|
const buffer = Buffer.from(data);
|
|
287
182
|
return options.encoding ? buffer.toString(options.encoding) : buffer;
|
|
288
183
|
}
|
|
@@ -291,9 +186,9 @@ export class FileHandle {
|
|
|
291
186
|
* The handle will not be closed automatically.
|
|
292
187
|
*/
|
|
293
188
|
readableWebStream(options = {}) {
|
|
294
|
-
if (this.
|
|
295
|
-
throw UV('EBADF', 'readableWebStream', this.path);
|
|
296
|
-
return this.fs.streamRead(this.internalPath, options);
|
|
189
|
+
if (this.vfs.isClosed)
|
|
190
|
+
throw UV('EBADF', 'readableWebStream', this.vfs.path);
|
|
191
|
+
return this.vfs.fs.streamRead(this.vfs.internalPath, options);
|
|
297
192
|
}
|
|
298
193
|
/**
|
|
299
194
|
* Not part of the Node.js API!
|
|
@@ -303,11 +198,11 @@ export class FileHandle {
|
|
|
303
198
|
* @internal
|
|
304
199
|
*/
|
|
305
200
|
writableWebStream(options = {}) {
|
|
306
|
-
if (this.
|
|
307
|
-
throw UV('EBADF', 'writableWebStream', this.path);
|
|
308
|
-
if (this.inode.flags & InodeFlags.Immutable)
|
|
309
|
-
throw UV('EPERM', 'writableWebStream', this.path);
|
|
310
|
-
return this.fs.streamWrite(this.internalPath, options);
|
|
201
|
+
if (this.vfs.isClosed)
|
|
202
|
+
throw UV('EBADF', 'writableWebStream', this.vfs.path);
|
|
203
|
+
if (this.vfs.inode.flags & InodeFlags.Immutable)
|
|
204
|
+
throw UV('EPERM', 'writableWebStream', this.vfs.path);
|
|
205
|
+
return this.vfs.fs.streamWrite(this.vfs.internalPath, options);
|
|
311
206
|
}
|
|
312
207
|
/**
|
|
313
208
|
* Creates a readline Interface object that allows reading the file line by line
|
|
@@ -315,49 +210,19 @@ export class FileHandle {
|
|
|
315
210
|
* @returns A readline interface for reading the file line by line
|
|
316
211
|
*/
|
|
317
212
|
readLines(options) {
|
|
318
|
-
if (this.
|
|
319
|
-
throw UV('EBADF', 'read', this.path);
|
|
213
|
+
if (this.vfs.isClosed || this.vfs.flag & constants.O_WRONLY)
|
|
214
|
+
throw UV('EBADF', 'read', this.vfs.path);
|
|
320
215
|
return createInterface({ input: this.createReadStream(options), crlfDelay: Infinity });
|
|
321
216
|
}
|
|
322
217
|
[Symbol.asyncDispose]() {
|
|
323
218
|
return this.close();
|
|
324
219
|
}
|
|
325
220
|
async stat(opts) {
|
|
326
|
-
if (this.
|
|
327
|
-
throw UV('EBADF', 'stat', this.path);
|
|
328
|
-
if (checkAccess && !hasAccess(this.context, this.inode, constants.R_OK))
|
|
329
|
-
throw UV('EACCES', 'stat', this.path);
|
|
330
|
-
return opts?.bigint ? new BigIntStats(this.inode) : new Stats(this.inode);
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* Write buffer to the file.
|
|
334
|
-
* @param buffer Uint8Array containing the data to write to the file.
|
|
335
|
-
* @param offset Offset in the buffer to start reading data from.
|
|
336
|
-
* @param length The amount of bytes to write to the file.
|
|
337
|
-
* @param position Offset from the beginning of the file where this data should be written.
|
|
338
|
-
* If position is null, the data will be written at the current position.
|
|
339
|
-
*/
|
|
340
|
-
async _write(buffer, offset = 0, length = buffer.byteLength - offset, position = this.position) {
|
|
341
|
-
if (this.closed)
|
|
342
|
-
throw UV('EBADF', 'write', this.path);
|
|
343
|
-
if (this.inode.flags & InodeFlags.Immutable)
|
|
344
|
-
throw UV('EPERM', 'write', this.path);
|
|
345
|
-
if (!(this.flag & constants.O_WRONLY || this.flag & constants.O_RDWR))
|
|
346
|
-
throw UV('EBADF', 'write', this.path);
|
|
347
|
-
if (this.fs.attributes.has('readonly'))
|
|
348
|
-
throw UV('EROFS', 'write', this.path);
|
|
349
|
-
this.dirty = true;
|
|
350
|
-
const end = position + length;
|
|
351
|
-
const slice = buffer.subarray(offset, offset + length);
|
|
352
|
-
if (!isCharacterDevice(this.inode) && !isBlockDevice(this.inode) && end > this.inode.size)
|
|
353
|
-
this.inode.size = end;
|
|
354
|
-
this.inode.mtimeMs = Date.now();
|
|
355
|
-
this.inode.ctimeMs = Date.now();
|
|
356
|
-
this._sync.position = position + slice.byteLength;
|
|
357
|
-
await this.fs.write(this.internalPath, slice, position);
|
|
358
|
-
if (this._isSync)
|
|
359
|
-
await this.sync();
|
|
360
|
-
return slice.byteLength;
|
|
221
|
+
if (this.vfs.isClosed)
|
|
222
|
+
throw UV('EBADF', 'stat', this.vfs.path);
|
|
223
|
+
if (checkAccess && !hasAccess(this.context, this.vfs.inode, constants.R_OK))
|
|
224
|
+
throw UV('EACCES', 'stat', this.vfs.path);
|
|
225
|
+
return opts?.bigint ? new BigIntStats(this.vfs.inode) : new Stats(this.vfs.inode);
|
|
361
226
|
}
|
|
362
227
|
/**
|
|
363
228
|
* Asynchronously writes `string` to the file.
|
|
@@ -384,8 +249,8 @@ export class FileHandle {
|
|
|
384
249
|
length = typeof lenOrEnc == 'number' ? lenOrEnc : buffer.byteLength;
|
|
385
250
|
position = typeof position === 'number' ? position : null;
|
|
386
251
|
}
|
|
387
|
-
position ??= this.position;
|
|
388
|
-
const bytesWritten = await this.
|
|
252
|
+
position ??= this.vfs.position;
|
|
253
|
+
const bytesWritten = await this.vfs.write(buffer, offset, length, position);
|
|
389
254
|
this._emitChange();
|
|
390
255
|
return { buffer: data, bytesWritten };
|
|
391
256
|
}
|
|
@@ -403,31 +268,18 @@ export class FileHandle {
|
|
|
403
268
|
const options = normalizeOptions(_options, 'utf8', 'w', 0o644);
|
|
404
269
|
const flag = flags.parse(options.flag);
|
|
405
270
|
if (!(flag & constants.O_WRONLY || flag & constants.O_RDWR))
|
|
406
|
-
throw UV('EBADF', 'writeFile', this.path);
|
|
271
|
+
throw UV('EBADF', 'writeFile', this.vfs.path);
|
|
407
272
|
const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : data;
|
|
408
|
-
await this.
|
|
273
|
+
await this.vfs.write(encodedData, 0, encodedData.length, 0);
|
|
409
274
|
this._emitChange();
|
|
410
275
|
}
|
|
411
276
|
/**
|
|
412
277
|
* Asynchronous close(2) - close a `FileHandle`.
|
|
413
278
|
*/
|
|
414
279
|
async close() {
|
|
415
|
-
|
|
416
|
-
throw UV('EBADF', 'close', this.path);
|
|
417
|
-
await this.sync();
|
|
418
|
-
this.dispose();
|
|
280
|
+
await this.vfs.close();
|
|
419
281
|
deleteFD(this.context, this.fd);
|
|
420
282
|
}
|
|
421
|
-
/**
|
|
422
|
-
* Cleans up. This will *not* sync the file data to the FS
|
|
423
|
-
*/
|
|
424
|
-
dispose(force) {
|
|
425
|
-
if (this.closed)
|
|
426
|
-
throw UV('EBADF', 'close', this.path);
|
|
427
|
-
if (this.dirty && !force)
|
|
428
|
-
throw UV('EBUSY', 'close', this.path);
|
|
429
|
-
this.closed = true;
|
|
430
|
-
}
|
|
431
283
|
/**
|
|
432
284
|
* Asynchronous `writev`. Writes from multiple buffers.
|
|
433
285
|
* @param buffers An array of Uint8Array buffers.
|
|
@@ -436,7 +288,7 @@ export class FileHandle {
|
|
|
436
288
|
*/
|
|
437
289
|
async writev(buffers, position) {
|
|
438
290
|
if (typeof position == 'number')
|
|
439
|
-
this.position = position;
|
|
291
|
+
this.vfs.position = position;
|
|
440
292
|
let bytesWritten = 0;
|
|
441
293
|
for (const buffer of buffers) {
|
|
442
294
|
bytesWritten += (await this.write(buffer)).bytesWritten;
|
|
@@ -451,7 +303,7 @@ export class FileHandle {
|
|
|
451
303
|
*/
|
|
452
304
|
async readv(buffers, position) {
|
|
453
305
|
if (typeof position == 'number')
|
|
454
|
-
this.position = position;
|
|
306
|
+
this.vfs.position = position;
|
|
455
307
|
let bytesRead = 0;
|
|
456
308
|
for (const buffer of buffers) {
|
|
457
309
|
bytesRead += (await this.read(buffer)).bytesRead;
|
|
@@ -463,8 +315,8 @@ export class FileHandle {
|
|
|
463
315
|
* @param options Options for the readable stream
|
|
464
316
|
*/
|
|
465
317
|
createReadStream(options = {}) {
|
|
466
|
-
if (this.
|
|
467
|
-
throw UV('EBADF', 'createReadStream', this.path);
|
|
318
|
+
if (this.vfs.isClosed || this.vfs.flag & constants.O_WRONLY)
|
|
319
|
+
throw UV('EBADF', 'createReadStream', this.vfs.path);
|
|
468
320
|
return new ReadStream(options, this);
|
|
469
321
|
}
|
|
470
322
|
/**
|
|
@@ -472,52 +324,26 @@ export class FileHandle {
|
|
|
472
324
|
* @param options Options for the writeable stream.
|
|
473
325
|
*/
|
|
474
326
|
createWriteStream(options = {}) {
|
|
475
|
-
if (this.
|
|
476
|
-
throw UV('EBADF', 'createWriteStream', this.path);
|
|
477
|
-
if (this.inode.flags & InodeFlags.Immutable)
|
|
478
|
-
throw UV('EPERM', 'createWriteStream', this.path);
|
|
479
|
-
if (this.fs.attributes.has('readonly'))
|
|
480
|
-
throw UV('EROFS', 'createWriteStream', this.path);
|
|
327
|
+
if (this.vfs.isClosed)
|
|
328
|
+
throw UV('EBADF', 'createWriteStream', this.vfs.path);
|
|
329
|
+
if (this.vfs.inode.flags & InodeFlags.Immutable)
|
|
330
|
+
throw UV('EPERM', 'createWriteStream', this.vfs.path);
|
|
331
|
+
if (this.vfs.fs.attributes.has('readonly'))
|
|
332
|
+
throw UV('EROFS', 'createWriteStream', this.vfs.path);
|
|
481
333
|
return new WriteStream(options, this);
|
|
482
334
|
}
|
|
483
335
|
}
|
|
484
336
|
export async function rename(oldPath, newPath) {
|
|
485
|
-
|
|
486
|
-
__assertType(oldPath);
|
|
487
|
-
newPath = normalizePath(newPath);
|
|
488
|
-
__assertType(newPath);
|
|
489
|
-
const $ex = { syscall: 'rename', path: oldPath, dest: newPath };
|
|
490
|
-
const src = resolveMount(oldPath, this);
|
|
491
|
-
const dst = resolveMount(newPath, this);
|
|
492
|
-
if (src.fs !== dst.fs)
|
|
493
|
-
throw UV('EXDEV', $ex);
|
|
494
|
-
if (dst.path.startsWith(src.path + '/'))
|
|
495
|
-
throw UV('EBUSY', $ex);
|
|
496
|
-
const parent = (await stat.call(this, dirname(oldPath)).catch(rethrow($ex)));
|
|
497
|
-
const stats = (await stat.call(this, oldPath).catch(rethrow($ex)));
|
|
498
|
-
const newParent = (await stat.call(this, dirname(newPath)).catch(rethrow($ex)));
|
|
499
|
-
const newStats = (await stat.call(this, newPath).catch((e) => {
|
|
500
|
-
if (e.code == 'ENOENT')
|
|
501
|
-
return null;
|
|
502
|
-
throw setUVMessage(Object.assign(e, $ex));
|
|
503
|
-
}));
|
|
504
|
-
if (checkAccess && (!parent.hasAccess(constants.R_OK, this) || !newParent.hasAccess(constants.W_OK, this)))
|
|
505
|
-
throw UV('EACCES', $ex);
|
|
506
|
-
if (newStats && !isDirectory(stats) && isDirectory(newStats))
|
|
507
|
-
throw UV('EISDIR', $ex);
|
|
508
|
-
if (newStats && isDirectory(stats) && !isDirectory(newStats))
|
|
509
|
-
throw UV('ENOTDIR', $ex);
|
|
510
|
-
await src.fs.rename(src.path, dst.path).catch(rethrow($ex));
|
|
511
|
-
emitChange(this, 'rename', oldPath);
|
|
512
|
-
emitChange(this, 'change', newPath);
|
|
337
|
+
await _async.rename.call(this, oldPath, newPath);
|
|
513
338
|
}
|
|
514
339
|
rename;
|
|
515
340
|
/**
|
|
516
341
|
* Test whether or not `path` exists by checking with the file system.
|
|
517
342
|
*/
|
|
518
343
|
export async function exists(path) {
|
|
344
|
+
path = normalizePath(path);
|
|
519
345
|
try {
|
|
520
|
-
const { fs, path: resolved } =
|
|
346
|
+
const { fs, path: resolved } = await _async.resolve(this, path);
|
|
521
347
|
return await fs.exists(resolved);
|
|
522
348
|
}
|
|
523
349
|
catch (e) {
|
|
@@ -529,7 +355,7 @@ export async function exists(path) {
|
|
|
529
355
|
}
|
|
530
356
|
export async function stat(path, options) {
|
|
531
357
|
path = normalizePath(path);
|
|
532
|
-
const { fs, path: resolved } =
|
|
358
|
+
const { fs, path: resolved } = await _async.resolve(this, path);
|
|
533
359
|
const $ex = { syscall: 'stat', path };
|
|
534
360
|
const stats = await fs.stat(resolved).catch(rethrow($ex));
|
|
535
361
|
if (checkAccess && !hasAccess(this, stats, constants.R_OK))
|
|
@@ -540,9 +366,9 @@ stat;
|
|
|
540
366
|
export async function lstat(path, options) {
|
|
541
367
|
path = normalizePath(path);
|
|
542
368
|
const $ex = { syscall: 'lstat', path };
|
|
543
|
-
|
|
544
|
-
const { fs, path:
|
|
545
|
-
const stats = await fs.stat(
|
|
369
|
+
const { base, dir } = parse(path);
|
|
370
|
+
const { fs, path: parent } = await _async.resolve(this, dir);
|
|
371
|
+
const stats = await fs.stat(base ? join(parent, base) : parent).catch(rethrow($ex));
|
|
546
372
|
if (checkAccess && !hasAccess(this, stats, constants.R_OK))
|
|
547
373
|
throw UV('EACCES', $ex);
|
|
548
374
|
return options?.bigint ? new BigIntStats(stats) : new Stats(stats);
|
|
@@ -576,45 +402,6 @@ export async function unlink(path) {
|
|
|
576
402
|
emitChange(this, 'rename', path.toString());
|
|
577
403
|
}
|
|
578
404
|
unlink;
|
|
579
|
-
/**
|
|
580
|
-
* Opens a file. This helper handles the complexity of file flags.
|
|
581
|
-
* @internal
|
|
582
|
-
*/
|
|
583
|
-
async function _open($, path, opt) {
|
|
584
|
-
path = normalizePath(path);
|
|
585
|
-
const mode = normalizeMode(opt.mode, 0o644), flag = flags.parse(opt.flag);
|
|
586
|
-
const $ex = { syscall: 'open', path };
|
|
587
|
-
const { fs, path: resolved, stats } = await _resolve($, path.toString(), opt.preserveSymlinks);
|
|
588
|
-
if (!stats) {
|
|
589
|
-
if (!(flag & constants.O_CREAT))
|
|
590
|
-
throw UV('ENOENT', $ex);
|
|
591
|
-
// Create the file
|
|
592
|
-
const parentStats = await fs.stat(dirname(resolved));
|
|
593
|
-
if (checkAccess && !hasAccess($, parentStats, constants.W_OK))
|
|
594
|
-
throw UV('EACCES', 'open', dirname(path));
|
|
595
|
-
if (!isDirectory(parentStats))
|
|
596
|
-
throw UV('ENOTDIR', 'open', dirname(path));
|
|
597
|
-
if (!opt.allowDirectory && mode & constants.S_IFDIR)
|
|
598
|
-
throw UV('EISDIR', 'open', path);
|
|
599
|
-
const { euid: uid, egid: gid } = $?.credentials ?? defaultContext.credentials;
|
|
600
|
-
const inode = await fs.createFile(resolved, {
|
|
601
|
-
mode,
|
|
602
|
-
uid: parentStats.mode & constants.S_ISUID ? parentStats.uid : uid,
|
|
603
|
-
gid: parentStats.mode & constants.S_ISGID ? parentStats.gid : gid,
|
|
604
|
-
});
|
|
605
|
-
return new FileHandle($, toFD(new SyncHandle($, path, fs, resolved, flag, inode)));
|
|
606
|
-
}
|
|
607
|
-
if (checkAccess && !hasAccess($, stats, flags.toMode(flag)))
|
|
608
|
-
throw UV('EACCES', $ex);
|
|
609
|
-
if (flag & constants.O_EXCL)
|
|
610
|
-
throw UV('EEXIST', $ex);
|
|
611
|
-
const handle = new FileHandle($, toFD(new SyncHandle($, path, fs, resolved, flag, stats)));
|
|
612
|
-
if (!opt.allowDirectory && mode & constants.S_IFDIR)
|
|
613
|
-
throw UV('EISDIR', 'open', path);
|
|
614
|
-
if (flag & constants.O_TRUNC)
|
|
615
|
-
await handle.truncate(0);
|
|
616
|
-
return handle;
|
|
617
|
-
}
|
|
618
405
|
/**
|
|
619
406
|
* Asynchronous file open.
|
|
620
407
|
* @see https://nodejs.org/api/fs.html#fspromisesopenpath-flags-mode
|
|
@@ -622,7 +409,8 @@ async function _open($, path, opt) {
|
|
|
622
409
|
* @param mode Mode to use to open the file. Can be ignored if the filesystem doesn't support permissions.
|
|
623
410
|
*/
|
|
624
411
|
export async function open(path, flag = 'r', mode = 0o644) {
|
|
625
|
-
|
|
412
|
+
const handle = await _async.open(this, path, { flag, mode });
|
|
413
|
+
return new FileHandle(this, toFD(handle));
|
|
626
414
|
}
|
|
627
415
|
open;
|
|
628
416
|
export async function readFile(path, _options) {
|
|
@@ -683,7 +471,7 @@ export async function appendFile(path, data, _options) {
|
|
|
683
471
|
try {
|
|
684
472
|
const options = normalizeOptions(_options, 'utf8', 'a', 0o644);
|
|
685
473
|
const flag = flags.parse(options.flag);
|
|
686
|
-
const $ex = { syscall: 'write', path: path instanceof FileHandle ? path.path : path.toString() };
|
|
474
|
+
const $ex = { syscall: 'write', path: path instanceof FileHandle ? path['vfs'].path : path.toString() };
|
|
687
475
|
if (!(flag & constants.O_APPEND))
|
|
688
476
|
throw UV('EBADF', $ex);
|
|
689
477
|
const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
@@ -702,8 +490,8 @@ export async function appendFile(path, data, _options) {
|
|
|
702
490
|
}
|
|
703
491
|
appendFile;
|
|
704
492
|
export async function rmdir(path) {
|
|
705
|
-
path =
|
|
706
|
-
const { fs, path: resolved } =
|
|
493
|
+
path = normalizePath(path);
|
|
494
|
+
const { fs, path: resolved } = await _async.resolve(this, path);
|
|
707
495
|
const $ex = { syscall: 'rmdir', path };
|
|
708
496
|
const stats = await fs.stat(resolved).catch(rethrow($ex));
|
|
709
497
|
if (!stats)
|
|
@@ -717,103 +505,32 @@ export async function rmdir(path) {
|
|
|
717
505
|
}
|
|
718
506
|
rmdir;
|
|
719
507
|
export async function mkdir(path, options) {
|
|
720
|
-
const { euid: uid, egid: gid } = this?.credentials ?? defaultContext.credentials;
|
|
721
508
|
options = typeof options === 'object' ? options : { mode: options };
|
|
722
509
|
const mode = normalizeMode(options?.mode, 0o777);
|
|
723
|
-
|
|
724
|
-
const { fs, path: resolved } = resolveMount(path, this);
|
|
725
|
-
const __create = async (path, resolved, parent) => {
|
|
726
|
-
if (checkAccess && !hasAccess(this, parent, constants.W_OK))
|
|
727
|
-
throw UV('EACCES', 'mkdir', dirname(path));
|
|
728
|
-
const inode = await fs
|
|
729
|
-
.mkdir(resolved, {
|
|
730
|
-
mode,
|
|
731
|
-
uid: parent.mode & constants.S_ISUID ? parent.uid : uid,
|
|
732
|
-
gid: parent.mode & constants.S_ISGID ? parent.gid : gid,
|
|
733
|
-
})
|
|
734
|
-
.catch(rethrow({ syscall: 'mkdir', path }));
|
|
735
|
-
emitChange(this, 'rename', path);
|
|
736
|
-
return inode;
|
|
737
|
-
};
|
|
738
|
-
if (!options?.recursive) {
|
|
739
|
-
await __create(path, resolved, await fs.stat(dirname(resolved)).catch(rethrow({ path: dirname(path) })));
|
|
740
|
-
return;
|
|
741
|
-
}
|
|
742
|
-
const dirs = [];
|
|
743
|
-
let origDir = path;
|
|
744
|
-
for (let dir = resolved; !(await fs.exists(dir).catch(rethrow({ syscall: 'exists', path: origDir }))); dir = dirname(dir), origDir = dirname(origDir)) {
|
|
745
|
-
dirs.unshift([origDir, dir]);
|
|
746
|
-
}
|
|
747
|
-
if (!dirs.length)
|
|
748
|
-
return;
|
|
749
|
-
const stats = [await fs.stat(dirname(dirs[0][1])).catch(rethrow({ syscall: 'stat', path: dirname(dirs[0][0]) }))];
|
|
750
|
-
for (const [i, [path, resolved]] of dirs.entries()) {
|
|
751
|
-
stats.push(await __create(path, resolved, stats[i]));
|
|
752
|
-
}
|
|
753
|
-
return dirs[0][0];
|
|
510
|
+
return await _async.mkdir.call(this, path, { ...options, mode });
|
|
754
511
|
}
|
|
755
512
|
mkdir;
|
|
756
|
-
export async function readdir(
|
|
513
|
+
export async function readdir(path, options) {
|
|
514
|
+
path = normalizePath(path);
|
|
757
515
|
const opt = typeof options === 'object' && options != null ? options : { encoding: options, withFileTypes: false, recursive: false };
|
|
758
|
-
const
|
|
759
|
-
const { fs, path: resolved } = resolveMount(path, this);
|
|
760
|
-
const $ex = { syscall: 'readdir', path };
|
|
761
|
-
const stats = await fs.stat(resolved).catch(rethrow({ syscall: 'stat', path }));
|
|
762
|
-
if (!stats)
|
|
763
|
-
throw UV('ENOENT', $ex);
|
|
764
|
-
if (checkAccess && !hasAccess(this, stats, constants.R_OK))
|
|
765
|
-
throw UV('EACCES', $ex);
|
|
766
|
-
if (!isDirectory(stats))
|
|
767
|
-
throw UV('ENOTDIR', $ex);
|
|
768
|
-
const entries = await fs.readdir(resolved).catch(rethrow($ex));
|
|
516
|
+
const rawEntries = await _async.readdir.call(this, path, opt);
|
|
769
517
|
const values = [];
|
|
770
|
-
const
|
|
771
|
-
let entryStats;
|
|
772
|
-
if (opt.recursive || opt.withFileTypes) {
|
|
773
|
-
entryStats = await fs.stat(join(resolved, entry)).catch((e) => {
|
|
774
|
-
if (e.code == 'ENOENT')
|
|
775
|
-
return;
|
|
776
|
-
throw setUVMessage(Object.assign(e, { syscall: 'stat', path: join(path, entry) }));
|
|
777
|
-
});
|
|
778
|
-
if (!entryStats)
|
|
779
|
-
return;
|
|
780
|
-
}
|
|
518
|
+
for (const entry of rawEntries) {
|
|
781
519
|
if (opt.withFileTypes) {
|
|
782
|
-
values.push(Dirent.from(
|
|
520
|
+
values.push(Dirent.from(entry, opt.encoding));
|
|
783
521
|
}
|
|
784
522
|
else if (opt.encoding == 'buffer') {
|
|
785
|
-
values.push(Buffer.from(entry));
|
|
523
|
+
values.push(Buffer.from(entry.path));
|
|
786
524
|
}
|
|
787
525
|
else {
|
|
788
|
-
values.push(entry);
|
|
526
|
+
values.push(entry.path);
|
|
789
527
|
}
|
|
790
|
-
|
|
791
|
-
return;
|
|
792
|
-
const children = await fs.readdir(join(resolved, entry)).catch(rethrow({ syscall: 'readdir', path: join(path, entry) }));
|
|
793
|
-
for (const child of children)
|
|
794
|
-
await addEntry(join(entry, child));
|
|
795
|
-
};
|
|
796
|
-
await Promise.all(entries.map(addEntry));
|
|
528
|
+
}
|
|
797
529
|
return values;
|
|
798
530
|
}
|
|
799
531
|
readdir;
|
|
800
532
|
export async function link(path, dest) {
|
|
801
|
-
|
|
802
|
-
dest = normalizePath(dest);
|
|
803
|
-
const { fs, path: resolved } = resolveMount(path, this);
|
|
804
|
-
const dst = resolveMount(dest, this);
|
|
805
|
-
const $ex = { syscall: 'link', path };
|
|
806
|
-
if (fs != dst.fs)
|
|
807
|
-
throw UV('EXDEV', $ex);
|
|
808
|
-
const stats = await fs.stat(dirname(resolved)).catch(rethrow({ syscall: 'stat', path: dirname(path) }));
|
|
809
|
-
if (checkAccess && !hasAccess(this, stats, constants.R_OK))
|
|
810
|
-
throw UV('EACCES', 'link', dirname(path));
|
|
811
|
-
// We need to use the VFS here since the link path may be a mount point
|
|
812
|
-
if (checkAccess && !(await stat.call(this, dirname(dest))).hasAccess(constants.W_OK, this))
|
|
813
|
-
throw UV('EACCES', 'link', dirname(dest));
|
|
814
|
-
if (checkAccess && !hasAccess(this, await fs.stat(resolved).catch(rethrow($ex)), constants.R_OK))
|
|
815
|
-
throw UV('EACCES', $ex);
|
|
816
|
-
return await fs.link(resolved, dst.path).catch(rethrow($ex));
|
|
533
|
+
return await _async.link.call(this, path, dest);
|
|
817
534
|
}
|
|
818
535
|
link;
|
|
819
536
|
/**
|
|
@@ -830,8 +547,9 @@ export async function symlink(dest, path, type = 'file') {
|
|
|
830
547
|
path = normalizePath(path);
|
|
831
548
|
if (await exists.call(this, path))
|
|
832
549
|
throw UV('EEXIST', 'symlink', path);
|
|
833
|
-
const handle = __addDisposableResource(env_5, await
|
|
834
|
-
|
|
550
|
+
const handle = __addDisposableResource(env_5, await _async.open(this, path, { flag: 'w+', mode: 0o644, preserveSymlinks: true }), true);
|
|
551
|
+
const encoded = encodeUTF8(normalizePath(dest, true));
|
|
552
|
+
await handle.write(encoded, 0, encoded.length, 0);
|
|
835
553
|
await handle.chmod(constants.S_IFLNK);
|
|
836
554
|
}
|
|
837
555
|
catch (e_5) {
|
|
@@ -846,17 +564,18 @@ export async function symlink(dest, path, type = 'file') {
|
|
|
846
564
|
}
|
|
847
565
|
symlink;
|
|
848
566
|
export async function readlink(path, options) {
|
|
567
|
+
path = normalizePath(path);
|
|
568
|
+
const buf = Buffer.from(await _async.readlink.call(this, path), 'utf-8');
|
|
569
|
+
const encoding = typeof options == 'object' ? options?.encoding : options;
|
|
570
|
+
// always defaults to utf-8 to avoid wrangler (cloudflare) worker "unknown encoding" exception
|
|
571
|
+
return encoding == 'buffer' ? buf : buf.toString((encoding ?? 'utf-8'));
|
|
572
|
+
}
|
|
573
|
+
readlink;
|
|
574
|
+
export async function chown(path, uid, gid) {
|
|
849
575
|
const env_6 = { stack: [], error: void 0, hasError: false };
|
|
850
576
|
try {
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
const handle = __addDisposableResource(env_6, await _open(this, path, { flag: 'r', mode: 0o644, preserveSymlinks: true }), true);
|
|
854
|
-
if (!isSymbolicLink(handle.inode))
|
|
855
|
-
throw UV('EINVAL', 'readlink', path);
|
|
856
|
-
const value = await handle.readFile();
|
|
857
|
-
const encoding = typeof options == 'object' ? options?.encoding : options;
|
|
858
|
-
// always defaults to utf-8 to avoid wrangler (cloudflare) worker "unknown encoding" exception
|
|
859
|
-
return encoding == 'buffer' ? value : value.toString((encoding ?? 'utf-8'));
|
|
577
|
+
const handle = __addDisposableResource(env_6, await open.call(this, path, 'r+'), true);
|
|
578
|
+
await handle.chown(uid, gid);
|
|
860
579
|
}
|
|
861
580
|
catch (e_6) {
|
|
862
581
|
env_6.error = e_6;
|
|
@@ -868,11 +587,16 @@ export async function readlink(path, options) {
|
|
|
868
587
|
await result_6;
|
|
869
588
|
}
|
|
870
589
|
}
|
|
871
|
-
|
|
872
|
-
export async function
|
|
590
|
+
chown;
|
|
591
|
+
export async function lchown(path, uid, gid) {
|
|
873
592
|
const env_7 = { stack: [], error: void 0, hasError: false };
|
|
874
593
|
try {
|
|
875
|
-
const handle = __addDisposableResource(env_7, await open
|
|
594
|
+
const handle = __addDisposableResource(env_7, await _async.open(this, path, {
|
|
595
|
+
flag: 'r+',
|
|
596
|
+
mode: 0o644,
|
|
597
|
+
preserveSymlinks: true,
|
|
598
|
+
allowDirectory: true,
|
|
599
|
+
}), true);
|
|
876
600
|
await handle.chown(uid, gid);
|
|
877
601
|
}
|
|
878
602
|
catch (e_7) {
|
|
@@ -885,17 +609,12 @@ export async function chown(path, uid, gid) {
|
|
|
885
609
|
await result_7;
|
|
886
610
|
}
|
|
887
611
|
}
|
|
888
|
-
|
|
889
|
-
export async function
|
|
612
|
+
lchown;
|
|
613
|
+
export async function chmod(path, mode) {
|
|
890
614
|
const env_8 = { stack: [], error: void 0, hasError: false };
|
|
891
615
|
try {
|
|
892
|
-
const handle = __addDisposableResource(env_8, await
|
|
893
|
-
|
|
894
|
-
mode: 0o644,
|
|
895
|
-
preserveSymlinks: true,
|
|
896
|
-
allowDirectory: true,
|
|
897
|
-
}), true);
|
|
898
|
-
await handle.chown(uid, gid);
|
|
616
|
+
const handle = __addDisposableResource(env_8, await open.call(this, path, 'r+'), true);
|
|
617
|
+
await handle.chmod(mode);
|
|
899
618
|
}
|
|
900
619
|
catch (e_8) {
|
|
901
620
|
env_8.error = e_8;
|
|
@@ -907,11 +626,17 @@ export async function lchown(path, uid, gid) {
|
|
|
907
626
|
await result_8;
|
|
908
627
|
}
|
|
909
628
|
}
|
|
910
|
-
|
|
911
|
-
export async function
|
|
629
|
+
chmod;
|
|
630
|
+
export async function lchmod(path, mode) {
|
|
912
631
|
const env_9 = { stack: [], error: void 0, hasError: false };
|
|
913
632
|
try {
|
|
914
|
-
|
|
633
|
+
mode = normalizeMode(mode);
|
|
634
|
+
const handle = __addDisposableResource(env_9, await _async.open(this, path, {
|
|
635
|
+
flag: 'r+',
|
|
636
|
+
mode: 0o644,
|
|
637
|
+
preserveSymlinks: true,
|
|
638
|
+
allowDirectory: true,
|
|
639
|
+
}), true);
|
|
915
640
|
await handle.chmod(mode);
|
|
916
641
|
}
|
|
917
642
|
catch (e_9) {
|
|
@@ -924,17 +649,18 @@ export async function chmod(path, mode) {
|
|
|
924
649
|
await result_9;
|
|
925
650
|
}
|
|
926
651
|
}
|
|
927
|
-
|
|
928
|
-
|
|
652
|
+
lchmod;
|
|
653
|
+
/**
|
|
654
|
+
* Change file timestamps of the file referenced by the supplied path.
|
|
655
|
+
*/
|
|
656
|
+
export async function utimes(path, atime, mtime) {
|
|
929
657
|
const env_10 = { stack: [], error: void 0, hasError: false };
|
|
930
658
|
try {
|
|
931
|
-
const handle = __addDisposableResource(env_10, await
|
|
659
|
+
const handle = __addDisposableResource(env_10, await _async.open(this, path, {
|
|
932
660
|
flag: 'r+',
|
|
933
|
-
mode: 0o644,
|
|
934
|
-
preserveSymlinks: true,
|
|
935
661
|
allowDirectory: true,
|
|
936
662
|
}), true);
|
|
937
|
-
await handle.
|
|
663
|
+
await handle.utimes(normalizeTime(atime), normalizeTime(mtime));
|
|
938
664
|
}
|
|
939
665
|
catch (e_10) {
|
|
940
666
|
env_10.error = e_10;
|
|
@@ -946,99 +672,36 @@ export async function lchmod(path, mode) {
|
|
|
946
672
|
await result_10;
|
|
947
673
|
}
|
|
948
674
|
}
|
|
949
|
-
lchmod;
|
|
950
|
-
/**
|
|
951
|
-
* Change file timestamps of the file referenced by the supplied path.
|
|
952
|
-
*/
|
|
953
|
-
export async function utimes(path, atime, mtime) {
|
|
954
|
-
const env_11 = { stack: [], error: void 0, hasError: false };
|
|
955
|
-
try {
|
|
956
|
-
const handle = __addDisposableResource(env_11, await open.call(this, path, 'r+'), true);
|
|
957
|
-
await handle.utimes(atime, mtime);
|
|
958
|
-
}
|
|
959
|
-
catch (e_11) {
|
|
960
|
-
env_11.error = e_11;
|
|
961
|
-
env_11.hasError = true;
|
|
962
|
-
}
|
|
963
|
-
finally {
|
|
964
|
-
const result_11 = __disposeResources(env_11);
|
|
965
|
-
if (result_11)
|
|
966
|
-
await result_11;
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
675
|
utimes;
|
|
970
676
|
/**
|
|
971
677
|
* Change file timestamps of the file referenced by the supplied path.
|
|
972
678
|
*/
|
|
973
679
|
export async function lutimes(path, atime, mtime) {
|
|
974
|
-
const
|
|
680
|
+
const env_11 = { stack: [], error: void 0, hasError: false };
|
|
975
681
|
try {
|
|
976
|
-
const handle = __addDisposableResource(
|
|
682
|
+
const handle = __addDisposableResource(env_11, await _async.open(this, path, {
|
|
977
683
|
flag: 'r+',
|
|
978
684
|
mode: 0o644,
|
|
979
685
|
preserveSymlinks: true,
|
|
980
686
|
allowDirectory: true,
|
|
981
687
|
}), true);
|
|
982
|
-
await handle.utimes(
|
|
688
|
+
await handle.utimes(normalizeTime(atime), normalizeTime(mtime));
|
|
983
689
|
}
|
|
984
|
-
catch (
|
|
985
|
-
|
|
986
|
-
|
|
690
|
+
catch (e_11) {
|
|
691
|
+
env_11.error = e_11;
|
|
692
|
+
env_11.hasError = true;
|
|
987
693
|
}
|
|
988
694
|
finally {
|
|
989
|
-
const
|
|
990
|
-
if (
|
|
991
|
-
await
|
|
695
|
+
const result_11 = __disposeResources(env_11);
|
|
696
|
+
if (result_11)
|
|
697
|
+
await result_11;
|
|
992
698
|
}
|
|
993
699
|
}
|
|
994
700
|
lutimes;
|
|
995
|
-
/**
|
|
996
|
-
* Resolves the mount and real path for a path.
|
|
997
|
-
* Additionally, any stats fetched will be returned for de-duplication
|
|
998
|
-
* @internal @hidden
|
|
999
|
-
*/
|
|
1000
|
-
async function _resolve($, path, preserveSymlinks) {
|
|
1001
|
-
if (preserveSymlinks) {
|
|
1002
|
-
const resolved = resolveMount(path, $);
|
|
1003
|
-
const stats = await resolved.fs.stat(resolved.path).catch(() => undefined);
|
|
1004
|
-
return { ...resolved, fullPath: path, stats };
|
|
1005
|
-
}
|
|
1006
|
-
/* Try to resolve it directly. If this works,
|
|
1007
|
-
that means we don't need to perform any resolution for parent directories. */
|
|
1008
|
-
try {
|
|
1009
|
-
const resolved = resolveMount(path, $);
|
|
1010
|
-
// Stat it to make sure it exists
|
|
1011
|
-
const stats = await resolved.fs.stat(resolved.path);
|
|
1012
|
-
if (!isSymbolicLink(stats)) {
|
|
1013
|
-
return { ...resolved, fullPath: path, stats };
|
|
1014
|
-
}
|
|
1015
|
-
const target = resolve.call($, dirname(path), (await readlink.call($, path)).toString());
|
|
1016
|
-
return await _resolve($, target);
|
|
1017
|
-
}
|
|
1018
|
-
catch {
|
|
1019
|
-
// Go the long way
|
|
1020
|
-
}
|
|
1021
|
-
const { base, dir } = parse(path);
|
|
1022
|
-
const realDir = dir == '/' ? '/' : await realpath.call($, dir);
|
|
1023
|
-
const maybePath = join(realDir, base);
|
|
1024
|
-
const resolved = resolveMount(maybePath, $);
|
|
1025
|
-
const stats = await resolved.fs.stat(resolved.path).catch((e) => {
|
|
1026
|
-
if (e.code == 'ENOENT')
|
|
1027
|
-
return;
|
|
1028
|
-
throw setUVMessage(Object.assign(e, { syscall: 'stat', path: maybePath }));
|
|
1029
|
-
});
|
|
1030
|
-
if (!stats)
|
|
1031
|
-
return { ...resolved, fullPath: path };
|
|
1032
|
-
if (!isSymbolicLink(stats)) {
|
|
1033
|
-
return { ...resolved, fullPath: maybePath, stats };
|
|
1034
|
-
}
|
|
1035
|
-
const target = resolve.call($, realDir, (await readlink.call($, maybePath)).toString());
|
|
1036
|
-
return await _resolve($, target);
|
|
1037
|
-
}
|
|
1038
701
|
export async function realpath(path, options) {
|
|
1039
702
|
const encoding = typeof options == 'string' ? options : (options?.encoding ?? 'utf8');
|
|
1040
703
|
path = normalizePath(path);
|
|
1041
|
-
const { fullPath } = await
|
|
704
|
+
const { fullPath } = await _async.resolve(this, path);
|
|
1042
705
|
if (encoding == 'utf8' || encoding == 'utf-8')
|
|
1043
706
|
return fullPath;
|
|
1044
707
|
const buf = Buffer.from(fullPath, 'utf-8');
|