@ai-ecoverse/slicc-kernel 1.34.1 → 1.36.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/README.md +19 -3
- package/dist/driver-worker.js.map +2 -2
- package/dist/driver.js.map +2 -2
- package/dist/kernel-worker.js +358 -76
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node-driver-worker.js.map +2 -2
- package/dist/node-process-worker.js +158 -8
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +358 -76
- package/dist/node.js.map +3 -3
- package/dist/process-worker.js +158 -8
- package/dist/process-worker.js.map +3 -3
- package/package.json +2 -2
package/dist/kernel-worker.js
CHANGED
|
@@ -448,11 +448,41 @@ var OpfsFs = class {
|
|
|
448
448
|
const fallback = directory || EXECUTABLE.test(path) ? 493 : 420;
|
|
449
449
|
return (directory ? S_IFDIR : S_IFREG) | (meta?.mode ?? fallback);
|
|
450
450
|
}
|
|
451
|
+
dirTimes = /* @__PURE__ */ new Map();
|
|
452
|
+
dirDirty = /* @__PURE__ */ new Set();
|
|
453
|
+
dirFlush;
|
|
454
|
+
touch(...dirs) {
|
|
455
|
+
const now = Date.now();
|
|
456
|
+
for (const dir of dirs) {
|
|
457
|
+
this.dirTimes.set(dir, now);
|
|
458
|
+
this.dirDirty.add(dir);
|
|
459
|
+
}
|
|
460
|
+
this.dirFlush ??= Promise.resolve().then(() => this.flushDirTimes()).catch(() => void 0).finally(() => {
|
|
461
|
+
this.dirFlush = void 0;
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
async flushDirTimes() {
|
|
465
|
+
for (const path of this.dirDirty) {
|
|
466
|
+
this.dirDirty.delete(path);
|
|
467
|
+
const ms = this.dirTimes.get(path);
|
|
468
|
+
if (ms === void 0) continue;
|
|
469
|
+
await this.meta.update(path, (entry) => ({
|
|
470
|
+
...entry,
|
|
471
|
+
path,
|
|
472
|
+
mtimeMs: ms,
|
|
473
|
+
mtimeFor: 0,
|
|
474
|
+
ctimeMs: ms
|
|
475
|
+
}));
|
|
476
|
+
if (this.dirTimes.get(path) === ms) this.dirTimes.delete(path);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
451
479
|
async statOf(path, handle, meta) {
|
|
452
480
|
const directory = handle.kind === "directory";
|
|
453
481
|
const file = directory ? void 0 : await handle.getFile();
|
|
454
482
|
const modified = file?.lastModified ?? 0;
|
|
455
|
-
const
|
|
483
|
+
const touched = directory ? this.dirTimes.get(path) : void 0;
|
|
484
|
+
const kept = meta?.mtimeMs !== void 0 && meta.mtimeFor === modified ? meta.mtimeMs : modified;
|
|
485
|
+
const mtime = touched ?? kept;
|
|
456
486
|
return {
|
|
457
487
|
isFile: !directory,
|
|
458
488
|
isDirectory: directory,
|
|
@@ -461,7 +491,7 @@ var OpfsFs = class {
|
|
|
461
491
|
mode: this.mode(path, directory, meta),
|
|
462
492
|
mtime: new Date(mtime),
|
|
463
493
|
atime: new Date(meta?.atimeMs ?? mtime),
|
|
464
|
-
ctime: new Date(Math.max(meta?.ctimeMs ?? mtime, modified)),
|
|
494
|
+
ctime: new Date(Math.max(touched ?? meta?.ctimeMs ?? mtime, modified)),
|
|
465
495
|
ino: meta?.ino ?? inodeOf(path),
|
|
466
496
|
...this.ranged && !directory ? { ranged: true } : {}
|
|
467
497
|
};
|
|
@@ -538,6 +568,19 @@ var OpfsFs = class {
|
|
|
538
568
|
const handle = await this.existing(path);
|
|
539
569
|
await this.retrying(path, () => positioned(handle, (io) => io.truncate(size)), true);
|
|
540
570
|
}
|
|
571
|
+
async writeSession(path, truncate) {
|
|
572
|
+
const handle = (await this.fileFor(path))[0];
|
|
573
|
+
const writable = await this.retrying(
|
|
574
|
+
path,
|
|
575
|
+
() => handle.createWritable({ keepExistingData: !truncate }),
|
|
576
|
+
true
|
|
577
|
+
);
|
|
578
|
+
return {
|
|
579
|
+
write: (at, bytes) => writable.write({ type: "write", position: at, data: bytes }),
|
|
580
|
+
truncate: (size) => writable.truncate(size),
|
|
581
|
+
close: () => writable.close()
|
|
582
|
+
};
|
|
583
|
+
}
|
|
541
584
|
async readFile(path) {
|
|
542
585
|
return new TextDecoder().decode(await this.readFileBuffer(path));
|
|
543
586
|
}
|
|
@@ -555,10 +598,12 @@ var OpfsFs = class {
|
|
|
555
598
|
const [target, existed] = await this.writeTarget(path);
|
|
556
599
|
const [dir, name2] = await this.parent(target);
|
|
557
600
|
try {
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
601
|
+
const handle = await this.inDir(
|
|
602
|
+
dir,
|
|
603
|
+
(parent) => parent.getFileHandle(name2, { create: true })
|
|
604
|
+
);
|
|
605
|
+
if (!existed) this.touch(parentOf2(target));
|
|
606
|
+
return [handle, existed];
|
|
562
607
|
} catch (err) {
|
|
563
608
|
const code = err?.name === "TypeMismatchError" ? "EISDIR" : null;
|
|
564
609
|
throw code ? fsError(code, path) : translate(err, path);
|
|
@@ -616,6 +661,7 @@ var OpfsFs = class {
|
|
|
616
661
|
const parent = await this.locate(parentOf2(path), true);
|
|
617
662
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
618
663
|
await parent.handle.getDirectoryHandle(baseOf(path), { create: true });
|
|
664
|
+
this.touch(parent.path);
|
|
619
665
|
}
|
|
620
666
|
async rm(path, options = {}) {
|
|
621
667
|
let found;
|
|
@@ -639,6 +685,7 @@ var OpfsFs = class {
|
|
|
639
685
|
this.changed(found.path);
|
|
640
686
|
}
|
|
641
687
|
await this.meta.remove([found.path]);
|
|
688
|
+
this.touch(parentOf2(found.path));
|
|
642
689
|
}
|
|
643
690
|
async rename(from, to) {
|
|
644
691
|
if (from === to) return;
|
|
@@ -670,6 +717,7 @@ var OpfsFs = class {
|
|
|
670
717
|
if (source.link) {
|
|
671
718
|
if (target?.handle) await this.rm(destination);
|
|
672
719
|
await this.meta.move(source.path, destination, carry);
|
|
720
|
+
this.touch(parentOf2(source.path), parent.path);
|
|
673
721
|
return;
|
|
674
722
|
}
|
|
675
723
|
const dir = parent.handle;
|
|
@@ -691,6 +739,7 @@ var OpfsFs = class {
|
|
|
691
739
|
}
|
|
692
740
|
if (copied) await this.restamp(destination, timed);
|
|
693
741
|
this.changed(source.path, destination);
|
|
742
|
+
this.touch(parentOf2(source.path), parent.path);
|
|
694
743
|
}
|
|
695
744
|
async modified(path) {
|
|
696
745
|
const handle = await this.handle(path);
|
|
@@ -754,6 +803,10 @@ var OpfsFs = class {
|
|
|
754
803
|
mtimeMs: now,
|
|
755
804
|
ctimeMs: now
|
|
756
805
|
}));
|
|
806
|
+
this.touch(parent.path);
|
|
807
|
+
}
|
|
808
|
+
async realpath(path, follow) {
|
|
809
|
+
return (await this.locate(path, follow)).path;
|
|
757
810
|
}
|
|
758
811
|
async readlink(path) {
|
|
759
812
|
const found = await this.locate(path, false);
|
|
@@ -791,6 +844,7 @@ var OpfsFs = class {
|
|
|
791
844
|
}
|
|
792
845
|
const handle = found.handle;
|
|
793
846
|
const file = handle.kind === "file" ? await handle.getFile() : void 0;
|
|
847
|
+
this.dirTimes.delete(found.path);
|
|
794
848
|
const ctimeMs = Date.now();
|
|
795
849
|
await this.meta.update(found.path, (entry) => ({
|
|
796
850
|
...entry,
|
|
@@ -4787,6 +4841,7 @@ function withCommandDirs(fs, names) {
|
|
|
4787
4841
|
rename: (from, to) => fs.rename(from, to),
|
|
4788
4842
|
symlink: (target, path) => fs.symlink(target, path),
|
|
4789
4843
|
readlink: (path) => fs.readlink(path),
|
|
4844
|
+
...fs.realpath ? { realpath: fs.realpath.bind(fs) } : {},
|
|
4790
4845
|
chmod: (path, mode) => fs.chmod(path, mode),
|
|
4791
4846
|
utimes: (path, atime, mtime) => fs.utimes(path, atime, mtime),
|
|
4792
4847
|
lutimes: (path, atime, mtime) => lutimesOf(fs, path, atime, mtime),
|
|
@@ -5183,18 +5238,36 @@ function parseSize(text) {
|
|
|
5183
5238
|
return Math.floor(Number(match[1]) * UNITS[match[2].toLowerCase()]);
|
|
5184
5239
|
}
|
|
5185
5240
|
var within3 = (path, target) => path === target || target === "/" || path.startsWith(`${target}/`);
|
|
5241
|
+
var HeldSet = class extends Set {
|
|
5242
|
+
idle;
|
|
5243
|
+
constructor(idle) {
|
|
5244
|
+
super();
|
|
5245
|
+
this.idle = idle;
|
|
5246
|
+
}
|
|
5247
|
+
add(holds) {
|
|
5248
|
+
holds.onIdle = this.idle;
|
|
5249
|
+
return super.add(holds);
|
|
5250
|
+
}
|
|
5251
|
+
delete(holds) {
|
|
5252
|
+
const removed = super.delete(holds);
|
|
5253
|
+
for (const path of holds.keys()) this.idle(path);
|
|
5254
|
+
return removed;
|
|
5255
|
+
}
|
|
5256
|
+
};
|
|
5186
5257
|
function heldUnder(held, target) {
|
|
5187
5258
|
for (const paths of held) for (const path of paths.keys()) if (within3(path, target)) return true;
|
|
5188
5259
|
return false;
|
|
5189
5260
|
}
|
|
5190
5261
|
var HeldPaths = class extends Map {
|
|
5191
5262
|
revoked = /* @__PURE__ */ new Set();
|
|
5263
|
+
onIdle;
|
|
5192
5264
|
hold(path, on) {
|
|
5193
5265
|
const count = (this.get(path) ?? 0) + (on ? 1 : -1);
|
|
5194
5266
|
if (count > 0) this.set(path, count);
|
|
5195
5267
|
else {
|
|
5196
5268
|
this.delete(path);
|
|
5197
5269
|
this.revoked.delete(path);
|
|
5270
|
+
this.onIdle?.(path);
|
|
5198
5271
|
}
|
|
5199
5272
|
}
|
|
5200
5273
|
revoke(prefix) {
|
|
@@ -5262,6 +5335,8 @@ function spliced(bytes, offset, part) {
|
|
|
5262
5335
|
}
|
|
5263
5336
|
var MountTable = class {
|
|
5264
5337
|
mounts = /* @__PURE__ */ new Map();
|
|
5338
|
+
sessions = /* @__PURE__ */ new Map();
|
|
5339
|
+
committing = /* @__PURE__ */ new Map();
|
|
5265
5340
|
devices = 0;
|
|
5266
5341
|
pending = /* @__PURE__ */ new Set();
|
|
5267
5342
|
notes = /* @__PURE__ */ new Map();
|
|
@@ -5386,8 +5461,69 @@ var MountTable = class {
|
|
|
5386
5461
|
if (!detach && this.deps.busy(at)) throw errnoError("EBUSY", `${at} has open files`);
|
|
5387
5462
|
this.notes.delete(at);
|
|
5388
5463
|
this.mounts.delete(at);
|
|
5389
|
-
mount.
|
|
5390
|
-
mount.
|
|
5464
|
+
const waits = [...this.sessions].filter(([, s]) => s.mount === mount).map(([real]) => this.commit(real));
|
|
5465
|
+
for (const c of this.committing.values()) if (c.mount === mount) waits.push(c.done);
|
|
5466
|
+
const close = () => {
|
|
5467
|
+
mount.conn.close();
|
|
5468
|
+
mount.dispose();
|
|
5469
|
+
};
|
|
5470
|
+
if (waits.length === 0) close();
|
|
5471
|
+
else void Promise.allSettled(waits).then(close);
|
|
5472
|
+
}
|
|
5473
|
+
session(mount, real, rel2) {
|
|
5474
|
+
let session = this.sessions.get(real);
|
|
5475
|
+
if (!session) {
|
|
5476
|
+
const open = () => mount.conn.call({
|
|
5477
|
+
op: "open",
|
|
5478
|
+
path: rel2,
|
|
5479
|
+
write: true,
|
|
5480
|
+
create: true,
|
|
5481
|
+
truncate: false,
|
|
5482
|
+
exclusive: false
|
|
5483
|
+
});
|
|
5484
|
+
const before = this.committing.get(real)?.done ?? Promise.resolve();
|
|
5485
|
+
const fh = before.then(open, open);
|
|
5486
|
+
session = { mount, fh, extents: [], truncated: false };
|
|
5487
|
+
this.sessions.set(real, session);
|
|
5488
|
+
fh.catch(() => this.sessions.delete(real));
|
|
5489
|
+
}
|
|
5490
|
+
return session;
|
|
5491
|
+
}
|
|
5492
|
+
writing(real) {
|
|
5493
|
+
return this.sessions.get(real);
|
|
5494
|
+
}
|
|
5495
|
+
async commit(real) {
|
|
5496
|
+
const session = this.sessions.get(real);
|
|
5497
|
+
if (!session) return this.committing.get(real)?.done;
|
|
5498
|
+
this.sessions.delete(real);
|
|
5499
|
+
const done4 = (async () => {
|
|
5500
|
+
try {
|
|
5501
|
+
await session.mount.conn.call({ op: "release", fh: await session.fh });
|
|
5502
|
+
} finally {
|
|
5503
|
+
this.forget(session.mount, real);
|
|
5504
|
+
}
|
|
5505
|
+
})();
|
|
5506
|
+
const entry = { mount: session.mount, done: done4 };
|
|
5507
|
+
this.committing.set(real, entry);
|
|
5508
|
+
const settle3 = () => {
|
|
5509
|
+
if (this.committing.get(real) === entry) this.committing.delete(real);
|
|
5510
|
+
};
|
|
5511
|
+
done4.then(settle3, settle3);
|
|
5512
|
+
return done4;
|
|
5513
|
+
}
|
|
5514
|
+
async commitUnder(prefix) {
|
|
5515
|
+
const at = normalizePath(prefix);
|
|
5516
|
+
await Promise.all(
|
|
5517
|
+
[...this.sessions.keys()].filter((p) => within3(p, at)).map((p) => this.commit(p))
|
|
5518
|
+
);
|
|
5519
|
+
}
|
|
5520
|
+
async commitOverlapping(real, offset, length2) {
|
|
5521
|
+
const session = this.sessions.get(real);
|
|
5522
|
+
if (!session) return;
|
|
5523
|
+
const end = offset + length2;
|
|
5524
|
+
if (session.truncated || session.extents.some(([a, b]) => a < end && offset < b)) {
|
|
5525
|
+
await this.commit(real);
|
|
5526
|
+
}
|
|
5391
5527
|
}
|
|
5392
5528
|
crashed(mount, error) {
|
|
5393
5529
|
mount.state = "failed";
|
|
@@ -5446,6 +5582,13 @@ var MountTable = class {
|
|
|
5446
5582
|
return new MountFs(this, base);
|
|
5447
5583
|
}
|
|
5448
5584
|
};
|
|
5585
|
+
function noteExtent(extents, from, to) {
|
|
5586
|
+
const last = extents.at(-1);
|
|
5587
|
+
if (last && from <= last[1] && to >= last[0]) {
|
|
5588
|
+
last[0] = Math.min(last[0], from);
|
|
5589
|
+
last[1] = Math.max(last[1], to);
|
|
5590
|
+
} else extents.push([from, to]);
|
|
5591
|
+
}
|
|
5449
5592
|
var MountFs = class {
|
|
5450
5593
|
table;
|
|
5451
5594
|
base;
|
|
@@ -5505,6 +5648,7 @@ var MountFs = class {
|
|
|
5505
5648
|
}
|
|
5506
5649
|
}
|
|
5507
5650
|
async readWhole(mount, real, rel2) {
|
|
5651
|
+
await this.table.commit(real);
|
|
5508
5652
|
const attr = await this.table.getattr(mount, real, rel2);
|
|
5509
5653
|
if (attr.kind === "directory") throw errnoError("EISDIR", real);
|
|
5510
5654
|
if (mount.maxFile > 0 && attr.size > mount.maxFile) {
|
|
@@ -5554,6 +5698,7 @@ var MountFs = class {
|
|
|
5554
5698
|
}
|
|
5555
5699
|
}
|
|
5556
5700
|
async writeWhole(mount, real, rel2, bytes) {
|
|
5701
|
+
await this.table.commit(real);
|
|
5557
5702
|
this.table.forget(mount, real);
|
|
5558
5703
|
const fh = await this.open(mount, rel2, true);
|
|
5559
5704
|
const chunk2 = mount.caps.maxIo ?? DEFAULT_IO;
|
|
@@ -5576,6 +5721,7 @@ var MountFs = class {
|
|
|
5576
5721
|
if ((await this.table.getattr(mount, real, rel2)).kind === "directory") {
|
|
5577
5722
|
throw errnoError("EISDIR", real);
|
|
5578
5723
|
}
|
|
5724
|
+
await this.table.commitOverlapping(real, offset, length2);
|
|
5579
5725
|
const fh = await mount.conn.call({
|
|
5580
5726
|
op: "open",
|
|
5581
5727
|
path: rel2,
|
|
@@ -5629,6 +5775,14 @@ var MountFs = class {
|
|
|
5629
5775
|
this.writable(mount, real);
|
|
5630
5776
|
this.fits(mount, real, offset + bytes.length);
|
|
5631
5777
|
this.table.forget(mount, real);
|
|
5778
|
+
if (mount.caps.sessions) {
|
|
5779
|
+
const session = this.table.session(mount, real, rel2);
|
|
5780
|
+
const end = offset + bytes.length;
|
|
5781
|
+
await this.writeRuns(mount, await session.fh, offset, bytes, transfer);
|
|
5782
|
+
noteExtent(session.extents, offset, end);
|
|
5783
|
+
this.table.forget(mount, real);
|
|
5784
|
+
return;
|
|
5785
|
+
}
|
|
5632
5786
|
const fh = await mount.conn.call({
|
|
5633
5787
|
op: "open",
|
|
5634
5788
|
path: rel2,
|
|
@@ -5637,17 +5791,20 @@ var MountFs = class {
|
|
|
5637
5791
|
truncate: false,
|
|
5638
5792
|
exclusive: false
|
|
5639
5793
|
});
|
|
5640
|
-
const chunk2 = mount.caps.maxIo ?? DEFAULT_IO;
|
|
5641
5794
|
try {
|
|
5642
|
-
|
|
5643
|
-
const part = handed(bytes, transfer, chunk2) ? bytes : bytes.slice(at, at + chunk2);
|
|
5644
|
-
await mount.conn.call({ op: "write", fh, offset: offset + at, bytes: part }, [part.buffer]);
|
|
5645
|
-
}
|
|
5795
|
+
await this.writeRuns(mount, fh, offset, bytes, transfer);
|
|
5646
5796
|
} finally {
|
|
5647
5797
|
await mount.conn.call({ op: "release", fh });
|
|
5648
5798
|
this.table.forget(mount, real);
|
|
5649
5799
|
}
|
|
5650
5800
|
}
|
|
5801
|
+
async writeRuns(mount, fh, offset, bytes, transfer) {
|
|
5802
|
+
const chunk2 = mount.caps.maxIo ?? DEFAULT_IO;
|
|
5803
|
+
for (let at = 0; at < bytes.length; at += chunk2) {
|
|
5804
|
+
const part = handed(bytes, transfer, chunk2) ? bytes : bytes.slice(at, at + chunk2);
|
|
5805
|
+
await mount.conn.call({ op: "write", fh, offset: offset + at, bytes: part }, [part.buffer]);
|
|
5806
|
+
}
|
|
5807
|
+
}
|
|
5651
5808
|
async truncate(path, size) {
|
|
5652
5809
|
const real = await this.follow(path);
|
|
5653
5810
|
const found = this.at(real);
|
|
@@ -5659,6 +5816,8 @@ var MountFs = class {
|
|
|
5659
5816
|
this.writable(mount, real);
|
|
5660
5817
|
this.fits(mount, real, size);
|
|
5661
5818
|
this.table.forget(mount, real);
|
|
5819
|
+
const session = this.table.writing(real);
|
|
5820
|
+
if (session) session.truncated = true;
|
|
5662
5821
|
try {
|
|
5663
5822
|
await mount.conn.call({ op: "setattr", path: rel2, size });
|
|
5664
5823
|
} finally {
|
|
@@ -5680,7 +5839,16 @@ var MountFs = class {
|
|
|
5680
5839
|
const found = this.at(path);
|
|
5681
5840
|
if (!found) return this.base.lstat(path);
|
|
5682
5841
|
const real = normalizePath(path);
|
|
5683
|
-
|
|
5842
|
+
if (this.table.writing(real)?.truncated) await this.table.commit(real);
|
|
5843
|
+
return this.statWriting(
|
|
5844
|
+
await this.table.getattr(found.mount, real, found.rel),
|
|
5845
|
+
real,
|
|
5846
|
+
found.mount
|
|
5847
|
+
);
|
|
5848
|
+
}
|
|
5849
|
+
statWriting(attr, real, mount) {
|
|
5850
|
+
const ends = (this.table.writing(real)?.extents ?? []).map(([, end]) => end);
|
|
5851
|
+
return statOf({ ...attr, size: Math.max(attr.size, ...ends) }, real, mount);
|
|
5684
5852
|
}
|
|
5685
5853
|
async stat(path) {
|
|
5686
5854
|
const real = await this.follow(path);
|
|
@@ -5707,7 +5875,7 @@ var MountFs = class {
|
|
|
5707
5875
|
list.map(async (entry) => {
|
|
5708
5876
|
const child = normalizePath(`${real}/${entry.name}`);
|
|
5709
5877
|
if (entry.attr && mount.caps.listingStats) {
|
|
5710
|
-
return [entry.name,
|
|
5878
|
+
return [entry.name, this.statWriting(entry.attr, child, mount)];
|
|
5711
5879
|
}
|
|
5712
5880
|
return [entry.name, await this.lstat(child).catch(() => null)];
|
|
5713
5881
|
})
|
|
@@ -5743,6 +5911,7 @@ var MountFs = class {
|
|
|
5743
5911
|
const real = normalizePath(path);
|
|
5744
5912
|
if (rel2 === "/") throw errnoError("EBUSY", `${real} is a mount point`);
|
|
5745
5913
|
this.writable(mount, real);
|
|
5914
|
+
await this.table.commitUnder(real);
|
|
5746
5915
|
let attr;
|
|
5747
5916
|
try {
|
|
5748
5917
|
attr = await this.table.getattr(mount, real, rel2);
|
|
@@ -5766,6 +5935,8 @@ var MountFs = class {
|
|
|
5766
5935
|
if (!a && !b) return this.base.rename(from, to);
|
|
5767
5936
|
if (!a || !b || a.mount !== b.mount) throw errnoError("EXDEV", `${from} -> ${to}`);
|
|
5768
5937
|
this.writable(a.mount, normalizePath(to));
|
|
5938
|
+
await this.table.commitUnder(from);
|
|
5939
|
+
await this.table.commitUnder(to);
|
|
5769
5940
|
this.table.forget(a.mount, normalizePath(from));
|
|
5770
5941
|
this.table.forget(a.mount, normalizePath(to));
|
|
5771
5942
|
try {
|
|
@@ -5784,6 +5955,12 @@ var MountFs = class {
|
|
|
5784
5955
|
this.table.forget(found.mount, normalizePath(path));
|
|
5785
5956
|
await found.mount.conn.call({ op: "symlink", target, path: found.rel });
|
|
5786
5957
|
}
|
|
5958
|
+
async realpath(path, follow) {
|
|
5959
|
+
if (this.at(path) || !this.base.realpath) throw errnoError("ENOSYS", path);
|
|
5960
|
+
const real = await this.base.realpath(path, follow);
|
|
5961
|
+
if (this.at(real)) throw errnoError("ENOSYS", path);
|
|
5962
|
+
return real;
|
|
5963
|
+
}
|
|
5787
5964
|
async readlink(path) {
|
|
5788
5965
|
const found = this.at(path);
|
|
5789
5966
|
if (!found) return this.base.readlink(path);
|
|
@@ -7366,6 +7543,7 @@ var VfsNode = class {
|
|
|
7366
7543
|
writeBack;
|
|
7367
7544
|
writeBackCost = 0;
|
|
7368
7545
|
opens = 0;
|
|
7546
|
+
writers = 0;
|
|
7369
7547
|
missing = false;
|
|
7370
7548
|
revoked = false;
|
|
7371
7549
|
fs;
|
|
@@ -7541,8 +7719,10 @@ var VfsNodes = class {
|
|
|
7541
7719
|
byPath = /* @__PURE__ */ new Map();
|
|
7542
7720
|
fs;
|
|
7543
7721
|
entries = /* @__PURE__ */ new Map();
|
|
7544
|
-
|
|
7722
|
+
onClosed;
|
|
7723
|
+
constructor(fs, onClosed) {
|
|
7545
7724
|
this.fs = fs;
|
|
7725
|
+
this.onClosed = onClosed;
|
|
7546
7726
|
}
|
|
7547
7727
|
async onEntry(path, op) {
|
|
7548
7728
|
const key = await this.entryKey(path);
|
|
@@ -7556,9 +7736,21 @@ var VfsNodes = class {
|
|
|
7556
7736
|
}
|
|
7557
7737
|
async entryKey(path) {
|
|
7558
7738
|
const parent = parentOf5(path);
|
|
7559
|
-
const dir = await
|
|
7560
|
-
|
|
7561
|
-
|
|
7739
|
+
const dir = await this.real(parent, true, () => realDir(this.fs, parent));
|
|
7740
|
+
return joinName(dir, path.slice(path.lastIndexOf("/") + 1));
|
|
7741
|
+
}
|
|
7742
|
+
targetKey(path) {
|
|
7743
|
+
return this.real(path, true, () => realTarget(this.fs, path));
|
|
7744
|
+
}
|
|
7745
|
+
async real(path, follow, walk) {
|
|
7746
|
+
if (this.fs.realpath) {
|
|
7747
|
+
try {
|
|
7748
|
+
return await this.fs.realpath(path, follow);
|
|
7749
|
+
} catch (err) {
|
|
7750
|
+
if (errCode(err) === "ELOOP") throw err;
|
|
7751
|
+
}
|
|
7752
|
+
}
|
|
7753
|
+
return walk();
|
|
7562
7754
|
}
|
|
7563
7755
|
createExclusive(path) {
|
|
7564
7756
|
return this.onEntry(path, async () => {
|
|
@@ -7568,16 +7760,17 @@ var VfsNodes = class {
|
|
|
7568
7760
|
await this.fs.writeFile(path, new Uint8Array(0));
|
|
7569
7761
|
});
|
|
7570
7762
|
}
|
|
7571
|
-
open(path, pin) {
|
|
7763
|
+
open(path, pin, writable = false) {
|
|
7572
7764
|
let node = this.byPath.get(path);
|
|
7573
7765
|
if (!node) {
|
|
7574
7766
|
node = new VfsNode(this.fs, path, void 0, false, false, pin);
|
|
7575
7767
|
this.byPath.set(path, node);
|
|
7576
7768
|
}
|
|
7577
7769
|
node.opens++;
|
|
7770
|
+
if (writable) node.writers++;
|
|
7578
7771
|
return node;
|
|
7579
7772
|
}
|
|
7580
|
-
adopt(path, contents2, dirty) {
|
|
7773
|
+
adopt(path, contents2, dirty, writable = false) {
|
|
7581
7774
|
let node = this.byPath.get(path);
|
|
7582
7775
|
if (!node) {
|
|
7583
7776
|
node = new VfsNode(this.fs, path, contents2, false, dirty);
|
|
@@ -7586,15 +7779,27 @@ var VfsNodes = class {
|
|
|
7586
7779
|
node.replace(contents2);
|
|
7587
7780
|
}
|
|
7588
7781
|
node.opens++;
|
|
7782
|
+
if (writable) node.writers++;
|
|
7589
7783
|
return node;
|
|
7590
7784
|
}
|
|
7591
7785
|
holds(prefix) {
|
|
7592
7786
|
for (const path of this.byPath.keys()) if (within4(path, prefix)) return true;
|
|
7593
7787
|
return false;
|
|
7594
7788
|
}
|
|
7595
|
-
|
|
7789
|
+
writes(prefix) {
|
|
7790
|
+
for (const [path, node] of this.byPath)
|
|
7791
|
+
if (node.writers > 0 && within4(path, prefix)) return true;
|
|
7792
|
+
return false;
|
|
7793
|
+
}
|
|
7794
|
+
closed(node, writable = false) {
|
|
7596
7795
|
node.opens--;
|
|
7597
|
-
if (
|
|
7796
|
+
if (writable) node.writers--;
|
|
7797
|
+
if (node.opens > 0) {
|
|
7798
|
+
if (writable && node.writers === 0) this.onClosed?.(node.path);
|
|
7799
|
+
return;
|
|
7800
|
+
}
|
|
7801
|
+
if (this.byPath.get(node.path) === node) this.byPath.delete(node.path);
|
|
7802
|
+
this.onClosed?.(node.path);
|
|
7598
7803
|
}
|
|
7599
7804
|
async flush(path) {
|
|
7600
7805
|
for (const [p, node] of this.byPath) if (within4(p, path)) await node.serial(() => node.flush());
|
|
@@ -7653,10 +7858,9 @@ function parentOf5(path) {
|
|
|
7653
7858
|
async function linkOf(fs, path) {
|
|
7654
7859
|
return fs.readlink?.(path).catch(() => void 0);
|
|
7655
7860
|
}
|
|
7656
|
-
async function realDir(fs, dir) {
|
|
7861
|
+
async function realDir(fs, dir, budget = { hops: 0 }) {
|
|
7657
7862
|
const queue = dir.split("/").filter(Boolean);
|
|
7658
7863
|
let at = "/";
|
|
7659
|
-
let hops = 0;
|
|
7660
7864
|
while (queue.length > 0) {
|
|
7661
7865
|
const part = queue.shift();
|
|
7662
7866
|
if (part === ".") continue;
|
|
@@ -7665,28 +7869,41 @@ async function realDir(fs, dir) {
|
|
|
7665
7869
|
continue;
|
|
7666
7870
|
}
|
|
7667
7871
|
const next = at === "/" ? `/${part}` : `${at}/${part}`;
|
|
7668
|
-
const link2 =
|
|
7872
|
+
const link2 = await linkOf(fs, next);
|
|
7669
7873
|
if (link2 === void 0) {
|
|
7670
7874
|
at = next;
|
|
7671
7875
|
continue;
|
|
7672
7876
|
}
|
|
7673
|
-
hops
|
|
7877
|
+
if (budget.hops >= MAX_LINKS5) throw fsError("ELOOP", dir);
|
|
7878
|
+
budget.hops++;
|
|
7674
7879
|
queue.unshift(...link2.split("/").filter(Boolean));
|
|
7675
7880
|
if (link2.startsWith("/")) at = "/";
|
|
7676
7881
|
}
|
|
7677
7882
|
return at;
|
|
7678
7883
|
}
|
|
7679
|
-
|
|
7680
|
-
|
|
7884
|
+
function errCode(err) {
|
|
7885
|
+
return err?.code;
|
|
7886
|
+
}
|
|
7887
|
+
function joinName(dir, name2) {
|
|
7888
|
+
return dir === "/" ? `/${name2}` : `${dir}/${name2}`;
|
|
7889
|
+
}
|
|
7890
|
+
async function realTarget(fs, path) {
|
|
7891
|
+
const budget = { hops: 0 };
|
|
7892
|
+
let dir = await realDir(fs, parentOf5(path), budget);
|
|
7681
7893
|
let name2 = path.slice(path.lastIndexOf("/") + 1);
|
|
7682
|
-
for (
|
|
7683
|
-
const link2 = await linkOf(fs, dir
|
|
7684
|
-
if (link2 === void 0)
|
|
7685
|
-
|
|
7686
|
-
|
|
7894
|
+
for (; ; ) {
|
|
7895
|
+
const link2 = await linkOf(fs, joinName(dir, name2));
|
|
7896
|
+
if (link2 === void 0) break;
|
|
7897
|
+
if (budget.hops >= MAX_LINKS5) throw fsError("ELOOP", path);
|
|
7898
|
+
budget.hops++;
|
|
7899
|
+
const target = link2.startsWith("/") ? link2 : joinName(dir, link2);
|
|
7900
|
+
dir = await realDir(fs, parentOf5(target), budget);
|
|
7687
7901
|
name2 = target.slice(target.lastIndexOf("/") + 1);
|
|
7688
7902
|
}
|
|
7689
|
-
return dir;
|
|
7903
|
+
return joinName(dir, name2);
|
|
7904
|
+
}
|
|
7905
|
+
async function targetDir(fs, path) {
|
|
7906
|
+
return parentOf5(await realTarget(fs, path).catch(() => path));
|
|
7690
7907
|
}
|
|
7691
7908
|
async function refuseReadonly(fs, path, flags, opts = {}) {
|
|
7692
7909
|
const writes = (flags & O_ACCMODE) !== 0 || opts.truncate === true;
|
|
@@ -7705,13 +7922,14 @@ function keepingOpen(fs, nodes) {
|
|
|
7705
7922
|
return {
|
|
7706
7923
|
...fs,
|
|
7707
7924
|
async rm(path, options) {
|
|
7708
|
-
const at = fs.resolvePath("/", path);
|
|
7925
|
+
const at = await nodes.entryKey(fs.resolvePath("/", path));
|
|
7709
7926
|
await nodes.unlinking(at);
|
|
7710
7927
|
await fs.rm(path, options);
|
|
7711
7928
|
nodes.unlinked(at);
|
|
7712
7929
|
},
|
|
7713
|
-
rename(from, to) {
|
|
7714
|
-
const
|
|
7930
|
+
async rename(from, to) {
|
|
7931
|
+
const a = await nodes.entryKey(fs.resolvePath("/", from));
|
|
7932
|
+
const b = await nodes.entryKey(fs.resolvePath("/", to));
|
|
7715
7933
|
return nodes.onEntry(b, async () => {
|
|
7716
7934
|
await nodes.unlinking(b);
|
|
7717
7935
|
await fs.rename(from, to);
|
|
@@ -7727,7 +7945,7 @@ function vfsFile(fs, opts, nodes) {
|
|
|
7727
7945
|
const access = opts.flags & O_ACCMODE;
|
|
7728
7946
|
const readable = access !== O_WRONLY;
|
|
7729
7947
|
const writable = access === O_WRONLY || access === O_RDWR;
|
|
7730
|
-
const node = !nodes || opts.orphan ? new VfsNode(fs, opts.path, opts.contents, opts.orphan === true, opts.dirty === true) : opts.contents !== void 0 ? nodes.adopt(opts.path, opts.contents, opts.dirty === true) : nodes.open(opts.path, opts.pin);
|
|
7948
|
+
const node = !nodes || opts.orphan ? new VfsNode(fs, opts.path, opts.contents, opts.orphan === true, opts.dirty === true) : opts.contents !== void 0 ? nodes.adopt(opts.path, opts.contents, opts.dirty === true, writable) : nodes.open(opts.path, opts.pin, writable);
|
|
7731
7949
|
let openError;
|
|
7732
7950
|
const atOpen = (op) => {
|
|
7733
7951
|
void node.serial(op).catch((err) => {
|
|
@@ -7790,7 +8008,7 @@ function vfsFile(fs, opts, nodes) {
|
|
|
7790
8008
|
takeOpenError();
|
|
7791
8009
|
await node.flush();
|
|
7792
8010
|
} finally {
|
|
7793
|
-
nodes?.closed(node);
|
|
8011
|
+
nodes?.closed(node, writable);
|
|
7794
8012
|
}
|
|
7795
8013
|
})
|
|
7796
8014
|
});
|
|
@@ -7857,10 +8075,12 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
|
|
|
7857
8075
|
"fd-cloexec",
|
|
7858
8076
|
"fd-list",
|
|
7859
8077
|
"proc-alarm",
|
|
8078
|
+
"proc-umask",
|
|
7860
8079
|
"dl-log",
|
|
7861
8080
|
"fd-renumber",
|
|
7862
8081
|
"fd-promote",
|
|
7863
8082
|
"fd-open-tty",
|
|
8083
|
+
"fd-tty-names",
|
|
7864
8084
|
"tty-get",
|
|
7865
8085
|
"tty-set",
|
|
7866
8086
|
"tty-winsz",
|
|
@@ -7894,6 +8114,7 @@ function isWasmSyscall(req) {
|
|
|
7894
8114
|
return typeof op === "string" && SYSCALL_OPS.has(op);
|
|
7895
8115
|
}
|
|
7896
8116
|
var MAX_READ = 1024 * 1024;
|
|
8117
|
+
var DEFAULT_UMASK = 18;
|
|
7897
8118
|
var DYING = { ok: false, errno: "EINTR", message: "the process is being killed" };
|
|
7898
8119
|
var HOSTS_ONLY = new Resolver({ routes: new Routes() });
|
|
7899
8120
|
var WasmProcess = class {
|
|
@@ -7904,6 +8125,7 @@ var WasmProcess = class {
|
|
|
7904
8125
|
inherited = 0;
|
|
7905
8126
|
interrupt = new AbortController();
|
|
7906
8127
|
dying = false;
|
|
8128
|
+
umask = DEFAULT_UMASK;
|
|
7907
8129
|
execChild;
|
|
7908
8130
|
execTermsig;
|
|
7909
8131
|
stopped = 0;
|
|
@@ -7921,6 +8143,7 @@ var WasmProcess = class {
|
|
|
7921
8143
|
this.fds = fds;
|
|
7922
8144
|
this.options = options;
|
|
7923
8145
|
this.inherited = options.ignored ?? 0;
|
|
8146
|
+
this.umask = options.umask ?? DEFAULT_UMASK;
|
|
7924
8147
|
this.children = new ChildTable(fds, options.spawner, options.forker);
|
|
7925
8148
|
this.nodes = options.nodes ?? new VfsNodes(options.fs);
|
|
7926
8149
|
if (!options.nodes) options.openFiles?.add(this.nodes);
|
|
@@ -7993,6 +8216,11 @@ var WasmProcess = class {
|
|
|
7993
8216
|
return result;
|
|
7994
8217
|
}
|
|
7995
8218
|
}
|
|
8219
|
+
setUmask(mask) {
|
|
8220
|
+
const old = this.umask;
|
|
8221
|
+
if (mask !== void 0) this.umask = mask & 511;
|
|
8222
|
+
return old;
|
|
8223
|
+
}
|
|
7996
8224
|
die() {
|
|
7997
8225
|
if (this.dying) return;
|
|
7998
8226
|
this.dying = true;
|
|
@@ -8063,9 +8291,21 @@ var WasmProcess = class {
|
|
|
8063
8291
|
await refuseReadonly(this.options.fs, req.path, req.flags, req);
|
|
8064
8292
|
const fd = this.fds.install(heldFile(), 3);
|
|
8065
8293
|
try {
|
|
8066
|
-
|
|
8067
|
-
|
|
8068
|
-
|
|
8294
|
+
const nodes = this.nodes;
|
|
8295
|
+
const path = req.orphan ? req.path : req.exclusive ? await nodes.entryKey(req.path) : await nodes.targetKey(req.path);
|
|
8296
|
+
const open = { ...req, path };
|
|
8297
|
+
if (req.exclusive) {
|
|
8298
|
+
await nodes.createExclusive(path);
|
|
8299
|
+
this.fds.installAt(fd, this.openVfsFile(open));
|
|
8300
|
+
} else if (req.create) {
|
|
8301
|
+
await nodes.onEntry(path, async () => {
|
|
8302
|
+
this.fds.installAt(fd, this.openVfsFile(open));
|
|
8303
|
+
await this.fds.get(fd).file.stat?.();
|
|
8304
|
+
});
|
|
8305
|
+
} else {
|
|
8306
|
+
this.fds.installAt(fd, this.openVfsFile(open));
|
|
8307
|
+
}
|
|
8308
|
+
if (req.existing && !await present(this.options.fs, path, true)) {
|
|
8069
8309
|
throw new KernelError("ENOENT");
|
|
8070
8310
|
}
|
|
8071
8311
|
} catch (err) {
|
|
@@ -8144,7 +8384,7 @@ var WasmProcess = class {
|
|
|
8144
8384
|
case "fd-reserve":
|
|
8145
8385
|
return { ok: true, kind: "json", json: this.reserve(req.fd, req.min, req.meta) };
|
|
8146
8386
|
case "fd-promote":
|
|
8147
|
-
this.promote(req);
|
|
8387
|
+
await this.promote(req);
|
|
8148
8388
|
return { ok: true, kind: "void" };
|
|
8149
8389
|
case "fd-renumber":
|
|
8150
8390
|
if (req.from !== req.to) {
|
|
@@ -8157,6 +8397,8 @@ var WasmProcess = class {
|
|
|
8157
8397
|
if (!tty) throw new KernelError("ENXIO");
|
|
8158
8398
|
return { ok: true, kind: "json", json: this.fds.install(tty.file(), 3) };
|
|
8159
8399
|
}
|
|
8400
|
+
case "fd-tty-names":
|
|
8401
|
+
return { ok: true, kind: "json", json: this.options.jobs?.terminalNames() ?? [] };
|
|
8160
8402
|
case "fd-select": {
|
|
8161
8403
|
const { read, write, timeoutMs } = req;
|
|
8162
8404
|
const signal = this.blockingSignal();
|
|
@@ -8178,10 +8420,14 @@ var WasmProcess = class {
|
|
|
8178
8420
|
async vfsSyscall(req) {
|
|
8179
8421
|
if ("path" in req || "from" in req) {
|
|
8180
8422
|
const nodes = this.nodes;
|
|
8181
|
-
if (req.op === "fd-path-flush")
|
|
8182
|
-
|
|
8183
|
-
else if (req.op === "fd-path-
|
|
8184
|
-
|
|
8423
|
+
if (req.op === "fd-path-flush") {
|
|
8424
|
+
await nodes.flush(await nodes.targetKey(req.path).catch(() => req.path));
|
|
8425
|
+
} else if (req.op === "fd-path-unlinking")
|
|
8426
|
+
await nodes.unlinking(await nodes.entryKey(req.path));
|
|
8427
|
+
else if (req.op === "fd-path-unlinked") nodes.unlinked(await nodes.entryKey(req.path));
|
|
8428
|
+
else if (req.op === "fd-path-renamed") {
|
|
8429
|
+
nodes.renamed(await nodes.entryKey(req.from), await nodes.entryKey(req.to));
|
|
8430
|
+
}
|
|
8185
8431
|
return { ok: true, kind: "void" };
|
|
8186
8432
|
}
|
|
8187
8433
|
const file = this.fds.get(req.fd).file;
|
|
@@ -8202,17 +8448,19 @@ var WasmProcess = class {
|
|
|
8202
8448
|
return { ok: true, kind: "json", json: await file.stat() };
|
|
8203
8449
|
}
|
|
8204
8450
|
}
|
|
8205
|
-
promote(req) {
|
|
8451
|
+
async promote(req) {
|
|
8206
8452
|
if (!this.fds.get(req.fd).file.held) throw new KernelError("EBADF");
|
|
8207
8453
|
if (req.share !== void 0) {
|
|
8208
8454
|
this.fds.dup2(req.share, req.fd);
|
|
8209
8455
|
return;
|
|
8210
8456
|
}
|
|
8211
8457
|
if (req.path === void 0) throw new KernelError("EINVAL");
|
|
8458
|
+
const path = req.orphan ? req.path : await this.nodes.targetKey(req.path);
|
|
8459
|
+
if (!this.fds.get(req.fd).file.held) throw new KernelError("EBADF");
|
|
8212
8460
|
const file = vfsFile(
|
|
8213
8461
|
this.options.fs,
|
|
8214
8462
|
{
|
|
8215
|
-
path
|
|
8463
|
+
path,
|
|
8216
8464
|
flags: req.flags ?? 0,
|
|
8217
8465
|
position: req.position ?? 0,
|
|
8218
8466
|
...req.contents !== void 0 ? { contents: req.contents } : {},
|
|
@@ -8388,6 +8636,8 @@ var WasmProcess = class {
|
|
|
8388
8636
|
case "proc-alarm":
|
|
8389
8637
|
this.setAlarm(req.sig, req.firstMs ?? req.ms, req.repeat ? req.ms : 0, req.timer);
|
|
8390
8638
|
return { ok: true, kind: "void" };
|
|
8639
|
+
case "proc-umask":
|
|
8640
|
+
return { ok: true, kind: "json", json: this.setUmask(req.mask) };
|
|
8391
8641
|
case "dl-log":
|
|
8392
8642
|
if (req.append) this.dlLog.push(req.append);
|
|
8393
8643
|
return { ok: true, kind: "json", json: this.dlLog.slice(req.from) };
|
|
@@ -8537,7 +8787,7 @@ var Dying = class {
|
|
|
8537
8787
|
return [typeof reported === "number" ? reported : CRASHED, void 0];
|
|
8538
8788
|
}
|
|
8539
8789
|
};
|
|
8540
|
-
function processInit(opts, sab) {
|
|
8790
|
+
function processInit(opts, sab, umask) {
|
|
8541
8791
|
const base = {
|
|
8542
8792
|
type: WASM_PROCESS_INIT,
|
|
8543
8793
|
pid: opts.shownPid ?? opts.pid,
|
|
@@ -8546,6 +8796,7 @@ function processInit(opts, sab) {
|
|
|
8546
8796
|
env: opts.env,
|
|
8547
8797
|
cwd: opts.cwd,
|
|
8548
8798
|
sab,
|
|
8799
|
+
umask,
|
|
8549
8800
|
...opts.ppid !== void 0 ? { ppid: opts.ppid } : {}
|
|
8550
8801
|
};
|
|
8551
8802
|
if (opts.program.abi === "js") {
|
|
@@ -8557,11 +8808,17 @@ function processInit(opts, sab) {
|
|
|
8557
8808
|
...opts.fork ? { fork: opts.fork } : { fds: inheritedFds(opts.fds) }
|
|
8558
8809
|
};
|
|
8559
8810
|
}
|
|
8811
|
+
function inherited(opts) {
|
|
8812
|
+
return {
|
|
8813
|
+
...opts.ignored ? { ignored: opts.ignored } : {},
|
|
8814
|
+
...opts.umask !== void 0 ? { umask: opts.umask } : {}
|
|
8815
|
+
};
|
|
8816
|
+
}
|
|
8560
8817
|
function spawnWasmProcess(opts) {
|
|
8561
8818
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
8562
8819
|
const header2 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
8563
8820
|
const process = new WasmProcess(opts.pid, opts.fds, {
|
|
8564
|
-
...opts
|
|
8821
|
+
...inherited(opts),
|
|
8565
8822
|
...opts.identity ? { identity: opts.identity } : {},
|
|
8566
8823
|
...opts.onSyscall ? { onSyscall: opts.onSyscall } : {},
|
|
8567
8824
|
spawner: opts.spawner,
|
|
@@ -8695,7 +8952,7 @@ function spawnWasmProcess(opts) {
|
|
|
8695
8952
|
};
|
|
8696
8953
|
tw.postMessage(tinit);
|
|
8697
8954
|
};
|
|
8698
|
-
const init = processInit(opts, sab);
|
|
8955
|
+
const init = processInit(opts, sab, process.umask);
|
|
8699
8956
|
worker.postMessage(init, opts.fork ? [opts.fork.memory.buffer] : []);
|
|
8700
8957
|
const signal = (sig) => {
|
|
8701
8958
|
if (process.signal(sig) !== "terminate") return;
|
|
@@ -8713,6 +8970,7 @@ function spawnWasmProcess(opts) {
|
|
|
8713
8970
|
onState: (listener) => process.onState(listener),
|
|
8714
8971
|
memory: () => Atomics.load(header2, SAB_I_MEMORY) * 65536,
|
|
8715
8972
|
ignoredSignals: (fork) => process.inheritable(fork),
|
|
8973
|
+
umask: () => process.umask,
|
|
8716
8974
|
writesBack: () => opts.program.abi === "wasi" && !done4
|
|
8717
8975
|
};
|
|
8718
8976
|
}
|
|
@@ -8818,8 +9076,13 @@ var JobTable = class {
|
|
|
8818
9076
|
return id;
|
|
8819
9077
|
}
|
|
8820
9078
|
terminalNamed(name2) {
|
|
8821
|
-
|
|
8822
|
-
|
|
9079
|
+
return this.knownTerminals().find((tty) => tty.name === name2);
|
|
9080
|
+
}
|
|
9081
|
+
terminalNames() {
|
|
9082
|
+
return this.knownTerminals().flatMap((tty) => tty.name ? [tty.name] : []);
|
|
9083
|
+
}
|
|
9084
|
+
knownTerminals() {
|
|
9085
|
+
return [.../* @__PURE__ */ new Set([...this.terminals.values(), ...this.foreground.keys()])];
|
|
8823
9086
|
}
|
|
8824
9087
|
controllingTerminal(pid) {
|
|
8825
9088
|
const member = this.members.get(pid);
|
|
@@ -9092,7 +9355,11 @@ function mediumSlot(lost, onLost) {
|
|
|
9092
9355
|
}
|
|
9093
9356
|
|
|
9094
9357
|
// src/mount/fsa.ts
|
|
9095
|
-
var FSA_CAPABILITIES = {
|
|
9358
|
+
var FSA_CAPABILITIES = {
|
|
9359
|
+
listingStats: true,
|
|
9360
|
+
ranges: true,
|
|
9361
|
+
sessions: true
|
|
9362
|
+
};
|
|
9096
9363
|
var codeOf2 = (err) => err?.code;
|
|
9097
9364
|
var denied = (err) => codeOf2(err) === "EACCES" || err?.name === "NotAllowedError";
|
|
9098
9365
|
function attrOf(st) {
|
|
@@ -9132,30 +9399,20 @@ function kernelFsHandlers(fs) {
|
|
|
9132
9399
|
if (st && flags.exclusive) throw fsError2("EEXIST", path);
|
|
9133
9400
|
if (st?.isDirectory && flags.write) throw fsError2("EISDIR", path);
|
|
9134
9401
|
if (!st && !flags.create) throw fsError2("ENOENT", path);
|
|
9135
|
-
|
|
9136
|
-
handles.set(++nextFh, { path
|
|
9402
|
+
if (!st || flags.truncate) await fs.writeFile(path, new Uint8Array(0));
|
|
9403
|
+
handles.set(++nextFh, { path });
|
|
9137
9404
|
return nextFh;
|
|
9138
9405
|
},
|
|
9139
|
-
async
|
|
9140
|
-
const h = handle(fh);
|
|
9141
|
-
return h.data.slice(offset, Math.min(h.length, offset + size));
|
|
9142
|
-
},
|
|
9406
|
+
read: async (fh, offset, size) => fs.pread(handle(fh).path, offset, size),
|
|
9143
9407
|
async write(fh, offset, bytes) {
|
|
9144
9408
|
const h = handle(fh);
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
const grown = new Uint8Array(Math.max(end, h.data.length * 2));
|
|
9148
|
-
grown.set(h.data.subarray(0, h.length));
|
|
9149
|
-
h.data = grown;
|
|
9150
|
-
}
|
|
9151
|
-
h.data.set(bytes, offset);
|
|
9152
|
-
h.length = Math.max(h.length, end);
|
|
9153
|
-
h.dirty = true;
|
|
9409
|
+
h.session ??= fs.writeSession(h.path, false);
|
|
9410
|
+
await (await h.session).write(offset, bytes);
|
|
9154
9411
|
},
|
|
9155
9412
|
async release(fh) {
|
|
9156
9413
|
const h = handle(fh);
|
|
9157
9414
|
handles.delete(fh);
|
|
9158
|
-
if (h.
|
|
9415
|
+
if (h.session !== void 0) await (await h.session).close();
|
|
9159
9416
|
},
|
|
9160
9417
|
mkdir: (path) => fs.mkdir(path),
|
|
9161
9418
|
async rmdir(path) {
|
|
@@ -9171,6 +9428,13 @@ function kernelFsHandlers(fs) {
|
|
|
9171
9428
|
symlink: (target, path) => fs.symlink(target, path),
|
|
9172
9429
|
readlink: (path) => fs.readlink(path),
|
|
9173
9430
|
async setattr(path, change) {
|
|
9431
|
+
if (change.size !== void 0) {
|
|
9432
|
+
const open = [...handles.values()].find(
|
|
9433
|
+
(h) => h.path === path && h.session !== void 0
|
|
9434
|
+
)?.session;
|
|
9435
|
+
if (open !== void 0) await (await open).truncate(change.size);
|
|
9436
|
+
else await fs.truncate?.(path, change.size);
|
|
9437
|
+
}
|
|
9174
9438
|
if (change.mode !== void 0) await fs.chmod(path, change.mode);
|
|
9175
9439
|
if (change.mtime !== void 0) {
|
|
9176
9440
|
await fs.utimes(path, new Date(change.mtime), new Date(change.mtime));
|
|
@@ -9886,6 +10150,7 @@ function tmpfs() {
|
|
|
9886
10150
|
const { dir, name: name2 } = parent(path);
|
|
9887
10151
|
if (dir.children.has(name2)) throw fsError2("EEXIST", path);
|
|
9888
10152
|
dir.children.set(name2, make("directory", 16877));
|
|
10153
|
+
dir.mtime = Date.now();
|
|
9889
10154
|
},
|
|
9890
10155
|
async rmdir(path) {
|
|
9891
10156
|
const { dir, name: name2 } = parent(path);
|
|
@@ -9894,6 +10159,7 @@ function tmpfs() {
|
|
|
9894
10159
|
if (node.kind !== "directory") throw fsError2("ENOTDIR", path);
|
|
9895
10160
|
if (node.children.size > 0) throw fsError2("ENOTEMPTY", path);
|
|
9896
10161
|
dir.children.delete(name2);
|
|
10162
|
+
dir.mtime = Date.now();
|
|
9897
10163
|
},
|
|
9898
10164
|
async unlink(path) {
|
|
9899
10165
|
const { dir, name: name2 } = parent(path);
|
|
@@ -9901,6 +10167,7 @@ function tmpfs() {
|
|
|
9901
10167
|
if (!node) throw fsError2("ENOENT", path);
|
|
9902
10168
|
if (node.kind === "directory") throw fsError2("EISDIR", path);
|
|
9903
10169
|
dir.children.delete(name2);
|
|
10170
|
+
dir.mtime = Date.now();
|
|
9904
10171
|
},
|
|
9905
10172
|
async rename(from, to) {
|
|
9906
10173
|
const a = `/${parts(from).join("/")}`;
|
|
@@ -9917,6 +10184,8 @@ function tmpfs() {
|
|
|
9917
10184
|
}
|
|
9918
10185
|
source.dir.children.delete(source.name);
|
|
9919
10186
|
target.dir.children.set(target.name, node);
|
|
10187
|
+
source.dir.mtime = Date.now();
|
|
10188
|
+
target.dir.mtime = source.dir.mtime;
|
|
9920
10189
|
},
|
|
9921
10190
|
async symlink(target, path) {
|
|
9922
10191
|
const { dir, name: name2 } = parent(path);
|
|
@@ -9924,6 +10193,7 @@ function tmpfs() {
|
|
|
9924
10193
|
const node = make("symlink", 41471);
|
|
9925
10194
|
node.target = target;
|
|
9926
10195
|
dir.children.set(name2, node);
|
|
10196
|
+
dir.mtime = Date.now();
|
|
9927
10197
|
},
|
|
9928
10198
|
async readlink(path) {
|
|
9929
10199
|
const node = find(path);
|
|
@@ -10222,7 +10492,7 @@ var Launcher = class {
|
|
|
10222
10492
|
deciding = /* @__PURE__ */ new Map();
|
|
10223
10493
|
identities = { asked: 0, timedOut: 0 };
|
|
10224
10494
|
nodes;
|
|
10225
|
-
held =
|
|
10495
|
+
held = new HeldSet((path) => this.released(path));
|
|
10226
10496
|
processMounts;
|
|
10227
10497
|
booting = new AbortController();
|
|
10228
10498
|
fstab = Promise.resolve([]);
|
|
@@ -10264,7 +10534,7 @@ var Launcher = class {
|
|
|
10264
10534
|
});
|
|
10265
10535
|
enableCdp(this.net, this.cdp);
|
|
10266
10536
|
const fs = withCommandDirs(this.base, async () => new Set((await this.commands()).keys()));
|
|
10267
|
-
this.nodes = new VfsNodes(fs);
|
|
10537
|
+
this.nodes = new VfsNodes(fs, (path) => this.released(path));
|
|
10268
10538
|
this.openFiles.add(this.nodes);
|
|
10269
10539
|
this.fs = keepingOpen(fs, this.nodes);
|
|
10270
10540
|
this.watchers.watch([this.modulesDir, this.pnpmHome], { recursive: true }, () => {
|
|
@@ -10453,6 +10723,7 @@ var Launcher = class {
|
|
|
10453
10723
|
this.settling.syscall(pid, call.op);
|
|
10454
10724
|
},
|
|
10455
10725
|
...req.ignored ? { ignored: req.ignored } : {},
|
|
10726
|
+
...req.umask !== void 0 ? { umask: req.umask } : {},
|
|
10456
10727
|
program: req.program,
|
|
10457
10728
|
argv0: req.argv0,
|
|
10458
10729
|
args: req.args,
|
|
@@ -10544,7 +10815,8 @@ var Launcher = class {
|
|
|
10544
10815
|
...described,
|
|
10545
10816
|
started: (this.described.get(root.pid) ?? described).started,
|
|
10546
10817
|
state: this.processes.has(member.pid) ? "S" : "Z",
|
|
10547
|
-
memory: this.processes.get(member.pid)?.memory() ?? 0
|
|
10818
|
+
memory: this.processes.get(member.pid)?.memory() ?? 0,
|
|
10819
|
+
umask: this.umaskOf(member.pid)
|
|
10548
10820
|
});
|
|
10549
10821
|
}
|
|
10550
10822
|
return listed;
|
|
@@ -10566,6 +10838,7 @@ var Launcher = class {
|
|
|
10566
10838
|
report,
|
|
10567
10839
|
ppid,
|
|
10568
10840
|
ignored: this.ignoredBy(ppid),
|
|
10841
|
+
umask: this.umaskOf(ppid),
|
|
10569
10842
|
...exec
|
|
10570
10843
|
});
|
|
10571
10844
|
deciding?.attach();
|
|
@@ -10610,7 +10883,8 @@ var Launcher = class {
|
|
|
10610
10883
|
fds,
|
|
10611
10884
|
ppid,
|
|
10612
10885
|
fork: state,
|
|
10613
|
-
ignored: this.ignoredBy(ppid, true)
|
|
10886
|
+
ignored: this.ignoredBy(ppid, true),
|
|
10887
|
+
umask: this.umaskOf(ppid)
|
|
10614
10888
|
})
|
|
10615
10889
|
);
|
|
10616
10890
|
}
|
|
@@ -10619,6 +10893,14 @@ var Launcher = class {
|
|
|
10619
10893
|
const foreground = () => this.jobs.tcgetpgrp(tty, fallback);
|
|
10620
10894
|
this.settling.deliver(sig, pgid, send, tty.reading ? void 0 : foreground);
|
|
10621
10895
|
}
|
|
10896
|
+
umaskOf(pid) {
|
|
10897
|
+
return this.processes.get(pid)?.umask?.() ?? DEFAULT_UMASK;
|
|
10898
|
+
}
|
|
10899
|
+
released(path) {
|
|
10900
|
+
const at = normalizePath(path);
|
|
10901
|
+
const open = [...this.openFiles].some((nodes) => nodes.writes(at)) || heldUnder(this.held, at);
|
|
10902
|
+
if (!open) void this.mounts.commit(at).catch(() => void 0);
|
|
10903
|
+
}
|
|
10622
10904
|
ignoredBy(pid, fork = false) {
|
|
10623
10905
|
return this.processes.get(pid)?.ignoredSignals(fork) ?? 0;
|
|
10624
10906
|
}
|