@poe-platform/safe-bash 0.1.533 → 0.1.534
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/safe-bash/commands/archive/index.d.ts +2 -0
- package/dist/safe-bash/commands/archive/index.d.ts.map +1 -1
- package/dist/safe-bash/commands/archive/index.js +11 -3
- package/dist/safe-bash/commands/archive/index.js.map +1 -1
- package/dist/safe-bash/commands/archive/unzip/arguments.d.ts +32 -0
- package/dist/safe-bash/commands/archive/unzip/arguments.d.ts.map +1 -0
- package/dist/safe-bash/commands/archive/unzip/arguments.js +214 -0
- package/dist/safe-bash/commands/archive/unzip/arguments.js.map +1 -0
- package/dist/safe-bash/commands/archive/unzip/safety.d.ts +28 -0
- package/dist/safe-bash/commands/archive/unzip/safety.d.ts.map +1 -0
- package/dist/safe-bash/commands/archive/unzip/safety.js +288 -0
- package/dist/safe-bash/commands/archive/unzip/safety.js.map +1 -0
- package/dist/safe-bash/commands/archive/unzip.d.ts +4 -0
- package/dist/safe-bash/commands/archive/unzip.d.ts.map +1 -0
- package/dist/safe-bash/commands/archive/unzip.js +264 -0
- package/dist/safe-bash/commands/archive/unzip.js.map +1 -0
- package/dist/safe-bash/commands/archive/zip/safety.d.ts +28 -0
- package/dist/safe-bash/commands/archive/zip/safety.d.ts.map +1 -0
- package/dist/safe-bash/commands/archive/zip/safety.js +228 -0
- package/dist/safe-bash/commands/archive/zip/safety.js.map +1 -0
- package/dist/safe-bash/commands/archive/zip-format.d.ts +39 -0
- package/dist/safe-bash/commands/archive/zip-format.d.ts.map +1 -0
- package/dist/safe-bash/commands/archive/zip-format.js +509 -0
- package/dist/safe-bash/commands/archive/zip-format.js.map +1 -0
- package/dist/safe-bash/commands/archive/zip.d.ts +4 -0
- package/dist/safe-bash/commands/archive/zip.d.ts.map +1 -0
- package/dist/safe-bash/commands/archive/zip.js +290 -0
- package/dist/safe-bash/commands/archive/zip.js.map +1 -0
- package/dist/safe-bash/commands/bytes/compression/codec.d.ts +1 -1
- package/dist/safe-bash/commands/bytes/compression/codec.d.ts.map +1 -1
- package/dist/safe-bash/commands/bytes/compression/codec.js +2 -2
- package/dist/safe-bash/commands/bytes/compression/codec.js.map +1 -1
- package/dist/safe-bash/core.browser.js +1932 -387
- package/dist/safe-bash/core.browser.js.map +4 -4
- package/package.json +2 -2
|
@@ -841,7 +841,7 @@ var Parser = class {
|
|
|
841
841
|
return { minimum: 0, maximum: 1 };
|
|
842
842
|
}
|
|
843
843
|
this.position += 2;
|
|
844
|
-
const
|
|
844
|
+
const number6 = () => {
|
|
845
845
|
let value2 = 0, count2 = 0;
|
|
846
846
|
while (this.tokens[this.position] >= "0" && this.tokens[this.position] <= "9") {
|
|
847
847
|
this.work.charge();
|
|
@@ -850,12 +850,12 @@ var Parser = class {
|
|
|
850
850
|
}
|
|
851
851
|
return count2 ? value2 : void 0;
|
|
852
852
|
};
|
|
853
|
-
const minimum =
|
|
853
|
+
const minimum = number6();
|
|
854
854
|
if (minimum === void 0) syntax("Invalid content of \\{\\}");
|
|
855
855
|
let maximum = minimum;
|
|
856
856
|
if (this.at(",")) {
|
|
857
857
|
this.position++;
|
|
858
|
-
maximum =
|
|
858
|
+
maximum = number6() ?? Infinity;
|
|
859
859
|
}
|
|
860
860
|
if (!this.escaped("}")) syntax("Unmatched \\{");
|
|
861
861
|
this.position += 2;
|
|
@@ -1111,15 +1111,15 @@ function* matchExprSteps(descriptor2, subject, options3 = {}) {
|
|
|
1111
1111
|
if (start < 0 || end < start || end - start > input3.values.length - state.position) break;
|
|
1112
1112
|
work.charge(end - start);
|
|
1113
1113
|
if (work.checkpoint()) yield;
|
|
1114
|
-
let
|
|
1114
|
+
let equal2 = true;
|
|
1115
1115
|
for (let offset = 0; offset < end - start; offset++) {
|
|
1116
1116
|
if (input3.values[start + offset] !== input3.values[state.position + offset]) {
|
|
1117
|
-
|
|
1117
|
+
equal2 = false;
|
|
1118
1118
|
break;
|
|
1119
1119
|
}
|
|
1120
1120
|
if ((offset + 1) % 256 === 0) yield;
|
|
1121
1121
|
}
|
|
1122
|
-
if (!
|
|
1122
|
+
if (!equal2) break;
|
|
1123
1123
|
state.position += end - start;
|
|
1124
1124
|
if (end > start) {
|
|
1125
1125
|
work.allocate(1);
|
|
@@ -2449,34 +2449,34 @@ async function formatPrintf(context2) {
|
|
|
2449
2449
|
const arguments_ = incoming.args[0] === "--" ? incoming.slice(1) : incoming;
|
|
2450
2450
|
const args = arguments_.args;
|
|
2451
2451
|
requireOperands(args);
|
|
2452
|
-
const
|
|
2453
|
-
if (
|
|
2452
|
+
const format3 = args[0];
|
|
2453
|
+
if (format3.startsWith("-") && incoming.args[0] !== "--") throw new UsageError(`invalid option '${format3}'`);
|
|
2454
2454
|
const rawFormat = typeof arguments_.values[0] === "string" ? void 0 : arguments_.bytes(0);
|
|
2455
|
-
const formatLength = rawFormat?.length ??
|
|
2455
|
+
const formatLength = rawFormat?.length ?? format3.length;
|
|
2456
2456
|
let argument2 = 1;
|
|
2457
2457
|
let exitCode = 0;
|
|
2458
2458
|
let stopped = false;
|
|
2459
2459
|
do {
|
|
2460
2460
|
const before = argument2;
|
|
2461
2461
|
for (let offset = 0; offset < formatLength && !stopped; ) {
|
|
2462
|
-
if (rawFormat ? rawFormat[offset] !== 37 :
|
|
2463
|
-
const end = rawFormat ? rawFormat.indexOf(37, offset) :
|
|
2462
|
+
if (rawFormat ? rawFormat[offset] !== 37 : format3[offset] !== "%") {
|
|
2463
|
+
const end = rawFormat ? rawFormat.indexOf(37, offset) : format3.indexOf("%", offset);
|
|
2464
2464
|
const limit = end < 0 ? formatLength : end;
|
|
2465
|
-
const literal = rawFormat ? rawFormat.subarray(offset, limit) :
|
|
2465
|
+
const literal = rawFormat ? rawFormat.subarray(offset, limit) : format3.slice(offset, limit);
|
|
2466
2466
|
const escaped3 = escapeBytes(literal);
|
|
2467
2467
|
await output(context2, escaped3.bytes);
|
|
2468
2468
|
stopped = escaped3.stop;
|
|
2469
2469
|
offset += literal.length;
|
|
2470
2470
|
continue;
|
|
2471
2471
|
}
|
|
2472
|
-
if (rawFormat ? rawFormat[offset + 1] === 37 :
|
|
2472
|
+
if (rawFormat ? rawFormat[offset + 1] === 37 : format3[offset + 1] === "%") {
|
|
2473
2473
|
await output(context2, "%");
|
|
2474
2474
|
offset += 2;
|
|
2475
2475
|
continue;
|
|
2476
2476
|
}
|
|
2477
2477
|
let tokenEnd = offset + 1;
|
|
2478
2478
|
if (rawFormat) while (tokenEnd < rawFormat.length && (rawFormat[tokenEnd] >= 48 && rawFormat[tokenEnd] <= 57 || [32, 35, 43, 45, 46].includes(rawFormat[tokenEnd]))) tokenEnd++;
|
|
2479
|
-
const fragment = rawFormat ? decoder.decode(rawFormat.subarray(offset, tokenEnd + 1)) :
|
|
2479
|
+
const fragment = rawFormat ? decoder.decode(rawFormat.subarray(offset, tokenEnd + 1)) : format3.slice(offset);
|
|
2480
2480
|
const match = /^%([-+ #0]*)(\d+)?(?:\.(\d+))?([sbqcdiouxXfFeEgG])/u.exec(fragment);
|
|
2481
2481
|
if (!match) throw new UsageError(`invalid format near '${fragment}'`);
|
|
2482
2482
|
offset += match[0].length;
|
|
@@ -2504,30 +2504,30 @@ async function formatPrintf(context2) {
|
|
|
2504
2504
|
if (specifier === "q") text3 = supplied === "" ? "''" : supplied.replace(/[^a-zA-Z0-9_./-]/gu, (character) => character === "\n" ? "$'\\n'" : `\\${character}`);
|
|
2505
2505
|
else if (specifier === "c") text3 = supplied ? String.fromCodePoint(supplied.codePointAt(0)) : "\0";
|
|
2506
2506
|
else {
|
|
2507
|
-
let
|
|
2507
|
+
let number6 = supplied === "" ? 0 : /^["']/u.test(supplied) ? supplied.codePointAt(1) ?? 0 : Number(supplied);
|
|
2508
2508
|
if (/^[+-]0[xX][0-9a-fA-F]+$/u.test(supplied.trim())) {
|
|
2509
|
-
|
|
2509
|
+
number6 = Number(supplied.trim().slice(1)) * (supplied.trim().startsWith("-") ? -1 : 1);
|
|
2510
2510
|
}
|
|
2511
2511
|
if (/^[+-]?0[0-9]+$/u.test(supplied) && !/[fFeEgG]/u.test(specifier)) {
|
|
2512
|
-
if (/[89]/u.test(supplied))
|
|
2513
|
-
else
|
|
2512
|
+
if (/[89]/u.test(supplied)) number6 = NaN;
|
|
2513
|
+
else number6 = parseInt(supplied.replace(/^[+-]?0/u, ""), 8) * (supplied.startsWith("-") ? -1 : 1);
|
|
2514
2514
|
}
|
|
2515
|
-
if (!Number.isFinite(
|
|
2515
|
+
if (!Number.isFinite(number6)) {
|
|
2516
2516
|
await writeDiagnostic(context2.stderr, `printf: '${supplied}': invalid number
|
|
2517
2517
|
`, context2.signal);
|
|
2518
2518
|
exitCode = 1;
|
|
2519
|
-
|
|
2519
|
+
number6 = 0;
|
|
2520
2520
|
}
|
|
2521
|
-
if (/[fF]/u.test(specifier)) text3 =
|
|
2522
|
-
else if (/[eE]/u.test(specifier)) text3 =
|
|
2523
|
-
else if (/[gG]/u.test(specifier)) text3 = Number(
|
|
2521
|
+
if (/[fF]/u.test(specifier)) text3 = number6.toFixed(precision ?? 6);
|
|
2522
|
+
else if (/[eE]/u.test(specifier)) text3 = number6.toExponential(precision ?? 6).replace(/e([+-])(\d)$/u, "e$10$2");
|
|
2523
|
+
else if (/[gG]/u.test(specifier)) text3 = Number(number6.toPrecision(Math.max(1, precision ?? 6))).toString();
|
|
2524
2524
|
else {
|
|
2525
2525
|
const radix = /[xX]/u.test(specifier) ? 16 : specifier === "o" ? 8 : 10;
|
|
2526
2526
|
const unsigned = /[uoxX]/u.test(specifier);
|
|
2527
2527
|
let integral;
|
|
2528
2528
|
try {
|
|
2529
2529
|
const token = supplied.trim();
|
|
2530
|
-
if (!token || /^["']/u.test(token)) integral = BigInt(Math.trunc(
|
|
2530
|
+
if (!token || /^["']/u.test(token)) integral = BigInt(Math.trunc(number6));
|
|
2531
2531
|
else {
|
|
2532
2532
|
const magnitude = token.replace(/^[+-]/u, "");
|
|
2533
2533
|
if (!/^(?:0[xX][0-9a-fA-F]+|0[0-7]*|[1-9][0-9]*)$/u.test(magnitude)) throw new Error("invalid integer");
|
|
@@ -2548,7 +2548,7 @@ async function formatPrintf(context2) {
|
|
|
2548
2548
|
}
|
|
2549
2549
|
}
|
|
2550
2550
|
if (/[XFEG]/u.test(specifier)) text3 = text3.toUpperCase();
|
|
2551
|
-
if (
|
|
2551
|
+
if (number6 >= 0 && /[difFeEgG]/u.test(specifier)) text3 = (flags3.includes("+") ? "+" : flags3.includes(" ") ? " " : "") + text3;
|
|
2552
2552
|
}
|
|
2553
2553
|
if (flags3.includes("-")) text3 = text3.padEnd(width, " ");
|
|
2554
2554
|
else if (flags3.includes("0") && /[diouxXfFeEgG]/u.test(specifier) && (precision === void 0 || /[fFeEgG]/u.test(specifier))) {
|
|
@@ -3384,14 +3384,14 @@ function filesystemCommands(maxDirectoryEntries) {
|
|
|
3384
3384
|
else if (parsed.flags.has("F") && stat.type === "file" && stat.mode & 73) suffix2 = "*";
|
|
3385
3385
|
if (parsed.flags.has("l")) {
|
|
3386
3386
|
const size = parsed.flags.has("h") ? humanSize(stat.size, path) : String(stat.size);
|
|
3387
|
-
const
|
|
3387
|
+
const date2 = new Date(stat.mtimeMs).toISOString().slice(0, 16).replace("T", " ");
|
|
3388
3388
|
let target = "";
|
|
3389
3389
|
if (stat.type === "symlink") {
|
|
3390
3390
|
await admitFilesystemModes(context2, "ls", ["link"], [path]);
|
|
3391
3391
|
needCapability(context2, "readlink");
|
|
3392
3392
|
target = ` -> ${escapeText(await context2.fs.readlink(path, { signal: context2.signal }), "display")}`;
|
|
3393
3393
|
}
|
|
3394
|
-
await output(context2, `${modeText(stat)} ${stat.nlink ?? 1} ${stat.uid ?? 0} ${stat.gid ?? 0} ${size} ${
|
|
3394
|
+
await output(context2, `${modeText(stat)} ${stat.nlink ?? 1} ${stat.uid ?? 0} ${stat.gid ?? 0} ${size} ${date2} ${escapeText(display2, "display")}${suffix2}${target}
|
|
3395
3395
|
`);
|
|
3396
3396
|
} else await output(context2, `${escapeText(display2, "display")}${suffix2}
|
|
3397
3397
|
`);
|
|
@@ -4152,7 +4152,7 @@ function streamCommands(maxTeeTargets = 64, maxTailFollowHandles = 64) {
|
|
|
4152
4152
|
}
|
|
4153
4153
|
let lineStart = true;
|
|
4154
4154
|
let blankCount = 0;
|
|
4155
|
-
let
|
|
4155
|
+
let number6 = 1;
|
|
4156
4156
|
for await (const chunk of source2) {
|
|
4157
4157
|
const transformed = [];
|
|
4158
4158
|
const append = (text3) => {
|
|
@@ -4160,7 +4160,7 @@ function streamCommands(maxTeeTargets = 64, maxTailFollowHandles = 64) {
|
|
|
4160
4160
|
};
|
|
4161
4161
|
for (const byte of chunk) {
|
|
4162
4162
|
if (lineStart && byte === 10 && parsed.flags.has("s") && blankCount > 0) continue;
|
|
4163
|
-
if (lineStart && (parsed.flags.has("b") ? byte !== 10 : parsed.flags.has("n"))) append(`${String(
|
|
4163
|
+
if (lineStart && (parsed.flags.has("b") ? byte !== 10 : parsed.flags.has("n"))) append(`${String(number6++).padStart(6)} `);
|
|
4164
4164
|
if (byte === 10) {
|
|
4165
4165
|
if (parsed.flags.has("E")) transformed.push(36);
|
|
4166
4166
|
transformed.push(10);
|
|
@@ -4654,7 +4654,7 @@ async function emitRecords(context2, records5, destination2) {
|
|
|
4654
4654
|
}
|
|
4655
4655
|
async function collectSortRecords(source2, delimiter, budget, signal, accept) {
|
|
4656
4656
|
const pending = new RecordBuffer(bufferLimit);
|
|
4657
|
-
const
|
|
4657
|
+
const admit3 = (length) => {
|
|
4658
4658
|
signal.throwIfAborted();
|
|
4659
4659
|
budget.admit(length);
|
|
4660
4660
|
};
|
|
@@ -4663,13 +4663,13 @@ async function collectSortRecords(source2, delimiter, budget, signal, accept) {
|
|
|
4663
4663
|
let start = 0;
|
|
4664
4664
|
for (let offset = 0; offset < chunk.length; offset++) {
|
|
4665
4665
|
if (chunk[offset] !== delimiter) continue;
|
|
4666
|
-
const accepted = accept(pending.finish(
|
|
4666
|
+
const accepted = accept(pending.finish(admit3, chunk, start, offset));
|
|
4667
4667
|
if ((accepted instanceof Promise ? await accepted : accepted) === false) return false;
|
|
4668
4668
|
start = offset + 1;
|
|
4669
4669
|
}
|
|
4670
4670
|
pending.append(chunk, start);
|
|
4671
4671
|
}
|
|
4672
|
-
if (pending.size) return await accept(pending.finish(
|
|
4672
|
+
if (pending.size) return await accept(pending.finish(admit3)) !== false;
|
|
4673
4673
|
return true;
|
|
4674
4674
|
} finally {
|
|
4675
4675
|
pending.clear();
|
|
@@ -5017,7 +5017,7 @@ function predicateCommands() {
|
|
|
5017
5017
|
const unary2 = /* @__PURE__ */ new Set(["-n", "-z", "-e", "-a", "-f", "-c", "-d", "-L", "-h", "-s", "-r", "-w", "-x"]);
|
|
5018
5018
|
const binary3 = /* @__PURE__ */ new Set(["=", "==", "!=", "<", ">", "-eq", "-ne", "-lt", "-le", "-gt", "-ge", "-nt", "-ot", "-ef"]);
|
|
5019
5019
|
let offset = 0;
|
|
5020
|
-
const
|
|
5020
|
+
const number6 = (text3) => {
|
|
5021
5021
|
if (!/^[ \t]*[+-]?[0-9]+[ \t]*$/u.test(text3)) throw new UsageError(`integer expression expected: '${text3}'`);
|
|
5022
5022
|
return BigInt(text3.trim());
|
|
5023
5023
|
};
|
|
@@ -5053,8 +5053,8 @@ function predicateCommands() {
|
|
|
5053
5053
|
if (identity2 !== "unknown") return identity2 === "same";
|
|
5054
5054
|
return leftStat?.ino !== void 0 && rightStat?.ino !== void 0 && leftStat.type === rightStat.type && leftStat.ino === rightStat.ino && leftStat.dev === rightStat.dev;
|
|
5055
5055
|
}
|
|
5056
|
-
const leftNumber =
|
|
5057
|
-
const rightNumber =
|
|
5056
|
+
const leftNumber = number6(token);
|
|
5057
|
+
const rightNumber = number6(right);
|
|
5058
5058
|
if (operator === "-eq") return leftNumber === rightNumber;
|
|
5059
5059
|
if (operator === "-ne") return leftNumber !== rightNumber;
|
|
5060
5060
|
if (operator === "-lt") return leftNumber < rightNumber;
|
|
@@ -5449,7 +5449,7 @@ async function* argumentsFrom(source2, signal, delimiter, replacement = false) {
|
|
|
5449
5449
|
let active = false;
|
|
5450
5450
|
let escaped3 = false;
|
|
5451
5451
|
let quote5 = "";
|
|
5452
|
-
const
|
|
5452
|
+
const parse19 = function* (text3) {
|
|
5453
5453
|
for (const character of text3) {
|
|
5454
5454
|
if (delimiter !== void 0) {
|
|
5455
5455
|
if (character === delimiter) {
|
|
@@ -5490,9 +5490,9 @@ async function* argumentsFrom(source2, signal, delimiter, replacement = false) {
|
|
|
5490
5490
|
};
|
|
5491
5491
|
for await (const chunk of readBytes(source2, signal)) {
|
|
5492
5492
|
signal.throwIfAborted();
|
|
5493
|
-
yield*
|
|
5493
|
+
yield* parse19(utf82.decode(chunk, { stream: true }));
|
|
5494
5494
|
}
|
|
5495
|
-
yield*
|
|
5495
|
+
yield* parse19(utf82.decode());
|
|
5496
5496
|
if (quote5 || escaped3) throw new UsageError(quote5 ? "unmatched quote in input" : "trailing backslash in input");
|
|
5497
5497
|
if (active) yield current;
|
|
5498
5498
|
}
|
|
@@ -6123,9 +6123,9 @@ function findCommands(execute5, maxDirectoryEntries) {
|
|
|
6123
6123
|
index++;
|
|
6124
6124
|
} else if (args[index] === "-maxdepth" || args[index] === "-mindepth") {
|
|
6125
6125
|
if (args[index + 1] === void 0) throw new UsageError(`${args[index]} requires a number`);
|
|
6126
|
-
const
|
|
6127
|
-
if (args[index] === "-maxdepth") maxDepth =
|
|
6128
|
-
else minDepth =
|
|
6126
|
+
const number6 = integer(args[index + 1]);
|
|
6127
|
+
if (args[index] === "-maxdepth") maxDepth = number6;
|
|
6128
|
+
else minDepth = number6;
|
|
6129
6129
|
args.splice(index, 2);
|
|
6130
6130
|
values.splice(index, 2);
|
|
6131
6131
|
} else if (args[index] === "-depth") {
|
|
@@ -6321,7 +6321,7 @@ function findCommands(execute5, maxDirectoryEntries) {
|
|
|
6321
6321
|
};
|
|
6322
6322
|
const evaluate = args.length ? disjunction() : async () => true;
|
|
6323
6323
|
if (offset !== args.length) throw new UsageError(`unexpected expression '${args[offset]}'`);
|
|
6324
|
-
for (const
|
|
6324
|
+
for (const prepare2 of formats2) await prepare2();
|
|
6325
6325
|
if (deletes && prunes && !explicitDepth) throw new PublicDiagnostic("-delete implies -depth; -prune is ineffective unless -depth is explicitly supplied");
|
|
6326
6326
|
for (const reference of references.keys()) {
|
|
6327
6327
|
context2.signal.throwIfAborted();
|
|
@@ -6958,15 +6958,15 @@ function widthValue(text3, maximum, unicode) {
|
|
|
6958
6958
|
while (text3.charCodeAt(offset) === 32 || text3.charCodeAt(offset) >= 9 && text3.charCodeAt(offset) <= 13) offset++;
|
|
6959
6959
|
if (text3[offset] === "+") offset++;
|
|
6960
6960
|
const start = offset;
|
|
6961
|
-
let
|
|
6961
|
+
let number6 = 0;
|
|
6962
6962
|
while (text3.charCodeAt(offset) >= 48 && text3.charCodeAt(offset) <= 57) {
|
|
6963
|
-
|
|
6963
|
+
number6 = Math.min(1073741824, number6 * 10 + text3.charCodeAt(offset++) - 48);
|
|
6964
6964
|
}
|
|
6965
|
-
if (offset === start || offset !== text3.length ||
|
|
6966
|
-
const range3 = offset === text3.length && offset !== start &&
|
|
6967
|
-
throw new PublicDiagnostic(`invalid width: ${quote(Uint8Array.from(text3, (unit2) => unit2.charCodeAt(0)), false, unicode)}${range3 ?
|
|
6965
|
+
if (offset === start || offset !== text3.length || number6 > maximum) {
|
|
6966
|
+
const range3 = offset === text3.length && offset !== start && number6 > maximum;
|
|
6967
|
+
throw new PublicDiagnostic(`invalid width: ${quote(Uint8Array.from(text3, (unit2) => unit2.charCodeAt(0)), false, unicode)}${range3 ? number6 > 1073741823 ? ": Value too large for defined data type" : ": Numerical result out of range" : ""}`);
|
|
6968
6968
|
}
|
|
6969
|
-
return
|
|
6969
|
+
return number6;
|
|
6970
6970
|
}
|
|
6971
6971
|
function parse3(context2) {
|
|
6972
6972
|
const settings17 = { width: 75, goal: 70, crown: false, tagged: false, split: false, uniform: false, prefix: new Uint8Array(), leading: 0, fullPrefix: 0, files: [] };
|
|
@@ -10291,8 +10291,8 @@ function parse4(context2) {
|
|
|
10291
10291
|
else if (key === "z") settings17.separator = 0;
|
|
10292
10292
|
else if (key === "help" || key === "version") settings17.information = key;
|
|
10293
10293
|
else if (key === "n") {
|
|
10294
|
-
const
|
|
10295
|
-
if (
|
|
10294
|
+
const number6 = decimal(value2, true, unicode);
|
|
10295
|
+
if (number6 < settings17.count) settings17.count = number6;
|
|
10296
10296
|
} else if (key === "i") {
|
|
10297
10297
|
if (settings17.range) throw new ShufDiagnostic("multiple -i options specified");
|
|
10298
10298
|
const dash = value2.indexOf("-");
|
|
@@ -13763,10 +13763,10 @@ function parse6(source2, extended, separator, maxProgramInstructions) {
|
|
|
13763
13763
|
};
|
|
13764
13764
|
const address = () => {
|
|
13765
13765
|
horizontal();
|
|
13766
|
-
const
|
|
13767
|
-
if (
|
|
13768
|
-
offset +=
|
|
13769
|
-
const value2 = Number(
|
|
13766
|
+
const number6 = /^[0-9]+/u.exec(source2.slice(offset));
|
|
13767
|
+
if (number6) {
|
|
13768
|
+
offset += number6[0].length;
|
|
13769
|
+
const value2 = Number(number6[0]);
|
|
13770
13770
|
if (!Number.isSafeInteger(value2) || value2 < 1) throw new ProgramError("sed line addresses must be positive integers");
|
|
13771
13771
|
return { kind: "number", number: value2 };
|
|
13772
13772
|
}
|
|
@@ -13966,7 +13966,7 @@ async function execute2(program, context2, files, quiet, budget, separator, outp
|
|
|
13966
13966
|
const next = await peekNext();
|
|
13967
13967
|
return !next.done && next.value.fileIndex !== record4.fileIndex ? { ...record4, terminated: true } : record4;
|
|
13968
13968
|
};
|
|
13969
|
-
let
|
|
13969
|
+
let number6 = 0;
|
|
13970
13970
|
let hold = "";
|
|
13971
13971
|
let holdTerminated = true;
|
|
13972
13972
|
const joinSpace = (left, right) => {
|
|
@@ -13987,7 +13987,7 @@ async function execute2(program, context2, files, quiet, budget, separator, outp
|
|
|
13987
13987
|
try {
|
|
13988
13988
|
while (!current.done) {
|
|
13989
13989
|
budget.step();
|
|
13990
|
-
|
|
13990
|
+
number6++;
|
|
13991
13991
|
let record4 = await prepareRecord(current.value);
|
|
13992
13992
|
let pattern = record4.text;
|
|
13993
13993
|
const appended = [];
|
|
@@ -14038,7 +14038,7 @@ async function execute2(program, context2, files, quiet, budget, separator, outp
|
|
|
14038
14038
|
if (terminated) outputState.unterminatedFiles.delete(path);
|
|
14039
14039
|
else outputState.unterminatedFiles.add(path);
|
|
14040
14040
|
};
|
|
14041
|
-
const matches3 = async (address) => address.kind === "number" ?
|
|
14041
|
+
const matches3 = async (address) => address.kind === "number" ? number6 === address.number : address.kind === "last" ? (await peekNext()).done === true : await getPattern(address.pattern).find(pattern, budget) !== void 0;
|
|
14042
14042
|
for (let pc = 0; pc < program.length; ) {
|
|
14043
14043
|
budget.step();
|
|
14044
14044
|
await budget.checkpoint();
|
|
@@ -14048,13 +14048,13 @@ async function execute2(program, context2, files, quiet, budget, separator, outp
|
|
|
14048
14048
|
if (instruction.first) {
|
|
14049
14049
|
if (instruction.second) {
|
|
14050
14050
|
if (active.has(pc)) {
|
|
14051
|
-
if (instruction.second.kind === "number" &&
|
|
14052
|
-
ending = instruction.second.kind === "number" ?
|
|
14051
|
+
if (instruction.second.kind === "number" && number6 > instruction.second.number) selected = false;
|
|
14052
|
+
ending = instruction.second.kind === "number" ? number6 >= instruction.second.number : await matches3(instruction.second);
|
|
14053
14053
|
if (ending) active.delete(pc);
|
|
14054
14054
|
} else {
|
|
14055
14055
|
selected = await matches3(instruction.first);
|
|
14056
14056
|
if (selected) {
|
|
14057
|
-
ending = instruction.second.kind === "number" &&
|
|
14057
|
+
ending = instruction.second.kind === "number" && number6 >= instruction.second.number || instruction.second.kind === "last" && (await peekNext()).done === true;
|
|
14058
14058
|
if (!ending) active.add(pc);
|
|
14059
14059
|
}
|
|
14060
14060
|
}
|
|
@@ -14075,7 +14075,7 @@ async function execute2(program, context2, files, quiet, budget, separator, outp
|
|
|
14075
14075
|
break;
|
|
14076
14076
|
}
|
|
14077
14077
|
case "=":
|
|
14078
|
-
await emit2(`${
|
|
14078
|
+
await emit2(`${number6}${separator}`);
|
|
14079
14079
|
break;
|
|
14080
14080
|
case "l": {
|
|
14081
14081
|
const escapes = { "\x07": "\\a", "\b": "\\b", "\f": "\\f", "\n": "\\n", "\r": "\\r", " ": "\\t", "\v": "\\v", "\\": "\\\\" };
|
|
@@ -14203,7 +14203,7 @@ async function execute2(program, context2, files, quiet, budget, separator, outp
|
|
|
14203
14203
|
return { status: 0, quit: false };
|
|
14204
14204
|
}
|
|
14205
14205
|
record4 = await prepareRecord(next.value);
|
|
14206
|
-
|
|
14206
|
+
number6++;
|
|
14207
14207
|
pattern = instruction.kind === "N" ? joinSpace(pattern, record4.text) : record4.text;
|
|
14208
14208
|
substituted = false;
|
|
14209
14209
|
break;
|
|
@@ -14338,7 +14338,7 @@ var AwkArray = class {
|
|
|
14338
14338
|
entries = /* @__PURE__ */ new Map();
|
|
14339
14339
|
};
|
|
14340
14340
|
var unset = Object.freeze({ kind: "unset" });
|
|
14341
|
-
var numeric = (
|
|
14341
|
+
var numeric = (number6) => ({ kind: "number", number: number6 });
|
|
14342
14342
|
var string = (text3) => ({ kind: "string", text: text3 });
|
|
14343
14343
|
function inputValue(text3) {
|
|
14344
14344
|
return /^[ \t\r\n]*[+-]?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[eE][+-]?[0-9]+)?[ \t\r\n]*$/u.test(text3) ? { kind: "numeric", text: text3, number: Number(text3) } : string(text3);
|
|
@@ -14366,28 +14366,28 @@ function general2(value2, precision, alternate) {
|
|
|
14366
14366
|
return result2;
|
|
14367
14367
|
}
|
|
14368
14368
|
var formatPattern = /^%([-+ #0]*)(\*|[0-9]+)?(?:\.(\*|[0-9]*))?([csdiuoxXfFeEgG])/u;
|
|
14369
|
-
function validateFormat(
|
|
14370
|
-
for (let offset = 0; offset <
|
|
14371
|
-
if (
|
|
14369
|
+
function validateFormat(format3) {
|
|
14370
|
+
for (let offset = 0; offset < format3.length; ) {
|
|
14371
|
+
if (format3[offset] !== "%") {
|
|
14372
14372
|
offset++;
|
|
14373
14373
|
continue;
|
|
14374
14374
|
}
|
|
14375
|
-
if (
|
|
14375
|
+
if (format3[offset + 1] === "%") {
|
|
14376
14376
|
offset += 2;
|
|
14377
14377
|
continue;
|
|
14378
14378
|
}
|
|
14379
|
-
const match = formatPattern.exec(
|
|
14380
|
-
if (!match) throw new ProgramError(`unsupported format near '${
|
|
14379
|
+
const match = formatPattern.exec(format3.slice(offset));
|
|
14380
|
+
if (!match) throw new ProgramError(`unsupported format near '${format3.slice(offset)}'`);
|
|
14381
14381
|
offset += match[0].length;
|
|
14382
14382
|
if (match[2] !== "*" && Number(match[2] ?? 0) > 1e6 || match[3] !== "*" && Number(match[3] ?? 0) > (/[fFeEgG]/u.test(match[4]) ? 100 : 1e6)) throw new ProgramError("excessive format width or precision");
|
|
14383
14383
|
}
|
|
14384
14384
|
}
|
|
14385
|
-
function formatted(
|
|
14386
|
-
budget?.step(
|
|
14385
|
+
function formatted(format3, values, text3, budget) {
|
|
14386
|
+
budget?.step(format3.length);
|
|
14387
14387
|
let result2 = "";
|
|
14388
14388
|
let argument2 = 0;
|
|
14389
14389
|
const limit = Math.min(budget?.maxBufferBytes ?? 32 * 1024 * 1024, 32 * 1024 * 1024);
|
|
14390
|
-
const
|
|
14390
|
+
const admit3 = (length) => {
|
|
14391
14391
|
budget?.step(0);
|
|
14392
14392
|
if (length > limit - result2.length) throw new ProgramError(budget && budget.maxBufferBytes < 32 * 1024 * 1024 ? "text buffer limit exceeded" : "formatted output exceeds buffer limit");
|
|
14393
14393
|
budget?.step(length);
|
|
@@ -14401,20 +14401,20 @@ function formatted(format2, values, text3, budget) {
|
|
|
14401
14401
|
if (value2 === void 0) throw new ProgramError("not enough arguments for format");
|
|
14402
14402
|
return value2;
|
|
14403
14403
|
};
|
|
14404
|
-
for (let offset = 0; offset <
|
|
14405
|
-
if (
|
|
14406
|
-
|
|
14407
|
-
result2 +=
|
|
14404
|
+
for (let offset = 0; offset < format3.length; ) {
|
|
14405
|
+
if (format3[offset] !== "%") {
|
|
14406
|
+
admit3(1);
|
|
14407
|
+
result2 += format3[offset++];
|
|
14408
14408
|
continue;
|
|
14409
14409
|
}
|
|
14410
|
-
if (
|
|
14411
|
-
|
|
14410
|
+
if (format3[offset + 1] === "%") {
|
|
14411
|
+
admit3(1);
|
|
14412
14412
|
result2 += "%";
|
|
14413
14413
|
offset += 2;
|
|
14414
14414
|
continue;
|
|
14415
14415
|
}
|
|
14416
|
-
const match = formatPattern.exec(
|
|
14417
|
-
if (!match) throw new ProgramError(`unsupported format near '${
|
|
14416
|
+
const match = formatPattern.exec(format3.slice(offset));
|
|
14417
|
+
if (!match) throw new ProgramError(`unsupported format near '${format3.slice(offset)}'`);
|
|
14418
14418
|
offset += match[0].length;
|
|
14419
14419
|
let flags3 = match[1];
|
|
14420
14420
|
let width = match[2] === "*" ? Math.trunc(amountOf(take())) : Number(match[2] ?? 0);
|
|
@@ -14430,10 +14430,10 @@ function formatted(format2, values, text3, budget) {
|
|
|
14430
14430
|
let part;
|
|
14431
14431
|
if (conversion === "s") {
|
|
14432
14432
|
const source2 = text3(value2);
|
|
14433
|
-
|
|
14433
|
+
admit3(Math.min(source2.length, precision ?? source2.length));
|
|
14434
14434
|
part = source2.slice(0, precision);
|
|
14435
14435
|
} else if (conversion === "c") {
|
|
14436
|
-
|
|
14436
|
+
admit3(1);
|
|
14437
14437
|
part = value2.kind === "string" ? value2.text[0] ?? "\0" : String.fromCharCode(Math.trunc(amountOf(value2)) & 255);
|
|
14438
14438
|
} else {
|
|
14439
14439
|
const amount = amountOf(value2);
|
|
@@ -14448,46 +14448,46 @@ function formatted(format2, values, text3, budget) {
|
|
|
14448
14448
|
part = (/[uoxX]/u.test(conversion) ? BigInt.asUintN(32, integer10) : integer10).toString(radix);
|
|
14449
14449
|
if (precision !== void 0) {
|
|
14450
14450
|
const negative = part.startsWith("-");
|
|
14451
|
-
|
|
14451
|
+
admit3(amount === 0 && precision === 0 ? 0 : Math.max(part.length, precision + Number(negative)));
|
|
14452
14452
|
part = amount === 0 && precision === 0 ? "" : negative ? `-${part.slice(1).padStart(precision, "0")}` : part.padStart(precision, "0");
|
|
14453
14453
|
}
|
|
14454
14454
|
if (flags3.includes("#") && amount !== 0) {
|
|
14455
14455
|
const prefix3 = radix === 16 ? "0x" : radix === 8 ? "0" : "";
|
|
14456
|
-
|
|
14456
|
+
admit3(prefix3.length + part.length);
|
|
14457
14457
|
part = prefix3 + part;
|
|
14458
14458
|
}
|
|
14459
14459
|
}
|
|
14460
|
-
|
|
14460
|
+
admit3(part.length);
|
|
14461
14461
|
part = part.replace(/e([+-])([0-9])$/u, "e$10$2");
|
|
14462
14462
|
if (/[XFEG]/u.test(conversion)) {
|
|
14463
|
-
|
|
14463
|
+
admit3(part.length);
|
|
14464
14464
|
part = part.toUpperCase();
|
|
14465
14465
|
}
|
|
14466
14466
|
if (amount >= 0 && !/[uoxX]/u.test(conversion)) {
|
|
14467
14467
|
const prefix3 = flags3.includes("+") ? "+" : flags3.includes(" ") ? " " : "";
|
|
14468
|
-
|
|
14468
|
+
admit3(prefix3.length + part.length);
|
|
14469
14469
|
part = prefix3 + part;
|
|
14470
14470
|
}
|
|
14471
14471
|
if (flags3.includes("#") && /[fFeE]/u.test(conversion)) {
|
|
14472
14472
|
budget?.step(part.length);
|
|
14473
14473
|
if (!part.includes(".")) {
|
|
14474
|
-
|
|
14474
|
+
admit3(part.length + 1);
|
|
14475
14475
|
part = part.replace(/([eE]|$)/u, ".$1");
|
|
14476
14476
|
}
|
|
14477
14477
|
}
|
|
14478
14478
|
}
|
|
14479
|
-
|
|
14479
|
+
admit3(Math.max(part.length, width));
|
|
14480
14480
|
if (flags3.includes("-")) part = part.padEnd(width, " ");
|
|
14481
14481
|
else if (flags3.includes("0") && /[diuoxXfFeEgG]/u.test(conversion) && (precision === void 0 || /[fFeEgG]/u.test(conversion))) {
|
|
14482
14482
|
const prefix3 = /^(?:[+ -]|0[xX])/u.exec(part)?.[0] ?? "";
|
|
14483
14483
|
part = prefix3 + part.slice(prefix3.length).padStart(Math.max(0, width - prefix3.length), "0");
|
|
14484
14484
|
} else part = part.padStart(width, " ");
|
|
14485
|
-
|
|
14485
|
+
admit3(part.length);
|
|
14486
14486
|
result2 += part;
|
|
14487
14487
|
}
|
|
14488
14488
|
return result2;
|
|
14489
14489
|
}
|
|
14490
|
-
function text(value2,
|
|
14490
|
+
function text(value2, format3 = "%.6g", budget) {
|
|
14491
14491
|
if (value2.kind === "unset") return "";
|
|
14492
14492
|
if (value2.kind !== "number") return value2.text;
|
|
14493
14493
|
if (Number.isInteger(value2.number) && Math.abs(value2.number) < 1e21) {
|
|
@@ -14497,16 +14497,16 @@ function text(value2, format2 = "%.6g", budget) {
|
|
|
14497
14497
|
budget?.step(result2.length);
|
|
14498
14498
|
return result2;
|
|
14499
14499
|
}
|
|
14500
|
-
return formatted(
|
|
14500
|
+
return formatted(format3, [value2], (argument2) => String(number(argument2)), budget);
|
|
14501
14501
|
}
|
|
14502
|
-
function compare3(left, right,
|
|
14502
|
+
function compare3(left, right, format3, budget) {
|
|
14503
14503
|
if (left.kind !== "string" && right.kind !== "string") {
|
|
14504
14504
|
const first2 = number(left);
|
|
14505
14505
|
const second2 = number(right);
|
|
14506
14506
|
return first2 < second2 ? -1 : first2 > second2 ? 1 : 0;
|
|
14507
14507
|
}
|
|
14508
|
-
const first = text(left,
|
|
14509
|
-
const second = text(right,
|
|
14508
|
+
const first = text(left, format3, budget);
|
|
14509
|
+
const second = text(right, format3, budget);
|
|
14510
14510
|
return first < second ? -1 : first > second ? 1 : 0;
|
|
14511
14511
|
}
|
|
14512
14512
|
|
|
@@ -14563,11 +14563,11 @@ var Lexer = class {
|
|
|
14563
14563
|
this.offset += name2.length;
|
|
14564
14564
|
return { kind: "name", text: name2, offset };
|
|
14565
14565
|
}
|
|
14566
|
-
const
|
|
14567
|
-
if (
|
|
14568
|
-
if (!Number.isFinite(Number(
|
|
14569
|
-
this.offset +=
|
|
14570
|
-
return { kind: "number", text:
|
|
14566
|
+
const number6 = /^(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[eE][+-]?[0-9]+)?/u.exec(rest)?.[0];
|
|
14567
|
+
if (number6) {
|
|
14568
|
+
if (!Number.isFinite(Number(number6))) throw new ProgramError("non-finite numeric literal");
|
|
14569
|
+
this.offset += number6.length;
|
|
14570
|
+
return { kind: "number", text: number6, offset };
|
|
14571
14571
|
}
|
|
14572
14572
|
if (rest[0] === '"') {
|
|
14573
14573
|
this.offset++;
|
|
@@ -16923,7 +16923,7 @@ async function diagnostic2(context2, error) {
|
|
|
16923
16923
|
async function* lines2(source2, limits, state, binary3, nullData) {
|
|
16924
16924
|
let pending = import_buffer.Buffer.alloc(0);
|
|
16925
16925
|
let offset = 0;
|
|
16926
|
-
let
|
|
16926
|
+
let number6 = 0;
|
|
16927
16927
|
const delimiter = nullData ? 0 : 10;
|
|
16928
16928
|
for await (const data2 of readBytes(source2, limits.signal)) {
|
|
16929
16929
|
await limits.tick();
|
|
@@ -16943,7 +16943,7 @@ async function* lines2(source2, limits, state, binary3, nullData) {
|
|
|
16943
16943
|
const content = import_buffer.Buffer.concat([pending, chunk.subarray(start, end)]);
|
|
16944
16944
|
const bytes3 = import_buffer.Buffer.concat([content, import_buffer.Buffer.from([delimiter])]);
|
|
16945
16945
|
state.bytesSearched = offset + bytes3.length;
|
|
16946
|
-
yield { content, bytes: bytes3, number: ++
|
|
16946
|
+
yield { content, bytes: bytes3, number: ++number6, offset };
|
|
16947
16947
|
offset += bytes3.length;
|
|
16948
16948
|
pending = import_buffer.Buffer.alloc(0);
|
|
16949
16949
|
start = end + 1;
|
|
@@ -16953,7 +16953,7 @@ async function* lines2(source2, limits, state, binary3, nullData) {
|
|
|
16953
16953
|
}
|
|
16954
16954
|
if (pending.length) {
|
|
16955
16955
|
state.bytesSearched = offset + pending.length;
|
|
16956
|
-
yield { bytes: pending, content: pending, number: ++
|
|
16956
|
+
yield { bytes: pending, content: pending, number: ++number6, offset };
|
|
16957
16957
|
}
|
|
16958
16958
|
}
|
|
16959
16959
|
|
|
@@ -17499,7 +17499,7 @@ function createGrepCommands(executor) {
|
|
|
17499
17499
|
const patterns2 = [];
|
|
17500
17500
|
let patternCount = 0;
|
|
17501
17501
|
let patternBytes = 0;
|
|
17502
|
-
const
|
|
17502
|
+
const admit3 = (chunk, atStart) => {
|
|
17503
17503
|
context2.signal.throwIfAborted();
|
|
17504
17504
|
const size = typeof chunk === "string" ? import_buffer.Buffer.byteLength(chunk) : chunk.length;
|
|
17505
17505
|
if (size > bufferLimit - patternBytes) throw new UsageError(`pattern byte limit exceeded (${bufferLimit} bytes)`);
|
|
@@ -17514,7 +17514,7 @@ function createGrepCommands(executor) {
|
|
|
17514
17514
|
return atStart;
|
|
17515
17515
|
};
|
|
17516
17516
|
const addArgument = async (pattern) => {
|
|
17517
|
-
|
|
17517
|
+
admit3(pattern, true);
|
|
17518
17518
|
if (pattern === "") {
|
|
17519
17519
|
if (++patternCount > maxPatternCount) throw new UsageError(`pattern count limit exceeded (${maxPatternCount})`);
|
|
17520
17520
|
patterns2.push("");
|
|
@@ -17525,7 +17525,7 @@ function createGrepCommands(executor) {
|
|
|
17525
17525
|
async function* admitted(source2) {
|
|
17526
17526
|
let atStart = true;
|
|
17527
17527
|
for await (const chunk of source2) {
|
|
17528
|
-
atStart =
|
|
17528
|
+
atStart = admit3(chunk, atStart);
|
|
17529
17529
|
yield chunk;
|
|
17530
17530
|
}
|
|
17531
17531
|
}
|
|
@@ -17554,9 +17554,9 @@ function createGrepCommands(executor) {
|
|
|
17554
17554
|
let failed = false;
|
|
17555
17555
|
for (const name2 of names) {
|
|
17556
17556
|
let count2 = 0;
|
|
17557
|
-
let
|
|
17557
|
+
let number6 = 0;
|
|
17558
17558
|
const named2 = name2 === "-" ? "(standard input)" : name2;
|
|
17559
|
-
const prefix3 = (lineNumber = false) => `${!parsed.flags.has("h") && (parsed.flags.has("H") || names.length > 1) ? `${named2}:` : ""}${lineNumber && parsed.flags.has("n") ? `${
|
|
17559
|
+
const prefix3 = (lineNumber = false) => `${!parsed.flags.has("h") && (parsed.flags.has("H") || names.length > 1) ? `${named2}:` : ""}${lineNumber && parsed.flags.has("n") ? `${number6}:` : ""}`;
|
|
17560
17560
|
try {
|
|
17561
17561
|
const available2 = new AvailableRecords(parsed.flags.has("z") ? 0 : 10, bufferLimit);
|
|
17562
17562
|
const source2 = name2 === "-" ? input(context2) : requiredFileInput(context2, grepRequirements, "file", name2, bufferLimit);
|
|
@@ -17565,7 +17565,7 @@ function createGrepCommands(executor) {
|
|
|
17565
17565
|
for (let index = 0; index < batch.length; index++) {
|
|
17566
17566
|
const line = batch[index];
|
|
17567
17567
|
context2.signal.throwIfAborted();
|
|
17568
|
-
|
|
17568
|
+
number6++;
|
|
17569
17569
|
const found = results[index];
|
|
17570
17570
|
if (found.length > 0 === parsed.flags.has("v")) continue;
|
|
17571
17571
|
count2++;
|
|
@@ -17625,9 +17625,9 @@ init_platform();
|
|
|
17625
17625
|
// packages/safe-bash/src/commands/bytes/encoding/shared.ts
|
|
17626
17626
|
init_platform();
|
|
17627
17627
|
var blockSize = 8192;
|
|
17628
|
-
function validatedOption(parsed, key,
|
|
17628
|
+
function validatedOption(parsed, key, parse19, fallback) {
|
|
17629
17629
|
let result2 = fallback;
|
|
17630
|
-
for (const text3 of parsed.values.get(key) ?? []) result2 =
|
|
17630
|
+
for (const text3 of parsed.values.get(key) ?? []) result2 = parse19(text3);
|
|
17631
17631
|
return result2;
|
|
17632
17632
|
}
|
|
17633
17633
|
async function* sources(context2, operands, maxInputBytes) {
|
|
@@ -17769,7 +17769,7 @@ function decodeQuantum(quantum, alphabet) {
|
|
|
17769
17769
|
}
|
|
17770
17770
|
carry &= (1 << bits) - 1;
|
|
17771
17771
|
}
|
|
17772
|
-
return { bytes: decoded, valid: quantum.length === alphabet.quantum && alphabet.lengths.includes(length) && quantum.slice(length).every((
|
|
17772
|
+
return { bytes: decoded, valid: quantum.length === alphabet.quantum && alphabet.lengths.includes(length) && quantum.slice(length).every((number6) => number6 === -1) && carry === 0 };
|
|
17773
17773
|
}
|
|
17774
17774
|
async function decode(context2, files, alphabet, ignore, maxInputBytes) {
|
|
17775
17775
|
const lookup = new Int16Array(256).fill(-2);
|
|
@@ -17831,27 +17831,27 @@ function formats(text3) {
|
|
|
17831
17831
|
if (!result2.length) throw new UsageError("empty output type");
|
|
17832
17832
|
return result2;
|
|
17833
17833
|
}
|
|
17834
|
-
function formatRow(row,
|
|
17834
|
+
function formatRow(row, format3, bigEndian) {
|
|
17835
17835
|
let text3 = "";
|
|
17836
17836
|
const escapes = { 0: "\\0", 7: "\\a", 8: "\\b", 9: "\\t", 10: "\\n", 11: "\\v", 12: "\\f", 13: "\\r" };
|
|
17837
|
-
for (let offset = 0; offset < row.length; offset +=
|
|
17838
|
-
if (
|
|
17837
|
+
for (let offset = 0; offset < row.length; offset += format3.size) {
|
|
17838
|
+
if (format3.kind === "c") {
|
|
17839
17839
|
const byte = row[offset];
|
|
17840
17840
|
const character = escapes[byte] ?? (byte >= 32 && byte <= 126 ? String.fromCharCode(byte) : byte.toString(8).padStart(3, "0"));
|
|
17841
17841
|
text3 += ` ${character.padStart(3)}`;
|
|
17842
17842
|
continue;
|
|
17843
17843
|
}
|
|
17844
|
-
let
|
|
17845
|
-
for (let index = 0; index <
|
|
17844
|
+
let number6 = 0n;
|
|
17845
|
+
for (let index = 0; index < format3.size; index++) {
|
|
17846
17846
|
const byte = row[offset + index] ?? 0;
|
|
17847
|
-
const shift = bigEndian ?
|
|
17848
|
-
|
|
17847
|
+
const shift = bigEndian ? format3.size - index - 1 : index;
|
|
17848
|
+
number6 |= BigInt(byte) << BigInt(shift * 8);
|
|
17849
17849
|
}
|
|
17850
|
-
const bits =
|
|
17851
|
-
if (
|
|
17852
|
-
const base =
|
|
17853
|
-
const width =
|
|
17854
|
-
text3 += ` ${
|
|
17850
|
+
const bits = format3.size * 8;
|
|
17851
|
+
if (format3.kind === "d" && number6 >= 1n << BigInt(bits - 1)) number6 -= 1n << BigInt(bits);
|
|
17852
|
+
const base = format3.kind === "o" ? 8 : format3.kind === "x" ? 16 : 10;
|
|
17853
|
+
const width = format3.kind === "o" ? Math.ceil(bits / 3) : format3.kind === "x" ? bits / 4 : format3.kind === "d" ? (1n << BigInt(bits - 1)).toString().length + 1 : ((1n << BigInt(bits)) - 1n).toString().length;
|
|
17854
|
+
text3 += ` ${number6.toString(base).padStart(width, base === 10 ? " " : "0")}`;
|
|
17855
17855
|
}
|
|
17856
17856
|
return text3;
|
|
17857
17857
|
}
|
|
@@ -17904,9 +17904,9 @@ function createOdCommand(maxInputBytes) {
|
|
|
17904
17904
|
const selected = (parsed.values.get("t") ?? ["o2"]).flatMap(formats);
|
|
17905
17905
|
if (selected.length > 16) throw new UsageError("at most 16 output types are supported");
|
|
17906
17906
|
const width = validatedOption(parsed, "w", (text3) => {
|
|
17907
|
-
const
|
|
17908
|
-
if (
|
|
17909
|
-
return
|
|
17907
|
+
const number6 = numeric2(text3);
|
|
17908
|
+
if (number6 < 1 || number6 > 4096 || selected.some((format3) => number6 % format3.size !== 0)) throw new UsageError("width must be 1..4096 and a multiple of each output type size");
|
|
17909
|
+
return number6;
|
|
17910
17910
|
}, 16);
|
|
17911
17911
|
const skip = validatedOption(parsed, "j", (text3) => numeric2(text3, true), 0);
|
|
17912
17912
|
const count2 = validatedOption(parsed, "N", (text3) => numeric2(text3, true), Infinity);
|
|
@@ -18016,14 +18016,14 @@ function createXxdCommand(maxInputBytes) {
|
|
|
18016
18016
|
const plain = parsed.flags.has("p");
|
|
18017
18017
|
const reverse = parsed.flags.has("r");
|
|
18018
18018
|
const columns = validatedOption(parsed, "c", (text3) => {
|
|
18019
|
-
const
|
|
18020
|
-
if (!plain && (
|
|
18021
|
-
return
|
|
18019
|
+
const number6 = numeric2(text3);
|
|
18020
|
+
if (!plain && (number6 < 1 || number6 > 256) || plain && number6 > 4096) throw new UsageError("columns must be 1..256 (plain: 0..4096)");
|
|
18021
|
+
return number6;
|
|
18022
18022
|
}, plain ? 30 : 16);
|
|
18023
18023
|
const group = validatedOption(parsed, "g", (text3) => {
|
|
18024
|
-
const
|
|
18025
|
-
if (
|
|
18026
|
-
return
|
|
18024
|
+
const number6 = numeric2(text3);
|
|
18025
|
+
if (number6 > 256) throw new UsageError("group size must be 0..256");
|
|
18026
|
+
return number6;
|
|
18027
18027
|
}, 2);
|
|
18028
18028
|
const skip = validatedOption(parsed, "s", numeric2, 0);
|
|
18029
18029
|
const count2 = validatedOption(parsed, "l", numeric2, Infinity);
|
|
@@ -22322,9 +22322,9 @@ async function* codec(input3, options3, signal) {
|
|
|
22322
22322
|
if (!Number.isSafeInteger(requestedSize) || requestedSize <= 0) throw new RangeError("invalid codec chunk size");
|
|
22323
22323
|
const chunkSize2 = Math.min(requestedSize, 64 * 1024);
|
|
22324
22324
|
let output2 = new Uint8Array(chunkSize2);
|
|
22325
|
-
const encoding = options3.mode === "gzip";
|
|
22325
|
+
const encoding = options3.mode === "gzip" || options3.mode === "deflate-raw";
|
|
22326
22326
|
const stream = new ZStream();
|
|
22327
|
-
const initialized = encoding ? deflateInit2(stream, options3.level ?? 6, 8, 31, 8, 0, true) : inflateInit2(stream, options3.mode === "inflate-raw" ? -15 : 31);
|
|
22327
|
+
const initialized = encoding ? deflateInit2(stream, options3.level ?? 6, 8, options3.mode === "deflate-raw" ? -15 : 31, 8, 0, true) : inflateInit2(stream, options3.mode === "inflate-raw" ? -15 : 31);
|
|
22328
22328
|
if (initialized !== Z_OK) {
|
|
22329
22329
|
if (encoding) deflateEnd(stream);
|
|
22330
22330
|
else inflateEnd(stream);
|
|
@@ -23240,9 +23240,9 @@ async function contextSide(changes, start, end, kind, budget, append) {
|
|
|
23240
23240
|
}
|
|
23241
23241
|
}
|
|
23242
23242
|
}
|
|
23243
|
-
async function contextual(changes,
|
|
23243
|
+
async function contextual(changes, format3, oldLabel, newLabel, context2, budget, append) {
|
|
23244
23244
|
context2 = Math.min(context2, changes.length);
|
|
23245
|
-
append(
|
|
23245
|
+
append(format3 === "unified" ? `--- ${oldLabel}
|
|
23246
23246
|
+++ ${newLabel}
|
|
23247
23247
|
` : `*** ${oldLabel}
|
|
23248
23248
|
--- ${newLabel}
|
|
@@ -23288,7 +23288,7 @@ async function contextual(changes, format2, oldLabel, newLabel, context2, budget
|
|
|
23288
23288
|
await budget.checkpoint();
|
|
23289
23289
|
}
|
|
23290
23290
|
budget.hunk();
|
|
23291
|
-
if (
|
|
23291
|
+
if (format3 === "unified") {
|
|
23292
23292
|
append(`@@ -${unifiedRange(oldPosition, oldCount)} +${unifiedRange(newPosition, newCount)} @@
|
|
23293
23293
|
`);
|
|
23294
23294
|
for (let index = start; index < end; index++) {
|
|
@@ -23322,15 +23322,15 @@ function contextLength(value2) {
|
|
|
23322
23322
|
function flags(args) {
|
|
23323
23323
|
const result2 = { format: "normal", whitespace: "exact", context: 0, brief: false, recursive: false, newFile: false, labels: [], files: [] };
|
|
23324
23324
|
let selectedFormat;
|
|
23325
|
-
const selectFormat = (
|
|
23326
|
-
if (selectedFormat !== void 0 && selectedFormat !==
|
|
23327
|
-
selectedFormat = result2.format =
|
|
23325
|
+
const selectFormat = (format3) => {
|
|
23326
|
+
if (selectedFormat !== void 0 && selectedFormat !== format3) throw new ToolError("conflicting output format options");
|
|
23327
|
+
selectedFormat = result2.format = format3;
|
|
23328
23328
|
};
|
|
23329
23329
|
let explicitContext = false;
|
|
23330
23330
|
let legacyContext = -1;
|
|
23331
23331
|
let previousDigit = false;
|
|
23332
|
-
const selectContext = (
|
|
23333
|
-
selectFormat(
|
|
23332
|
+
const selectContext = (format3, width, explicit) => {
|
|
23333
|
+
selectFormat(format3);
|
|
23334
23334
|
result2.context = Math.max(result2.context, width);
|
|
23335
23335
|
explicitContext ||= explicit;
|
|
23336
23336
|
};
|
|
@@ -24085,7 +24085,7 @@ async function context(reader) {
|
|
|
24085
24085
|
}
|
|
24086
24086
|
return output2.join("");
|
|
24087
24087
|
}
|
|
24088
|
-
async function parsePatch(text3, budget,
|
|
24088
|
+
async function parsePatch(text3, budget, format3, target, progress) {
|
|
24089
24089
|
if (text3 && !text3.endsWith("\n")) throw new ToolError("patch is truncated: missing final LF");
|
|
24090
24090
|
const reader = new Reader2(text3, budget);
|
|
24091
24091
|
const patches = [];
|
|
@@ -24112,7 +24112,7 @@ async function parsePatch(text3, budget, format2, target, progress) {
|
|
|
24112
24112
|
while (/^diff /u.test(reader.peek() ?? "")) await reader.take();
|
|
24113
24113
|
const first = reader.peek() ?? "";
|
|
24114
24114
|
const detected = first.startsWith("*** ") ? "context" : /^\d/u.test(first) ? "normal" : "unified";
|
|
24115
|
-
if (
|
|
24115
|
+
if (format3 && detected !== format3) throw new ToolError(`patch format is ${detected}, not requested ${format3}`);
|
|
24116
24116
|
if (detected === "unified") {
|
|
24117
24117
|
reader.index = start;
|
|
24118
24118
|
patches.push(...(await parseUnifiedSection(reader, budget)).map((patch) => ({ ...patch, ...indexPath === void 0 ? {} : { indexPath } })));
|
|
@@ -24208,8 +24208,8 @@ async function backupName(path, budget) {
|
|
|
24208
24208
|
const version = entry.name.slice(prefix3.length, -1);
|
|
24209
24209
|
if (version.length > 4096) throw new ToolError("backup version length limit exceeded");
|
|
24210
24210
|
if (!/^[1-9]\d*$/u.test(version)) continue;
|
|
24211
|
-
const
|
|
24212
|
-
if (
|
|
24211
|
+
const number6 = BigInt(version);
|
|
24212
|
+
if (number6 > maximum) maximum = number6;
|
|
24213
24213
|
}
|
|
24214
24214
|
return maximum ? `${path}.~${maximum + 1n}~` : `${path}.orig`;
|
|
24215
24215
|
}
|
|
@@ -24404,8 +24404,8 @@ ${context2 ? "---" : "+++"} ${names[1]}${times[1]}
|
|
|
24404
24404
|
function flags2(args) {
|
|
24405
24405
|
const result2 = { input: "-", reverse: false, dryRun: false, atomic: false, quiet: false, force: false, backup: true, fuzz: 2, ignoreWhitespace: false, removeEmpty: false };
|
|
24406
24406
|
const operands = [];
|
|
24407
|
-
const select = (
|
|
24408
|
-
result2.format =
|
|
24407
|
+
const select = (format3) => {
|
|
24408
|
+
result2.format = format3;
|
|
24409
24409
|
};
|
|
24410
24410
|
let literal = false;
|
|
24411
24411
|
for (let index = 0; index < args.length; index++) {
|
|
@@ -24918,7 +24918,7 @@ function createChmodCommand(configuration = {}) {
|
|
|
24918
24918
|
init_platform();
|
|
24919
24919
|
function parse9(args) {
|
|
24920
24920
|
let follow = false;
|
|
24921
|
-
let
|
|
24921
|
+
let format3;
|
|
24922
24922
|
let printf = false;
|
|
24923
24923
|
let literal = false;
|
|
24924
24924
|
const paths = [];
|
|
@@ -24929,14 +24929,14 @@ function parse9(args) {
|
|
|
24929
24929
|
else if (argument2 === "--dereference") follow = true;
|
|
24930
24930
|
else if (argument2 === "--format" || argument2.startsWith("--format=") || argument2 === "--printf" || argument2.startsWith("--printf=")) {
|
|
24931
24931
|
printf = argument2.startsWith("--printf");
|
|
24932
|
-
|
|
24933
|
-
if (
|
|
24932
|
+
format3 = argument2.includes("=") ? argument2.slice(argument2.indexOf("=") + 1) : args[++index];
|
|
24933
|
+
if (format3 === void 0) throw new UsageError(`missing format for '${argument2}'`);
|
|
24934
24934
|
} else if (!argument2.startsWith("--")) {
|
|
24935
24935
|
for (let offset = 1; offset < argument2.length; offset++) {
|
|
24936
24936
|
if (argument2[offset] === "L") follow = true;
|
|
24937
24937
|
else if (argument2[offset] === "c") {
|
|
24938
|
-
|
|
24939
|
-
if (
|
|
24938
|
+
format3 = argument2.slice(offset + 1) || args[++index];
|
|
24939
|
+
if (format3 === void 0) throw new UsageError("missing format for '-c'");
|
|
24940
24940
|
printf = false;
|
|
24941
24941
|
break;
|
|
24942
24942
|
} else throw new UsageError(`unrecognized option '${argument2}'`);
|
|
@@ -24944,7 +24944,7 @@ function parse9(args) {
|
|
|
24944
24944
|
} else throw new UsageError(`unrecognized option '${argument2}'`);
|
|
24945
24945
|
}
|
|
24946
24946
|
requireOperands(paths);
|
|
24947
|
-
return { follow, format:
|
|
24947
|
+
return { follow, format: format3, printf, paths };
|
|
24948
24948
|
}
|
|
24949
24949
|
function quoted(text3, style2) {
|
|
24950
24950
|
if (style2 === "literal") return text3;
|
|
@@ -24977,9 +24977,9 @@ function timestamp2(milliseconds) {
|
|
|
24977
24977
|
const nanoseconds = value2 < 0 ? -magnitude : magnitude;
|
|
24978
24978
|
const remainder = (nanoseconds % 1000000000n + 1000000000n) % 1000000000n;
|
|
24979
24979
|
const seconds = (nanoseconds - remainder) / 1000000000n;
|
|
24980
|
-
const
|
|
24981
|
-
if (Number.isNaN(
|
|
24982
|
-
return `${
|
|
24980
|
+
const date2 = new Date(Number(seconds * 1000n));
|
|
24981
|
+
if (Number.isNaN(date2.getTime())) throw new FsError("EIO", { message: "invalid filesystem timestamp" });
|
|
24982
|
+
return `${date2.toISOString().replace("T", " ").replace(/\.\d{3}Z$/u, `.${remainder.toString().padStart(9, "0")}`)} +0000`;
|
|
24983
24983
|
}
|
|
24984
24984
|
function epoch(milliseconds, precision) {
|
|
24985
24985
|
if (precision > 3) throw new FsError("ENOTSUP", { message: "stat timestamps support at most millisecond precision" });
|
|
@@ -24990,21 +24990,21 @@ function epoch(milliseconds, precision) {
|
|
|
24990
24990
|
const seconds = value2 < 0 && fraction === 0 ? -Math.floor(value2 / 1e3) : Math.floor(absolute2 / scale);
|
|
24991
24991
|
return `${value2 < 0 ? "-" : ""}${seconds}${precision ? "." + fraction.toString().padStart(precision, "0") : ""}`;
|
|
24992
24992
|
}
|
|
24993
|
-
function directive(
|
|
24993
|
+
function directive(format3, start) {
|
|
24994
24994
|
let index = start + 1;
|
|
24995
24995
|
const flagsStart = index;
|
|
24996
|
-
while (index <
|
|
24997
|
-
const flags3 =
|
|
24996
|
+
while (index < format3.length && "-+ #0".includes(format3[index])) index++;
|
|
24997
|
+
const flags3 = format3.slice(flagsStart, index);
|
|
24998
24998
|
const widthStart = index;
|
|
24999
|
-
while (index <
|
|
25000
|
-
const width =
|
|
24999
|
+
while (index < format3.length && format3[index] >= "0" && format3[index] <= "9") index++;
|
|
25000
|
+
const width = format3.slice(widthStart, index);
|
|
25001
25001
|
let precision;
|
|
25002
|
-
if (
|
|
25002
|
+
if (format3[index] === ".") {
|
|
25003
25003
|
const precisionStart = ++index;
|
|
25004
|
-
while (index <
|
|
25005
|
-
precision =
|
|
25004
|
+
while (index < format3.length && format3[index] >= "0" && format3[index] <= "9") index++;
|
|
25005
|
+
precision = format3.slice(precisionStart, index);
|
|
25006
25006
|
}
|
|
25007
|
-
const code =
|
|
25007
|
+
const code = format3[index];
|
|
25008
25008
|
if (code === void 0) throw new UsageError("invalid stat format directive");
|
|
25009
25009
|
const codePoint = code.charCodeAt(0);
|
|
25010
25010
|
if (code !== "%" && !(codePoint >= 65 && codePoint <= 90) && !(codePoint >= 97 && codePoint <= 122)) {
|
|
@@ -25036,7 +25036,7 @@ function formatField(text3, code, flags3, width, precision, numeric4, epoch2) {
|
|
|
25036
25036
|
}
|
|
25037
25037
|
return import_buffer.Buffer.concat([import_buffer.Buffer.alloc(padding, 32), bytes3]);
|
|
25038
25038
|
}
|
|
25039
|
-
async function render(context2, path, name2, stat,
|
|
25039
|
+
async function render(context2, path, name2, stat, format3, escapes, limit) {
|
|
25040
25040
|
const chunks = [];
|
|
25041
25041
|
let bytes3 = 0;
|
|
25042
25042
|
const append = (text3) => {
|
|
@@ -25045,11 +25045,11 @@ async function render(context2, path, name2, stat, format2, escapes, limit) {
|
|
|
25045
25045
|
if (bytes3 > limit) throw new FsError("EFBIG", { message: "stat format output limit exceeded" });
|
|
25046
25046
|
chunks.push(chunk);
|
|
25047
25047
|
};
|
|
25048
|
-
for (let index = 0; index <
|
|
25048
|
+
for (let index = 0; index < format3.length; ) {
|
|
25049
25049
|
context2.signal.throwIfAborted();
|
|
25050
|
-
if (escapes &&
|
|
25050
|
+
if (escapes && format3[index] === "\\") {
|
|
25051
25051
|
const named2 = { a: "\x07", b: "\b", e: "\x1B", f: "\f", n: "\n", r: "\r", t: " ", v: "\v", "\\": "\\" };
|
|
25052
|
-
const code2 =
|
|
25052
|
+
const code2 = format3[index + 1] ?? "";
|
|
25053
25053
|
if (Object.hasOwn(named2, code2)) {
|
|
25054
25054
|
append(named2[code2]);
|
|
25055
25055
|
index += 2;
|
|
@@ -25057,30 +25057,30 @@ async function render(context2, path, name2, stat, format2, escapes, limit) {
|
|
|
25057
25057
|
}
|
|
25058
25058
|
const radix = code2 === "x" ? 16 : 8;
|
|
25059
25059
|
const start = index + (radix === 16 ? 2 : 1);
|
|
25060
|
-
const end = Math.min(
|
|
25060
|
+
const end = Math.min(format3.length, start + (radix === 16 ? 2 : 3));
|
|
25061
25061
|
let offset = start;
|
|
25062
25062
|
let value2 = 0;
|
|
25063
25063
|
while (offset < end) {
|
|
25064
|
-
const digit3 = "0123456789abcdef".indexOf(
|
|
25064
|
+
const digit3 = "0123456789abcdef".indexOf(format3[offset].toLowerCase());
|
|
25065
25065
|
if (digit3 < 0 || digit3 >= radix) break;
|
|
25066
25066
|
value2 = value2 * radix + digit3;
|
|
25067
25067
|
offset++;
|
|
25068
25068
|
}
|
|
25069
25069
|
if (offset === start) {
|
|
25070
|
-
append(
|
|
25070
|
+
append(format3[index++]);
|
|
25071
25071
|
continue;
|
|
25072
25072
|
}
|
|
25073
25073
|
append(Uint8Array.of(value2));
|
|
25074
25074
|
index = offset;
|
|
25075
25075
|
continue;
|
|
25076
25076
|
}
|
|
25077
|
-
if (
|
|
25078
|
-
const point = String.fromCodePoint(
|
|
25077
|
+
if (format3[index] !== "%") {
|
|
25078
|
+
const point = String.fromCodePoint(format3.codePointAt(index));
|
|
25079
25079
|
append(point);
|
|
25080
25080
|
index += point.length;
|
|
25081
25081
|
continue;
|
|
25082
25082
|
}
|
|
25083
|
-
const parsed = directive(
|
|
25083
|
+
const parsed = directive(format3, index);
|
|
25084
25084
|
index += parsed.length;
|
|
25085
25085
|
const { code, flags: flags3 } = parsed;
|
|
25086
25086
|
const width = Number(parsed.width || 0);
|
|
@@ -25136,8 +25136,8 @@ function createStatCommand(configuration = {}) {
|
|
|
25136
25136
|
try {
|
|
25137
25137
|
const path = pathOf(context2, name2);
|
|
25138
25138
|
const stat = await context2.fs[parsed.follow ? "stat" : "lstat"](path, { signal: context2.signal });
|
|
25139
|
-
const
|
|
25140
|
-
const text3 = await render(context2, path, name2, stat,
|
|
25139
|
+
const format3 = parsed.format ?? " File: %N\n Size: %s Type: %F\n Mode: %a (%A)\nAccess: %x\nModify: %y\nChange: %z\n Birth: %w";
|
|
25140
|
+
const text3 = await render(context2, path, name2, stat, format3, parsed.printf, configured.limits.maxOutputBytes);
|
|
25141
25141
|
await budget.output(parsed.printf ? text3 : import_buffer.Buffer.concat([text3, Uint8Array.of(10)]));
|
|
25142
25142
|
} catch (error) {
|
|
25143
25143
|
context2.signal.throwIfAborted();
|
|
@@ -26896,12 +26896,12 @@ function truncateCommand(options3 = {}) {
|
|
|
26896
26896
|
}
|
|
26897
26897
|
}
|
|
26898
26898
|
outputBytes += length;
|
|
26899
|
-
const
|
|
26899
|
+
const encoder5 = new TextEncoder();
|
|
26900
26900
|
for (let offset = 0; offset < text3.length; ) {
|
|
26901
26901
|
let end = Math.min(text3.length, offset + (utf82 ? 16384 : 65536));
|
|
26902
26902
|
if (utf82 && end < text3.length && text3.charCodeAt(end - 1) >= 55296 && text3.charCodeAt(end - 1) <= 56319) end--;
|
|
26903
26903
|
const chunk = text3.slice(offset, end);
|
|
26904
|
-
await writeBytes(error ? stderr.output : stdout.output, utf82 ?
|
|
26904
|
+
await writeBytes(error ? stderr.output : stdout.output, utf82 ? encoder5.encode(chunk) : Uint8Array.from(chunk, (character) => character.charCodeAt(0)), signal);
|
|
26905
26905
|
offset = end;
|
|
26906
26906
|
}
|
|
26907
26907
|
};
|
|
@@ -27476,7 +27476,7 @@ async function parseOptions2(context2, limits) {
|
|
|
27476
27476
|
let gzip = false;
|
|
27477
27477
|
let verbose2 = false;
|
|
27478
27478
|
let strip = 0;
|
|
27479
|
-
let
|
|
27479
|
+
let format3 = "pax";
|
|
27480
27480
|
let cwd = context2.cwd;
|
|
27481
27481
|
let nullFiles = false;
|
|
27482
27482
|
let verbatim = false;
|
|
@@ -27545,7 +27545,7 @@ async function parseOptions2(context2, limits) {
|
|
|
27545
27545
|
strip = Number(value2);
|
|
27546
27546
|
} else if (flag === "format") {
|
|
27547
27547
|
if (value2 !== "ustar" && value2 !== "pax" && value2 !== "posix") fail2(`unsupported archive format: ${value2}`);
|
|
27548
|
-
|
|
27548
|
+
format3 = value2 === "ustar" ? "ustar" : "pax";
|
|
27549
27549
|
} else if (flag === "null") {
|
|
27550
27550
|
nullFiles = true;
|
|
27551
27551
|
verbatim = true;
|
|
@@ -27593,7 +27593,7 @@ async function parseOptions2(context2, limits) {
|
|
|
27593
27593
|
if (mode === "c" && lateExclude) fail2("--exclude after source operands is unsupported; place exclusions before operands");
|
|
27594
27594
|
if (mode === "c" && !operands.length && !filesFrom) fail2("refusing to create an empty archive without -T");
|
|
27595
27595
|
if (archive !== "-") checkPath(archive, limits);
|
|
27596
|
-
return { mode, archive, gzip, verbose: verbose2, strip, format:
|
|
27596
|
+
return { mode, archive, gzip, verbose: verbose2, strip, format: format3, cwd, operands, excludes };
|
|
27597
27597
|
}
|
|
27598
27598
|
function tokenize(pattern) {
|
|
27599
27599
|
const characters = Array.from(pattern);
|
|
@@ -28176,6 +28176,1545 @@ async function readArchive(context2, source2, options3, budget) {
|
|
|
28176
28176
|
}
|
|
28177
28177
|
}
|
|
28178
28178
|
|
|
28179
|
+
// packages/safe-bash/src/commands/archive/zip.ts
|
|
28180
|
+
init_platform();
|
|
28181
|
+
|
|
28182
|
+
// packages/safe-bash/src/commands/archive/zip-format.ts
|
|
28183
|
+
init_platform();
|
|
28184
|
+
var encoder2 = new TextEncoder();
|
|
28185
|
+
var cp437 = "\xC7\xFC\xE9\xE2\xE4\xE0\xE5\xE7\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xFF\xD6\xDC\xA2\xA3\xA5\u20A7\u0192\xE1\xED\xF3\xFA\xF1\xD1\xAA\xBA\xBF\u2310\xAC\xBD\xBC\xA1\xAB\xBB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\xDF\u0393\u03C0\u03A3\u03C3\xB5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\xB1\u2265\u2264\u2320\u2321\xF7\u2248\xB0\u2219\xB7\u221A\u207F\xB2\u25A0\xA0";
|
|
28186
|
+
var crcTable4 = Uint32Array.from({ length: 256 }, (_, index) => {
|
|
28187
|
+
let value2 = index;
|
|
28188
|
+
for (let bit = 0; bit < 8; bit++) value2 = value2 >>> 1 ^ (value2 & 1 ? 3988292384 : 0);
|
|
28189
|
+
return value2 >>> 0;
|
|
28190
|
+
});
|
|
28191
|
+
function crc322(bytes3, previous = 0) {
|
|
28192
|
+
let value2 = previous ^ 4294967295;
|
|
28193
|
+
for (const byte of bytes3) value2 = value2 >>> 8 ^ crcTable4[(value2 ^ byte) & 255];
|
|
28194
|
+
return (value2 ^ 4294967295) >>> 0;
|
|
28195
|
+
}
|
|
28196
|
+
function number3(value2, maximum, label) {
|
|
28197
|
+
if (!Number.isSafeInteger(value2) || value2 < 0 || value2 > maximum) fail2(`ZIP ${label} limit exceeded or invalid value`);
|
|
28198
|
+
}
|
|
28199
|
+
function admit2(limits, signal) {
|
|
28200
|
+
signal.throwIfAborted();
|
|
28201
|
+
for (const key of ["maxArchiveBytes", "maxEntryBytes", "maxTotalBytes", "maxMembers", "maxPathBytes", "maxDepth", "maxPaxBytes", "maxTextBytes", "chunkSize"]) {
|
|
28202
|
+
number3(limits[key], Number.MAX_SAFE_INTEGER, key);
|
|
28203
|
+
}
|
|
28204
|
+
if (limits.chunkSize < 512 || limits.chunkSize > 1024 * 1024) fail2("ZIP chunk size must be between 512 and 1048576");
|
|
28205
|
+
return Math.min(limits.chunkSize, 64 * 1024);
|
|
28206
|
+
}
|
|
28207
|
+
function pathBytes(name2, limits) {
|
|
28208
|
+
if (name2.length > Math.min(limits.maxPathBytes, 65535)) fail2("ZIP path byte limit exceeded");
|
|
28209
|
+
const bytes3 = encoder2.encode(name2);
|
|
28210
|
+
if (!name2 || text2(bytes3) !== name2 || name2.includes("\0")) fail2("ZIP invalid or unsafe path");
|
|
28211
|
+
number3(bytes3.length, Math.min(limits.maxPathBytes, 65535), "path byte");
|
|
28212
|
+
const parts = name2.split("/");
|
|
28213
|
+
if (parts.at(-1) === "") parts.pop();
|
|
28214
|
+
if (parts.some((part) => !part || part === "." || part === "..")) fail2("ZIP unsafe traversal or absolute path");
|
|
28215
|
+
number3(parts.length, limits.maxDepth, "path depth");
|
|
28216
|
+
return bytes3;
|
|
28217
|
+
}
|
|
28218
|
+
function equal(first, second) {
|
|
28219
|
+
return first.length === second.length && first.every((byte, index) => byte === second[index]);
|
|
28220
|
+
}
|
|
28221
|
+
function legacyName(bytes3) {
|
|
28222
|
+
let name2 = "";
|
|
28223
|
+
for (const byte of bytes3) name2 += byte < 128 ? String.fromCharCode(byte) : cp437[byte - 128];
|
|
28224
|
+
return name2;
|
|
28225
|
+
}
|
|
28226
|
+
function extras(bytes3, rawName, comment2, central, limits) {
|
|
28227
|
+
number3(bytes3.length, Math.min(limits.maxPaxBytes, 65535), "extra field");
|
|
28228
|
+
const result2 = {};
|
|
28229
|
+
const view = new DataView(bytes3.buffer, bytes3.byteOffset, bytes3.byteLength);
|
|
28230
|
+
const seen = /* @__PURE__ */ new Set();
|
|
28231
|
+
let offset = 0;
|
|
28232
|
+
while (offset < bytes3.length) {
|
|
28233
|
+
if (offset + 4 > bytes3.length) fail2("ZIP truncated extra field");
|
|
28234
|
+
const identifier = view.getUint16(offset, true);
|
|
28235
|
+
const length = view.getUint16(offset + 2, true);
|
|
28236
|
+
offset += 4;
|
|
28237
|
+
if (offset + length > bytes3.length) fail2("ZIP truncated extra field payload");
|
|
28238
|
+
if (seen.has(identifier)) fail2("ZIP duplicate extra field");
|
|
28239
|
+
seen.add(identifier);
|
|
28240
|
+
if (identifier === 1) fail2("ZIP64 is unsupported");
|
|
28241
|
+
if (identifier === 39169 || identifier === 23 || identifier === 24 || identifier === 25) fail2("ZIP encryption is unsupported");
|
|
28242
|
+
if (identifier === 28789 || identifier === 25461) {
|
|
28243
|
+
if (length < 5 || bytes3[offset] !== 1) fail2("ZIP unsupported or truncated Unicode extra field");
|
|
28244
|
+
const original = identifier === 28789 ? rawName : comment2;
|
|
28245
|
+
if (view.getUint32(offset + 1, true) !== crc322(original)) fail2("ZIP Unicode extra field CRC mismatch");
|
|
28246
|
+
const decoded = text2(bytes3.subarray(offset + 5, offset + length));
|
|
28247
|
+
if (identifier === 28789) {
|
|
28248
|
+
pathBytes(decoded, limits);
|
|
28249
|
+
result2.name = decoded;
|
|
28250
|
+
} else number3(length - 5, limits.maxTextBytes, "Unicode comment");
|
|
28251
|
+
}
|
|
28252
|
+
if (identifier === 21589) {
|
|
28253
|
+
if (!length) fail2("ZIP truncated timestamp extra field");
|
|
28254
|
+
const flags3 = bytes3[offset];
|
|
28255
|
+
if (flags3 & ~7) fail2("ZIP unsupported timestamp flags");
|
|
28256
|
+
const count2 = (flags3 & 1) + (central ? 0 : (flags3 >>> 1 & 1) + (flags3 >>> 2 & 1));
|
|
28257
|
+
if (length !== 1 + count2 * 4) fail2("ZIP truncated or inconsistent timestamp extra field");
|
|
28258
|
+
if (flags3 & 1) result2.modified = view.getInt32(offset + 1, true) * 1e3;
|
|
28259
|
+
}
|
|
28260
|
+
offset += length;
|
|
28261
|
+
}
|
|
28262
|
+
return result2;
|
|
28263
|
+
}
|
|
28264
|
+
function nameFrom(rawName, flags3, metadata3, limits) {
|
|
28265
|
+
number3(rawName.length, Math.min(limits.maxPathBytes, 65535), "raw path byte");
|
|
28266
|
+
const raw = flags3 & 2048 ? text2(rawName) : legacyName(rawName);
|
|
28267
|
+
pathBytes(raw, limits);
|
|
28268
|
+
if (flags3 & 2048 && metadata3.name !== void 0 && metadata3.name !== raw) fail2("ZIP conflicting UTF-8 and Unicode extra names");
|
|
28269
|
+
return metadata3.name ?? raw;
|
|
28270
|
+
}
|
|
28271
|
+
function format(method, flags3, version) {
|
|
28272
|
+
number3(flags3, 65535, "general purpose flags");
|
|
28273
|
+
if (flags3 & (1 | 64 | 8192)) fail2("ZIP encryption is unsupported");
|
|
28274
|
+
if (flags3 & ~2062 || method === 0 && flags3 & 6) fail2("ZIP unsupported general purpose flags");
|
|
28275
|
+
if (method !== 0 && method !== 8) fail2("ZIP unsupported compression method");
|
|
28276
|
+
if (version < (method === 8 || flags3 & 8 ? 20 : 10) || version > 20) fail2("ZIP unsupported extraction version (including ZIP64)");
|
|
28277
|
+
}
|
|
28278
|
+
function dosModified(date2, time) {
|
|
28279
|
+
if (!date2 && !time) return new Date(1980, 0, 1);
|
|
28280
|
+
const year = 1980 + (date2 >>> 9);
|
|
28281
|
+
const month = (date2 >>> 5 & 15) - 1;
|
|
28282
|
+
const day = date2 & 31;
|
|
28283
|
+
const hours = time >>> 11;
|
|
28284
|
+
const minutes = time >>> 5 & 63;
|
|
28285
|
+
const seconds = (time & 31) * 2;
|
|
28286
|
+
const result2 = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
|
|
28287
|
+
if (result2.getUTCFullYear() !== year || result2.getUTCMonth() !== month || result2.getUTCDate() !== day || hours > 23 || minutes > 59 || seconds > 59) fail2("ZIP invalid DOS timestamp");
|
|
28288
|
+
return new Date(year, month, day, hours, minutes, seconds);
|
|
28289
|
+
}
|
|
28290
|
+
function entryBounds(entry, limits) {
|
|
28291
|
+
pathBytes(entry.name, limits);
|
|
28292
|
+
number3(entry.size, Math.min(limits.maxEntryBytes, limits.maxTotalBytes, 4294967294), "entry byte");
|
|
28293
|
+
number3(entry.data.length, Math.min(limits.maxArchiveBytes, 4294967294), "compressed byte");
|
|
28294
|
+
number3(entry.crc32, 4294967295, "CRC32");
|
|
28295
|
+
number3(entry.mode, 65535, "mode");
|
|
28296
|
+
format(entry.method, entry.flags ?? 2048, entry.method === 8 || (entry.flags ?? 0) & 8 ? 20 : 10);
|
|
28297
|
+
if (entry.directory !== entry.name.endsWith("/") || entry.directory && (entry.symlink || entry.size !== 0)) fail2("ZIP inconsistent directory metadata");
|
|
28298
|
+
const type = entry.mode & 61440;
|
|
28299
|
+
if (type !== 0 && type !== (entry.directory ? 16384 : entry.symlink ? 40960 : 32768)) fail2("ZIP unsupported or conflicting file type");
|
|
28300
|
+
if (!Number.isFinite(entry.modified.getTime())) fail2("ZIP invalid modification time");
|
|
28301
|
+
}
|
|
28302
|
+
async function copyBytes(source2, destination2, start, chunkSize2, signal) {
|
|
28303
|
+
for (let offset = 0; offset < source2.length; offset += chunkSize2) {
|
|
28304
|
+
signal.throwIfAborted();
|
|
28305
|
+
destination2.set(source2.subarray(offset, offset + chunkSize2), start + offset);
|
|
28306
|
+
if (offset + chunkSize2 < source2.length) await yieldTurn(signal);
|
|
28307
|
+
}
|
|
28308
|
+
}
|
|
28309
|
+
async function readZipArchive(bytes3, limits, signal) {
|
|
28310
|
+
const chunkSize2 = admit2(limits, signal);
|
|
28311
|
+
number3(bytes3.length, Math.min(limits.maxArchiveBytes, 4294967294), "archive byte");
|
|
28312
|
+
const view = new DataView(bytes3.buffer, bytes3.byteOffset, bytes3.byteLength);
|
|
28313
|
+
let end = -1;
|
|
28314
|
+
const lower = Math.max(0, bytes3.length - 22 - 65535);
|
|
28315
|
+
for (let offset2 = bytes3.length - 22; offset2 >= lower; offset2--) {
|
|
28316
|
+
if ((bytes3.length - offset2) % 4096 === 0) await yieldTurn(signal);
|
|
28317
|
+
if (view.getUint32(offset2, true) === 101010256 && offset2 + 22 + view.getUint16(offset2 + 20, true) === bytes3.length) {
|
|
28318
|
+
const size = view.getUint32(offset2 + 12, true);
|
|
28319
|
+
const start = view.getUint32(offset2 + 16, true);
|
|
28320
|
+
const zip64 = size === 4294967295 || start === 4294967295 || view.getUint16(offset2 + 10, true) === 65535 || offset2 >= 20 && view.getUint32(offset2 - 20, true) === 117853008;
|
|
28321
|
+
if (!zip64 && start + size !== offset2) continue;
|
|
28322
|
+
if (end !== -1) fail2("ZIP ambiguous end records");
|
|
28323
|
+
end = offset2;
|
|
28324
|
+
}
|
|
28325
|
+
}
|
|
28326
|
+
if (end === -1) fail2("ZIP truncated or missing end of central directory");
|
|
28327
|
+
const members = view.getUint16(end + 10, true);
|
|
28328
|
+
const centralSize = view.getUint32(end + 12, true);
|
|
28329
|
+
const centralStart = view.getUint32(end + 16, true);
|
|
28330
|
+
if (members === 65535 || centralSize === 4294967295 || centralStart === 4294967295) fail2("ZIP64 is unsupported");
|
|
28331
|
+
if (view.getUint16(end + 4, true) || view.getUint16(end + 6, true) || view.getUint16(end + 8, true) !== members) fail2("ZIP multi-disk or inconsistent member count is unsupported");
|
|
28332
|
+
if (centralStart + centralSize !== end) fail2("ZIP invalid central directory span or unsupported ZIP64/trailing records");
|
|
28333
|
+
number3(members, limits.maxMembers, "member");
|
|
28334
|
+
number3(bytes3.length - end - 22, limits.maxTextBytes, "archive comment");
|
|
28335
|
+
const entries2 = [];
|
|
28336
|
+
const spans = [];
|
|
28337
|
+
let offset = centralStart;
|
|
28338
|
+
let total = 0;
|
|
28339
|
+
for (let index = 0; index < members; index++) {
|
|
28340
|
+
await yieldTurn(signal);
|
|
28341
|
+
if (offset + 46 > end || view.getUint32(offset, true) !== 33639248) fail2("ZIP truncated or invalid central header");
|
|
28342
|
+
const versionMadeBy = view.getUint16(offset + 4, true);
|
|
28343
|
+
const version = view.getUint16(offset + 6, true);
|
|
28344
|
+
const flags3 = view.getUint16(offset + 8, true);
|
|
28345
|
+
const method = view.getUint16(offset + 10, true);
|
|
28346
|
+
format(method, flags3, version);
|
|
28347
|
+
const dosTime = view.getUint16(offset + 12, true);
|
|
28348
|
+
const dosDate = view.getUint16(offset + 14, true);
|
|
28349
|
+
const checksum = view.getUint32(offset + 16, true);
|
|
28350
|
+
const compressedSize = view.getUint32(offset + 20, true);
|
|
28351
|
+
const size = view.getUint32(offset + 24, true);
|
|
28352
|
+
const nameLength = view.getUint16(offset + 28, true);
|
|
28353
|
+
const extraLength = view.getUint16(offset + 30, true);
|
|
28354
|
+
const commentLength = view.getUint16(offset + 32, true);
|
|
28355
|
+
const internalAttributes = view.getUint16(offset + 36, true);
|
|
28356
|
+
if (internalAttributes & ~1) fail2("ZIP unsupported internal attributes");
|
|
28357
|
+
const externalAttributes = view.getUint32(offset + 38, true);
|
|
28358
|
+
const local = view.getUint32(offset + 42, true);
|
|
28359
|
+
if (view.getUint16(offset + 34, true)) fail2("ZIP multi-disk member is unsupported");
|
|
28360
|
+
if (compressedSize === 4294967295 || size === 4294967295 || local === 4294967295) fail2("ZIP64 is unsupported");
|
|
28361
|
+
number3(size, limits.maxEntryBytes, "entry byte");
|
|
28362
|
+
if (method === 0 && compressedSize !== size) fail2("ZIP stored size mismatch");
|
|
28363
|
+
total += size;
|
|
28364
|
+
number3(total, limits.maxTotalBytes, "total byte");
|
|
28365
|
+
const next = offset + 46 + nameLength + extraLength + commentLength;
|
|
28366
|
+
if (next > end) fail2("ZIP truncated central metadata");
|
|
28367
|
+
number3(commentLength, limits.maxTextBytes, "entry comment");
|
|
28368
|
+
const rawName = bytes3.subarray(offset + 46, offset + 46 + nameLength);
|
|
28369
|
+
const centralExtra = bytes3.subarray(offset + 46 + nameLength, next - commentLength);
|
|
28370
|
+
const comment2 = bytes3.subarray(next - commentLength, next);
|
|
28371
|
+
if (flags3 & 2048) text2(comment2);
|
|
28372
|
+
const centralMetadata = extras(centralExtra, rawName, comment2, true, limits);
|
|
28373
|
+
const name2 = nameFrom(rawName, flags3, centralMetadata, limits);
|
|
28374
|
+
if (local + 30 > centralStart || view.getUint32(local, true) !== 67324752) fail2("ZIP invalid local header span");
|
|
28375
|
+
if (view.getUint16(local + 4, true) !== version || view.getUint16(local + 6, true) !== flags3 || view.getUint16(local + 8, true) !== method || view.getUint16(local + 10, true) !== dosTime || view.getUint16(local + 12, true) !== dosDate) fail2("ZIP central/local metadata mismatch");
|
|
28376
|
+
const localNameLength = view.getUint16(local + 26, true);
|
|
28377
|
+
const localExtraLength = view.getUint16(local + 28, true);
|
|
28378
|
+
const payloadStart = local + 30 + localNameLength + localExtraLength;
|
|
28379
|
+
let payloadEnd = payloadStart + compressedSize;
|
|
28380
|
+
if (payloadEnd > centralStart) fail2("ZIP truncated or overlapping local payload");
|
|
28381
|
+
const localName = bytes3.subarray(local + 30, local + 30 + localNameLength);
|
|
28382
|
+
if (!equal(rawName, localName)) fail2("ZIP central/local filename mismatch");
|
|
28383
|
+
const localExtra = bytes3.subarray(local + 30 + localNameLength, payloadStart);
|
|
28384
|
+
const localMetadata = extras(localExtra, localName, comment2, false, limits);
|
|
28385
|
+
const localEffective = nameFrom(localName, flags3, localMetadata, limits);
|
|
28386
|
+
if (localMetadata.name !== void 0 && localEffective !== name2) fail2("ZIP central/local Unicode name mismatch");
|
|
28387
|
+
if (centralMetadata.modified !== void 0 && localMetadata.modified !== void 0 && centralMetadata.modified !== localMetadata.modified) fail2("ZIP central/local timestamp mismatch");
|
|
28388
|
+
for (const [position, expected] of [[14, checksum], [18, compressedSize], [22, size]]) {
|
|
28389
|
+
const actual = view.getUint32(local + position, true);
|
|
28390
|
+
if (actual !== expected && (!(flags3 & 8) || actual !== 0)) fail2("ZIP central/local size or CRC mismatch");
|
|
28391
|
+
}
|
|
28392
|
+
if (flags3 & 8) {
|
|
28393
|
+
const matches3 = [];
|
|
28394
|
+
for (const signed2 of [false, true]) {
|
|
28395
|
+
const descriptor2 = payloadEnd + (signed2 ? 4 : 0);
|
|
28396
|
+
if (descriptor2 + 12 <= centralStart && (!signed2 || view.getUint32(payloadEnd, true) === 134695760) && view.getUint32(descriptor2, true) === checksum && view.getUint32(descriptor2 + 4, true) === compressedSize && view.getUint32(descriptor2 + 8, true) === size) matches3.push(descriptor2 + 12);
|
|
28397
|
+
}
|
|
28398
|
+
if (matches3.length !== 1) fail2("ZIP truncated, ambiguous or mismatched data descriptor");
|
|
28399
|
+
payloadEnd = matches3[0];
|
|
28400
|
+
}
|
|
28401
|
+
const host2 = versionMadeBy >>> 8;
|
|
28402
|
+
const unixMode = host2 === 3 || host2 === 19 ? externalAttributes >>> 16 : 0;
|
|
28403
|
+
const directory2 = name2.endsWith("/");
|
|
28404
|
+
if (Boolean(externalAttributes & 16) && !directory2) fail2("ZIP conflicting directory attributes");
|
|
28405
|
+
const mode = unixMode || (directory2 ? 16877 : 33188);
|
|
28406
|
+
const symlink = (mode & 61440) === 40960;
|
|
28407
|
+
const modified = dosModified(dosDate, dosTime);
|
|
28408
|
+
const timestamp3 = centralMetadata.modified ?? localMetadata.modified;
|
|
28409
|
+
if (timestamp3 !== void 0) modified.setTime(timestamp3);
|
|
28410
|
+
const entry = { name: name2, data: bytes3.subarray(payloadStart, payloadStart + compressedSize), size, method, crc32: checksum, modified, mode, directory: directory2, symlink, rawName, localName, comment: comment2, localExtra, centralExtra, flags: flags3, versionMadeBy, internalAttributes, externalAttributes, dosTime, dosDate };
|
|
28411
|
+
entryBounds(entry, limits);
|
|
28412
|
+
entries2.push(entry);
|
|
28413
|
+
spans.push({ start: local, end: payloadEnd });
|
|
28414
|
+
offset = next;
|
|
28415
|
+
}
|
|
28416
|
+
if (offset !== end) fail2("ZIP central directory size or member count mismatch");
|
|
28417
|
+
spans.sort((first, second) => first.start - second.start);
|
|
28418
|
+
let covered = 0;
|
|
28419
|
+
for (const span of spans) {
|
|
28420
|
+
if (span.start !== covered) fail2("ZIP overlapping spans, gaps or self-extracting prefix are unsupported");
|
|
28421
|
+
covered = span.end;
|
|
28422
|
+
}
|
|
28423
|
+
if (covered !== centralStart) fail2("ZIP unreferenced local data is unsupported");
|
|
28424
|
+
for (const entry of entries2) {
|
|
28425
|
+
const data2 = new Uint8Array(entry.data.length);
|
|
28426
|
+
await copyBytes(entry.data, data2, 0, chunkSize2, signal);
|
|
28427
|
+
entry.data = data2;
|
|
28428
|
+
entry.rawName = new Uint8Array(entry.rawName);
|
|
28429
|
+
entry.localName = new Uint8Array(entry.localName);
|
|
28430
|
+
entry.comment = new Uint8Array(entry.comment);
|
|
28431
|
+
entry.localExtra = new Uint8Array(entry.localExtra);
|
|
28432
|
+
entry.centralExtra = new Uint8Array(entry.centralExtra);
|
|
28433
|
+
await yieldTurn(signal);
|
|
28434
|
+
}
|
|
28435
|
+
return { entries: entries2, comment: new Uint8Array(bytes3.subarray(end + 22)) };
|
|
28436
|
+
}
|
|
28437
|
+
async function* decodeZipEntry(entry, limits, signal) {
|
|
28438
|
+
const chunkSize2 = admit2(limits, signal);
|
|
28439
|
+
entryBounds(entry, limits);
|
|
28440
|
+
const reader = new CodecReader((async function* () {
|
|
28441
|
+
yield entry.data;
|
|
28442
|
+
})(), signal);
|
|
28443
|
+
let length = 0;
|
|
28444
|
+
let checksum = 0;
|
|
28445
|
+
const source2 = entry.method === 8 ? codec(reader, { mode: "inflate-raw", chunkSize: chunkSize2 }, signal) : (async function* () {
|
|
28446
|
+
for (let offset = 0; offset < entry.data.length; offset += chunkSize2) {
|
|
28447
|
+
yield new Uint8Array(entry.data.subarray(offset, offset + chunkSize2));
|
|
28448
|
+
await yieldTurn(signal);
|
|
28449
|
+
}
|
|
28450
|
+
})();
|
|
28451
|
+
try {
|
|
28452
|
+
for await (const chunk of source2) {
|
|
28453
|
+
signal.throwIfAborted();
|
|
28454
|
+
length += chunk.length;
|
|
28455
|
+
number3(length, Math.min(limits.maxEntryBytes, limits.maxTotalBytes), "decoded byte");
|
|
28456
|
+
checksum = crc322(chunk, checksum);
|
|
28457
|
+
yield chunk;
|
|
28458
|
+
}
|
|
28459
|
+
if (entry.method === 8 && await reader.chunk() !== void 0) fail2("ZIP trailing compressed data");
|
|
28460
|
+
if (length !== entry.size) fail2("ZIP uncompressed size mismatch");
|
|
28461
|
+
if (checksum !== entry.crc32) fail2("ZIP CRC32 mismatch");
|
|
28462
|
+
} finally {
|
|
28463
|
+
await reader.close();
|
|
28464
|
+
}
|
|
28465
|
+
}
|
|
28466
|
+
async function makeZipEntry(name2, bytes3, attributes, limits, signal) {
|
|
28467
|
+
const chunkSize2 = admit2(limits, signal);
|
|
28468
|
+
const entry = { name: name2, data: bytes3, size: bytes3.length, method: 0, crc32: 0, ...attributes, modified: new Date(attributes.modified.getTime()) };
|
|
28469
|
+
entryBounds(entry, limits);
|
|
28470
|
+
for (let offset = 0; offset < bytes3.length; offset += chunkSize2) {
|
|
28471
|
+
entry.crc32 = crc322(bytes3.subarray(offset, offset + chunkSize2), entry.crc32);
|
|
28472
|
+
await yieldTurn(signal);
|
|
28473
|
+
}
|
|
28474
|
+
const reader = new CodecReader((async function* () {
|
|
28475
|
+
yield bytes3;
|
|
28476
|
+
})(), signal);
|
|
28477
|
+
try {
|
|
28478
|
+
if (bytes3.length && !entry.directory && !entry.symlink) {
|
|
28479
|
+
const chunks = [];
|
|
28480
|
+
let length = 0;
|
|
28481
|
+
for await (const chunk of codec(reader, { mode: "deflate-raw", chunkSize: chunkSize2 }, signal)) {
|
|
28482
|
+
length += chunk.length;
|
|
28483
|
+
if (length >= bytes3.length) break;
|
|
28484
|
+
chunks.push(new Uint8Array(chunk));
|
|
28485
|
+
}
|
|
28486
|
+
if (length < bytes3.length) {
|
|
28487
|
+
entry.data = new Uint8Array(length);
|
|
28488
|
+
let offset = 0;
|
|
28489
|
+
for (const chunk of chunks) {
|
|
28490
|
+
entry.data.set(chunk, offset);
|
|
28491
|
+
offset += chunk.length;
|
|
28492
|
+
await yieldTurn(signal);
|
|
28493
|
+
}
|
|
28494
|
+
entry.method = 8;
|
|
28495
|
+
return entry;
|
|
28496
|
+
}
|
|
28497
|
+
}
|
|
28498
|
+
entry.data = new Uint8Array(bytes3.length);
|
|
28499
|
+
await copyBytes(bytes3, entry.data, 0, chunkSize2, signal);
|
|
28500
|
+
return entry;
|
|
28501
|
+
} finally {
|
|
28502
|
+
await reader.close();
|
|
28503
|
+
}
|
|
28504
|
+
}
|
|
28505
|
+
function timestampExtra(modified) {
|
|
28506
|
+
const seconds = Math.floor(modified.getTime() / 1e3);
|
|
28507
|
+
if (seconds < -2147483648 || seconds > 2147483647) return new Uint8Array();
|
|
28508
|
+
const bytes3 = new Uint8Array(9);
|
|
28509
|
+
const view = new DataView(bytes3.buffer);
|
|
28510
|
+
view.setUint16(0, 21589, true);
|
|
28511
|
+
view.setUint16(2, 5, true);
|
|
28512
|
+
bytes3[4] = 1;
|
|
28513
|
+
view.setInt32(5, seconds, true);
|
|
28514
|
+
return bytes3;
|
|
28515
|
+
}
|
|
28516
|
+
async function writeZipArchive(archive, limits, signal) {
|
|
28517
|
+
const chunkSize2 = admit2(limits, signal);
|
|
28518
|
+
number3(archive.entries.length, Math.min(limits.maxMembers, 65534), "member");
|
|
28519
|
+
number3(archive.comment.length, Math.min(limits.maxTextBytes, 65535), "archive comment");
|
|
28520
|
+
let length = 22 + archive.comment.length;
|
|
28521
|
+
let localLength = 0;
|
|
28522
|
+
let total = 0;
|
|
28523
|
+
const encoded2 = [];
|
|
28524
|
+
for (const entry of archive.entries) {
|
|
28525
|
+
await yieldTurn(signal);
|
|
28526
|
+
entryBounds(entry, limits);
|
|
28527
|
+
if (entry.method === 0 && entry.data.length !== entry.size) fail2("ZIP stored size mismatch");
|
|
28528
|
+
total += entry.size;
|
|
28529
|
+
number3(total, limits.maxTotalBytes, "total byte");
|
|
28530
|
+
const rawName = entry.rawName ?? pathBytes(entry.name, limits);
|
|
28531
|
+
const flags3 = (entry.flags ?? 2048) & ~8;
|
|
28532
|
+
const comment2 = entry.comment ?? new Uint8Array();
|
|
28533
|
+
number3(comment2.length, Math.min(limits.maxTextBytes, 65535), "entry comment");
|
|
28534
|
+
if (flags3 & 2048) text2(comment2);
|
|
28535
|
+
const localExtra = entry.localExtra ?? timestampExtra(entry.modified);
|
|
28536
|
+
const centralExtra = entry.centralExtra ?? timestampExtra(entry.modified);
|
|
28537
|
+
const localMetadata = extras(localExtra, rawName, comment2, false, limits);
|
|
28538
|
+
const centralMetadata = extras(centralExtra, rawName, comment2, true, limits);
|
|
28539
|
+
if (nameFrom(rawName, flags3, centralMetadata, limits) !== entry.name || localMetadata.name !== void 0 && nameFrom(rawName, flags3, localMetadata, limits) !== entry.name || entry.localName && !equal(rawName, entry.localName)) fail2("ZIP retained filename metadata mismatch");
|
|
28540
|
+
if (localMetadata.modified !== void 0 && centralMetadata.modified !== void 0 && localMetadata.modified !== centralMetadata.modified) fail2("ZIP retained timestamp metadata mismatch");
|
|
28541
|
+
const rounded2 = new Date(Math.ceil(Math.floor(entry.modified.getTime() / 1e3) / 2) * 2e3);
|
|
28542
|
+
const year = Math.max(1980, Math.min(2107, rounded2.getFullYear()));
|
|
28543
|
+
const date2 = entry.dosDate ?? year - 1980 << 9 | rounded2.getMonth() + 1 << 5 | rounded2.getDate();
|
|
28544
|
+
const time = entry.dosTime ?? rounded2.getHours() << 11 | rounded2.getMinutes() << 5 | rounded2.getSeconds() >>> 1;
|
|
28545
|
+
number3(date2, 65535, "DOS date");
|
|
28546
|
+
number3(time, 65535, "DOS time");
|
|
28547
|
+
const dosTimestamp = dosModified(date2, time).getTime();
|
|
28548
|
+
const extendedTimestamp = centralMetadata.modified ?? localMetadata.modified;
|
|
28549
|
+
if (extendedTimestamp === void 0 ? dosTimestamp !== rounded2.getTime() : Math.floor(extendedTimestamp / 1e3) !== Math.floor(entry.modified.getTime() / 1e3)) fail2("ZIP retained or unrepresentable timestamp metadata mismatch");
|
|
28550
|
+
for (const [value2, maximum, label] of [[entry.versionMadeBy ?? 798, 65535, "creator version"], [entry.internalAttributes ?? 0, 65535, "internal attributes"], [entry.externalAttributes ?? 0, 4294967295, "external attributes"]]) number3(value2, maximum, label);
|
|
28551
|
+
if ((entry.internalAttributes ?? 0) & ~1) fail2("ZIP unsupported internal attributes");
|
|
28552
|
+
if (entry.externalAttributes !== void 0) {
|
|
28553
|
+
const host2 = (entry.versionMadeBy ?? 798) >>> 8;
|
|
28554
|
+
const unixMode = host2 === 3 || host2 === 19 ? entry.externalAttributes >>> 16 : 0;
|
|
28555
|
+
const mode = unixMode || (entry.directory ? 16877 : 33188);
|
|
28556
|
+
if (mode !== entry.mode || Boolean(entry.externalAttributes & 16) && !entry.directory) fail2("ZIP retained file attributes mismatch");
|
|
28557
|
+
}
|
|
28558
|
+
encoded2.push({ entry, rawName, flags: flags3, localExtra, centralExtra, comment: comment2, date: date2, time, offset: localLength });
|
|
28559
|
+
localLength += 30 + rawName.length + localExtra.length + entry.data.length;
|
|
28560
|
+
length += 76 + 2 * rawName.length + localExtra.length + centralExtra.length + comment2.length + entry.data.length;
|
|
28561
|
+
number3(length, Math.min(limits.maxArchiveBytes, 4294967294), "archive byte");
|
|
28562
|
+
}
|
|
28563
|
+
number3(length, Math.min(limits.maxArchiveBytes, 4294967294), "archive byte");
|
|
28564
|
+
const bytes3 = new Uint8Array(length);
|
|
28565
|
+
const view = new DataView(bytes3.buffer);
|
|
28566
|
+
let central = localLength;
|
|
28567
|
+
for (const item of encoded2) {
|
|
28568
|
+
await yieldTurn(signal);
|
|
28569
|
+
const { entry, rawName, flags: flags3, localExtra, centralExtra, comment: comment2, date: date2, time, offset } = item;
|
|
28570
|
+
const version = entry.method === 8 ? 20 : 10;
|
|
28571
|
+
view.setUint32(offset, 67324752, true);
|
|
28572
|
+
view.setUint16(offset + 4, version, true);
|
|
28573
|
+
view.setUint16(offset + 6, flags3, true);
|
|
28574
|
+
view.setUint16(offset + 8, entry.method, true);
|
|
28575
|
+
view.setUint16(offset + 10, time, true);
|
|
28576
|
+
view.setUint16(offset + 12, date2, true);
|
|
28577
|
+
view.setUint32(offset + 14, entry.crc32, true);
|
|
28578
|
+
view.setUint32(offset + 18, entry.data.length, true);
|
|
28579
|
+
view.setUint32(offset + 22, entry.size, true);
|
|
28580
|
+
view.setUint16(offset + 26, rawName.length, true);
|
|
28581
|
+
view.setUint16(offset + 28, localExtra.length, true);
|
|
28582
|
+
bytes3.set(rawName, offset + 30);
|
|
28583
|
+
bytes3.set(localExtra, offset + 30 + rawName.length);
|
|
28584
|
+
await copyBytes(entry.data, bytes3, offset + 30 + rawName.length + localExtra.length, chunkSize2, signal);
|
|
28585
|
+
view.setUint32(central, 33639248, true);
|
|
28586
|
+
view.setUint16(central + 4, entry.versionMadeBy ?? 798, true);
|
|
28587
|
+
view.setUint16(central + 6, version, true);
|
|
28588
|
+
view.setUint16(central + 8, flags3, true);
|
|
28589
|
+
view.setUint16(central + 10, entry.method, true);
|
|
28590
|
+
view.setUint16(central + 12, time, true);
|
|
28591
|
+
view.setUint16(central + 14, date2, true);
|
|
28592
|
+
view.setUint32(central + 16, entry.crc32, true);
|
|
28593
|
+
view.setUint32(central + 20, entry.data.length, true);
|
|
28594
|
+
view.setUint32(central + 24, entry.size, true);
|
|
28595
|
+
view.setUint16(central + 28, rawName.length, true);
|
|
28596
|
+
view.setUint16(central + 30, centralExtra.length, true);
|
|
28597
|
+
view.setUint16(central + 32, comment2.length, true);
|
|
28598
|
+
view.setUint16(central + 36, entry.internalAttributes ?? 0, true);
|
|
28599
|
+
view.setUint32(central + 38, entry.externalAttributes ?? (entry.mode | (entry.directory ? 16384 : entry.symlink ? 40960 : 32768)) * 65536 + (entry.directory ? 16 : 0), true);
|
|
28600
|
+
view.setUint32(central + 42, offset, true);
|
|
28601
|
+
bytes3.set(rawName, central + 46);
|
|
28602
|
+
bytes3.set(centralExtra, central + 46 + rawName.length);
|
|
28603
|
+
bytes3.set(comment2, central + 46 + rawName.length + centralExtra.length);
|
|
28604
|
+
central += 46 + rawName.length + centralExtra.length + comment2.length;
|
|
28605
|
+
}
|
|
28606
|
+
view.setUint32(central, 101010256, true);
|
|
28607
|
+
view.setUint16(central + 8, encoded2.length, true);
|
|
28608
|
+
view.setUint16(central + 10, encoded2.length, true);
|
|
28609
|
+
view.setUint32(central + 12, central - localLength, true);
|
|
28610
|
+
view.setUint32(central + 16, localLength, true);
|
|
28611
|
+
view.setUint16(central + 20, archive.comment.length, true);
|
|
28612
|
+
bytes3.set(archive.comment, central + 22);
|
|
28613
|
+
signal.throwIfAborted();
|
|
28614
|
+
return bytes3;
|
|
28615
|
+
}
|
|
28616
|
+
|
|
28617
|
+
// packages/safe-bash/src/commands/archive/zip/safety.ts
|
|
28618
|
+
init_platform();
|
|
28619
|
+
import { retainFileSystemCleanup } from "@poe-platform/safe-fs/core";
|
|
28620
|
+
var ZipScope = class {
|
|
28621
|
+
constructor(original, limits) {
|
|
28622
|
+
this.original = original;
|
|
28623
|
+
this.limits = limits;
|
|
28624
|
+
this.context = { ...original, signal: AbortSignal.any([original.signal, this.controller.signal]) };
|
|
28625
|
+
original.registerCleanup?.(this.close);
|
|
28626
|
+
}
|
|
28627
|
+
original;
|
|
28628
|
+
limits;
|
|
28629
|
+
context;
|
|
28630
|
+
controller = new AbortController();
|
|
28631
|
+
pending = /* @__PURE__ */ new Set();
|
|
28632
|
+
readers = /* @__PURE__ */ new Set();
|
|
28633
|
+
closedReason = new Error("ZIP command is closed");
|
|
28634
|
+
drain;
|
|
28635
|
+
work = 0;
|
|
28636
|
+
close = () => {
|
|
28637
|
+
if (!this.drain) {
|
|
28638
|
+
this.drain = Promise.resolve().then(async () => {
|
|
28639
|
+
while (this.pending.size) await Promise.allSettled([...this.pending]);
|
|
28640
|
+
const results = await Promise.allSettled([...this.readers].map((close) => close()));
|
|
28641
|
+
const failures = results.filter((result2) => result2.status === "rejected").map((result2) => result2.reason);
|
|
28642
|
+
if (failures.length === 1) throw failures[0];
|
|
28643
|
+
if (failures.length) throw new AggregateError(failures, "ZIP reader cleanup failed");
|
|
28644
|
+
});
|
|
28645
|
+
this.controller.abort(this.original.signal.aborted ? this.original.signal.reason : this.closedReason);
|
|
28646
|
+
}
|
|
28647
|
+
return this.drain;
|
|
28648
|
+
};
|
|
28649
|
+
async operation(action) {
|
|
28650
|
+
this.context.signal.throwIfAborted();
|
|
28651
|
+
if (++this.work > this.limits.maxPatternSteps) fail2("filesystem work limit exceeded");
|
|
28652
|
+
const pending = Promise.resolve().then(() => {
|
|
28653
|
+
this.context.signal.throwIfAborted();
|
|
28654
|
+
return action();
|
|
28655
|
+
});
|
|
28656
|
+
this.pending.add(pending);
|
|
28657
|
+
try {
|
|
28658
|
+
const value2 = await pending;
|
|
28659
|
+
this.context.signal.throwIfAborted();
|
|
28660
|
+
return value2;
|
|
28661
|
+
} finally {
|
|
28662
|
+
this.pending.delete(pending);
|
|
28663
|
+
}
|
|
28664
|
+
}
|
|
28665
|
+
async stat(path) {
|
|
28666
|
+
try {
|
|
28667
|
+
return await this.operation(() => this.context.fs.lstat(path, { signal: this.context.signal }));
|
|
28668
|
+
} catch (error) {
|
|
28669
|
+
this.context.signal.throwIfAborted();
|
|
28670
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") return void 0;
|
|
28671
|
+
throw error;
|
|
28672
|
+
}
|
|
28673
|
+
}
|
|
28674
|
+
source(source2) {
|
|
28675
|
+
const iterator = source2[Symbol.asyncIterator]();
|
|
28676
|
+
let closing;
|
|
28677
|
+
const close = () => closing ??= (async () => {
|
|
28678
|
+
try {
|
|
28679
|
+
await iterator.return?.();
|
|
28680
|
+
} finally {
|
|
28681
|
+
this.readers.delete(close);
|
|
28682
|
+
}
|
|
28683
|
+
})();
|
|
28684
|
+
this.readers.add(close);
|
|
28685
|
+
return { [Symbol.asyncIterator]: () => ({
|
|
28686
|
+
next: () => this.operation(async () => {
|
|
28687
|
+
const result2 = await iterator.next();
|
|
28688
|
+
if (result2.done) this.readers.delete(close);
|
|
28689
|
+
return result2;
|
|
28690
|
+
}),
|
|
28691
|
+
async return() {
|
|
28692
|
+
await close();
|
|
28693
|
+
return { done: true, value: void 0 };
|
|
28694
|
+
}
|
|
28695
|
+
}) };
|
|
28696
|
+
}
|
|
28697
|
+
async *input(path) {
|
|
28698
|
+
const { fs, signal } = this.context;
|
|
28699
|
+
const capabilities = await this.operation(() => fs.capabilitiesFor?.(path, { signal }) ?? fs.capabilities);
|
|
28700
|
+
if (fs.readStream && capabilities.streamingRead !== false) {
|
|
28701
|
+
const source2 = await this.operation(() => this.source(fs.readStream(path, { signal, chunkSize: this.limits.chunkSize })));
|
|
28702
|
+
yield* readBytes(source2, signal);
|
|
28703
|
+
} else {
|
|
28704
|
+
const stat = await this.operation(() => fs.stat(path, { signal }));
|
|
28705
|
+
if (stat.size > this.limits.maxBufferedFileBytes) fail2("filesystem lacks streaming reads: buffered file limit exceeded");
|
|
28706
|
+
const bytes3 = await this.operation(() => fs.readFile(path, { signal, maxBytes: this.limits.maxBufferedFileBytes }));
|
|
28707
|
+
if (bytes3.length > this.limits.maxBufferedFileBytes) fail2("buffered file limit exceeded");
|
|
28708
|
+
yield bytes3;
|
|
28709
|
+
}
|
|
28710
|
+
}
|
|
28711
|
+
};
|
|
28712
|
+
async function publishZip(scope, prepared) {
|
|
28713
|
+
const { fs, signal } = scope.context;
|
|
28714
|
+
const capabilities = await scope.operation(() => fs.capabilitiesFor?.(prepared.output, { signal }) ?? fs.capabilities);
|
|
28715
|
+
if (capabilities.atomicRename !== true || capabilities.exclusiveCreate !== true || capabilities.explicitDirectories !== true || capabilities.permissions !== true || !fs.rmdir || (prepared.existing ? !fs.chmod : capabilities.atomicRenameNoReplace !== true)) fail2("ZIP publication requires atomic rename, exclusive creation, private directories and mode preservation");
|
|
28716
|
+
let directory2;
|
|
28717
|
+
let temporary = "";
|
|
28718
|
+
let identity2;
|
|
28719
|
+
let published = false;
|
|
28720
|
+
let collision = false;
|
|
28721
|
+
let failure;
|
|
28722
|
+
const checkOwner = async () => {
|
|
28723
|
+
const parent = await scope.operation(() => fs.realpath(prepared.parentName, { signal }));
|
|
28724
|
+
const owner = directory2 && await scope.stat(directory2.path);
|
|
28725
|
+
if (parent !== prepared.parent || !owner || owner.type !== "directory" || !sameIdentity2(owner, directory2.stat)) fail2("ZIP temporary ownership changed before mutation");
|
|
28726
|
+
};
|
|
28727
|
+
const close = retainFileSystemCleanup(fs, async (cleanup) => {
|
|
28728
|
+
if (!directory2 || !hasIdentity(directory2.stat)) return;
|
|
28729
|
+
const parent = await cleanup.realpath(prepared.parentName);
|
|
28730
|
+
const owner = await cleanup.lstat(directory2.path);
|
|
28731
|
+
if (parent !== prepared.parent || owner.type !== "directory" || !sameIdentity2(owner, directory2.stat)) fail2("ZIP temporary ownership changed before cleanup");
|
|
28732
|
+
if (temporary && !published && !collision) {
|
|
28733
|
+
let current;
|
|
28734
|
+
try {
|
|
28735
|
+
current = await cleanup.lstat(temporary);
|
|
28736
|
+
} catch (error) {
|
|
28737
|
+
if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "ENOENT") throw error;
|
|
28738
|
+
}
|
|
28739
|
+
if (current) {
|
|
28740
|
+
if (!identity2 || !sameIdentity2(current, identity2) || current.type !== "file" || current.nlink !== 1) fail2("ZIP temporary file changed before cleanup");
|
|
28741
|
+
await cleanup.rm(temporary);
|
|
28742
|
+
}
|
|
28743
|
+
}
|
|
28744
|
+
await cleanup.rmdir(directory2.path);
|
|
28745
|
+
}, { maxOperations: 16 });
|
|
28746
|
+
try {
|
|
28747
|
+
for (let attempt = 0; attempt < Math.min(64, scope.limits.maxMembers); attempt++) {
|
|
28748
|
+
const path = `${prepared.parent === "/" ? "" : prepared.parent}/.zip-${attempt + 1}`;
|
|
28749
|
+
checkPath(path, scope.limits);
|
|
28750
|
+
if (path === prepared.output) continue;
|
|
28751
|
+
try {
|
|
28752
|
+
await scope.operation(async () => {
|
|
28753
|
+
await fs.mkdir(path, { signal, mode: 448 });
|
|
28754
|
+
directory2 = { path, stat: await fs.lstat(path) };
|
|
28755
|
+
});
|
|
28756
|
+
break;
|
|
28757
|
+
} catch (error) {
|
|
28758
|
+
signal.throwIfAborted();
|
|
28759
|
+
if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "EEXIST") throw error;
|
|
28760
|
+
}
|
|
28761
|
+
}
|
|
28762
|
+
if (!directory2) fail2("ZIP temporary directory attempt limit exceeded");
|
|
28763
|
+
if (directory2.stat.type !== "directory" || !hasIdentity(directory2.stat) || (directory2.stat.mode & 511) !== 448) fail2("ZIP temporary directory ownership unavailable");
|
|
28764
|
+
temporary = `${directory2.path}/archive.zip`;
|
|
28765
|
+
checkPath(temporary, scope.limits);
|
|
28766
|
+
await checkOwner();
|
|
28767
|
+
await scope.operation(async () => {
|
|
28768
|
+
let writeFailure;
|
|
28769
|
+
try {
|
|
28770
|
+
await fs.writeFile(temporary, prepared.bytes, { signal, flag: "wx", ...prepared.existing ? { mode: prepared.existing.mode & 4095 } : {} });
|
|
28771
|
+
} catch (error) {
|
|
28772
|
+
collision = typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
|
|
28773
|
+
writeFailure = { reason: error };
|
|
28774
|
+
}
|
|
28775
|
+
if (!collision) {
|
|
28776
|
+
await checkOwner();
|
|
28777
|
+
try {
|
|
28778
|
+
identity2 = await fs.lstat(temporary);
|
|
28779
|
+
} catch (error) {
|
|
28780
|
+
if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "ENOENT") throw error;
|
|
28781
|
+
}
|
|
28782
|
+
}
|
|
28783
|
+
if (writeFailure) throw writeFailure.reason;
|
|
28784
|
+
});
|
|
28785
|
+
if (!identity2 || !hasIdentity(identity2) || identity2.type !== "file" || identity2.nlink !== 1 || identity2.size !== prepared.bytes.length) fail2("ZIP staged archive identity or size changed");
|
|
28786
|
+
if (prepared.existing) {
|
|
28787
|
+
await checkOwner();
|
|
28788
|
+
await scope.operation(() => fs.chmod(temporary, prepared.existing.mode & 4095, { signal }));
|
|
28789
|
+
}
|
|
28790
|
+
const parent = await scope.operation(() => fs.realpath(prepared.parentName, { signal }));
|
|
28791
|
+
const current = await scope.stat(prepared.output);
|
|
28792
|
+
if (parent !== prepared.parent || (prepared.existing ? !current || !sameIdentity2(prepared.existing, current) || current.type !== "file" || current.nlink !== 1 || current.size !== prepared.existing.size || current.mode !== prepared.existing.mode || current.mtimeMs !== prepared.existing.mtimeMs || current.ctimeMs !== prepared.existing.ctimeMs : current !== void 0)) fail2("archive backing entry changed before publication");
|
|
28793
|
+
const staging = await scope.stat(temporary);
|
|
28794
|
+
const owner = await scope.stat(directory2.path);
|
|
28795
|
+
if (!staging || !sameIdentity2(staging, identity2) || staging.type !== "file" || staging.nlink !== 1 || staging.size !== prepared.bytes.length || !owner || !sameIdentity2(owner, directory2.stat) || owner.type !== "directory") fail2("ZIP temporary ownership changed before publication");
|
|
28796
|
+
await scope.operation(async () => {
|
|
28797
|
+
await fs.rename(temporary, prepared.output, { signal, ...!prepared.existing ? { noReplace: true } : {} });
|
|
28798
|
+
published = true;
|
|
28799
|
+
});
|
|
28800
|
+
} catch (error) {
|
|
28801
|
+
failure = { reason: error };
|
|
28802
|
+
}
|
|
28803
|
+
try {
|
|
28804
|
+
await close();
|
|
28805
|
+
} catch (error) {
|
|
28806
|
+
if (failure) throw new AggregateError([failure.reason, error], "ZIP publication and cleanup failed");
|
|
28807
|
+
throw error;
|
|
28808
|
+
}
|
|
28809
|
+
if (failure) throw failure.reason;
|
|
28810
|
+
}
|
|
28811
|
+
|
|
28812
|
+
// packages/safe-bash/src/commands/archive/zip.ts
|
|
28813
|
+
var ZipFailure = class extends Error {
|
|
28814
|
+
constructor(status2, label, detail) {
|
|
28815
|
+
super(detail);
|
|
28816
|
+
this.status = status2;
|
|
28817
|
+
this.label = label;
|
|
28818
|
+
}
|
|
28819
|
+
status;
|
|
28820
|
+
label;
|
|
28821
|
+
};
|
|
28822
|
+
function parse12(context2, limits) {
|
|
28823
|
+
if (context2.args.length > limits.maxArgumentBytes) fail2("argument count limit exceeded");
|
|
28824
|
+
let bytes3 = 0;
|
|
28825
|
+
for (const argument2 of context2.args) {
|
|
28826
|
+
const size = import_buffer.Buffer.byteLength(argument2);
|
|
28827
|
+
if (size > limits.maxArgumentBytes - bytes3) fail2("argument byte limit exceeded");
|
|
28828
|
+
bytes3 += size;
|
|
28829
|
+
}
|
|
28830
|
+
if (context2.argumentValues) {
|
|
28831
|
+
const argumentsValue = getCommandArguments(context2);
|
|
28832
|
+
let rawBytes = 0;
|
|
28833
|
+
for (const value2 of argumentsValue.values) {
|
|
28834
|
+
const size = shellValueByteLength(value2);
|
|
28835
|
+
if (size > limits.maxArgumentBytes - rawBytes) fail2("argument byte limit exceeded");
|
|
28836
|
+
rawBytes += size;
|
|
28837
|
+
}
|
|
28838
|
+
for (const value2 of argumentsValue.values) text2(shellValueBytes(value2));
|
|
28839
|
+
}
|
|
28840
|
+
let archive;
|
|
28841
|
+
let recursive = false;
|
|
28842
|
+
let literal = false;
|
|
28843
|
+
let firstOperand = -1;
|
|
28844
|
+
const operands = [];
|
|
28845
|
+
for (const [index, argument2] of context2.args.entries()) {
|
|
28846
|
+
checkPath(argument2, limits);
|
|
28847
|
+
if (!literal && argument2 === "--") {
|
|
28848
|
+
if (archive === void 0) throw new ZipFailure(16, "Invalid command arguments", "can't use -- before archive name");
|
|
28849
|
+
literal = true;
|
|
28850
|
+
} else if (!literal && argument2.startsWith("-") && argument2 !== "-") {
|
|
28851
|
+
if (argument2.length > 1 && [...argument2.slice(1)].every((flag) => flag === "r")) recursive = true;
|
|
28852
|
+
else throw new ZipFailure(16, "Invalid command arguments", `unsupported option: ${argument2}`);
|
|
28853
|
+
} else if (archive === void 0) archive = argument2;
|
|
28854
|
+
else {
|
|
28855
|
+
if (operands.length >= limits.maxMembers) fail2("operand limit exceeded");
|
|
28856
|
+
if (firstOperand < 0) firstOperand = index;
|
|
28857
|
+
operands.push(argument2);
|
|
28858
|
+
}
|
|
28859
|
+
}
|
|
28860
|
+
if (archive === void 0) throw new ZipFailure(16, "Invalid command arguments", "expected zip [-r] ARCHIVE FILES...");
|
|
28861
|
+
if (archive === "-" || operands.includes("-")) throw new ZipFailure(16, "Invalid command arguments", "standard input/output archives are unsupported");
|
|
28862
|
+
if (!archive.slice(archive.lastIndexOf("/") + 1).includes(".")) archive += ".zip";
|
|
28863
|
+
checkPath(archive, limits);
|
|
28864
|
+
return { archive, recursive, operands, firstOperand };
|
|
28865
|
+
}
|
|
28866
|
+
function memberName(path, limits) {
|
|
28867
|
+
if (path.startsWith("//") && !path.startsWith("///")) fail2("UNC source paths are unsupported");
|
|
28868
|
+
let start = 0;
|
|
28869
|
+
while (path[start] === "/") start++;
|
|
28870
|
+
while (path.slice(start, start + 2) === "./") start += 2;
|
|
28871
|
+
const name2 = path.slice(start);
|
|
28872
|
+
if (name2.split("/").includes("..")) fail2("parent-component archive names are unsupported");
|
|
28873
|
+
if (name2 && name2 !== ".") checkPath(name2, limits);
|
|
28874
|
+
return name2 === "." ? "" : name2;
|
|
28875
|
+
}
|
|
28876
|
+
function unchanged4(before, after) {
|
|
28877
|
+
return before.type === after.type && before.size === after.size && before.mode === after.mode && before.mtimeMs === after.mtimeMs && before.ctimeMs === after.ctimeMs && before.nlink === after.nlink && (!hasIdentity(before) || sameIdentity2(before, after));
|
|
28878
|
+
}
|
|
28879
|
+
async function prepare(scope, parsed, budget) {
|
|
28880
|
+
const context2 = scope.context;
|
|
28881
|
+
const limits = budget.limits;
|
|
28882
|
+
const outputName = vfsPath(context2.cwd, parsed.archive);
|
|
28883
|
+
const parentName = dirname(outputName);
|
|
28884
|
+
const parent = await scope.operation(() => context2.fs.realpath(parentName, { signal: context2.signal }));
|
|
28885
|
+
const output2 = `${parent === "/" ? "" : parent}/${outputName.slice(outputName.lastIndexOf("/") + 1)}`;
|
|
28886
|
+
checkPath(output2, limits);
|
|
28887
|
+
const existing2 = await scope.stat(output2);
|
|
28888
|
+
if (existing2 && (existing2.type !== "file" || !hasIdentity(existing2) || existing2.nlink !== 1)) fail2("updating archive requires a regular, single-link file with known backing identity; archive aliases are unsupported");
|
|
28889
|
+
let archive = { entries: [], comment: new Uint8Array() };
|
|
28890
|
+
if (existing2) {
|
|
28891
|
+
if (!Number.isSafeInteger(existing2.size) || existing2.size < 0 || existing2.size > limits.maxArchiveBytes) fail2("archive byte limit exceeded");
|
|
28892
|
+
const bytes4 = await collectBytes(scope.input(output2), { maxBytes: limits.maxArchiveBytes, signal: context2.signal });
|
|
28893
|
+
if (bytes4.length !== existing2.size) fail2("archive changed while reading");
|
|
28894
|
+
archive = await readZipArchive(bytes4, limits, context2.signal);
|
|
28895
|
+
const current = await scope.stat(output2);
|
|
28896
|
+
if (!current || !unchanged4(existing2, current)) fail2("archive changed while reading");
|
|
28897
|
+
}
|
|
28898
|
+
const old = new Map(archive.entries.map((entry) => [entry.name, entry]));
|
|
28899
|
+
const selected = /* @__PURE__ */ new Map();
|
|
28900
|
+
const ancestors = [];
|
|
28901
|
+
let visits = 0;
|
|
28902
|
+
let work = 0;
|
|
28903
|
+
let compressedBytes = 0;
|
|
28904
|
+
const visit = async (source2, name2, depth) => {
|
|
28905
|
+
context2.signal.throwIfAborted();
|
|
28906
|
+
if (++visits > limits.maxMembers) fail2("traversal member limit exceeded");
|
|
28907
|
+
if (++work > limits.maxPatternSteps) fail2("archive work limit exceeded");
|
|
28908
|
+
if (visits % 128 === 0) await yieldTurn(context2.signal);
|
|
28909
|
+
if (depth > limits.maxDepth) fail2("archive recursion depth limit exceeded");
|
|
28910
|
+
const path = vfsPath(context2.cwd, source2);
|
|
28911
|
+
checkPath(path, limits);
|
|
28912
|
+
let canonical;
|
|
28913
|
+
let stat;
|
|
28914
|
+
try {
|
|
28915
|
+
canonical = await scope.operation(() => context2.fs.realpath(path, { signal: context2.signal }));
|
|
28916
|
+
stat = await scope.operation(() => context2.fs.stat(path, { signal: context2.signal }));
|
|
28917
|
+
} catch (error) {
|
|
28918
|
+
context2.signal.throwIfAborted();
|
|
28919
|
+
if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "ENOENT") throw error;
|
|
28920
|
+
if (!old.has(name2)) await budget.output(` zip warning: name not matched: ${source2}
|
|
28921
|
+
`);
|
|
28922
|
+
return;
|
|
28923
|
+
}
|
|
28924
|
+
checkPath(canonical, limits);
|
|
28925
|
+
if (canonical === output2 || existing2 && sameIdentity2(existing2, stat)) return;
|
|
28926
|
+
if (stat.type !== "file" && stat.type !== "directory") {
|
|
28927
|
+
await budget.output(` zip warning: ignoring special file: ${source2}
|
|
28928
|
+
`);
|
|
28929
|
+
return;
|
|
28930
|
+
}
|
|
28931
|
+
if (existing2 && !hasIdentity(stat)) fail2("cannot exclude archive aliases when source backing identity is unknown");
|
|
28932
|
+
const directory2 = stat.type === "directory";
|
|
28933
|
+
if (directory2 && name2 && !name2.endsWith("/")) name2 += "/";
|
|
28934
|
+
if (name2) {
|
|
28935
|
+
checkPath(name2, limits);
|
|
28936
|
+
const previous = selected.get(name2);
|
|
28937
|
+
if (previous && previous.source !== source2) {
|
|
28938
|
+
await budget.output(` zip warning: first full name: ${previous.source}
|
|
28939
|
+
second full name: ${source2}
|
|
28940
|
+
name in zip file repeated: ${name2}
|
|
28941
|
+
`);
|
|
28942
|
+
throw new ZipFailure(16, "Invalid command arguments", "cannot repeat names in zip file");
|
|
28943
|
+
}
|
|
28944
|
+
if (!previous) {
|
|
28945
|
+
await budget.member(directory2 ? 0 : stat.size);
|
|
28946
|
+
const bytes4 = directory2 ? new Uint8Array() : await collectBytes(scope.input(path), { maxBytes: stat.size, signal: context2.signal });
|
|
28947
|
+
if (!directory2 && bytes4.length !== stat.size) fail2(`source changed while reading: ${source2}`);
|
|
28948
|
+
const current = await scope.operation(() => context2.fs.stat(path, { signal: context2.signal }));
|
|
28949
|
+
const currentPath = await scope.operation(() => context2.fs.realpath(path, { signal: context2.signal }));
|
|
28950
|
+
if (currentPath !== canonical || !unchanged4(stat, current)) fail2(`source changed while reading: ${source2}`);
|
|
28951
|
+
let entry = await makeZipEntry(name2, bytes4, { modified: new Date(stat.mtimeMs), mode: stat.mode, directory: directory2, symlink: false }, limits, context2.signal);
|
|
28952
|
+
if ([".z", ".zip", ".zoo", ".arc", ".lzh", ".arj"].some((suffix2) => name2.toLowerCase().endsWith(suffix2))) entry = { ...entry, method: 0, data: bytes4 };
|
|
28953
|
+
const prior = old.get(name2);
|
|
28954
|
+
if (prior?.comment) entry = { ...entry, comment: prior.comment };
|
|
28955
|
+
if (entry.data.length > limits.maxArchiveBytes - compressedBytes) fail2("archive byte limit exceeded");
|
|
28956
|
+
compressedBytes += entry.data.length;
|
|
28957
|
+
selected.set(name2, { entry, source: source2 });
|
|
28958
|
+
}
|
|
28959
|
+
}
|
|
28960
|
+
if (directory2 && parsed.recursive) {
|
|
28961
|
+
if (ancestors.some((ancestor) => ancestor.path === canonical || sameIdentity2(ancestor.stat, stat))) fail2(`directory cycle while archiving: ${source2}`);
|
|
28962
|
+
ancestors.push({ path: canonical, stat });
|
|
28963
|
+
try {
|
|
28964
|
+
const children = await scope.operation(() => context2.fs.readdir(path, { signal: context2.signal, maxEntries: limits.maxMembers - visits }));
|
|
28965
|
+
if (children.length > limits.maxMembers - visits) fail2("traversal member limit exceeded");
|
|
28966
|
+
for (const child of children) {
|
|
28967
|
+
if (!child.name || child.name === "." || child.name === ".." || child.name.includes("/") || child.name.includes("\0")) fail2("invalid filesystem directory entry");
|
|
28968
|
+
const prefix3 = source2 === "." ? "" : source2.endsWith("/") ? source2 : `${source2}/`;
|
|
28969
|
+
await visit(`${prefix3}${child.name}`, `${name2}${child.name}`, depth + 1);
|
|
28970
|
+
}
|
|
28971
|
+
} finally {
|
|
28972
|
+
ancestors.pop();
|
|
28973
|
+
}
|
|
28974
|
+
}
|
|
28975
|
+
};
|
|
28976
|
+
for (const operand of parsed.operands) await visit(operand, memberName(operand, limits), 0);
|
|
28977
|
+
if (!selected.size) {
|
|
28978
|
+
const detail = parsed.recursive && parsed.firstOperand >= 0 ? `try: zip ${context2.args.slice(0, parsed.firstOperand).join(" ")} . -i ${context2.args.slice(parsed.firstOperand).join(" ")}` : parsed.archive;
|
|
28979
|
+
throw new ZipFailure(12, "Nothing to do!", detail);
|
|
28980
|
+
}
|
|
28981
|
+
const entries2 = [];
|
|
28982
|
+
const progress = [];
|
|
28983
|
+
let progressBytes = 0;
|
|
28984
|
+
const append = (entry, update) => {
|
|
28985
|
+
const percentage = entry.size ? Math.trunc((Math.trunc(200 * (entry.size - entry.data.length) / entry.size) + 1) / 2) : 0;
|
|
28986
|
+
const message3 = `${update ? "updating:" : " adding:"} ${entry.name} (${entry.method === 8 ? `deflated ${percentage}%` : "stored 0%"})
|
|
28987
|
+
`;
|
|
28988
|
+
const size = import_buffer.Buffer.byteLength(message3);
|
|
28989
|
+
if (size > limits.maxTextBytes - budget.textBytes - progressBytes) fail2("text output limit exceeded");
|
|
28990
|
+
progressBytes += size;
|
|
28991
|
+
progress.push(message3);
|
|
28992
|
+
};
|
|
28993
|
+
for (const entry of archive.entries) {
|
|
28994
|
+
if (++work > limits.maxPatternSteps) fail2("archive work limit exceeded");
|
|
28995
|
+
const replacement = selected.get(entry.name);
|
|
28996
|
+
if (replacement) {
|
|
28997
|
+
entries2.push(replacement.entry);
|
|
28998
|
+
append(replacement.entry, true);
|
|
28999
|
+
selected.delete(entry.name);
|
|
29000
|
+
} else {
|
|
29001
|
+
await budget.member(entry.size);
|
|
29002
|
+
entries2.push(entry);
|
|
29003
|
+
}
|
|
29004
|
+
}
|
|
29005
|
+
for (const { entry } of selected.values()) {
|
|
29006
|
+
entries2.push(entry);
|
|
29007
|
+
append(entry, false);
|
|
29008
|
+
}
|
|
29009
|
+
const bytes3 = await writeZipArchive({ entries: entries2, comment: archive.comment }, limits, context2.signal);
|
|
29010
|
+
return { output: output2, parentName, parent, existing: existing2, bytes: bytes3, progress };
|
|
29011
|
+
}
|
|
29012
|
+
function createZipCommand(options3 = {}) {
|
|
29013
|
+
const limits = settings2(options3);
|
|
29014
|
+
return { name: "zip", description: "Create or update bounded ZIP archives in the virtual filesystem", async execute(original) {
|
|
29015
|
+
original.signal.throwIfAborted();
|
|
29016
|
+
const scope = new ZipScope(original, limits);
|
|
29017
|
+
const context2 = scope.context;
|
|
29018
|
+
const budget = new Budget14(context2, limits);
|
|
29019
|
+
try {
|
|
29020
|
+
const parsed = parse12(context2, limits);
|
|
29021
|
+
const prepared = await prepare(scope, parsed, budget);
|
|
29022
|
+
await writeFileOutput(context2, prepared.bytes, () => scope.operation(() => publishZip(scope, prepared)));
|
|
29023
|
+
for (const message3 of prepared.progress) await budget.output(message3);
|
|
29024
|
+
return { exitCode: 0 };
|
|
29025
|
+
} catch (error) {
|
|
29026
|
+
original.signal.throwIfAborted();
|
|
29027
|
+
context2.signal.throwIfAborted();
|
|
29028
|
+
if (error instanceof ZipFailure) {
|
|
29029
|
+
await budget.output(`
|
|
29030
|
+
zip error: ${error.label} (${error.message})
|
|
29031
|
+
`);
|
|
29032
|
+
return { exitCode: error.status };
|
|
29033
|
+
}
|
|
29034
|
+
const message3 = escapeText(display(publicDiagnosticMessage(error, context2.onInternalError).slice(0, 1024)), "diagnostic");
|
|
29035
|
+
await writeBytes(context2.stderr, import_buffer.Buffer.from(`zip: ${message3}
|
|
29036
|
+
`).subarray(0, limits.maxDiagnosticBytes), context2.signal);
|
|
29037
|
+
return { exitCode: 2 };
|
|
29038
|
+
} finally {
|
|
29039
|
+
try {
|
|
29040
|
+
await scope.close();
|
|
29041
|
+
} finally {
|
|
29042
|
+
original.signal.throwIfAborted();
|
|
29043
|
+
}
|
|
29044
|
+
}
|
|
29045
|
+
} };
|
|
29046
|
+
}
|
|
29047
|
+
|
|
29048
|
+
// packages/safe-bash/src/commands/archive/unzip.ts
|
|
29049
|
+
init_platform();
|
|
29050
|
+
|
|
29051
|
+
// packages/safe-bash/src/commands/archive/unzip/arguments.ts
|
|
29052
|
+
init_platform();
|
|
29053
|
+
function parseArguments(context2, limits) {
|
|
29054
|
+
const { args } = context2;
|
|
29055
|
+
let bytes3 = 0;
|
|
29056
|
+
for (const argument2 of args) {
|
|
29057
|
+
bytes3 += import_buffer.Buffer.byteLength(argument2) + 1;
|
|
29058
|
+
if (bytes3 > limits.maxArgumentBytes) fail2("argument byte limit exceeded");
|
|
29059
|
+
if (argument2.includes("\0")) fail2("NUL in argument");
|
|
29060
|
+
}
|
|
29061
|
+
if (context2.argumentValues) {
|
|
29062
|
+
const argumentsValue = getCommandArguments(context2);
|
|
29063
|
+
let rawBytes = 0;
|
|
29064
|
+
for (const value2 of argumentsValue.values) {
|
|
29065
|
+
const size = shellValueByteLength(value2) + 1;
|
|
29066
|
+
if (size > limits.maxArgumentBytes - rawBytes) fail2("argument byte limit exceeded");
|
|
29067
|
+
rawBytes += size;
|
|
29068
|
+
}
|
|
29069
|
+
for (const value2 of argumentsValue.values) text2(shellValueBytes(value2));
|
|
29070
|
+
}
|
|
29071
|
+
let list = false;
|
|
29072
|
+
let overwrite = false;
|
|
29073
|
+
let destination2;
|
|
29074
|
+
let archive;
|
|
29075
|
+
let ended = false;
|
|
29076
|
+
const patterns2 = [];
|
|
29077
|
+
for (let index = 0; index < args.length; index++) {
|
|
29078
|
+
const argument2 = args[index];
|
|
29079
|
+
if (!ended && argument2 === "--") {
|
|
29080
|
+
ended = true;
|
|
29081
|
+
continue;
|
|
29082
|
+
}
|
|
29083
|
+
if (!ended && argument2.startsWith("-") && argument2 !== "-") {
|
|
29084
|
+
for (let offset = 1; offset < argument2.length; offset++) {
|
|
29085
|
+
const flag = argument2[offset];
|
|
29086
|
+
if (flag === "l") list = true;
|
|
29087
|
+
else if (flag === "o") overwrite = true;
|
|
29088
|
+
else if (flag === "d") {
|
|
29089
|
+
if (destination2 !== void 0) fail2("-d may only be specified once");
|
|
29090
|
+
destination2 = argument2.slice(offset + 1) || args[++index];
|
|
29091
|
+
if (!destination2) fail2("must specify directory to which to extract with -d option");
|
|
29092
|
+
checkPath(destination2, limits);
|
|
29093
|
+
break;
|
|
29094
|
+
} else fail2(`unsupported option: -${flag}`);
|
|
29095
|
+
}
|
|
29096
|
+
} else if (archive === void 0) archive = argument2;
|
|
29097
|
+
else patterns2.push(argument2);
|
|
29098
|
+
}
|
|
29099
|
+
if (archive === void 0) fail2("usage: unzip [-l] [-o] [-d DIR] ARCHIVE [FILES...]");
|
|
29100
|
+
checkPath(archive, limits);
|
|
29101
|
+
return { list, overwrite, destination: destination2, archive, patterns: patterns2 };
|
|
29102
|
+
}
|
|
29103
|
+
function tokenize2(pattern) {
|
|
29104
|
+
const characters = Array.from(pattern);
|
|
29105
|
+
const tokens2 = [];
|
|
29106
|
+
for (let index = 0; index < characters.length; index++) {
|
|
29107
|
+
const character = characters[index];
|
|
29108
|
+
if (character === "*") {
|
|
29109
|
+
if (tokens2.at(-1)?.kind !== "star") tokens2.push({ kind: "star" });
|
|
29110
|
+
} else if (character === "?") tokens2.push({ kind: "any" });
|
|
29111
|
+
else if (character === "\\") {
|
|
29112
|
+
const escaped3 = characters[++index];
|
|
29113
|
+
tokens2.push(escaped3 === void 0 ? { kind: "never" } : { kind: "literal", value: escaped3 });
|
|
29114
|
+
} else if (character === "[") {
|
|
29115
|
+
const negative = characters[index + 1] === "!" || characters[index + 1] === "^";
|
|
29116
|
+
if (negative) index++;
|
|
29117
|
+
const ranges = [];
|
|
29118
|
+
let closed = false;
|
|
29119
|
+
while (++index < characters.length) {
|
|
29120
|
+
let first = characters[index];
|
|
29121
|
+
if (first === "]") {
|
|
29122
|
+
closed = true;
|
|
29123
|
+
break;
|
|
29124
|
+
}
|
|
29125
|
+
if (first === "\\") first = characters[++index] ?? "";
|
|
29126
|
+
let last = first;
|
|
29127
|
+
if (characters[index + 1] === "-" && characters[index + 2] && characters[index + 2] !== "]") {
|
|
29128
|
+
index += 2;
|
|
29129
|
+
last = characters[index];
|
|
29130
|
+
if (last === "\\") last = characters[++index] ?? "";
|
|
29131
|
+
}
|
|
29132
|
+
ranges.push([first.codePointAt(0) ?? -1, last.codePointAt(0) ?? -1]);
|
|
29133
|
+
}
|
|
29134
|
+
tokens2.push(closed ? { kind: "class", ranges, negative } : { kind: "never" });
|
|
29135
|
+
} else tokens2.push({ kind: "literal", value: character });
|
|
29136
|
+
}
|
|
29137
|
+
return tokens2;
|
|
29138
|
+
}
|
|
29139
|
+
var Selection = class {
|
|
29140
|
+
constructor(patterns2, limits, signal) {
|
|
29141
|
+
this.limits = limits;
|
|
29142
|
+
this.signal = signal;
|
|
29143
|
+
this.patterns = patterns2.map(tokenize2);
|
|
29144
|
+
}
|
|
29145
|
+
limits;
|
|
29146
|
+
signal;
|
|
29147
|
+
work = 0;
|
|
29148
|
+
patterns;
|
|
29149
|
+
matched = /* @__PURE__ */ new Set();
|
|
29150
|
+
step() {
|
|
29151
|
+
if (++this.work > this.limits.maxPatternSteps) fail2("pattern work limit exceeded");
|
|
29152
|
+
}
|
|
29153
|
+
async matches(name2) {
|
|
29154
|
+
if (!this.patterns.length) return true;
|
|
29155
|
+
const characters = Array.from(name2);
|
|
29156
|
+
let selected = false;
|
|
29157
|
+
for (let pattern = 0; pattern < this.patterns.length; pattern++) {
|
|
29158
|
+
this.step();
|
|
29159
|
+
let states = new Uint8Array(characters.length + 1);
|
|
29160
|
+
states[0] = 1;
|
|
29161
|
+
for (const token of this.patterns[pattern]) {
|
|
29162
|
+
const next = new Uint8Array(states.length);
|
|
29163
|
+
for (let index = 0; index < states.length; index++) {
|
|
29164
|
+
this.step();
|
|
29165
|
+
if (token.kind === "star") next[index] = states[index] || (index > 0 ? next[index - 1] : 0);
|
|
29166
|
+
else if (states[index] && index < characters.length) {
|
|
29167
|
+
const character = characters[index];
|
|
29168
|
+
let match = token.kind === "any" || token.kind === "literal" && token.value === character;
|
|
29169
|
+
if (token.kind === "class") {
|
|
29170
|
+
let inRange = false;
|
|
29171
|
+
for (const [first, last] of token.ranges) {
|
|
29172
|
+
this.step();
|
|
29173
|
+
if (character.codePointAt(0) >= first && character.codePointAt(0) <= last) inRange = true;
|
|
29174
|
+
}
|
|
29175
|
+
match = inRange !== token.negative;
|
|
29176
|
+
}
|
|
29177
|
+
if (match) next[index + 1] = 1;
|
|
29178
|
+
}
|
|
29179
|
+
if (this.work % 4096 === 0) await yieldTurn(this.signal);
|
|
29180
|
+
}
|
|
29181
|
+
states = next;
|
|
29182
|
+
}
|
|
29183
|
+
if (states[characters.length]) {
|
|
29184
|
+
this.matched.add(pattern);
|
|
29185
|
+
selected = true;
|
|
29186
|
+
}
|
|
29187
|
+
}
|
|
29188
|
+
return selected;
|
|
29189
|
+
}
|
|
29190
|
+
};
|
|
29191
|
+
var Answers = class {
|
|
29192
|
+
constructor(source2, limits, signal) {
|
|
29193
|
+
this.limits = limits;
|
|
29194
|
+
this.signal = signal;
|
|
29195
|
+
this.iterator = readBytes(source2, signal)[Symbol.asyncIterator]();
|
|
29196
|
+
}
|
|
29197
|
+
limits;
|
|
29198
|
+
signal;
|
|
29199
|
+
iterator;
|
|
29200
|
+
chunk = new Uint8Array();
|
|
29201
|
+
offset = 0;
|
|
29202
|
+
bytes = 0;
|
|
29203
|
+
pulls = 0;
|
|
29204
|
+
async read(maximum = 9) {
|
|
29205
|
+
const answer = [];
|
|
29206
|
+
while (answer.length < maximum) {
|
|
29207
|
+
this.signal.throwIfAborted();
|
|
29208
|
+
if (this.offset === this.chunk.length) {
|
|
29209
|
+
if (++this.pulls > this.limits.maxPatternSteps) fail2("overwrite input work limit exceeded");
|
|
29210
|
+
if (this.pulls % 64 === 0) await yieldTurn(this.signal);
|
|
29211
|
+
const next = await this.iterator.next();
|
|
29212
|
+
if (next.done) break;
|
|
29213
|
+
if (next.value.length > this.limits.maxFilesFromBytes - this.bytes) fail2("overwrite input byte limit exceeded");
|
|
29214
|
+
this.bytes += next.value.length;
|
|
29215
|
+
this.chunk = Uint8Array.from(next.value);
|
|
29216
|
+
this.offset = 0;
|
|
29217
|
+
if (!this.chunk.length) continue;
|
|
29218
|
+
}
|
|
29219
|
+
const byte = this.chunk[this.offset++];
|
|
29220
|
+
answer.push(byte);
|
|
29221
|
+
if (byte === 10) break;
|
|
29222
|
+
}
|
|
29223
|
+
return answer.length ? import_buffer.Buffer.from(answer).toString("utf8") : void 0;
|
|
29224
|
+
}
|
|
29225
|
+
async close() {
|
|
29226
|
+
await this.iterator.return?.();
|
|
29227
|
+
}
|
|
29228
|
+
};
|
|
29229
|
+
|
|
29230
|
+
// packages/safe-bash/src/commands/archive/unzip/safety.ts
|
|
29231
|
+
init_platform();
|
|
29232
|
+
import { retainFileSystemCleanup as retainFileSystemCleanup2 } from "@poe-platform/safe-fs/core";
|
|
29233
|
+
var Extraction = class {
|
|
29234
|
+
constructor(context2, limits) {
|
|
29235
|
+
this.context = context2;
|
|
29236
|
+
this.limits = limits;
|
|
29237
|
+
}
|
|
29238
|
+
context;
|
|
29239
|
+
limits;
|
|
29240
|
+
pending = /* @__PURE__ */ new Set();
|
|
29241
|
+
publications = /* @__PURE__ */ new Set();
|
|
29242
|
+
readers = /* @__PURE__ */ new Set();
|
|
29243
|
+
closed = false;
|
|
29244
|
+
work = 0;
|
|
29245
|
+
serial = 0;
|
|
29246
|
+
async operation(action) {
|
|
29247
|
+
this.context.signal.throwIfAborted();
|
|
29248
|
+
if (this.closed) fail2("extraction is closed");
|
|
29249
|
+
if (++this.work > this.limits.maxPatternSteps) fail2("filesystem work limit exceeded");
|
|
29250
|
+
const pending = Promise.resolve().then(() => {
|
|
29251
|
+
this.context.signal.throwIfAborted();
|
|
29252
|
+
return action();
|
|
29253
|
+
});
|
|
29254
|
+
this.pending.add(pending);
|
|
29255
|
+
try {
|
|
29256
|
+
const value2 = await pending;
|
|
29257
|
+
this.context.signal.throwIfAborted();
|
|
29258
|
+
return value2;
|
|
29259
|
+
} finally {
|
|
29260
|
+
this.pending.delete(pending);
|
|
29261
|
+
}
|
|
29262
|
+
}
|
|
29263
|
+
async close() {
|
|
29264
|
+
this.closed = true;
|
|
29265
|
+
while (this.pending.size) await Promise.allSettled([...this.pending]);
|
|
29266
|
+
while (this.publications.size) await Promise.allSettled([...this.publications]);
|
|
29267
|
+
await Promise.allSettled([...this.readers].map((close) => close()));
|
|
29268
|
+
}
|
|
29269
|
+
source(source2) {
|
|
29270
|
+
return { [Symbol.asyncIterator]: () => {
|
|
29271
|
+
const state = {};
|
|
29272
|
+
let closing;
|
|
29273
|
+
const close = () => closing ??= (async () => {
|
|
29274
|
+
try {
|
|
29275
|
+
await state.iterator?.return?.();
|
|
29276
|
+
} finally {
|
|
29277
|
+
this.readers.delete(close);
|
|
29278
|
+
}
|
|
29279
|
+
})();
|
|
29280
|
+
this.readers.add(close);
|
|
29281
|
+
this.context.signal.throwIfAborted();
|
|
29282
|
+
state.iterator = source2[Symbol.asyncIterator]();
|
|
29283
|
+
return {
|
|
29284
|
+
next: () => this.operation(async () => {
|
|
29285
|
+
const result2 = await state.iterator.next();
|
|
29286
|
+
if (result2.done) this.readers.delete(close);
|
|
29287
|
+
return result2;
|
|
29288
|
+
}),
|
|
29289
|
+
async return() {
|
|
29290
|
+
await close();
|
|
29291
|
+
return { done: true, value: void 0 };
|
|
29292
|
+
}
|
|
29293
|
+
};
|
|
29294
|
+
} };
|
|
29295
|
+
}
|
|
29296
|
+
async *input(path) {
|
|
29297
|
+
const { fs, signal } = this.context;
|
|
29298
|
+
const capabilities = await this.operation(async () => await fs.capabilitiesFor?.(path, { signal }) ?? fs.capabilities);
|
|
29299
|
+
if (fs.readStream && capabilities.streamingRead !== false) {
|
|
29300
|
+
const source2 = await this.operation(async () => fs.readStream(path, { signal, chunkSize: this.limits.chunkSize }));
|
|
29301
|
+
yield* readBytes(this.source(source2), signal);
|
|
29302
|
+
} else {
|
|
29303
|
+
const stat = await this.operation(() => fs.stat(path, { signal }));
|
|
29304
|
+
if (stat.size > this.limits.maxBufferedFileBytes) fail2("filesystem lacks streaming reads: buffered file limit exceeded");
|
|
29305
|
+
const bytes3 = await this.operation(() => fs.readFile(path, { signal, maxBytes: this.limits.maxBufferedFileBytes }));
|
|
29306
|
+
if (bytes3.length > this.limits.maxBufferedFileBytes) fail2("buffered file limit exceeded");
|
|
29307
|
+
yield bytes3;
|
|
29308
|
+
}
|
|
29309
|
+
}
|
|
29310
|
+
async stat(path) {
|
|
29311
|
+
try {
|
|
29312
|
+
return await this.operation(() => this.context.fs.lstat(path, { signal: this.context.signal }));
|
|
29313
|
+
} catch (error) {
|
|
29314
|
+
this.context.signal.throwIfAborted();
|
|
29315
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") return void 0;
|
|
29316
|
+
throw error;
|
|
29317
|
+
}
|
|
29318
|
+
}
|
|
29319
|
+
async directory(raw, create) {
|
|
29320
|
+
checkPath(raw, this.limits);
|
|
29321
|
+
let current = "/";
|
|
29322
|
+
const { fs, signal } = this.context;
|
|
29323
|
+
for (const component of raw.split("/")) {
|
|
29324
|
+
if (!component || component === ".") continue;
|
|
29325
|
+
current = resolvePath(current, component);
|
|
29326
|
+
const stat = await this.stat(current);
|
|
29327
|
+
if (!stat && create) await this.operation(() => fs.mkdir(current, { signal, mode: 493 }));
|
|
29328
|
+
else if (!stat || stat.type !== "directory") fail2(`unsafe non-directory or symlink ancestor: ${display(current)}`);
|
|
29329
|
+
}
|
|
29330
|
+
return current;
|
|
29331
|
+
}
|
|
29332
|
+
async parents(root, path, create) {
|
|
29333
|
+
if (!isPathWithin(root, path)) fail2("extraction path escapes root");
|
|
29334
|
+
await this.directory(dirname(path), create);
|
|
29335
|
+
}
|
|
29336
|
+
member(root, name2) {
|
|
29337
|
+
checkPath(name2, this.limits);
|
|
29338
|
+
if (name2.startsWith("/") || name2.split("/").includes("..")) fail2(`unsafe archive member: ${display(name2)}`);
|
|
29339
|
+
const path = resolvePath(root, name2);
|
|
29340
|
+
checkPath(path, this.limits);
|
|
29341
|
+
if (!isPathWithin(root, path)) fail2("extraction path escapes root");
|
|
29342
|
+
return path;
|
|
29343
|
+
}
|
|
29344
|
+
async target(root, path, target) {
|
|
29345
|
+
checkPath(target, this.limits);
|
|
29346
|
+
if (target.startsWith("/")) fail2("symlink target escapes extraction root");
|
|
29347
|
+
let current = dirname(path);
|
|
29348
|
+
const components2 = (value2) => {
|
|
29349
|
+
checkPath(value2, this.limits);
|
|
29350
|
+
let descended = false;
|
|
29351
|
+
const result2 = value2.split("/");
|
|
29352
|
+
for (const component of result2) {
|
|
29353
|
+
if (component === ".." && descended) fail2("unsafe non-leading parent in symlink target");
|
|
29354
|
+
if (component && component !== "." && component !== "..") descended = true;
|
|
29355
|
+
}
|
|
29356
|
+
return result2;
|
|
29357
|
+
};
|
|
29358
|
+
let pending = components2(target);
|
|
29359
|
+
let links = 0;
|
|
29360
|
+
let steps = 0;
|
|
29361
|
+
while (pending.length) {
|
|
29362
|
+
if (++steps > this.limits.maxDepth * 41) fail2("symlink target resolution limit exceeded");
|
|
29363
|
+
const component = pending.shift();
|
|
29364
|
+
if (!component || component === ".") continue;
|
|
29365
|
+
if (component === "..") {
|
|
29366
|
+
if (current === root) fail2("symlink target escapes extraction root");
|
|
29367
|
+
current = dirname(current);
|
|
29368
|
+
continue;
|
|
29369
|
+
}
|
|
29370
|
+
const candidate = resolvePath(current, component);
|
|
29371
|
+
checkPath(candidate, this.limits);
|
|
29372
|
+
if (!isPathWithin(root, candidate)) fail2("symlink target escapes extraction root");
|
|
29373
|
+
const stat = await this.stat(candidate);
|
|
29374
|
+
if (stat?.type === "symlink") {
|
|
29375
|
+
if (++links > 40 || !this.context.fs.readlink) fail2("symlink target chain cannot be safely resolved");
|
|
29376
|
+
const link = await this.operation(() => this.context.fs.readlink(candidate, { signal: this.context.signal }));
|
|
29377
|
+
if (link.startsWith("/")) fail2("absolute symlink target chain is unsafe");
|
|
29378
|
+
pending = [...components2(link), ...pending];
|
|
29379
|
+
if (pending.length > this.limits.maxDepth * 41) fail2("symlink target resolution limit exceeded");
|
|
29380
|
+
} else current = candidate;
|
|
29381
|
+
}
|
|
29382
|
+
}
|
|
29383
|
+
async destination(path, archivePath, archiveStat) {
|
|
29384
|
+
const stat = await this.stat(path);
|
|
29385
|
+
if (path === archivePath || stat && sameIdentity2(stat, archiveStat)) fail2("entry would overwrite input archive");
|
|
29386
|
+
if (stat && stat.type !== "file") fail2(`unsafe non-regular destination: ${display(path)}`);
|
|
29387
|
+
if (stat && (!hasIdentity(stat) || !hasIdentity(archiveStat))) fail2("cannot overwrite file with unknown input-archive backing identity");
|
|
29388
|
+
return stat;
|
|
29389
|
+
}
|
|
29390
|
+
async checked(root, path, expected) {
|
|
29391
|
+
await this.parents(root, path, false);
|
|
29392
|
+
const current = await this.stat(path);
|
|
29393
|
+
if (!current || current.type !== expected.type || !sameIdentity2(current, expected)) fail2("extraction entry changed before mutation");
|
|
29394
|
+
}
|
|
29395
|
+
async metadata(root, path, identity2, mode, modified) {
|
|
29396
|
+
const { fs, signal } = this.context;
|
|
29397
|
+
if (fs.chmod && fs.capabilities.permissions !== false) {
|
|
29398
|
+
await this.checked(root, path, identity2);
|
|
29399
|
+
await this.operation(() => fs.chmod(path, mode & 511, { signal }));
|
|
29400
|
+
}
|
|
29401
|
+
if (fs.utimes && fs.capabilities.timestamps !== false) {
|
|
29402
|
+
await this.checked(root, path, identity2);
|
|
29403
|
+
await this.operation(() => fs.utimes(path, modified.getTime(), modified.getTime(), { signal }));
|
|
29404
|
+
}
|
|
29405
|
+
}
|
|
29406
|
+
publish(root, path, chunks, expected, mode, modified, target) {
|
|
29407
|
+
const publication = this.stage(root, path, chunks, expected, mode, modified, target);
|
|
29408
|
+
this.publications.add(publication);
|
|
29409
|
+
return publication.finally(() => {
|
|
29410
|
+
this.publications.delete(publication);
|
|
29411
|
+
});
|
|
29412
|
+
}
|
|
29413
|
+
async stage(root, path, chunks, expected, mode, modified, target) {
|
|
29414
|
+
const { fs, signal } = this.context;
|
|
29415
|
+
let temporary = "";
|
|
29416
|
+
let identity2;
|
|
29417
|
+
let created = false;
|
|
29418
|
+
let failure;
|
|
29419
|
+
const cleanup = retainFileSystemCleanup2(fs, async (view) => {
|
|
29420
|
+
if (!created || !identity2) return;
|
|
29421
|
+
try {
|
|
29422
|
+
let parent = "/";
|
|
29423
|
+
for (const component of dirname(temporary).split("/").filter(Boolean)) {
|
|
29424
|
+
parent = resolvePath(parent, component);
|
|
29425
|
+
if ((await view.lstat(parent)).type !== "directory") return;
|
|
29426
|
+
}
|
|
29427
|
+
const current = await view.lstat(temporary);
|
|
29428
|
+
if (current.type === identity2.type && sameIdentity2(current, identity2)) await view.rm(temporary);
|
|
29429
|
+
} catch (error) {
|
|
29430
|
+
if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "ENOENT") throw error;
|
|
29431
|
+
}
|
|
29432
|
+
}, { maxOperations: Math.min(4096, this.limits.maxDepth + 3) });
|
|
29433
|
+
try {
|
|
29434
|
+
await this.parents(root, path, true);
|
|
29435
|
+
for (let attempt = 0; attempt < this.limits.maxMembers; attempt++) {
|
|
29436
|
+
temporary = resolvePath(dirname(path), `.unzip-${++this.serial}`);
|
|
29437
|
+
checkPath(temporary, this.limits);
|
|
29438
|
+
if (temporary === path || await this.stat(temporary)) continue;
|
|
29439
|
+
await this.operation(async () => {
|
|
29440
|
+
if (target === void 0) await fs.writeFile(temporary, new Uint8Array(), { signal, flag: "wx", mode: 384 });
|
|
29441
|
+
else await fs.symlink(target, temporary, { signal });
|
|
29442
|
+
created = true;
|
|
29443
|
+
identity2 = await fs.lstat(temporary);
|
|
29444
|
+
});
|
|
29445
|
+
if (!identity2 || !hasIdentity(identity2)) fail2("temporary file backing identity unavailable");
|
|
29446
|
+
break;
|
|
29447
|
+
}
|
|
29448
|
+
if (!created) fail2("temporary file attempt limit exceeded");
|
|
29449
|
+
if (target === void 0) {
|
|
29450
|
+
for (const chunk of chunks) {
|
|
29451
|
+
await this.checked(root, temporary, identity2);
|
|
29452
|
+
await this.operation(() => fs.appendFile(temporary, chunk, { signal }));
|
|
29453
|
+
}
|
|
29454
|
+
await this.metadata(root, temporary, identity2, mode, modified);
|
|
29455
|
+
}
|
|
29456
|
+
await this.parents(root, path, false);
|
|
29457
|
+
const current = await this.stat(path);
|
|
29458
|
+
if (current ? !expected || !sameIdentity2(current, expected) || current.type !== "file" : expected !== void 0) fail2("destination changed before publication");
|
|
29459
|
+
const staging = await this.stat(temporary);
|
|
29460
|
+
if (!staging || !identity2 || !sameIdentity2(staging, identity2) || staging.type !== (target === void 0 ? "file" : "symlink")) fail2("temporary file changed before publication");
|
|
29461
|
+
await this.operation(() => fs.rename(temporary, path, { signal }));
|
|
29462
|
+
created = false;
|
|
29463
|
+
} catch (error) {
|
|
29464
|
+
failure = { reason: error };
|
|
29465
|
+
}
|
|
29466
|
+
try {
|
|
29467
|
+
await cleanup();
|
|
29468
|
+
} catch (error) {
|
|
29469
|
+
if (failure) throw new AggregateError([failure.reason, error], "unzip publication and cleanup failed");
|
|
29470
|
+
throw error;
|
|
29471
|
+
}
|
|
29472
|
+
if (failure) throw failure.reason;
|
|
29473
|
+
}
|
|
29474
|
+
};
|
|
29475
|
+
|
|
29476
|
+
// packages/safe-bash/src/commands/archive/unzip.ts
|
|
29477
|
+
function filtered(name2) {
|
|
29478
|
+
let output2 = "";
|
|
29479
|
+
for (const character of name2) {
|
|
29480
|
+
const code = character.charCodeAt(0);
|
|
29481
|
+
output2 += code < 32 ? `^${String.fromCharCode(code + 64)}` : character;
|
|
29482
|
+
}
|
|
29483
|
+
return output2;
|
|
29484
|
+
}
|
|
29485
|
+
function padded(name2) {
|
|
29486
|
+
return name2 + " ".repeat(Math.max(0, 22 - import_buffer.Buffer.byteLength(name2)));
|
|
29487
|
+
}
|
|
29488
|
+
function date(entry) {
|
|
29489
|
+
const modified = entry.modified;
|
|
29490
|
+
const pad = (value2) => String(value2).padStart(2, "0");
|
|
29491
|
+
return `${modified.getFullYear()}-${pad(modified.getMonth() + 1)}-${pad(modified.getDate())} ${pad(modified.getHours())}:${pad(modified.getMinutes())}`;
|
|
29492
|
+
}
|
|
29493
|
+
async function comment(bytes3, budget) {
|
|
29494
|
+
if (!bytes3.length) return;
|
|
29495
|
+
const output2 = [];
|
|
29496
|
+
let length = 0;
|
|
29497
|
+
for (const byte of bytes3) {
|
|
29498
|
+
if (!byte) break;
|
|
29499
|
+
if (byte !== 13 && byte !== 19) length += byte === 27 ? 2 : 1;
|
|
29500
|
+
if (length > budget.limits.maxTextBytes - budget.textBytes) fail2("text output limit exceeded");
|
|
29501
|
+
}
|
|
29502
|
+
for (const byte of bytes3) {
|
|
29503
|
+
if (!byte) break;
|
|
29504
|
+
if (byte === 13 || byte === 19) continue;
|
|
29505
|
+
if (byte === 27) output2.push(94, 91);
|
|
29506
|
+
else output2.push(byte);
|
|
29507
|
+
}
|
|
29508
|
+
if (output2.length && output2.at(-1) !== 10) output2.push(10);
|
|
29509
|
+
const value2 = Uint8Array.from(output2);
|
|
29510
|
+
if (value2.length > budget.limits.maxTextBytes - budget.textBytes) fail2("text output limit exceeded");
|
|
29511
|
+
budget.textBytes += value2.length;
|
|
29512
|
+
await writeBytes(budget.context.stdout, value2, budget.context.signal);
|
|
29513
|
+
}
|
|
29514
|
+
function createUnzipCommand(options3 = {}) {
|
|
29515
|
+
const limits = settings2(options3);
|
|
29516
|
+
return { name: "unzip", description: "List and safely extract ZIP archives in the virtual filesystem", async execute(original) {
|
|
29517
|
+
original.signal.throwIfAborted();
|
|
29518
|
+
const controller = new AbortController();
|
|
29519
|
+
const context2 = { ...original, signal: AbortSignal.any([original.signal, controller.signal]) };
|
|
29520
|
+
const extraction = new Extraction(context2, limits);
|
|
29521
|
+
let answers;
|
|
29522
|
+
let closing;
|
|
29523
|
+
const close = () => closing ??= (async () => {
|
|
29524
|
+
controller.abort(new Error("unzip command closed"));
|
|
29525
|
+
await extraction.close();
|
|
29526
|
+
await answers?.close().catch(() => {
|
|
29527
|
+
});
|
|
29528
|
+
})();
|
|
29529
|
+
original.registerCleanup?.(close);
|
|
29530
|
+
const budget = new Budget14(context2, limits);
|
|
29531
|
+
try {
|
|
29532
|
+
const parsed = parseArguments(context2, limits);
|
|
29533
|
+
const selection = new Selection(parsed.patterns, limits, context2.signal);
|
|
29534
|
+
let archive = parsed.archive;
|
|
29535
|
+
let archiveStat;
|
|
29536
|
+
for (const candidate of [archive, `${archive}.zip`, `${archive}.ZIP`]) {
|
|
29537
|
+
checkPath(candidate, limits);
|
|
29538
|
+
const candidateStat2 = await extraction.stat(vfsPath(context2.cwd, candidate));
|
|
29539
|
+
if (candidateStat2) {
|
|
29540
|
+
archive = candidate;
|
|
29541
|
+
archiveStat = candidateStat2;
|
|
29542
|
+
break;
|
|
29543
|
+
}
|
|
29544
|
+
}
|
|
29545
|
+
if (!archiveStat) {
|
|
29546
|
+
await budget.output(`unzip: cannot find or open ${archive}, ${archive}.zip or ${archive}.ZIP.
|
|
29547
|
+
`, true);
|
|
29548
|
+
return { exitCode: 9 };
|
|
29549
|
+
}
|
|
29550
|
+
const archivePath = await extraction.operation(() => context2.fs.realpath(vfsPath(context2.cwd, archive), { signal: context2.signal }));
|
|
29551
|
+
archiveStat = await extraction.operation(() => context2.fs.stat(archivePath, { signal: context2.signal }));
|
|
29552
|
+
if (archiveStat.type !== "file") fail2("input archive is not a regular file");
|
|
29553
|
+
const bytes3 = await collectBytes(bounded(extraction.input(archivePath), limits.maxArchiveBytes, context2.signal, limits.chunkSize), { signal: context2.signal, maxBytes: limits.maxArchiveBytes });
|
|
29554
|
+
await budget.output(`Archive: ${filtered(archive)}
|
|
29555
|
+
`);
|
|
29556
|
+
const zip = await readZipArchive(bytes3, limits, context2.signal);
|
|
29557
|
+
await comment(zip.comment, budget);
|
|
29558
|
+
if (!zip.entries.length) {
|
|
29559
|
+
await budget.output(`warning [${filtered(archive)}]: zipfile is empty
|
|
29560
|
+
`, true);
|
|
29561
|
+
return { exitCode: 1 };
|
|
29562
|
+
}
|
|
29563
|
+
if (parsed.list) await budget.output(" Length Date Time Name\n--------- ---------- ----- ----\n");
|
|
29564
|
+
const rootRaw = parsed.destination === void 0 ? context2.cwd : vfsPath(context2.cwd, parsed.destination);
|
|
29565
|
+
const root = parsed.list ? resolvePath(rootRaw) : await extraction.directory(rootRaw, true);
|
|
29566
|
+
answers = new Answers(extraction.source(context2.stdin), limits, context2.signal);
|
|
29567
|
+
let overwrite = parsed.overwrite ? "all" : "ask";
|
|
29568
|
+
let exitCode = 0;
|
|
29569
|
+
let selected = 0;
|
|
29570
|
+
let total = 0;
|
|
29571
|
+
let actualTotal = 0;
|
|
29572
|
+
const links = [];
|
|
29573
|
+
const directories = [];
|
|
29574
|
+
for (const entry of zip.entries) {
|
|
29575
|
+
await budget.member(entry.size);
|
|
29576
|
+
checkPath(entry.name, limits);
|
|
29577
|
+
if (!await selection.matches(entry.name)) continue;
|
|
29578
|
+
selected++;
|
|
29579
|
+
total += entry.size;
|
|
29580
|
+
if (parsed.list) {
|
|
29581
|
+
await budget.output(`${String(entry.size).padStart(9)} ${date(entry)} ${filtered(entry.name)}
|
|
29582
|
+
`);
|
|
29583
|
+
if (entry.comment) await comment(entry.comment, budget);
|
|
29584
|
+
continue;
|
|
29585
|
+
}
|
|
29586
|
+
let path = extraction.member(root, entry.name);
|
|
29587
|
+
const fileType = entry.mode & 61440;
|
|
29588
|
+
if (fileType && fileType !== 32768 && fileType !== 16384 && fileType !== 40960) fail2("unsupported special ZIP entry");
|
|
29589
|
+
if (path === root && !entry.directory) fail2("entry would replace extraction root");
|
|
29590
|
+
let shown = parsed.destination === void 0 ? entry.name : `${parsed.destination.endsWith("/") ? parsed.destination : `${parsed.destination}/`}${entry.name}`;
|
|
29591
|
+
await extraction.parents(root, path, true);
|
|
29592
|
+
if (entry.directory) {
|
|
29593
|
+
if (entry.size) fail2("directory has nonempty payload");
|
|
29594
|
+
for await (const chunk of readBytes(decodeZipEntry(entry, limits, context2.signal), context2.signal)) {
|
|
29595
|
+
await writeFileOutput(context2, chunk, async () => {
|
|
29596
|
+
if (chunk.length) fail2("directory has nonempty payload");
|
|
29597
|
+
});
|
|
29598
|
+
}
|
|
29599
|
+
const existing3 = await extraction.stat(path);
|
|
29600
|
+
if (existing3 && existing3.type !== "directory") fail2("directory destination is not a directory");
|
|
29601
|
+
if (!existing3) {
|
|
29602
|
+
await extraction.operation(() => context2.fs.mkdir(path, { signal: context2.signal, mode: 493 }));
|
|
29603
|
+
await budget.output(` creating: ${filtered(shown)}
|
|
29604
|
+
`);
|
|
29605
|
+
}
|
|
29606
|
+
const identity2 = await extraction.stat(path);
|
|
29607
|
+
if (!identity2 || identity2.type !== "directory") fail2("directory changed during creation");
|
|
29608
|
+
directories.push({ path, entry, identity: identity2 });
|
|
29609
|
+
continue;
|
|
29610
|
+
}
|
|
29611
|
+
let existing2 = await extraction.destination(path, archivePath, archiveStat);
|
|
29612
|
+
let skip = false;
|
|
29613
|
+
let prompting = 0;
|
|
29614
|
+
while (existing2 && overwrite !== "all") {
|
|
29615
|
+
if (overwrite === "none") {
|
|
29616
|
+
skip = true;
|
|
29617
|
+
break;
|
|
29618
|
+
}
|
|
29619
|
+
if (++prompting > limits.maxMembers) fail2("overwrite prompt work limit exceeded");
|
|
29620
|
+
await budget.output(`replace ${filtered(shown)}? [y]es, [n]o, [A]ll, [N]one, [r]ename: `, true);
|
|
29621
|
+
const answer = await answers.read();
|
|
29622
|
+
if (answer === void 0) {
|
|
29623
|
+
await budget.output(' NULL\n(EOF or read error, treating as "[N]one" ...)\n', true);
|
|
29624
|
+
overwrite = "none";
|
|
29625
|
+
exitCode = 1;
|
|
29626
|
+
skip = true;
|
|
29627
|
+
break;
|
|
29628
|
+
}
|
|
29629
|
+
const choice = answer[0];
|
|
29630
|
+
if (choice === "A") {
|
|
29631
|
+
overwrite = "all";
|
|
29632
|
+
break;
|
|
29633
|
+
}
|
|
29634
|
+
if (choice === "y" || choice === "Y") break;
|
|
29635
|
+
if (choice === "n" || choice === "N") {
|
|
29636
|
+
if (choice === "N") overwrite = "none";
|
|
29637
|
+
skip = true;
|
|
29638
|
+
break;
|
|
29639
|
+
}
|
|
29640
|
+
if (choice === "r" || choice === "R") {
|
|
29641
|
+
let renamed = "";
|
|
29642
|
+
while (!renamed) {
|
|
29643
|
+
await budget.output("new name: ", true);
|
|
29644
|
+
const value2 = await answers.read(limits.maxPathBytes);
|
|
29645
|
+
if (value2 === void 0) fail2("EOF while reading replacement name");
|
|
29646
|
+
renamed = value2.endsWith("\n") ? value2.slice(0, -1) : value2;
|
|
29647
|
+
}
|
|
29648
|
+
path = extraction.member(root, renamed);
|
|
29649
|
+
shown = parsed.destination === void 0 ? renamed : `${parsed.destination.endsWith("/") ? parsed.destination : `${parsed.destination}/`}${renamed}`;
|
|
29650
|
+
await extraction.parents(root, path, true);
|
|
29651
|
+
existing2 = await extraction.destination(path, archivePath, archiveStat);
|
|
29652
|
+
continue;
|
|
29653
|
+
}
|
|
29654
|
+
const response = choice === "\n" || choice === "\r" ? "{ENTER}" : answer.endsWith("\n") ? answer.slice(0, -1) : answer;
|
|
29655
|
+
await budget.output(`error: invalid response [${response}]
|
|
29656
|
+
`, true);
|
|
29657
|
+
}
|
|
29658
|
+
if (skip) continue;
|
|
29659
|
+
const chunks = [];
|
|
29660
|
+
let actual = 0;
|
|
29661
|
+
for await (const chunk of readBytes(decodeZipEntry(entry, limits, context2.signal), context2.signal)) {
|
|
29662
|
+
if (chunk.length > limits.maxEntryBytes - actual || chunk.length > limits.maxTotalBytes - actualTotal) fail2("actual decompressed byte limit exceeded");
|
|
29663
|
+
actual += chunk.length;
|
|
29664
|
+
actualTotal += chunk.length;
|
|
29665
|
+
await writeFileOutput(context2, chunk, async (bytes4) => {
|
|
29666
|
+
chunks.push(Uint8Array.from(bytes4));
|
|
29667
|
+
});
|
|
29668
|
+
}
|
|
29669
|
+
if (entry.symlink) {
|
|
29670
|
+
if (actual > limits.maxPathBytes) fail2("symlink target byte limit exceeded");
|
|
29671
|
+
const target = text2(import_buffer.Buffer.concat(chunks));
|
|
29672
|
+
await extraction.target(root, path, target);
|
|
29673
|
+
if (!context2.fs.symlink || context2.fs.capabilities.symlinks === false) fail2("filesystem does not support symlinks");
|
|
29674
|
+
links.push({ path, shown, target, existing: existing2, entry });
|
|
29675
|
+
await budget.output(` linking: ${padded(filtered(shown))} -> ${filtered(target)}
|
|
29676
|
+
`);
|
|
29677
|
+
} else {
|
|
29678
|
+
await extraction.publish(root, path, chunks, existing2, entry.mode, entry.modified);
|
|
29679
|
+
await budget.output(`${entry.method === 0 ? " extracting" : " inflating"}: ${padded(filtered(shown))}
|
|
29680
|
+
`);
|
|
29681
|
+
}
|
|
29682
|
+
}
|
|
29683
|
+
if (parsed.list) await budget.output(`--------- -------
|
|
29684
|
+
${String(total).padStart(9)} ${selected} file${selected === 1 ? "" : "s"}
|
|
29685
|
+
`);
|
|
29686
|
+
else {
|
|
29687
|
+
if (links.length) await budget.output("finishing deferred symbolic links:\n");
|
|
29688
|
+
for (const link of links) {
|
|
29689
|
+
await extraction.parents(root, link.path, false);
|
|
29690
|
+
await extraction.target(root, link.path, link.target);
|
|
29691
|
+
await extraction.destination(link.path, archivePath, archiveStat);
|
|
29692
|
+
await extraction.publish(root, link.path, [], link.existing, link.entry.mode, link.entry.modified, link.target);
|
|
29693
|
+
await budget.output(` ${padded(filtered(link.shown))} -> ${filtered(link.target)}
|
|
29694
|
+
`);
|
|
29695
|
+
}
|
|
29696
|
+
for (const { path, entry, identity: identity2 } of directories.reverse()) {
|
|
29697
|
+
await extraction.metadata(root, path, identity2, entry.mode, entry.modified);
|
|
29698
|
+
}
|
|
29699
|
+
for (let index = 0; index < parsed.patterns.length; index++) if (!selection.matched.has(index)) {
|
|
29700
|
+
await budget.output(`caution: filename not matched: ${filtered(parsed.patterns[index])}
|
|
29701
|
+
`, true);
|
|
29702
|
+
exitCode = 11;
|
|
29703
|
+
}
|
|
29704
|
+
}
|
|
29705
|
+
return { exitCode: selected ? exitCode : 11 };
|
|
29706
|
+
} catch (error) {
|
|
29707
|
+
original.signal.throwIfAborted();
|
|
29708
|
+
const message3 = display(publicDiagnosticMessage(error, original.onInternalError).slice(0, limits.maxDiagnosticBytes));
|
|
29709
|
+
await writeBytes(original.stderr, import_buffer.Buffer.from(`unzip: ${message3}
|
|
29710
|
+
`).subarray(0, limits.maxDiagnosticBytes), original.signal);
|
|
29711
|
+
return { exitCode: 2 };
|
|
29712
|
+
} finally {
|
|
29713
|
+
await close();
|
|
29714
|
+
}
|
|
29715
|
+
} };
|
|
29716
|
+
}
|
|
29717
|
+
|
|
28179
29718
|
// packages/safe-bash/src/commands/archive/index.ts
|
|
28180
29719
|
function createTarCommand(options3 = {}) {
|
|
28181
29720
|
const limits = settings2(options3);
|
|
@@ -28219,12 +29758,16 @@ function createTarCommand(options3 = {}) {
|
|
|
28219
29758
|
} };
|
|
28220
29759
|
}
|
|
28221
29760
|
function createArchiveCommands(options3 = {}) {
|
|
28222
|
-
return [createTarCommand(options3)];
|
|
29761
|
+
return [createTarCommand(options3), createZipCommand(options3), createUnzipCommand(options3)];
|
|
28223
29762
|
}
|
|
28224
29763
|
function archiveCommands(options3 = {}) {
|
|
28225
29764
|
const commands = createArchiveCommands(options3);
|
|
28226
29765
|
return { name: "archive-commands", setup(host2) {
|
|
28227
|
-
if (!options3.replace
|
|
29766
|
+
if (!options3.replace) {
|
|
29767
|
+
for (const command7 of commands) {
|
|
29768
|
+
if (host2.commands.has(command7.name)) throw new Error(`Command already registered: ${command7.name}`);
|
|
29769
|
+
}
|
|
29770
|
+
}
|
|
28228
29771
|
for (const command7 of commands) host2.commands.register(command7, { replace: options3.replace ?? false });
|
|
28229
29772
|
} };
|
|
28230
29773
|
}
|
|
@@ -28642,17 +30185,17 @@ function createCommCommand(options3 = {}) {
|
|
|
28642
30185
|
|
|
28643
30186
|
// packages/safe-bash/src/commands/table-text/join.ts
|
|
28644
30187
|
init_platform();
|
|
28645
|
-
function
|
|
30188
|
+
function number4(value2, label) {
|
|
28646
30189
|
if (!/^[0-9]+$/u.test(value2) || !Number.isSafeInteger(Number(value2)) || Number(value2) < 1) fail3(`invalid ${label}: ${value2}`);
|
|
28647
30190
|
return Number(value2);
|
|
28648
30191
|
}
|
|
28649
|
-
function
|
|
30192
|
+
function parse13(context2, budget) {
|
|
28650
30193
|
const options3 = { files: [], fields: [0, 0], unpaired: /* @__PURE__ */ new Set(), paired: true, separator: 10, delimiter: void 0, whole: false, replacement: empty, format: void 0, fold: false, header: false, order: "default" };
|
|
28651
30194
|
let literal = false;
|
|
28652
30195
|
let delimiterChoice;
|
|
28653
30196
|
const apply = (flag, value2) => {
|
|
28654
30197
|
if (flag === "1" || flag === "2" || flag === "j") {
|
|
28655
|
-
const field2 =
|
|
30198
|
+
const field2 = number4(value2, "field") - 1;
|
|
28656
30199
|
if (flag !== "2") options3.fields[0] = field2;
|
|
28657
30200
|
if (flag !== "1") options3.fields[1] = field2;
|
|
28658
30201
|
} else if (flag === "a" || flag === "v") {
|
|
@@ -28687,7 +30230,7 @@ function parse12(context2, budget) {
|
|
|
28687
30230
|
if (specification === "0") return { file: 0, index: 0 };
|
|
28688
30231
|
const match = /^([12])\.([0-9]+)$/u.exec(specification);
|
|
28689
30232
|
if (!match) fail3(`invalid output field: ${specification}`);
|
|
28690
|
-
return { file: Number(match[1]), index:
|
|
30233
|
+
return { file: Number(match[1]), index: number4(match[2], "output field") - 1 };
|
|
28691
30234
|
});
|
|
28692
30235
|
options3.format = [...Array.isArray(options3.format) ? options3.format : [], ...fields3];
|
|
28693
30236
|
budget.check(options3.format.length, budget.limits.maxFields, "field");
|
|
@@ -28769,7 +30312,7 @@ function split3(bytes3, options3, budget) {
|
|
|
28769
30312
|
function createJoinCommand(factory = {}) {
|
|
28770
30313
|
const limits = settings3(factory);
|
|
28771
30314
|
return command3("join", async (context2) => {
|
|
28772
|
-
const budget = new Budget17(context2, limits), options3 =
|
|
30315
|
+
const budget = new Budget17(context2, limits), options3 = parse13(context2, budget);
|
|
28773
30316
|
requireCLocale(context2);
|
|
28774
30317
|
const inputs2 = new Inputs(context2, budget, options3.separator), order = new OrderCheck(options3.order, context2);
|
|
28775
30318
|
const terminator = Uint8Array.of(options3.separator), delimiter = Uint8Array.of(options3.delimiter ?? 32);
|
|
@@ -29195,9 +30738,9 @@ function tabs(specifications) {
|
|
|
29195
30738
|
if (!entry) continue;
|
|
29196
30739
|
const prefix3 = entry.match(/^[+/]+/u)?.[0] ?? "";
|
|
29197
30740
|
if (prefix3) marker = prefix3.at(-1);
|
|
29198
|
-
const
|
|
29199
|
-
if (!
|
|
29200
|
-
const stop = integer(
|
|
30741
|
+
const number6 = entry.slice(prefix3.length);
|
|
30742
|
+
if (!number6) continue;
|
|
30743
|
+
const stop = integer(number6, marker ? 0 : 1);
|
|
29201
30744
|
if (marker === "+") {
|
|
29202
30745
|
if (relativeRepeat) throw new UsageError("repeating tab stop must be last");
|
|
29203
30746
|
relativeRepeat = stop;
|
|
@@ -29614,9 +31157,9 @@ function fixed2(coefficient, scale, precision) {
|
|
|
29614
31157
|
function exponentOf(coefficient, scale) {
|
|
29615
31158
|
return coefficient === 0n ? 0 : (coefficient < 0n ? -coefficient : coefficient).toString().length - scale - 1;
|
|
29616
31159
|
}
|
|
29617
|
-
function formatted2(coefficient, scale,
|
|
29618
|
-
const kind =
|
|
29619
|
-
let precision =
|
|
31160
|
+
function formatted2(coefficient, scale, format3, negativeZero = false) {
|
|
31161
|
+
const kind = format3.kind.toLowerCase();
|
|
31162
|
+
let precision = format3.precision;
|
|
29620
31163
|
let exponent = exponentOf(coefficient, scale);
|
|
29621
31164
|
let text3;
|
|
29622
31165
|
if (kind === "f") text3 = fixed2(coefficient, scale, precision);
|
|
@@ -29628,24 +31171,24 @@ function formatted2(coefficient, scale, format2, negativeZero = false) {
|
|
|
29628
31171
|
exponent = exponentOf(value2, significantScale);
|
|
29629
31172
|
if (kind === "e" || exponent < -4 || exponent >= precision) {
|
|
29630
31173
|
text3 = fixed2(value2, significantScale + exponent, significant - 1);
|
|
29631
|
-
if (kind === "g" && !
|
|
29632
|
-
if (
|
|
31174
|
+
if (kind === "g" && !format3.flags.includes("#") && text3.includes(".")) text3 = text3.replace(/\.?0+$/u, "");
|
|
31175
|
+
if (format3.flags.includes("#") && !text3.includes(".")) text3 += ".";
|
|
29633
31176
|
text3 += `e${exponent < 0 ? "-" : "+"}${Math.abs(exponent).toString().padStart(2, "0")}`;
|
|
29634
31177
|
} else {
|
|
29635
31178
|
text3 = fixed2(value2, significantScale, Math.max(0, precision - exponent - 1));
|
|
29636
|
-
if (!
|
|
31179
|
+
if (!format3.flags.includes("#") && text3.includes(".")) text3 = text3.replace(/\.?0+$/u, "");
|
|
29637
31180
|
}
|
|
29638
31181
|
}
|
|
29639
|
-
if (
|
|
31182
|
+
if (format3.flags.includes("#") && !text3.includes(".") && !text3.includes("e")) text3 += ".";
|
|
29640
31183
|
if ((coefficient < 0n || negativeZero) && !text3.startsWith("-")) text3 = "-" + text3;
|
|
29641
|
-
if (coefficient >= 0n && !negativeZero) text3 = (
|
|
29642
|
-
if (
|
|
29643
|
-
if (
|
|
29644
|
-
else if (
|
|
31184
|
+
if (coefficient >= 0n && !negativeZero) text3 = (format3.flags.includes("+") ? "+" : format3.flags.includes(" ") ? " " : "") + text3;
|
|
31185
|
+
if (format3.kind === format3.kind.toUpperCase()) text3 = text3.toUpperCase();
|
|
31186
|
+
if (format3.flags.includes("-")) text3 = text3.padEnd(format3.width, " ");
|
|
31187
|
+
else if (format3.flags.includes("0")) {
|
|
29645
31188
|
const sign = /^[+ -]/u.test(text3) ? text3[0] : "";
|
|
29646
|
-
text3 = sign + text3.slice(sign.length).padStart(Math.max(0,
|
|
29647
|
-
} else text3 = text3.padStart(
|
|
29648
|
-
return
|
|
31189
|
+
text3 = sign + text3.slice(sign.length).padStart(Math.max(0, format3.width - sign.length), "0");
|
|
31190
|
+
} else text3 = text3.padStart(format3.width, " ");
|
|
31191
|
+
return format3.prefix + text3 + format3.suffix;
|
|
29649
31192
|
}
|
|
29650
31193
|
function binaryDecimal(value2) {
|
|
29651
31194
|
const view = new DataView(new ArrayBuffer(8));
|
|
@@ -29658,12 +31201,12 @@ function binaryDecimal(value2) {
|
|
|
29658
31201
|
if (bits >> 63n) coefficient = -coefficient;
|
|
29659
31202
|
return power2 >= 0 ? { coefficient: coefficient << BigInt(power2), scale: 0 } : { coefficient: coefficient * 5n ** BigInt(-power2), scale: -power2 };
|
|
29660
31203
|
}
|
|
29661
|
-
async function floatingSequence(first, increment, last,
|
|
31204
|
+
async function floatingSequence(first, increment, last, format3, separator, session) {
|
|
29662
31205
|
if (![first, increment, last].every(Number.isFinite) || increment === 0) throw new UsageError("formatted operands must fit finite binary64 with a nonzero increment");
|
|
29663
31206
|
if (increment > 0 ? first > last : first < last) return;
|
|
29664
|
-
const render2 = (
|
|
29665
|
-
const decimal4 = binaryDecimal(
|
|
29666
|
-
const text3 = formatted2(decimal4.coefficient, decimal4.scale,
|
|
31207
|
+
const render2 = (number6) => {
|
|
31208
|
+
const decimal4 = binaryDecimal(number6);
|
|
31209
|
+
const text3 = formatted2(decimal4.coefficient, decimal4.scale, format3, Object.is(number6, -0));
|
|
29667
31210
|
session.check(import_buffer.Buffer.byteLength(text3), session.limits.maxRecordBytes, "record");
|
|
29668
31211
|
return text3;
|
|
29669
31212
|
};
|
|
@@ -29679,7 +31222,7 @@ async function floatingSequence(first, increment, last, format2, separator, sess
|
|
|
29679
31222
|
const outside = increment > 0 ? current > last : current < last;
|
|
29680
31223
|
const text3 = render2(current);
|
|
29681
31224
|
if (outside) {
|
|
29682
|
-
const numeric4 = text3.slice(
|
|
31225
|
+
const numeric4 = text3.slice(format3.prefix.length, text3.length - format3.suffix.length);
|
|
29683
31226
|
if (Number(numeric4) !== last || text3 === previous) break;
|
|
29684
31227
|
}
|
|
29685
31228
|
await session.text((index ? separator : "") + text3);
|
|
@@ -29766,9 +31309,9 @@ function createSeqCommand(limits) {
|
|
|
29766
31309
|
let current = align(first);
|
|
29767
31310
|
const step = align(increment), finish = align(last);
|
|
29768
31311
|
const precision = Math.max(first.precision, increment.precision);
|
|
29769
|
-
const
|
|
29770
|
-
if (
|
|
29771
|
-
await floatingSequence(Number(operands.length === 1 ? "1" : operands[0]), Number(operands.length === 3 ? operands[1] : "1"), Number(operands.at(-1)),
|
|
31312
|
+
const format3 = formatText === void 0 ? void 0 : parseFormat(formatText, session);
|
|
31313
|
+
if (format3) {
|
|
31314
|
+
await floatingSequence(Number(operands.length === 1 ? "1" : operands[0]), Number(operands.length === 3 ? operands[1] : "1"), Number(operands.at(-1)), format3, separator, session);
|
|
29772
31315
|
return;
|
|
29773
31316
|
}
|
|
29774
31317
|
const firstText = (first.negativeZero ? "-" : "") + fixed2(current, scale, precision);
|
|
@@ -29806,9 +31349,9 @@ function style(text3) {
|
|
|
29806
31349
|
}
|
|
29807
31350
|
function signed(text3) {
|
|
29808
31351
|
if (!/^[+-]?\d+$/u.test(text3.trim())) throw new UsageError(`invalid line number: '${text3}'`);
|
|
29809
|
-
const
|
|
29810
|
-
if (
|
|
29811
|
-
return
|
|
31352
|
+
const number6 = BigInt(text3);
|
|
31353
|
+
if (number6 < -(1n << 63n) || number6 >= 1n << 63n) throw new UsageError(`line number out of range: '${text3}'`);
|
|
31354
|
+
return number6;
|
|
29812
31355
|
}
|
|
29813
31356
|
function createNlCommand(limits) {
|
|
29814
31357
|
return command5("nl", limits, async (session) => {
|
|
@@ -29828,8 +31371,8 @@ function createNlCommand(limits) {
|
|
|
29828
31371
|
const header3 = style(value(parsed, "h") ?? "n"), body = style(value(parsed, "b") ?? "t"), footer = style(value(parsed, "f") ?? "n");
|
|
29829
31372
|
const start = signed(value(parsed, "v") ?? "1"), increment = signed(value(parsed, "i") ?? "1");
|
|
29830
31373
|
const join = Math.max(1, integer(value(parsed, "l") ?? "1")), width = integer(value(parsed, "w") ?? "6", 1);
|
|
29831
|
-
const separator = value(parsed, "s") ?? " ",
|
|
29832
|
-
if (!["ln", "rn", "rz"].includes(
|
|
31374
|
+
const separator = value(parsed, "s") ?? " ", format3 = value(parsed, "n") ?? "rn";
|
|
31375
|
+
if (!["ln", "rn", "rz"].includes(format3)) throw new UsageError(`invalid line numbering format: '${format3}'`);
|
|
29833
31376
|
session.check(width + import_buffer.Buffer.byteLength(separator), limits.maxRecordBytes, "number field");
|
|
29834
31377
|
let delimiter = import_buffer.Buffer.from("\\:");
|
|
29835
31378
|
for (const argument2 of parsed.values.get("d") ?? []) {
|
|
@@ -29839,14 +31382,14 @@ function createNlCommand(limits) {
|
|
|
29839
31382
|
const delimiters2 = [1, 2, 3].map((count2) => import_buffer.Buffer.concat(Array.from({ length: count2 }, () => delimiter)));
|
|
29840
31383
|
const budget = new PatternBudget(session);
|
|
29841
31384
|
const unnumbered = " ".repeat(width + import_buffer.Buffer.byteLength(separator));
|
|
29842
|
-
let current = body,
|
|
31385
|
+
let current = body, number6 = start, blanks = 0;
|
|
29843
31386
|
await session.files(session.names(parsed.operands), async (source2) => {
|
|
29844
31387
|
for await (const record4 of records2(source2, session)) {
|
|
29845
31388
|
const bytes3 = import_buffer.Buffer.from(record4);
|
|
29846
31389
|
const section = delimiter.length ? delimiters2.findIndex((candidate) => candidate.equals(bytes3)) : -1;
|
|
29847
31390
|
if (section >= 0) {
|
|
29848
31391
|
current = section === 0 ? footer : section === 1 ? body : header3;
|
|
29849
|
-
if (!parsed.flags.has("p"))
|
|
31392
|
+
if (!parsed.flags.has("p")) number6 = start;
|
|
29850
31393
|
await session.text("\n");
|
|
29851
31394
|
continue;
|
|
29852
31395
|
}
|
|
@@ -29858,13 +31401,13 @@ function createNlCommand(limits) {
|
|
|
29858
31401
|
else if (current === "n") numbered = false;
|
|
29859
31402
|
else numbered = await current.find(bytes3.toString("latin1"), budget) !== void 0;
|
|
29860
31403
|
if (numbered) {
|
|
29861
|
-
if (
|
|
29862
|
-
let label =
|
|
29863
|
-
if (
|
|
29864
|
-
else if (
|
|
29865
|
-
else label = label.padStart(width,
|
|
31404
|
+
if (number6 < -(1n << 63n) || number6 >= 1n << 63n) throw new UsageError("line number overflow");
|
|
31405
|
+
let label = number6.toString();
|
|
31406
|
+
if (format3 === "ln") label = label.padEnd(width, " ");
|
|
31407
|
+
else if (format3 === "rz" && number6 < 0n) label = "-" + label.slice(1).padStart(width - 1, "0");
|
|
31408
|
+
else label = label.padStart(width, format3 === "rz" ? "0" : " ");
|
|
29866
31409
|
await session.text(label + separator);
|
|
29867
|
-
|
|
31410
|
+
number6 += increment;
|
|
29868
31411
|
} else await session.text(unnumbered);
|
|
29869
31412
|
await session.output(record4);
|
|
29870
31413
|
await session.text("\n");
|
|
@@ -29941,13 +31484,13 @@ function tabStops(specifications, session) {
|
|
|
29941
31484
|
for (const entry of specification.split(/[, \t]+/u).filter(Boolean)) {
|
|
29942
31485
|
if (repeat) throw new UsageError("repeating tab stop must be last");
|
|
29943
31486
|
const marker = entry[0] === "+" || entry[0] === "/" ? entry[0] : "";
|
|
29944
|
-
const
|
|
31487
|
+
const number6 = integer(entry.slice(marker.length), 1);
|
|
29945
31488
|
if (marker) {
|
|
29946
|
-
repeat =
|
|
31489
|
+
repeat = number6;
|
|
29947
31490
|
relative = marker === "+";
|
|
29948
31491
|
} else {
|
|
29949
|
-
if (
|
|
29950
|
-
stops.push(
|
|
31492
|
+
if (number6 <= (stops.at(-1) ?? 0)) throw new UsageError("tab stops must be ascending");
|
|
31493
|
+
stops.push(number6);
|
|
29951
31494
|
}
|
|
29952
31495
|
}
|
|
29953
31496
|
}
|
|
@@ -30080,7 +31623,7 @@ function settings6(options3) {
|
|
|
30080
31623
|
}
|
|
30081
31624
|
return limits;
|
|
30082
31625
|
}
|
|
30083
|
-
function
|
|
31626
|
+
function number5(text3, label, units = false, zero2 = false) {
|
|
30084
31627
|
const match = /^[\t\n\v\f\r ]*\+?([0-9]*)([a-zA-Z]*)$/u.exec(text3);
|
|
30085
31628
|
if (!match || !match[1] && (!units || !match[2] || text3 !== match[2])) throw new PublicDiagnostic(`invalid ${label}: '${text3}'`);
|
|
30086
31629
|
const suffix2 = match[2];
|
|
@@ -30099,7 +31642,7 @@ function number4(text3, label, units = false, zero2 = false) {
|
|
|
30099
31642
|
if (!Number.isSafeInteger(value2) || value2 < (zero2 ? 0 : 1)) throw new PublicDiagnostic(`invalid ${label}: '${text3}'`);
|
|
30100
31643
|
return value2;
|
|
30101
31644
|
}
|
|
30102
|
-
function
|
|
31645
|
+
function parseArguments2(args, limits) {
|
|
30103
31646
|
if (args.reduce((total, argument2) => total + import_buffer.Buffer.byteLength(argument2), 0) > limits.maxArgumentBytes) {
|
|
30104
31647
|
throw new PublicDiagnostic("split argument limit exceeded");
|
|
30105
31648
|
}
|
|
@@ -30118,14 +31661,14 @@ function parseArguments(args, limits) {
|
|
|
30118
31661
|
if (!/^[0-9]*$/u.test(value2)) throw new PublicDiagnostic(`invalid start value for numerical suffix: '${value2}'`);
|
|
30119
31662
|
numericStart = value2.replace(/^0+(?=\d)/u, "") || "0";
|
|
30120
31663
|
}
|
|
30121
|
-
} else if (option === "a") suffixLength =
|
|
31664
|
+
} else if (option === "a") suffixLength = number5(value2, "suffix length", false, true);
|
|
30122
31665
|
else if (option === "additional-suffix") {
|
|
30123
31666
|
if (value2.includes("/") || value2.includes("\0")) throw new PublicDiagnostic("invalid additional suffix: contains directory separator or NUL");
|
|
30124
31667
|
additionalSuffix = value2;
|
|
30125
31668
|
} else {
|
|
30126
31669
|
if (mode) throw new PublicDiagnostic("cannot split in more than one way");
|
|
30127
31670
|
mode = option === "l" ? "lines" : option === "b" ? "bytes" : "line-bytes";
|
|
30128
|
-
size =
|
|
31671
|
+
size = number5(value2, option === "l" ? "number of lines" : "number of bytes", option !== "l");
|
|
30129
31672
|
}
|
|
30130
31673
|
};
|
|
30131
31674
|
const long = {
|
|
@@ -30472,7 +32015,7 @@ var LineBytes = class {
|
|
|
30472
32015
|
}
|
|
30473
32016
|
};
|
|
30474
32017
|
async function run3(context2, limits) {
|
|
30475
|
-
const args =
|
|
32018
|
+
const args = parseArguments2(context2.args, limits);
|
|
30476
32019
|
const controller = new AbortController();
|
|
30477
32020
|
const signal = AbortSignal.any([context2.signal, controller.signal]);
|
|
30478
32021
|
const budget = new Budget18(limits, signal);
|
|
@@ -30725,22 +32268,22 @@ function millisecondsInstant(value2) {
|
|
|
30725
32268
|
return boundedInstant(scale >= 0 ? coefficient * 10n ** BigInt(scale) : floorDivide(coefficient, 10n ** BigInt(-scale)));
|
|
30726
32269
|
}
|
|
30727
32270
|
function utcMilliseconds(fields3) {
|
|
30728
|
-
const
|
|
30729
|
-
|
|
30730
|
-
|
|
30731
|
-
const value2 =
|
|
32271
|
+
const date2 = /* @__PURE__ */ new Date(0);
|
|
32272
|
+
date2.setUTCFullYear(fields3.year, fields3.month - 1, fields3.day);
|
|
32273
|
+
date2.setUTCHours(fields3.hour, fields3.minute, fields3.second, 0);
|
|
32274
|
+
const value2 = date2.getTime();
|
|
30732
32275
|
if (!Number.isFinite(value2)) throw new CommandFailure("date is outside the supported range");
|
|
30733
32276
|
return value2;
|
|
30734
32277
|
}
|
|
30735
32278
|
function utcFields(milliseconds) {
|
|
30736
|
-
const
|
|
32279
|
+
const date2 = new Date(milliseconds);
|
|
30737
32280
|
return {
|
|
30738
|
-
year:
|
|
30739
|
-
month:
|
|
30740
|
-
day:
|
|
30741
|
-
hour:
|
|
30742
|
-
minute:
|
|
30743
|
-
second:
|
|
32281
|
+
year: date2.getUTCFullYear(),
|
|
32282
|
+
month: date2.getUTCMonth() + 1,
|
|
32283
|
+
day: date2.getUTCDate(),
|
|
32284
|
+
hour: date2.getUTCHours(),
|
|
32285
|
+
minute: date2.getUTCMinutes(),
|
|
32286
|
+
second: date2.getUTCSeconds()
|
|
30744
32287
|
};
|
|
30745
32288
|
}
|
|
30746
32289
|
function sameFields(left, right) {
|
|
@@ -30905,7 +32448,7 @@ function offsetText(offset, colons) {
|
|
|
30905
32448
|
if (colons === 1 || minutes !== "00") return { value: `${sign}${hours}:${minutes}`, width: 6 };
|
|
30906
32449
|
return { value: `${sign}${hours}`, width: 3 };
|
|
30907
32450
|
}
|
|
30908
|
-
function formatDate(
|
|
32451
|
+
function formatDate(format3, instant, zone, limits) {
|
|
30909
32452
|
const fields3 = zone.fields(instant);
|
|
30910
32453
|
const midnight = utcMilliseconds({ ...fields3, hour: 0, minute: 0, second: 0 });
|
|
30911
32454
|
const weekday = new Date(midnight).getUTCDay();
|
|
@@ -30914,8 +32457,8 @@ function formatDate(format2, instant, zone, limits) {
|
|
|
30914
32457
|
const isoYear = thursday.getUTCFullYear();
|
|
30915
32458
|
const isoWeek = 1 + Math.floor((thursday.getTime() - utcMilliseconds({ year: isoYear, month: 1, day: 1, hour: 0, minute: 0, second: 0 })) / 6048e5);
|
|
30916
32459
|
const nano = (instant - floorDivide(instant, nanosecondsPerSecond) * nanosecondsPerSecond).toString().padStart(9, "0");
|
|
30917
|
-
const
|
|
30918
|
-
const time = `${
|
|
32460
|
+
const number6 = (value2, width = 2, padding = "0") => value2.toString().padStart(width, padding);
|
|
32461
|
+
const time = `${number6(fields3.hour)}:${number6(fields3.minute)}:${number6(fields3.second)}`;
|
|
30919
32462
|
const hour12 = fields3.hour % 12 || 12;
|
|
30920
32463
|
const meridian = fields3.hour < 12 ? "AM" : "PM";
|
|
30921
32464
|
const pieces = [];
|
|
@@ -30925,32 +32468,32 @@ function formatDate(format2, instant, zone, limits) {
|
|
|
30925
32468
|
checkSize(size + 1, limits.maxOutputBytes, "output");
|
|
30926
32469
|
pieces.push(value2);
|
|
30927
32470
|
};
|
|
30928
|
-
for (let offset = 0; offset <
|
|
30929
|
-
const next =
|
|
32471
|
+
for (let offset = 0; offset < format3.length; ) {
|
|
32472
|
+
const next = format3.indexOf("%", offset);
|
|
30930
32473
|
if (next < 0) {
|
|
30931
|
-
append(
|
|
32474
|
+
append(format3.slice(offset));
|
|
30932
32475
|
break;
|
|
30933
32476
|
}
|
|
30934
|
-
append(
|
|
32477
|
+
append(format3.slice(offset, next));
|
|
30935
32478
|
offset = next + 1;
|
|
30936
32479
|
let padding, upper = false, swap = false;
|
|
30937
|
-
while (offset <
|
|
30938
|
-
const flag =
|
|
32480
|
+
while (offset < format3.length && "-_0^#".includes(format3[offset])) {
|
|
32481
|
+
const flag = format3[offset++];
|
|
30939
32482
|
if (flag === "^") upper = true;
|
|
30940
32483
|
else if (flag === "#") swap = true;
|
|
30941
32484
|
else padding = flag === "-" ? "" : flag === "_" ? " " : "0";
|
|
30942
32485
|
}
|
|
30943
32486
|
let widthText = "";
|
|
30944
|
-
while (offset <
|
|
32487
|
+
while (offset < format3.length && /[0-9]/.test(format3[offset])) widthText += format3[offset++];
|
|
30945
32488
|
const width = widthText ? Number(widthText) : void 0;
|
|
30946
32489
|
if (width !== void 0) checkSize(width, limits.maxFormatWidth, "format width");
|
|
30947
32490
|
let colons = 0;
|
|
30948
|
-
while (
|
|
32491
|
+
while (format3[offset] === ":") {
|
|
30949
32492
|
colons++;
|
|
30950
32493
|
offset++;
|
|
30951
32494
|
}
|
|
30952
|
-
const modifier =
|
|
30953
|
-
const code =
|
|
32495
|
+
const modifier = format3[offset] === "E" || format3[offset] === "O" ? format3[offset++] : void 0;
|
|
32496
|
+
const code = format3[offset++];
|
|
30954
32497
|
if (!code || colons > 3 || colons && code !== "z") throw new CommandFailure("unsupported date format directive");
|
|
30955
32498
|
if (code === "%" && (padding !== void 0 || upper || swap || width !== void 0 || modifier)) {
|
|
30956
32499
|
throw new CommandFailure("only an unmodified %% literal is supported");
|
|
@@ -30975,7 +32518,7 @@ function formatDate(format2, instant, zone, limits) {
|
|
|
30975
32518
|
value2 = monthNames[fields3.month - 1];
|
|
30976
32519
|
break;
|
|
30977
32520
|
case "c":
|
|
30978
|
-
value2 = `${weekdayNames[weekday].slice(0, 3)} ${monthNames[fields3.month - 1].slice(0, 3)} ${
|
|
32521
|
+
value2 = `${weekdayNames[weekday].slice(0, 3)} ${monthNames[fields3.month - 1].slice(0, 3)} ${number6(fields3.day, 2, " ")} ${time} ${number6(fields3.year, 4)}`;
|
|
30979
32522
|
break;
|
|
30980
32523
|
case "C":
|
|
30981
32524
|
value2 = String(Math.floor(fields3.year / 100));
|
|
@@ -30988,15 +32531,15 @@ function formatDate(format2, instant, zone, limits) {
|
|
|
30988
32531
|
if (code === "e") defaultPadding = " ";
|
|
30989
32532
|
break;
|
|
30990
32533
|
case "D":
|
|
30991
|
-
value2 = `${
|
|
32534
|
+
value2 = `${number6(fields3.month)}/${number6(fields3.day)}/${number6(fields3.year % 100, 2, padding ?? "0")}`;
|
|
30992
32535
|
break;
|
|
30993
32536
|
case "x":
|
|
30994
|
-
value2 = `${
|
|
32537
|
+
value2 = `${number6(fields3.month)}/${number6(fields3.day)}/${number6(fields3.year % 100)}`;
|
|
30995
32538
|
break;
|
|
30996
32539
|
case "F": {
|
|
30997
32540
|
const yearWidth = width === void 0 && padding === void 0 ? 4 : Math.max(0, (width ?? 0) - 6);
|
|
30998
|
-
const year = padding === "" ? String(fields3.year) :
|
|
30999
|
-
append(`${year}-${
|
|
32541
|
+
const year = padding === "" ? String(fields3.year) : number6(fields3.year, yearWidth, padding ?? "0");
|
|
32542
|
+
append(`${year}-${number6(fields3.month)}-${number6(fields3.day)}`);
|
|
31000
32543
|
continue;
|
|
31001
32544
|
}
|
|
31002
32545
|
case "g":
|
|
@@ -31053,10 +32596,10 @@ function formatDate(format2, instant, zone, limits) {
|
|
|
31053
32596
|
defaultWidth = 1;
|
|
31054
32597
|
break;
|
|
31055
32598
|
case "r":
|
|
31056
|
-
value2 = `${
|
|
32599
|
+
value2 = `${number6(hour12)}:${number6(fields3.minute)}:${number6(fields3.second)} ${meridian}`;
|
|
31057
32600
|
break;
|
|
31058
32601
|
case "R":
|
|
31059
|
-
value2 = `${
|
|
32602
|
+
value2 = `${number6(fields3.hour)}:${number6(fields3.minute)}`;
|
|
31060
32603
|
break;
|
|
31061
32604
|
case "s":
|
|
31062
32605
|
value2 = floorDivide(instant, nanosecondsPerSecond).toString();
|
|
@@ -31124,8 +32667,8 @@ function formatDate(format2, instant, zone, limits) {
|
|
|
31124
32667
|
}
|
|
31125
32668
|
|
|
31126
32669
|
// packages/safe-bash/src/commands/time-env/date.ts
|
|
31127
|
-
function
|
|
31128
|
-
let input3, reference,
|
|
32670
|
+
function parseArguments3(args) {
|
|
32671
|
+
let input3, reference, format3, style2;
|
|
31129
32672
|
let utc = false, ended = false;
|
|
31130
32673
|
const formatted3 = (value2) => {
|
|
31131
32674
|
if (style2 !== void 0) throw new CommandFailure("multiple output formats specified");
|
|
@@ -31217,15 +32760,15 @@ function parseArguments2(args) {
|
|
|
31217
32760
|
}
|
|
31218
32761
|
} else {
|
|
31219
32762
|
if (!argument2.startsWith("+")) throw new CommandFailure("expected +FORMAT; clock-setting operands are unsupported");
|
|
31220
|
-
if (
|
|
31221
|
-
|
|
32763
|
+
if (format3 !== void 0) throw new CommandFailure("extra format operand");
|
|
32764
|
+
format3 = argument2.slice(1);
|
|
31222
32765
|
}
|
|
31223
32766
|
}
|
|
31224
32767
|
if (input3 !== void 0 && reference !== void 0) throw new CommandFailure("--date and --reference are mutually exclusive");
|
|
31225
|
-
if (
|
|
32768
|
+
if (format3 !== void 0 && style2 !== void 0) throw new CommandFailure("multiple output formats specified");
|
|
31226
32769
|
return {
|
|
31227
32770
|
utc,
|
|
31228
|
-
format:
|
|
32771
|
+
format: format3 ?? style2 ?? "%a %b %e %T %Z %Y",
|
|
31229
32772
|
...input3 === void 0 ? {} : { input: input3 },
|
|
31230
32773
|
...reference === void 0 ? {} : { reference }
|
|
31231
32774
|
};
|
|
@@ -31233,7 +32776,7 @@ function parseArguments2(args) {
|
|
|
31233
32776
|
function createDateCommand(configuration) {
|
|
31234
32777
|
new TimeZone(configuration.defaultTimeZone);
|
|
31235
32778
|
return command6("date", configuration, async (context2) => {
|
|
31236
|
-
const parsed =
|
|
32779
|
+
const parsed = parseArguments3(context2.args);
|
|
31237
32780
|
if (parsed.informational) {
|
|
31238
32781
|
await emit(context2, parsed.informational === "version" ? "date (safe-bash virtual command)\n" : "Usage: date [-u] [-d DATE | -r FILE] [+FORMAT]\nAlso: -I[date|hours|minutes|seconds|ns], -R, --rfc-3339=PRECISION\nDATE accepts @seconds, ISO calendar/time, RFC dates, now/today/yesterday/tomorrow, and integer seconds/minutes/hours relative to now.\nVirtual TZ defaults to UTC; no clock setting or host-locale parsing.\n", configuration.limits);
|
|
31239
32782
|
return 0;
|
|
@@ -31614,7 +33157,7 @@ function environmentCharset(budget) {
|
|
|
31614
33157
|
}
|
|
31615
33158
|
|
|
31616
33159
|
// packages/safe-bash/src/commands/tree/arguments.ts
|
|
31617
|
-
function
|
|
33160
|
+
function parse14(args, budget) {
|
|
31618
33161
|
budget.check(args.length, budget.limits.maxArguments, "argument count");
|
|
31619
33162
|
let bytes3 = 0;
|
|
31620
33163
|
for (const arg of args) {
|
|
@@ -31983,7 +33526,7 @@ function createTreeCommand(options3 = {}) {
|
|
|
31983
33526
|
const budget = new WalkBudget(context2, limits);
|
|
31984
33527
|
let args;
|
|
31985
33528
|
try {
|
|
31986
|
-
args =
|
|
33529
|
+
args = parse14(context2.args, budget);
|
|
31987
33530
|
} catch (error) {
|
|
31988
33531
|
context2.signal.throwIfAborted();
|
|
31989
33532
|
if (!(error instanceof UsageError2)) throw error;
|
|
@@ -32289,7 +33832,7 @@ function limitMessage(error) {
|
|
|
32289
33832
|
// packages/safe-bash/src/commands/file/index.ts
|
|
32290
33833
|
var profile = "virtual-bash-file-v1";
|
|
32291
33834
|
var help2 = "Usage: file [-bihL] [--mime-type] [--mime-encoding] [--] FILE...\nClassify bounded VFS content; '-' reads stdin. -h is the default.\nOptions: --brief, --mime, --dereference, --no-dereference, --help, --version\nNo decompression, external magic database, or complete format validation.\n";
|
|
32292
|
-
async function
|
|
33835
|
+
async function parse15(args, budget) {
|
|
32293
33836
|
const result2 = { brief: false, follow: false, mimeType: false, mimeEncoding: false, names: [] };
|
|
32294
33837
|
let argumentBytes = 0;
|
|
32295
33838
|
budget.check(args.length, budget.limits.maxArgumentBytes, "argument");
|
|
@@ -32437,7 +33980,7 @@ function createFileCommand(options3 = {}) {
|
|
|
32437
33980
|
const budget = new SharedBudget(context2, limits);
|
|
32438
33981
|
let writing = false;
|
|
32439
33982
|
try {
|
|
32440
|
-
const args = await
|
|
33983
|
+
const args = await parse15(context2.args, budget);
|
|
32441
33984
|
if (args.action) {
|
|
32442
33985
|
writing = true;
|
|
32443
33986
|
await budget.output(context2.stdout, args.action === "help" ? help2 : `file (${profile})
|
|
@@ -32665,7 +34208,7 @@ function readerSettings(limits) {
|
|
|
32665
34208
|
function usage(message3) {
|
|
32666
34209
|
throw new FsError("EINVAL", { message: message3 });
|
|
32667
34210
|
}
|
|
32668
|
-
function
|
|
34211
|
+
function parse16(args, limits) {
|
|
32669
34212
|
if (args.length > limits.maxArgumentBytes) usage("argument count limit exceeded");
|
|
32670
34213
|
let argumentBytes = 0;
|
|
32671
34214
|
for (const token of args) {
|
|
@@ -33057,7 +34600,7 @@ function createColumnCommand(options3 = {}) {
|
|
|
33057
34600
|
let rejection;
|
|
33058
34601
|
try {
|
|
33059
34602
|
try {
|
|
33060
|
-
const parsed =
|
|
34603
|
+
const parsed = parse16(context2.args, limits);
|
|
33061
34604
|
inputs2 = new ColumnInputs(context2, limits);
|
|
33062
34605
|
const budget = inputs2.budget;
|
|
33063
34606
|
if (parsed.help) await budget.text(helpText3);
|
|
@@ -33872,7 +35415,7 @@ This documented HTML subset is a converter, not a sanitizer or browser HTML5 par
|
|
|
33872
35415
|
|
|
33873
35416
|
// packages/safe-bash/src/commands/html-to-markdown/render.ts
|
|
33874
35417
|
init_platform();
|
|
33875
|
-
var
|
|
35418
|
+
var format2 = (tag) => tag === "em" || tag === "i" ? "em" : tag === "strong" || tag === "b" ? "strong" : tag === "del" || tag === "s" ? "del" : void 0;
|
|
33876
35419
|
var inlineAtoms = /* @__PURE__ */ new Set(["a", "img", "code", "br"]);
|
|
33877
35420
|
var Renderer = class {
|
|
33878
35421
|
constructor(budget) {
|
|
@@ -33951,9 +35494,9 @@ var Renderer = class {
|
|
|
33951
35494
|
const append = async (child, target = result2) => {
|
|
33952
35495
|
this.budget.work(1);
|
|
33953
35496
|
await this.budget.checkpoint();
|
|
33954
|
-
const style2 =
|
|
35497
|
+
const style2 = format2(child.tag);
|
|
33955
35498
|
const previous = target.at(-1);
|
|
33956
|
-
if (style2 && previous &&
|
|
35499
|
+
if (style2 && previous && format2(previous.tag) === style2) {
|
|
33957
35500
|
for (const nested of child.children) await append(nested, previous.children);
|
|
33958
35501
|
} else target.push(child);
|
|
33959
35502
|
};
|
|
@@ -33979,9 +35522,9 @@ var Renderer = class {
|
|
|
33979
35522
|
this.budget.work(1);
|
|
33980
35523
|
this.destinations.set(child, url);
|
|
33981
35524
|
}
|
|
33982
|
-
const style2 =
|
|
35525
|
+
const style2 = format2(child.tag);
|
|
33983
35526
|
if (child.tag !== "text" && !blockTags.has(child.tag) && !inlineAtoms.has(child.tag)) {
|
|
33984
|
-
if (!style2 || style2 ===
|
|
35527
|
+
if (!style2 || style2 === format2(node.tag)) {
|
|
33985
35528
|
for (const nested of child.children) await visit(nested);
|
|
33986
35529
|
return;
|
|
33987
35530
|
}
|
|
@@ -34003,7 +35546,7 @@ var Renderer = class {
|
|
|
34003
35546
|
return result2;
|
|
34004
35547
|
}
|
|
34005
35548
|
async punctuationBoundary(node, ending) {
|
|
34006
|
-
if (!node || !
|
|
35549
|
+
if (!node || !format2(node.tag)) return false;
|
|
34007
35550
|
const edge = async (parent) => {
|
|
34008
35551
|
for (let step = 0; step < parent.children.length; step++) {
|
|
34009
35552
|
this.budget.work(1);
|
|
@@ -34012,7 +35555,7 @@ var Renderer = class {
|
|
|
34012
35555
|
if (child.tag === "text") {
|
|
34013
35556
|
if (child.text) return ending ? Array.from(child.text.slice(-2)).at(-1) : String.fromCodePoint(child.text.codePointAt(0));
|
|
34014
35557
|
} else if (child.tag === "br" || blockTags.has(child.tag)) return " ";
|
|
34015
|
-
else if (
|
|
35558
|
+
else if (format2(child.tag) || inlineAtoms.has(child.tag)) return "*";
|
|
34016
35559
|
else {
|
|
34017
35560
|
const nested = await edge(child);
|
|
34018
35561
|
if (nested !== void 0) return nested;
|
|
@@ -34050,8 +35593,8 @@ var Renderer = class {
|
|
|
34050
35593
|
async children(node, maximum = this.budget.limits.maxOutputBytes - this.budget.output) {
|
|
34051
35594
|
const result2 = new Builder(this.budget, maximum);
|
|
34052
35595
|
const children = await this.inlineChildren(node);
|
|
34053
|
-
const alternate = (index) =>
|
|
34054
|
-
const separate = async (index, ending) =>
|
|
35596
|
+
const alternate = (index) => format2(node.tag) === "em" || format2(children[index - 1]?.tag ?? "") === "em" || format2(children[index + 1]?.tag ?? "") === "em";
|
|
35597
|
+
const separate = async (index, ending) => format2(children[index]?.tag ?? "") === "strong" && alternate(index) || await this.punctuationBoundary(children[index], ending);
|
|
34055
35598
|
for (let index = 0; index < children.length; index++) {
|
|
34056
35599
|
const child = children[index];
|
|
34057
35600
|
this.budget.work(1);
|
|
@@ -34361,10 +35904,10 @@ function blockSize2(value2) {
|
|
|
34361
35904
|
function ceiling(value2, divisor) {
|
|
34362
35905
|
return (value2 + divisor - 1n) / divisor;
|
|
34363
35906
|
}
|
|
34364
|
-
function formatSize(value2,
|
|
35907
|
+
function formatSize(value2, format3) {
|
|
34365
35908
|
const bytes3 = BigInt(value2);
|
|
34366
|
-
if (!
|
|
34367
|
-
const base = BigInt(
|
|
35909
|
+
if (!format3.human) return `${ceiling(bytes3, format3.unit)}${format3.suffix}`;
|
|
35910
|
+
const base = BigInt(format3.human);
|
|
34368
35911
|
let unit2 = 1n;
|
|
34369
35912
|
let exponent = 0;
|
|
34370
35913
|
while (bytes3 >= unit2 * base) {
|
|
@@ -34377,13 +35920,13 @@ function formatSize(value2, format2) {
|
|
|
34377
35920
|
exponent++;
|
|
34378
35921
|
}
|
|
34379
35922
|
const tenths = ceiling(bytes3 * 10n, unit2);
|
|
34380
|
-
const
|
|
34381
|
-
const suffix2 = (
|
|
34382
|
-
return
|
|
35923
|
+
const number6 = tenths < 100n ? `${tenths / 10n}.${tenths % 10n}` : String(ceiling(bytes3, unit2));
|
|
35924
|
+
const suffix2 = (format3.human === 1e3 ? "kMGTPEZYRQ" : "KMGTPEZYRQ")[exponent - 1];
|
|
35925
|
+
return number6 + suffix2;
|
|
34383
35926
|
}
|
|
34384
35927
|
|
|
34385
35928
|
// packages/safe-bash/src/commands/du/arguments.ts
|
|
34386
|
-
function
|
|
35929
|
+
function parse17(budget) {
|
|
34387
35930
|
const { args, env } = budget.context;
|
|
34388
35931
|
budget.check(args.length, budget.limits.maxArguments, "argument count");
|
|
34389
35932
|
let bytes3 = 0;
|
|
@@ -34397,11 +35940,11 @@ function parse16(budget) {
|
|
|
34397
35940
|
const operands = [];
|
|
34398
35941
|
let all = false, summarize = false, total = false, apparent = false, countLinks = false, nullOutput = false, help5 = false;
|
|
34399
35942
|
let depth;
|
|
34400
|
-
let
|
|
35943
|
+
let format3;
|
|
34401
35944
|
let options3 = true;
|
|
34402
35945
|
const valueOption = (flag, value2) => {
|
|
34403
35946
|
if (flag === "B" || flag === "block-size") {
|
|
34404
|
-
|
|
35947
|
+
format3 = blockSize2(value2);
|
|
34405
35948
|
return;
|
|
34406
35949
|
}
|
|
34407
35950
|
if (!/^\d+$/u.test(value2) || !Number.isSafeInteger(Number(value2))) throw new UsageError3(`invalid maximum depth '${value2}'`);
|
|
@@ -34423,18 +35966,18 @@ function parse16(budget) {
|
|
|
34423
35966
|
break;
|
|
34424
35967
|
case "h":
|
|
34425
35968
|
case "human-readable":
|
|
34426
|
-
|
|
35969
|
+
format3 = blockSize2("human-readable");
|
|
34427
35970
|
break;
|
|
34428
35971
|
case "k":
|
|
34429
|
-
|
|
35972
|
+
format3 = blockSize2("1024");
|
|
34430
35973
|
break;
|
|
34431
35974
|
case "m":
|
|
34432
|
-
|
|
35975
|
+
format3 = blockSize2("1048576");
|
|
34433
35976
|
break;
|
|
34434
35977
|
case "b":
|
|
34435
35978
|
case "bytes":
|
|
34436
35979
|
apparent = true;
|
|
34437
|
-
|
|
35980
|
+
format3 = blockSize2("1");
|
|
34438
35981
|
break;
|
|
34439
35982
|
case "apparent-size":
|
|
34440
35983
|
apparent = true;
|
|
@@ -34490,7 +36033,7 @@ function parse16(budget) {
|
|
|
34490
36033
|
}
|
|
34491
36034
|
if (all && summarize) throw new UsageError3("cannot combine --all and --summarize");
|
|
34492
36035
|
if (summarize && depth !== void 0 && depth !== 0) throw new UsageError3("--summarize conflicts with --max-depth");
|
|
34493
|
-
if (!
|
|
36036
|
+
if (!format3) {
|
|
34494
36037
|
let selected;
|
|
34495
36038
|
for (const name2 of ["DU_BLOCK_SIZE", "BLOCK_SIZE", "BLOCKSIZE"]) {
|
|
34496
36039
|
if (Object.hasOwn(env, name2)) {
|
|
@@ -34503,16 +36046,16 @@ function parse16(budget) {
|
|
|
34503
36046
|
budget.check(import_buffer.Buffer.byteLength(selected), budget.limits.maxArgumentBytes - bytes3, "environment bytes");
|
|
34504
36047
|
budget.step(selected.length + 1);
|
|
34505
36048
|
try {
|
|
34506
|
-
|
|
36049
|
+
format3 = blockSize2(selected);
|
|
34507
36050
|
} catch (error) {
|
|
34508
36051
|
if (!(error instanceof UsageError3)) throw error;
|
|
34509
|
-
|
|
36052
|
+
format3 = blockSize2(Object.hasOwn(env, "POSIXLY_CORRECT") ? "512" : "1024");
|
|
34510
36053
|
}
|
|
34511
|
-
} else
|
|
36054
|
+
} else format3 = blockSize2(Object.hasOwn(env, "POSIXLY_CORRECT") ? "512" : "1024");
|
|
34512
36055
|
}
|
|
34513
36056
|
if (operands.length === 0) operands.push(".");
|
|
34514
36057
|
for (const operand of operands) budget.text(operand);
|
|
34515
|
-
return { operands, all, summarize, total, apparent, countLinks, nullOutput, depth: summarize ? 0 : depth ?? Number.MAX_SAFE_INTEGER, format:
|
|
36058
|
+
return { operands, all, summarize, total, apparent, countLinks, nullOutput, depth: summarize ? 0 : depth ?? Number.MAX_SAFE_INTEGER, format: format3, help: help5 };
|
|
34516
36059
|
}
|
|
34517
36060
|
var helpText5 = `Usage: du [OPTION]... [--] [FILE]...
|
|
34518
36061
|
Report provider allocation; unknown allocation is an error, never logical size.
|
|
@@ -34837,7 +36380,7 @@ function createDuCommand(options3 = {}) {
|
|
|
34837
36380
|
const budget = new Budget21(work, limits, context2);
|
|
34838
36381
|
context2.registerCleanup?.(budget.close);
|
|
34839
36382
|
try {
|
|
34840
|
-
const args =
|
|
36383
|
+
const args = parse17(budget);
|
|
34841
36384
|
if (context2.stdout.ownedOutput) operation2 = createOutputOperation(context2, context2.stdout);
|
|
34842
36385
|
if (args.help) {
|
|
34843
36386
|
await budget.emit(work.stdout, helpText5);
|
|
@@ -35120,9 +36663,9 @@ async function evaluateCall(operator, values, budget, match) {
|
|
|
35120
36663
|
const candidateEnd = nextCharacter(accept, candidate, unicode);
|
|
35121
36664
|
budget.charge(1 + end2 - offset);
|
|
35122
36665
|
if (end2 - offset === candidateEnd - candidate) {
|
|
35123
|
-
let
|
|
35124
|
-
for (let byte = 0; byte < end2 - offset; byte++) if (subject[offset + byte] !== accept[candidate + byte])
|
|
35125
|
-
if (
|
|
36666
|
+
let equal2 = true;
|
|
36667
|
+
for (let byte = 0; byte < end2 - offset; byte++) if (subject[offset + byte] !== accept[candidate + byte]) equal2 = false;
|
|
36668
|
+
if (equal2) return smallInteger(position2, budget);
|
|
35126
36669
|
}
|
|
35127
36670
|
candidate = candidateEnd;
|
|
35128
36671
|
await budget.yield();
|
|
@@ -35369,7 +36912,7 @@ function settings14(options3) {
|
|
|
35369
36912
|
|
|
35370
36913
|
// packages/safe-bash/src/commands/which/which.ts
|
|
35371
36914
|
var USAGE = "usage: which [-as] program ...\n";
|
|
35372
|
-
var
|
|
36915
|
+
var encoder3 = new TextEncoder();
|
|
35373
36916
|
var descriptions = {
|
|
35374
36917
|
EACCES: "permission denied",
|
|
35375
36918
|
EAGAIN: "resource temporarily unavailable",
|
|
@@ -35487,7 +37030,7 @@ ${USAGE}`);
|
|
|
35487
37030
|
}
|
|
35488
37031
|
async write(sink, text3) {
|
|
35489
37032
|
this.check();
|
|
35490
|
-
const bytes3 =
|
|
37033
|
+
const bytes3 = encoder3.encode(text3);
|
|
35491
37034
|
this.check();
|
|
35492
37035
|
try {
|
|
35493
37036
|
await writeBytes(sink, bytes3, this.context.signal);
|
|
@@ -35827,22 +37370,22 @@ function createDeadline(binding, duration2, maximumChunk) {
|
|
|
35827
37370
|
}
|
|
35828
37371
|
|
|
35829
37372
|
// packages/safe-bash/src/commands/timeout/index.ts
|
|
35830
|
-
var
|
|
37373
|
+
var encoder4 = new TextEncoder();
|
|
35831
37374
|
var records3 = Object.freeze({
|
|
35832
|
-
missingDuration:
|
|
35833
|
-
invalidDuration:
|
|
35834
|
-
durationOverflow:
|
|
35835
|
-
missingCommand:
|
|
35836
|
-
invalidOption:
|
|
35837
|
-
preserveStatus:
|
|
35838
|
-
signal:
|
|
35839
|
-
killAfter:
|
|
35840
|
-
foreground:
|
|
35841
|
-
verbose:
|
|
35842
|
-
invokeUnavailable:
|
|
35843
|
-
timerSetupFailed:
|
|
35844
|
-
help:
|
|
35845
|
-
version:
|
|
37375
|
+
missingDuration: encoder4.encode("timeout: missing duration\n"),
|
|
37376
|
+
invalidDuration: encoder4.encode("timeout: invalid duration\n"),
|
|
37377
|
+
durationOverflow: encoder4.encode("timeout: duration exceeds supported range\n"),
|
|
37378
|
+
missingCommand: encoder4.encode("timeout: missing command\n"),
|
|
37379
|
+
invalidOption: encoder4.encode("timeout: invalid option\n"),
|
|
37380
|
+
preserveStatus: encoder4.encode("timeout: option --preserve-status is unsupported\n"),
|
|
37381
|
+
signal: encoder4.encode("timeout: option --signal is unsupported\n"),
|
|
37382
|
+
killAfter: encoder4.encode("timeout: option --kill-after is unsupported\n"),
|
|
37383
|
+
foreground: encoder4.encode("timeout: option --foreground is unsupported\n"),
|
|
37384
|
+
verbose: encoder4.encode("timeout: option --verbose is unsupported\n"),
|
|
37385
|
+
invokeUnavailable: encoder4.encode("timeout: command invocation is unavailable\n"),
|
|
37386
|
+
timerSetupFailed: encoder4.encode("timeout: timer setup failed\n"),
|
|
37387
|
+
help: encoder4.encode("Usage: timeout [OPTION] DURATION COMMAND [ARG]...\nRun a virtual-bash command with a cooperative time limit.\n"),
|
|
37388
|
+
version: encoder4.encode("timeout (virtual-bash cooperative profile)\n")
|
|
35846
37389
|
});
|
|
35847
37390
|
function optionsObject(value2) {
|
|
35848
37391
|
if (value2 === void 0) return void 0;
|
|
@@ -36125,7 +37668,7 @@ var Work2 = class {
|
|
|
36125
37668
|
return text3.slice(start, end);
|
|
36126
37669
|
}
|
|
36127
37670
|
async encodeInto(text3, target, start) {
|
|
36128
|
-
const
|
|
37671
|
+
const encoder5 = new TextEncoder();
|
|
36129
37672
|
let offset = start;
|
|
36130
37673
|
for (let index = 0; index < text3.length; ) {
|
|
36131
37674
|
let end = Math.min(text3.length, index + 1024);
|
|
@@ -36135,7 +37678,7 @@ var Work2 = class {
|
|
|
36135
37678
|
const chunk = text3.slice(index, end);
|
|
36136
37679
|
const bytes3 = await this.utf8(chunk, target.length - offset);
|
|
36137
37680
|
await this.charge(bytes3);
|
|
36138
|
-
const encoded2 =
|
|
37681
|
+
const encoded2 = encoder5.encodeInto(chunk, target.subarray(offset, offset + bytes3));
|
|
36139
37682
|
if (encoded2.read !== chunk.length || encoded2.written !== bytes3) throw new Error("apply_patch encoding size mismatch");
|
|
36140
37683
|
offset += bytes3;
|
|
36141
37684
|
index = end;
|
|
@@ -36308,7 +37851,7 @@ async function targetPath(value2, work) {
|
|
|
36308
37851
|
if (absolute2.split("/").length - 1 > work.limits.maxPathComponents) throw new PatchError("maxPathComponents limit exceeded");
|
|
36309
37852
|
return absolute2;
|
|
36310
37853
|
}
|
|
36311
|
-
async function
|
|
37854
|
+
async function parse18(text3, work) {
|
|
36312
37855
|
await work.utf8(work.cwd, work.limits.maxPathBytes, 2);
|
|
36313
37856
|
if (!work.cwd.startsWith("/") || work.cwd.includes("\0")) throw new PatchError("cwd must be an absolute virtual path", 2);
|
|
36314
37857
|
const lines3 = await patchLines(text3, work);
|
|
@@ -36736,7 +38279,7 @@ var Invocation2 = class {
|
|
|
36736
38279
|
let summary;
|
|
36737
38280
|
try {
|
|
36738
38281
|
try {
|
|
36739
|
-
const files = await
|
|
38282
|
+
const files = await parse18(await this.input(), work);
|
|
36740
38283
|
const plans = await this.prepare(files);
|
|
36741
38284
|
const lines3 = ["Success. Updated the following files:\n"];
|
|
36742
38285
|
let bytes3 = lines3[0].length;
|
|
@@ -38044,7 +39587,7 @@ shell: command substitution: line ${line}: \`${sourceLine}'
|
|
|
38044
39587
|
const quoteLine = this.lineAt(this.position);
|
|
38045
39588
|
this.position += 2;
|
|
38046
39589
|
const bytes3 = [];
|
|
38047
|
-
const
|
|
39590
|
+
const encoder5 = new TextEncoder();
|
|
38048
39591
|
const escapes = { a: 7, b: 8, e: 27, E: 27, f: 12, n: 10, r: 13, t: 9, v: 11, "\\": 92, "'": 39, '"': 34, "?": 63 };
|
|
38049
39592
|
while (this.position < this.source.length) {
|
|
38050
39593
|
const character = String.fromCodePoint(this.source.codePointAt(this.position));
|
|
@@ -38063,7 +39606,7 @@ shell: command substitution: line ${line}: \`${sourceLine}'
|
|
|
38063
39606
|
}
|
|
38064
39607
|
}
|
|
38065
39608
|
if (character !== "\\") {
|
|
38066
|
-
bytes3.push(...
|
|
39609
|
+
bytes3.push(...encoder5.encode(character));
|
|
38067
39610
|
continue;
|
|
38068
39611
|
}
|
|
38069
39612
|
const escape = this.source[this.position++];
|
|
@@ -38087,16 +39630,16 @@ shell: command substitution: line ${line}: \`${sourceLine}'
|
|
|
38087
39630
|
const code = parseInt(digits, 16);
|
|
38088
39631
|
if (escape === "x") bytes3.push(code);
|
|
38089
39632
|
else if (this.byteLocale && code > 127) {
|
|
38090
|
-
bytes3.push(...
|
|
39633
|
+
bytes3.push(...encoder5.encode(`\\${code <= 65535 ? "u" : "U"}${code.toString(16).toUpperCase().padStart(code <= 65535 ? 4 : 8, "0")}`));
|
|
38091
39634
|
} else {
|
|
38092
39635
|
if (code > 1114111 || code >= 55296 && code <= 57343) this.error("Unsupported non-scalar ANSI-C Unicode escape");
|
|
38093
|
-
bytes3.push(...
|
|
39636
|
+
bytes3.push(...encoder5.encode(String.fromCodePoint(code)));
|
|
38094
39637
|
}
|
|
38095
39638
|
} else if (escape === "c" && this.source[this.position] !== "'" && this.position < this.source.length) {
|
|
38096
39639
|
const control = this.source[this.position++];
|
|
38097
39640
|
if (control === "\\" && this.source[this.position] === "\\") this.position++;
|
|
38098
39641
|
bytes3.push(control === "?" ? 127 : control.toUpperCase().charCodeAt(0) & 31);
|
|
38099
|
-
} else bytes3.push(92, ...
|
|
39642
|
+
} else bytes3.push(92, ...encoder5.encode(escape));
|
|
38100
39643
|
}
|
|
38101
39644
|
this.error("Unterminated ANSI-C quote", { quote: "'", line: quoteLine });
|
|
38102
39645
|
}
|
|
@@ -38374,7 +39917,7 @@ var Parser4 = class {
|
|
|
38374
39917
|
this.advance();
|
|
38375
39918
|
let nodes = 0;
|
|
38376
39919
|
const grouped = /* @__PURE__ */ new WeakSet();
|
|
38377
|
-
const
|
|
39920
|
+
const admit3 = () => {
|
|
38378
39921
|
if (nodes >= 4096) this.error("Conditional syntax exceeds 4096 nodes");
|
|
38379
39922
|
nodes++;
|
|
38380
39923
|
};
|
|
@@ -38385,7 +39928,7 @@ var Parser4 = class {
|
|
|
38385
39928
|
const primary = (depth) => {
|
|
38386
39929
|
if (depth > 64) this.error("Conditional syntax nesting exceeds 64");
|
|
38387
39930
|
if (this.is("!")) {
|
|
38388
|
-
|
|
39931
|
+
admit3();
|
|
38389
39932
|
this.advance();
|
|
38390
39933
|
const expression2 = primary(depth + 1);
|
|
38391
39934
|
if (expression2.kind === "not" && !grouped.has(expression2)) return expression2.operand;
|
|
@@ -38399,7 +39942,7 @@ var Parser4 = class {
|
|
|
38399
39942
|
grouped.add(expression2);
|
|
38400
39943
|
return expression2;
|
|
38401
39944
|
}
|
|
38402
|
-
|
|
39945
|
+
admit3();
|
|
38403
39946
|
this.budget.admit();
|
|
38404
39947
|
const first = operand();
|
|
38405
39948
|
if (conditionalBinary.has(this.current.value)) {
|
|
@@ -38415,7 +39958,7 @@ var Parser4 = class {
|
|
|
38415
39958
|
const conjunction = (depth) => {
|
|
38416
39959
|
let expression2 = primary(depth);
|
|
38417
39960
|
while (this.is("&&")) {
|
|
38418
|
-
|
|
39961
|
+
admit3();
|
|
38419
39962
|
this.budget.admit();
|
|
38420
39963
|
this.advance();
|
|
38421
39964
|
expression2 = { kind: "and", left: expression2, right: primary(depth) };
|
|
@@ -38425,7 +39968,7 @@ var Parser4 = class {
|
|
|
38425
39968
|
const disjunction = (depth) => {
|
|
38426
39969
|
let expression2 = conjunction(depth);
|
|
38427
39970
|
while (this.is("||")) {
|
|
38428
|
-
|
|
39971
|
+
admit3();
|
|
38429
39972
|
this.budget.admit();
|
|
38430
39973
|
this.advance();
|
|
38431
39974
|
expression2 = { kind: "or", left: expression2, right: conjunction(depth) };
|
|
@@ -39038,7 +40581,7 @@ async function* expandBraces(word, budget, signal) {
|
|
|
39038
40581
|
signal.throwIfAborted();
|
|
39039
40582
|
if (++work % 128 === 0) await yieldTurn(signal);
|
|
39040
40583
|
};
|
|
39041
|
-
const
|
|
40584
|
+
const admit3 = (bytes3 = 64) => {
|
|
39042
40585
|
budget.parsing.admit();
|
|
39043
40586
|
allocation.reserveBytes(bytes3);
|
|
39044
40587
|
};
|
|
@@ -39051,15 +40594,15 @@ async function* expandBraces(word, budget, signal) {
|
|
|
39051
40594
|
return left * right;
|
|
39052
40595
|
};
|
|
39053
40596
|
const partNode = (part) => {
|
|
39054
|
-
|
|
40597
|
+
admit3();
|
|
39055
40598
|
return { kind: "part", part, count: 1, bytes: part.kind === "text" ? shellValueByteLength(part.byteValue ?? part.value) : 0 };
|
|
39056
40599
|
};
|
|
39057
40600
|
const textNode = (value2) => {
|
|
39058
|
-
|
|
40601
|
+
admit3(value2.length * 2);
|
|
39059
40602
|
return partNode({ kind: "text", value: value2, quoted: false });
|
|
39060
40603
|
};
|
|
39061
40604
|
const product = async (children) => {
|
|
39062
|
-
|
|
40605
|
+
admit3();
|
|
39063
40606
|
let count2 = 1;
|
|
39064
40607
|
let bytes3 = 0;
|
|
39065
40608
|
for (const child of children) {
|
|
@@ -39073,24 +40616,24 @@ async function* expandBraces(word, budget, signal) {
|
|
|
39073
40616
|
if (children.length !== 1 || children[0].kind !== "part") return void 0;
|
|
39074
40617
|
const part = children[0].part;
|
|
39075
40618
|
if (part.kind !== "text" || part.quoted || part.byteValue) return void 0;
|
|
39076
|
-
|
|
40619
|
+
admit3(32);
|
|
39077
40620
|
const pieces = [];
|
|
39078
40621
|
let startOffset = 0;
|
|
39079
40622
|
for (let offset = 0; offset < part.value.length; offset++) {
|
|
39080
40623
|
if (offset % 1024 === 0) await checkpoint();
|
|
39081
40624
|
if (part.value[offset] !== "." || part.value[offset + 1] !== ".") continue;
|
|
39082
40625
|
if (pieces.length === 2) return void 0;
|
|
39083
|
-
|
|
40626
|
+
admit3(16 + (offset - startOffset) * 2);
|
|
39084
40627
|
pieces.push(part.value.slice(startOffset, offset));
|
|
39085
40628
|
startOffset = offset + 2;
|
|
39086
40629
|
offset++;
|
|
39087
40630
|
}
|
|
39088
40631
|
if (!pieces.length) return void 0;
|
|
39089
|
-
|
|
40632
|
+
admit3(16 + (part.value.length - startOffset) * 2);
|
|
39090
40633
|
pieces.push(part.value.slice(startOffset));
|
|
39091
40634
|
const first = pieces[0];
|
|
39092
40635
|
const last = pieces[1];
|
|
39093
|
-
|
|
40636
|
+
admit3(256);
|
|
39094
40637
|
let start = await integer8(first, checkpoint);
|
|
39095
40638
|
let end = await integer8(last, checkpoint);
|
|
39096
40639
|
const numeric4 = start !== void 0 && end !== void 0;
|
|
@@ -39107,16 +40650,16 @@ async function* expandBraces(word, budget, signal) {
|
|
|
39107
40650
|
const distance = end - start;
|
|
39108
40651
|
const cardinality = (distance < 0n ? -distance : distance) / step + 1n;
|
|
39109
40652
|
if (cardinality > BigInt(budget.limits.maxExpansionFields)) budget.fail("maxExpansionFields");
|
|
39110
|
-
const
|
|
39111
|
-
const width = numeric4 && (
|
|
40653
|
+
const padded2 = (value2) => value2.length > 1 && value2.startsWith("0") || value2.length > 2 && value2.startsWith("-0");
|
|
40654
|
+
const width = numeric4 && (padded2(first) || padded2(last)) ? Math.max(first.length, last.length) : 0;
|
|
39112
40655
|
const count2 = Number(cardinality);
|
|
39113
40656
|
const termBytes = numeric4 ? Math.max(width, start.toString().length, end.toString().length) : 1;
|
|
39114
40657
|
const bytes3 = multiply3(count2, termBytes, "maxExpansionBytes");
|
|
39115
|
-
|
|
40658
|
+
admit3();
|
|
39116
40659
|
return { kind: "range", start, step: distance < 0n ? -step : step, width, numeric: numeric4, count: count2, bytes: bytes3 };
|
|
39117
40660
|
};
|
|
39118
40661
|
try {
|
|
39119
|
-
|
|
40662
|
+
admit3();
|
|
39120
40663
|
const frames = [{ branches: [[]] }];
|
|
39121
40664
|
const append = (node) => {
|
|
39122
40665
|
frames.at(-1).branches.at(-1).push(node);
|
|
@@ -39136,20 +40679,20 @@ async function* expandBraces(word, budget, signal) {
|
|
|
39136
40679
|
const character = part.value[offset];
|
|
39137
40680
|
if (character !== "{" && character !== "}" && character !== ",") continue;
|
|
39138
40681
|
if (start < offset) {
|
|
39139
|
-
|
|
40682
|
+
admit3((offset - start) * 2);
|
|
39140
40683
|
append(textNode(part.value.slice(start, offset)));
|
|
39141
40684
|
}
|
|
39142
40685
|
start = offset + 1;
|
|
39143
40686
|
if (character === "{") {
|
|
39144
|
-
|
|
40687
|
+
admit3();
|
|
39145
40688
|
frames.push({ branches: [[]] });
|
|
39146
40689
|
} else if (character === "," && frames.length > 1) {
|
|
39147
|
-
|
|
40690
|
+
admit3();
|
|
39148
40691
|
frames.at(-1).branches.push([]);
|
|
39149
40692
|
} else if (character === "}" && frames.length > 1) {
|
|
39150
40693
|
const frame = frames.pop();
|
|
39151
40694
|
if (frame.branches.length > 1) {
|
|
39152
|
-
|
|
40695
|
+
admit3(frame.branches.length * 8);
|
|
39153
40696
|
const children = [];
|
|
39154
40697
|
for (const branch of frame.branches) children.push(await product(branch));
|
|
39155
40698
|
let count2 = 0;
|
|
@@ -39178,7 +40721,7 @@ async function* expandBraces(word, budget, signal) {
|
|
|
39178
40721
|
if (start < part.value.length) {
|
|
39179
40722
|
if (start === 0) append(partNode(part));
|
|
39180
40723
|
else {
|
|
39181
|
-
|
|
40724
|
+
admit3((part.value.length - start) * 2);
|
|
39182
40725
|
append(textNode(part.value.slice(start)));
|
|
39183
40726
|
}
|
|
39184
40727
|
}
|
|
@@ -41569,7 +43112,7 @@ var Restoration = class {
|
|
|
41569
43112
|
this.holding?.release();
|
|
41570
43113
|
}
|
|
41571
43114
|
};
|
|
41572
|
-
async function snapshotState(state, clone, signal,
|
|
43115
|
+
async function snapshotState(state, clone, signal, prepare2, scope) {
|
|
41573
43116
|
const monitor = stateMonitor(state);
|
|
41574
43117
|
if (!monitor) return clone();
|
|
41575
43118
|
const session = scope ? { ...monitor.session, scope, owner: void 0, guestOwner: void 0, monitors: /* @__PURE__ */ new Set() } : monitor.session;
|
|
@@ -41659,8 +43202,8 @@ async function snapshotState(state, clone, signal, prepare, scope) {
|
|
|
41659
43202
|
await owner.ledger.checkpoint(signal, 5);
|
|
41660
43203
|
}
|
|
41661
43204
|
check();
|
|
41662
|
-
if (
|
|
41663
|
-
await
|
|
43205
|
+
if (prepare2) {
|
|
43206
|
+
await prepare2(result2.proxy, owner);
|
|
41664
43207
|
check();
|
|
41665
43208
|
}
|
|
41666
43209
|
return result2.proxy;
|
|
@@ -42253,7 +43796,7 @@ var typedSavedVariables = /* @__PURE__ */ new WeakMap();
|
|
|
42253
43796
|
var valueScope = /* @__PURE__ */ Symbol("shell value allocation scope");
|
|
42254
43797
|
var invokedValues = /* @__PURE__ */ new WeakMap();
|
|
42255
43798
|
function isolateIO(io) {
|
|
42256
|
-
return { ...io, nameExpansionContext: void 0, ...io.descriptors ? { descriptors: new Map([...io.descriptors].map(([
|
|
43799
|
+
return { ...io, nameExpansionContext: void 0, ...io.descriptors ? { descriptors: new Map([...io.descriptors].map(([number6, descriptor2]) => [number6, { ...descriptor2 }])) } : {} };
|
|
42257
43800
|
}
|
|
42258
43801
|
function activeIO(io) {
|
|
42259
43802
|
const input3 = io.descriptors?.get(0);
|
|
@@ -43571,9 +45114,9 @@ var Runtime = class _Runtime {
|
|
|
43571
45114
|
async arrayIndex(binding, index, state, io, owner, create = false) {
|
|
43572
45115
|
if (!binding?.associative) {
|
|
43573
45116
|
const selected = index.source === void 0 ? index : literalIndex(index.source, 0, this.budget.parsing);
|
|
43574
|
-
const
|
|
43575
|
-
if (
|
|
43576
|
-
return
|
|
45117
|
+
const number6 = numericIndex(selected);
|
|
45118
|
+
if (number6 === void 0) throw new ArrayFailure("index outside 0..2147483647");
|
|
45119
|
+
return number6;
|
|
43577
45120
|
}
|
|
43578
45121
|
const word = index.word ?? parseArraySubscript(index.source ?? index.decimal, this.budget.parsing, byteLocale(state.variables), state.depth);
|
|
43579
45122
|
const fields3 = await this.valueWord(word, state, io, false);
|
|
@@ -45322,7 +46865,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
45322
46865
|
this.reconcileGetopts(child, state.variables.OPTIND);
|
|
45323
46866
|
return child;
|
|
45324
46867
|
}
|
|
45325
|
-
async shebangStage(incoming, state, io, terminal,
|
|
46868
|
+
async shebangStage(incoming, state, io, terminal, prepare2, replacementInput, existingScope) {
|
|
45326
46869
|
const scope = existingScope ?? io[invocationScope].child();
|
|
45327
46870
|
const ownsScope = existingScope === void 0;
|
|
45328
46871
|
const runtime = new _Runtime(
|
|
@@ -45383,7 +46926,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
45383
46926
|
if (argumentValues.values.every((value2) => typeof value2 === "string")) Reflect.deleteProperty(context2, "argumentValues");
|
|
45384
46927
|
const child = await runtime.shebangState(context2, state);
|
|
45385
46928
|
const childIO = { ...io, ...context2, [invocationScope]: scope };
|
|
45386
|
-
invocationOverride.current =
|
|
46929
|
+
invocationOverride.current = prepare2?.(runtime, context2, child, childIO);
|
|
45387
46930
|
const runtimeFrame = {};
|
|
45388
46931
|
const middleware = this.middleware.map((handler) => (context3, next) => {
|
|
45389
46932
|
scope.assertOpen();
|
|
@@ -45879,7 +47422,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
45879
47422
|
async letBuiltin(context2, state) {
|
|
45880
47423
|
this.signal.throwIfAborted();
|
|
45881
47424
|
const { maxExpansionBytes: bytes3, maxExpansionFields: fields3 } = this.budget.limits;
|
|
45882
|
-
const
|
|
47425
|
+
const admit3 = (value3) => {
|
|
45883
47426
|
if (typeof value3 !== "string" || value3.includes("\0")) throw new CommandFailure2("let: arguments must be strings without NUL", 2);
|
|
45884
47427
|
if (value3.length > bytes3 || import_buffer.Buffer.byteLength(value3) > bytes3) this.budget.fail("maxExpansionBytes");
|
|
45885
47428
|
};
|
|
@@ -45891,10 +47434,10 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
45891
47434
|
const { args } = context2;
|
|
45892
47435
|
if (!Array.isArray(args)) throw new CommandFailure2("let: argument array required", 2);
|
|
45893
47436
|
if (args.length + 1 > fields3) this.budget.fail("maxExpansionFields");
|
|
45894
|
-
|
|
47437
|
+
admit3(context2.command);
|
|
45895
47438
|
for (let index = 0; index < args.length; index++) {
|
|
45896
47439
|
this.signal.throwIfAborted();
|
|
45897
|
-
|
|
47440
|
+
admit3(args[index]);
|
|
45898
47441
|
if ((index + 1) % 128 === 0) await checkpoint();
|
|
45899
47442
|
}
|
|
45900
47443
|
if (args[0] === "--help") throw new CommandFailure2("let: --help: unsupported option", 2);
|
|
@@ -45923,7 +47466,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
45923
47466
|
async getoptsBuiltin(context2, state) {
|
|
45924
47467
|
this.signal.throwIfAborted();
|
|
45925
47468
|
const { maxExpansionBytes: bytes3, maxExpansionFields: fields3 } = this.budget.limits;
|
|
45926
|
-
const
|
|
47469
|
+
const admit3 = (value2) => {
|
|
45927
47470
|
if (typeof value2 !== "string") throw new CommandFailure2("getopts: arguments must be strings without NUL", 2);
|
|
45928
47471
|
if (value2.length > bytes3 || import_buffer.Buffer.byteLength(value2) > bytes3) this.budget.fail("maxExpansionBytes");
|
|
45929
47472
|
if (value2.includes("\0")) throw new CommandFailure2("getopts: arguments must be strings without NUL", 2);
|
|
@@ -45935,10 +47478,10 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
45935
47478
|
};
|
|
45936
47479
|
if (!Array.isArray(context2.args)) throw new CommandFailure2("getopts: argument array required", 2);
|
|
45937
47480
|
if (context2.args.length + 1 > fields3) this.budget.fail("maxExpansionFields");
|
|
45938
|
-
|
|
47481
|
+
admit3(context2.command);
|
|
45939
47482
|
for (let index = 0; index < context2.args.length; index++) {
|
|
45940
47483
|
this.signal.throwIfAborted();
|
|
45941
|
-
|
|
47484
|
+
admit3(context2.args[index]);
|
|
45942
47485
|
if ((index + 1) % 128 === 0) await checkpoint();
|
|
45943
47486
|
}
|
|
45944
47487
|
const offset = context2.args[0] === "--" ? 1 : 0;
|
|
@@ -45977,7 +47520,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
45977
47520
|
const args = input3?.args ?? supplied;
|
|
45978
47521
|
if (!input3 || allocation) for (let index = 0; index < args.length; index++) {
|
|
45979
47522
|
this.signal.throwIfAborted();
|
|
45980
|
-
|
|
47523
|
+
admit3(args[index]);
|
|
45981
47524
|
if ((index + 1) % 128 === 0) await checkpoint();
|
|
45982
47525
|
}
|
|
45983
47526
|
state.getopts ??= cloneGetoptsBinding(state);
|
|
@@ -46128,8 +47671,8 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46128
47671
|
continue;
|
|
46129
47672
|
}
|
|
46130
47673
|
if ((token.startsWith("+") || token.startsWith("-")) && !(command7 === "pushd" && token === "-")) {
|
|
46131
|
-
const
|
|
46132
|
-
selected = token.startsWith("+") ?
|
|
47674
|
+
const number6 = await work.number(token);
|
|
47675
|
+
selected = token.startsWith("+") ? number6 : BigInt(count2) - number6;
|
|
46133
47676
|
if (command7 === "pushd") boundedIndex(selected);
|
|
46134
47677
|
continue;
|
|
46135
47678
|
}
|
|
@@ -46309,8 +47852,8 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46309
47852
|
}
|
|
46310
47853
|
}
|
|
46311
47854
|
const arguments_ = incoming.slice(offset);
|
|
46312
|
-
const
|
|
46313
|
-
if (
|
|
47855
|
+
const format3 = arguments_.args[0] === "--" ? arguments_.args[1] : arguments_.args[0];
|
|
47856
|
+
if (format3 === void 0 || arguments_.args[0] !== "--" && format3.startsWith("-")) {
|
|
46314
47857
|
await writeDiagnostic(context2.stderr, "printf: usage: printf [-v var] format [arguments]\n");
|
|
46315
47858
|
return 2;
|
|
46316
47859
|
}
|
|
@@ -48786,17 +50329,17 @@ var Shell = class {
|
|
|
48786
50329
|
if (!middleware || typeof middleware.setup !== "function") throw new TypeError("Expected middleware or shell plugin");
|
|
48787
50330
|
this.#ready = this.#ready.then(async () => {
|
|
48788
50331
|
let active = true;
|
|
48789
|
-
const
|
|
50332
|
+
const admit3 = () => {
|
|
48790
50333
|
if (this.#disposed && !active) throw new Error("Shell is disposed");
|
|
48791
50334
|
};
|
|
48792
50335
|
const host2 = {
|
|
48793
50336
|
commands: this.commands,
|
|
48794
50337
|
use: (middleware2) => {
|
|
48795
|
-
|
|
50338
|
+
admit3();
|
|
48796
50339
|
this.#install(middleware2);
|
|
48797
50340
|
},
|
|
48798
50341
|
registerFileSystem: (scheme, factory) => {
|
|
48799
|
-
|
|
50342
|
+
admit3();
|
|
48800
50343
|
this.#registerFileSystem(scheme, factory);
|
|
48801
50344
|
}
|
|
48802
50345
|
};
|
|
@@ -51679,17 +53222,17 @@ var WebDavFileSystem = class {
|
|
|
51679
53222
|
}
|
|
51680
53223
|
const sizeText = directory2 ? "0" : scalar2(required("getcontentlength"));
|
|
51681
53224
|
if (!/^\d+$/.test(sizeText) || !Number.isSafeInteger(Number(sizeText))) throw new Error("invalid content length property");
|
|
51682
|
-
const
|
|
53225
|
+
const date2 = (name2) => {
|
|
51683
53226
|
const property = properties.get(name2);
|
|
51684
53227
|
if (!property) return void 0;
|
|
51685
53228
|
const value2 = Date.parse(scalar2(property));
|
|
51686
53229
|
if (!Number.isFinite(value2)) throw new Error("invalid date property");
|
|
51687
53230
|
return value2;
|
|
51688
53231
|
};
|
|
51689
|
-
const birthtimeMs =
|
|
53232
|
+
const birthtimeMs = date2("creationdate");
|
|
51690
53233
|
const etag = properties.get("getetag");
|
|
51691
53234
|
const validator = etag && scalar2(etag);
|
|
51692
|
-
let mtimeMs =
|
|
53235
|
+
let mtimeMs = date2("getlastmodified") ?? 0;
|
|
51693
53236
|
let atimeMs = 0;
|
|
51694
53237
|
if (timestampProperty) {
|
|
51695
53238
|
const timestamps = JSON.parse(scalar2(timestampProperty));
|
|
@@ -52995,12 +54538,14 @@ export {
|
|
|
52995
54538
|
createTimeoutCommands,
|
|
52996
54539
|
createTreeCommand,
|
|
52997
54540
|
createTreeCommands,
|
|
54541
|
+
createUnzipCommand,
|
|
52998
54542
|
createWgetCommand,
|
|
52999
54543
|
createWhichCommand,
|
|
53000
54544
|
createWhichCommands,
|
|
53001
54545
|
createXmlCommands,
|
|
53002
54546
|
createYqCommand,
|
|
53003
54547
|
createYqCommands,
|
|
54548
|
+
createZipCommand,
|
|
53004
54549
|
curlCommands,
|
|
53005
54550
|
defaultJqLimits,
|
|
53006
54551
|
defaultMemoryFileSystemLimits2 as defaultMemoryFileSystemLimits,
|