@obsidize/tar-browserify
Version:
Browser-based tar utility for packing and unpacking tar files (stream-capable)
207 lines (206 loc) • 6.85 kB
JavaScript
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,
};
}
}