@openclaw/fs-safe 0.8.1 → 0.8.2
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/CHANGELOG.md +11 -0
- package/README.md +1 -1
- package/dist/archive-entry.d.ts.map +1 -1
- package/dist/archive-entry.js +5 -0
- package/dist/archive-gzip-tail.d.ts +18 -0
- package/dist/archive-gzip-tail.d.ts.map +1 -0
- package/dist/archive-gzip-tail.js +74 -0
- package/dist/archive-parser.wasm +0 -0
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +18 -60
- package/dist/archive-tar-extract.d.ts +11 -0
- package/dist/archive-tar-extract.d.ts.map +1 -0
- package/dist/archive-tar-extract.js +49 -0
- package/dist/archive-tar-stream.d.ts +18 -0
- package/dist/archive-tar-stream.d.ts.map +1 -0
- package/dist/archive-tar-stream.js +95 -0
- package/dist/archive-tar-wasm.d.ts +18 -0
- package/dist/archive-tar-wasm.d.ts.map +1 -0
- package/dist/archive-tar-wasm.js +102 -0
- package/dist/archive-tar.d.ts +0 -1
- package/dist/archive-tar.d.ts.map +1 -1
- package/dist/archive-tar.js +0 -22
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +2 -109
- package/dist/device-path.d.ts +1 -0
- package/dist/device-path.d.ts.map +1 -1
- package/dist/device-path.js +5 -2
- package/dist/directory-mode-owner.d.ts.map +1 -1
- package/dist/directory-mode-owner.js +3 -0
- package/dist/replace-file-descriptor.d.ts.map +1 -1
- package/dist/replace-file-descriptor.js +2 -1
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +2 -0
- package/dist/secret-read-async.d.ts.map +1 -1
- package/dist/secret-read-async.js +3 -0
- package/docs/archive.md +66 -61
- package/docs/contributing.md +35 -1
- package/docs/install.md +1 -1
- package/docs/native-helper.md +5 -0
- package/docs/native.md +16 -10
- package/docs/secret-file.md +5 -0
- package/package.json +19 -16
- package/dist/archive-tar-admission.d.ts +0 -7
- package/dist/archive-tar-admission.d.ts.map +0 -1
- package/dist/archive-tar-admission.js +0 -43
- package/dist/archive-tar-gnu.d.ts +0 -2
- package/dist/archive-tar-gnu.d.ts.map +0 -1
- package/dist/archive-tar-gnu.js +0 -20
- package/dist/archive-tar-header.d.ts +0 -8
- package/dist/archive-tar-header.d.ts.map +0 -1
- package/dist/archive-tar-header.js +0 -47
- package/dist/archive-tar-meta.d.ts +0 -34
- package/dist/archive-tar-meta.d.ts.map +0 -1
- package/dist/archive-tar-meta.js +0 -277
- package/dist/archive-tar-pax.d.ts +0 -8
- package/dist/archive-tar-pax.d.ts.map +0 -1
- package/dist/archive-tar-pax.js +0 -100
- package/dist/archive-tar-runtime.d.ts +0 -49
- package/dist/archive-tar-runtime.d.ts.map +0 -1
- package/dist/archive-tar-runtime.js +0 -22
package/dist/archive-tar-pax.js
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { ArchiveFormatError } from "./archive-errors.js";
|
|
2
|
-
function invalid() {
|
|
3
|
-
throw new ArchiveFormatError("invalid TAR header: unsupported or malformed PAX metadata");
|
|
4
|
-
}
|
|
5
|
-
function decimal(bytes) {
|
|
6
|
-
const text = bytes.toString("latin1");
|
|
7
|
-
if (!/^(0|[1-9][0-9]*)$/.test(text))
|
|
8
|
-
invalid();
|
|
9
|
-
const value = Number(text);
|
|
10
|
-
if (!Number.isSafeInteger(value))
|
|
11
|
-
invalid();
|
|
12
|
-
return value;
|
|
13
|
-
}
|
|
14
|
-
function ascii(bytes) {
|
|
15
|
-
if (bytes.length === 0 || bytes.some((byte) => byte < 0x20 || byte > 0x7e))
|
|
16
|
-
invalid();
|
|
17
|
-
return bytes.toString("ascii");
|
|
18
|
-
}
|
|
19
|
-
// Keep this grammar aligned with native/src/tar_pax.rs. Downstream parsers
|
|
20
|
-
// disagree on duplicates, coercions and UTF-8 chunk boundaries.
|
|
21
|
-
export function parseLocalPax(body) {
|
|
22
|
-
if (body.length === 0)
|
|
23
|
-
invalid();
|
|
24
|
-
const result = {};
|
|
25
|
-
const keys = new Set();
|
|
26
|
-
let offset = 0;
|
|
27
|
-
while (offset < body.length) {
|
|
28
|
-
const space = body.indexOf(0x20, offset);
|
|
29
|
-
if (space < 0)
|
|
30
|
-
invalid();
|
|
31
|
-
const length = decimal(body.subarray(offset, space));
|
|
32
|
-
if (length > body.length - offset || length <= space - offset + 3)
|
|
33
|
-
invalid();
|
|
34
|
-
const end = offset + length;
|
|
35
|
-
if (body[end - 1] !== 0x0a)
|
|
36
|
-
invalid();
|
|
37
|
-
const record = body.subarray(space + 1, end - 1);
|
|
38
|
-
if (record.includes(0x0a))
|
|
39
|
-
invalid();
|
|
40
|
-
const equals = record.indexOf(0x3d);
|
|
41
|
-
if (equals <= 0)
|
|
42
|
-
invalid();
|
|
43
|
-
const key = ascii(record.subarray(0, equals));
|
|
44
|
-
if (!/^[A-Za-z0-9_.-]+$/.test(key) || keys.has(key))
|
|
45
|
-
invalid();
|
|
46
|
-
keys.add(key);
|
|
47
|
-
const value = record.subarray(equals + 1);
|
|
48
|
-
if (/^(LIBARCHIVE|SCHILY)\.xattr\..+$/.test(key)) {
|
|
49
|
-
// Inert bytes, never restored. Newlines would corrupt Rust's subsequent
|
|
50
|
-
// record lookup; NUL and non-UTF8 bytes in these values are harmless.
|
|
51
|
-
}
|
|
52
|
-
else if (key === "path" || key === "linkpath") {
|
|
53
|
-
result[key] = ascii(value);
|
|
54
|
-
}
|
|
55
|
-
else if (key === "size") {
|
|
56
|
-
result.size = decimal(value);
|
|
57
|
-
}
|
|
58
|
-
else if (key === "uid" || key === "gid") {
|
|
59
|
-
decimal(value);
|
|
60
|
-
}
|
|
61
|
-
else if (key === "uname" || key === "gname") {
|
|
62
|
-
ascii(value);
|
|
63
|
-
}
|
|
64
|
-
else if (key === "mtime" || key === "atime" || key === "ctime") {
|
|
65
|
-
const text = ascii(value);
|
|
66
|
-
if (!/^-?(0|[1-9][0-9]*)(\.[0-9]+)?$/.test(text) || Math.abs(Number(text)) > 8_640_000_000_000)
|
|
67
|
-
invalid();
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
invalid();
|
|
71
|
-
}
|
|
72
|
-
offset = end;
|
|
73
|
-
}
|
|
74
|
-
return result;
|
|
75
|
-
}
|
|
76
|
-
function rawText(field) {
|
|
77
|
-
const zero = field.indexOf(0);
|
|
78
|
-
const value = field.subarray(0, zero < 0 ? field.length : zero);
|
|
79
|
-
return value.length === 0 ? "" : ascii(value);
|
|
80
|
-
}
|
|
81
|
-
export function paxMemberSize(pax, type, rawSize, header) {
|
|
82
|
-
if (![0, 0x30, 0x31, 0x32, 0x35, 0x37].includes(type))
|
|
83
|
-
invalid();
|
|
84
|
-
const rawName = rawText(header.subarray(0, 100));
|
|
85
|
-
const rawLink = rawText(header.subarray(157, 257));
|
|
86
|
-
if (header.subarray(257, 265).equals(Buffer.from("ustar\0" + "00"))) {
|
|
87
|
-
rawText(header.subarray(345, 500));
|
|
88
|
-
}
|
|
89
|
-
const isLink = type === 0x31 || type === 0x32;
|
|
90
|
-
if (isLink !== (rawLink.length > 0))
|
|
91
|
-
invalid();
|
|
92
|
-
const size = pax.size ?? rawSize;
|
|
93
|
-
if ([0x31, 0x32, 0x35].includes(type) && (rawSize !== 0 || size !== 0))
|
|
94
|
-
invalid();
|
|
95
|
-
if (type !== 0x35 && (pax.path?.endsWith("/") || pax.path?.endsWith("\\") || rawName.endsWith("\\")))
|
|
96
|
-
invalid();
|
|
97
|
-
if (pax.linkpath !== undefined && !isLink)
|
|
98
|
-
invalid();
|
|
99
|
-
return size;
|
|
100
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
export type TarParserEntry = {
|
|
2
|
-
meta?: boolean;
|
|
3
|
-
size: number;
|
|
4
|
-
type?: string;
|
|
5
|
-
resume(): void;
|
|
6
|
-
};
|
|
7
|
-
export type TarParser = NodeJS.WritableStream & {
|
|
8
|
-
abort(error: Error): void;
|
|
9
|
-
on(event: "ignoredEntry", listener: (entry: TarParserEntry) => void): TarParser;
|
|
10
|
-
on(event: "entry", listener: (entry: TarParserEntry) => void): TarParser;
|
|
11
|
-
on(event: "meta", listener: (metadata: string) => void): TarParser;
|
|
12
|
-
on(event: "error", listener: (error: Error) => void): TarParser;
|
|
13
|
-
on(event: "end", listener: () => void): TarParser;
|
|
14
|
-
};
|
|
15
|
-
export declare const NODE_TAR_RATIO_DISABLED: number;
|
|
16
|
-
export type TarModule = {
|
|
17
|
-
Parser: new (options: {
|
|
18
|
-
strict: true;
|
|
19
|
-
maxMetaEntrySize: number;
|
|
20
|
-
}) => TarParser;
|
|
21
|
-
x(options: {
|
|
22
|
-
cwd: string;
|
|
23
|
-
strip: number;
|
|
24
|
-
gzip?: boolean;
|
|
25
|
-
signal?: AbortSignal;
|
|
26
|
-
preservePaths: false;
|
|
27
|
-
noChmod: true;
|
|
28
|
-
preserveOwner: false;
|
|
29
|
-
noMtime: true;
|
|
30
|
-
dmode: number;
|
|
31
|
-
strict: true;
|
|
32
|
-
maxMetaEntrySize: number;
|
|
33
|
-
maxDecompressionRatio: number;
|
|
34
|
-
filter?(this: TarParser, entryPath: string, entry: unknown): boolean;
|
|
35
|
-
onReadEntry(this: unknown, entry: unknown): void;
|
|
36
|
-
}): TarParser;
|
|
37
|
-
t(options: {
|
|
38
|
-
file: string;
|
|
39
|
-
strict: true;
|
|
40
|
-
maxMetaEntrySize: number;
|
|
41
|
-
maxDecompressionRatio: number;
|
|
42
|
-
onReadEntry(entry: AsyncIterable<unknown> & {
|
|
43
|
-
resume(): void;
|
|
44
|
-
}): void;
|
|
45
|
-
}): Promise<unknown>;
|
|
46
|
-
};
|
|
47
|
-
export declare function importOptionalTar(): Promise<TarModule>;
|
|
48
|
-
export declare function normalizeTarParserError(error: unknown): unknown;
|
|
49
|
-
//# sourceMappingURL=archive-tar-runtime.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"archive-tar-runtime.d.ts","sourceRoot":"","sources":["../src/archive-tar-runtime.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,GAAG;IAC9C,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC1B,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,SAAS,CAAC;IAChF,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,SAAS,CAAC;IACzE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,SAAS,CAAC;IACnE,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,SAAS,CAAC;IAChE,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,SAAS,CAAC;CACnD,CAAC;AAIF,eAAO,MAAM,uBAAuB,QAA2B,CAAC;AAEhE,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,EAAE,KAAK,OAAO,EAAE;QAAE,MAAM,EAAE,IAAI,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,KAAK,SAAS,CAAC;IAC/E,CAAC,CAAC,OAAO,EAAE;QACT,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,aAAa,EAAE,KAAK,CAAC;QACrB,OAAO,EAAE,IAAI,CAAC;QACd,aAAa,EAAE,KAAK,CAAC;QACrB,OAAO,EAAE,IAAI,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,IAAI,CAAC;QACb,gBAAgB,EAAE,MAAM,CAAC;QACzB,qBAAqB,EAAE,MAAM,CAAC;QAC9B,MAAM,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;QACrE,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;KAClD,GAAG,SAAS,CAAC;IACd,CAAC,CAAC,OAAO,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,IAAI,CAAC;QACb,gBAAgB,EAAE,MAAM,CAAC;QACzB,qBAAqB,EAAE,MAAM,CAAC;QAC9B,WAAW,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG;YAAE,MAAM,IAAI,IAAI,CAAA;SAAE,GAAG,IAAI,CAAC;KACvE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACtB,CAAC;AAEF,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,SAAS,CAAC,CAS5D;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAS/D"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { ArchiveFormatError } from "./archive-errors.js";
|
|
2
|
-
// Both callers parse an immutable staged stream only after fs-safe's complete
|
|
3
|
-
// decoded-byte admission, so node-tar must not add backend-specific policy.
|
|
4
|
-
export const NODE_TAR_RATIO_DISABLED = Number.POSITIVE_INFINITY;
|
|
5
|
-
export async function importOptionalTar() {
|
|
6
|
-
try {
|
|
7
|
-
return await import("tar");
|
|
8
|
-
}
|
|
9
|
-
catch (cause) {
|
|
10
|
-
throw new Error('Optional archive dependency "tar" is not installed. Install it to use TAR archive helpers from @openclaw/fs-safe/archive.', { cause });
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
export function normalizeTarParserError(error) {
|
|
14
|
-
const code = error?.code;
|
|
15
|
-
if (typeof code !== "string" || !code.startsWith("TAR_")) {
|
|
16
|
-
return error;
|
|
17
|
-
}
|
|
18
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
19
|
-
return new ArchiveFormatError(`invalid TAR archive: ${message}`, {
|
|
20
|
-
cause: error instanceof Error ? error : undefined,
|
|
21
|
-
});
|
|
22
|
-
}
|