@zenfs/core 0.9.7 → 0.10.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/AsyncStore.js +29 -29
- package/dist/backends/Fetch.d.ts +84 -0
- package/dist/backends/Fetch.js +171 -0
- package/dist/backends/Index.js +19 -19
- package/dist/backends/Locked.d.ts +11 -11
- package/dist/backends/Locked.js +50 -49
- package/dist/backends/Overlay.js +21 -21
- package/dist/backends/SyncStore.js +27 -27
- package/dist/backends/backend.js +4 -4
- package/dist/backends/port/fs.d.ts +124 -0
- package/dist/backends/port/fs.js +241 -0
- package/dist/backends/port/rpc.d.ts +60 -0
- package/dist/backends/port/rpc.js +71 -0
- package/dist/backends/port/store.d.ts +30 -0
- package/dist/backends/port/store.js +142 -0
- package/dist/browser.min.js +4 -4
- package/dist/browser.min.js.map +4 -4
- package/dist/config.d.ts +8 -10
- package/dist/config.js +11 -11
- package/dist/emulation/async.js +6 -6
- package/dist/emulation/dir.js +2 -2
- package/dist/emulation/index.d.ts +1 -1
- package/dist/emulation/index.js +1 -1
- package/dist/emulation/path.d.ts +3 -2
- package/dist/emulation/path.js +19 -45
- package/dist/emulation/promises.d.ts +7 -12
- package/dist/emulation/promises.js +144 -146
- package/dist/emulation/shared.d.ts +5 -10
- package/dist/emulation/shared.js +8 -8
- package/dist/emulation/streams.js +3 -3
- package/dist/emulation/sync.js +25 -25
- package/dist/{ApiError.d.ts → error.d.ts} +13 -14
- package/dist/error.js +292 -0
- package/dist/file.d.ts +2 -0
- package/dist/file.js +10 -4
- package/dist/filesystem.js +15 -15
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -1
- package/dist/mutex.js +2 -1
- package/dist/utils.d.ts +8 -7
- package/dist/utils.js +11 -12
- package/package.json +3 -3
- package/readme.md +17 -9
- package/src/backends/AsyncStore.ts +29 -29
- package/src/backends/Fetch.ts +230 -0
- package/src/backends/Index.ts +19 -19
- package/src/backends/Locked.ts +50 -49
- package/src/backends/Overlay.ts +23 -23
- package/src/backends/SyncStore.ts +27 -27
- package/src/backends/backend.ts +6 -6
- package/src/backends/port/fs.ts +308 -0
- package/src/backends/port/readme.md +59 -0
- package/src/backends/port/rpc.ts +144 -0
- package/src/backends/port/store.ts +187 -0
- package/src/config.ts +20 -24
- package/src/emulation/async.ts +6 -6
- package/src/emulation/dir.ts +2 -2
- package/src/emulation/index.ts +1 -1
- package/src/emulation/path.ts +25 -49
- package/src/emulation/promises.ts +150 -159
- package/src/emulation/shared.ts +12 -14
- package/src/emulation/streams.ts +3 -3
- package/src/emulation/sync.ts +28 -28
- package/src/{ApiError.ts → error.ts} +89 -89
- package/src/file.ts +12 -4
- package/src/filesystem.ts +15 -15
- package/src/index.ts +4 -1
- package/src/mutex.ts +3 -1
- package/src/utils.ts +16 -18
- package/tsconfig.json +2 -2
- package/dist/ApiError.js +0 -292
package/dist/backends/Locked.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ErrnoError } from '../error.js';
|
|
1
2
|
import { Mutex } from '../mutex.js';
|
|
2
3
|
/**
|
|
3
4
|
* This class serializes access to an underlying async filesystem.
|
|
@@ -31,21 +32,21 @@ export class LockedFS {
|
|
|
31
32
|
}
|
|
32
33
|
renameSync(oldPath, newPath, cred) {
|
|
33
34
|
if (this._mu.isLocked(oldPath)) {
|
|
34
|
-
throw
|
|
35
|
+
throw ErrnoError.With('EBUSY', oldPath, 'rename');
|
|
35
36
|
}
|
|
36
37
|
return this.fs.renameSync(oldPath, newPath, cred);
|
|
37
38
|
}
|
|
38
|
-
async stat(
|
|
39
|
-
await this._mu.lock(
|
|
40
|
-
const stats = await this.fs.stat(
|
|
41
|
-
this._mu.unlock(
|
|
39
|
+
async stat(path, cred) {
|
|
40
|
+
await this._mu.lock(path);
|
|
41
|
+
const stats = await this.fs.stat(path, cred);
|
|
42
|
+
this._mu.unlock(path);
|
|
42
43
|
return stats;
|
|
43
44
|
}
|
|
44
|
-
statSync(
|
|
45
|
-
if (this._mu.isLocked(
|
|
46
|
-
throw
|
|
45
|
+
statSync(path, cred) {
|
|
46
|
+
if (this._mu.isLocked(path)) {
|
|
47
|
+
throw ErrnoError.With('EBUSY', path, 'stat');
|
|
47
48
|
}
|
|
48
|
-
return this.fs.statSync(
|
|
49
|
+
return this.fs.statSync(path, cred);
|
|
49
50
|
}
|
|
50
51
|
async openFile(path, flag, cred) {
|
|
51
52
|
await this._mu.lock(path);
|
|
@@ -55,7 +56,7 @@ export class LockedFS {
|
|
|
55
56
|
}
|
|
56
57
|
openFileSync(path, flag, cred) {
|
|
57
58
|
if (this._mu.isLocked(path)) {
|
|
58
|
-
throw
|
|
59
|
+
throw ErrnoError.With('EBUSY', path, 'openFile');
|
|
59
60
|
}
|
|
60
61
|
return this.fs.openFileSync(path, flag, cred);
|
|
61
62
|
}
|
|
@@ -67,7 +68,7 @@ export class LockedFS {
|
|
|
67
68
|
}
|
|
68
69
|
createFileSync(path, flag, mode, cred) {
|
|
69
70
|
if (this._mu.isLocked(path)) {
|
|
70
|
-
throw
|
|
71
|
+
throw ErrnoError.With('EBUSY', path, 'createFile');
|
|
71
72
|
}
|
|
72
73
|
return this.fs.createFileSync(path, flag, mode, cred);
|
|
73
74
|
}
|
|
@@ -76,57 +77,57 @@ export class LockedFS {
|
|
|
76
77
|
await this.fs.unlink(p, cred);
|
|
77
78
|
this._mu.unlock(p);
|
|
78
79
|
}
|
|
79
|
-
unlinkSync(
|
|
80
|
-
if (this._mu.isLocked(
|
|
81
|
-
throw
|
|
80
|
+
unlinkSync(path, cred) {
|
|
81
|
+
if (this._mu.isLocked(path)) {
|
|
82
|
+
throw ErrnoError.With('EBUSY', path, 'unlink');
|
|
82
83
|
}
|
|
83
|
-
return this.fs.unlinkSync(
|
|
84
|
+
return this.fs.unlinkSync(path, cred);
|
|
84
85
|
}
|
|
85
|
-
async rmdir(
|
|
86
|
-
await this._mu.lock(
|
|
87
|
-
await this.fs.rmdir(
|
|
88
|
-
this._mu.unlock(
|
|
86
|
+
async rmdir(path, cred) {
|
|
87
|
+
await this._mu.lock(path);
|
|
88
|
+
await this.fs.rmdir(path, cred);
|
|
89
|
+
this._mu.unlock(path);
|
|
89
90
|
}
|
|
90
|
-
rmdirSync(
|
|
91
|
-
if (this._mu.isLocked(
|
|
92
|
-
throw
|
|
91
|
+
rmdirSync(path, cred) {
|
|
92
|
+
if (this._mu.isLocked(path)) {
|
|
93
|
+
throw ErrnoError.With('EBUSY', path, 'rmdir');
|
|
93
94
|
}
|
|
94
|
-
return this.fs.rmdirSync(
|
|
95
|
+
return this.fs.rmdirSync(path, cred);
|
|
95
96
|
}
|
|
96
|
-
async mkdir(
|
|
97
|
-
await this._mu.lock(
|
|
98
|
-
await this.fs.mkdir(
|
|
99
|
-
this._mu.unlock(
|
|
97
|
+
async mkdir(path, mode, cred) {
|
|
98
|
+
await this._mu.lock(path);
|
|
99
|
+
await this.fs.mkdir(path, mode, cred);
|
|
100
|
+
this._mu.unlock(path);
|
|
100
101
|
}
|
|
101
|
-
mkdirSync(
|
|
102
|
-
if (this._mu.isLocked(
|
|
103
|
-
throw
|
|
102
|
+
mkdirSync(path, mode, cred) {
|
|
103
|
+
if (this._mu.isLocked(path)) {
|
|
104
|
+
throw ErrnoError.With('EBUSY', path, 'mkdir');
|
|
104
105
|
}
|
|
105
|
-
return this.fs.mkdirSync(
|
|
106
|
+
return this.fs.mkdirSync(path, mode, cred);
|
|
106
107
|
}
|
|
107
|
-
async readdir(
|
|
108
|
-
await this._mu.lock(
|
|
109
|
-
const files = await this.fs.readdir(
|
|
110
|
-
this._mu.unlock(
|
|
108
|
+
async readdir(path, cred) {
|
|
109
|
+
await this._mu.lock(path);
|
|
110
|
+
const files = await this.fs.readdir(path, cred);
|
|
111
|
+
this._mu.unlock(path);
|
|
111
112
|
return files;
|
|
112
113
|
}
|
|
113
|
-
readdirSync(
|
|
114
|
-
if (this._mu.isLocked(
|
|
115
|
-
throw
|
|
114
|
+
readdirSync(path, cred) {
|
|
115
|
+
if (this._mu.isLocked(path)) {
|
|
116
|
+
throw ErrnoError.With('EBUSY', path, 'readdir');
|
|
116
117
|
}
|
|
117
|
-
return this.fs.readdirSync(
|
|
118
|
+
return this.fs.readdirSync(path, cred);
|
|
118
119
|
}
|
|
119
|
-
async exists(
|
|
120
|
-
await this._mu.lock(
|
|
121
|
-
const exists = await this.fs.exists(
|
|
122
|
-
this._mu.unlock(
|
|
120
|
+
async exists(path, cred) {
|
|
121
|
+
await this._mu.lock(path);
|
|
122
|
+
const exists = await this.fs.exists(path, cred);
|
|
123
|
+
this._mu.unlock(path);
|
|
123
124
|
return exists;
|
|
124
125
|
}
|
|
125
|
-
existsSync(
|
|
126
|
-
if (this._mu.isLocked(
|
|
127
|
-
throw
|
|
126
|
+
existsSync(path, cred) {
|
|
127
|
+
if (this._mu.isLocked(path)) {
|
|
128
|
+
throw ErrnoError.With('EBUSY', path, 'exists');
|
|
128
129
|
}
|
|
129
|
-
return this.fs.existsSync(
|
|
130
|
+
return this.fs.existsSync(path, cred);
|
|
130
131
|
}
|
|
131
132
|
async link(srcpath, dstpath, cred) {
|
|
132
133
|
await this._mu.lock(srcpath);
|
|
@@ -135,7 +136,7 @@ export class LockedFS {
|
|
|
135
136
|
}
|
|
136
137
|
linkSync(srcpath, dstpath, cred) {
|
|
137
138
|
if (this._mu.isLocked(srcpath)) {
|
|
138
|
-
throw
|
|
139
|
+
throw ErrnoError.With('EBUSY', srcpath, 'link');
|
|
139
140
|
}
|
|
140
141
|
return this.fs.linkSync(srcpath, dstpath, cred);
|
|
141
142
|
}
|
|
@@ -146,7 +147,7 @@ export class LockedFS {
|
|
|
146
147
|
}
|
|
147
148
|
syncSync(path, data, stats) {
|
|
148
149
|
if (this._mu.isLocked(path)) {
|
|
149
|
-
throw
|
|
150
|
+
throw ErrnoError.With('EBUSY', path, 'sync');
|
|
150
151
|
}
|
|
151
152
|
return this.fs.syncSync(path, data, stats);
|
|
152
153
|
}
|
package/dist/backends/Overlay.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FileSystem } from '../filesystem.js';
|
|
2
|
-
import {
|
|
2
|
+
import { ErrnoError, Errno } from '../error.js';
|
|
3
3
|
import { PreloadFile, parseFlag } from '../file.js';
|
|
4
4
|
import { Stats } from '../stats.js';
|
|
5
5
|
import { LockedFS } from './Locked.js';
|
|
@@ -38,7 +38,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
38
38
|
this._writable = writable;
|
|
39
39
|
this._readable = readable;
|
|
40
40
|
if (this._writable.metadata().readonly) {
|
|
41
|
-
throw new
|
|
41
|
+
throw new ErrnoError(Errno.EINVAL, 'Writable file system must be writable.');
|
|
42
42
|
}
|
|
43
43
|
this._ready = this._initialize();
|
|
44
44
|
}
|
|
@@ -80,7 +80,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
80
80
|
this._deleteLog = decode(buffer);
|
|
81
81
|
}
|
|
82
82
|
catch (err) {
|
|
83
|
-
if (err.errno !==
|
|
83
|
+
if (err.errno !== Errno.ENOENT) {
|
|
84
84
|
throw err;
|
|
85
85
|
}
|
|
86
86
|
}
|
|
@@ -104,7 +104,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
104
104
|
}
|
|
105
105
|
catch (e) {
|
|
106
106
|
if (this._deletedFiles.has(oldPath)) {
|
|
107
|
-
throw
|
|
107
|
+
throw ErrnoError.With('ENOENT', oldPath, 'rename');
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
}
|
|
@@ -117,7 +117,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
117
117
|
}
|
|
118
118
|
catch (e) {
|
|
119
119
|
if (this._deletedFiles.has(oldPath)) {
|
|
120
|
-
throw
|
|
120
|
+
throw ErrnoError.With('ENOENT', oldPath, 'rename');
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
}
|
|
@@ -128,7 +128,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
128
128
|
}
|
|
129
129
|
catch (e) {
|
|
130
130
|
if (this._deletedFiles.has(p)) {
|
|
131
|
-
throw
|
|
131
|
+
throw ErrnoError.With('ENOENT', p, 'stat');
|
|
132
132
|
}
|
|
133
133
|
const oldStat = new Stats(await this._readable.stat(p, cred));
|
|
134
134
|
// Make the oldStat's mode writable. Preserve the topmost part of the mode, which specifies the type
|
|
@@ -143,7 +143,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
143
143
|
}
|
|
144
144
|
catch (e) {
|
|
145
145
|
if (this._deletedFiles.has(p)) {
|
|
146
|
-
throw
|
|
146
|
+
throw ErrnoError.With('ENOENT', p, 'stat');
|
|
147
147
|
}
|
|
148
148
|
const oldStat = new Stats(this._readable.statSync(p, cred));
|
|
149
149
|
// Make the oldStat's mode writable. Preserve the topmost part of the mode, which specifies the type.
|
|
@@ -194,7 +194,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
194
194
|
this.checkInitialized();
|
|
195
195
|
this.checkPath(p);
|
|
196
196
|
if (!(await this.exists(p, cred))) {
|
|
197
|
-
throw
|
|
197
|
+
throw ErrnoError.With('ENOENT', p, 'unlink');
|
|
198
198
|
}
|
|
199
199
|
if (await this._writable.exists(p, cred)) {
|
|
200
200
|
await this._writable.unlink(p, cred);
|
|
@@ -208,7 +208,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
208
208
|
this.checkInitialized();
|
|
209
209
|
this.checkPath(p);
|
|
210
210
|
if (!this.existsSync(p, cred)) {
|
|
211
|
-
throw
|
|
211
|
+
throw ErrnoError.With('ENOENT', p, 'unlink');
|
|
212
212
|
}
|
|
213
213
|
if (this._writable.existsSync(p, cred)) {
|
|
214
214
|
this._writable.unlinkSync(p, cred);
|
|
@@ -221,7 +221,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
221
221
|
async rmdir(p, cred) {
|
|
222
222
|
this.checkInitialized();
|
|
223
223
|
if (!(await this.exists(p, cred))) {
|
|
224
|
-
throw
|
|
224
|
+
throw ErrnoError.With('ENOENT', p, 'rmdir');
|
|
225
225
|
}
|
|
226
226
|
if (await this._writable.exists(p, cred)) {
|
|
227
227
|
await this._writable.rmdir(p, cred);
|
|
@@ -229,7 +229,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
229
229
|
if (await this.exists(p, cred)) {
|
|
230
230
|
// Check if directory is empty.
|
|
231
231
|
if ((await this.readdir(p, cred)).length > 0) {
|
|
232
|
-
throw
|
|
232
|
+
throw ErrnoError.With('ENOTEMPTY', p, 'rmdir');
|
|
233
233
|
}
|
|
234
234
|
else {
|
|
235
235
|
this.deletePath(p, cred);
|
|
@@ -239,7 +239,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
239
239
|
rmdirSync(p, cred) {
|
|
240
240
|
this.checkInitialized();
|
|
241
241
|
if (!this.existsSync(p, cred)) {
|
|
242
|
-
throw
|
|
242
|
+
throw ErrnoError.With('ENOENT', p, 'rmdir');
|
|
243
243
|
}
|
|
244
244
|
if (this._writable.existsSync(p, cred)) {
|
|
245
245
|
this._writable.rmdirSync(p, cred);
|
|
@@ -247,7 +247,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
247
247
|
if (this.existsSync(p, cred)) {
|
|
248
248
|
// Check if directory is empty.
|
|
249
249
|
if (this.readdirSync(p, cred).length > 0) {
|
|
250
|
-
throw
|
|
250
|
+
throw ErrnoError.With('ENOTEMPTY', p, 'rmdir');
|
|
251
251
|
}
|
|
252
252
|
else {
|
|
253
253
|
this.deletePath(p, cred);
|
|
@@ -257,7 +257,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
257
257
|
async mkdir(p, mode, cred) {
|
|
258
258
|
this.checkInitialized();
|
|
259
259
|
if (await this.exists(p, cred)) {
|
|
260
|
-
throw
|
|
260
|
+
throw ErrnoError.With('EEXIST', p, 'mkdir');
|
|
261
261
|
}
|
|
262
262
|
// The below will throw should any of the parent directories fail to exist on _writable.
|
|
263
263
|
await this.createParentDirectories(p, cred);
|
|
@@ -266,7 +266,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
266
266
|
mkdirSync(p, mode, cred) {
|
|
267
267
|
this.checkInitialized();
|
|
268
268
|
if (this.existsSync(p, cred)) {
|
|
269
|
-
throw
|
|
269
|
+
throw ErrnoError.With('EEXIST', p, 'mkdir');
|
|
270
270
|
}
|
|
271
271
|
// The below will throw should any of the parent directories fail to exist on _writable.
|
|
272
272
|
this.createParentDirectoriesSync(p, cred);
|
|
@@ -276,7 +276,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
276
276
|
this.checkInitialized();
|
|
277
277
|
const dirStats = await this.stat(p, cred);
|
|
278
278
|
if (!dirStats.isDirectory()) {
|
|
279
|
-
throw
|
|
279
|
+
throw ErrnoError.With('ENOTDIR', p, 'readdir');
|
|
280
280
|
}
|
|
281
281
|
// Readdir in both, check delete log on RO file system's listing, merge, return.
|
|
282
282
|
const contents = [];
|
|
@@ -303,7 +303,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
303
303
|
this.checkInitialized();
|
|
304
304
|
const dirStats = this.statSync(p, cred);
|
|
305
305
|
if (!dirStats.isDirectory()) {
|
|
306
|
-
throw
|
|
306
|
+
throw ErrnoError.With('ENOTDIR', p, 'readdir');
|
|
307
307
|
}
|
|
308
308
|
// Readdir in both, check delete log on RO file system's listing, merge, return.
|
|
309
309
|
let contents = [];
|
|
@@ -364,7 +364,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
364
364
|
}
|
|
365
365
|
checkInitialized() {
|
|
366
366
|
if (!this._isInitialized) {
|
|
367
|
-
throw new
|
|
367
|
+
throw new ErrnoError(Errno.EPERM, 'OverlayFS is not initialized. Please initialize OverlayFS using its initialize() method before using it.');
|
|
368
368
|
}
|
|
369
369
|
if (!this._deleteLogError) {
|
|
370
370
|
return;
|
|
@@ -375,7 +375,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
375
375
|
}
|
|
376
376
|
checkPath(path) {
|
|
377
377
|
if (path == deletionLogPath) {
|
|
378
|
-
throw
|
|
378
|
+
throw ErrnoError.With('EPERM', path, 'checkPath');
|
|
379
379
|
}
|
|
380
380
|
}
|
|
381
381
|
/**
|
|
@@ -412,7 +412,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
412
412
|
*/
|
|
413
413
|
operateOnWritable(p, cred) {
|
|
414
414
|
if (!this.existsSync(p, cred)) {
|
|
415
|
-
throw
|
|
415
|
+
throw ErrnoError.With('ENOENT', p, 'operateOnWriteable');
|
|
416
416
|
}
|
|
417
417
|
if (!this._writable.existsSync(p, cred)) {
|
|
418
418
|
// File is on readable storage. Copy to writable storage before
|
|
@@ -422,7 +422,7 @@ export class UnlockedOverlayFS extends FileSystem {
|
|
|
422
422
|
}
|
|
423
423
|
async operateOnWritableAsync(p, cred) {
|
|
424
424
|
if (!(await this.exists(p, cred))) {
|
|
425
|
-
throw
|
|
425
|
+
throw ErrnoError.With('ENOENT', p, 'operateOnWritable');
|
|
426
426
|
}
|
|
427
427
|
if (!(await this._writable.exists(p, cred))) {
|
|
428
428
|
return this.copyToWritable(p, cred);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { dirname, basename, join, resolve, sep } from '../emulation/path.js';
|
|
2
|
-
import {
|
|
2
|
+
import { ErrnoError, Errno } from '../error.js';
|
|
3
3
|
import { W_OK, R_OK } from '../emulation/constants.js';
|
|
4
4
|
import { PreloadFile, flagToMode } from '../file.js';
|
|
5
5
|
import { FileSystem, Sync } from '../filesystem.js';
|
|
@@ -110,10 +110,10 @@ export class SyncStoreFS extends Sync(FileSystem) {
|
|
|
110
110
|
// Remove oldPath from parent's directory listing.
|
|
111
111
|
oldDirNode = this.findINode(tx, oldParent), oldDirList = this.getDirListing(tx, oldDirNode, oldParent);
|
|
112
112
|
if (!oldDirNode.toStats().hasAccess(W_OK, cred)) {
|
|
113
|
-
throw
|
|
113
|
+
throw ErrnoError.With('EACCES', oldPath, 'rename');
|
|
114
114
|
}
|
|
115
115
|
if (!oldDirList[oldName]) {
|
|
116
|
-
throw
|
|
116
|
+
throw ErrnoError.With('ENOENT', oldPath, 'rename');
|
|
117
117
|
}
|
|
118
118
|
const ino = oldDirList[oldName];
|
|
119
119
|
delete oldDirList[oldName];
|
|
@@ -122,7 +122,7 @@ export class SyncStoreFS extends Sync(FileSystem) {
|
|
|
122
122
|
// is a subpath of newParent. We append '/' to avoid matching folders that
|
|
123
123
|
// are a substring of the bottom-most folder in the path.
|
|
124
124
|
if ((newParent + '/').indexOf(oldPath + '/') == 0) {
|
|
125
|
-
throw new
|
|
125
|
+
throw new ErrnoError(Errno.EBUSY, oldParent);
|
|
126
126
|
}
|
|
127
127
|
// Add newPath to parent's directory listing.
|
|
128
128
|
let newDirNode, newDirList;
|
|
@@ -151,7 +151,7 @@ export class SyncStoreFS extends Sync(FileSystem) {
|
|
|
151
151
|
}
|
|
152
152
|
else {
|
|
153
153
|
// If it's a directory, throw a permissions error.
|
|
154
|
-
throw
|
|
154
|
+
throw ErrnoError.With('EPERM', newPath, 'rename');
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
newDirList[newName] = ino;
|
|
@@ -170,7 +170,7 @@ export class SyncStoreFS extends Sync(FileSystem) {
|
|
|
170
170
|
// Get the inode to the item, convert it into a Stats object.
|
|
171
171
|
const stats = this.findINode(this.store.beginTransaction(), p).toStats();
|
|
172
172
|
if (!stats.hasAccess(R_OK, cred)) {
|
|
173
|
-
throw
|
|
173
|
+
throw ErrnoError.With('EACCES', p, 'stat');
|
|
174
174
|
}
|
|
175
175
|
return stats;
|
|
176
176
|
}
|
|
@@ -181,10 +181,10 @@ export class SyncStoreFS extends Sync(FileSystem) {
|
|
|
181
181
|
openFileSync(p, flag, cred) {
|
|
182
182
|
const tx = this.store.beginTransaction(), node = this.findINode(tx, p), data = tx.get(node.ino);
|
|
183
183
|
if (!node.toStats().hasAccess(flagToMode(flag), cred)) {
|
|
184
|
-
throw
|
|
184
|
+
throw ErrnoError.With('EACCES', p, 'openFile');
|
|
185
185
|
}
|
|
186
186
|
if (!data) {
|
|
187
|
-
throw
|
|
187
|
+
throw ErrnoError.With('ENOENT', p, 'openFile');
|
|
188
188
|
}
|
|
189
189
|
return new PreloadFile(this, p, flag, node.toStats(), data);
|
|
190
190
|
}
|
|
@@ -194,7 +194,7 @@ export class SyncStoreFS extends Sync(FileSystem) {
|
|
|
194
194
|
rmdirSync(p, cred) {
|
|
195
195
|
// Check first if directory is empty.
|
|
196
196
|
if (this.readdirSync(p, cred).length > 0) {
|
|
197
|
-
throw
|
|
197
|
+
throw ErrnoError.With('ENOTEMPTY', p, 'rmdir');
|
|
198
198
|
}
|
|
199
199
|
else {
|
|
200
200
|
this.removeEntry(p, true, cred);
|
|
@@ -207,7 +207,7 @@ export class SyncStoreFS extends Sync(FileSystem) {
|
|
|
207
207
|
const tx = this.store.beginTransaction();
|
|
208
208
|
const node = this.findINode(tx, p);
|
|
209
209
|
if (!node.toStats().hasAccess(R_OK, cred)) {
|
|
210
|
-
throw
|
|
210
|
+
throw ErrnoError.With('EACCES', p, 'readdir');
|
|
211
211
|
}
|
|
212
212
|
return Object.keys(this.getDirListing(tx, node, p));
|
|
213
213
|
}
|
|
@@ -234,16 +234,16 @@ export class SyncStoreFS extends Sync(FileSystem) {
|
|
|
234
234
|
linkSync(existing, newpath, cred) {
|
|
235
235
|
const tx = this.store.beginTransaction(), existingDir = dirname(existing), existingDirNode = this.findINode(tx, existingDir);
|
|
236
236
|
if (!existingDirNode.toStats().hasAccess(R_OK, cred)) {
|
|
237
|
-
throw
|
|
237
|
+
throw ErrnoError.With('EACCES', existingDir, 'link');
|
|
238
238
|
}
|
|
239
239
|
const newDir = dirname(newpath), newDirNode = this.findINode(tx, newDir), newListing = this.getDirListing(tx, newDirNode, newDir);
|
|
240
240
|
if (!newDirNode.toStats().hasAccess(W_OK, cred)) {
|
|
241
|
-
throw
|
|
241
|
+
throw ErrnoError.With('EACCES', newDir, 'link');
|
|
242
242
|
}
|
|
243
243
|
const ino = this._findINode(tx, existingDir, basename(existing));
|
|
244
244
|
const node = this.getINode(tx, ino, existing);
|
|
245
245
|
if (!node.toStats().hasAccess(W_OK, cred)) {
|
|
246
|
-
throw
|
|
246
|
+
throw ErrnoError.With('EACCES', newpath, 'link');
|
|
247
247
|
}
|
|
248
248
|
node.nlink++;
|
|
249
249
|
newListing[basename(newpath)] = ino;
|
|
@@ -283,14 +283,14 @@ export class SyncStoreFS extends Sync(FileSystem) {
|
|
|
283
283
|
_findINode(tx, parent, filename, visited = new Set()) {
|
|
284
284
|
const currentPath = join(parent, filename);
|
|
285
285
|
if (visited.has(currentPath)) {
|
|
286
|
-
throw new
|
|
286
|
+
throw new ErrnoError(Errno.EIO, 'Infinite loop detected while finding inode', currentPath);
|
|
287
287
|
}
|
|
288
288
|
visited.add(currentPath);
|
|
289
289
|
if (parent != '/') {
|
|
290
290
|
const ino = this._findINode(tx, dirname(parent), basename(parent), visited);
|
|
291
291
|
const dir = this.getDirListing(tx, this.getINode(tx, ino, parent + sep + filename), parent);
|
|
292
292
|
if (!(filename in dir)) {
|
|
293
|
-
throw
|
|
293
|
+
throw ErrnoError.With('ENOENT', resolve(parent, filename), '_findINode');
|
|
294
294
|
}
|
|
295
295
|
return dir[filename];
|
|
296
296
|
}
|
|
@@ -298,7 +298,7 @@ export class SyncStoreFS extends Sync(FileSystem) {
|
|
|
298
298
|
// Find the item in the root node.
|
|
299
299
|
const dir = this.getDirListing(tx, this.getINode(tx, rootIno, parent), parent);
|
|
300
300
|
if (!(filename in dir)) {
|
|
301
|
-
throw
|
|
301
|
+
throw ErrnoError.With('ENOENT', resolve(parent, filename), '_findINode');
|
|
302
302
|
}
|
|
303
303
|
return dir[filename];
|
|
304
304
|
}
|
|
@@ -324,7 +324,7 @@ export class SyncStoreFS extends Sync(FileSystem) {
|
|
|
324
324
|
getINode(tx, id, path) {
|
|
325
325
|
const data = tx.get(id);
|
|
326
326
|
if (!data) {
|
|
327
|
-
throw
|
|
327
|
+
throw ErrnoError.With('ENOENT', path, 'getINode');
|
|
328
328
|
}
|
|
329
329
|
const inode = new Inode(data.buffer);
|
|
330
330
|
return inode;
|
|
@@ -334,11 +334,11 @@ export class SyncStoreFS extends Sync(FileSystem) {
|
|
|
334
334
|
*/
|
|
335
335
|
getDirListing(tx, inode, p) {
|
|
336
336
|
if (!inode.toStats().isDirectory()) {
|
|
337
|
-
throw
|
|
337
|
+
throw ErrnoError.With('ENOTDIR', p, 'getDirListing');
|
|
338
338
|
}
|
|
339
339
|
const data = tx.get(inode.ino);
|
|
340
340
|
if (!data) {
|
|
341
|
-
throw
|
|
341
|
+
throw ErrnoError.With('ENOENT', p, 'getDirListing');
|
|
342
342
|
}
|
|
343
343
|
return decodeDirListing(data);
|
|
344
344
|
}
|
|
@@ -355,7 +355,7 @@ export class SyncStoreFS extends Sync(FileSystem) {
|
|
|
355
355
|
}
|
|
356
356
|
return ino;
|
|
357
357
|
}
|
|
358
|
-
throw new
|
|
358
|
+
throw new ErrnoError(Errno.EIO, 'Unable to commit data to key-value store.');
|
|
359
359
|
}
|
|
360
360
|
/**
|
|
361
361
|
* Commits a new file (well, a FILE or a DIRECTORY) to the file system with the given mode.
|
|
@@ -370,18 +370,18 @@ export class SyncStoreFS extends Sync(FileSystem) {
|
|
|
370
370
|
const tx = this.store.beginTransaction(), parentDir = dirname(p), fname = basename(p), parentNode = this.findINode(tx, parentDir), dirListing = this.getDirListing(tx, parentNode, parentDir);
|
|
371
371
|
//Check that the creater has correct access
|
|
372
372
|
if (!parentNode.toStats().hasAccess(W_OK, cred)) {
|
|
373
|
-
throw
|
|
373
|
+
throw ErrnoError.With('EACCES', p, 'commitNewFile');
|
|
374
374
|
}
|
|
375
375
|
/* Invariant: The root always exists.
|
|
376
376
|
If we don't check this prior to taking steps below,
|
|
377
377
|
we will create a file with name '' in root should p == '/'.
|
|
378
378
|
*/
|
|
379
379
|
if (p === '/') {
|
|
380
|
-
throw
|
|
380
|
+
throw ErrnoError.With('EEXIST', p, 'commitNewFile');
|
|
381
381
|
}
|
|
382
382
|
// Check if file already exists.
|
|
383
383
|
if (dirListing[fname]) {
|
|
384
|
-
throw
|
|
384
|
+
throw ErrnoError.With('EEXIST', p, 'commitNewFile');
|
|
385
385
|
}
|
|
386
386
|
const fileNode = new Inode();
|
|
387
387
|
try {
|
|
@@ -411,20 +411,20 @@ export class SyncStoreFS extends Sync(FileSystem) {
|
|
|
411
411
|
removeEntry(p, isDir, cred) {
|
|
412
412
|
const tx = this.store.beginTransaction(), parent = dirname(p), parentNode = this.findINode(tx, parent), parentListing = this.getDirListing(tx, parentNode, parent), fileName = basename(p), fileIno = parentListing[fileName];
|
|
413
413
|
if (!fileIno) {
|
|
414
|
-
throw
|
|
414
|
+
throw ErrnoError.With('ENOENT', p, 'removeEntry');
|
|
415
415
|
}
|
|
416
416
|
// Get file inode.
|
|
417
417
|
const fileNode = this.getINode(tx, fileIno, p);
|
|
418
418
|
if (!fileNode.toStats().hasAccess(W_OK, cred)) {
|
|
419
|
-
throw
|
|
419
|
+
throw ErrnoError.With('EACCES', p, 'removeEntry');
|
|
420
420
|
}
|
|
421
421
|
// Remove from directory listing of parent.
|
|
422
422
|
delete parentListing[fileName];
|
|
423
423
|
if (!isDir && fileNode.toStats().isDirectory()) {
|
|
424
|
-
throw
|
|
424
|
+
throw ErrnoError.With('EISDIR', p, 'removeEntry');
|
|
425
425
|
}
|
|
426
426
|
if (isDir && !fileNode.toStats().isDirectory()) {
|
|
427
|
-
throw
|
|
427
|
+
throw ErrnoError.With('ENOTDIR', p, 'removeEntry');
|
|
428
428
|
}
|
|
429
429
|
try {
|
|
430
430
|
// Update directory listing.
|
package/dist/backends/backend.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ErrnoError, Errno } from '../error.js';
|
|
2
2
|
import { levenshtein } from '../utils.js';
|
|
3
3
|
/**
|
|
4
4
|
* @internal
|
|
@@ -12,7 +12,7 @@ export function isBackend(arg) {
|
|
|
12
12
|
*/
|
|
13
13
|
export async function checkOptions(backend, opts) {
|
|
14
14
|
if (typeof opts != 'object' || opts === null) {
|
|
15
|
-
throw new
|
|
15
|
+
throw new ErrnoError(Errno.EINVAL, 'Invalid options');
|
|
16
16
|
}
|
|
17
17
|
// Check for required options.
|
|
18
18
|
for (const [optName, opt] of Object.entries(backend.options)) {
|
|
@@ -31,12 +31,12 @@ export async function checkOptions(backend, opts) {
|
|
|
31
31
|
})
|
|
32
32
|
.filter(o => o.distance < 5)
|
|
33
33
|
.sort((a, b) => a.distance - b.distance);
|
|
34
|
-
throw new
|
|
34
|
+
throw new ErrnoError(Errno.EINVAL, `${backend.name}: Required option '${optName}' not provided.${incorrectOptions.length > 0 ? ` You provided '${incorrectOptions[0].str}', did you mean '${optName}'.` : ''}`);
|
|
35
35
|
}
|
|
36
36
|
// Option provided, check type.
|
|
37
37
|
const typeMatches = Array.isArray(opt.type) ? opt.type.indexOf(typeof providedValue) != -1 : typeof providedValue == opt.type;
|
|
38
38
|
if (!typeMatches) {
|
|
39
|
-
throw new
|
|
39
|
+
throw new ErrnoError(Errno.EINVAL, `${backend.name}: Value provided for option ${optName} is not the proper type. Expected ${Array.isArray(opt.type) ? `one of {${opt.type.join(', ')}}` : opt.type}, but received ${typeof providedValue}`);
|
|
40
40
|
}
|
|
41
41
|
if (opt.validator) {
|
|
42
42
|
await opt.validator(providedValue);
|