@zenfs/core 0.0.12 → 0.2.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/ApiError.d.ts +52 -15
- package/dist/ApiError.js +77 -50
- package/dist/FileIndex.d.ts +32 -35
- package/dist/FileIndex.js +93 -109
- package/dist/backends/AsyncMirror.d.ts +42 -43
- package/dist/backends/AsyncMirror.js +154 -147
- package/dist/backends/AsyncStore.d.ts +29 -28
- package/dist/backends/AsyncStore.js +375 -482
- package/dist/backends/FolderAdapter.js +8 -19
- package/dist/backends/InMemory.d.ts +16 -13
- package/dist/backends/InMemory.js +29 -14
- package/dist/backends/Locked.d.ts +8 -28
- package/dist/backends/Locked.js +74 -224
- package/dist/backends/OverlayFS.d.ts +26 -34
- package/dist/backends/OverlayFS.js +303 -511
- package/dist/backends/SyncStore.d.ts +54 -72
- package/dist/backends/SyncStore.js +159 -161
- package/dist/backends/backend.d.ts +45 -29
- package/dist/backends/backend.js +83 -13
- package/dist/backends/index.d.ts +6 -7
- package/dist/backends/index.js +5 -6
- package/dist/browser.min.js +21 -6
- package/dist/browser.min.js.map +4 -4
- package/dist/emulation/callbacks.d.ts +119 -113
- package/dist/emulation/callbacks.js +129 -92
- package/dist/emulation/constants.js +1 -1
- package/dist/emulation/dir.d.ts +55 -0
- package/dist/emulation/dir.js +104 -0
- package/dist/emulation/fs.d.ts +1 -2
- package/dist/emulation/fs.js +0 -1
- package/dist/emulation/index.d.ts +3 -0
- package/dist/emulation/index.js +3 -0
- package/dist/emulation/promises.d.ts +265 -145
- package/dist/emulation/promises.js +526 -383
- package/dist/emulation/shared.d.ts +20 -6
- package/dist/emulation/shared.js +22 -23
- package/dist/emulation/streams.d.ts +102 -0
- package/dist/emulation/streams.js +55 -0
- package/dist/emulation/sync.d.ts +98 -69
- package/dist/emulation/sync.js +280 -133
- package/dist/file.d.ts +175 -173
- package/dist/file.js +257 -273
- package/dist/filesystem.d.ts +71 -244
- package/dist/filesystem.js +67 -472
- package/dist/index.d.ts +7 -44
- package/dist/index.js +22 -75
- package/dist/inode.d.ts +37 -28
- package/dist/inode.js +123 -65
- package/dist/stats.d.ts +91 -36
- package/dist/stats.js +138 -110
- package/dist/utils.d.ts +26 -13
- package/dist/utils.js +79 -107
- package/package.json +7 -4
- package/readme.md +2 -40
|
@@ -1,39 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
var _a;
|
|
11
|
-
import { BaseFileSystem } from '../filesystem.js';
|
|
1
|
+
import { FileSystem } from '../filesystem.js';
|
|
12
2
|
import { ApiError, ErrorCode } from '../ApiError.js';
|
|
13
|
-
import { FileFlag,
|
|
3
|
+
import { FileFlag, PreloadFile } from '../file.js';
|
|
14
4
|
import { Stats } from '../stats.js';
|
|
15
5
|
import LockedFS from './Locked.js';
|
|
16
|
-
import {
|
|
6
|
+
import { dirname } from '../emulation/path.js';
|
|
17
7
|
import { Cred } from '../cred.js';
|
|
18
|
-
import { CreateBackend } from './backend.js';
|
|
19
8
|
import { decode, encode } from '../utils.js';
|
|
20
9
|
/**
|
|
21
10
|
* @internal
|
|
22
11
|
*/
|
|
23
|
-
const deletionLogPath = '/.
|
|
24
|
-
/**
|
|
25
|
-
* Given a read-only mode, makes it writable.
|
|
26
|
-
* @internal
|
|
27
|
-
*/
|
|
28
|
-
function makeModeWritable(mode) {
|
|
29
|
-
return 0o222 | mode;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* @internal
|
|
33
|
-
*/
|
|
34
|
-
function getFlag(f) {
|
|
35
|
-
return FileFlag.getFileFlag(f);
|
|
36
|
-
}
|
|
12
|
+
const deletionLogPath = '/.deleted';
|
|
37
13
|
/**
|
|
38
14
|
* Overlays a RO file to make it writable.
|
|
39
15
|
*/
|
|
@@ -41,60 +17,65 @@ class OverlayFile extends PreloadFile {
|
|
|
41
17
|
constructor(fs, path, flag, stats, data) {
|
|
42
18
|
super(fs, path, flag, stats, data);
|
|
43
19
|
}
|
|
44
|
-
sync() {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.resetDirty();
|
|
51
|
-
});
|
|
20
|
+
async sync() {
|
|
21
|
+
if (!this.isDirty()) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
await this.fs.sync(this.path, this.buffer, this.stats);
|
|
25
|
+
this.resetDirty();
|
|
52
26
|
}
|
|
53
27
|
syncSync() {
|
|
54
28
|
if (this.isDirty()) {
|
|
55
|
-
this.
|
|
29
|
+
this.fs.syncSync(this.path, this.buffer, this.stats);
|
|
56
30
|
this.resetDirty();
|
|
57
31
|
}
|
|
58
32
|
}
|
|
59
|
-
close() {
|
|
60
|
-
|
|
61
|
-
yield this.sync();
|
|
62
|
-
});
|
|
33
|
+
async close() {
|
|
34
|
+
await this.sync();
|
|
63
35
|
}
|
|
64
36
|
closeSync() {
|
|
65
37
|
this.syncSync();
|
|
66
38
|
}
|
|
67
39
|
}
|
|
68
40
|
/**
|
|
69
|
-
*
|
|
41
|
+
* OverlayFS makes a read-only filesystem writable by storing writes on a second, writable file system.
|
|
42
|
+
* Deletes are persisted via metadata stored on the writable file system.
|
|
43
|
+
*
|
|
44
|
+
* This class contains no locking whatsoever. It is wrapped in a LockedFS to prevent races.
|
|
70
45
|
*
|
|
71
|
-
*
|
|
72
|
-
* in a LockedFS to prevent races.
|
|
46
|
+
* @internal
|
|
73
47
|
*/
|
|
74
|
-
export class UnlockedOverlayFS extends
|
|
75
|
-
|
|
76
|
-
|
|
48
|
+
export class UnlockedOverlayFS extends FileSystem {
|
|
49
|
+
async ready() {
|
|
50
|
+
await this._readable.ready();
|
|
51
|
+
await this._writable.ready();
|
|
52
|
+
await this._ready;
|
|
53
|
+
return this;
|
|
77
54
|
}
|
|
78
55
|
constructor({ writable, readable }) {
|
|
79
56
|
super();
|
|
80
57
|
this._isInitialized = false;
|
|
81
|
-
this._deletedFiles =
|
|
58
|
+
this._deletedFiles = new Set();
|
|
82
59
|
this._deleteLog = '';
|
|
83
60
|
// If 'true', we have scheduled a delete log update.
|
|
84
61
|
this._deleteLogUpdatePending = false;
|
|
85
62
|
// If 'true', a delete log update is needed after the scheduled delete log
|
|
86
63
|
// update finishes.
|
|
87
64
|
this._deleteLogUpdateNeeded = false;
|
|
88
|
-
// If there was an error updating the delete log...
|
|
89
|
-
this._deleteLogError = null;
|
|
90
65
|
this._writable = writable;
|
|
91
66
|
this._readable = readable;
|
|
92
67
|
if (this._writable.metadata.readonly) {
|
|
93
68
|
throw new ApiError(ErrorCode.EINVAL, 'Writable file system must be writable.');
|
|
94
69
|
}
|
|
70
|
+
this._ready = this._initialize();
|
|
95
71
|
}
|
|
96
72
|
get metadata() {
|
|
97
|
-
return
|
|
73
|
+
return {
|
|
74
|
+
...super.metadata,
|
|
75
|
+
name: OverlayFS.name,
|
|
76
|
+
synchronous: this._readable.metadata.synchronous && this._writable.metadata.synchronous,
|
|
77
|
+
supportsProperties: this._readable.metadata.supportsProperties && this._writable.metadata.supportsProperties,
|
|
78
|
+
};
|
|
98
79
|
}
|
|
99
80
|
getOverlayedFileSystems() {
|
|
100
81
|
return {
|
|
@@ -102,42 +83,38 @@ export class UnlockedOverlayFS extends BaseFileSystem {
|
|
|
102
83
|
writable: this._writable,
|
|
103
84
|
};
|
|
104
85
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
return this._writable.writeFile(file.getPath(), file.getBuffer(), getFlag('w'), stats.mode, stats.getCred(0, 0));
|
|
110
|
-
});
|
|
86
|
+
async sync(path, data, stats) {
|
|
87
|
+
const cred = stats.getCred(0, 0);
|
|
88
|
+
await this.createParentDirectories(path, cred);
|
|
89
|
+
await this._writable.sync(path, data, stats);
|
|
111
90
|
}
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
this.
|
|
115
|
-
this._writable.
|
|
91
|
+
syncSync(path, data, stats) {
|
|
92
|
+
const cred = stats.getCred(0, 0);
|
|
93
|
+
this.createParentDirectoriesSync(path, cred);
|
|
94
|
+
this._writable.syncSync(path, data, stats);
|
|
116
95
|
}
|
|
117
96
|
/**
|
|
118
|
-
* **INTERNAL METHOD**
|
|
119
|
-
*
|
|
120
97
|
* Called once to load up metadata stored on the writable file system.
|
|
98
|
+
* @internal
|
|
121
99
|
*/
|
|
122
|
-
_initialize() {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
100
|
+
async _initialize() {
|
|
101
|
+
if (this._isInitialized) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
// Read deletion log, process into metadata.
|
|
105
|
+
try {
|
|
106
|
+
const file = await this._writable.openFile(deletionLogPath, FileFlag.FromString('r'), Cred.Root);
|
|
107
|
+
const { size } = await file.stat();
|
|
108
|
+
const { buffer } = await file.read(new Uint8Array(size));
|
|
109
|
+
this._deleteLog = decode(buffer);
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
if (err.errno !== ErrorCode.ENOENT) {
|
|
113
|
+
throw err;
|
|
137
114
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
115
|
+
}
|
|
116
|
+
this._isInitialized = true;
|
|
117
|
+
this._reparseDeletionLog();
|
|
141
118
|
}
|
|
142
119
|
getDeletionLog() {
|
|
143
120
|
return this._deleteLog;
|
|
@@ -147,133 +124,47 @@ export class UnlockedOverlayFS extends BaseFileSystem {
|
|
|
147
124
|
this._reparseDeletionLog();
|
|
148
125
|
this.updateLog('', cred);
|
|
149
126
|
}
|
|
150
|
-
rename(oldPath, newPath, cred) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (oldStats.isDirectory()) {
|
|
161
|
-
// Optimization: Don't bother moving if old === new.
|
|
162
|
-
if (oldPath === newPath) {
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
let mode = 0o777;
|
|
166
|
-
if (yield this.exists(newPath, cred)) {
|
|
167
|
-
const stats = yield this.stat(newPath, cred);
|
|
168
|
-
mode = stats.mode;
|
|
169
|
-
if (stats.isDirectory()) {
|
|
170
|
-
if ((yield this.readdir(newPath, cred)).length > 0) {
|
|
171
|
-
throw ApiError.ENOTEMPTY(newPath);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
throw ApiError.ENOTDIR(newPath);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
// Take care of writable first. Move any files there, or create an empty directory
|
|
179
|
-
// if it doesn't exist.
|
|
180
|
-
if (yield this._writable.exists(oldPath, cred)) {
|
|
181
|
-
yield this._writable.rename(oldPath, newPath, cred);
|
|
182
|
-
}
|
|
183
|
-
else if (!(yield this._writable.exists(newPath, cred))) {
|
|
184
|
-
yield this._writable.mkdir(newPath, mode, cred);
|
|
185
|
-
}
|
|
186
|
-
// Need to move *every file/folder* currently stored on readable to its new location
|
|
187
|
-
// on writable.
|
|
188
|
-
if (yield this._readable.exists(oldPath, cred)) {
|
|
189
|
-
for (const name of yield this._readable.readdir(oldPath, cred)) {
|
|
190
|
-
// Recursion! Should work for any nested files / folders.
|
|
191
|
-
yield this.rename(resolve(oldPath, name), resolve(newPath, name), cred);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
if ((yield this.exists(newPath, cred)) && (yield this.stat(newPath, cred)).isDirectory()) {
|
|
197
|
-
throw ApiError.EISDIR(newPath);
|
|
198
|
-
}
|
|
199
|
-
yield this.writeFile(newPath, yield this.readFile(oldPath, getFlag('r'), cred), getFlag('w'), oldStats.mode, cred);
|
|
200
|
-
}
|
|
201
|
-
if (oldPath !== newPath && (yield this.exists(oldPath, cred))) {
|
|
202
|
-
yield this.unlink(oldPath, cred);
|
|
127
|
+
async rename(oldPath, newPath, cred) {
|
|
128
|
+
this.checkInitialized();
|
|
129
|
+
this.checkPath(oldPath);
|
|
130
|
+
this.checkPath(newPath);
|
|
131
|
+
try {
|
|
132
|
+
await this._writable.rename(oldPath, newPath, cred);
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
if (this._deletedFiles.has(oldPath)) {
|
|
136
|
+
throw ApiError.ENOENT(oldPath);
|
|
203
137
|
}
|
|
204
|
-
}
|
|
138
|
+
}
|
|
205
139
|
}
|
|
206
140
|
renameSync(oldPath, newPath, cred) {
|
|
207
141
|
this.checkInitialized();
|
|
208
142
|
this.checkPath(oldPath);
|
|
209
143
|
this.checkPath(newPath);
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
213
|
-
// Write newPath using oldPath's contents, delete oldPath.
|
|
214
|
-
const oldStats = this.statSync(oldPath, cred);
|
|
215
|
-
if (oldStats.isDirectory()) {
|
|
216
|
-
// Optimization: Don't bother moving if old === new.
|
|
217
|
-
if (oldPath === newPath) {
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
let mode = 0o777;
|
|
221
|
-
if (this.existsSync(newPath, cred)) {
|
|
222
|
-
const stats = this.statSync(newPath, cred);
|
|
223
|
-
mode = stats.mode;
|
|
224
|
-
if (stats.isDirectory()) {
|
|
225
|
-
if (this.readdirSync(newPath, cred).length > 0) {
|
|
226
|
-
throw ApiError.ENOTEMPTY(newPath);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
throw ApiError.ENOTDIR(newPath);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
// Take care of writable first. Move any files there, or create an empty directory
|
|
234
|
-
// if it doesn't exist.
|
|
235
|
-
if (this._writable.existsSync(oldPath, cred)) {
|
|
236
|
-
this._writable.renameSync(oldPath, newPath, cred);
|
|
237
|
-
}
|
|
238
|
-
else if (!this._writable.existsSync(newPath, cred)) {
|
|
239
|
-
this._writable.mkdirSync(newPath, mode, cred);
|
|
240
|
-
}
|
|
241
|
-
// Need to move *every file/folder* currently stored on readable to its new location
|
|
242
|
-
// on writable.
|
|
243
|
-
if (this._readable.existsSync(oldPath, cred)) {
|
|
244
|
-
this._readable.readdirSync(oldPath, cred).forEach(name => {
|
|
245
|
-
// Recursion! Should work for any nested files / folders.
|
|
246
|
-
this.renameSync(resolve(oldPath, name), resolve(newPath, name), cred);
|
|
247
|
-
});
|
|
248
|
-
}
|
|
144
|
+
try {
|
|
145
|
+
this._writable.renameSync(oldPath, newPath, cred);
|
|
249
146
|
}
|
|
250
|
-
|
|
251
|
-
if (this.
|
|
252
|
-
throw ApiError.
|
|
147
|
+
catch (e) {
|
|
148
|
+
if (this._deletedFiles.has(oldPath)) {
|
|
149
|
+
throw ApiError.ENOENT(oldPath);
|
|
253
150
|
}
|
|
254
|
-
this.writeFileSync(newPath, this.readFileSync(oldPath, getFlag('r'), cred), getFlag('w'), oldStats.mode, cred);
|
|
255
|
-
}
|
|
256
|
-
if (oldPath !== newPath && this.existsSync(oldPath, cred)) {
|
|
257
|
-
this.unlinkSync(oldPath, cred);
|
|
258
151
|
}
|
|
259
152
|
}
|
|
260
|
-
stat(p, cred) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
throw ApiError.ENOENT(p);
|
|
269
|
-
}
|
|
270
|
-
const oldStat = Stats.clone(yield this._readable.stat(p, cred));
|
|
271
|
-
// Make the oldStat's mode writable. Preserve the topmost part of the
|
|
272
|
-
// mode, which specifies if it is a file or a directory.
|
|
273
|
-
oldStat.mode = makeModeWritable(oldStat.mode);
|
|
274
|
-
return oldStat;
|
|
153
|
+
async stat(p, cred) {
|
|
154
|
+
this.checkInitialized();
|
|
155
|
+
try {
|
|
156
|
+
return this._writable.stat(p, cred);
|
|
157
|
+
}
|
|
158
|
+
catch (e) {
|
|
159
|
+
if (this._deletedFiles.has(p)) {
|
|
160
|
+
throw ApiError.ENOENT(p);
|
|
275
161
|
}
|
|
276
|
-
|
|
162
|
+
const oldStat = Stats.clone(await this._readable.stat(p, cred));
|
|
163
|
+
// Make the oldStat's mode writable. Preserve the topmost part of the
|
|
164
|
+
// mode, which specifies if it is a file or a directory.
|
|
165
|
+
oldStat.mode |= 0o222;
|
|
166
|
+
return oldStat;
|
|
167
|
+
}
|
|
277
168
|
}
|
|
278
169
|
statSync(p, cred) {
|
|
279
170
|
this.checkInitialized();
|
|
@@ -281,219 +172,162 @@ export class UnlockedOverlayFS extends BaseFileSystem {
|
|
|
281
172
|
return this._writable.statSync(p, cred);
|
|
282
173
|
}
|
|
283
174
|
catch (e) {
|
|
284
|
-
if (this._deletedFiles
|
|
175
|
+
if (this._deletedFiles.has(p)) {
|
|
285
176
|
throw ApiError.ENOENT(p);
|
|
286
177
|
}
|
|
287
178
|
const oldStat = Stats.clone(this._readable.statSync(p, cred));
|
|
288
179
|
// Make the oldStat's mode writable. Preserve the topmost part of the
|
|
289
180
|
// mode, which specifies if it is a file or a directory.
|
|
290
|
-
oldStat.mode
|
|
181
|
+
oldStat.mode |= 0o222;
|
|
291
182
|
return oldStat;
|
|
292
183
|
}
|
|
293
184
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
this.
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
});
|
|
185
|
+
async openFile(path, flag, cred) {
|
|
186
|
+
if (await this._writable.exists(path, cred)) {
|
|
187
|
+
return this._writable.openFile(path, flag, cred);
|
|
188
|
+
}
|
|
189
|
+
// Create an OverlayFile.
|
|
190
|
+
const file = await this._readable.openFile(path, FileFlag.FromString('r'), cred);
|
|
191
|
+
const stats = Stats.clone(await file.stat());
|
|
192
|
+
const { buffer } = await file.read(new Uint8Array(stats.size));
|
|
193
|
+
return new OverlayFile(this, path, flag, stats, buffer);
|
|
194
|
+
}
|
|
195
|
+
openFileSync(path, flag, cred) {
|
|
196
|
+
if (this._writable.existsSync(path, cred)) {
|
|
197
|
+
return this._writable.openFileSync(path, flag, cred);
|
|
198
|
+
}
|
|
199
|
+
// Create an OverlayFile.
|
|
200
|
+
const file = this._readable.openFileSync(path, FileFlag.FromString('r'), cred);
|
|
201
|
+
const stats = Stats.clone(file.statSync());
|
|
202
|
+
const data = new Uint8Array(stats.size);
|
|
203
|
+
file.readSync(data);
|
|
204
|
+
return new OverlayFile(this, path, flag, stats, data);
|
|
205
|
+
}
|
|
206
|
+
async createFile(path, flag, mode, cred) {
|
|
207
|
+
this.checkInitialized();
|
|
208
|
+
await this._writable.createFile(path, flag, mode, cred);
|
|
209
|
+
return this.openFile(path, flag, cred);
|
|
210
|
+
}
|
|
211
|
+
createFileSync(path, flag, mode, cred) {
|
|
212
|
+
this.checkInitialized();
|
|
213
|
+
this._writable.createFileSync(path, flag, mode, cred);
|
|
214
|
+
return this.openFileSync(path, flag, cred);
|
|
215
|
+
}
|
|
216
|
+
async link(srcpath, dstpath, cred) {
|
|
217
|
+
this.checkInitialized();
|
|
218
|
+
await this._writable.link(srcpath, dstpath, cred);
|
|
331
219
|
}
|
|
332
|
-
|
|
220
|
+
linkSync(srcpath, dstpath, cred) {
|
|
221
|
+
this.checkInitialized();
|
|
222
|
+
this._writable.linkSync(srcpath, dstpath, cred);
|
|
223
|
+
}
|
|
224
|
+
async unlink(p, cred) {
|
|
333
225
|
this.checkInitialized();
|
|
334
226
|
this.checkPath(p);
|
|
335
|
-
if (p
|
|
336
|
-
throw ApiError.
|
|
227
|
+
if (!(await this.exists(p, cred))) {
|
|
228
|
+
throw ApiError.ENOENT(p);
|
|
337
229
|
}
|
|
338
|
-
if (this.
|
|
339
|
-
|
|
340
|
-
case ActionType.TRUNCATE_FILE:
|
|
341
|
-
this.createParentDirectories(p, cred);
|
|
342
|
-
return this._writable.openSync(p, flag, mode, cred);
|
|
343
|
-
case ActionType.NOP:
|
|
344
|
-
if (this._writable.existsSync(p, cred)) {
|
|
345
|
-
return this._writable.openSync(p, flag, mode, cred);
|
|
346
|
-
}
|
|
347
|
-
else {
|
|
348
|
-
// Create an OverlayFile.
|
|
349
|
-
const buf = this._readable.readFileSync(p, getFlag('r'), cred);
|
|
350
|
-
const stats = Stats.clone(this._readable.statSync(p, cred));
|
|
351
|
-
stats.mode = mode;
|
|
352
|
-
return new OverlayFile(this, p, flag, stats, buf);
|
|
353
|
-
}
|
|
354
|
-
default:
|
|
355
|
-
throw ApiError.EEXIST(p);
|
|
356
|
-
}
|
|
230
|
+
if (await this._writable.exists(p, cred)) {
|
|
231
|
+
await this._writable.unlink(p, cred);
|
|
357
232
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
this.createParentDirectories(p, cred);
|
|
362
|
-
return this._writable.openSync(p, flag, mode, cred);
|
|
363
|
-
default:
|
|
364
|
-
throw ApiError.ENOENT(p);
|
|
365
|
-
}
|
|
233
|
+
// if it still exists add to the delete log
|
|
234
|
+
if (await this.exists(p, cred)) {
|
|
235
|
+
this.deletePath(p, cred);
|
|
366
236
|
}
|
|
367
237
|
}
|
|
368
|
-
unlink(p, cred) {
|
|
369
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
370
|
-
this.checkInitialized();
|
|
371
|
-
this.checkPath(p);
|
|
372
|
-
if (yield this.exists(p, cred)) {
|
|
373
|
-
if (yield this._writable.exists(p, cred)) {
|
|
374
|
-
yield this._writable.unlink(p, cred);
|
|
375
|
-
}
|
|
376
|
-
// if it still exists add to the delete log
|
|
377
|
-
if (yield this.exists(p, cred)) {
|
|
378
|
-
this.deletePath(p, cred);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
else {
|
|
382
|
-
throw ApiError.ENOENT(p);
|
|
383
|
-
}
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
238
|
unlinkSync(p, cred) {
|
|
387
239
|
this.checkInitialized();
|
|
388
240
|
this.checkPath(p);
|
|
241
|
+
if (!this.existsSync(p, cred)) {
|
|
242
|
+
throw ApiError.ENOENT(p);
|
|
243
|
+
}
|
|
244
|
+
if (this._writable.existsSync(p, cred)) {
|
|
245
|
+
this._writable.unlinkSync(p, cred);
|
|
246
|
+
}
|
|
247
|
+
// if it still exists add to the delete log
|
|
389
248
|
if (this.existsSync(p, cred)) {
|
|
390
|
-
|
|
391
|
-
this._writable.unlinkSync(p, cred);
|
|
392
|
-
}
|
|
393
|
-
// if it still exists add to the delete log
|
|
394
|
-
if (this.existsSync(p, cred)) {
|
|
395
|
-
this.deletePath(p, cred);
|
|
396
|
-
}
|
|
249
|
+
this.deletePath(p, cred);
|
|
397
250
|
}
|
|
398
|
-
|
|
251
|
+
}
|
|
252
|
+
async rmdir(p, cred) {
|
|
253
|
+
this.checkInitialized();
|
|
254
|
+
if (!(await this.exists(p, cred))) {
|
|
399
255
|
throw ApiError.ENOENT(p);
|
|
400
256
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
if
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
}
|
|
409
|
-
if (yield this.exists(p, cred)) {
|
|
410
|
-
// Check if directory is empty.
|
|
411
|
-
if ((yield this.readdir(p, cred)).length > 0) {
|
|
412
|
-
throw ApiError.ENOTEMPTY(p);
|
|
413
|
-
}
|
|
414
|
-
else {
|
|
415
|
-
this.deletePath(p, cred);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
257
|
+
if (await this._writable.exists(p, cred)) {
|
|
258
|
+
await this._writable.rmdir(p, cred);
|
|
259
|
+
}
|
|
260
|
+
if (await this.exists(p, cred)) {
|
|
261
|
+
// Check if directory is empty.
|
|
262
|
+
if ((await this.readdir(p, cred)).length > 0) {
|
|
263
|
+
throw ApiError.ENOTEMPTY(p);
|
|
418
264
|
}
|
|
419
265
|
else {
|
|
420
|
-
|
|
266
|
+
this.deletePath(p, cred);
|
|
421
267
|
}
|
|
422
|
-
}
|
|
268
|
+
}
|
|
423
269
|
}
|
|
424
270
|
rmdirSync(p, cred) {
|
|
425
271
|
this.checkInitialized();
|
|
426
|
-
if (this.existsSync(p, cred)) {
|
|
427
|
-
if (this._writable.existsSync(p, cred)) {
|
|
428
|
-
this._writable.rmdirSync(p, cred);
|
|
429
|
-
}
|
|
430
|
-
if (this.existsSync(p, cred)) {
|
|
431
|
-
// Check if directory is empty.
|
|
432
|
-
if (this.readdirSync(p, cred).length > 0) {
|
|
433
|
-
throw ApiError.ENOTEMPTY(p);
|
|
434
|
-
}
|
|
435
|
-
else {
|
|
436
|
-
this.deletePath(p, cred);
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
else {
|
|
272
|
+
if (!this.existsSync(p, cred)) {
|
|
441
273
|
throw ApiError.ENOENT(p);
|
|
442
274
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
if
|
|
448
|
-
|
|
275
|
+
if (this._writable.existsSync(p, cred)) {
|
|
276
|
+
this._writable.rmdirSync(p, cred);
|
|
277
|
+
}
|
|
278
|
+
if (this.existsSync(p, cred)) {
|
|
279
|
+
// Check if directory is empty.
|
|
280
|
+
if (this.readdirSync(p, cred).length > 0) {
|
|
281
|
+
throw ApiError.ENOTEMPTY(p);
|
|
449
282
|
}
|
|
450
283
|
else {
|
|
451
|
-
|
|
452
|
-
// on _writable.
|
|
453
|
-
yield this.createParentDirectoriesAsync(p, cred);
|
|
454
|
-
yield this._writable.mkdir(p, mode, cred);
|
|
284
|
+
this.deletePath(p, cred);
|
|
455
285
|
}
|
|
456
|
-
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
async mkdir(p, mode, cred) {
|
|
289
|
+
this.checkInitialized();
|
|
290
|
+
if (await this.exists(p, cred)) {
|
|
291
|
+
throw ApiError.EEXIST(p);
|
|
292
|
+
}
|
|
293
|
+
// The below will throw should any of the parent directories fail to exist on _writable.
|
|
294
|
+
await this.createParentDirectories(p, cred);
|
|
295
|
+
await this._writable.mkdir(p, mode, cred);
|
|
457
296
|
}
|
|
458
297
|
mkdirSync(p, mode, cred) {
|
|
459
298
|
this.checkInitialized();
|
|
460
299
|
if (this.existsSync(p, cred)) {
|
|
461
300
|
throw ApiError.EEXIST(p);
|
|
462
301
|
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
this.createParentDirectories(p, cred);
|
|
467
|
-
this._writable.mkdirSync(p, mode, cred);
|
|
468
|
-
}
|
|
302
|
+
// The below will throw should any of the parent directories fail to exist on _writable.
|
|
303
|
+
this.createParentDirectoriesSync(p, cred);
|
|
304
|
+
this._writable.mkdirSync(p, mode, cred);
|
|
469
305
|
}
|
|
470
|
-
readdir(p, cred) {
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
return result;
|
|
496
|
-
});
|
|
306
|
+
async readdir(p, cred) {
|
|
307
|
+
this.checkInitialized();
|
|
308
|
+
const dirStats = await this.stat(p, cred);
|
|
309
|
+
if (!dirStats.isDirectory()) {
|
|
310
|
+
throw ApiError.ENOTDIR(p);
|
|
311
|
+
}
|
|
312
|
+
// Readdir in both, check delete log on RO file system's listing, merge, return.
|
|
313
|
+
let contents = [];
|
|
314
|
+
try {
|
|
315
|
+
contents.push(...(await this._writable.readdir(p, cred)));
|
|
316
|
+
}
|
|
317
|
+
catch (e) {
|
|
318
|
+
// NOP.
|
|
319
|
+
}
|
|
320
|
+
try {
|
|
321
|
+
contents.push(...(await this._readable.readdir(p, cred)).filter((fPath) => !this._deletedFiles.has(`${p}/${fPath}`)));
|
|
322
|
+
}
|
|
323
|
+
catch (e) {
|
|
324
|
+
// NOP.
|
|
325
|
+
}
|
|
326
|
+
const seenMap = {};
|
|
327
|
+
return contents.filter((fileP) => {
|
|
328
|
+
const result = !seenMap[fileP];
|
|
329
|
+
seenMap[fileP] = true;
|
|
330
|
+
return result;
|
|
497
331
|
});
|
|
498
332
|
}
|
|
499
333
|
readdirSync(p, cred) {
|
|
@@ -511,7 +345,7 @@ export class UnlockedOverlayFS extends BaseFileSystem {
|
|
|
511
345
|
// NOP.
|
|
512
346
|
}
|
|
513
347
|
try {
|
|
514
|
-
contents = contents.concat(this._readable.readdirSync(p, cred).filter((fPath) => !this._deletedFiles
|
|
348
|
+
contents = contents.concat(this._readable.readdirSync(p, cred).filter((fPath) => !this._deletedFiles.has(`${p}/${fPath}`)));
|
|
515
349
|
}
|
|
516
350
|
catch (e) {
|
|
517
351
|
// NOP.
|
|
@@ -523,106 +357,63 @@ export class UnlockedOverlayFS extends BaseFileSystem {
|
|
|
523
357
|
return result;
|
|
524
358
|
});
|
|
525
359
|
}
|
|
526
|
-
exists(p, cred) {
|
|
527
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
528
|
-
this.checkInitialized();
|
|
529
|
-
return (yield this._writable.exists(p, cred)) || ((yield this._readable.exists(p, cred)) && this._deletedFiles[p] !== true);
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
existsSync(p, cred) {
|
|
533
|
-
this.checkInitialized();
|
|
534
|
-
return this._writable.existsSync(p, cred) || (this._readable.existsSync(p, cred) && this._deletedFiles[p] !== true);
|
|
535
|
-
}
|
|
536
|
-
chmod(p, mode, cred) {
|
|
537
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
538
|
-
this.checkInitialized();
|
|
539
|
-
yield this.operateOnWritableAsync(p, cred);
|
|
540
|
-
yield this._writable.chmod(p, mode, cred);
|
|
541
|
-
});
|
|
542
|
-
}
|
|
543
|
-
chmodSync(p, mode, cred) {
|
|
544
|
-
this.checkInitialized();
|
|
545
|
-
this.operateOnWritable(p, cred);
|
|
546
|
-
this._writable.chmodSync(p, mode, cred);
|
|
547
|
-
}
|
|
548
|
-
chown(p, new_uid, new_gid, cred) {
|
|
549
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
550
|
-
this.checkInitialized();
|
|
551
|
-
yield this.operateOnWritableAsync(p, cred);
|
|
552
|
-
yield this._writable.chown(p, new_uid, new_gid, cred);
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
chownSync(p, new_uid, new_gid, cred) {
|
|
556
|
-
this.checkInitialized();
|
|
557
|
-
this.operateOnWritable(p, cred);
|
|
558
|
-
this._writable.chownSync(p, new_uid, new_gid, cred);
|
|
559
|
-
}
|
|
560
|
-
utimes(p, atime, mtime, cred) {
|
|
561
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
562
|
-
this.checkInitialized();
|
|
563
|
-
yield this.operateOnWritableAsync(p, cred);
|
|
564
|
-
yield this._writable.utimes(p, atime, mtime, cred);
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
|
-
utimesSync(p, atime, mtime, cred) {
|
|
568
|
-
this.checkInitialized();
|
|
569
|
-
this.operateOnWritable(p, cred);
|
|
570
|
-
this._writable.utimesSync(p, atime, mtime, cred);
|
|
571
|
-
}
|
|
572
360
|
deletePath(p, cred) {
|
|
573
|
-
this._deletedFiles
|
|
361
|
+
this._deletedFiles.add(p);
|
|
574
362
|
this.updateLog(`d${p}\n`, cred);
|
|
575
363
|
}
|
|
576
|
-
updateLog(addition, cred) {
|
|
364
|
+
async updateLog(addition, cred) {
|
|
577
365
|
this._deleteLog += addition;
|
|
578
366
|
if (this._deleteLogUpdatePending) {
|
|
579
367
|
this._deleteLogUpdateNeeded = true;
|
|
368
|
+
return;
|
|
580
369
|
}
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
this._deleteLogUpdatePending = false;
|
|
596
|
-
});
|
|
370
|
+
this._deleteLogUpdatePending = true;
|
|
371
|
+
const log = await this._writable.openFile(deletionLogPath, FileFlag.FromString('w'), cred);
|
|
372
|
+
try {
|
|
373
|
+
await log.write(encode(this._deleteLog));
|
|
374
|
+
if (this._deleteLogUpdateNeeded) {
|
|
375
|
+
this._deleteLogUpdateNeeded = false;
|
|
376
|
+
this.updateLog('', cred);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
catch (e) {
|
|
380
|
+
this._deleteLogError = e;
|
|
381
|
+
}
|
|
382
|
+
finally {
|
|
383
|
+
this._deleteLogUpdatePending = false;
|
|
597
384
|
}
|
|
598
385
|
}
|
|
599
386
|
_reparseDeletionLog() {
|
|
600
|
-
this._deletedFiles
|
|
601
|
-
this._deleteLog.split('\n')
|
|
387
|
+
this._deletedFiles.clear();
|
|
388
|
+
for (const entry of this._deleteLog.split('\n')) {
|
|
389
|
+
if (!entry.startsWith('d')) {
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
602
392
|
// If the log entry begins w/ 'd', it's a deletion.
|
|
603
|
-
this._deletedFiles
|
|
604
|
-
}
|
|
393
|
+
this._deletedFiles.add(entry.slice(1));
|
|
394
|
+
}
|
|
605
395
|
}
|
|
606
396
|
checkInitialized() {
|
|
607
397
|
if (!this._isInitialized) {
|
|
608
398
|
throw new ApiError(ErrorCode.EPERM, 'OverlayFS is not initialized. Please initialize OverlayFS using its initialize() method before using it.');
|
|
609
399
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
this._deleteLogError = null;
|
|
613
|
-
throw e;
|
|
400
|
+
if (!this._deleteLogError) {
|
|
401
|
+
return;
|
|
614
402
|
}
|
|
403
|
+
const error = this._deleteLogError;
|
|
404
|
+
this._deleteLogError = null;
|
|
405
|
+
throw error;
|
|
615
406
|
}
|
|
616
|
-
checkPath(
|
|
617
|
-
if (
|
|
618
|
-
throw ApiError.EPERM(
|
|
407
|
+
checkPath(path) {
|
|
408
|
+
if (path == deletionLogPath) {
|
|
409
|
+
throw ApiError.EPERM(path);
|
|
619
410
|
}
|
|
620
411
|
}
|
|
621
412
|
/**
|
|
622
413
|
* With the given path, create the needed parent directories on the writable storage
|
|
623
414
|
* should they not exist. Use modes from the read-only storage.
|
|
624
415
|
*/
|
|
625
|
-
|
|
416
|
+
createParentDirectoriesSync(p, cred) {
|
|
626
417
|
let parent = dirname(p), toCreate = [];
|
|
627
418
|
while (!this._writable.existsSync(parent, cred)) {
|
|
628
419
|
toCreate.push(parent);
|
|
@@ -633,19 +424,17 @@ export class UnlockedOverlayFS extends BaseFileSystem {
|
|
|
633
424
|
this._writable.mkdirSync(p, this.statSync(p, cred).mode, cred);
|
|
634
425
|
}
|
|
635
426
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
}
|
|
648
|
-
});
|
|
427
|
+
async createParentDirectories(p, cred) {
|
|
428
|
+
let parent = dirname(p), toCreate = [];
|
|
429
|
+
while (!(await this._writable.exists(parent, cred))) {
|
|
430
|
+
toCreate.push(parent);
|
|
431
|
+
parent = dirname(parent);
|
|
432
|
+
}
|
|
433
|
+
toCreate = toCreate.reverse();
|
|
434
|
+
for (const p of toCreate) {
|
|
435
|
+
const stats = await this.stat(p, cred);
|
|
436
|
+
await this._writable.mkdir(p, stats.mode, cred);
|
|
437
|
+
}
|
|
649
438
|
}
|
|
650
439
|
/**
|
|
651
440
|
* Helper function:
|
|
@@ -659,42 +448,48 @@ export class UnlockedOverlayFS extends BaseFileSystem {
|
|
|
659
448
|
if (!this._writable.existsSync(p, cred)) {
|
|
660
449
|
// File is on readable storage. Copy to writable storage before
|
|
661
450
|
// changing its mode.
|
|
662
|
-
this.
|
|
451
|
+
this.copyToWritableSync(p, cred);
|
|
663
452
|
}
|
|
664
453
|
}
|
|
665
|
-
operateOnWritableAsync(p, cred) {
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
}
|
|
673
|
-
});
|
|
454
|
+
async operateOnWritableAsync(p, cred) {
|
|
455
|
+
if (!(await this.exists(p, cred))) {
|
|
456
|
+
throw ApiError.ENOENT(p);
|
|
457
|
+
}
|
|
458
|
+
if (!(await this._writable.exists(p, cred))) {
|
|
459
|
+
return this.copyToWritable(p, cred);
|
|
460
|
+
}
|
|
674
461
|
}
|
|
675
462
|
/**
|
|
676
463
|
* Copy from readable to writable storage.
|
|
677
464
|
* PRECONDITION: File does not exist on writable storage.
|
|
678
465
|
*/
|
|
679
|
-
|
|
680
|
-
const
|
|
681
|
-
if (
|
|
682
|
-
this._writable.mkdirSync(p,
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
466
|
+
copyToWritableSync(p, cred) {
|
|
467
|
+
const stats = this.statSync(p, cred);
|
|
468
|
+
if (stats.isDirectory()) {
|
|
469
|
+
this._writable.mkdirSync(p, stats.mode, cred);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
const data = new Uint8Array(stats.size);
|
|
473
|
+
const readable = this._readable.openFileSync(p, FileFlag.FromString('r'), cred);
|
|
474
|
+
readable.readSync(data);
|
|
475
|
+
readable.closeSync();
|
|
476
|
+
const writable = this._writable.openFileSync(p, FileFlag.FromString('w'), cred);
|
|
477
|
+
writable.writeSync(data);
|
|
478
|
+
writable.closeSync();
|
|
479
|
+
}
|
|
480
|
+
async copyToWritable(p, cred) {
|
|
481
|
+
const stats = await this.stat(p, cred);
|
|
482
|
+
if (stats.isDirectory()) {
|
|
483
|
+
await this._writable.mkdir(p, stats.mode, cred);
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
const data = new Uint8Array(stats.size);
|
|
487
|
+
const readable = await this._readable.openFile(p, FileFlag.FromString('r'), cred);
|
|
488
|
+
await readable.read(data);
|
|
489
|
+
await readable.close();
|
|
490
|
+
const writable = await this._writable.openFile(p, FileFlag.FromString('w'), cred);
|
|
491
|
+
await writable.write(data);
|
|
492
|
+
await writable.close();
|
|
698
493
|
}
|
|
699
494
|
}
|
|
700
495
|
/**
|
|
@@ -703,15 +498,15 @@ export class UnlockedOverlayFS extends BaseFileSystem {
|
|
|
703
498
|
* file system.
|
|
704
499
|
*/
|
|
705
500
|
export class OverlayFS extends LockedFS {
|
|
706
|
-
|
|
707
|
-
|
|
501
|
+
async ready() {
|
|
502
|
+
await super.ready();
|
|
503
|
+
return this;
|
|
708
504
|
}
|
|
709
505
|
/**
|
|
710
506
|
* @param options The options to initialize the OverlayFS with
|
|
711
507
|
*/
|
|
712
508
|
constructor(options) {
|
|
713
509
|
super(new UnlockedOverlayFS(options));
|
|
714
|
-
this._ready = this._initialize();
|
|
715
510
|
}
|
|
716
511
|
getOverlayedFileSystems() {
|
|
717
512
|
return super.fs.getOverlayedFileSystems();
|
|
@@ -725,26 +520,23 @@ export class OverlayFS extends LockedFS {
|
|
|
725
520
|
unwrap() {
|
|
726
521
|
return super.fs;
|
|
727
522
|
}
|
|
728
|
-
_initialize() {
|
|
729
|
-
const _super = Object.create(null, {
|
|
730
|
-
fs: { get: () => super.fs }
|
|
731
|
-
});
|
|
732
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
733
|
-
yield _super.fs._initialize();
|
|
734
|
-
return this;
|
|
735
|
-
});
|
|
736
|
-
}
|
|
737
523
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
524
|
+
export const Overlay = {
|
|
525
|
+
name: 'Overlay',
|
|
526
|
+
options: {
|
|
527
|
+
writable: {
|
|
528
|
+
type: 'object',
|
|
529
|
+
description: 'The file system to write modified files to.',
|
|
530
|
+
},
|
|
531
|
+
readable: {
|
|
532
|
+
type: 'object',
|
|
533
|
+
description: 'The file system that initially populates this file system.',
|
|
534
|
+
},
|
|
535
|
+
},
|
|
536
|
+
isAvailable() {
|
|
537
|
+
return true;
|
|
745
538
|
},
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
description: 'The file system that initially populates this file system.',
|
|
539
|
+
create(options) {
|
|
540
|
+
return new OverlayFS(options);
|
|
749
541
|
},
|
|
750
542
|
};
|