tar-xz 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/LICENSE +165 -0
  2. package/README.md +201 -0
  3. package/lib/browser/create.d.ts +27 -0
  4. package/lib/browser/create.d.ts.map +1 -0
  5. package/lib/browser/create.js +113 -0
  6. package/lib/browser/create.js.map +1 -0
  7. package/lib/browser/extract.d.ts +24 -0
  8. package/lib/browser/extract.d.ts.map +1 -0
  9. package/lib/browser/extract.js +112 -0
  10. package/lib/browser/extract.js.map +1 -0
  11. package/lib/browser/index.d.ts +7 -0
  12. package/lib/browser/index.d.ts.map +1 -0
  13. package/lib/browser/index.js +7 -0
  14. package/lib/browser/index.js.map +1 -0
  15. package/lib/browser/list.d.ts +23 -0
  16. package/lib/browser/list.d.ts.map +1 -0
  17. package/lib/browser/list.js +81 -0
  18. package/lib/browser/list.js.map +1 -0
  19. package/lib/index.browser.d.ts +12 -0
  20. package/lib/index.browser.d.ts.map +1 -0
  21. package/lib/index.browser.js +14 -0
  22. package/lib/index.browser.js.map +1 -0
  23. package/lib/index.d.ts +12 -0
  24. package/lib/index.d.ts.map +1 -0
  25. package/lib/index.js +14 -0
  26. package/lib/index.js.map +1 -0
  27. package/lib/node/create.d.ts +22 -0
  28. package/lib/node/create.d.ts.map +1 -0
  29. package/lib/node/create.js +155 -0
  30. package/lib/node/create.js.map +1 -0
  31. package/lib/node/extract.d.ts +30 -0
  32. package/lib/node/extract.d.ts.map +1 -0
  33. package/lib/node/extract.js +274 -0
  34. package/lib/node/extract.js.map +1 -0
  35. package/lib/node/index.d.ts +7 -0
  36. package/lib/node/index.d.ts.map +1 -0
  37. package/lib/node/index.js +7 -0
  38. package/lib/node/index.js.map +1 -0
  39. package/lib/node/list.d.ts +20 -0
  40. package/lib/node/list.d.ts.map +1 -0
  41. package/lib/node/list.js +115 -0
  42. package/lib/node/list.js.map +1 -0
  43. package/lib/tar/checksum.d.ts +40 -0
  44. package/lib/tar/checksum.d.ts.map +1 -0
  45. package/lib/tar/checksum.js +91 -0
  46. package/lib/tar/checksum.js.map +1 -0
  47. package/lib/tar/format.d.ts +87 -0
  48. package/lib/tar/format.d.ts.map +1 -0
  49. package/lib/tar/format.js +244 -0
  50. package/lib/tar/format.js.map +1 -0
  51. package/lib/tar/index.d.ts +8 -0
  52. package/lib/tar/index.d.ts.map +1 -0
  53. package/lib/tar/index.js +6 -0
  54. package/lib/tar/index.js.map +1 -0
  55. package/lib/tar/pax.d.ts +82 -0
  56. package/lib/tar/pax.d.ts.map +1 -0
  57. package/lib/tar/pax.js +185 -0
  58. package/lib/tar/pax.js.map +1 -0
  59. package/lib/types.d.ts +144 -0
  60. package/lib/types.d.ts.map +1 -0
  61. package/lib/types.js +26 -0
  62. package/lib/types.js.map +1 -0
  63. package/package.json +80 -0
@@ -0,0 +1,274 @@
1
+ /**
2
+ * Node.js TAR extraction with XZ decompression
3
+ */
4
+ import { createReadStream, promises as fs } from 'node:fs';
5
+ import * as path from 'node:path';
6
+ import { Writable } from 'node:stream';
7
+ import { pipeline } from 'node:stream/promises';
8
+ import { createUnxz } from 'node-liblzma';
9
+ import { applyPaxAttributes, BLOCK_SIZE, calculatePadding, isEmptyBlock, parseHeader, parsePaxData, } from '../tar/index.js';
10
+ import { TarEntryType } from '../types.js';
11
+ /**
12
+ * Transform stream that unpacks TAR format
13
+ */
14
+ class TarUnpack extends Writable {
15
+ buffer = Buffer.alloc(0);
16
+ currentEntry = null;
17
+ bytesRemaining = 0;
18
+ paddingRemaining = 0;
19
+ contentChunks = [];
20
+ paxAttrs = null;
21
+ emptyBlockCount = 0;
22
+ entries = [];
23
+ _write(chunk, _encoding, callback) {
24
+ this.buffer = Buffer.concat([this.buffer, chunk]);
25
+ try {
26
+ this.processBuffer();
27
+ callback();
28
+ }
29
+ catch (error) {
30
+ callback(error);
31
+ }
32
+ }
33
+ processBuffer() {
34
+ while (this.buffer.length > 0) {
35
+ // Handle padding
36
+ if (this.paddingRemaining > 0) {
37
+ const skip = Math.min(this.paddingRemaining, this.buffer.length);
38
+ this.buffer = this.buffer.subarray(skip);
39
+ this.paddingRemaining -= skip;
40
+ continue;
41
+ }
42
+ // Handle file content
43
+ if (this.bytesRemaining > 0 && this.currentEntry) {
44
+ const readSize = Math.min(this.bytesRemaining, this.buffer.length);
45
+ this.contentChunks.push(this.buffer.subarray(0, readSize));
46
+ this.buffer = this.buffer.subarray(readSize);
47
+ this.bytesRemaining -= readSize;
48
+ // Entry complete
49
+ if (this.bytesRemaining === 0) {
50
+ const content = Buffer.concat(this.contentChunks);
51
+ this.entries.push({ ...this.currentEntry, content });
52
+ // Calculate padding
53
+ this.paddingRemaining = calculatePadding(this.currentEntry.size);
54
+ this.currentEntry = null;
55
+ this.contentChunks = [];
56
+ }
57
+ continue;
58
+ }
59
+ // Need a full block for header
60
+ if (this.buffer.length < BLOCK_SIZE) {
61
+ break;
62
+ }
63
+ const headerBlock = this.buffer.subarray(0, BLOCK_SIZE);
64
+ this.buffer = this.buffer.subarray(BLOCK_SIZE);
65
+ // Check for end-of-archive
66
+ if (isEmptyBlock(headerBlock)) {
67
+ this.emptyBlockCount++;
68
+ if (this.emptyBlockCount >= 2) {
69
+ // End of archive
70
+ break;
71
+ }
72
+ continue;
73
+ }
74
+ this.emptyBlockCount = 0;
75
+ // Parse header
76
+ let entry = parseHeader(headerBlock);
77
+ if (!entry) {
78
+ continue;
79
+ }
80
+ // Handle PAX headers
81
+ if (entry.type === TarEntryType.PAX_HEADER) {
82
+ // Read PAX data
83
+ const paxSize = entry.size;
84
+ const paxPadding = calculatePadding(paxSize);
85
+ const totalNeeded = paxSize + paxPadding;
86
+ if (this.buffer.length < totalNeeded) {
87
+ // Put header back and wait for more data
88
+ this.buffer = Buffer.concat([headerBlock, this.buffer]);
89
+ break;
90
+ }
91
+ const paxData = this.buffer.subarray(0, paxSize);
92
+ this.buffer = this.buffer.subarray(paxSize + paxPadding);
93
+ this.paxAttrs = parsePaxData(paxData);
94
+ continue;
95
+ }
96
+ if (entry.type === TarEntryType.PAX_GLOBAL) {
97
+ // Skip global PAX headers (we don't support them yet)
98
+ const skipSize = entry.size + calculatePadding(entry.size);
99
+ if (this.buffer.length < skipSize) {
100
+ this.buffer = Buffer.concat([headerBlock, this.buffer]);
101
+ break;
102
+ }
103
+ this.buffer = this.buffer.subarray(skipSize);
104
+ continue;
105
+ }
106
+ // Apply PAX attributes if present
107
+ if (this.paxAttrs) {
108
+ entry = applyPaxAttributes(entry, this.paxAttrs);
109
+ this.paxAttrs = null;
110
+ }
111
+ // Handle directories (no content)
112
+ if (entry.type === TarEntryType.DIRECTORY) {
113
+ this.entries.push({ ...entry, content: Buffer.alloc(0) });
114
+ continue;
115
+ }
116
+ // Handle symlinks (no content)
117
+ if (entry.type === TarEntryType.SYMLINK || entry.type === TarEntryType.HARDLINK) {
118
+ this.entries.push({ ...entry, content: Buffer.alloc(0) });
119
+ continue;
120
+ }
121
+ // Regular file - prepare to read content
122
+ if (entry.size > 0) {
123
+ this.currentEntry = entry;
124
+ this.bytesRemaining = entry.size;
125
+ this.contentChunks = [];
126
+ }
127
+ else {
128
+ this.entries.push({ ...entry, content: Buffer.alloc(0) });
129
+ }
130
+ }
131
+ }
132
+ _final(callback) {
133
+ if (this.bytesRemaining > 0) {
134
+ callback(new Error(`Unexpected end of archive, ${this.bytesRemaining} bytes remaining`));
135
+ }
136
+ else {
137
+ callback();
138
+ }
139
+ }
140
+ }
141
+ /**
142
+ * Strip leading path components from a path
143
+ */
144
+ function stripPath(filePath, strip) {
145
+ if (strip <= 0) {
146
+ return filePath;
147
+ }
148
+ const parts = filePath.split('/');
149
+ return parts.slice(strip).join('/');
150
+ }
151
+ /**
152
+ * Validate that a path doesn't escape the target directory (path traversal protection)
153
+ * @throws Error if path traversal is detected
154
+ */
155
+ function validatePath(destPath, cwd) {
156
+ const resolvedDest = path.resolve(destPath);
157
+ const resolvedCwd = path.resolve(cwd);
158
+ // Ensure the destination path starts with the cwd (no escape via ../)
159
+ if (!resolvedDest.startsWith(resolvedCwd + path.sep) && resolvedDest !== resolvedCwd) {
160
+ throw new Error(`Path traversal detected: ${destPath} escapes ${cwd}`);
161
+ }
162
+ }
163
+ /**
164
+ * Extract a tar.xz archive
165
+ *
166
+ * @param options - Extraction options
167
+ * @returns Promise with list of extracted entries
168
+ *
169
+ * @example
170
+ * ```ts
171
+ * await extract({
172
+ * file: 'archive.tar.xz',
173
+ * cwd: '/dest',
174
+ * strip: 1
175
+ * });
176
+ * ```
177
+ */
178
+ export async function extract(options) {
179
+ const { file, cwd = process.cwd(), strip = 0, filter, preserveOwner = false } = options;
180
+ // Create decompression and unpacking streams
181
+ const inputStream = createReadStream(file);
182
+ const unxzStream = createUnxz();
183
+ const tarUnpack = new TarUnpack();
184
+ // Run pipeline
185
+ await pipeline(inputStream, unxzStream, tarUnpack);
186
+ // Extract files
187
+ const extractedEntries = [];
188
+ for (const entry of tarUnpack.entries) {
189
+ // Apply strip
190
+ const strippedName = stripPath(entry.name, strip);
191
+ if (!strippedName) {
192
+ continue;
193
+ }
194
+ // Apply filter
195
+ const entryForFilter = { ...entry, name: strippedName };
196
+ if (filter && !filter(entryForFilter)) {
197
+ continue;
198
+ }
199
+ const destPath = path.join(cwd, strippedName);
200
+ // Validate path doesn't escape cwd (path traversal protection)
201
+ validatePath(destPath, cwd);
202
+ // Ensure parent directory exists
203
+ await fs.mkdir(path.dirname(destPath), { recursive: true });
204
+ if (entry.type === TarEntryType.DIRECTORY) {
205
+ await fs.mkdir(destPath, { recursive: true });
206
+ }
207
+ else if (entry.type === TarEntryType.SYMLINK) {
208
+ try {
209
+ await fs.unlink(destPath);
210
+ }
211
+ catch {
212
+ // Ignore if doesn't exist
213
+ }
214
+ await fs.symlink(entry.linkname, destPath);
215
+ }
216
+ else if (entry.type === TarEntryType.HARDLINK) {
217
+ const linkDest = path.join(cwd, stripPath(entry.linkname, strip));
218
+ try {
219
+ await fs.unlink(destPath);
220
+ }
221
+ catch {
222
+ // Ignore if doesn't exist
223
+ }
224
+ await fs.link(linkDest, destPath);
225
+ }
226
+ else {
227
+ // Regular file
228
+ await fs.writeFile(destPath, entry.content);
229
+ }
230
+ // Set permissions
231
+ try {
232
+ await fs.chmod(destPath, entry.mode);
233
+ }
234
+ catch {
235
+ // Ignore permission errors
236
+ }
237
+ // Set ownership if requested and running as root
238
+ if (preserveOwner && process.getuid?.() === 0) {
239
+ try {
240
+ await fs.chown(destPath, entry.uid, entry.gid);
241
+ }
242
+ catch {
243
+ // Ignore ownership errors
244
+ }
245
+ }
246
+ // Set modification time
247
+ try {
248
+ const mtime = new Date(entry.mtime * 1000);
249
+ await fs.utimes(destPath, mtime, mtime);
250
+ }
251
+ catch {
252
+ // Ignore time errors
253
+ }
254
+ extractedEntries.push(entryForFilter);
255
+ }
256
+ return extractedEntries;
257
+ }
258
+ /**
259
+ * Extract archive to memory (no disk writes)
260
+ */
261
+ export async function extractToMemory(file, options = {}) {
262
+ const { strip = 0, filter } = options;
263
+ const inputStream = createReadStream(file);
264
+ const unxzStream = createUnxz();
265
+ const tarUnpack = new TarUnpack();
266
+ await pipeline(inputStream, unxzStream, tarUnpack);
267
+ return tarUnpack.entries
268
+ .map((entry) => ({
269
+ ...entry,
270
+ name: stripPath(entry.name, strip),
271
+ }))
272
+ .filter((entry) => entry.name && (!filter || filter(entry)));
273
+ }
274
+ //# sourceMappingURL=extract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/node/extract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Node.js API for tar.xz archives
3
+ */
4
+ export { create } from './create.js';
5
+ export { extract, extractToMemory } from './extract.js';
6
+ export { list } from './list.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Node.js API for tar.xz archives
3
+ */
4
+ export { create } from './create.js';
5
+ export { extract, extractToMemory } from './extract.js';
6
+ export { list } from './list.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Node.js TAR listing with XZ decompression
3
+ */
4
+ import { type ListOptions, type TarEntry } from '../types.js';
5
+ /**
6
+ * List contents of a tar.xz archive
7
+ *
8
+ * @param options - List options
9
+ * @returns Promise with list of entries
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const entries = await list({ file: 'archive.tar.xz' });
14
+ * for (const entry of entries) {
15
+ * console.log(entry.name, entry.size);
16
+ * }
17
+ * ```
18
+ */
19
+ export declare function list(options: ListOptions): Promise<TarEntry[]>;
20
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/node/list.ts"],"names":[],"mappings":"AAAA;;GAEG;AAeH,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAgB,MAAM,aAAa,CAAC;AAsG5E;;;;;;;;;;;;;GAaG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAUpE"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Node.js TAR listing with XZ decompression
3
+ */
4
+ import { createReadStream } from 'node:fs';
5
+ import { Writable } from 'node:stream';
6
+ import { pipeline } from 'node:stream/promises';
7
+ import { createUnxz } from 'node-liblzma';
8
+ import { applyPaxAttributes, BLOCK_SIZE, calculatePadding, isEmptyBlock, parseHeader, parsePaxData, } from '../tar/index.js';
9
+ import { TarEntryType } from '../types.js';
10
+ /**
11
+ * Writable stream that lists TAR entries without extracting content
12
+ */
13
+ class TarList extends Writable {
14
+ buffer = Buffer.alloc(0);
15
+ bytesToSkip = 0;
16
+ paxAttrs = null;
17
+ emptyBlockCount = 0;
18
+ entries = [];
19
+ _write(chunk, _encoding, callback) {
20
+ this.buffer = Buffer.concat([this.buffer, chunk]);
21
+ try {
22
+ this.processBuffer();
23
+ callback();
24
+ }
25
+ catch (error) {
26
+ callback(error);
27
+ }
28
+ }
29
+ processBuffer() {
30
+ while (this.buffer.length > 0) {
31
+ // Skip content and padding
32
+ if (this.bytesToSkip > 0) {
33
+ const skip = Math.min(this.bytesToSkip, this.buffer.length);
34
+ this.buffer = this.buffer.subarray(skip);
35
+ this.bytesToSkip -= skip;
36
+ continue;
37
+ }
38
+ // Need a full block for header
39
+ if (this.buffer.length < BLOCK_SIZE) {
40
+ break;
41
+ }
42
+ const headerBlock = this.buffer.subarray(0, BLOCK_SIZE);
43
+ this.buffer = this.buffer.subarray(BLOCK_SIZE);
44
+ // Check for end-of-archive
45
+ if (isEmptyBlock(headerBlock)) {
46
+ this.emptyBlockCount++;
47
+ if (this.emptyBlockCount >= 2) {
48
+ break;
49
+ }
50
+ continue;
51
+ }
52
+ this.emptyBlockCount = 0;
53
+ // Parse header
54
+ let entry = parseHeader(headerBlock);
55
+ if (!entry) {
56
+ continue;
57
+ }
58
+ // Handle PAX headers
59
+ if (entry.type === TarEntryType.PAX_HEADER) {
60
+ const paxSize = entry.size;
61
+ const paxPadding = calculatePadding(paxSize);
62
+ const totalNeeded = paxSize + paxPadding;
63
+ if (this.buffer.length < totalNeeded) {
64
+ this.buffer = Buffer.concat([headerBlock, this.buffer]);
65
+ break;
66
+ }
67
+ const paxData = this.buffer.subarray(0, paxSize);
68
+ this.buffer = this.buffer.subarray(paxSize + paxPadding);
69
+ this.paxAttrs = parsePaxData(paxData);
70
+ continue;
71
+ }
72
+ if (entry.type === TarEntryType.PAX_GLOBAL) {
73
+ this.bytesToSkip = entry.size + calculatePadding(entry.size);
74
+ continue;
75
+ }
76
+ // Apply PAX attributes if present
77
+ if (this.paxAttrs) {
78
+ entry = applyPaxAttributes(entry, this.paxAttrs);
79
+ this.paxAttrs = null;
80
+ }
81
+ // Add entry to list
82
+ this.entries.push(entry);
83
+ // Skip content
84
+ if (entry.size > 0) {
85
+ this.bytesToSkip = entry.size + calculatePadding(entry.size);
86
+ }
87
+ }
88
+ }
89
+ _final(callback) {
90
+ callback();
91
+ }
92
+ }
93
+ /**
94
+ * List contents of a tar.xz archive
95
+ *
96
+ * @param options - List options
97
+ * @returns Promise with list of entries
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * const entries = await list({ file: 'archive.tar.xz' });
102
+ * for (const entry of entries) {
103
+ * console.log(entry.name, entry.size);
104
+ * }
105
+ * ```
106
+ */
107
+ export async function list(options) {
108
+ const { file } = options;
109
+ const inputStream = createReadStream(file);
110
+ const unxzStream = createUnxz();
111
+ const tarList = new TarList();
112
+ await pipeline(inputStream, unxzStream, tarList);
113
+ return tarList.entries;
114
+ }
115
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/node/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * TAR header checksum calculation
3
+ *
4
+ * The checksum is a simple sum of all bytes in the header block,
5
+ * with the 8-byte checksum field (bytes 148-155) treated as spaces (0x20).
6
+ */
7
+ /** Offset of checksum field in TAR header */
8
+ export declare const CHECKSUM_OFFSET = 148;
9
+ /** Length of checksum field */
10
+ export declare const CHECKSUM_LENGTH = 8;
11
+ /**
12
+ * Calculate TAR header checksum
13
+ *
14
+ * @param header - 512-byte TAR header block
15
+ * @returns Checksum value (sum of unsigned bytes, checksum field as spaces)
16
+ */
17
+ export declare function calculateChecksum(header: Uint8Array): number;
18
+ /**
19
+ * Verify TAR header checksum
20
+ *
21
+ * @param header - 512-byte TAR header block
22
+ * @returns true if checksum is valid
23
+ */
24
+ export declare function verifyChecksum(header: Uint8Array): boolean;
25
+ /**
26
+ * Write checksum to TAR header
27
+ *
28
+ * @param header - 512-byte TAR header block (will be modified)
29
+ */
30
+ export declare function writeChecksum(header: Uint8Array): void;
31
+ /**
32
+ * Parse octal number from header field
33
+ *
34
+ * @param header - Header buffer
35
+ * @param offset - Field offset
36
+ * @param length - Field length
37
+ * @returns Parsed number
38
+ */
39
+ export declare function parseOctal(header: Uint8Array, offset: number, length: number): number;
40
+ //# sourceMappingURL=checksum.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checksum.d.ts","sourceRoot":"","sources":["../../src/tar/checksum.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,6CAA6C;AAC7C,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC,+BAA+B;AAC/B,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAiB5D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAK1D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAgBtD;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAsBrF"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * TAR header checksum calculation
3
+ *
4
+ * The checksum is a simple sum of all bytes in the header block,
5
+ * with the 8-byte checksum field (bytes 148-155) treated as spaces (0x20).
6
+ */
7
+ /** Offset of checksum field in TAR header */
8
+ export const CHECKSUM_OFFSET = 148;
9
+ /** Length of checksum field */
10
+ export const CHECKSUM_LENGTH = 8;
11
+ /**
12
+ * Calculate TAR header checksum
13
+ *
14
+ * @param header - 512-byte TAR header block
15
+ * @returns Checksum value (sum of unsigned bytes, checksum field as spaces)
16
+ */
17
+ export function calculateChecksum(header) {
18
+ if (header.length !== 512) {
19
+ throw new Error(`Invalid TAR header length: ${header.length}, expected 512`);
20
+ }
21
+ let sum = 0;
22
+ for (let i = 0; i < 512; i++) {
23
+ // Treat checksum field (bytes 148-155) as spaces (0x20 = 32)
24
+ if (i >= CHECKSUM_OFFSET && i < CHECKSUM_OFFSET + CHECKSUM_LENGTH) {
25
+ sum += 0x20;
26
+ }
27
+ else {
28
+ sum += header[i];
29
+ }
30
+ }
31
+ return sum;
32
+ }
33
+ /**
34
+ * Verify TAR header checksum
35
+ *
36
+ * @param header - 512-byte TAR header block
37
+ * @returns true if checksum is valid
38
+ */
39
+ export function verifyChecksum(header) {
40
+ const calculated = calculateChecksum(header);
41
+ const stored = parseOctal(header, CHECKSUM_OFFSET, CHECKSUM_LENGTH);
42
+ return calculated === stored;
43
+ }
44
+ /**
45
+ * Write checksum to TAR header
46
+ *
47
+ * @param header - 512-byte TAR header block (will be modified)
48
+ */
49
+ export function writeChecksum(header) {
50
+ // First, fill checksum field with spaces
51
+ for (let i = 0; i < CHECKSUM_LENGTH; i++) {
52
+ header[CHECKSUM_OFFSET + i] = 0x20;
53
+ }
54
+ // Calculate checksum
55
+ const checksum = calculateChecksum(header);
56
+ // Write checksum as 6-digit octal, space, null
57
+ const octalStr = checksum.toString(8).padStart(6, '0');
58
+ for (let i = 0; i < 6; i++) {
59
+ header[CHECKSUM_OFFSET + i] = octalStr.charCodeAt(i);
60
+ }
61
+ header[CHECKSUM_OFFSET + 6] = 0x00; // null terminator
62
+ header[CHECKSUM_OFFSET + 7] = 0x20; // space
63
+ }
64
+ /**
65
+ * Parse octal number from header field
66
+ *
67
+ * @param header - Header buffer
68
+ * @param offset - Field offset
69
+ * @param length - Field length
70
+ * @returns Parsed number
71
+ */
72
+ export function parseOctal(header, offset, length) {
73
+ let str = '';
74
+ for (let i = 0; i < length; i++) {
75
+ const byte = header[offset + i];
76
+ // Stop at null or space
77
+ if (byte === 0 || byte === 0x20) {
78
+ break;
79
+ }
80
+ str += String.fromCharCode(byte);
81
+ }
82
+ if (str.length === 0) {
83
+ return 0;
84
+ }
85
+ const value = Number.parseInt(str, 8);
86
+ if (Number.isNaN(value)) {
87
+ return 0;
88
+ }
89
+ return value;
90
+ }
91
+ //# sourceMappingURL=checksum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checksum.js","sourceRoot":"","sources":["../../src/tar/checksum.ts"],"names":[],"mappings":"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"}