@zenfs/core 0.18.0 → 1.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backends/overlay.d.ts +3 -5
- package/dist/backends/overlay.js +9 -9
- package/dist/backends/port/fs.d.ts +1 -2
- package/dist/backends/port/fs.js +2 -3
- package/dist/browser.min.js +4 -4
- package/dist/browser.min.js.map +3 -3
- package/dist/emulation/promises.js +14 -15
- package/dist/emulation/sync.js +13 -14
- package/dist/file.d.ts +22 -13
- package/dist/file.js +16 -7
- package/dist/mixins/mutexed.d.ts +72 -10
- package/dist/mixins/mutexed.js +375 -379
- package/dist/mixins/shared.d.ts +1 -0
- package/dist/mixins/shared.js +1 -0
- package/dist/stats.d.ts +2 -3
- package/dist/stats.js +4 -4
- package/dist/utils.d.ts +2 -1
- package/package.json +1 -1
- package/readme.md +1 -1
- package/src/backends/overlay.ts +9 -11
- package/src/backends/port/fs.ts +4 -4
- package/src/emulation/promises.ts +14 -15
- package/src/emulation/sync.ts +13 -14
- package/src/file.ts +16 -11
- package/src/mixins/mutexed.ts +194 -189
- package/src/mixins/shared.ts +3 -2
- package/src/stats.ts +4 -5
- package/src/utils.ts +3 -1
package/dist/mixins/shared.d.ts
CHANGED
package/dist/mixins/shared.js
CHANGED
package/dist/stats.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
import type * as Node from 'fs';
|
|
3
|
-
import type
|
|
3
|
+
import { type Credentials } from './credentials.js';
|
|
4
4
|
import { S_IFDIR, S_IFLNK, S_IFREG } from './emulation/constants.js';
|
|
5
5
|
/**
|
|
6
6
|
* Indicates the type of the given file. Applied to 'mode'.
|
|
@@ -146,11 +146,10 @@ export declare abstract class StatsCommon<T extends number | bigint> implements
|
|
|
146
146
|
/**
|
|
147
147
|
* Checks if a given user/group has access to this item
|
|
148
148
|
* @param mode The requested access, combination of W_OK, R_OK, and X_OK
|
|
149
|
-
* @param cred The requesting credentials
|
|
150
149
|
* @returns True if the request has access, false if the request does not
|
|
151
150
|
* @internal
|
|
152
151
|
*/
|
|
153
|
-
hasAccess(mode: number
|
|
152
|
+
hasAccess(mode: number): boolean;
|
|
154
153
|
/**
|
|
155
154
|
* Convert the current stats object into a credentials object
|
|
156
155
|
* @internal
|
package/dist/stats.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { credentials } from './credentials.js';
|
|
1
2
|
import { S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK, S_IRWXG, S_IRWXO, S_IRWXU } from './emulation/constants.js';
|
|
2
3
|
import { size_max } from './inode.js';
|
|
3
4
|
/**
|
|
@@ -115,17 +116,16 @@ export class StatsCommon {
|
|
|
115
116
|
/**
|
|
116
117
|
* Checks if a given user/group has access to this item
|
|
117
118
|
* @param mode The requested access, combination of W_OK, R_OK, and X_OK
|
|
118
|
-
* @param cred The requesting credentials
|
|
119
119
|
* @returns True if the request has access, false if the request does not
|
|
120
120
|
* @internal
|
|
121
121
|
*/
|
|
122
|
-
hasAccess(mode
|
|
123
|
-
if (
|
|
122
|
+
hasAccess(mode) {
|
|
123
|
+
if (credentials.euid === 0 || credentials.egid === 0) {
|
|
124
124
|
//Running as root
|
|
125
125
|
return true;
|
|
126
126
|
}
|
|
127
127
|
// Mask for
|
|
128
|
-
const adjusted = (
|
|
128
|
+
const adjusted = (credentials.uid == this.uid ? S_IRWXU : 0) | (credentials.gid == this.gid ? S_IRWXG : 0) | S_IRWXO;
|
|
129
129
|
return (mode & this.mode & adjusted) == mode;
|
|
130
130
|
}
|
|
131
131
|
/**
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
/// <reference types="node" resolution-mode="require"/>
|
|
3
3
|
import type * as fs from 'node:fs';
|
|
4
|
-
import type { OptionalTuple } from 'utilium';
|
|
4
|
+
import type { ClassLike, OptionalTuple } from 'utilium';
|
|
5
5
|
import { type AbsolutePath } from './emulation/path.js';
|
|
6
6
|
import { ErrnoError } from './error.js';
|
|
7
7
|
import type { FileSystem } from './filesystem.js';
|
|
@@ -81,3 +81,4 @@ export declare function normalizeOptions(options: fs.WriteFileOptions | (fs.Enco
|
|
|
81
81
|
flag: string;
|
|
82
82
|
mode: number;
|
|
83
83
|
};
|
|
84
|
+
export type Concrete<T extends ClassLike> = Pick<T, keyof T> & (new (...args: any[]) => InstanceType<T>);
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -17,7 +17,7 @@ ZenFS is modular and extensible. The core includes some built-in backends:
|
|
|
17
17
|
|
|
18
18
|
ZenFS supports a number of other backends. Many are provided as separate packages under `@zenfs`. More backends can be defined by separate libraries by extending the `FileSystem` class and providing a `Backend` object.
|
|
19
19
|
|
|
20
|
-
As an added bonus, all ZenFS backends support
|
|
20
|
+
As an added bonus, all ZenFS backends support synchronous operations. All of the backends included with the core are cross-platform.
|
|
21
21
|
|
|
22
22
|
For more information, see the [docs](https://zen-fs.github.io/core).
|
|
23
23
|
|
package/src/backends/overlay.ts
CHANGED
|
@@ -432,31 +432,29 @@ export class UnmutexedOverlayFS extends FileSystem {
|
|
|
432
432
|
* should they not exist. Use modes from the read-only storage.
|
|
433
433
|
*/
|
|
434
434
|
private createParentDirectoriesSync(path: string): void {
|
|
435
|
-
let parent = dirname(path)
|
|
436
|
-
|
|
435
|
+
let parent = dirname(path);
|
|
436
|
+
const toCreate: string[] = [];
|
|
437
437
|
while (!this.writable.existsSync(parent)) {
|
|
438
438
|
toCreate.push(parent);
|
|
439
439
|
parent = dirname(parent);
|
|
440
440
|
}
|
|
441
|
-
toCreate = toCreate.reverse();
|
|
442
441
|
|
|
443
|
-
for (const
|
|
444
|
-
this.writable.mkdirSync(
|
|
442
|
+
for (const path of toCreate.reverse()) {
|
|
443
|
+
this.writable.mkdirSync(path, this.statSync(path).mode);
|
|
445
444
|
}
|
|
446
445
|
}
|
|
447
446
|
|
|
448
447
|
private async createParentDirectories(path: string): Promise<void> {
|
|
449
|
-
let parent = dirname(path)
|
|
450
|
-
|
|
448
|
+
let parent = dirname(path);
|
|
449
|
+
const toCreate: string[] = [];
|
|
451
450
|
while (!(await this.writable.exists(parent))) {
|
|
452
451
|
toCreate.push(parent);
|
|
453
452
|
parent = dirname(parent);
|
|
454
453
|
}
|
|
455
|
-
toCreate = toCreate.reverse();
|
|
456
454
|
|
|
457
|
-
for (const
|
|
458
|
-
const stats = await this.stat(
|
|
459
|
-
await this.writable.mkdir(
|
|
455
|
+
for (const path of toCreate.reverse()) {
|
|
456
|
+
const stats = await this.stat(path);
|
|
457
|
+
await this.writable.mkdir(path, stats.mode);
|
|
460
458
|
}
|
|
461
459
|
}
|
|
462
460
|
|
package/src/backends/port/fs.ts
CHANGED
|
@@ -22,12 +22,12 @@ interface FileRequest<TMethod extends FileMethod = FileMethod> extends RPC.Reque
|
|
|
22
22
|
|
|
23
23
|
export class PortFile extends File {
|
|
24
24
|
constructor(
|
|
25
|
-
public
|
|
25
|
+
public fs: PortFS,
|
|
26
26
|
public readonly fd: number,
|
|
27
|
-
|
|
27
|
+
path: string,
|
|
28
28
|
public position: number
|
|
29
29
|
) {
|
|
30
|
-
super();
|
|
30
|
+
super(fs, path);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
public rpc<const T extends FileMethod>(method: T, ...args: Parameters<FileMethods[T]>): Promise<Awaited<ReturnType<FileMethods[T]>>> {
|
|
@@ -43,7 +43,7 @@ export class PortFile extends File {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
protected _throwNoSync(syscall: string): never {
|
|
46
|
-
throw new ErrnoError(Errno.ENOTSUP, '
|
|
46
|
+
throw new ErrnoError(Errno.ENOTSUP, 'Synchronous operations not supported on PortFile', this.path, syscall);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
public async stat(): Promise<Stats> {
|
|
@@ -18,7 +18,6 @@ import * as constants from './constants.js';
|
|
|
18
18
|
import { Dir, Dirent } from './dir.js';
|
|
19
19
|
import { dirname, join, parse } from './path.js';
|
|
20
20
|
import { _statfs, fd2file, fdMap, file2fd, fixError, mounts, resolveMount } from './shared.js';
|
|
21
|
-
import { credentials } from '../credentials.js';
|
|
22
21
|
import { ReadStream, WriteStream } from './streams.js';
|
|
23
22
|
import { FSWatcher, emitChange } from './watchers.js';
|
|
24
23
|
export * as constants from './constants.js';
|
|
@@ -220,7 +219,7 @@ export class FileHandle implements promises.FileHandle {
|
|
|
220
219
|
public async stat(opts?: fs.StatOptions & { bigint?: false }): Promise<Stats>;
|
|
221
220
|
public async stat(opts?: fs.StatOptions): Promise<Stats | BigIntStats> {
|
|
222
221
|
const stats = await this.file.stat();
|
|
223
|
-
if (!stats.hasAccess(constants.R_OK
|
|
222
|
+
if (!stats.hasAccess(constants.R_OK)) {
|
|
224
223
|
throw ErrnoError.With('EACCES', this.file.path, 'stat');
|
|
225
224
|
}
|
|
226
225
|
return opts?.bigint ? new BigIntStats(stats) : stats;
|
|
@@ -396,7 +395,7 @@ export async function rename(oldPath: fs.PathLike, newPath: fs.PathLike): Promis
|
|
|
396
395
|
newPath = normalizePath(newPath);
|
|
397
396
|
const src = resolveMount(oldPath);
|
|
398
397
|
const dst = resolveMount(newPath);
|
|
399
|
-
if (!(await stat(dirname(oldPath))).hasAccess(constants.W_OK
|
|
398
|
+
if (!(await stat(dirname(oldPath))).hasAccess(constants.W_OK)) {
|
|
400
399
|
throw ErrnoError.With('EACCES', oldPath, 'rename');
|
|
401
400
|
}
|
|
402
401
|
try {
|
|
@@ -444,7 +443,7 @@ export async function stat(path: fs.PathLike, options?: fs.StatOptions): Promise
|
|
|
444
443
|
const { fs, path: resolved } = resolveMount((await exists(path)) ? await realpath(path) : path);
|
|
445
444
|
try {
|
|
446
445
|
const stats = await fs.stat(resolved);
|
|
447
|
-
if (!stats.hasAccess(constants.R_OK
|
|
446
|
+
if (!stats.hasAccess(constants.R_OK)) {
|
|
448
447
|
throw ErrnoError.With('EACCES', path, 'stat');
|
|
449
448
|
}
|
|
450
449
|
return options?.bigint ? new BigIntStats(stats) : stats;
|
|
@@ -496,7 +495,7 @@ export async function unlink(path: fs.PathLike): Promise<void> {
|
|
|
496
495
|
path = normalizePath(path);
|
|
497
496
|
const { fs, path: resolved } = resolveMount(path);
|
|
498
497
|
try {
|
|
499
|
-
if (!(await fs.stat(resolved)).hasAccess(constants.W_OK
|
|
498
|
+
if (!(await fs.stat(resolved)).hasAccess(constants.W_OK)) {
|
|
500
499
|
throw ErrnoError.With('EACCES', resolved, 'unlink');
|
|
501
500
|
}
|
|
502
501
|
await fs.unlink(resolved);
|
|
@@ -527,7 +526,7 @@ async function _open(path: fs.PathLike, _flag: fs.OpenMode, _mode: fs.Mode = 0o6
|
|
|
527
526
|
}
|
|
528
527
|
// Create the file
|
|
529
528
|
const parentStats: Stats = await fs.stat(dirname(resolved));
|
|
530
|
-
if (!parentStats.hasAccess(constants.W_OK
|
|
529
|
+
if (!parentStats.hasAccess(constants.W_OK)) {
|
|
531
530
|
throw ErrnoError.With('EACCES', dirname(path), '_open');
|
|
532
531
|
}
|
|
533
532
|
if (!parentStats.isDirectory()) {
|
|
@@ -536,7 +535,7 @@ async function _open(path: fs.PathLike, _flag: fs.OpenMode, _mode: fs.Mode = 0o6
|
|
|
536
535
|
return new FileHandle(await fs.createFile(resolved, flag, mode));
|
|
537
536
|
}
|
|
538
537
|
|
|
539
|
-
if (!stats.hasAccess(flagToMode(flag)
|
|
538
|
+
if (!stats.hasAccess(flagToMode(flag))) {
|
|
540
539
|
throw ErrnoError.With('EACCES', path, '_open');
|
|
541
540
|
}
|
|
542
541
|
|
|
@@ -663,7 +662,7 @@ export async function rmdir(path: fs.PathLike): Promise<void> {
|
|
|
663
662
|
path = (await exists(path)) ? await realpath(path) : path;
|
|
664
663
|
const { fs, path: resolved } = resolveMount(path);
|
|
665
664
|
try {
|
|
666
|
-
if (!(await fs.stat(resolved)).hasAccess(constants.W_OK
|
|
665
|
+
if (!(await fs.stat(resolved)).hasAccess(constants.W_OK)) {
|
|
667
666
|
throw ErrnoError.With('EACCES', resolved, 'rmdir');
|
|
668
667
|
}
|
|
669
668
|
await fs.rmdir(resolved);
|
|
@@ -694,7 +693,7 @@ export async function mkdir(path: fs.PathLike, options?: fs.Mode | fs.MakeDirect
|
|
|
694
693
|
|
|
695
694
|
try {
|
|
696
695
|
if (!options?.recursive) {
|
|
697
|
-
if (!(await fs.stat(dirname(resolved))).hasAccess(constants.W_OK
|
|
696
|
+
if (!(await fs.stat(dirname(resolved))).hasAccess(constants.W_OK)) {
|
|
698
697
|
throw ErrnoError.With('EACCES', dirname(resolved), 'mkdir');
|
|
699
698
|
}
|
|
700
699
|
await fs.mkdir(resolved, mode);
|
|
@@ -708,7 +707,7 @@ export async function mkdir(path: fs.PathLike, options?: fs.Mode | fs.MakeDirect
|
|
|
708
707
|
errorPaths[dir] = origDir;
|
|
709
708
|
}
|
|
710
709
|
for (const dir of dirs) {
|
|
711
|
-
if (!(await fs.stat(dirname(dir))).hasAccess(constants.W_OK
|
|
710
|
+
if (!(await fs.stat(dirname(dir))).hasAccess(constants.W_OK)) {
|
|
712
711
|
throw ErrnoError.With('EACCES', dirname(dir), 'mkdir');
|
|
713
712
|
}
|
|
714
713
|
await fs.mkdir(dir, mode);
|
|
@@ -738,7 +737,7 @@ export async function readdir(
|
|
|
738
737
|
options?: { withFileTypes?: boolean; recursive?: boolean; encoding?: BufferEncoding | 'buffer' | null } | BufferEncoding | 'buffer' | null
|
|
739
738
|
): Promise<string[] | Dirent[] | Buffer[]> {
|
|
740
739
|
path = normalizePath(path);
|
|
741
|
-
if (!(await stat(path)).hasAccess(constants.R_OK
|
|
740
|
+
if (!(await stat(path)).hasAccess(constants.R_OK)) {
|
|
742
741
|
throw ErrnoError.With('EACCES', path, 'readdir');
|
|
743
742
|
}
|
|
744
743
|
path = (await exists(path)) ? await realpath(path) : path;
|
|
@@ -776,11 +775,11 @@ readdir satisfies typeof promises.readdir;
|
|
|
776
775
|
*/
|
|
777
776
|
export async function link(targetPath: fs.PathLike, linkPath: fs.PathLike): Promise<void> {
|
|
778
777
|
targetPath = normalizePath(targetPath);
|
|
779
|
-
if (!(await stat(dirname(targetPath))).hasAccess(constants.R_OK
|
|
778
|
+
if (!(await stat(dirname(targetPath))).hasAccess(constants.R_OK)) {
|
|
780
779
|
throw ErrnoError.With('EACCES', dirname(targetPath), 'link');
|
|
781
780
|
}
|
|
782
781
|
linkPath = normalizePath(linkPath);
|
|
783
|
-
if (!(await stat(dirname(linkPath))).hasAccess(constants.W_OK
|
|
782
|
+
if (!(await stat(dirname(linkPath))).hasAccess(constants.W_OK)) {
|
|
784
783
|
throw ErrnoError.With('EACCES', dirname(linkPath), 'link');
|
|
785
784
|
}
|
|
786
785
|
|
|
@@ -790,7 +789,7 @@ export async function link(targetPath: fs.PathLike, linkPath: fs.PathLike): Prom
|
|
|
790
789
|
throw ErrnoError.With('EXDEV', linkPath, 'link');
|
|
791
790
|
}
|
|
792
791
|
try {
|
|
793
|
-
if (!(await fs.stat(path)).hasAccess(constants.W_OK
|
|
792
|
+
if (!(await fs.stat(path)).hasAccess(constants.W_OK)) {
|
|
794
793
|
throw ErrnoError.With('EACCES', path, 'link');
|
|
795
794
|
}
|
|
796
795
|
return await fs.link(path, link.path);
|
|
@@ -969,7 +968,7 @@ watch satisfies typeof promises.watch;
|
|
|
969
968
|
*/
|
|
970
969
|
export async function access(path: fs.PathLike, mode: number = constants.F_OK): Promise<void> {
|
|
971
970
|
const stats = await stat(path);
|
|
972
|
-
if (!stats.hasAccess(mode
|
|
971
|
+
if (!stats.hasAccess(mode)) {
|
|
973
972
|
throw new ErrnoError(Errno.EACCES);
|
|
974
973
|
}
|
|
975
974
|
}
|
package/src/emulation/sync.ts
CHANGED
|
@@ -10,7 +10,6 @@ import * as constants from './constants.js';
|
|
|
10
10
|
import { Dir, Dirent } from './dir.js';
|
|
11
11
|
import { dirname, join, parse } from './path.js';
|
|
12
12
|
import { _statfs, fd2file, fdMap, file2fd, fixError, mounts, resolveMount } from './shared.js';
|
|
13
|
-
import { credentials } from '../credentials.js';
|
|
14
13
|
import { emitChange } from './watchers.js';
|
|
15
14
|
|
|
16
15
|
/**
|
|
@@ -23,7 +22,7 @@ export function renameSync(oldPath: fs.PathLike, newPath: fs.PathLike): void {
|
|
|
23
22
|
newPath = normalizePath(newPath);
|
|
24
23
|
const oldMount = resolveMount(oldPath);
|
|
25
24
|
const newMount = resolveMount(newPath);
|
|
26
|
-
if (!statSync(dirname(oldPath)).hasAccess(constants.W_OK
|
|
25
|
+
if (!statSync(dirname(oldPath)).hasAccess(constants.W_OK)) {
|
|
27
26
|
throw ErrnoError.With('EACCES', oldPath, 'rename');
|
|
28
27
|
}
|
|
29
28
|
try {
|
|
@@ -73,7 +72,7 @@ export function statSync(path: fs.PathLike, options?: fs.StatOptions): Stats | B
|
|
|
73
72
|
const { fs, path: resolved } = resolveMount(existsSync(path) ? realpathSync(path) : path);
|
|
74
73
|
try {
|
|
75
74
|
const stats = fs.statSync(resolved);
|
|
76
|
-
if (!stats.hasAccess(constants.R_OK
|
|
75
|
+
if (!stats.hasAccess(constants.R_OK)) {
|
|
77
76
|
throw ErrnoError.With('EACCES', path, 'stat');
|
|
78
77
|
}
|
|
79
78
|
return options?.bigint ? new BigIntStats(stats) : stats;
|
|
@@ -126,7 +125,7 @@ export function unlinkSync(path: fs.PathLike): void {
|
|
|
126
125
|
path = normalizePath(path);
|
|
127
126
|
const { fs, path: resolved } = resolveMount(path);
|
|
128
127
|
try {
|
|
129
|
-
if (!fs.statSync(resolved).hasAccess(constants.W_OK
|
|
128
|
+
if (!fs.statSync(resolved).hasAccess(constants.W_OK)) {
|
|
130
129
|
throw ErrnoError.With('EACCES', resolved, 'unlink');
|
|
131
130
|
}
|
|
132
131
|
fs.unlinkSync(resolved);
|
|
@@ -151,7 +150,7 @@ function _openSync(path: fs.PathLike, _flag: fs.OpenMode, _mode?: fs.Mode | null
|
|
|
151
150
|
}
|
|
152
151
|
// Create the file
|
|
153
152
|
const parentStats: Stats = fs.statSync(dirname(resolved));
|
|
154
|
-
if (!parentStats.hasAccess(constants.W_OK
|
|
153
|
+
if (!parentStats.hasAccess(constants.W_OK)) {
|
|
155
154
|
throw ErrnoError.With('EACCES', dirname(path), '_open');
|
|
156
155
|
}
|
|
157
156
|
if (!parentStats.isDirectory()) {
|
|
@@ -162,7 +161,7 @@ function _openSync(path: fs.PathLike, _flag: fs.OpenMode, _mode?: fs.Mode | null
|
|
|
162
161
|
|
|
163
162
|
const stats: Stats = fs.statSync(resolved);
|
|
164
163
|
|
|
165
|
-
if (!stats.hasAccess(mode
|
|
164
|
+
if (!stats.hasAccess(mode) || !stats.hasAccess(flagToMode(flag))) {
|
|
166
165
|
throw ErrnoError.With('EACCES', path, '_open');
|
|
167
166
|
}
|
|
168
167
|
|
|
@@ -466,7 +465,7 @@ export function rmdirSync(path: fs.PathLike): void {
|
|
|
466
465
|
path = normalizePath(path);
|
|
467
466
|
const { fs, path: resolved } = resolveMount(existsSync(path) ? realpathSync(path) : path);
|
|
468
467
|
try {
|
|
469
|
-
if (!fs.statSync(resolved).hasAccess(constants.W_OK
|
|
468
|
+
if (!fs.statSync(resolved).hasAccess(constants.W_OK)) {
|
|
470
469
|
throw ErrnoError.With('EACCES', resolved, 'rmdir');
|
|
471
470
|
}
|
|
472
471
|
fs.rmdirSync(resolved);
|
|
@@ -496,7 +495,7 @@ export function mkdirSync(path: fs.PathLike, options?: fs.Mode | fs.MakeDirector
|
|
|
496
495
|
|
|
497
496
|
try {
|
|
498
497
|
if (!options?.recursive) {
|
|
499
|
-
if (!fs.statSync(dirname(resolved)).hasAccess(constants.W_OK
|
|
498
|
+
if (!fs.statSync(dirname(resolved)).hasAccess(constants.W_OK)) {
|
|
500
499
|
throw ErrnoError.With('EACCES', dirname(resolved), 'mkdir');
|
|
501
500
|
}
|
|
502
501
|
return fs.mkdirSync(resolved, mode);
|
|
@@ -508,7 +507,7 @@ export function mkdirSync(path: fs.PathLike, options?: fs.Mode | fs.MakeDirector
|
|
|
508
507
|
errorPaths[dir] = original;
|
|
509
508
|
}
|
|
510
509
|
for (const dir of dirs) {
|
|
511
|
-
if (!fs.statSync(dirname(dir)).hasAccess(constants.W_OK
|
|
510
|
+
if (!fs.statSync(dirname(dir)).hasAccess(constants.W_OK)) {
|
|
512
511
|
throw ErrnoError.With('EACCES', dirname(dir), 'mkdir');
|
|
513
512
|
}
|
|
514
513
|
fs.mkdirSync(dir, mode);
|
|
@@ -536,7 +535,7 @@ export function readdirSync(
|
|
|
536
535
|
path = normalizePath(path);
|
|
537
536
|
const { fs, path: resolved } = resolveMount(existsSync(path) ? realpathSync(path) : path);
|
|
538
537
|
let entries: string[];
|
|
539
|
-
if (!statSync(path).hasAccess(constants.R_OK
|
|
538
|
+
if (!statSync(path).hasAccess(constants.R_OK)) {
|
|
540
539
|
throw ErrnoError.With('EACCES', path, 'readdir');
|
|
541
540
|
}
|
|
542
541
|
try {
|
|
@@ -578,11 +577,11 @@ readdirSync satisfies typeof fs.readdirSync;
|
|
|
578
577
|
*/
|
|
579
578
|
export function linkSync(targetPath: fs.PathLike, linkPath: fs.PathLike): void {
|
|
580
579
|
targetPath = normalizePath(targetPath);
|
|
581
|
-
if (!statSync(dirname(targetPath)).hasAccess(constants.R_OK
|
|
580
|
+
if (!statSync(dirname(targetPath)).hasAccess(constants.R_OK)) {
|
|
582
581
|
throw ErrnoError.With('EACCES', dirname(targetPath), 'link');
|
|
583
582
|
}
|
|
584
583
|
linkPath = normalizePath(linkPath);
|
|
585
|
-
if (!statSync(dirname(linkPath)).hasAccess(constants.W_OK
|
|
584
|
+
if (!statSync(dirname(linkPath)).hasAccess(constants.W_OK)) {
|
|
586
585
|
throw ErrnoError.With('EACCES', dirname(linkPath), 'link');
|
|
587
586
|
}
|
|
588
587
|
|
|
@@ -592,7 +591,7 @@ export function linkSync(targetPath: fs.PathLike, linkPath: fs.PathLike): void {
|
|
|
592
591
|
throw ErrnoError.With('EXDEV', linkPath, 'link');
|
|
593
592
|
}
|
|
594
593
|
try {
|
|
595
|
-
if (!fs.statSync(path).hasAccess(constants.W_OK
|
|
594
|
+
if (!fs.statSync(path).hasAccess(constants.W_OK)) {
|
|
596
595
|
throw ErrnoError.With('EACCES', path, 'link');
|
|
597
596
|
}
|
|
598
597
|
return fs.linkSync(path, linkPath);
|
|
@@ -753,7 +752,7 @@ realpathSync satisfies Omit<typeof fs.realpathSync, 'native'>;
|
|
|
753
752
|
*/
|
|
754
753
|
export function accessSync(path: fs.PathLike, mode: number = 0o600): void {
|
|
755
754
|
const stats = statSync(path);
|
|
756
|
-
if (!stats.hasAccess(mode
|
|
755
|
+
if (!stats.hasAccess(mode)) {
|
|
757
756
|
throw new ErrnoError(Errno.EACCES);
|
|
758
757
|
}
|
|
759
758
|
}
|
package/src/file.ts
CHANGED
|
@@ -146,16 +146,23 @@ export function isExclusive(flag: string): boolean {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
export abstract class File {
|
|
149
|
+
constructor(
|
|
150
|
+
/**
|
|
151
|
+
* @internal
|
|
152
|
+
* The file system that created the file
|
|
153
|
+
*/
|
|
154
|
+
public fs: FileSystem,
|
|
155
|
+
/**
|
|
156
|
+
* The path to the file
|
|
157
|
+
*/
|
|
158
|
+
public readonly path: string
|
|
159
|
+
) {}
|
|
160
|
+
|
|
149
161
|
/**
|
|
150
162
|
* Get the current file position.
|
|
151
163
|
*/
|
|
152
164
|
public abstract position: number;
|
|
153
165
|
|
|
154
|
-
/**
|
|
155
|
-
* The path to the file
|
|
156
|
-
*/
|
|
157
|
-
public abstract readonly path: string;
|
|
158
|
-
|
|
159
166
|
/**
|
|
160
167
|
* Asynchronous `stat`.
|
|
161
168
|
*/
|
|
@@ -355,17 +362,15 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
355
362
|
constructor(
|
|
356
363
|
/**
|
|
357
364
|
* The file system that created the file.
|
|
365
|
+
* @internal
|
|
358
366
|
*/
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
* Path to the file
|
|
362
|
-
*/
|
|
363
|
-
public readonly path: string,
|
|
367
|
+
public fs: FS,
|
|
368
|
+
path: string,
|
|
364
369
|
public readonly flag: string,
|
|
365
370
|
public readonly stats: Stats,
|
|
366
371
|
protected _buffer: Uint8Array = new Uint8Array(new ArrayBuffer(0, fs.metadata().noResizableBuffers ? {} : { maxByteLength: size_max }))
|
|
367
372
|
) {
|
|
368
|
-
super();
|
|
373
|
+
super(fs, path);
|
|
369
374
|
|
|
370
375
|
/*
|
|
371
376
|
Note:
|