UNPKG

@obsidize/tar-browserify

Version:

Browser-based tar utility for packing and unpacking tar files (stream-capable)

207 lines (206 loc) 6.85 kB
import { Constants } from '../../common/constants'; import { TarUtility } from '../../common/tar-utility'; import { TarHeaderUtility } from '../tar-header-utility'; import { UstarHeaderField } from './ustar-header-field'; import { UstarHeaderLinkIndicatorType } from './ustar-header-link-indicator-type'; /** * Facade over a backing Uint8Array buffer to consume/edit header data * at a specific location in the buffer. * * Does not perform any mutations or reads on creation, and * lazy loads/sets data via getters and setters. */ export class UstarHeader { constructor(attributes = {}) { this.mValueMap = UstarHeader.defaultValues(); this.update(attributes); } static isUstarHeader(value) { return !!(value && value instanceof UstarHeader); } /** * @returns A new `UstarHeader` instance based on the given attributes (if they are a POJO). * Note that if the given value is already a UstarHeader instance, this will return it as-is. */ static fromAttributes(attributes) { return UstarHeader.isUstarHeader(attributes) ? attributes : new UstarHeader(attributes); } /** * Short-hand for constructing a new `UstarHeader` and immediately calling `toUint8Array()` on it */ static serializeAttributes(attributes) { return UstarHeader.fromAttributes(attributes).toUint8Array(); } /** * Parses out a UstarHeader instance from the given input buffer, at the given offset. * The given offset must be a multiple of SECTOR_SIZE. * * If the sector at the given offset is not marked with a ustar indicator, * this will return null. */ static deserialize(input, offset = 0) { if (!TarHeaderUtility.isUstarSector(input, offset)) { return null; } const attributes = {}; for (const field of TarHeaderUtility.ALL_FIELDS) { attributes[field.name] = field.readFrom(input, offset); } return new UstarHeader(attributes); } static defaultValues() { return { fileName: '', fileMode: Constants.FILE_MODE_DEFAULT, groupUserId: 0, ownerUserId: 0, fileSize: 0, lastModified: TarUtility.getUstarTimestamp(), headerChecksum: 0, linkedFileName: '', typeFlag: UstarHeaderLinkIndicatorType.NORMAL_FILE, ustarIndicator: Constants.USTAR_INDICATOR_VALUE, ustarVersion: Constants.USTAR_VERSION_VALUE, ownerUserName: '', ownerGroupName: '', deviceMajorNumber: '00', deviceMinorNumber: '00', fileNamePrefix: '', }; } get fileName() { return this.mValueMap.fileName; } set fileName(value) { this.mValueMap.fileName = value; } get fileMode() { return this.mValueMap.fileMode; } set fileMode(value) { this.mValueMap.fileMode = value; } get ownerUserId() { return this.mValueMap.ownerUserId; } set ownerUserId(value) { this.mValueMap.ownerUserId = value; } get groupUserId() { return this.mValueMap.groupUserId; } set groupUserId(value) { this.mValueMap.groupUserId = value; } get fileSize() { return this.mValueMap.fileSize; } set fileSize(value) { this.mValueMap.fileSize = value; } get lastModified() { return this.mValueMap.lastModified; } set lastModified(value) { this.mValueMap.lastModified = TarUtility.sanitizeDateTimeAsUstar(value); } get headerChecksum() { return this.mValueMap.headerChecksum; } set headerChecksum(value) { this.mValueMap.headerChecksum = value; } get linkedFileName() { return this.mValueMap.linkedFileName; } set linkedFileName(value) { this.mValueMap.linkedFileName = value; } get typeFlag() { return this.mValueMap.typeFlag; } set typeFlag(value) { this.mValueMap.typeFlag = value; } get ustarIndicator() { return this.mValueMap.ustarIndicator; } get ustarVersion() { return this.mValueMap.ustarVersion; } set ustarVersion(value) { this.mValueMap.ustarVersion = value; } get ownerUserName() { return this.mValueMap.ownerUserName; } set ownerUserName(value) { this.mValueMap.ownerUserName = value; } get ownerGroupName() { return this.mValueMap.ownerGroupName; } set ownerGroupName(value) { this.mValueMap.ownerGroupName = value; } get deviceMajorNumber() { return this.mValueMap.deviceMajorNumber; } set deviceMajorNumber(value) { this.mValueMap.deviceMajorNumber = value; } get deviceMinorNumber() { return this.mValueMap.deviceMinorNumber; } set deviceMinorNumber(value) { this.mValueMap.deviceMinorNumber = value; } get fileNamePrefix() { return this.mValueMap.fileNamePrefix; } set fileNamePrefix(value) { this.mValueMap.fileNamePrefix = value; } get isPaxHeader() { return this.isLocalPaxHeader || this.isGlobalPaxHeader; } get isGlobalPaxHeader() { return this.typeFlag === UstarHeaderLinkIndicatorType.GLOBAL_EXTENDED_HEADER; } get isLocalPaxHeader() { return this.typeFlag === UstarHeaderLinkIndicatorType.LOCAL_EXTENDED_HEADER; } get isFileHeader() { return TarHeaderUtility.isTarHeaderLinkIndicatorTypeFile(this.typeFlag); } get isDirectoryHeader() { return TarHeaderUtility.isTarHeaderLinkIndicatorTypeDirectory(this.typeFlag); } update(attributes) { Object.assign(this.mValueMap, attributes); return this; } toAttributes() { return Object.assign({}, this.mValueMap); } toUint8Array() { const result = new Uint8Array(Constants.HEADER_SIZE); let checksum = TarHeaderUtility.CHECKSUM_SEED; for (const field of TarHeaderUtility.CHECKSUM_FIELDS) { field.writeTo(result, 0, this.mValueMap[field.name]); checksum += field.calculateChecksum(result); } this.headerChecksum = checksum; UstarHeaderField.headerChecksum.writeTo(result, 0, checksum); return result; } toJSON() { const attributes = this.toAttributes(); const bytes = this.toUint8Array(); const buffer = TarUtility.getDebugBufferJson(bytes); return { attributes, buffer, }; } }