11cb0ef41Sopenharmony_ci'use strict' 21cb0ef41Sopenharmony_ciconst { Minipass } = require('minipass') 31cb0ef41Sopenharmony_ciconst normPath = require('./normalize-windows-path.js') 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ciconst SLURP = Symbol('slurp') 61cb0ef41Sopenharmony_cimodule.exports = class ReadEntry extends Minipass { 71cb0ef41Sopenharmony_ci constructor (header, ex, gex) { 81cb0ef41Sopenharmony_ci super() 91cb0ef41Sopenharmony_ci // read entries always start life paused. this is to avoid the 101cb0ef41Sopenharmony_ci // situation where Minipass's auto-ending empty streams results 111cb0ef41Sopenharmony_ci // in an entry ending before we're ready for it. 121cb0ef41Sopenharmony_ci this.pause() 131cb0ef41Sopenharmony_ci this.extended = ex 141cb0ef41Sopenharmony_ci this.globalExtended = gex 151cb0ef41Sopenharmony_ci this.header = header 161cb0ef41Sopenharmony_ci this.startBlockSize = 512 * Math.ceil(header.size / 512) 171cb0ef41Sopenharmony_ci this.blockRemain = this.startBlockSize 181cb0ef41Sopenharmony_ci this.remain = header.size 191cb0ef41Sopenharmony_ci this.type = header.type 201cb0ef41Sopenharmony_ci this.meta = false 211cb0ef41Sopenharmony_ci this.ignore = false 221cb0ef41Sopenharmony_ci switch (this.type) { 231cb0ef41Sopenharmony_ci case 'File': 241cb0ef41Sopenharmony_ci case 'OldFile': 251cb0ef41Sopenharmony_ci case 'Link': 261cb0ef41Sopenharmony_ci case 'SymbolicLink': 271cb0ef41Sopenharmony_ci case 'CharacterDevice': 281cb0ef41Sopenharmony_ci case 'BlockDevice': 291cb0ef41Sopenharmony_ci case 'Directory': 301cb0ef41Sopenharmony_ci case 'FIFO': 311cb0ef41Sopenharmony_ci case 'ContiguousFile': 321cb0ef41Sopenharmony_ci case 'GNUDumpDir': 331cb0ef41Sopenharmony_ci break 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci case 'NextFileHasLongLinkpath': 361cb0ef41Sopenharmony_ci case 'NextFileHasLongPath': 371cb0ef41Sopenharmony_ci case 'OldGnuLongPath': 381cb0ef41Sopenharmony_ci case 'GlobalExtendedHeader': 391cb0ef41Sopenharmony_ci case 'ExtendedHeader': 401cb0ef41Sopenharmony_ci case 'OldExtendedHeader': 411cb0ef41Sopenharmony_ci this.meta = true 421cb0ef41Sopenharmony_ci break 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci // NOTE: gnutar and bsdtar treat unrecognized types as 'File' 451cb0ef41Sopenharmony_ci // it may be worth doing the same, but with a warning. 461cb0ef41Sopenharmony_ci default: 471cb0ef41Sopenharmony_ci this.ignore = true 481cb0ef41Sopenharmony_ci } 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci this.path = normPath(header.path) 511cb0ef41Sopenharmony_ci this.mode = header.mode 521cb0ef41Sopenharmony_ci if (this.mode) { 531cb0ef41Sopenharmony_ci this.mode = this.mode & 0o7777 541cb0ef41Sopenharmony_ci } 551cb0ef41Sopenharmony_ci this.uid = header.uid 561cb0ef41Sopenharmony_ci this.gid = header.gid 571cb0ef41Sopenharmony_ci this.uname = header.uname 581cb0ef41Sopenharmony_ci this.gname = header.gname 591cb0ef41Sopenharmony_ci this.size = header.size 601cb0ef41Sopenharmony_ci this.mtime = header.mtime 611cb0ef41Sopenharmony_ci this.atime = header.atime 621cb0ef41Sopenharmony_ci this.ctime = header.ctime 631cb0ef41Sopenharmony_ci this.linkpath = normPath(header.linkpath) 641cb0ef41Sopenharmony_ci this.uname = header.uname 651cb0ef41Sopenharmony_ci this.gname = header.gname 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci if (ex) { 681cb0ef41Sopenharmony_ci this[SLURP](ex) 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci if (gex) { 711cb0ef41Sopenharmony_ci this[SLURP](gex, true) 721cb0ef41Sopenharmony_ci } 731cb0ef41Sopenharmony_ci } 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci write (data) { 761cb0ef41Sopenharmony_ci const writeLen = data.length 771cb0ef41Sopenharmony_ci if (writeLen > this.blockRemain) { 781cb0ef41Sopenharmony_ci throw new Error('writing more to entry than is appropriate') 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci const r = this.remain 821cb0ef41Sopenharmony_ci const br = this.blockRemain 831cb0ef41Sopenharmony_ci this.remain = Math.max(0, r - writeLen) 841cb0ef41Sopenharmony_ci this.blockRemain = Math.max(0, br - writeLen) 851cb0ef41Sopenharmony_ci if (this.ignore) { 861cb0ef41Sopenharmony_ci return true 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci if (r >= writeLen) { 901cb0ef41Sopenharmony_ci return super.write(data) 911cb0ef41Sopenharmony_ci } 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci // r < writeLen 941cb0ef41Sopenharmony_ci return super.write(data.slice(0, r)) 951cb0ef41Sopenharmony_ci } 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci [SLURP] (ex, global) { 981cb0ef41Sopenharmony_ci for (const k in ex) { 991cb0ef41Sopenharmony_ci // we slurp in everything except for the path attribute in 1001cb0ef41Sopenharmony_ci // a global extended header, because that's weird. 1011cb0ef41Sopenharmony_ci if (ex[k] !== null && ex[k] !== undefined && 1021cb0ef41Sopenharmony_ci !(global && k === 'path')) { 1031cb0ef41Sopenharmony_ci this[k] = k === 'path' || k === 'linkpath' ? normPath(ex[k]) : ex[k] 1041cb0ef41Sopenharmony_ci } 1051cb0ef41Sopenharmony_ci } 1061cb0ef41Sopenharmony_ci } 1071cb0ef41Sopenharmony_ci} 108