@componentor/fs 3.0.45 → 3.0.46
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/index.js +212 -25
- package/dist/index.js.map +1 -1
- package/dist/workers/repair.worker.js +212 -25
- package/dist/workers/repair.worker.js.map +1 -1
- package/dist/workers/server.worker.js +212 -25
- package/dist/workers/server.worker.js.map +1 -1
- package/dist/workers/sync-relay.worker.js +212 -25
- package/dist/workers/sync-relay.worker.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +15 -0
package/dist/index.js
CHANGED
|
@@ -4204,6 +4204,16 @@ var VFSEngine = class {
|
|
|
4204
4204
|
superblockDirty = false;
|
|
4205
4205
|
// Free inode hint — skip O(n) scan
|
|
4206
4206
|
freeInodeHint = 0;
|
|
4207
|
+
// Implicit directory support — tracks all directory prefixes implied by file paths.
|
|
4208
|
+
// Rebuilt lazily when pathIndex changes (tracked via generation counter).
|
|
4209
|
+
// Map value is the stable timestamp (ms since epoch) assigned when the implicit
|
|
4210
|
+
// dir was first discovered, so that stat() returns consistent mtime/ctime/atime
|
|
4211
|
+
// across repeated calls.
|
|
4212
|
+
implicitDirs = /* @__PURE__ */ new Map();
|
|
4213
|
+
implicitDirsGen = -1;
|
|
4214
|
+
// generation when implicitDirs was last rebuilt
|
|
4215
|
+
pathIndexGen = 0;
|
|
4216
|
+
// bumped on every pathIndex mutation
|
|
4207
4217
|
// Configurable upper bounds
|
|
4208
4218
|
maxInodes = 4e6;
|
|
4209
4219
|
maxBlocks = 4e6;
|
|
@@ -4488,6 +4498,7 @@ var VFSEngine = class {
|
|
|
4488
4498
|
}
|
|
4489
4499
|
this.pathIndex.set(path, i);
|
|
4490
4500
|
}
|
|
4501
|
+
this.pathIndexGen++;
|
|
4491
4502
|
}
|
|
4492
4503
|
// ========== Low-level inode I/O ==========
|
|
4493
4504
|
readInode(idx) {
|
|
@@ -4808,6 +4819,7 @@ var VFSEngine = class {
|
|
|
4808
4819
|
};
|
|
4809
4820
|
this.writeInode(idx, inode);
|
|
4810
4821
|
this.pathIndex.set(path, idx);
|
|
4822
|
+
this.pathIndexGen++;
|
|
4811
4823
|
return idx;
|
|
4812
4824
|
}
|
|
4813
4825
|
// ========== Public API — called by server worker dispatch ==========
|
|
@@ -4964,6 +4976,7 @@ var VFSEngine = class {
|
|
|
4964
4976
|
inode.type = INODE_TYPE.FREE;
|
|
4965
4977
|
this.writeInode(idx, inode);
|
|
4966
4978
|
this.pathIndex.delete(path);
|
|
4979
|
+
this.pathIndexGen++;
|
|
4967
4980
|
if (idx < this.freeInodeHint) this.freeInodeHint = idx;
|
|
4968
4981
|
this.commitPending();
|
|
4969
4982
|
return { status: 0 };
|
|
@@ -4972,7 +4985,12 @@ var VFSEngine = class {
|
|
|
4972
4985
|
stat(path) {
|
|
4973
4986
|
path = this.normalizePath(path);
|
|
4974
4987
|
const idx = this.resolvePathComponents(path, true);
|
|
4975
|
-
if (idx === void 0)
|
|
4988
|
+
if (idx === void 0) {
|
|
4989
|
+
if (this.isImplicitDirectory(path)) {
|
|
4990
|
+
return this.encodeImplicitDirStatResponse(path);
|
|
4991
|
+
}
|
|
4992
|
+
return { status: CODE_TO_STATUS.ENOENT, data: null };
|
|
4993
|
+
}
|
|
4976
4994
|
return this.encodeStatResponse(idx);
|
|
4977
4995
|
}
|
|
4978
4996
|
// ---- LSTAT (no symlink follow for the FINAL component) ----
|
|
@@ -4981,7 +4999,12 @@ var VFSEngine = class {
|
|
|
4981
4999
|
let idx = this.resolvePathComponents(path, false);
|
|
4982
5000
|
if (idx === void 0) {
|
|
4983
5001
|
idx = this.resolvePathComponents(path, true);
|
|
4984
|
-
if (idx === void 0)
|
|
5002
|
+
if (idx === void 0) {
|
|
5003
|
+
if (this.isImplicitDirectory(path)) {
|
|
5004
|
+
return this.encodeImplicitDirStatResponse(path);
|
|
5005
|
+
}
|
|
5006
|
+
return { status: CODE_TO_STATUS.ENOENT, data: null };
|
|
5007
|
+
}
|
|
4985
5008
|
}
|
|
4986
5009
|
return this.encodeStatResponse(idx);
|
|
4987
5010
|
}
|
|
@@ -4990,13 +5013,17 @@ var VFSEngine = class {
|
|
|
4990
5013
|
let nlink = inode.nlink;
|
|
4991
5014
|
if (inode.type === INODE_TYPE.DIRECTORY) {
|
|
4992
5015
|
const path = this.readPath(inode.pathOffset, inode.pathLength);
|
|
4993
|
-
const children = this.
|
|
5016
|
+
const children = this.getDirectChildrenWithImplicit(path);
|
|
4994
5017
|
let subdirCount = 0;
|
|
4995
5018
|
for (const child of children) {
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5019
|
+
if (child.type === "implicit") {
|
|
5020
|
+
subdirCount++;
|
|
5021
|
+
} else {
|
|
5022
|
+
const childIdx = this.pathIndex.get(child.path);
|
|
5023
|
+
if (childIdx !== void 0) {
|
|
5024
|
+
const childInode = this.readInode(childIdx);
|
|
5025
|
+
if (childInode.type === INODE_TYPE.DIRECTORY) subdirCount++;
|
|
5026
|
+
}
|
|
5000
5027
|
}
|
|
5001
5028
|
}
|
|
5002
5029
|
nlink = 2 + subdirCount;
|
|
@@ -5022,7 +5049,9 @@ var VFSEngine = class {
|
|
|
5022
5049
|
if (recursive) {
|
|
5023
5050
|
return this.mkdirRecursive(path);
|
|
5024
5051
|
}
|
|
5025
|
-
if (this.pathIndex.has(path)
|
|
5052
|
+
if (this.pathIndex.has(path) || this.isImplicitDirectory(path)) {
|
|
5053
|
+
return { status: CODE_TO_STATUS.EEXIST, data: null };
|
|
5054
|
+
}
|
|
5026
5055
|
const parentStatus = this.ensureParent(path);
|
|
5027
5056
|
if (parentStatus !== 0) return { status: parentStatus, data: null };
|
|
5028
5057
|
const mode = DEFAULT_DIR_MODE & ~(this.umask & 511);
|
|
@@ -5057,7 +5086,26 @@ var VFSEngine = class {
|
|
|
5057
5086
|
path = this.normalizePath(path);
|
|
5058
5087
|
const recursive = (flags & 1) !== 0;
|
|
5059
5088
|
const idx = this.pathIndex.get(path);
|
|
5060
|
-
if (idx === void 0)
|
|
5089
|
+
if (idx === void 0) {
|
|
5090
|
+
if (this.isImplicitDirectory(path)) {
|
|
5091
|
+
const children2 = this.getDirectChildrenWithImplicit(path);
|
|
5092
|
+
if (children2.length > 0) {
|
|
5093
|
+
if (!recursive) return { status: CODE_TO_STATUS.ENOTEMPTY };
|
|
5094
|
+
for (const desc of this.getAllDescendants(path)) {
|
|
5095
|
+
const descIdx = this.pathIndex.get(desc);
|
|
5096
|
+
const descInode = this.readInode(descIdx);
|
|
5097
|
+
this.freeBlockRange(descInode.firstBlock, descInode.blockCount);
|
|
5098
|
+
descInode.type = INODE_TYPE.FREE;
|
|
5099
|
+
this.writeInode(descIdx, descInode);
|
|
5100
|
+
this.pathIndex.delete(desc);
|
|
5101
|
+
}
|
|
5102
|
+
this.pathIndexGen++;
|
|
5103
|
+
this.commitPending();
|
|
5104
|
+
}
|
|
5105
|
+
return { status: 0 };
|
|
5106
|
+
}
|
|
5107
|
+
return { status: CODE_TO_STATUS.ENOENT };
|
|
5108
|
+
}
|
|
5061
5109
|
const inode = this.readInode(idx);
|
|
5062
5110
|
if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR };
|
|
5063
5111
|
const children = this.getDirectChildren(path);
|
|
@@ -5075,6 +5123,7 @@ var VFSEngine = class {
|
|
|
5075
5123
|
inode.type = INODE_TYPE.FREE;
|
|
5076
5124
|
this.writeInode(idx, inode);
|
|
5077
5125
|
this.pathIndex.delete(path);
|
|
5126
|
+
this.pathIndexGen++;
|
|
5078
5127
|
if (idx < this.freeInodeHint) this.freeInodeHint = idx;
|
|
5079
5128
|
this.commitPending();
|
|
5080
5129
|
return { status: 0 };
|
|
@@ -5083,20 +5132,33 @@ var VFSEngine = class {
|
|
|
5083
5132
|
readdir(path, flags = 0) {
|
|
5084
5133
|
path = this.normalizePath(path);
|
|
5085
5134
|
const resolved = this.resolvePathFull(path, true);
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5135
|
+
let effectiveDirPath;
|
|
5136
|
+
if (resolved) {
|
|
5137
|
+
const inode = this.readInode(resolved.idx);
|
|
5138
|
+
if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR, data: null };
|
|
5139
|
+
effectiveDirPath = resolved.resolvedPath;
|
|
5140
|
+
} else if (this.isImplicitDirectory(path)) {
|
|
5141
|
+
effectiveDirPath = path;
|
|
5142
|
+
} else {
|
|
5143
|
+
return { status: CODE_TO_STATUS.ENOENT, data: null };
|
|
5144
|
+
}
|
|
5089
5145
|
const withFileTypes = (flags & 1) !== 0;
|
|
5090
|
-
const children = this.
|
|
5146
|
+
const children = this.getDirectChildrenWithImplicit(effectiveDirPath);
|
|
5091
5147
|
if (withFileTypes) {
|
|
5092
5148
|
let totalSize2 = 4;
|
|
5093
5149
|
const entries = [];
|
|
5094
|
-
for (const
|
|
5095
|
-
const name =
|
|
5150
|
+
for (const child of children) {
|
|
5151
|
+
const name = child.path.substring(child.path.lastIndexOf("/") + 1);
|
|
5096
5152
|
const nameBytes = encoder10.encode(name);
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5153
|
+
let type;
|
|
5154
|
+
if (child.type === "implicit") {
|
|
5155
|
+
type = INODE_TYPE.DIRECTORY;
|
|
5156
|
+
} else {
|
|
5157
|
+
const childIdx = this.pathIndex.get(child.path);
|
|
5158
|
+
const childInode = this.readInode(childIdx);
|
|
5159
|
+
type = childInode.type;
|
|
5160
|
+
}
|
|
5161
|
+
entries.push({ name: nameBytes, type });
|
|
5100
5162
|
totalSize2 += 2 + nameBytes.byteLength + 1;
|
|
5101
5163
|
}
|
|
5102
5164
|
const buf2 = new Uint8Array(totalSize2);
|
|
@@ -5114,8 +5176,8 @@ var VFSEngine = class {
|
|
|
5114
5176
|
}
|
|
5115
5177
|
let totalSize = 4;
|
|
5116
5178
|
const nameEntries = [];
|
|
5117
|
-
for (const
|
|
5118
|
-
const name =
|
|
5179
|
+
for (const child of children) {
|
|
5180
|
+
const name = child.path.substring(child.path.lastIndexOf("/") + 1);
|
|
5119
5181
|
const nameBytes = encoder10.encode(name);
|
|
5120
5182
|
nameEntries.push(nameBytes);
|
|
5121
5183
|
totalSize += 2 + nameBytes.byteLength;
|
|
@@ -5156,6 +5218,7 @@ var VFSEngine = class {
|
|
|
5156
5218
|
this.writeInode(idx, inode);
|
|
5157
5219
|
this.pathIndex.delete(oldPath);
|
|
5158
5220
|
this.pathIndex.set(newPath, idx);
|
|
5221
|
+
this.pathIndexGen++;
|
|
5159
5222
|
if (inode.type === INODE_TYPE.DIRECTORY) {
|
|
5160
5223
|
const prefix = oldPath === "/" ? "/" : oldPath + "/";
|
|
5161
5224
|
const toRename = [];
|
|
@@ -5184,7 +5247,7 @@ var VFSEngine = class {
|
|
|
5184
5247
|
path = this.normalizePath(path);
|
|
5185
5248
|
const idx = this.resolvePathComponents(path, true);
|
|
5186
5249
|
const buf = new Uint8Array(1);
|
|
5187
|
-
buf[0] = idx !== void 0 ? 1 : 0;
|
|
5250
|
+
buf[0] = idx !== void 0 || this.isImplicitDirectory(path) ? 1 : 0;
|
|
5188
5251
|
return { status: 0, data: buf };
|
|
5189
5252
|
}
|
|
5190
5253
|
// ---- TRUNCATE ----
|
|
@@ -5287,7 +5350,10 @@ var VFSEngine = class {
|
|
|
5287
5350
|
access(path, mode = 0) {
|
|
5288
5351
|
path = this.normalizePath(path);
|
|
5289
5352
|
const idx = this.resolvePathComponents(path, true);
|
|
5290
|
-
if (idx === void 0)
|
|
5353
|
+
if (idx === void 0) {
|
|
5354
|
+
if (this.isImplicitDirectory(path)) return { status: 0 };
|
|
5355
|
+
return { status: CODE_TO_STATUS.ENOENT };
|
|
5356
|
+
}
|
|
5291
5357
|
if (mode === 0) return { status: 0 };
|
|
5292
5358
|
if (!this.strictPermissions) return { status: 0 };
|
|
5293
5359
|
const inode = this.readInode(idx);
|
|
@@ -5307,7 +5373,12 @@ var VFSEngine = class {
|
|
|
5307
5373
|
realpath(path) {
|
|
5308
5374
|
path = this.normalizePath(path);
|
|
5309
5375
|
const idx = this.resolvePathComponents(path, true);
|
|
5310
|
-
if (idx === void 0)
|
|
5376
|
+
if (idx === void 0) {
|
|
5377
|
+
if (this.isImplicitDirectory(path)) {
|
|
5378
|
+
return { status: 0, data: encoder10.encode(path) };
|
|
5379
|
+
}
|
|
5380
|
+
return { status: CODE_TO_STATUS.ENOENT, data: null };
|
|
5381
|
+
}
|
|
5311
5382
|
const inode = this.readInode(idx);
|
|
5312
5383
|
const resolvedPath = this.readPath(inode.pathOffset, inode.pathLength);
|
|
5313
5384
|
return { status: 0, data: encoder10.encode(resolvedPath) };
|
|
@@ -5496,6 +5567,7 @@ var VFSEngine = class {
|
|
|
5496
5567
|
fstat(fd) {
|
|
5497
5568
|
const entry = this.fdTable.get(fd);
|
|
5498
5569
|
if (!entry) return { status: CODE_TO_STATUS.EBADF, data: null };
|
|
5570
|
+
if (entry.implicitPath) return this.encodeImplicitDirStatResponse(entry.implicitPath);
|
|
5499
5571
|
return this.encodeStatResponse(entry.inodeIdx);
|
|
5500
5572
|
}
|
|
5501
5573
|
// ---- FTRUNCATE ----
|
|
@@ -5518,6 +5590,7 @@ var VFSEngine = class {
|
|
|
5518
5590
|
fchmod(fd, mode) {
|
|
5519
5591
|
const entry = this.fdTable.get(fd);
|
|
5520
5592
|
if (!entry) return { status: CODE_TO_STATUS.EBADF };
|
|
5593
|
+
if (entry.implicitPath) return { status: 0 };
|
|
5521
5594
|
const inode = this.readInode(entry.inodeIdx);
|
|
5522
5595
|
inode.mode = inode.mode & S_IFMT | mode & 4095;
|
|
5523
5596
|
inode.ctime = Date.now();
|
|
@@ -5528,6 +5601,7 @@ var VFSEngine = class {
|
|
|
5528
5601
|
fchown(fd, uid, gid) {
|
|
5529
5602
|
const entry = this.fdTable.get(fd);
|
|
5530
5603
|
if (!entry) return { status: CODE_TO_STATUS.EBADF };
|
|
5604
|
+
if (entry.implicitPath) return { status: 0 };
|
|
5531
5605
|
const inode = this.readInode(entry.inodeIdx);
|
|
5532
5606
|
inode.uid = uid;
|
|
5533
5607
|
inode.gid = gid;
|
|
@@ -5539,6 +5613,7 @@ var VFSEngine = class {
|
|
|
5539
5613
|
futimes(fd, atime, mtime) {
|
|
5540
5614
|
const entry = this.fdTable.get(fd);
|
|
5541
5615
|
if (!entry) return { status: CODE_TO_STATUS.EBADF };
|
|
5616
|
+
if (entry.implicitPath) return { status: 0 };
|
|
5542
5617
|
const inode = this.readInode(entry.inodeIdx);
|
|
5543
5618
|
inode.atime = atime;
|
|
5544
5619
|
inode.mtime = mtime;
|
|
@@ -5550,7 +5625,16 @@ var VFSEngine = class {
|
|
|
5550
5625
|
opendir(path, tabId) {
|
|
5551
5626
|
path = this.normalizePath(path);
|
|
5552
5627
|
const idx = this.resolvePathComponents(path, true);
|
|
5553
|
-
if (idx === void 0)
|
|
5628
|
+
if (idx === void 0) {
|
|
5629
|
+
if (this.isImplicitDirectory(path)) {
|
|
5630
|
+
const fd2 = this.nextFd++;
|
|
5631
|
+
this.fdTable.set(fd2, { tabId, inodeIdx: -1, position: 0, flags: 0, implicitPath: path });
|
|
5632
|
+
const buf2 = new Uint8Array(4);
|
|
5633
|
+
new DataView(buf2.buffer).setUint32(0, fd2, true);
|
|
5634
|
+
return { status: 0, data: buf2 };
|
|
5635
|
+
}
|
|
5636
|
+
return { status: CODE_TO_STATUS.ENOENT, data: null };
|
|
5637
|
+
}
|
|
5554
5638
|
const inode = this.readInode(idx);
|
|
5555
5639
|
if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR, data: null };
|
|
5556
5640
|
const fd = this.nextFd++;
|
|
@@ -5589,6 +5673,106 @@ var VFSEngine = class {
|
|
|
5589
5673
|
}
|
|
5590
5674
|
return children.sort();
|
|
5591
5675
|
}
|
|
5676
|
+
/**
|
|
5677
|
+
* Rebuild the set of all implicit directory paths.
|
|
5678
|
+
* An implicit directory is any ancestor path of a file/symlink in pathIndex
|
|
5679
|
+
* that doesn't itself have an explicit inode entry.
|
|
5680
|
+
* Only rebuilt when pathIndex has changed (tracked via generation counter).
|
|
5681
|
+
*/
|
|
5682
|
+
rebuildImplicitDirs() {
|
|
5683
|
+
if (this.implicitDirsGen === this.pathIndexGen) return;
|
|
5684
|
+
const now = Date.now();
|
|
5685
|
+
const prev = this.implicitDirs;
|
|
5686
|
+
this.implicitDirs = /* @__PURE__ */ new Map();
|
|
5687
|
+
for (const filePath of this.pathIndex.keys()) {
|
|
5688
|
+
let pos = filePath.length;
|
|
5689
|
+
while (true) {
|
|
5690
|
+
pos = filePath.lastIndexOf("/", pos - 1);
|
|
5691
|
+
if (pos <= 0) break;
|
|
5692
|
+
const ancestor = filePath.substring(0, pos);
|
|
5693
|
+
if (this.implicitDirs.has(ancestor)) break;
|
|
5694
|
+
if (!this.pathIndex.has(ancestor)) {
|
|
5695
|
+
this.implicitDirs.set(ancestor, prev.get(ancestor) ?? now);
|
|
5696
|
+
}
|
|
5697
|
+
}
|
|
5698
|
+
}
|
|
5699
|
+
this.implicitDirsGen = this.pathIndexGen;
|
|
5700
|
+
}
|
|
5701
|
+
/**
|
|
5702
|
+
* Check if a path is an implicit directory (exists because files exist under it,
|
|
5703
|
+
* but no explicit directory inode was created for it).
|
|
5704
|
+
*/
|
|
5705
|
+
isImplicitDirectory(path) {
|
|
5706
|
+
if (path === "/") return false;
|
|
5707
|
+
this.rebuildImplicitDirs();
|
|
5708
|
+
return this.implicitDirs.has(path);
|
|
5709
|
+
}
|
|
5710
|
+
/**
|
|
5711
|
+
* Get direct children of a directory path, including implicit subdirectories.
|
|
5712
|
+
* Returns unique child full paths. Each entry is tagged with whether it's a
|
|
5713
|
+
* real inode or an implicit directory.
|
|
5714
|
+
*/
|
|
5715
|
+
getDirectChildrenWithImplicit(dirPath) {
|
|
5716
|
+
const prefix = dirPath === "/" ? "/" : dirPath + "/";
|
|
5717
|
+
const childNames = /* @__PURE__ */ new Map();
|
|
5718
|
+
for (const path of this.pathIndex.keys()) {
|
|
5719
|
+
if (path === dirPath) continue;
|
|
5720
|
+
if (!path.startsWith(prefix)) continue;
|
|
5721
|
+
const rest = path.substring(prefix.length);
|
|
5722
|
+
const slashPos = rest.indexOf("/");
|
|
5723
|
+
if (slashPos === -1) {
|
|
5724
|
+
childNames.set(rest, "real");
|
|
5725
|
+
} else {
|
|
5726
|
+
const childName = rest.substring(0, slashPos);
|
|
5727
|
+
if (!childNames.has(childName)) {
|
|
5728
|
+
const childFullPath = prefix + childName;
|
|
5729
|
+
childNames.set(childName, this.pathIndex.has(childFullPath) ? "real" : "implicit");
|
|
5730
|
+
}
|
|
5731
|
+
}
|
|
5732
|
+
}
|
|
5733
|
+
const result = [];
|
|
5734
|
+
for (const [name, type] of childNames) {
|
|
5735
|
+
result.push({ path: prefix + name, type });
|
|
5736
|
+
}
|
|
5737
|
+
result.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
5738
|
+
return result;
|
|
5739
|
+
}
|
|
5740
|
+
/**
|
|
5741
|
+
* Encode a synthetic stat response for an implicit directory.
|
|
5742
|
+
* Returns directory stats with default mode, zero size, current timestamps.
|
|
5743
|
+
*/
|
|
5744
|
+
encodeImplicitDirStatResponse(path) {
|
|
5745
|
+
this.rebuildImplicitDirs();
|
|
5746
|
+
const ts = this.implicitDirs.get(path) ?? Date.now();
|
|
5747
|
+
const mode = DEFAULT_DIR_MODE & ~(this.umask & 511);
|
|
5748
|
+
const children = this.getDirectChildrenWithImplicit(path);
|
|
5749
|
+
let subdirCount = 0;
|
|
5750
|
+
for (const child of children) {
|
|
5751
|
+
if (child.type === "implicit") {
|
|
5752
|
+
subdirCount++;
|
|
5753
|
+
} else {
|
|
5754
|
+
const childIdx = this.pathIndex.get(child.path);
|
|
5755
|
+
if (childIdx !== void 0) {
|
|
5756
|
+
const childInode = this.readInode(childIdx);
|
|
5757
|
+
if (childInode.type === INODE_TYPE.DIRECTORY) subdirCount++;
|
|
5758
|
+
}
|
|
5759
|
+
}
|
|
5760
|
+
}
|
|
5761
|
+
const nlink = 2 + subdirCount;
|
|
5762
|
+
const buf = new Uint8Array(53);
|
|
5763
|
+
const view = new DataView(buf.buffer);
|
|
5764
|
+
view.setUint8(0, INODE_TYPE.DIRECTORY);
|
|
5765
|
+
view.setUint32(1, mode, true);
|
|
5766
|
+
view.setFloat64(5, 0, true);
|
|
5767
|
+
view.setFloat64(13, ts, true);
|
|
5768
|
+
view.setFloat64(21, ts, true);
|
|
5769
|
+
view.setFloat64(29, ts, true);
|
|
5770
|
+
view.setUint32(37, this.processUid, true);
|
|
5771
|
+
view.setUint32(41, this.processGid, true);
|
|
5772
|
+
view.setUint32(45, 0, true);
|
|
5773
|
+
view.setUint32(49, nlink, true);
|
|
5774
|
+
return { status: 0, data: buf };
|
|
5775
|
+
}
|
|
5592
5776
|
getAllDescendants(dirPath) {
|
|
5593
5777
|
const prefix = dirPath === "/" ? "/" : dirPath + "/";
|
|
5594
5778
|
const descendants = [];
|
|
@@ -5606,7 +5790,10 @@ var VFSEngine = class {
|
|
|
5606
5790
|
if (lastSlash <= 0) return 0;
|
|
5607
5791
|
const parentPath = path.substring(0, lastSlash);
|
|
5608
5792
|
const parentIdx = this.pathIndex.get(parentPath);
|
|
5609
|
-
if (parentIdx === void 0)
|
|
5793
|
+
if (parentIdx === void 0) {
|
|
5794
|
+
if (this.isImplicitDirectory(parentPath)) return 0;
|
|
5795
|
+
return CODE_TO_STATUS.ENOENT;
|
|
5796
|
+
}
|
|
5610
5797
|
const parentInode = this.readInode(parentIdx);
|
|
5611
5798
|
if (parentInode.type !== INODE_TYPE.DIRECTORY) return CODE_TO_STATUS.ENOTDIR;
|
|
5612
5799
|
return 0;
|