@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
package/dist/vfs/sync.js
CHANGED
|
@@ -1,189 +1,67 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var dispose, inner;
|
|
5
|
-
if (async) {
|
|
6
|
-
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
-
dispose = value[Symbol.asyncDispose];
|
|
8
|
-
}
|
|
9
|
-
if (dispose === void 0) {
|
|
10
|
-
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
-
dispose = value[Symbol.dispose];
|
|
12
|
-
if (async) inner = dispose;
|
|
13
|
-
}
|
|
14
|
-
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
-
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
-
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
-
}
|
|
18
|
-
else if (async) {
|
|
19
|
-
env.stack.push({ async: true });
|
|
20
|
-
}
|
|
21
|
-
return value;
|
|
22
|
-
};
|
|
23
|
-
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
-
return function (env) {
|
|
25
|
-
function fail(e) {
|
|
26
|
-
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
-
env.hasError = true;
|
|
28
|
-
}
|
|
29
|
-
var r, s = 0;
|
|
30
|
-
function next() {
|
|
31
|
-
while (r = env.stack.pop()) {
|
|
32
|
-
try {
|
|
33
|
-
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
34
|
-
if (r.dispose) {
|
|
35
|
-
var result = r.dispose.call(r.value);
|
|
36
|
-
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
37
|
-
}
|
|
38
|
-
else s |= 1;
|
|
39
|
-
}
|
|
40
|
-
catch (e) {
|
|
41
|
-
fail(e);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
45
|
-
if (env.hasError) throw env.error;
|
|
46
|
-
}
|
|
47
|
-
return next();
|
|
48
|
-
};
|
|
49
|
-
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
50
|
-
var e = new Error(message);
|
|
51
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
|
-
});
|
|
53
|
-
import { Buffer } from 'buffer';
|
|
54
|
-
import { Errno, Exception, setUVMessage, UV } from 'kerium';
|
|
55
|
-
import { encodeUTF8 } from 'utilium';
|
|
1
|
+
import { setUVMessage, UV } from 'kerium';
|
|
2
|
+
import { decodeUTF8 } from 'utilium';
|
|
3
|
+
import * as constants from '../constants.js';
|
|
56
4
|
import { defaultContext } from '../internal/contexts.js';
|
|
57
|
-
import { wrap } from '../internal/error.js';
|
|
58
5
|
import { hasAccess, isDirectory, isSymbolicLink } from '../internal/inode.js';
|
|
59
|
-
import { basename, dirname, join,
|
|
60
|
-
import {
|
|
6
|
+
import { basename, dirname, join, parse, resolve as resolvePath } from '../path.js';
|
|
7
|
+
import { normalizeMode, normalizePath } from '../utils.js';
|
|
61
8
|
import { checkAccess } from './config.js';
|
|
62
|
-
import
|
|
63
|
-
import {
|
|
64
|
-
import { deleteFD, fromFD, SyncHandle, toFD } from './file.js';
|
|
9
|
+
import { Dirent, ifToDt } from './dir.js';
|
|
10
|
+
import { Handle } from './file.js';
|
|
65
11
|
import * as flags from './flags.js';
|
|
66
|
-
import {
|
|
67
|
-
import { BigIntStats, Stats } from './stats.js';
|
|
12
|
+
import { resolveMount } from './shared.js';
|
|
68
13
|
import { emitChange } from './watchers.js';
|
|
69
|
-
export function renameSync(oldPath, newPath) {
|
|
70
|
-
oldPath = normalizePath(oldPath);
|
|
71
|
-
__assertType(oldPath);
|
|
72
|
-
newPath = normalizePath(newPath);
|
|
73
|
-
__assertType(newPath);
|
|
74
|
-
const src = resolveMount(oldPath, this);
|
|
75
|
-
const dst = resolveMount(newPath, this);
|
|
76
|
-
const $ex = { syscall: 'rename', path: oldPath, dest: newPath };
|
|
77
|
-
if (src.fs !== dst.fs)
|
|
78
|
-
throw UV('EXDEV', $ex);
|
|
79
|
-
if (dst.path.startsWith(src.path + '/'))
|
|
80
|
-
throw UV('EBUSY', $ex);
|
|
81
|
-
const oldStats = statSync.call(this, oldPath);
|
|
82
|
-
const oldParent = statSync.call(this, dirname(oldPath));
|
|
83
|
-
const newParent = statSync.call(this, dirname(newPath));
|
|
84
|
-
let newStats;
|
|
85
|
-
try {
|
|
86
|
-
newStats = statSync.call(this, newPath);
|
|
87
|
-
}
|
|
88
|
-
catch (e) {
|
|
89
|
-
setUVMessage(Object.assign(e, $ex));
|
|
90
|
-
if (e.code != 'ENOENT')
|
|
91
|
-
throw e;
|
|
92
|
-
}
|
|
93
|
-
if (checkAccess && (!oldParent.hasAccess(constants.R_OK, this) || !newParent.hasAccess(constants.W_OK, this)))
|
|
94
|
-
throw UV('EACCES', $ex);
|
|
95
|
-
if (newStats && !isDirectory(oldStats) && isDirectory(newStats))
|
|
96
|
-
throw UV('EISDIR', $ex);
|
|
97
|
-
if (newStats && isDirectory(oldStats) && !isDirectory(newStats))
|
|
98
|
-
throw UV('ENOTDIR', $ex);
|
|
99
|
-
try {
|
|
100
|
-
src.fs.renameSync(src.path, dst.path);
|
|
101
|
-
}
|
|
102
|
-
catch (e) {
|
|
103
|
-
throw setUVMessage(Object.assign(e, $ex));
|
|
104
|
-
}
|
|
105
|
-
emitChange(this, 'rename', oldPath);
|
|
106
|
-
emitChange(this, 'change', newPath);
|
|
107
|
-
}
|
|
108
|
-
renameSync;
|
|
109
14
|
/**
|
|
110
|
-
*
|
|
15
|
+
* Resolves the mount and real path for a path.
|
|
16
|
+
* Additionally, any stats fetched will be returned for de-duplication
|
|
17
|
+
* @category VFS
|
|
18
|
+
* @internal @hidden
|
|
111
19
|
*/
|
|
112
|
-
export function
|
|
113
|
-
|
|
20
|
+
export function resolve($, path, preserveSymlinks, extra) {
|
|
21
|
+
/* Try to resolve it directly. If this works,
|
|
22
|
+
that means we don't need to perform any resolution for parent directories. */
|
|
114
23
|
try {
|
|
115
|
-
const
|
|
116
|
-
|
|
24
|
+
const resolved = resolveMount(path, $);
|
|
25
|
+
// Stat it to make sure it exists
|
|
26
|
+
const stats = resolved.fs.statSync(resolved.path);
|
|
27
|
+
if (!isSymbolicLink(stats) || preserveSymlinks) {
|
|
28
|
+
return { ...resolved, fullPath: path, stats };
|
|
29
|
+
}
|
|
30
|
+
const target = resolvePath.call($, dirname(path), readlink.call($, path));
|
|
31
|
+
return resolve($, target, preserveSymlinks, extra);
|
|
117
32
|
}
|
|
118
33
|
catch (e) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
34
|
+
setUVMessage(Object.assign(e, { syscall: 'stat', path }));
|
|
35
|
+
if (preserveSymlinks)
|
|
36
|
+
throw e;
|
|
122
37
|
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const { fs, path: resolved } = resolveMount(realpathSync.call(this, path), this);
|
|
38
|
+
const { base, dir } = parse(path);
|
|
39
|
+
const realDir = dir == '/' ? '/' : resolve($, dir, false, extra).fullPath;
|
|
40
|
+
const maybePath = join(realDir, base);
|
|
41
|
+
const resolved = resolveMount(maybePath, $);
|
|
128
42
|
let stats;
|
|
129
43
|
try {
|
|
130
|
-
stats = fs.statSync(resolved);
|
|
44
|
+
stats = resolved.fs.statSync(resolved.path);
|
|
131
45
|
}
|
|
132
46
|
catch (e) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
throw UV('EACCES', { syscall: 'stat', path });
|
|
137
|
-
return options?.bigint ? new BigIntStats(stats) : new Stats(stats);
|
|
138
|
-
}
|
|
139
|
-
statSync;
|
|
140
|
-
export function lstatSync(path, options) {
|
|
141
|
-
path = normalizePath(path);
|
|
142
|
-
const real = join(realpathSync.call(this, dirname(path)), basename(path));
|
|
143
|
-
const { fs, path: resolved } = resolveMount(real, this);
|
|
144
|
-
const stats = wrap(fs, 'statSync', path)(resolved);
|
|
145
|
-
if (checkAccess && !hasAccess(this, stats, constants.R_OK))
|
|
146
|
-
throw UV('EACCES', { syscall: 'lstat', path });
|
|
147
|
-
return options?.bigint ? new BigIntStats(stats) : new Stats(stats);
|
|
148
|
-
}
|
|
149
|
-
lstatSync;
|
|
150
|
-
export function truncateSync(path, len = 0) {
|
|
151
|
-
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
152
|
-
try {
|
|
153
|
-
const file = __addDisposableResource(env_1, _openSync.call(this, path, { flag: 'r+' }), false);
|
|
154
|
-
len ||= 0;
|
|
155
|
-
if (len < 0)
|
|
156
|
-
throw UV('EINVAL', 'truncate', path.toString());
|
|
157
|
-
file.truncate(len);
|
|
158
|
-
}
|
|
159
|
-
catch (e_1) {
|
|
160
|
-
env_1.error = e_1;
|
|
161
|
-
env_1.hasError = true;
|
|
162
|
-
}
|
|
163
|
-
finally {
|
|
164
|
-
__disposeResources(env_1);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
truncateSync;
|
|
168
|
-
export function unlinkSync(path) {
|
|
169
|
-
path = normalizePath(path);
|
|
170
|
-
const { fs, path: resolved } = resolveMount(path, this);
|
|
171
|
-
try {
|
|
172
|
-
if (checkAccess && !hasAccess(this, fs.statSync(resolved), constants.W_OK)) {
|
|
173
|
-
throw UV('EACCES', 'unlink');
|
|
174
|
-
}
|
|
175
|
-
fs.unlinkSync(resolved);
|
|
47
|
+
if (e.code === 'ENOENT')
|
|
48
|
+
return { ...resolved, fullPath: path };
|
|
49
|
+
throw setUVMessage(Object.assign(e, { syscall: 'stat', path: maybePath }));
|
|
176
50
|
}
|
|
177
|
-
|
|
178
|
-
|
|
51
|
+
if (!isSymbolicLink(stats)) {
|
|
52
|
+
return { ...resolved, fullPath: maybePath, stats };
|
|
179
53
|
}
|
|
180
|
-
|
|
54
|
+
const target = resolvePath.call($, realDir, readlink.call($, maybePath));
|
|
55
|
+
return resolve($, target, false, extra);
|
|
181
56
|
}
|
|
182
|
-
|
|
183
|
-
|
|
57
|
+
/**
|
|
58
|
+
* @category VFS
|
|
59
|
+
* @internal
|
|
60
|
+
*/
|
|
61
|
+
export function open(path, opt) {
|
|
184
62
|
path = normalizePath(path);
|
|
185
63
|
const mode = normalizeMode(opt.mode, 0o644), flag = flags.parse(opt.flag);
|
|
186
|
-
path = opt.preserveSymlinks ? path :
|
|
64
|
+
path = opt.preserveSymlinks ? path : resolve(this, path).fullPath;
|
|
187
65
|
const { fs, path: resolved } = resolveMount(path, this);
|
|
188
66
|
let stats;
|
|
189
67
|
try {
|
|
@@ -215,241 +93,43 @@ function _openSync(path, opt) {
|
|
|
215
93
|
uid: parentStats.mode & constants.S_ISUID ? parentStats.uid : uid,
|
|
216
94
|
gid: parentStats.mode & constants.S_ISGID ? parentStats.gid : gid,
|
|
217
95
|
});
|
|
218
|
-
return new
|
|
96
|
+
return new Handle(this, path, fs, resolved, flag, inode);
|
|
219
97
|
}
|
|
220
98
|
if (checkAccess && (!hasAccess(this, stats, mode) || !hasAccess(this, stats, flags.toMode(flag)))) {
|
|
221
99
|
throw UV('EACCES', 'open', path);
|
|
222
100
|
}
|
|
223
101
|
if (flag & constants.O_EXCL)
|
|
224
102
|
throw UV('EEXIST', 'open', path);
|
|
225
|
-
const file = new
|
|
103
|
+
const file = new Handle(this, path, fs, resolved, flag, stats);
|
|
226
104
|
if (!opt.allowDirectory && stats.mode & constants.S_IFDIR)
|
|
227
105
|
throw UV('EISDIR', 'open', path);
|
|
228
106
|
if (flag & constants.O_TRUNC)
|
|
229
|
-
file.
|
|
107
|
+
file.truncateSync(0);
|
|
230
108
|
return file;
|
|
231
109
|
}
|
|
232
|
-
|
|
233
|
-
* Synchronous file open.
|
|
234
|
-
* @see https://nodejs.org/api/fs.html#fsopensyncpath-flags-mode
|
|
235
|
-
* @param flag {@link https://nodejs.org/api/fs.html#file-system-flags}
|
|
236
|
-
*/
|
|
237
|
-
export function openSync(path, flag, mode = constants.F_OK) {
|
|
238
|
-
return toFD(_openSync.call(this, path, { flag, mode }));
|
|
239
|
-
}
|
|
240
|
-
openSync;
|
|
241
|
-
/**
|
|
242
|
-
* Opens a file or symlink
|
|
243
|
-
* @internal
|
|
244
|
-
*/
|
|
245
|
-
export function lopenSync(path, flag, mode) {
|
|
246
|
-
return toFD(_openSync.call(this, path, { flag, mode, preserveSymlinks: true }));
|
|
247
|
-
}
|
|
248
|
-
export function readFileSync(path, _options = {}) {
|
|
249
|
-
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
250
|
-
try {
|
|
251
|
-
const options = normalizeOptions(_options, null, 'r', 0o644);
|
|
252
|
-
const flag = flags.parse(options.flag);
|
|
253
|
-
if (flag & constants.O_WRONLY)
|
|
254
|
-
throw UV('EBADF', 'read', path.toString());
|
|
255
|
-
const file = __addDisposableResource(env_2, typeof path == 'number'
|
|
256
|
-
? fromFD(this, path)
|
|
257
|
-
: _openSync.call(this, path.toString(), { flag: options.flag, mode: 0o644, preserveSymlinks: false }), false);
|
|
258
|
-
const { size } = file.stat();
|
|
259
|
-
const data = Buffer.alloc(size);
|
|
260
|
-
file.read(data, 0, size, 0);
|
|
261
|
-
return options.encoding ? data.toString(options.encoding) : data;
|
|
262
|
-
}
|
|
263
|
-
catch (e_2) {
|
|
264
|
-
env_2.error = e_2;
|
|
265
|
-
env_2.hasError = true;
|
|
266
|
-
}
|
|
267
|
-
finally {
|
|
268
|
-
__disposeResources(env_2);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
readFileSync;
|
|
272
|
-
export function writeFileSync(path, data, _options = {}) {
|
|
273
|
-
const env_3 = { stack: [], error: void 0, hasError: false };
|
|
274
|
-
try {
|
|
275
|
-
const options = normalizeOptions(_options, 'utf8', 'w+', 0o644);
|
|
276
|
-
const flag = flags.parse(options.flag);
|
|
277
|
-
if (!(flag & constants.O_WRONLY || flag & constants.O_RDWR)) {
|
|
278
|
-
throw new Exception(Errno.EINVAL, 'Flag passed to writeFile must allow for writing');
|
|
279
|
-
}
|
|
280
|
-
if (typeof data != 'string' && !options.encoding) {
|
|
281
|
-
throw new Exception(Errno.EINVAL, 'Encoding not specified');
|
|
282
|
-
}
|
|
283
|
-
const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
284
|
-
if (!encodedData) {
|
|
285
|
-
throw new Exception(Errno.EINVAL, 'Data not specified');
|
|
286
|
-
}
|
|
287
|
-
const file = __addDisposableResource(env_3, typeof path == 'number'
|
|
288
|
-
? fromFD(this, path)
|
|
289
|
-
: _openSync.call(this, path.toString(), {
|
|
290
|
-
flag,
|
|
291
|
-
mode: options.mode,
|
|
292
|
-
preserveSymlinks: true,
|
|
293
|
-
}), false);
|
|
294
|
-
file.write(encodedData, 0, encodedData.byteLength, 0);
|
|
295
|
-
emitChange(this, 'change', path.toString());
|
|
296
|
-
}
|
|
297
|
-
catch (e_3) {
|
|
298
|
-
env_3.error = e_3;
|
|
299
|
-
env_3.hasError = true;
|
|
300
|
-
}
|
|
301
|
-
finally {
|
|
302
|
-
__disposeResources(env_3);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
writeFileSync;
|
|
306
|
-
/**
|
|
307
|
-
* Asynchronously append data to a file, creating the file if it not yet exists.
|
|
308
|
-
* @option encoding Defaults to `'utf8'`.
|
|
309
|
-
* @option mode Defaults to `0644`.
|
|
310
|
-
* @option flag Defaults to `'a+'`.
|
|
311
|
-
*/
|
|
312
|
-
export function appendFileSync(filename, data, _options = {}) {
|
|
313
|
-
const env_4 = { stack: [], error: void 0, hasError: false };
|
|
314
|
-
try {
|
|
315
|
-
const options = normalizeOptions(_options, 'utf8', 'a+', 0o644);
|
|
316
|
-
const flag = flags.parse(options.flag);
|
|
317
|
-
if (!(flag & constants.O_APPEND)) {
|
|
318
|
-
throw new Exception(Errno.EINVAL, 'Flag passed to appendFile must allow for appending');
|
|
319
|
-
}
|
|
320
|
-
if (typeof data != 'string' && !options.encoding) {
|
|
321
|
-
throw new Exception(Errno.EINVAL, 'Encoding not specified');
|
|
322
|
-
}
|
|
323
|
-
const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
324
|
-
const file = __addDisposableResource(env_4, _openSync.call(this, typeof filename == 'number' ? fromFD(this, filename).path : filename.toString(), {
|
|
325
|
-
flag,
|
|
326
|
-
mode: options.mode,
|
|
327
|
-
preserveSymlinks: true,
|
|
328
|
-
}), false);
|
|
329
|
-
file.write(encodedData, 0, encodedData.byteLength);
|
|
330
|
-
}
|
|
331
|
-
catch (e_4) {
|
|
332
|
-
env_4.error = e_4;
|
|
333
|
-
env_4.hasError = true;
|
|
334
|
-
}
|
|
335
|
-
finally {
|
|
336
|
-
__disposeResources(env_4);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
appendFileSync;
|
|
340
|
-
export function fstatSync(fd, options) {
|
|
341
|
-
const stats = fromFD(this, fd).stat();
|
|
342
|
-
return options?.bigint ? new BigIntStats(stats) : new Stats(stats);
|
|
343
|
-
}
|
|
344
|
-
fstatSync;
|
|
345
|
-
export function closeSync(fd) {
|
|
346
|
-
fromFD(this, fd).close();
|
|
347
|
-
deleteFD(this, fd);
|
|
348
|
-
}
|
|
349
|
-
closeSync;
|
|
350
|
-
export function ftruncateSync(fd, len = 0) {
|
|
351
|
-
len ||= 0;
|
|
352
|
-
if (len < 0) {
|
|
353
|
-
throw new Exception(Errno.EINVAL);
|
|
354
|
-
}
|
|
355
|
-
fromFD(this, fd).truncate(len);
|
|
356
|
-
}
|
|
357
|
-
ftruncateSync;
|
|
358
|
-
export function fsyncSync(fd) {
|
|
359
|
-
fromFD(this, fd).sync();
|
|
360
|
-
}
|
|
361
|
-
fsyncSync;
|
|
362
|
-
export function fdatasyncSync(fd) {
|
|
363
|
-
fromFD(this, fd).datasync();
|
|
364
|
-
}
|
|
365
|
-
fdatasyncSync;
|
|
366
|
-
export function writeSync(fd, data, posOrOff, lenOrEnc, pos) {
|
|
367
|
-
let buffer, offset, length, position;
|
|
368
|
-
if (typeof data === 'string') {
|
|
369
|
-
// Signature 1: (fd, string, [position?, [encoding?]])
|
|
370
|
-
position = typeof posOrOff === 'number' ? posOrOff : null;
|
|
371
|
-
const encoding = typeof lenOrEnc === 'string' ? lenOrEnc : 'utf8';
|
|
372
|
-
offset = 0;
|
|
373
|
-
buffer = Buffer.from(data, encoding);
|
|
374
|
-
length = buffer.byteLength;
|
|
375
|
-
}
|
|
376
|
-
else {
|
|
377
|
-
// Signature 2: (fd, buffer, offset, length, position?)
|
|
378
|
-
buffer = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
379
|
-
offset = posOrOff;
|
|
380
|
-
length = lenOrEnc;
|
|
381
|
-
position = typeof pos === 'number' ? pos : null;
|
|
382
|
-
}
|
|
383
|
-
const file = fromFD(this, fd);
|
|
384
|
-
position ??= file.position;
|
|
385
|
-
const bytesWritten = file.write(buffer, offset, length, position);
|
|
386
|
-
emitChange(this, 'change', file.path);
|
|
387
|
-
return bytesWritten;
|
|
388
|
-
}
|
|
389
|
-
writeSync;
|
|
390
|
-
/**
|
|
391
|
-
* Read data from the file specified by `fd`.
|
|
392
|
-
* @param buffer The buffer that the data will be written to.
|
|
393
|
-
* @param offset The offset within the buffer where writing will start.
|
|
394
|
-
* @param length An integer specifying the number of bytes to read.
|
|
395
|
-
* @param position An integer specifying where to begin reading from in the file.
|
|
396
|
-
* If position is null, data will be read from the current file position.
|
|
397
|
-
*/
|
|
398
|
-
export function readSync(fd, buffer, options, length, position) {
|
|
399
|
-
const file = fromFD(this, fd);
|
|
400
|
-
const offset = typeof options == 'object' ? options.offset : options;
|
|
401
|
-
if (typeof options == 'object') {
|
|
402
|
-
length = options.length;
|
|
403
|
-
position = options.position;
|
|
404
|
-
}
|
|
405
|
-
position = Number(position);
|
|
406
|
-
if (isNaN(position)) {
|
|
407
|
-
position = file.position;
|
|
408
|
-
}
|
|
409
|
-
return file.read(buffer, offset, length, position);
|
|
410
|
-
}
|
|
411
|
-
readSync;
|
|
412
|
-
export function fchownSync(fd, uid, gid) {
|
|
413
|
-
fromFD(this, fd).chown(uid, gid);
|
|
414
|
-
}
|
|
415
|
-
fchownSync;
|
|
416
|
-
export function fchmodSync(fd, mode) {
|
|
417
|
-
const numMode = normalizeMode(mode, -1);
|
|
418
|
-
if (numMode < 0) {
|
|
419
|
-
throw new Exception(Errno.EINVAL, `Invalid mode.`);
|
|
420
|
-
}
|
|
421
|
-
fromFD(this, fd).chmod(numMode);
|
|
422
|
-
}
|
|
423
|
-
fchmodSync;
|
|
424
|
-
/**
|
|
425
|
-
* Change the file timestamps of a file referenced by the supplied file descriptor.
|
|
426
|
-
*/
|
|
427
|
-
export function futimesSync(fd, atime, mtime) {
|
|
428
|
-
fromFD(this, fd).utimes(normalizeTime(atime), normalizeTime(mtime));
|
|
429
|
-
}
|
|
430
|
-
futimesSync;
|
|
431
|
-
export function rmdirSync(path) {
|
|
110
|
+
export function readlink(path) {
|
|
432
111
|
path = normalizePath(path);
|
|
433
|
-
const { fs, path: resolved } =
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
112
|
+
const { fs, stats, path: resolved } = resolve(this, path, true);
|
|
113
|
+
if (!stats)
|
|
114
|
+
throw UV('ENOENT', 'readlink', path);
|
|
115
|
+
if (checkAccess && !hasAccess(this, stats, constants.R_OK))
|
|
116
|
+
throw UV('EACCES', 'readlink', path);
|
|
117
|
+
if (!isSymbolicLink(stats))
|
|
118
|
+
throw UV('EINVAL', 'readlink', path);
|
|
119
|
+
const size = stats.size;
|
|
120
|
+
const data = new Uint8Array(size);
|
|
121
|
+
fs.readSync(resolved, data, 0, size);
|
|
122
|
+
return decodeUTF8(data);
|
|
123
|
+
}
|
|
124
|
+
export function mkdir(path, options = {}) {
|
|
125
|
+
path = normalizePath(path);
|
|
126
|
+
const { fs, path: resolved } = resolve(this, path);
|
|
444
127
|
const { euid: uid, egid: gid } = this?.credentials ?? defaultContext.credentials;
|
|
445
|
-
|
|
446
|
-
const mode = normalizeMode(options?.mode, 0o777);
|
|
447
|
-
path = realpathSync.call(this, path);
|
|
448
|
-
const { fs, path: resolved } = resolveMount(path, this);
|
|
128
|
+
const { mode = 0o777, recursive } = options;
|
|
449
129
|
const __create = (path, resolved, parent) => {
|
|
450
130
|
if (checkAccess && !hasAccess(this, parent, constants.W_OK))
|
|
451
131
|
throw UV('EACCES', 'mkdir', dirname(path));
|
|
452
|
-
const inode =
|
|
132
|
+
const inode = fs.mkdirSync(resolved, {
|
|
453
133
|
mode,
|
|
454
134
|
uid: parent.mode & constants.S_ISUID ? parent.uid : uid,
|
|
455
135
|
gid: parent.mode & constants.S_ISGID ? parent.gid : gid,
|
|
@@ -457,33 +137,31 @@ export function mkdirSync(path, options) {
|
|
|
457
137
|
emitChange(this, 'rename', path);
|
|
458
138
|
return inode;
|
|
459
139
|
};
|
|
460
|
-
if (!
|
|
461
|
-
__create(path, resolved,
|
|
140
|
+
if (!recursive) {
|
|
141
|
+
__create(path, resolved, fs.statSync(dirname(resolved)));
|
|
462
142
|
return;
|
|
463
143
|
}
|
|
464
144
|
const dirs = [];
|
|
465
|
-
for (let dir = resolved, original = path; !
|
|
145
|
+
for (let dir = resolved, original = path; !fs.existsSync(dir); dir = dirname(dir), original = dirname(original)) {
|
|
466
146
|
dirs.unshift({ resolved: dir, original });
|
|
467
147
|
}
|
|
468
148
|
if (!dirs.length)
|
|
469
149
|
return;
|
|
470
|
-
const stats = [
|
|
150
|
+
const stats = [fs.statSync(dirname(dirs[0].resolved))];
|
|
471
151
|
for (const [i, dir] of dirs.entries()) {
|
|
472
152
|
stats.push(__create(dir.original, dir.resolved, stats[i]));
|
|
473
153
|
}
|
|
474
154
|
return dirs[0].original;
|
|
475
155
|
}
|
|
476
|
-
|
|
477
|
-
export function readdirSync(path, options) {
|
|
478
|
-
options = typeof options === 'object' ? options : { encoding: options };
|
|
156
|
+
export function readdir(path, options = {}) {
|
|
479
157
|
path = normalizePath(path);
|
|
480
|
-
const { fs, path: resolved } =
|
|
481
|
-
const stats =
|
|
158
|
+
const { fs, path: resolved } = resolve(this, path);
|
|
159
|
+
const stats = fs.statSync(resolved);
|
|
482
160
|
if (checkAccess && !hasAccess(this, stats, constants.R_OK))
|
|
483
161
|
throw UV('EACCES', 'readdir', path);
|
|
484
162
|
if (!isDirectory(stats))
|
|
485
163
|
throw UV('ENOTDIR', 'readdir', path);
|
|
486
|
-
const entries =
|
|
164
|
+
const entries = fs.readdirSync(resolved);
|
|
487
165
|
// Iterate over entries and handle recursive case if needed
|
|
488
166
|
const values = [];
|
|
489
167
|
const addEntry = (entry) => {
|
|
@@ -494,20 +172,17 @@ export function readdirSync(path, options) {
|
|
|
494
172
|
catch (e) {
|
|
495
173
|
if (e.code == 'ENOENT')
|
|
496
174
|
return;
|
|
497
|
-
throw
|
|
498
|
-
}
|
|
499
|
-
if (options?.withFileTypes) {
|
|
500
|
-
values.push(Dirent.from(entry, entryStat, options.encoding));
|
|
501
|
-
}
|
|
502
|
-
else if (options?.encoding == 'buffer') {
|
|
503
|
-
values.push(Buffer.from(entry));
|
|
504
|
-
}
|
|
505
|
-
else {
|
|
506
|
-
values.push(entry);
|
|
175
|
+
throw e;
|
|
507
176
|
}
|
|
177
|
+
const ent = new Dirent();
|
|
178
|
+
ent.ino = entryStat.ino;
|
|
179
|
+
ent.type = ifToDt(entryStat.mode);
|
|
180
|
+
ent.path = entry;
|
|
181
|
+
ent.name = basename(entry);
|
|
182
|
+
values.push(ent);
|
|
508
183
|
if (!isDirectory(entryStat) || !options?.recursive)
|
|
509
184
|
return;
|
|
510
|
-
const children =
|
|
185
|
+
const children = fs.readdirSync(join(resolved, entry));
|
|
511
186
|
for (const child of children)
|
|
512
187
|
addEntry(join(entry, child));
|
|
513
188
|
};
|
|
@@ -515,376 +190,57 @@ export function readdirSync(path, options) {
|
|
|
515
190
|
addEntry(entry);
|
|
516
191
|
return values;
|
|
517
192
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
if (checkAccess && !hasAccess(this, stats, constants.R_OK))
|
|
535
|
-
throw UV('EACCES', 'link', path);
|
|
536
|
-
return wrap(fs, 'linkSync', targetPath, linkPath)(path, link.path);
|
|
537
|
-
}
|
|
538
|
-
linkSync;
|
|
539
|
-
/**
|
|
540
|
-
* Synchronous `symlink`.
|
|
541
|
-
* @param target target path
|
|
542
|
-
* @param path link path
|
|
543
|
-
* @param type can be either `'dir'` or `'file'` (default is `'file'`)
|
|
544
|
-
*/
|
|
545
|
-
export function symlinkSync(target, path, type = 'file') {
|
|
546
|
-
const env_5 = { stack: [], error: void 0, hasError: false };
|
|
547
|
-
try {
|
|
548
|
-
if (!['file', 'dir', 'junction'].includes(type))
|
|
549
|
-
throw new TypeError('Invalid symlink type: ' + type);
|
|
550
|
-
path = normalizePath(path);
|
|
551
|
-
const file = __addDisposableResource(env_5, _openSync.call(this, path, { flag: 'wx', mode: 0o644 }), false);
|
|
552
|
-
file.write(encodeUTF8(normalizePath(target, true)));
|
|
553
|
-
file.chmod(constants.S_IFLNK);
|
|
554
|
-
}
|
|
555
|
-
catch (e_5) {
|
|
556
|
-
env_5.error = e_5;
|
|
557
|
-
env_5.hasError = true;
|
|
558
|
-
}
|
|
559
|
-
finally {
|
|
560
|
-
__disposeResources(env_5);
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
symlinkSync;
|
|
564
|
-
export function readlinkSync(path, options) {
|
|
565
|
-
const env_6 = { stack: [], error: void 0, hasError: false };
|
|
566
|
-
try {
|
|
567
|
-
const handle = __addDisposableResource(env_6, _openSync.call(this, normalizePath(path), { flag: 'r', mode: 0o644, preserveSymlinks: true }), false);
|
|
568
|
-
if (!isSymbolicLink(handle.inode))
|
|
569
|
-
throw new Exception(Errno.EINVAL, 'Not a symbolic link: ' + path);
|
|
570
|
-
const size = handle.inode.size;
|
|
571
|
-
const data = Buffer.alloc(size);
|
|
572
|
-
handle.read(data, 0, size, 0);
|
|
573
|
-
const encoding = typeof options == 'object' ? options?.encoding : options;
|
|
574
|
-
if (encoding == 'buffer') {
|
|
575
|
-
return data;
|
|
576
|
-
}
|
|
577
|
-
// always defaults to utf-8 to avoid wrangler (cloudflare) worker "unknown encoding" exception
|
|
578
|
-
return data.toString(encoding ?? 'utf-8');
|
|
579
|
-
}
|
|
580
|
-
catch (e_6) {
|
|
581
|
-
env_6.error = e_6;
|
|
582
|
-
env_6.hasError = true;
|
|
583
|
-
}
|
|
584
|
-
finally {
|
|
585
|
-
__disposeResources(env_6);
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
readlinkSync;
|
|
589
|
-
export function chownSync(path, uid, gid) {
|
|
590
|
-
const fd = openSync.call(this, path, 'r+');
|
|
591
|
-
fchownSync.call(this, fd, uid, gid);
|
|
592
|
-
closeSync.call(this, fd);
|
|
593
|
-
}
|
|
594
|
-
chownSync;
|
|
595
|
-
export function lchownSync(path, uid, gid) {
|
|
596
|
-
const fd = lopenSync.call(this, path, 'r+');
|
|
597
|
-
fchownSync.call(this, fd, uid, gid);
|
|
598
|
-
closeSync.call(this, fd);
|
|
599
|
-
}
|
|
600
|
-
lchownSync;
|
|
601
|
-
export function chmodSync(path, mode) {
|
|
602
|
-
const fd = openSync.call(this, path, 'r+');
|
|
603
|
-
fchmodSync.call(this, fd, mode);
|
|
604
|
-
closeSync.call(this, fd);
|
|
605
|
-
}
|
|
606
|
-
chmodSync;
|
|
607
|
-
export function lchmodSync(path, mode) {
|
|
608
|
-
const fd = lopenSync.call(this, path, 'r+');
|
|
609
|
-
fchmodSync.call(this, fd, mode);
|
|
610
|
-
closeSync.call(this, fd);
|
|
611
|
-
}
|
|
612
|
-
lchmodSync;
|
|
613
|
-
/**
|
|
614
|
-
* Change file timestamps of the file referenced by the supplied path.
|
|
615
|
-
*/
|
|
616
|
-
export function utimesSync(path, atime, mtime) {
|
|
617
|
-
const fd = openSync.call(this, path, 'r+');
|
|
618
|
-
futimesSync.call(this, fd, atime, mtime);
|
|
619
|
-
closeSync.call(this, fd);
|
|
620
|
-
}
|
|
621
|
-
utimesSync;
|
|
622
|
-
/**
|
|
623
|
-
* Change file timestamps of the file referenced by the supplied path.
|
|
624
|
-
*/
|
|
625
|
-
export function lutimesSync(path, atime, mtime) {
|
|
626
|
-
const fd = lopenSync.call(this, path, 'r+');
|
|
627
|
-
futimesSync.call(this, fd, atime, mtime);
|
|
628
|
-
closeSync.call(this, fd);
|
|
629
|
-
}
|
|
630
|
-
lutimesSync;
|
|
631
|
-
/**
|
|
632
|
-
* Resolves the mount and real path for a path.
|
|
633
|
-
* Additionally, any stats fetched will be returned for de-duplication
|
|
634
|
-
* @internal @hidden
|
|
635
|
-
*/
|
|
636
|
-
function _resolveSync($, path, preserveSymlinks) {
|
|
637
|
-
if (preserveSymlinks) {
|
|
638
|
-
const resolved = resolveMount(path, $);
|
|
639
|
-
const stats = resolved.fs.statSync(resolved.path);
|
|
640
|
-
return { ...resolved, fullPath: path, stats };
|
|
641
|
-
}
|
|
642
|
-
/* Try to resolve it directly. If this works,
|
|
643
|
-
that means we don't need to perform any resolution for parent directories. */
|
|
644
|
-
try {
|
|
645
|
-
const resolved = resolveMount(path, $);
|
|
646
|
-
// Stat it to make sure it exists
|
|
647
|
-
const stats = resolved.fs.statSync(resolved.path);
|
|
648
|
-
if (!isSymbolicLink(stats)) {
|
|
649
|
-
return { ...resolved, fullPath: path, stats };
|
|
650
|
-
}
|
|
651
|
-
const target = resolve.call($, dirname(path), readlinkSync.call($, path).toString());
|
|
652
|
-
return _resolveSync($, target);
|
|
653
|
-
}
|
|
654
|
-
catch {
|
|
655
|
-
// Go the long way
|
|
656
|
-
}
|
|
657
|
-
const { base, dir } = parse(path);
|
|
658
|
-
const realDir = dir == '/' ? '/' : realpathSync.call($, dir);
|
|
659
|
-
const maybePath = join(realDir, base);
|
|
660
|
-
const resolved = resolveMount(maybePath, $);
|
|
661
|
-
let stats;
|
|
193
|
+
export function rename(oldPath, newPath) {
|
|
194
|
+
oldPath = normalizePath(oldPath);
|
|
195
|
+
newPath = normalizePath(newPath);
|
|
196
|
+
const $ex = { syscall: 'rename', path: oldPath, dest: newPath };
|
|
197
|
+
const src = resolve(this, oldPath, true, $ex);
|
|
198
|
+
const dst = resolveMount(newPath, this, $ex);
|
|
199
|
+
if (src.fs.uuid !== dst.fs.uuid)
|
|
200
|
+
throw UV('EXDEV', $ex);
|
|
201
|
+
if (dst.path.startsWith(src.path + '/'))
|
|
202
|
+
throw UV('EBUSY', $ex);
|
|
203
|
+
if (!src.stats)
|
|
204
|
+
throw UV('ENOENT', $ex);
|
|
205
|
+
const fs = src.fs;
|
|
206
|
+
const oldParent = fs.statSync(dirname(src.path));
|
|
207
|
+
const newParent = fs.statSync(dirname(dst.path));
|
|
208
|
+
let newStats;
|
|
662
209
|
try {
|
|
663
|
-
|
|
210
|
+
newStats = fs.statSync(dst.path);
|
|
664
211
|
}
|
|
665
212
|
catch (e) {
|
|
666
|
-
if (e.code
|
|
667
|
-
|
|
668
|
-
throw setUVMessage(Object.assign(e, { syscall: 'stat', path: maybePath }));
|
|
669
|
-
}
|
|
670
|
-
if (!isSymbolicLink(stats)) {
|
|
671
|
-
return { ...resolved, fullPath: maybePath, stats };
|
|
672
|
-
}
|
|
673
|
-
const target = resolve.call($, realDir, readlinkSync.call($, maybePath).toString());
|
|
674
|
-
return _resolveSync($, target);
|
|
675
|
-
}
|
|
676
|
-
export function realpathSync(path, options) {
|
|
677
|
-
const encoding = typeof options == 'string' ? options : (options?.encoding ?? 'utf8');
|
|
678
|
-
path = normalizePath(path);
|
|
679
|
-
const { fullPath } = _resolveSync(this, path);
|
|
680
|
-
if (encoding == 'utf8' || encoding == 'utf-8')
|
|
681
|
-
return fullPath;
|
|
682
|
-
const buf = Buffer.from(fullPath, 'utf-8');
|
|
683
|
-
if (encoding == 'buffer')
|
|
684
|
-
return buf;
|
|
685
|
-
return buf.toString(encoding);
|
|
686
|
-
}
|
|
687
|
-
realpathSync;
|
|
688
|
-
export function accessSync(path, mode = 0o600) {
|
|
689
|
-
if (!checkAccess)
|
|
690
|
-
return;
|
|
691
|
-
if (!hasAccess(this, statSync.call(this, path), mode)) {
|
|
692
|
-
throw new Exception(Errno.EACCES);
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
accessSync;
|
|
696
|
-
/**
|
|
697
|
-
* Synchronous `rm`. Removes files or directories (recursively).
|
|
698
|
-
* @param path The path to the file or directory to remove.
|
|
699
|
-
*/
|
|
700
|
-
export function rmSync(path, options) {
|
|
701
|
-
path = normalizePath(path);
|
|
702
|
-
let stats;
|
|
703
|
-
try {
|
|
704
|
-
stats = lstatSync.bind(this)(path);
|
|
705
|
-
}
|
|
706
|
-
catch (error) {
|
|
707
|
-
if (error.code != 'ENOENT' || !options?.force)
|
|
708
|
-
throw error;
|
|
709
|
-
}
|
|
710
|
-
if (!stats)
|
|
711
|
-
return;
|
|
712
|
-
switch (stats.mode & constants.S_IFMT) {
|
|
713
|
-
case constants.S_IFDIR:
|
|
714
|
-
if (options?.recursive) {
|
|
715
|
-
for (const entry of readdirSync.call(this, path)) {
|
|
716
|
-
rmSync.call(this, join(path, entry), options);
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
rmdirSync.call(this, path);
|
|
720
|
-
break;
|
|
721
|
-
case constants.S_IFREG:
|
|
722
|
-
case constants.S_IFLNK:
|
|
723
|
-
case constants.S_IFBLK:
|
|
724
|
-
case constants.S_IFCHR:
|
|
725
|
-
unlinkSync.call(this, path);
|
|
726
|
-
break;
|
|
727
|
-
case constants.S_IFIFO:
|
|
728
|
-
case constants.S_IFSOCK:
|
|
729
|
-
default:
|
|
730
|
-
throw UV('ENOSYS', 'rm', path);
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
rmSync;
|
|
734
|
-
export function mkdtempSync(prefix, options) {
|
|
735
|
-
const encoding = typeof options === 'object' ? options?.encoding : options || 'utf8';
|
|
736
|
-
const path = _tempDirName(prefix);
|
|
737
|
-
mkdirSync.call(this, path);
|
|
738
|
-
return encoding == 'buffer' ? Buffer.from(path) : path;
|
|
739
|
-
}
|
|
740
|
-
mkdtempSync;
|
|
741
|
-
/**
|
|
742
|
-
* Returns a disposable object whose `path` property holds the created directory path.
|
|
743
|
-
* When the object is disposed, the directory and its contents will be removed if it still exists.
|
|
744
|
-
* If the directory cannot be deleted, disposal will throw an error.
|
|
745
|
-
* The object has a `remove()` method which will perform the same task.
|
|
746
|
-
* @todo Add `satisfies` and maybe change return type once @types/node adds this.
|
|
747
|
-
*/
|
|
748
|
-
export function mkdtempDisposableSync(prefix, options) {
|
|
749
|
-
const path = _tempDirName(prefix);
|
|
750
|
-
mkdirSync.call(this, path);
|
|
751
|
-
const remove = () => rmSync(path, { recursive: true, force: true });
|
|
752
|
-
return { path, remove, [Symbol.dispose]: remove };
|
|
753
|
-
}
|
|
754
|
-
/**
|
|
755
|
-
* Synchronous `copyFile`. Copies a file.
|
|
756
|
-
* @param flags Optional flags for the copy operation. Currently supports these flags:
|
|
757
|
-
* - `fs.constants.COPYFILE_EXCL`: If the destination file already exists, the operation fails.
|
|
758
|
-
*/
|
|
759
|
-
export function copyFileSync(source, destination, flags) {
|
|
760
|
-
source = normalizePath(source);
|
|
761
|
-
destination = normalizePath(destination);
|
|
762
|
-
if (flags && flags & constants.COPYFILE_EXCL && existsSync(destination))
|
|
763
|
-
throw UV('EEXIST', 'copyFile', destination);
|
|
764
|
-
writeFileSync.call(this, destination, readFileSync(source));
|
|
765
|
-
emitChange(this, 'rename', destination.toString());
|
|
766
|
-
}
|
|
767
|
-
copyFileSync;
|
|
768
|
-
/**
|
|
769
|
-
* Synchronous `readv`. Reads from a file descriptor into multiple buffers.
|
|
770
|
-
* @param fd The file descriptor.
|
|
771
|
-
* @param buffers An array of Uint8Array buffers.
|
|
772
|
-
* @param position The position in the file where to begin reading.
|
|
773
|
-
* @returns The number of bytes read.
|
|
774
|
-
*/
|
|
775
|
-
export function readvSync(fd, buffers, position) {
|
|
776
|
-
const file = fromFD(this, fd);
|
|
777
|
-
let bytesRead = 0;
|
|
778
|
-
for (const buffer of buffers) {
|
|
779
|
-
bytesRead += file.read(buffer, 0, buffer.byteLength, position + bytesRead);
|
|
780
|
-
}
|
|
781
|
-
return bytesRead;
|
|
782
|
-
}
|
|
783
|
-
readvSync;
|
|
784
|
-
/**
|
|
785
|
-
* Synchronous `writev`. Writes from multiple buffers into a file descriptor.
|
|
786
|
-
* @param fd The file descriptor.
|
|
787
|
-
* @param buffers An array of Uint8Array buffers.
|
|
788
|
-
* @param position The position in the file where to begin writing.
|
|
789
|
-
* @returns The number of bytes written.
|
|
790
|
-
*/
|
|
791
|
-
export function writevSync(fd, buffers, position) {
|
|
792
|
-
const file = fromFD(this, fd);
|
|
793
|
-
let bytesWritten = 0;
|
|
794
|
-
for (const buffer of buffers) {
|
|
795
|
-
bytesWritten += file.write(new Uint8Array(buffer.buffer), 0, buffer.byteLength, position + bytesWritten);
|
|
796
|
-
}
|
|
797
|
-
return bytesWritten;
|
|
798
|
-
}
|
|
799
|
-
writevSync;
|
|
800
|
-
/**
|
|
801
|
-
* Synchronous `opendir`. Opens a directory.
|
|
802
|
-
* @param path The path to the directory.
|
|
803
|
-
* @param options Options for opening the directory.
|
|
804
|
-
* @returns A `Dir` object representing the opened directory.
|
|
805
|
-
* @todo Handle options
|
|
806
|
-
*/
|
|
807
|
-
export function opendirSync(path, options) {
|
|
808
|
-
path = normalizePath(path);
|
|
809
|
-
return new Dir(path, this);
|
|
810
|
-
}
|
|
811
|
-
opendirSync;
|
|
812
|
-
/**
|
|
813
|
-
* Synchronous `cp`. Recursively copies a file or directory.
|
|
814
|
-
* @param source The source file or directory.
|
|
815
|
-
* @param destination The destination file or directory.
|
|
816
|
-
* @param opts Options for the copy operation. Currently supports these options from Node.js 'fs.cpSync':
|
|
817
|
-
* - `dereference`: Dereference symbolic links. *(unconfirmed)*
|
|
818
|
-
* - `errorOnExist`: Throw an error if the destination file or directory already exists.
|
|
819
|
-
* - `filter`: A function that takes a source and destination path and returns a boolean, indicating whether to copy `source` element.
|
|
820
|
-
* - `force`: Overwrite the destination if it exists, and overwrite existing readonly destination files. *(unconfirmed)*
|
|
821
|
-
* - `preserveTimestamps`: Preserve file timestamps.
|
|
822
|
-
* - `recursive`: If `true`, copies directories recursively.
|
|
823
|
-
*/
|
|
824
|
-
export function cpSync(source, destination, opts) {
|
|
825
|
-
source = normalizePath(source);
|
|
826
|
-
destination = normalizePath(destination);
|
|
827
|
-
const srcStats = lstatSync.call(this, source); // Use lstat to follow symlinks if not dereferencing
|
|
828
|
-
if (opts?.errorOnExist && existsSync.call(this, destination))
|
|
829
|
-
throw UV('EEXIST', 'cp', destination);
|
|
830
|
-
switch (srcStats.mode & constants.S_IFMT) {
|
|
831
|
-
case constants.S_IFDIR:
|
|
832
|
-
if (!opts?.recursive)
|
|
833
|
-
throw UV('EISDIR', 'cp', source);
|
|
834
|
-
mkdirSync.call(this, destination, { recursive: true }); // Ensure the destination directory exists
|
|
835
|
-
for (const dirent of readdirSync.call(this, source, { withFileTypes: true })) {
|
|
836
|
-
if (opts.filter && !opts.filter(join(source, dirent.name), join(destination, dirent.name))) {
|
|
837
|
-
continue; // Skip if the filter returns false
|
|
838
|
-
}
|
|
839
|
-
cpSync.call(this, join(source, dirent.name), join(destination, dirent.name), opts);
|
|
840
|
-
}
|
|
841
|
-
break;
|
|
842
|
-
case constants.S_IFREG:
|
|
843
|
-
case constants.S_IFLNK:
|
|
844
|
-
copyFileSync.call(this, source, destination);
|
|
845
|
-
break;
|
|
846
|
-
case constants.S_IFBLK:
|
|
847
|
-
case constants.S_IFCHR:
|
|
848
|
-
case constants.S_IFIFO:
|
|
849
|
-
case constants.S_IFSOCK:
|
|
850
|
-
default:
|
|
851
|
-
throw UV('ENOSYS', 'cp', source);
|
|
852
|
-
}
|
|
853
|
-
// Optionally preserve timestamps
|
|
854
|
-
if (opts?.preserveTimestamps) {
|
|
855
|
-
utimesSync.call(this, destination, srcStats.atime, srcStats.mtime);
|
|
213
|
+
if (e.code != 'ENOENT')
|
|
214
|
+
throw e;
|
|
856
215
|
}
|
|
216
|
+
if (checkAccess && (!hasAccess(this, oldParent, constants.R_OK) || !hasAccess(this, newParent, constants.W_OK)))
|
|
217
|
+
throw UV('EACCES', $ex);
|
|
218
|
+
if (newStats && !isDirectory(src.stats) && isDirectory(newStats))
|
|
219
|
+
throw UV('EISDIR', $ex);
|
|
220
|
+
if (newStats && isDirectory(src.stats) && !isDirectory(newStats))
|
|
221
|
+
throw UV('ENOTDIR', $ex);
|
|
222
|
+
src.fs.renameSync(src.path, dst.path);
|
|
223
|
+
emitChange(this, 'rename', oldPath);
|
|
224
|
+
emitChange(this, 'change', newPath);
|
|
857
225
|
}
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
const {
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
const
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
*/
|
|
879
|
-
if (statSync(fullPath).isDirectory() && regexPatterns.some(pattern => pattern.source.includes('.*'))) {
|
|
880
|
-
recursiveList(fullPath);
|
|
881
|
-
}
|
|
882
|
-
if (regexPatterns.some(pattern => pattern.test(fullPath.replace(/^\/+/g, '')))) {
|
|
883
|
-
results.push(withFileTypes ? entry : fullPath.replace(/^\/+/g, ''));
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
recursiveList(cwd);
|
|
888
|
-
return results;
|
|
226
|
+
export function link(target, link) {
|
|
227
|
+
target = normalizePath(target);
|
|
228
|
+
link = normalizePath(link);
|
|
229
|
+
const $ex = { syscall: 'link', path: link, dest: target };
|
|
230
|
+
const { fs, path: resolved } = resolveMount(target, this, $ex);
|
|
231
|
+
const dst = resolveMount(link, this, $ex);
|
|
232
|
+
if (fs.uuid !== dst.fs.uuid)
|
|
233
|
+
throw UV('EXDEV', $ex);
|
|
234
|
+
const stats = fs.statSync(resolved);
|
|
235
|
+
if (checkAccess) {
|
|
236
|
+
if (!hasAccess(this, stats, constants.R_OK))
|
|
237
|
+
throw UV('EACCES', $ex);
|
|
238
|
+
const dirStats = fs.statSync(dirname(resolved));
|
|
239
|
+
if (!hasAccess(this, dirStats, constants.R_OK))
|
|
240
|
+
throw UV('EACCES', $ex);
|
|
241
|
+
const destStats = fs.statSync(dirname(dst.path));
|
|
242
|
+
if (!hasAccess(this, destStats, constants.W_OK))
|
|
243
|
+
throw UV('EACCES', $ex);
|
|
244
|
+
}
|
|
245
|
+
return fs.linkSync(resolved, dst.path);
|
|
889
246
|
}
|
|
890
|
-
globSync;
|