@zenfs/core 2.4.0 → 2.4.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.
- package/COPYING.md +18 -0
- package/{readme.md → README.md} +16 -74
- 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.js +1 -1
- 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/path.js +3 -25
- 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 +1 -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
package/dist/vfs/async.js
CHANGED
|
@@ -1,518 +1,229 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { setUVMessage, UV } from 'kerium';
|
|
2
|
+
import { decodeUTF8 } from 'utilium';
|
|
3
|
+
import * as constants from '../constants.js';
|
|
4
|
+
import { defaultContext } from '../internal/contexts.js';
|
|
5
|
+
import { hasAccess, isDirectory, isSymbolicLink } from '../internal/inode.js';
|
|
6
|
+
import { basename, dirname, join, parse, resolve as resolvePath } from '../path.js';
|
|
3
7
|
import { normalizeMode, normalizePath } from '../utils.js';
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
|
|
8
|
+
import { checkAccess } from './config.js';
|
|
9
|
+
import { Dirent, ifToDt } from './dir.js';
|
|
10
|
+
import { Handle } from './file.js';
|
|
11
|
+
import * as flags from './flags.js';
|
|
12
|
+
import { resolveMount } from './shared.js';
|
|
13
|
+
import { emitChange } from './watchers.js';
|
|
10
14
|
/**
|
|
11
|
-
*
|
|
15
|
+
* Resolves the mount and real path for a path.
|
|
16
|
+
* Additionally, any stats fetched will be returned for de-duplication
|
|
17
|
+
* @internal @hidden
|
|
12
18
|
*/
|
|
13
|
-
async function
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
export async function resolve($, path, preserveSymlinks, extra) {
|
|
20
|
+
if (preserveSymlinks) {
|
|
21
|
+
const resolved = resolveMount(path, $, extra);
|
|
22
|
+
const stats = await resolved.fs.stat(resolved.path).catch(() => undefined);
|
|
23
|
+
return { ...resolved, fullPath: path, stats };
|
|
17
24
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
.then(() => cb(null))
|
|
27
|
-
.catch(cb);
|
|
28
|
-
}
|
|
29
|
-
rename;
|
|
30
|
-
/**
|
|
31
|
-
* Test whether or not `path` exists by checking with the file system.
|
|
32
|
-
* Then call the callback argument with either true or false.
|
|
33
|
-
* According to Node.js: deprecated Use {@link stat} or {@link access} instead.
|
|
34
|
-
*/
|
|
35
|
-
export function exists(path, cb = nop) {
|
|
36
|
-
promises.exists
|
|
37
|
-
.call(this, path)
|
|
38
|
-
.then(cb)
|
|
39
|
-
.catch(() => cb(false));
|
|
40
|
-
}
|
|
41
|
-
exists;
|
|
42
|
-
export function stat(path, options, callback = nop) {
|
|
43
|
-
callback = typeof options == 'function' ? options : callback;
|
|
44
|
-
promises.stat
|
|
45
|
-
.call(this, path, typeof options != 'function' ? options : {})
|
|
46
|
-
.then(stats => callback(null, stats))
|
|
47
|
-
.catch(callback);
|
|
48
|
-
}
|
|
49
|
-
stat;
|
|
50
|
-
export function lstat(path, options, callback = nop) {
|
|
51
|
-
callback = typeof options == 'function' ? options : callback;
|
|
52
|
-
promises.lstat
|
|
53
|
-
.call(this, path, typeof options != 'function' ? options : {})
|
|
54
|
-
.then(stats => callback(null, stats))
|
|
55
|
-
.catch(callback);
|
|
56
|
-
}
|
|
57
|
-
lstat;
|
|
58
|
-
export function truncate(path, cbLen = 0, cb = nop) {
|
|
59
|
-
cb = typeof cbLen === 'function' ? cbLen : cb;
|
|
60
|
-
const len = typeof cbLen === 'number' ? cbLen : 0;
|
|
61
|
-
promises.truncate
|
|
62
|
-
.call(this, path, len)
|
|
63
|
-
.then(() => cb(null))
|
|
64
|
-
.catch(cb);
|
|
65
|
-
}
|
|
66
|
-
truncate;
|
|
67
|
-
export function unlink(path, cb = nop) {
|
|
68
|
-
promises.unlink
|
|
69
|
-
.call(this, path)
|
|
70
|
-
.then(() => cb(null))
|
|
71
|
-
.catch(cb);
|
|
72
|
-
}
|
|
73
|
-
unlink;
|
|
74
|
-
export function open(path, flag, cbMode, cb = nop) {
|
|
75
|
-
const mode = normalizeMode(cbMode, 0o644);
|
|
76
|
-
cb = typeof cbMode === 'function' ? cbMode : cb;
|
|
77
|
-
promises.open
|
|
78
|
-
.call(this, path, flag, mode)
|
|
79
|
-
.then(handle => cb(null, handle.fd))
|
|
80
|
-
.catch(cb);
|
|
81
|
-
}
|
|
82
|
-
open;
|
|
83
|
-
export function readFile(filename, options, cb = nop) {
|
|
84
|
-
cb = typeof options === 'function' ? options : cb;
|
|
85
|
-
promises.readFile
|
|
86
|
-
.call(this, filename, typeof options === 'function' ? null : options)
|
|
87
|
-
.then(data => cb(null, data))
|
|
88
|
-
.catch(cb);
|
|
89
|
-
}
|
|
90
|
-
readFile;
|
|
91
|
-
export function writeFile(filename, data, cbEncOpts, cb = nop) {
|
|
92
|
-
cb = typeof cbEncOpts === 'function' ? cbEncOpts : cb;
|
|
93
|
-
promises.writeFile
|
|
94
|
-
.call(this, filename, data, typeof cbEncOpts != 'function' ? cbEncOpts : null)
|
|
95
|
-
.then(() => cb(null))
|
|
96
|
-
.catch(cb);
|
|
97
|
-
}
|
|
98
|
-
writeFile;
|
|
99
|
-
export function appendFile(filename, data, cbEncOpts, cb = nop) {
|
|
100
|
-
const optionsOrEncoding = typeof cbEncOpts != 'function' ? cbEncOpts : undefined;
|
|
101
|
-
cb = typeof cbEncOpts === 'function' ? cbEncOpts : cb;
|
|
102
|
-
promises.appendFile
|
|
103
|
-
.call(this, filename, data, optionsOrEncoding)
|
|
104
|
-
.then(() => cb(null))
|
|
105
|
-
.catch(cb);
|
|
106
|
-
}
|
|
107
|
-
appendFile;
|
|
108
|
-
export function fstat(fd, options, cb = nop) {
|
|
109
|
-
cb = typeof options == 'function' ? options : cb;
|
|
110
|
-
new promises.FileHandle(this, fd)
|
|
111
|
-
.stat()
|
|
112
|
-
.then(stats => cb(null, typeof options == 'object' && options?.bigint ? new BigIntStats(stats) : stats))
|
|
113
|
-
.catch(cb);
|
|
114
|
-
}
|
|
115
|
-
fstat;
|
|
116
|
-
export function close(fd, cb = nop) {
|
|
117
|
-
new promises.FileHandle(this, fd)
|
|
118
|
-
.close()
|
|
119
|
-
.then(() => cb(null))
|
|
120
|
-
.catch(cb);
|
|
121
|
-
}
|
|
122
|
-
close;
|
|
123
|
-
export function ftruncate(fd, lenOrCB, cb = nop) {
|
|
124
|
-
const length = typeof lenOrCB === 'number' ? lenOrCB : 0;
|
|
125
|
-
cb = typeof lenOrCB === 'function' ? lenOrCB : cb;
|
|
126
|
-
const file = new promises.FileHandle(this, fd);
|
|
127
|
-
if (length < 0)
|
|
128
|
-
throw withErrno('EINVAL');
|
|
129
|
-
file.truncate(length)
|
|
130
|
-
.then(() => cb(null))
|
|
131
|
-
.catch(cb);
|
|
132
|
-
}
|
|
133
|
-
ftruncate;
|
|
134
|
-
export function fsync(fd, cb = nop) {
|
|
135
|
-
new promises.FileHandle(this, fd)
|
|
136
|
-
.sync()
|
|
137
|
-
.then(() => cb(null))
|
|
138
|
-
.catch(cb);
|
|
139
|
-
}
|
|
140
|
-
fsync;
|
|
141
|
-
export function fdatasync(fd, cb = nop) {
|
|
142
|
-
new promises.FileHandle(this, fd)
|
|
143
|
-
.datasync()
|
|
144
|
-
.then(() => cb(null))
|
|
145
|
-
.catch(cb);
|
|
146
|
-
}
|
|
147
|
-
fdatasync;
|
|
148
|
-
export function write(fd, data, cbPosOff, cbLenEnc, cbPosEnc, cb = nop) {
|
|
149
|
-
let buffer, offset, length, position, encoding;
|
|
150
|
-
const handle = new promises.FileHandle(this, fd);
|
|
151
|
-
if (typeof data === 'string') {
|
|
152
|
-
// Signature 1: (fd, string, [position?, [encoding?]], cb?)
|
|
153
|
-
encoding = 'utf8';
|
|
154
|
-
switch (typeof cbPosOff) {
|
|
155
|
-
case 'function':
|
|
156
|
-
// (fd, string, cb)
|
|
157
|
-
cb = cbPosOff;
|
|
158
|
-
break;
|
|
159
|
-
case 'number':
|
|
160
|
-
// (fd, string, position, encoding?, cb?)
|
|
161
|
-
position = cbPosOff;
|
|
162
|
-
encoding = typeof cbLenEnc === 'string' ? cbLenEnc : 'utf8';
|
|
163
|
-
cb = typeof cbPosEnc === 'function' ? cbPosEnc : cb;
|
|
164
|
-
break;
|
|
165
|
-
default:
|
|
166
|
-
// ...try to find the callback and get out of here!
|
|
167
|
-
cb = (typeof cbLenEnc === 'function' ? cbLenEnc : typeof cbPosEnc === 'function' ? cbPosEnc : cb);
|
|
168
|
-
cb(withErrno('EINVAL'));
|
|
169
|
-
return;
|
|
25
|
+
/* Try to resolve it directly. If this works,
|
|
26
|
+
that means we don't need to perform any resolution for parent directories. */
|
|
27
|
+
try {
|
|
28
|
+
const resolved = resolveMount(path, $);
|
|
29
|
+
// Stat it to make sure it exists
|
|
30
|
+
const stats = await resolved.fs.stat(resolved.path);
|
|
31
|
+
if (!isSymbolicLink(stats)) {
|
|
32
|
+
return { ...resolved, fullPath: path, stats };
|
|
170
33
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
length = buffer.length;
|
|
174
|
-
const _cb = cb;
|
|
175
|
-
handle
|
|
176
|
-
.write(buffer, offset, length, position)
|
|
177
|
-
.then(({ bytesWritten }) => _cb(null, bytesWritten, buffer.toString(encoding)))
|
|
178
|
-
.catch(_cb);
|
|
34
|
+
const target = resolvePath.call($, dirname(path), await readlink.call($, path));
|
|
35
|
+
return await resolve($, target, preserveSymlinks, extra);
|
|
179
36
|
}
|
|
180
|
-
|
|
181
|
-
//
|
|
182
|
-
buffer = Buffer.from(data.buffer);
|
|
183
|
-
offset = cbPosOff;
|
|
184
|
-
length = cbLenEnc;
|
|
185
|
-
position = typeof cbPosEnc === 'number' ? cbPosEnc : null;
|
|
186
|
-
const _cb = (typeof cbPosEnc === 'function' ? cbPosEnc : cb);
|
|
187
|
-
void handle
|
|
188
|
-
.write(buffer, offset, length, position)
|
|
189
|
-
.then(({ bytesWritten }) => _cb(null, bytesWritten, buffer))
|
|
190
|
-
.catch(_cb);
|
|
37
|
+
catch {
|
|
38
|
+
// Go the long way
|
|
191
39
|
}
|
|
40
|
+
const { base, dir } = parse(path);
|
|
41
|
+
const realDir = dir == '/' ? '/' : (await resolve($, dir, false, extra)).fullPath;
|
|
42
|
+
const maybePath = join(realDir, base);
|
|
43
|
+
const resolved = resolveMount(maybePath, $);
|
|
44
|
+
const stats = await resolved.fs.stat(resolved.path).catch((e) => {
|
|
45
|
+
if (e.code == 'ENOENT')
|
|
46
|
+
return;
|
|
47
|
+
throw setUVMessage(Object.assign(e, { syscall: 'stat', path: maybePath }));
|
|
48
|
+
});
|
|
49
|
+
if (!stats)
|
|
50
|
+
return { ...resolved, fullPath: path };
|
|
51
|
+
if (!isSymbolicLink(stats)) {
|
|
52
|
+
return { ...resolved, fullPath: maybePath, stats };
|
|
53
|
+
}
|
|
54
|
+
const target = resolvePath.call($, realDir, await readlink.call($, maybePath));
|
|
55
|
+
return await resolve($, target, false, extra);
|
|
192
56
|
}
|
|
193
|
-
write;
|
|
194
|
-
/**
|
|
195
|
-
* Read data from the file specified by `fd`.
|
|
196
|
-
* @param buffer The buffer that the data will be written to.
|
|
197
|
-
* @param offset The offset within the buffer where writing will start.
|
|
198
|
-
* @param length An integer specifying the number of bytes to read.
|
|
199
|
-
* @param position An integer specifying where to begin reading from in the file.
|
|
200
|
-
* If position is null, data will be read from the current file position.
|
|
201
|
-
* @param cb The number is the number of bytes read
|
|
202
|
-
*/
|
|
203
|
-
export function read(fd, buffer, offset, length, position, cb = nop) {
|
|
204
|
-
new promises.FileHandle(this, fd)
|
|
205
|
-
.read(buffer, offset, length, position)
|
|
206
|
-
.then(({ bytesRead, buffer }) => cb(null, bytesRead, buffer))
|
|
207
|
-
.catch(cb);
|
|
208
|
-
}
|
|
209
|
-
read;
|
|
210
|
-
export function fchown(fd, uid, gid, cb = nop) {
|
|
211
|
-
new promises.FileHandle(this, fd)
|
|
212
|
-
.chown(uid, gid)
|
|
213
|
-
.then(() => cb(null))
|
|
214
|
-
.catch(cb);
|
|
215
|
-
}
|
|
216
|
-
fchown;
|
|
217
|
-
export function fchmod(fd, mode, cb) {
|
|
218
|
-
new promises.FileHandle(this, fd)
|
|
219
|
-
.chmod(mode)
|
|
220
|
-
.then(() => cb(null))
|
|
221
|
-
.catch(cb);
|
|
222
|
-
}
|
|
223
|
-
fchmod;
|
|
224
|
-
/**
|
|
225
|
-
* Change the file timestamps of a file referenced by the supplied file descriptor.
|
|
226
|
-
*/
|
|
227
|
-
export function futimes(fd, atime, mtime, cb = nop) {
|
|
228
|
-
new promises.FileHandle(this, fd)
|
|
229
|
-
.utimes(atime, mtime)
|
|
230
|
-
.then(() => cb(null))
|
|
231
|
-
.catch(cb);
|
|
232
|
-
}
|
|
233
|
-
futimes;
|
|
234
|
-
export function rmdir(path, cb = nop) {
|
|
235
|
-
promises.rmdir
|
|
236
|
-
.call(this, path)
|
|
237
|
-
.then(() => cb(null))
|
|
238
|
-
.catch(cb);
|
|
239
|
-
}
|
|
240
|
-
rmdir;
|
|
241
|
-
/**
|
|
242
|
-
* Asynchronous `mkdir`.
|
|
243
|
-
* @param mode defaults to `0777`
|
|
244
|
-
*/
|
|
245
|
-
export function mkdir(path, mode, cb = nop) {
|
|
246
|
-
promises.mkdir
|
|
247
|
-
.call(this, path, mode)
|
|
248
|
-
.then(() => cb(null))
|
|
249
|
-
.catch(cb);
|
|
250
|
-
}
|
|
251
|
-
mkdir;
|
|
252
|
-
export function readdir(path, _options, cb = nop) {
|
|
253
|
-
cb = typeof _options == 'function' ? _options : cb;
|
|
254
|
-
const options = typeof _options != 'function' ? _options : {};
|
|
255
|
-
promises.readdir
|
|
256
|
-
.call(this, path, options)
|
|
257
|
-
.then(entries => cb(null, entries))
|
|
258
|
-
.catch(cb);
|
|
259
|
-
}
|
|
260
|
-
readdir;
|
|
261
|
-
export function link(existing, newpath, cb = nop) {
|
|
262
|
-
promises.link
|
|
263
|
-
.call(this, existing, newpath)
|
|
264
|
-
.then(() => cb(null))
|
|
265
|
-
.catch(cb);
|
|
266
|
-
}
|
|
267
|
-
link;
|
|
268
|
-
export function symlink(target, path, typeOrCB, cb = nop) {
|
|
269
|
-
const type = typeof typeOrCB === 'string' ? typeOrCB : 'file';
|
|
270
|
-
cb = typeof typeOrCB === 'function' ? typeOrCB : cb;
|
|
271
|
-
promises.symlink
|
|
272
|
-
.call(this, target, path, type)
|
|
273
|
-
.then(() => cb(null))
|
|
274
|
-
.catch(cb);
|
|
275
|
-
}
|
|
276
|
-
symlink;
|
|
277
|
-
export function readlink(path, options, callback = nop) {
|
|
278
|
-
callback = typeof options == 'function' ? options : callback;
|
|
279
|
-
promises.readlink
|
|
280
|
-
.call(this, path)
|
|
281
|
-
.then(result => callback(null, result))
|
|
282
|
-
.catch(callback);
|
|
283
|
-
}
|
|
284
|
-
readlink;
|
|
285
|
-
export function chown(path, uid, gid, cb = nop) {
|
|
286
|
-
promises.chown
|
|
287
|
-
.call(this, path, uid, gid)
|
|
288
|
-
.then(() => cb(null))
|
|
289
|
-
.catch(cb);
|
|
290
|
-
}
|
|
291
|
-
chown;
|
|
292
|
-
export function lchown(path, uid, gid, cb = nop) {
|
|
293
|
-
promises.lchown
|
|
294
|
-
.call(this, path, uid, gid)
|
|
295
|
-
.then(() => cb(null))
|
|
296
|
-
.catch(cb);
|
|
297
|
-
}
|
|
298
|
-
lchown;
|
|
299
|
-
export function chmod(path, mode, cb = nop) {
|
|
300
|
-
promises.chmod
|
|
301
|
-
.call(this, path, mode)
|
|
302
|
-
.then(() => cb(null))
|
|
303
|
-
.catch(cb);
|
|
304
|
-
}
|
|
305
|
-
chmod;
|
|
306
|
-
export function lchmod(path, mode, cb = nop) {
|
|
307
|
-
promises.lchmod
|
|
308
|
-
.call(this, path, mode)
|
|
309
|
-
.then(() => cb(null))
|
|
310
|
-
.catch(cb);
|
|
311
|
-
}
|
|
312
|
-
lchmod;
|
|
313
|
-
/**
|
|
314
|
-
* Change file timestamps of the file referenced by the supplied path.
|
|
315
|
-
*/
|
|
316
|
-
export function utimes(path, atime, mtime, cb = nop) {
|
|
317
|
-
promises.utimes
|
|
318
|
-
.call(this, path, atime, mtime)
|
|
319
|
-
.then(() => cb(null))
|
|
320
|
-
.catch(cb);
|
|
321
|
-
}
|
|
322
|
-
utimes;
|
|
323
57
|
/**
|
|
324
|
-
*
|
|
58
|
+
* Opens a file. This helper handles the complexity of file flags.
|
|
59
|
+
* @internal
|
|
325
60
|
*/
|
|
326
|
-
export function
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
access;
|
|
350
|
-
const statWatchers = new Map();
|
|
351
|
-
export function watchFile(path, options, listener) {
|
|
352
|
-
const normalizedPath = normalizePath(path);
|
|
353
|
-
const opts = typeof options != 'function' ? options : {};
|
|
354
|
-
if (typeof options == 'function') {
|
|
355
|
-
listener = options;
|
|
61
|
+
export async function open($, path, opt) {
|
|
62
|
+
path = normalizePath(path);
|
|
63
|
+
const mode = normalizeMode(opt.mode, 0o644), flag = flags.parse(opt.flag);
|
|
64
|
+
const $ex = { syscall: 'open', path };
|
|
65
|
+
const { fs, path: resolved, stats } = await resolve($, path, opt.preserveSymlinks, $ex);
|
|
66
|
+
if (!stats) {
|
|
67
|
+
if (!(flag & constants.O_CREAT))
|
|
68
|
+
throw UV('ENOENT', $ex);
|
|
69
|
+
// Create the file
|
|
70
|
+
const parentStats = await fs.stat(dirname(resolved));
|
|
71
|
+
if (checkAccess && !hasAccess($, parentStats, constants.W_OK))
|
|
72
|
+
throw UV('EACCES', 'open', dirname(path));
|
|
73
|
+
if (!isDirectory(parentStats))
|
|
74
|
+
throw UV('ENOTDIR', 'open', dirname(path));
|
|
75
|
+
if (!opt.allowDirectory && mode & constants.S_IFDIR)
|
|
76
|
+
throw UV('EISDIR', 'open', path);
|
|
77
|
+
const { euid: uid, egid: gid } = $?.credentials ?? defaultContext.credentials;
|
|
78
|
+
const inode = await fs.createFile(resolved, {
|
|
79
|
+
mode,
|
|
80
|
+
uid: parentStats.mode & constants.S_ISUID ? parentStats.uid : uid,
|
|
81
|
+
gid: parentStats.mode & constants.S_ISGID ? parentStats.gid : gid,
|
|
82
|
+
});
|
|
83
|
+
return new Handle($, path, fs, resolved, flag, inode);
|
|
356
84
|
}
|
|
357
|
-
if (!
|
|
358
|
-
throw UV('
|
|
359
|
-
if (
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
85
|
+
if (checkAccess && !hasAccess($, stats, flags.toMode(flag)))
|
|
86
|
+
throw UV('EACCES', $ex);
|
|
87
|
+
if (flag & constants.O_EXCL)
|
|
88
|
+
throw UV('EEXIST', $ex);
|
|
89
|
+
const handle = new Handle($, path, fs, resolved, flag, stats);
|
|
90
|
+
if (!opt.allowDirectory && mode & constants.S_IFDIR)
|
|
91
|
+
throw UV('EISDIR', 'open', path);
|
|
92
|
+
if (flag & constants.O_TRUNC)
|
|
93
|
+
await handle.truncate(0);
|
|
94
|
+
return handle;
|
|
95
|
+
}
|
|
96
|
+
export async function readlink(path) {
|
|
97
|
+
path = normalizePath(path);
|
|
98
|
+
const $ex = { syscall: 'readlink', path };
|
|
99
|
+
const { fs, stats, path: resolved } = await resolve(this, path, true, $ex);
|
|
100
|
+
if (!stats)
|
|
101
|
+
throw UV('ENOENT', $ex);
|
|
102
|
+
if (checkAccess && !hasAccess(this, stats, constants.R_OK))
|
|
103
|
+
throw UV('EACCES', $ex);
|
|
104
|
+
if (!isSymbolicLink(stats))
|
|
105
|
+
throw UV('EINVAL', $ex);
|
|
106
|
+
const size = stats.size;
|
|
107
|
+
const data = new Uint8Array(size);
|
|
108
|
+
await fs.read(resolved, data, 0, size);
|
|
109
|
+
return decodeUTF8(data);
|
|
110
|
+
}
|
|
111
|
+
export async function mkdir(path, options = {}) {
|
|
112
|
+
path = normalizePath(path);
|
|
113
|
+
const { euid: uid, egid: gid } = this?.credentials ?? defaultContext.credentials;
|
|
114
|
+
const { mode = 0o777, recursive } = options;
|
|
115
|
+
const { fs, path: resolved } = resolveMount(path, this, { syscall: 'mkdir' });
|
|
116
|
+
const __create = async (path, resolved, parent) => {
|
|
117
|
+
if (checkAccess && !hasAccess(this, parent, constants.W_OK))
|
|
118
|
+
throw UV('EACCES', 'mkdir', path);
|
|
119
|
+
const inode = await fs.mkdir(resolved, {
|
|
120
|
+
mode,
|
|
121
|
+
uid: parent.mode & constants.S_ISUID ? parent.uid : uid,
|
|
122
|
+
gid: parent.mode & constants.S_ISGID ? parent.gid : gid,
|
|
123
|
+
});
|
|
124
|
+
emitChange(this, 'rename', path);
|
|
125
|
+
return inode;
|
|
126
|
+
};
|
|
127
|
+
if (!recursive) {
|
|
128
|
+
await __create(path, resolved, await fs.stat(dirname(resolved)));
|
|
364
129
|
return;
|
|
365
130
|
}
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
131
|
+
const dirs = [];
|
|
132
|
+
let origDir = path;
|
|
133
|
+
for (let dir = resolved; !(await fs.exists(dir)); dir = dirname(dir), origDir = dirname(origDir)) {
|
|
134
|
+
dirs.unshift([origDir, dir]);
|
|
135
|
+
}
|
|
136
|
+
if (!dirs.length)
|
|
137
|
+
return;
|
|
138
|
+
const stats = [await fs.stat(dirname(dirs[0][1]))];
|
|
139
|
+
for (const [i, [path, resolved]] of dirs.entries()) {
|
|
140
|
+
stats.push(await __create(path, resolved, stats[i]));
|
|
141
|
+
}
|
|
142
|
+
return dirs[0][0];
|
|
143
|
+
}
|
|
144
|
+
export async function readdir(path, options = {}) {
|
|
145
|
+
path = normalizePath(path);
|
|
146
|
+
const $ex = { syscall: 'readdir', path };
|
|
147
|
+
const { fs, path: resolved, stats } = await resolve(this, path, false, $ex);
|
|
148
|
+
if (!stats)
|
|
149
|
+
throw UV('ENOENT', $ex);
|
|
150
|
+
if (checkAccess && !hasAccess(this, stats, constants.R_OK))
|
|
151
|
+
throw UV('EACCES', $ex);
|
|
152
|
+
if (!isDirectory(stats))
|
|
153
|
+
throw UV('ENOTDIR', $ex);
|
|
154
|
+
const entries = await fs.readdir(resolved);
|
|
155
|
+
const values = [];
|
|
156
|
+
const addEntry = async (entry) => {
|
|
157
|
+
const entryStats = await fs.stat(join(resolved, entry)).catch((e) => {
|
|
158
|
+
if (e.code == 'ENOENT')
|
|
159
|
+
return;
|
|
160
|
+
throw e;
|
|
161
|
+
});
|
|
162
|
+
if (!entryStats)
|
|
370
163
|
return;
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
164
|
+
const ent = new Dirent();
|
|
165
|
+
ent.ino = entryStats.ino;
|
|
166
|
+
ent.type = ifToDt(entryStats.mode);
|
|
167
|
+
ent.path = entry;
|
|
168
|
+
ent.name = basename(entry);
|
|
169
|
+
values.push(ent);
|
|
170
|
+
if (!options.recursive || !isDirectory(entryStats))
|
|
171
|
+
return;
|
|
172
|
+
const children = await fs.readdir(join(resolved, entry));
|
|
173
|
+
for (const child of children)
|
|
174
|
+
await addEntry(join(entry, child));
|
|
175
|
+
};
|
|
176
|
+
await Promise.all(entries.map(addEntry));
|
|
177
|
+
return values;
|
|
178
|
+
}
|
|
179
|
+
export async function rename(oldPath, newPath) {
|
|
180
|
+
oldPath = normalizePath(oldPath);
|
|
181
|
+
newPath = normalizePath(newPath);
|
|
182
|
+
const $ex = { syscall: 'rename', path: oldPath, dest: newPath };
|
|
183
|
+
const src = await resolve(this, oldPath, true, $ex);
|
|
184
|
+
const dst = resolveMount(newPath, this, $ex);
|
|
185
|
+
if (src.fs.uuid !== dst.fs.uuid)
|
|
186
|
+
throw UV('EXDEV', $ex);
|
|
187
|
+
if (dst.path.startsWith(src.path + '/'))
|
|
188
|
+
throw UV('EBUSY', $ex);
|
|
189
|
+
if (!src.stats)
|
|
190
|
+
throw UV('ENOENT', $ex);
|
|
191
|
+
const fs = src.fs;
|
|
192
|
+
const oldParent = await fs.stat(dirname(src.path));
|
|
193
|
+
const newParent = await fs.stat(dirname(dst.path));
|
|
194
|
+
const newStats = await fs.stat(dst.path).catch((e) => {
|
|
195
|
+
if (e.code == 'ENOENT')
|
|
196
|
+
return null;
|
|
197
|
+
throw e;
|
|
375
198
|
});
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
const
|
|
390
|
-
const
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
if (
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
199
|
+
if (checkAccess && (!hasAccess(this, oldParent, constants.R_OK) || !hasAccess(this, newParent, constants.W_OK)))
|
|
200
|
+
throw UV('EACCES', $ex);
|
|
201
|
+
if (newStats && !isDirectory(src.stats) && isDirectory(newStats))
|
|
202
|
+
throw UV('EISDIR', $ex);
|
|
203
|
+
if (newStats && isDirectory(src.stats) && !isDirectory(newStats))
|
|
204
|
+
throw UV('ENOTDIR', $ex);
|
|
205
|
+
await src.fs.rename(src.path, dst.path);
|
|
206
|
+
emitChange(this, 'rename', oldPath);
|
|
207
|
+
emitChange(this, 'change', newPath);
|
|
208
|
+
}
|
|
209
|
+
export async function link(target, link) {
|
|
210
|
+
target = normalizePath(target);
|
|
211
|
+
link = normalizePath(link);
|
|
212
|
+
const $ex = { syscall: 'link', path: link, dest: target };
|
|
213
|
+
const { fs, path: resolved } = resolveMount(target, this, $ex);
|
|
214
|
+
const dst = resolveMount(link, this, $ex);
|
|
215
|
+
if (fs.uuid != dst.fs.uuid)
|
|
216
|
+
throw UV('EXDEV', $ex);
|
|
217
|
+
const stats = await fs.stat(resolved);
|
|
218
|
+
if (checkAccess) {
|
|
219
|
+
if (!hasAccess(this, stats, constants.R_OK))
|
|
220
|
+
throw UV('EACCES', $ex);
|
|
221
|
+
const dirStats = await fs.stat(dirname(resolved));
|
|
222
|
+
if (!hasAccess(this, dirStats, constants.R_OK))
|
|
223
|
+
throw UV('EACCES', $ex);
|
|
224
|
+
const destStats = await fs.stat(dirname(dst.path));
|
|
225
|
+
if (!hasAccess(this, destStats, constants.W_OK))
|
|
226
|
+
throw UV('EACCES', $ex);
|
|
404
227
|
}
|
|
228
|
+
return await fs.link(resolved, dst.path);
|
|
405
229
|
}
|
|
406
|
-
unwatchFile;
|
|
407
|
-
export function watch(path, options, listener) {
|
|
408
|
-
const watcher = new FSWatcher(this, normalizePath(path), typeof options == 'object' ? options : {});
|
|
409
|
-
listener = typeof options == 'function' ? options : listener;
|
|
410
|
-
watcher.on('change', listener || nop);
|
|
411
|
-
return watcher;
|
|
412
|
-
}
|
|
413
|
-
watch;
|
|
414
|
-
/**
|
|
415
|
-
* Opens a file in read mode and creates a Node.js-like ReadStream.
|
|
416
|
-
*
|
|
417
|
-
* @param path The path to the file to be opened.
|
|
418
|
-
* @param options Options for the ReadStream and file opening (e.g., `encoding`, `highWaterMark`, `mode`).
|
|
419
|
-
* @returns A ReadStream object for interacting with the file's contents.
|
|
420
|
-
*/
|
|
421
|
-
export function createReadStream(path, options) {
|
|
422
|
-
options = typeof options == 'object' ? options : { encoding: options };
|
|
423
|
-
const _handle = promises.open.call(this, path, 'r', options?.mode);
|
|
424
|
-
return new ReadStream({ ...options, autoClose: true }, _handle);
|
|
425
|
-
}
|
|
426
|
-
createReadStream;
|
|
427
|
-
/**
|
|
428
|
-
* Opens a file in write mode and creates a Node.js-like WriteStream.
|
|
429
|
-
*
|
|
430
|
-
* @param path The path to the file to be opened.
|
|
431
|
-
* @param options Options for the WriteStream and file opening (e.g., `encoding`, `highWaterMark`, `mode`).
|
|
432
|
-
* @returns A WriteStream object for writing to the file.
|
|
433
|
-
*/
|
|
434
|
-
export function createWriteStream(path, options) {
|
|
435
|
-
options = typeof options == 'object' ? options : { encoding: options };
|
|
436
|
-
const _handle = promises.open.call(this, path, 'w', options?.mode);
|
|
437
|
-
return new WriteStream(options, _handle);
|
|
438
|
-
}
|
|
439
|
-
createWriteStream;
|
|
440
|
-
export function rm(path, options, callback = nop) {
|
|
441
|
-
callback = typeof options === 'function' ? options : callback;
|
|
442
|
-
promises.rm
|
|
443
|
-
.call(this, path, typeof options === 'function' ? undefined : options)
|
|
444
|
-
.then(() => callback(null))
|
|
445
|
-
.catch(callback);
|
|
446
|
-
}
|
|
447
|
-
rm;
|
|
448
|
-
export function mkdtemp(prefix, options, callback = nop) {
|
|
449
|
-
callback = typeof options === 'function' ? options : callback;
|
|
450
|
-
promises.mkdtemp
|
|
451
|
-
.call(this, prefix, typeof options != 'function' ? options : null)
|
|
452
|
-
.then(result => callback(null, result))
|
|
453
|
-
.catch(callback);
|
|
454
|
-
}
|
|
455
|
-
mkdtemp;
|
|
456
|
-
export function copyFile(src, dest, flags, callback = nop) {
|
|
457
|
-
callback = typeof flags === 'function' ? flags : callback;
|
|
458
|
-
promises.copyFile
|
|
459
|
-
.call(this, src, dest, typeof flags === 'function' ? undefined : flags)
|
|
460
|
-
.then(() => callback(null))
|
|
461
|
-
.catch(callback);
|
|
462
|
-
}
|
|
463
|
-
copyFile;
|
|
464
|
-
export function readv(fd, buffers, position, cb = nop) {
|
|
465
|
-
cb = typeof position === 'function' ? position : cb;
|
|
466
|
-
new promises.FileHandle(this, fd)
|
|
467
|
-
.readv(buffers, typeof position === 'function' ? undefined : position)
|
|
468
|
-
.then(({ buffers, bytesRead }) => cb(null, bytesRead, buffers))
|
|
469
|
-
.catch(cb);
|
|
470
|
-
}
|
|
471
|
-
readv;
|
|
472
|
-
export function writev(fd, buffers, position, cb = nop) {
|
|
473
|
-
cb = typeof position === 'function' ? position : cb;
|
|
474
|
-
new promises.FileHandle(this, fd)
|
|
475
|
-
.writev(buffers, typeof position === 'function' ? undefined : position)
|
|
476
|
-
.then(({ buffers, bytesWritten }) => cb(null, bytesWritten, buffers))
|
|
477
|
-
.catch(cb);
|
|
478
|
-
}
|
|
479
|
-
writev;
|
|
480
|
-
export function opendir(path, options, cb = nop) {
|
|
481
|
-
cb = typeof options === 'function' ? options : cb;
|
|
482
|
-
promises.opendir
|
|
483
|
-
.call(this, path, typeof options === 'function' ? undefined : options)
|
|
484
|
-
.then(result => cb(null, result))
|
|
485
|
-
.catch(cb);
|
|
486
|
-
}
|
|
487
|
-
opendir;
|
|
488
|
-
export function cp(source, destination, opts, callback = nop) {
|
|
489
|
-
callback = typeof opts === 'function' ? opts : callback;
|
|
490
|
-
promises.cp
|
|
491
|
-
.call(this, source, destination, typeof opts === 'function' ? undefined : opts)
|
|
492
|
-
.then(() => callback(null))
|
|
493
|
-
.catch(callback);
|
|
494
|
-
}
|
|
495
|
-
cp;
|
|
496
|
-
export function statfs(path, options, callback = nop) {
|
|
497
|
-
callback = typeof options === 'function' ? options : callback;
|
|
498
|
-
promises.statfs
|
|
499
|
-
.call(this, path, typeof options === 'function' ? undefined : options)
|
|
500
|
-
.then(result => callback(null, result))
|
|
501
|
-
.catch(callback);
|
|
502
|
-
}
|
|
503
|
-
statfs;
|
|
504
|
-
export async function openAsBlob(path, options) {
|
|
505
|
-
const handle = await promises.open.call(this, path.toString(), 'r');
|
|
506
|
-
const buffer = await handle.readFile();
|
|
507
|
-
await handle.close();
|
|
508
|
-
return new Blob([buffer], options);
|
|
509
|
-
}
|
|
510
|
-
openAsBlob;
|
|
511
|
-
export function glob(pattern, options, callback = nop) {
|
|
512
|
-
callback = typeof options == 'function' ? options : callback;
|
|
513
|
-
const it = promises.glob.call(this, pattern, typeof options === 'function' ? undefined : options);
|
|
514
|
-
collectAsyncIterator(it)
|
|
515
|
-
.then(results => callback(null, results ?? []))
|
|
516
|
-
.catch((e) => callback(e));
|
|
517
|
-
}
|
|
518
|
-
glob;
|