diff --git a/extract.js b/extract.js index f656d49..d685bb3 100644 --- a/extract.js +++ b/extract.js @@ -53,6 +53,8 @@ var Extract = function(opts) { this._destroyed = false this._pax = null this._paxGlobal = null + this._gnuLongPath = null + this._gnuLongLinkPath = null var self = this var b = self._buffer @@ -96,6 +98,20 @@ var Extract = function(opts) { onstreamend() } + var ongnulongpath = function() { + var size = self._header.size + this._gnuLongPath = headers.decodeLongPath(b.slice(0, size)) + b.consume(size) + onstreamend() + } + + var ongnulonglinkpath = function() { + var size = self._header.size + this._gnuLongLinkPath = headers.decodeLongPath(b.slice(0, size)) + b.consume(size) + onstreamend() + } + var onheader = function() { var offset = self._offset var header @@ -111,6 +127,16 @@ var Extract = function(opts) { oncontinue() return } + if (header.type === 'gnu-long-path') { + self._parse(header.size, ongnulongpath) + oncontinue() + return + } + if (header.type === 'gnu-long-link-path') { + self._parse(header.size, ongnulonglinkpath) + oncontinue() + return + } if (header.type === 'pax-global-header') { self._parse(header.size, onpaxglobalheader) oncontinue() @@ -122,6 +148,16 @@ var Extract = function(opts) { return } + if (self._gnuLongPath) { + header.name = self._gnuLongPath + self._gnuLongPath = null + } + + if (self._gnuLongLinkPath) { + header.linkname = self._gnuLongLinkPath + self._gnuLongLinkPath = null + } + if (self._pax) { self._header = header = mixinPax(header, self._pax) self._pax = null diff --git a/headers.js b/headers.js index df8deae..19c8bf1 100644 --- a/headers.js +++ b/headers.js @@ -34,6 +34,11 @@ var toType = function(flag) { return 'pax-header' case 55: return 'pax-global-header' + case 27: + return 'gnu-long-link-path' + case 28: + case 30: + return 'gnu-long-path' } return null @@ -110,6 +115,10 @@ var addLength = function(str) { return (len+digits)+str } +exports.decodeLongPath = function(buf) { + return decodeStr(buf, 0, buf.length) +} + exports.encodePax = function(opts) { // TODO: encode more stuff in pax var result = '' if (opts.name) result += addLength(' path='+opts.name+'\n') diff --git a/test/extract.js b/test/extract.js index 4bec7a4..d5ac947 100644 --- a/test/extract.js +++ b/test/extract.js @@ -435,3 +435,21 @@ test('space prefixed', function(t) { extract.end(fs.readFileSync(fixtures.SPACE_TAR_GZ)) }) + +test('gnu long path', function(t) { + t.plan(2) + + var extract = tar.extract() + + extract.on('entry', function(header, stream, callback) { + t.ok(header.name.length > 100) + callback() + }) + + extract.on('finish', function() { + t.ok(true) + }) + + extract.end(fs.readFileSync(fixtures.GNU_LONG_PATH)) + +}) \ No newline at end of file diff --git a/test/fixtures/gnu-long-path.tar b/test/fixtures/gnu-long-path.tar new file mode 100644 index 0000000..efb204c Binary files /dev/null and b/test/fixtures/gnu-long-path.tar differ diff --git a/test/fixtures/index.js b/test/fixtures/index.js index d058613..1e5d37e 100644 --- a/test/fixtures/index.js +++ b/test/fixtures/index.js @@ -9,3 +9,4 @@ exports.UNICODE_TAR = path.join(__dirname, 'unicode.tar') exports.NAME_IS_100_TAR = path.join(__dirname, 'name-is-100.tar') exports.INVALID_TGZ = path.join(__dirname, 'invalid.tgz') exports.SPACE_TAR_GZ = path.join(__dirname, 'space.tar') +exports.GNU_LONG_PATH = path.join(__dirname, 'gnu-long-path.tar') \ No newline at end of file