update style

This commit is contained in:
Mathias Buus 2014-09-23 07:30:58 -07:00
parent 0b57f1c1c6
commit bc15a53e8b
5 changed files with 511 additions and 509 deletions

100
README.md
View file

@ -2,7 +2,9 @@
tar-stream is a streaming tar parser and generator and nothing else. It is streams2 and operates purely using streams which means you can easily extract/parse tarballs without ever hitting the file system.
npm install tar-stream
```
npm install tar-stream
```
[![build status](https://secure.travis-ci.org/mafintosh/tar-stream.png)](http://travis-ci.org/mafintosh/tar-stream)
@ -22,22 +24,22 @@ If you want to pack/unpack directories on the file system check out [tar-fs](htt
To create a pack stream use `tar.pack()` and call `pack.entry(header, [callback])` to add tar entries.
``` js
var tar = require('tar-stream');
var pack = tar.pack(); // p is a streams2 stream
var tar = require('tar-stream')
var pack = tar.pack() // p is a streams2 stream
// add a file called my-test.txt with the content "Hello World!"
pack.entry({ name: 'my-test.txt' }, 'Hello World!');
pack.entry({ name: 'my-test.txt' }, 'Hello World!')
// add a file called my-stream-test.txt from a stream
var entry = pack.entry({ name: 'my-stream-test.txt' }, function(err) {
// the stream was added
// no more entries
pack.finalize();
});
myStream.pipe(entry);
// the stream was added
// no more entries
pack.finalize()
})
myStream.pipe(entry)
// pipe the pack stream somewhere
pack.pipe(process.stdout);
pack.pipe(process.stdout)
```
## Extracting
@ -45,24 +47,24 @@ pack.pipe(process.stdout);
To extract a stream use `tar.extract()` and listen for `extract.on('entry', header, stream, callback)`
``` js
var extract = tar.extract();
var extract = tar.extract()
extract.on('entry', function(header, stream, callback) {
// header is the tar header
// stream is the content body (might be an empty stream)
// call next when you are done with this entry
// header is the tar header
// stream is the content body (might be an empty stream)
// call next when you are done with this entry
stream.resume(); // just auto drain the stream
stream.on('end', function() {
callback(); // ready for next entry
});
});
stream.resume() // just auto drain the stream
stream.on('end', function() {
callback() // ready for next entry
})
})
extract.on('finish', function() {
// all entries read
});
// all entries read
})
pack.pipe(extract);
pack.pipe(extract)
```
## Headers
@ -72,20 +74,20 @@ Most of these values can be found by stat'ing a file.
``` js
{
name: 'path/to/this/entry.txt',
size: 1314, // entry size. defaults to 0
mode: 0644, // entry mode. defaults to to 0755 for dirs and 0644 otherwise
mtime: new Date(), // last modified date for entry. defaults to now.
type: 'file', // type of entry. defaults to file. can be:
// file | link | symlink | directory | block-device
// character-device | fifo | contigious-file
linkname: 'path', // linked file name
uid: 0, // uid of entry owner. defaults to 0
gid: 0, // gid of entry owner. defaults to 0
uname: 'maf', // uname of entry owner. defaults to null
gname: 'staff', // gname of entry owner. defaults to null
devmajor: 0, // device major version. defaults to 0
devminor: 0 // device minor version. defaults to 0
name: 'path/to/this/entry.txt',
size: 1314, // entry size. defaults to 0
mode: 0644, // entry mode. defaults to to 0755 for dirs and 0644 otherwise
mtime: new Date(), // last modified date for entry. defaults to now.
type: 'file', // type of entry. defaults to file. can be:
// file | link | symlink | directory | block-device
// character-device | fifo | contigious-file
linkname: 'path', // linked file name
uid: 0, // uid of entry owner. defaults to 0
gid: 0, // gid of entry owner. defaults to 0
uname: 'maf', // uname of entry owner. defaults to null
gname: 'staff', // gname of entry owner. defaults to null
devmajor: 0, // device major version. defaults to 0
devminor: 0 // device minor version. defaults to 0
}
```
@ -94,27 +96,27 @@ Most of these values can be found by stat'ing a file.
Using tar-stream it is easy to rewrite paths / change modes etc in an existing tarball.
``` js
var extract = tar.extract();
var pack = tar.pack();
var path = require('path');
var extract = tar.extract()
var pack = tar.pack()
var path = require('path')
extract.on('entry', function(header, stream, callback) {
// let's prefix all names with 'tmp'
header.name = path.join('tmp', header.name);
// write the new entry to the pack stream
stream.pipe(pack.entry(header, callback));
});
// let's prefix all names with 'tmp'
header.name = path.join('tmp', header.name)
// write the new entry to the pack stream
stream.pipe(pack.entry(header, callback))
})
extract.on('finish', function() {
// all entries done - lets finalize it
pack.finalize();
});
// all entries done - lets finalize it
pack.finalize()
})
// pipe the old tarball to the extractor
oldTarball.pipe(extract);
oldTarball.pipe(extract)
// pipe the new tarball the another stream
pack.pipe(newTarball);
pack.pipe(newTarball)
```
## Performance

View file

@ -1,194 +1,194 @@
var util = require('util');
var bl = require('bl');
var xtend = require('xtend');
var headers = require('./headers');
var util = require('util')
var bl = require('bl')
var xtend = require('xtend')
var headers = require('./headers')
var Writable = require('readable-stream').Writable;
var PassThrough = require('readable-stream').PassThrough;
var Writable = require('readable-stream').Writable
var PassThrough = require('readable-stream').PassThrough
var noop = function() {};
var noop = function() {}
var overflow = function(size) {
size &= 511;
return size && 512 - size;
};
size &= 511
return size && 512 - size
}
var emptyStream = function() {
var s = new PassThrough();
s.end();
return s;
};
var s = new PassThrough()
s.end()
return s
}
var mixinPax = function(header, pax) {
if (pax.path) header.name = pax.path;
if (pax.linkpath) header.linkname = pax.linkpath;
return header;
};
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);
Writable.call(this, opts);
if (!(this instanceof Extract)) return new Extract(opts)
Writable.call(this, opts)
this._buffer = bl();
this._missing = 0;
this._onparse = noop;
this._header = null;
this._stream = null;
this._overflow = null;
this._cb = null;
this._locked = false;
this._destroyed = false;
this._pax = null;
this._paxGlobal = null;
this._buffer = bl()
this._missing = 0
this._onparse = noop
this._header = null
this._stream = null
this._overflow = null
this._cb = null
this._locked = false
this._destroyed = false
this._pax = null
this._paxGlobal = null
var self = this;
var b = self._buffer;
var self = this
var b = self._buffer
var oncontinue = function() {
self._continue();
};
var oncontinue = function() {
self._continue()
}
var onunlock = function(err) {
self._locked = false;
if (err) return self.destroy(err);
if (!self._stream) oncontinue();
};
var onunlock = function(err) {
self._locked = false
if (err) return self.destroy(err)
if (!self._stream) oncontinue()
}
var onstreamend = function() {
self._stream = null;
var drain = overflow(self._header.size);
if (drain) self._parse(drain, ondrain);
else self._parse(512, onheader);
if (!self._locked) oncontinue();
};
var onstreamend = function() {
self._stream = null
var drain = overflow(self._header.size)
if (drain) self._parse(drain, ondrain)
else self._parse(512, onheader)
if (!self._locked) oncontinue()
}
var ondrain = function() {
self._buffer.consume(overflow(self._header.size));
self._parse(512, onheader);
oncontinue();
};
var ondrain = function() {
self._buffer.consume(overflow(self._header.size))
self._parse(512, onheader)
oncontinue()
}
var onpaxglobalheader = function() {
var size = self._header.size;
self._paxGlobal = headers.decodePax(b.slice(0, size));
b.consume(size);
onstreamend();
}
var onpaxglobalheader = function() {
var size = self._header.size
self._paxGlobal = headers.decodePax(b.slice(0, size))
b.consume(size)
onstreamend()
}
var onpaxheader = function() {
var size = self._header.size;
self._pax = headers.decodePax(b.slice(0, size));
if (self._paxGlobal) self._pax = xtend(self._paxGlobal, self._pax);
b.consume(size);
onstreamend();
};
var onpaxheader = function() {
var size = self._header.size
self._pax = headers.decodePax(b.slice(0, size))
if (self._paxGlobal) self._pax = xtend(self._paxGlobal, self._pax)
b.consume(size)
onstreamend()
}
var onheader = function() {
var header
try {
header = self._header = headers.decode(b.slice(0, 512));
} catch (err) {
self.emit('error', err);
}
b.consume(512);
var onheader = function() {
var header
try {
header = self._header = headers.decode(b.slice(0, 512))
} catch (err) {
self.emit('error', err)
}
b.consume(512)
if (!header) {
self._parse(512, onheader);
oncontinue();
return;
}
if (header.type === 'pax-global-header') {
self._parse(header.size, onpaxglobalheader);
oncontinue();
return;
}
if (header.type === 'pax-header') {
self._parse(header.size, onpaxheader);
oncontinue();
return;
}
if (!header) {
self._parse(512, onheader)
oncontinue()
return
}
if (header.type === 'pax-global-header') {
self._parse(header.size, onpaxglobalheader)
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;
}
if (self._pax) {
self._header = header = mixinPax(header, self._pax)
self._pax = null
}
self._locked = true;
self._locked = true
if (!header.size) {
self._parse(512, onheader);
self.emit('entry', header, emptyStream(), onunlock);
return;
}
if (!header.size) {
self._parse(512, onheader)
self.emit('entry', header, emptyStream(), onunlock)
return
}
self._stream = new PassThrough();
self._stream = new PassThrough()
self.emit('entry', header, self._stream, onunlock);
self._parse(header.size, onstreamend);
oncontinue();
};
self.emit('entry', header, self._stream, onunlock)
self._parse(header.size, onstreamend)
oncontinue()
}
this._parse(512, onheader);
};
this._parse(512, onheader)
}
util.inherits(Extract, Writable);
util.inherits(Extract, Writable)
Extract.prototype.destroy = function(err) {
if (this._destroyed) return;
this._destroyed = true;
if (this._destroyed) return
this._destroyed = true
if (err) this.emit('error', err);
this.emit('close');
if (this._stream) this._stream.emit('close');
};
if (err) this.emit('error', err)
this.emit('close')
if (this._stream) this._stream.emit('close')
}
Extract.prototype._parse = function(size, onparse) {
if (this._destroyed) return;
this._missing = size;
this._onparse = onparse;
};
if (this._destroyed) return
this._missing = size
this._onparse = onparse
}
Extract.prototype._continue = function(err) {
if (this._destroyed) return;
var cb = this._cb;
this._cb = noop;
if (this._overflow) this._write(this._overflow, undefined, cb);
else cb();
};
if (this._destroyed) return
var cb = this._cb
this._cb = noop
if (this._overflow) this._write(this._overflow, undefined, cb)
else cb()
}
Extract.prototype._write = function(data, enc, cb) {
if (this._destroyed) return;
if (this._destroyed) return
var s = this._stream;
var b = this._buffer;
var missing = this._missing;
var s = this._stream
var b = this._buffer
var missing = this._missing
// we do not reach end-of-chunk now. just forward it
// we do not reach end-of-chunk now. just forward it
if (data.length < missing) {
this._missing -= data.length;
this._overflow = null;
if (s) return s.write(data, cb);
b.append(data);
return cb();
}
if (data.length < missing) {
this._missing -= data.length
this._overflow = null
if (s) return s.write(data, cb)
b.append(data)
return cb()
}
// end-of-chunk. the parser should call cb.
// end-of-chunk. the parser should call cb.
this._cb = cb;
this._missing = 0;
this._cb = cb
this._missing = 0
var overflow = null;
if (data.length > missing) {
overflow = data.slice(missing);
data = data.slice(0, missing);
}
var overflow = null
if (data.length > missing) {
overflow = data.slice(missing)
data = data.slice(0, missing)
}
if (s) s.end(data);
else b.append(data);
if (s) s.end(data)
else b.append(data)
this._overflow = overflow;
this._onparse();
};
this._overflow = overflow
this._onparse()
}
module.exports = Extract;
module.exports = Extract

View file

@ -1,221 +1,221 @@
var ZEROS = '0000000000000000000';
var ZERO_OFFSET = '0'.charCodeAt(0);
var USTAR = 'ustar\x0000';
var ZEROS = '0000000000000000000'
var ZERO_OFFSET = '0'.charCodeAt(0)
var USTAR = 'ustar\x0000'
var clamp = function(index, len, defaultValue) {
if (typeof index !== 'number') return defaultValue;
index = ~~index; // Coerce to integer.
if (index >= len) return len;
if (index >= 0) return index;
index += len;
if (index >= 0) return index;
return 0;
};
if (typeof index !== 'number') return defaultValue
index = ~~index // Coerce to integer.
if (index >= len) return len
if (index >= 0) return index
index += len
if (index >= 0) return index
return 0
}
var toType = function(flag) {
switch (flag) {
case 0:
return 'file';
case 1:
return 'link';
case 2:
return 'symlink';
case 3:
return 'character-device';
case 4:
return 'block-device';
case 5:
return 'directory';
case 6:
return 'fifo';
case 7:
return 'contiguous-file';
case 72:
return 'pax-header';
case 55:
return 'pax-global-header'
}
switch (flag) {
case 0:
return 'file'
case 1:
return 'link'
case 2:
return 'symlink'
case 3:
return 'character-device'
case 4:
return 'block-device'
case 5:
return 'directory'
case 6:
return 'fifo'
case 7:
return 'contiguous-file'
case 72:
return 'pax-header'
case 55:
return 'pax-global-header'
}
return null;
};
return null
}
var toTypeflag = function(flag) {
switch (flag) {
case 'file':
return 0;
case 'link':
return 1;
case 'symlink':
return 2;
case 'character-device':
return 3;
case 'block-device':
return 4;
case 'directory':
return 5;
case 'fifo':
return 6;
case 'contiguous-file':
return 7;
case 'pax-header':
return 72;
}
switch (flag) {
case 'file':
return 0
case 'link':
return 1
case 'symlink':
return 2
case 'character-device':
return 3
case 'block-device':
return 4
case 'directory':
return 5
case 'fifo':
return 6
case 'contiguous-file':
return 7
case 'pax-header':
return 72
}
return 0;
};
return 0
}
var alloc = function(size) {
var buf = new Buffer(size);
buf.fill(0);
return buf;
};
var buf = new Buffer(size)
buf.fill(0)
return buf
}
var indexOf = function(block, num, offset, end) {
for (; offset < end; offset++) {
if (block[offset] === num) return offset;
}
return end;
};
for (; offset < end; offset++) {
if (block[offset] === num) return offset
}
return end
}
var cksum = function(block) {
var sum = 8 * 32;
for (var i = 0; i < 148; i++) sum += block[i];
for (var i = 156; i < 512; i++) sum += block[i];
return sum;
};
var sum = 8 * 32
for (var i = 0; i < 148; i++) sum += block[i]
for (var i = 156; i < 512; i++) sum += block[i]
return sum
}
var encodeOct = function(val, n) {
val = val.toString(8);
return ZEROS.slice(0, n-val.length)+val+' ';
};
val = val.toString(8)
return ZEROS.slice(0, n-val.length)+val+' '
}
var decodeOct = function(val, offset) {
// Older versions of tar can prefix with spaces
while (val[offset] === 32) offset += 1;
// Older versions of tar can prefix with spaces
while (offset < val.length && val[offset] === 32) offset++
return parseInt(val.slice(offset, clamp(indexOf(val, 32, offset, val.length), val.length, val.length)).toString(), 8);
};
return parseInt(val.slice(offset, clamp(indexOf(val, 32, offset, val.length), val.length, val.length)).toString(), 8)
}
var decodeStr = function(val, offset, length) {
return val.slice(offset, indexOf(val, 0, offset, offset+length)).toString();
};
return val.slice(offset, indexOf(val, 0, offset, offset+length)).toString();
}
var addLength = function(str) {
var len = Buffer.byteLength(str);
var digits = Math.floor(Math.log(len) / Math.log(10)) + 1;
if (len + digits > Math.pow(10, digits)) digits++;
var len = Buffer.byteLength(str)
var digits = Math.floor(Math.log(len) / Math.log(10)) + 1
if (len + digits > Math.pow(10, digits)) digits++
return (len+digits)+str;
};
return (len+digits)+str
}
exports.encodePax = function(opts) { // TODO: encode more stuff in pax
var result = '';
if (opts.name) result += addLength(' path='+opts.name+'\n');
if (opts.linkname) result += addLength(' linkpath='+opts.linkname+'\n');
return new Buffer(result);
};
var result = ''
if (opts.name) result += addLength(' path='+opts.name+'\n')
if (opts.linkname) result += addLength(' linkpath='+opts.linkname+'\n')
return new Buffer(result)
}
exports.decodePax = function(buf) {
var result = {};
var result = {}
while (buf.length) {
var i = 0;
for (; i < buf.length && buf[i] !== 32; i++);
var len = parseInt(buf.slice(0, i).toString());
if (!len) return result;
while (buf.length) {
var i = 0
while (i < buf.length && buf[i] !== 32) i++
var b = buf.slice(i+1, len-1).toString();
var keyIndex = b.indexOf('=');
if (keyIndex === -1) return result;
result[b.slice(0, keyIndex)] = b.slice(keyIndex+1);
var len = parseInt(buf.slice(0, i).toString())
if (!len) return result
buf = buf.slice(len);
}
var b = buf.slice(i+1, len-1).toString()
var keyIndex = b.indexOf('=')
if (keyIndex === -1) return result
result[b.slice(0, keyIndex)] = b.slice(keyIndex+1)
return result;
};
buf = buf.slice(len)
}
return result
}
exports.encode = function(opts) {
var buf = alloc(512);
var name = opts.name;
var prefix = '';
var buf = alloc(512)
var name = opts.name
var prefix = ''
if (opts.typeflag === 5 && name[name.length-1] !== '/') name += '/';
if (Buffer.byteLength(name) !== name.length) return null; // utf-8
if (opts.typeflag === 5 && name[name.length-1] !== '/') name += '/'
if (Buffer.byteLength(name) !== name.length) return null // utf-8
while (Buffer.byteLength(name) > 100) {
var i = name.indexOf('/');
if (i === -1) return null;
prefix += prefix ? '/' + name.slice(0, i) : name.slice(0, i);
name = name.slice(i+1);
}
while (Buffer.byteLength(name) > 100) {
var i = name.indexOf('/')
if (i === -1) return null
prefix += prefix ? '/' + name.slice(0, i) : name.slice(0, i)
name = name.slice(i+1)
}
if (Buffer.byteLength(name) > 100 || Buffer.byteLength(prefix) > 155) return null;
if (opts.linkname && Buffer.byteLength(opts.linkname) > 100) return null;
if (Buffer.byteLength(name) > 100 || Buffer.byteLength(prefix) > 155) return null
if (opts.linkname && Buffer.byteLength(opts.linkname) > 100) return null
buf.write(name);
buf.write(encodeOct(opts.mode & 07777, 6), 100);
buf.write(encodeOct(opts.uid, 6), 108);
buf.write(encodeOct(opts.gid, 6), 116);
buf.write(encodeOct(opts.size, 11), 124);
buf.write(encodeOct((opts.mtime.getTime() / 1000) | 0, 11), 136);
buf.write(name)
buf.write(encodeOct(opts.mode & 07777, 6), 100)
buf.write(encodeOct(opts.uid, 6), 108)
buf.write(encodeOct(opts.gid, 6), 116)
buf.write(encodeOct(opts.size, 11), 124)
buf.write(encodeOct((opts.mtime.getTime() / 1000) | 0, 11), 136)
buf[156] = ZERO_OFFSET + toTypeflag(opts.type);
buf[156] = ZERO_OFFSET + toTypeflag(opts.type)
if (opts.linkname) buf.write(opts.linkname, 157);
if (opts.linkname) buf.write(opts.linkname, 157)
buf.write(USTAR, 257);
if (opts.uname) buf.write(opts.uname, 265);
if (opts.gname) buf.write(opts.gname, 297);
buf.write(encodeOct(opts.devmajor || 0, 6), 329);
buf.write(encodeOct(opts.devminor || 0, 6), 337);
buf.write(USTAR, 257)
if (opts.uname) buf.write(opts.uname, 265)
if (opts.gname) buf.write(opts.gname, 297)
buf.write(encodeOct(opts.devmajor || 0, 6), 329)
buf.write(encodeOct(opts.devminor || 0, 6), 337)
if (prefix) buf.write(prefix, 345);
if (prefix) buf.write(prefix, 345)
buf.write(encodeOct(cksum(buf), 6), 148);
buf.write(encodeOct(cksum(buf), 6), 148)
return buf;
};
return buf
}
exports.decode = function(buf) {
var typeflag = buf[156] === 0 ? 0 : buf[156] - ZERO_OFFSET;
var type = toType(typeflag);
var typeflag = buf[156] === 0 ? 0 : buf[156] - ZERO_OFFSET
var type = toType(typeflag)
var name = decodeStr(buf, 0, 100);
var mode = decodeOct(buf, 100);
var uid = decodeOct(buf, 108);
var gid = decodeOct(buf, 116);
var size = decodeOct(buf, 124);
var mtime = decodeOct(buf, 136);
var linkname = buf[157] === 0 ? null : decodeStr(buf, 157, 100);
var uname = decodeStr(buf, 265, 32);
var gname = decodeStr(buf, 297, 32);
var devmajor = decodeOct(buf, 329);
var devminor = decodeOct(buf, 337);
var name = decodeStr(buf, 0, 100)
var mode = decodeOct(buf, 100)
var uid = decodeOct(buf, 108)
var gid = decodeOct(buf, 116)
var size = decodeOct(buf, 124)
var mtime = decodeOct(buf, 136)
var linkname = buf[157] === 0 ? null : decodeStr(buf, 157, 100)
var uname = decodeStr(buf, 265, 32)
var gname = decodeStr(buf, 297, 32)
var devmajor = decodeOct(buf, 329)
var devminor = decodeOct(buf, 337)
if (buf[345]) name = decodeStr(buf, 345, 155)+'/'+name;
if (buf[345]) name = decodeStr(buf, 345, 155)+'/'+name
var c = cksum(buf)
var c = cksum(buf)
//checksum is still initial value if header was null.
if (c === 8*32) return null;
//checksum is still initial value if header was null.
if (c === 8*32) return null
//valid checksum
if (c !== decodeOct(buf, 148)) throw new Error('invalid header');
return {
name: name,
mode: mode,
uid: uid,
gid: gid,
size: size,
mtime: new Date(1000 * mtime),
type: toType(typeflag),
linkname: linkname,
uname: uname,
gname: gname,
devmajor: devmajor,
devminor: devminor
};
};
//valid checksum
if (c !== decodeOct(buf, 148)) throw new Error('invalid header')
return {
name: name,
mode: mode,
uid: uid,
gid: gid,
size: size,
mtime: new Date(1000 * mtime),
type: toType(typeflag),
linkname: linkname,
uname: uname,
gname: gname,
devmajor: devmajor,
devminor: devminor
}
}

View file

@ -1,2 +1,2 @@
exports.extract = require('./extract');
exports.pack = require('./pack');
exports.extract = require('./extract')
exports.pack = require('./pack')

280
pack.js
View file

@ -1,194 +1,194 @@
var util = require('util');
var eos = require('end-of-stream');
var headers = require('./headers');
var util = require('util')
var eos = require('end-of-stream')
var headers = require('./headers')
var Readable = require('readable-stream').Readable;
var Writable = require('readable-stream').Writable;
var PassThrough = require('readable-stream').PassThrough;
var Readable = require('readable-stream').Readable
var Writable = require('readable-stream').Writable
var PassThrough = require('readable-stream').PassThrough
var END_OF_TAR = new Buffer(1024);
END_OF_TAR.fill(0);
var END_OF_TAR = new Buffer(1024)
END_OF_TAR.fill(0)
var noop = function() {};
var noop = function() {}
var overflow = function(self, size) {
size &= 511;
if (size) self.push(END_OF_TAR.slice(0, 512 - size));
};
size &= 511
if (size) self.push(END_OF_TAR.slice(0, 512 - size))
}
var Sink = function(to) {
Writable.call(this);
this.written = 0;
this._to = to;
this._destroyed = false;
};
Writable.call(this)
this.written = 0
this._to = to
this._destroyed = false
}
util.inherits(Sink, Writable);
util.inherits(Sink, Writable)
Sink.prototype._write = function(data, enc, cb) {
this.written += data.length;
if (this._to.push(data)) return cb();
this._to._drain = cb;
};
this.written += data.length
if (this._to.push(data)) return cb()
this._to._drain = cb
}
Sink.prototype.destroy = function() {
if (this._destroyed) return;
this._destroyed = true;
this.emit('close');
};
if (this._destroyed) return
this._destroyed = true
this.emit('close')
}
var Void = function() {
Writable.call(this)
this._destroyed = false;
};
Writable.call(this)
this._destroyed = false
}
util.inherits(Void, Writable);
util.inherits(Void, Writable)
Void.prototype._write = function(data, enc, cb) {
cb(new Error('No body allowed for this entry'))
};
cb(new Error('No body allowed for this entry'))
}
Void.prototype.destroy = function() {
if (this._destroyed) return;
this._destroyed = true;
this.emit('close')
if (this._destroyed) return
this._destroyed = true
this.emit('close')
}
var Pack = function(opts) {
if (!(this instanceof Pack)) return new Pack(opts);
Readable.call(this, opts);
if (!(this instanceof Pack)) return new Pack(opts)
Readable.call(this, opts)
this._drain = noop;
this._finalized = false;
this._finalizing = false;
this._destroyed = false;
this._stream = null;
};
this._drain = noop
this._finalized = false
this._finalizing = false
this._destroyed = false
this._stream = null
}
util.inherits(Pack, Readable);
util.inherits(Pack, Readable)
Pack.prototype.entry = function(header, buffer, callback) {
if (this._stream) throw new Error('already piping an entry');
if (this._finalized || this._destroyed) return;
if (this._stream) throw new Error('already piping an entry')
if (this._finalized || this._destroyed) return
if (typeof buffer === 'function') {
callback = buffer;
buffer = null;
}
if (typeof buffer === 'function') {
callback = buffer
buffer = null
}
if (!callback) callback = noop;
if (!callback) callback = noop
var self = this;
var self = this
if (!header.size) header.size = 0;
if (!header.type) header.type = 'file';
if (!header.mode) header.mode = header.type === 'directory' ? 0755 : 0644;
if (!header.uid) header.uid = 0;
if (!header.gid) header.gid = 0;
if (!header.mtime) header.mtime = new Date();
if (!header.size) header.size = 0
if (!header.type) header.type = 'file'
if (!header.mode) header.mode = header.type === 'directory' ? 0755 : 0644
if (!header.uid) header.uid = 0
if (!header.gid) header.gid = 0
if (!header.mtime) header.mtime = new Date()
if (typeof buffer === 'string') buffer = new Buffer(buffer);
if (Buffer.isBuffer(buffer)) {
header.size = buffer.length;
this._encode(header);
this.push(buffer);
overflow(self, header.size);
process.nextTick(callback);
return new Void();
}
if (header.type !== 'file' && header.type !== 'contigious-file') {
this._encode(header);
process.nextTick(callback);
return new Void();
}
if (typeof buffer === 'string') buffer = new Buffer(buffer)
if (Buffer.isBuffer(buffer)) {
header.size = buffer.length
this._encode(header)
this.push(buffer)
overflow(self, header.size)
process.nextTick(callback)
return new Void()
}
if (header.type !== 'file' && header.type !== 'contigious-file') {
this._encode(header)
process.nextTick(callback)
return new Void()
}
var sink = new Sink(this);
var sink = new Sink(this)
this._encode(header);
this._stream = sink;
this._encode(header)
this._stream = sink
eos(sink, function(err) {
self._stream = null;
eos(sink, function(err) {
self._stream = null
if (err) { // stream was closed
self.destroy();
return callback(err);
}
if (err) { // stream was closed
self.destroy()
return callback(err)
}
if (sink.written !== header.size) { // corrupting tar
self.destroy();
return callback(new Error('size mismatch'));
}
if (sink.written !== header.size) { // corrupting tar
self.destroy()
return callback(new Error('size mismatch'))
}
overflow(self, header.size);
if (self._finalizing) self.finalize();
callback();
});
overflow(self, header.size)
if (self._finalizing) self.finalize()
callback()
})
return sink;
};
return sink
}
Pack.prototype.finalize = function() {
if (this._stream) {
this._finalizing = true;
return;
}
if (this._stream) {
this._finalizing = true
return
}
if (this._finalized) return;
this._finalized = true;
this.push(END_OF_TAR);
this.push(null);
};
if (this._finalized) return
this._finalized = true
this.push(END_OF_TAR)
this.push(null)
}
Pack.prototype.destroy = function(err) {
if (this._destroyed) return;
this._destroyed = true;
if (this._destroyed) return
this._destroyed = true
if (err) this.emit('error', err);
this.emit('close');
if (this._stream && this._stream.destroy) this._stream.destroy();
};
if (err) this.emit('error', err)
this.emit('close')
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);
};
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 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
};
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);
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));
};
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;
drain();
};
var drain = this._drain
this._drain = noop
drain()
}
module.exports = Pack;
module.exports = Pack