@componentor/fs 3.0.45 → 3.0.47
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.d.mts +27 -1
- package/dist/index.js +282 -45
- 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 +22 -0
|
@@ -154,6 +154,16 @@ var VFSEngine = class {
|
|
|
154
154
|
superblockDirty = false;
|
|
155
155
|
// Free inode hint — skip O(n) scan
|
|
156
156
|
freeInodeHint = 0;
|
|
157
|
+
// Implicit directory support — tracks all directory prefixes implied by file paths.
|
|
158
|
+
// Rebuilt lazily when pathIndex changes (tracked via generation counter).
|
|
159
|
+
// Map value is the stable timestamp (ms since epoch) assigned when the implicit
|
|
160
|
+
// dir was first discovered, so that stat() returns consistent mtime/ctime/atime
|
|
161
|
+
// across repeated calls.
|
|
162
|
+
implicitDirs = /* @__PURE__ */ new Map();
|
|
163
|
+
implicitDirsGen = -1;
|
|
164
|
+
// generation when implicitDirs was last rebuilt
|
|
165
|
+
pathIndexGen = 0;
|
|
166
|
+
// bumped on every pathIndex mutation
|
|
157
167
|
// Configurable upper bounds
|
|
158
168
|
maxInodes = 4e6;
|
|
159
169
|
maxBlocks = 4e6;
|
|
@@ -438,6 +448,7 @@ var VFSEngine = class {
|
|
|
438
448
|
}
|
|
439
449
|
this.pathIndex.set(path, i);
|
|
440
450
|
}
|
|
451
|
+
this.pathIndexGen++;
|
|
441
452
|
}
|
|
442
453
|
// ========== Low-level inode I/O ==========
|
|
443
454
|
readInode(idx) {
|
|
@@ -758,6 +769,7 @@ var VFSEngine = class {
|
|
|
758
769
|
};
|
|
759
770
|
this.writeInode(idx, inode);
|
|
760
771
|
this.pathIndex.set(path, idx);
|
|
772
|
+
this.pathIndexGen++;
|
|
761
773
|
return idx;
|
|
762
774
|
}
|
|
763
775
|
// ========== Public API — called by server worker dispatch ==========
|
|
@@ -914,6 +926,7 @@ var VFSEngine = class {
|
|
|
914
926
|
inode.type = INODE_TYPE.FREE;
|
|
915
927
|
this.writeInode(idx, inode);
|
|
916
928
|
this.pathIndex.delete(path);
|
|
929
|
+
this.pathIndexGen++;
|
|
917
930
|
if (idx < this.freeInodeHint) this.freeInodeHint = idx;
|
|
918
931
|
this.commitPending();
|
|
919
932
|
return { status: 0 };
|
|
@@ -922,7 +935,12 @@ var VFSEngine = class {
|
|
|
922
935
|
stat(path) {
|
|
923
936
|
path = this.normalizePath(path);
|
|
924
937
|
const idx = this.resolvePathComponents(path, true);
|
|
925
|
-
if (idx === void 0)
|
|
938
|
+
if (idx === void 0) {
|
|
939
|
+
if (this.isImplicitDirectory(path)) {
|
|
940
|
+
return this.encodeImplicitDirStatResponse(path);
|
|
941
|
+
}
|
|
942
|
+
return { status: CODE_TO_STATUS.ENOENT, data: null };
|
|
943
|
+
}
|
|
926
944
|
return this.encodeStatResponse(idx);
|
|
927
945
|
}
|
|
928
946
|
// ---- LSTAT (no symlink follow for the FINAL component) ----
|
|
@@ -931,7 +949,12 @@ var VFSEngine = class {
|
|
|
931
949
|
let idx = this.resolvePathComponents(path, false);
|
|
932
950
|
if (idx === void 0) {
|
|
933
951
|
idx = this.resolvePathComponents(path, true);
|
|
934
|
-
if (idx === void 0)
|
|
952
|
+
if (idx === void 0) {
|
|
953
|
+
if (this.isImplicitDirectory(path)) {
|
|
954
|
+
return this.encodeImplicitDirStatResponse(path);
|
|
955
|
+
}
|
|
956
|
+
return { status: CODE_TO_STATUS.ENOENT, data: null };
|
|
957
|
+
}
|
|
935
958
|
}
|
|
936
959
|
return this.encodeStatResponse(idx);
|
|
937
960
|
}
|
|
@@ -940,13 +963,17 @@ var VFSEngine = class {
|
|
|
940
963
|
let nlink = inode.nlink;
|
|
941
964
|
if (inode.type === INODE_TYPE.DIRECTORY) {
|
|
942
965
|
const path = this.readPath(inode.pathOffset, inode.pathLength);
|
|
943
|
-
const children = this.
|
|
966
|
+
const children = this.getDirectChildrenWithImplicit(path);
|
|
944
967
|
let subdirCount = 0;
|
|
945
968
|
for (const child of children) {
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
969
|
+
if (child.type === "implicit") {
|
|
970
|
+
subdirCount++;
|
|
971
|
+
} else {
|
|
972
|
+
const childIdx = this.pathIndex.get(child.path);
|
|
973
|
+
if (childIdx !== void 0) {
|
|
974
|
+
const childInode = this.readInode(childIdx);
|
|
975
|
+
if (childInode.type === INODE_TYPE.DIRECTORY) subdirCount++;
|
|
976
|
+
}
|
|
950
977
|
}
|
|
951
978
|
}
|
|
952
979
|
nlink = 2 + subdirCount;
|
|
@@ -972,7 +999,9 @@ var VFSEngine = class {
|
|
|
972
999
|
if (recursive) {
|
|
973
1000
|
return this.mkdirRecursive(path);
|
|
974
1001
|
}
|
|
975
|
-
if (this.pathIndex.has(path)
|
|
1002
|
+
if (this.pathIndex.has(path) || this.isImplicitDirectory(path)) {
|
|
1003
|
+
return { status: CODE_TO_STATUS.EEXIST, data: null };
|
|
1004
|
+
}
|
|
976
1005
|
const parentStatus = this.ensureParent(path);
|
|
977
1006
|
if (parentStatus !== 0) return { status: parentStatus, data: null };
|
|
978
1007
|
const mode = DEFAULT_DIR_MODE & ~(this.umask & 511);
|
|
@@ -1007,7 +1036,26 @@ var VFSEngine = class {
|
|
|
1007
1036
|
path = this.normalizePath(path);
|
|
1008
1037
|
const recursive = (flags & 1) !== 0;
|
|
1009
1038
|
const idx = this.pathIndex.get(path);
|
|
1010
|
-
if (idx === void 0)
|
|
1039
|
+
if (idx === void 0) {
|
|
1040
|
+
if (this.isImplicitDirectory(path)) {
|
|
1041
|
+
const children2 = this.getDirectChildrenWithImplicit(path);
|
|
1042
|
+
if (children2.length > 0) {
|
|
1043
|
+
if (!recursive) return { status: CODE_TO_STATUS.ENOTEMPTY };
|
|
1044
|
+
for (const desc of this.getAllDescendants(path)) {
|
|
1045
|
+
const descIdx = this.pathIndex.get(desc);
|
|
1046
|
+
const descInode = this.readInode(descIdx);
|
|
1047
|
+
this.freeBlockRange(descInode.firstBlock, descInode.blockCount);
|
|
1048
|
+
descInode.type = INODE_TYPE.FREE;
|
|
1049
|
+
this.writeInode(descIdx, descInode);
|
|
1050
|
+
this.pathIndex.delete(desc);
|
|
1051
|
+
}
|
|
1052
|
+
this.pathIndexGen++;
|
|
1053
|
+
this.commitPending();
|
|
1054
|
+
}
|
|
1055
|
+
return { status: 0 };
|
|
1056
|
+
}
|
|
1057
|
+
return { status: CODE_TO_STATUS.ENOENT };
|
|
1058
|
+
}
|
|
1011
1059
|
const inode = this.readInode(idx);
|
|
1012
1060
|
if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR };
|
|
1013
1061
|
const children = this.getDirectChildren(path);
|
|
@@ -1025,6 +1073,7 @@ var VFSEngine = class {
|
|
|
1025
1073
|
inode.type = INODE_TYPE.FREE;
|
|
1026
1074
|
this.writeInode(idx, inode);
|
|
1027
1075
|
this.pathIndex.delete(path);
|
|
1076
|
+
this.pathIndexGen++;
|
|
1028
1077
|
if (idx < this.freeInodeHint) this.freeInodeHint = idx;
|
|
1029
1078
|
this.commitPending();
|
|
1030
1079
|
return { status: 0 };
|
|
@@ -1033,20 +1082,33 @@ var VFSEngine = class {
|
|
|
1033
1082
|
readdir(path, flags = 0) {
|
|
1034
1083
|
path = this.normalizePath(path);
|
|
1035
1084
|
const resolved = this.resolvePathFull(path, true);
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1085
|
+
let effectiveDirPath;
|
|
1086
|
+
if (resolved) {
|
|
1087
|
+
const inode = this.readInode(resolved.idx);
|
|
1088
|
+
if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR, data: null };
|
|
1089
|
+
effectiveDirPath = resolved.resolvedPath;
|
|
1090
|
+
} else if (this.isImplicitDirectory(path)) {
|
|
1091
|
+
effectiveDirPath = path;
|
|
1092
|
+
} else {
|
|
1093
|
+
return { status: CODE_TO_STATUS.ENOENT, data: null };
|
|
1094
|
+
}
|
|
1039
1095
|
const withFileTypes = (flags & 1) !== 0;
|
|
1040
|
-
const children = this.
|
|
1096
|
+
const children = this.getDirectChildrenWithImplicit(effectiveDirPath);
|
|
1041
1097
|
if (withFileTypes) {
|
|
1042
1098
|
let totalSize2 = 4;
|
|
1043
1099
|
const entries = [];
|
|
1044
|
-
for (const
|
|
1045
|
-
const name =
|
|
1100
|
+
for (const child of children) {
|
|
1101
|
+
const name = child.path.substring(child.path.lastIndexOf("/") + 1);
|
|
1046
1102
|
const nameBytes = encoder.encode(name);
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1103
|
+
let type;
|
|
1104
|
+
if (child.type === "implicit") {
|
|
1105
|
+
type = INODE_TYPE.DIRECTORY;
|
|
1106
|
+
} else {
|
|
1107
|
+
const childIdx = this.pathIndex.get(child.path);
|
|
1108
|
+
const childInode = this.readInode(childIdx);
|
|
1109
|
+
type = childInode.type;
|
|
1110
|
+
}
|
|
1111
|
+
entries.push({ name: nameBytes, type });
|
|
1050
1112
|
totalSize2 += 2 + nameBytes.byteLength + 1;
|
|
1051
1113
|
}
|
|
1052
1114
|
const buf2 = new Uint8Array(totalSize2);
|
|
@@ -1064,8 +1126,8 @@ var VFSEngine = class {
|
|
|
1064
1126
|
}
|
|
1065
1127
|
let totalSize = 4;
|
|
1066
1128
|
const nameEntries = [];
|
|
1067
|
-
for (const
|
|
1068
|
-
const name =
|
|
1129
|
+
for (const child of children) {
|
|
1130
|
+
const name = child.path.substring(child.path.lastIndexOf("/") + 1);
|
|
1069
1131
|
const nameBytes = encoder.encode(name);
|
|
1070
1132
|
nameEntries.push(nameBytes);
|
|
1071
1133
|
totalSize += 2 + nameBytes.byteLength;
|
|
@@ -1106,6 +1168,7 @@ var VFSEngine = class {
|
|
|
1106
1168
|
this.writeInode(idx, inode);
|
|
1107
1169
|
this.pathIndex.delete(oldPath);
|
|
1108
1170
|
this.pathIndex.set(newPath, idx);
|
|
1171
|
+
this.pathIndexGen++;
|
|
1109
1172
|
if (inode.type === INODE_TYPE.DIRECTORY) {
|
|
1110
1173
|
const prefix = oldPath === "/" ? "/" : oldPath + "/";
|
|
1111
1174
|
const toRename = [];
|
|
@@ -1134,7 +1197,7 @@ var VFSEngine = class {
|
|
|
1134
1197
|
path = this.normalizePath(path);
|
|
1135
1198
|
const idx = this.resolvePathComponents(path, true);
|
|
1136
1199
|
const buf = new Uint8Array(1);
|
|
1137
|
-
buf[0] = idx !== void 0 ? 1 : 0;
|
|
1200
|
+
buf[0] = idx !== void 0 || this.isImplicitDirectory(path) ? 1 : 0;
|
|
1138
1201
|
return { status: 0, data: buf };
|
|
1139
1202
|
}
|
|
1140
1203
|
// ---- TRUNCATE ----
|
|
@@ -1237,7 +1300,10 @@ var VFSEngine = class {
|
|
|
1237
1300
|
access(path, mode = 0) {
|
|
1238
1301
|
path = this.normalizePath(path);
|
|
1239
1302
|
const idx = this.resolvePathComponents(path, true);
|
|
1240
|
-
if (idx === void 0)
|
|
1303
|
+
if (idx === void 0) {
|
|
1304
|
+
if (this.isImplicitDirectory(path)) return { status: 0 };
|
|
1305
|
+
return { status: CODE_TO_STATUS.ENOENT };
|
|
1306
|
+
}
|
|
1241
1307
|
if (mode === 0) return { status: 0 };
|
|
1242
1308
|
if (!this.strictPermissions) return { status: 0 };
|
|
1243
1309
|
const inode = this.readInode(idx);
|
|
@@ -1257,7 +1323,12 @@ var VFSEngine = class {
|
|
|
1257
1323
|
realpath(path) {
|
|
1258
1324
|
path = this.normalizePath(path);
|
|
1259
1325
|
const idx = this.resolvePathComponents(path, true);
|
|
1260
|
-
if (idx === void 0)
|
|
1326
|
+
if (idx === void 0) {
|
|
1327
|
+
if (this.isImplicitDirectory(path)) {
|
|
1328
|
+
return { status: 0, data: encoder.encode(path) };
|
|
1329
|
+
}
|
|
1330
|
+
return { status: CODE_TO_STATUS.ENOENT, data: null };
|
|
1331
|
+
}
|
|
1261
1332
|
const inode = this.readInode(idx);
|
|
1262
1333
|
const resolvedPath = this.readPath(inode.pathOffset, inode.pathLength);
|
|
1263
1334
|
return { status: 0, data: encoder.encode(resolvedPath) };
|
|
@@ -1446,6 +1517,7 @@ var VFSEngine = class {
|
|
|
1446
1517
|
fstat(fd) {
|
|
1447
1518
|
const entry = this.fdTable.get(fd);
|
|
1448
1519
|
if (!entry) return { status: CODE_TO_STATUS.EBADF, data: null };
|
|
1520
|
+
if (entry.implicitPath) return this.encodeImplicitDirStatResponse(entry.implicitPath);
|
|
1449
1521
|
return this.encodeStatResponse(entry.inodeIdx);
|
|
1450
1522
|
}
|
|
1451
1523
|
// ---- FTRUNCATE ----
|
|
@@ -1468,6 +1540,7 @@ var VFSEngine = class {
|
|
|
1468
1540
|
fchmod(fd, mode) {
|
|
1469
1541
|
const entry = this.fdTable.get(fd);
|
|
1470
1542
|
if (!entry) return { status: CODE_TO_STATUS.EBADF };
|
|
1543
|
+
if (entry.implicitPath) return { status: 0 };
|
|
1471
1544
|
const inode = this.readInode(entry.inodeIdx);
|
|
1472
1545
|
inode.mode = inode.mode & S_IFMT | mode & 4095;
|
|
1473
1546
|
inode.ctime = Date.now();
|
|
@@ -1478,6 +1551,7 @@ var VFSEngine = class {
|
|
|
1478
1551
|
fchown(fd, uid, gid) {
|
|
1479
1552
|
const entry = this.fdTable.get(fd);
|
|
1480
1553
|
if (!entry) return { status: CODE_TO_STATUS.EBADF };
|
|
1554
|
+
if (entry.implicitPath) return { status: 0 };
|
|
1481
1555
|
const inode = this.readInode(entry.inodeIdx);
|
|
1482
1556
|
inode.uid = uid;
|
|
1483
1557
|
inode.gid = gid;
|
|
@@ -1489,6 +1563,7 @@ var VFSEngine = class {
|
|
|
1489
1563
|
futimes(fd, atime, mtime) {
|
|
1490
1564
|
const entry = this.fdTable.get(fd);
|
|
1491
1565
|
if (!entry) return { status: CODE_TO_STATUS.EBADF };
|
|
1566
|
+
if (entry.implicitPath) return { status: 0 };
|
|
1492
1567
|
const inode = this.readInode(entry.inodeIdx);
|
|
1493
1568
|
inode.atime = atime;
|
|
1494
1569
|
inode.mtime = mtime;
|
|
@@ -1500,7 +1575,16 @@ var VFSEngine = class {
|
|
|
1500
1575
|
opendir(path, tabId2) {
|
|
1501
1576
|
path = this.normalizePath(path);
|
|
1502
1577
|
const idx = this.resolvePathComponents(path, true);
|
|
1503
|
-
if (idx === void 0)
|
|
1578
|
+
if (idx === void 0) {
|
|
1579
|
+
if (this.isImplicitDirectory(path)) {
|
|
1580
|
+
const fd2 = this.nextFd++;
|
|
1581
|
+
this.fdTable.set(fd2, { tabId: tabId2, inodeIdx: -1, position: 0, flags: 0, implicitPath: path });
|
|
1582
|
+
const buf2 = new Uint8Array(4);
|
|
1583
|
+
new DataView(buf2.buffer).setUint32(0, fd2, true);
|
|
1584
|
+
return { status: 0, data: buf2 };
|
|
1585
|
+
}
|
|
1586
|
+
return { status: CODE_TO_STATUS.ENOENT, data: null };
|
|
1587
|
+
}
|
|
1504
1588
|
const inode = this.readInode(idx);
|
|
1505
1589
|
if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR, data: null };
|
|
1506
1590
|
const fd = this.nextFd++;
|
|
@@ -1539,6 +1623,106 @@ var VFSEngine = class {
|
|
|
1539
1623
|
}
|
|
1540
1624
|
return children.sort();
|
|
1541
1625
|
}
|
|
1626
|
+
/**
|
|
1627
|
+
* Rebuild the set of all implicit directory paths.
|
|
1628
|
+
* An implicit directory is any ancestor path of a file/symlink in pathIndex
|
|
1629
|
+
* that doesn't itself have an explicit inode entry.
|
|
1630
|
+
* Only rebuilt when pathIndex has changed (tracked via generation counter).
|
|
1631
|
+
*/
|
|
1632
|
+
rebuildImplicitDirs() {
|
|
1633
|
+
if (this.implicitDirsGen === this.pathIndexGen) return;
|
|
1634
|
+
const now = Date.now();
|
|
1635
|
+
const prev = this.implicitDirs;
|
|
1636
|
+
this.implicitDirs = /* @__PURE__ */ new Map();
|
|
1637
|
+
for (const filePath of this.pathIndex.keys()) {
|
|
1638
|
+
let pos = filePath.length;
|
|
1639
|
+
while (true) {
|
|
1640
|
+
pos = filePath.lastIndexOf("/", pos - 1);
|
|
1641
|
+
if (pos <= 0) break;
|
|
1642
|
+
const ancestor = filePath.substring(0, pos);
|
|
1643
|
+
if (this.implicitDirs.has(ancestor)) break;
|
|
1644
|
+
if (!this.pathIndex.has(ancestor)) {
|
|
1645
|
+
this.implicitDirs.set(ancestor, prev.get(ancestor) ?? now);
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
this.implicitDirsGen = this.pathIndexGen;
|
|
1650
|
+
}
|
|
1651
|
+
/**
|
|
1652
|
+
* Check if a path is an implicit directory (exists because files exist under it,
|
|
1653
|
+
* but no explicit directory inode was created for it).
|
|
1654
|
+
*/
|
|
1655
|
+
isImplicitDirectory(path) {
|
|
1656
|
+
if (path === "/") return false;
|
|
1657
|
+
this.rebuildImplicitDirs();
|
|
1658
|
+
return this.implicitDirs.has(path);
|
|
1659
|
+
}
|
|
1660
|
+
/**
|
|
1661
|
+
* Get direct children of a directory path, including implicit subdirectories.
|
|
1662
|
+
* Returns unique child full paths. Each entry is tagged with whether it's a
|
|
1663
|
+
* real inode or an implicit directory.
|
|
1664
|
+
*/
|
|
1665
|
+
getDirectChildrenWithImplicit(dirPath) {
|
|
1666
|
+
const prefix = dirPath === "/" ? "/" : dirPath + "/";
|
|
1667
|
+
const childNames = /* @__PURE__ */ new Map();
|
|
1668
|
+
for (const path of this.pathIndex.keys()) {
|
|
1669
|
+
if (path === dirPath) continue;
|
|
1670
|
+
if (!path.startsWith(prefix)) continue;
|
|
1671
|
+
const rest = path.substring(prefix.length);
|
|
1672
|
+
const slashPos = rest.indexOf("/");
|
|
1673
|
+
if (slashPos === -1) {
|
|
1674
|
+
childNames.set(rest, "real");
|
|
1675
|
+
} else {
|
|
1676
|
+
const childName = rest.substring(0, slashPos);
|
|
1677
|
+
if (!childNames.has(childName)) {
|
|
1678
|
+
const childFullPath = prefix + childName;
|
|
1679
|
+
childNames.set(childName, this.pathIndex.has(childFullPath) ? "real" : "implicit");
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
const result = [];
|
|
1684
|
+
for (const [name, type] of childNames) {
|
|
1685
|
+
result.push({ path: prefix + name, type });
|
|
1686
|
+
}
|
|
1687
|
+
result.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
1688
|
+
return result;
|
|
1689
|
+
}
|
|
1690
|
+
/**
|
|
1691
|
+
* Encode a synthetic stat response for an implicit directory.
|
|
1692
|
+
* Returns directory stats with default mode, zero size, current timestamps.
|
|
1693
|
+
*/
|
|
1694
|
+
encodeImplicitDirStatResponse(path) {
|
|
1695
|
+
this.rebuildImplicitDirs();
|
|
1696
|
+
const ts = this.implicitDirs.get(path) ?? Date.now();
|
|
1697
|
+
const mode = DEFAULT_DIR_MODE & ~(this.umask & 511);
|
|
1698
|
+
const children = this.getDirectChildrenWithImplicit(path);
|
|
1699
|
+
let subdirCount = 0;
|
|
1700
|
+
for (const child of children) {
|
|
1701
|
+
if (child.type === "implicit") {
|
|
1702
|
+
subdirCount++;
|
|
1703
|
+
} else {
|
|
1704
|
+
const childIdx = this.pathIndex.get(child.path);
|
|
1705
|
+
if (childIdx !== void 0) {
|
|
1706
|
+
const childInode = this.readInode(childIdx);
|
|
1707
|
+
if (childInode.type === INODE_TYPE.DIRECTORY) subdirCount++;
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
const nlink = 2 + subdirCount;
|
|
1712
|
+
const buf = new Uint8Array(53);
|
|
1713
|
+
const view = new DataView(buf.buffer);
|
|
1714
|
+
view.setUint8(0, INODE_TYPE.DIRECTORY);
|
|
1715
|
+
view.setUint32(1, mode, true);
|
|
1716
|
+
view.setFloat64(5, 0, true);
|
|
1717
|
+
view.setFloat64(13, ts, true);
|
|
1718
|
+
view.setFloat64(21, ts, true);
|
|
1719
|
+
view.setFloat64(29, ts, true);
|
|
1720
|
+
view.setUint32(37, this.processUid, true);
|
|
1721
|
+
view.setUint32(41, this.processGid, true);
|
|
1722
|
+
view.setUint32(45, 0, true);
|
|
1723
|
+
view.setUint32(49, nlink, true);
|
|
1724
|
+
return { status: 0, data: buf };
|
|
1725
|
+
}
|
|
1542
1726
|
getAllDescendants(dirPath) {
|
|
1543
1727
|
const prefix = dirPath === "/" ? "/" : dirPath + "/";
|
|
1544
1728
|
const descendants = [];
|
|
@@ -1556,7 +1740,10 @@ var VFSEngine = class {
|
|
|
1556
1740
|
if (lastSlash <= 0) return 0;
|
|
1557
1741
|
const parentPath = path.substring(0, lastSlash);
|
|
1558
1742
|
const parentIdx = this.pathIndex.get(parentPath);
|
|
1559
|
-
if (parentIdx === void 0)
|
|
1743
|
+
if (parentIdx === void 0) {
|
|
1744
|
+
if (this.isImplicitDirectory(parentPath)) return 0;
|
|
1745
|
+
return CODE_TO_STATUS.ENOENT;
|
|
1746
|
+
}
|
|
1560
1747
|
const parentInode = this.readInode(parentIdx);
|
|
1561
1748
|
if (parentInode.type !== INODE_TYPE.DIRECTORY) return CODE_TO_STATUS.ENOTDIR;
|
|
1562
1749
|
return 0;
|