diff --git a/archive/_common.ts b/archive/_common.ts index ab0ddeb7e0d3..d333c4bd4407 100644 --- a/archive/_common.ts +++ b/archive/_common.ts @@ -71,7 +71,7 @@ struct posix_header { // byte offset }; */ -export const ustarStructure = [ +export const USTAR_STRUCTURE = [ { field: "fileName", length: 100, @@ -138,7 +138,7 @@ export const ustarStructure = [ }, ] as const; -export type UstarFields = (typeof ustarStructure)[number]["field"]; +export type UstarFields = (typeof USTAR_STRUCTURE)[number]["field"]; export async function readBlock( reader: Reader, diff --git a/archive/tar.ts b/archive/tar.ts index 8b56b9fa1e8d..afb5bc168a78 100644 --- a/archive/tar.ts +++ b/archive/tar.ts @@ -33,7 +33,7 @@ import { type TarInfo, type TarMeta, type TarOptions, - ustarStructure, + USTAR_STRUCTURE, } from "./_common.ts"; import type { Reader } from "../io/types.ts"; import { MultiReader } from "../io/multi_reader.ts"; @@ -43,7 +43,7 @@ import { HEADER_LENGTH } from "./_common.ts"; export type { TarInfo, TarMeta, TarOptions }; -const USTAR_MAGIC_HEADER = "ustar\u000000"; +const USTAR_MAGIC_HEADER = "ustar\u000000" as const; /** * Simple file reader @@ -67,31 +67,31 @@ class FileReader implements Reader { } /** - * Initialize Uint8Array of the specified length filled with 0 - * @param length + * Pads a number with leading zeros to a specified number of bytes. + * + * @param num The number to pad. + * @param bytes The number of bytes to pad the number to. + * @returns The padded number as a string. */ -function clean(length: number): Uint8Array { - const buffer = new Uint8Array(length); - return buffer; -} - -function pad(num: number, bytes: number, base = 8): string { - const numString = num.toString(base); - return "000000000000".slice(numString.length + 12 - bytes) + numString; +function pad(num: number, bytes: number): string { + return num.toString(8).padStart(bytes, "0"); } /** - * Create header for a file in a tar archive + * Formats the header data for a tar file entry. + * + * @param data The data object containing the values for the tar header fields. + * @returns The formatted header data as a Uint8Array. */ function formatHeader(data: TarData): Uint8Array { const encoder = new TextEncoder(); - const buffer = clean(HEADER_LENGTH); + const buffer = new Uint8Array(HEADER_LENGTH); let offset = 0; - ustarStructure.forEach(function (value) { - const entry = encoder.encode(data[value.field as keyof TarData] || ""); + for (const { field, length } of USTAR_STRUCTURE) { + const entry = encoder.encode(data[field as keyof TarData] || ""); buffer.set(entry, offset); - offset += value.length; // space it out with nulls - }); + offset += length; + } return buffer; } @@ -324,7 +324,7 @@ export class Tar { assert(tarData.fileSize !== undefined, "fileSize must be set"); readers.push( new Buffer( - clean( + new Uint8Array( HEADER_LENGTH - (parseInt(tarData.fileSize, 8) % HEADER_LENGTH || HEADER_LENGTH), ), @@ -333,7 +333,7 @@ export class Tar { }); // append 2 empty records - readers.push(new Buffer(clean(HEADER_LENGTH * 2))); + readers.push(new Buffer(new Uint8Array(HEADER_LENGTH * 2))); return new MultiReader(readers); } } diff --git a/archive/untar.ts b/archive/untar.ts index 9e550a272ccc..fdda9b3b506b 100644 --- a/archive/untar.ts +++ b/archive/untar.ts @@ -34,8 +34,8 @@ import { HEADER_LENGTH, readBlock, type TarMeta, + USTAR_STRUCTURE, type UstarFields, - ustarStructure, } from "./_common.ts"; import { readAll } from "../io/read_all.ts"; import type { Reader } from "../io/types.ts"; @@ -57,13 +57,15 @@ export type TarHeader = { const initialChecksum = 8 * 32; /** - * Remove the trailing null codes - * @param buffer + * Trims a Uint8Array by removing any trailing zero bytes. + * + * @param buffer The Uint8Array to trim. + * @returns A new Uint8Array with trailing zero bytes removed, or the original + * buffer if no trailing zero bytes are found. */ function trim(buffer: Uint8Array): Uint8Array { - const index = buffer.findIndex((v): boolean => v === 0); - if (index < 0) return buffer; - return buffer.subarray(0, index); + const index = buffer.indexOf(0); + return index === -1 ? buffer : buffer.subarray(0, index); } /** @@ -73,7 +75,7 @@ function trim(buffer: Uint8Array): Uint8Array { function parseHeader(buffer: Uint8Array): TarHeader { const data = {} as TarHeader; let offset = 0; - ustarStructure.forEach(function (value) { + USTAR_STRUCTURE.forEach(function (value) { const arr = buffer.subarray(offset, offset + value.length); data[value.field] = arr; offset += value.length; @@ -262,22 +264,20 @@ export class Untar { if (fileNamePrefix.byteLength > 0) { meta.fileName = decoder.decode(fileNamePrefix) + "/" + meta.fileName; } - ( - ["fileMode", "mtime", "uid", "gid"] as ["fileMode", "mtime", "uid", "gid"] - ).forEach((key) => { - const arr = trim(header[key]); - if (arr.byteLength > 0) { - meta[key] = parseInt(decoder.decode(arr), 8); - } - }); - (["owner", "group", "type"] as ["owner", "group", "type"]).forEach( - (key) => { + (["fileMode", "mtime", "uid", "gid"] as const) + .forEach((key) => { + const arr = trim(header[key]); + if (arr.byteLength > 0) { + meta[key] = parseInt(decoder.decode(arr), 8); + } + }); + (["owner", "group", "type"] as const) + .forEach((key) => { const arr = trim(header[key]); if (arr.byteLength > 0) { meta[key] = decoder.decode(arr); } - }, - ); + }); meta.fileSize = parseInt(decoder.decode(header.fileSize), 8); meta.type = FileTypes[parseInt(meta.type!)] ?? meta.type;