From 6af6a7123c80e483e7849951d39beb93db14567a Mon Sep 17 00:00:00 2001 From: Mathias Buus Date: Mon, 23 Dec 2013 01:35:28 +0100 Subject: [PATCH] using pax headers for long/unicode filenames --- extract.js | 24 ++++++++++++++++++++++++ pack.js | 42 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/extract.js b/extract.js index fbc0b9a..f6e7b51 100644 --- a/extract.js +++ b/extract.js @@ -16,6 +16,12 @@ var emptyStream = function() { return s; }; +var mixinPax = function(header, pax) { + if (pax.path) header.name = pax.path; + if (pax.linkpath) header.linkname = pax.linkpath; + return header; +}; + var Extract = function(opts) { if (!(this instanceof Extract)) return new Extract(opts); stream.Writable.call(this, opts); @@ -29,6 +35,7 @@ var Extract = function(opts) { this._cb = null; this._locked = false; this._destroyed = false; + this._pax = null; var self = this; var b = self._buffer; @@ -57,6 +64,13 @@ var Extract = function(opts) { oncontinue(); }; + var onpaxheader = function() { + var size = self._header.size; + self._pax = headers.decodePax(b.slice(0, size)); + b.consume(size); + onstreamend(); + }; + var onheader = function() { var header = self._header = headers.decode(b.slice(0, 512)); b.consume(512); @@ -66,6 +80,16 @@ var Extract = function(opts) { oncontinue(); return; } + if (header.type === 'pax-header') { + self._parse(header.size, onpaxheader); + oncontinue(); + return; + } + + if (self._pax) { + self._header = header = mixinPax(header, self._pax); + self._pax = null; + } self._locked = true; diff --git a/pack.js b/pack.js index abb05ee..a4ad380 100644 --- a/pack.js +++ b/pack.js @@ -70,19 +70,19 @@ Pack.prototype.entry = function(header, buffer, callback) { if (typeof buffer === 'string') buffer = new Buffer(buffer); if (Buffer.isBuffer(buffer)) { header.size = buffer.length; - this.push(headers.encode(header)); + this._encode(header); this.push(buffer); overflow(self, header.size); process.nextTick(callback); return; } if (header.type !== 'file' && header.type !== 'contigious-file') { - this.push(headers.encode(header)); + this._encode(header); process.nextTick(callback); return; } - this.push(headers.encode(header)); + this._encode(header); this._stream = stream; var sink = new Sink(this); @@ -129,6 +129,42 @@ Pack.prototype.destroy = function(err) { if (this._stream && this._stream.destroy) this._stream.destroy(); }; +Pack.prototype._encode = function(header) { + var buf = headers.encode(header); + if (buf) this.push(buf); + else this._encodePax(header); +}; + +Pack.prototype._encodePax = function(header) { + var paxHeader = headers.encodePax({ + name: header.name, + linkname: header.linkname + }); + + var newHeader = { + name: 'PaxHeader', + mode: header.mode, + uid: header.uid, + gid: header.gid, + size: paxHeader.length, + mtime: header.mtime, + type: 'pax-header', + linkname: header.linkname && 'PaxHeader', + uname: header.uname, + gname: header.gname, + devmajor: header.devmajor, + devminor: header.devminor + }; + + this.push(headers.encode(newHeader)); + this.push(paxHeader); + overflow(this, paxHeader.length); + + newHeader.size = header.size; + newHeader.type = header.type; + this.push(headers.encode(newHeader)); +}; + Pack.prototype._read = function(n) { var drain = this._drain; this._drain = noop;