Comparing version 6.1.4 to 6.1.5
@@ -338,13 +338,31 @@ 'use strict' | ||
}) | ||
stream.on('error', er => this[ONERROR](er, entry)) | ||
stream.on('error', er => { | ||
if (stream.fd) | ||
fs.close(stream.fd, () => {}) | ||
// flush all the data out so that we aren't left hanging | ||
// if the error wasn't actually fatal. otherwise the parse | ||
// is blocked, and we never proceed. | ||
stream.write = () => true | ||
this[ONERROR](er, entry) | ||
fullyDone() | ||
}) | ||
let actions = 1 | ||
const done = er => { | ||
if (er) | ||
return this[ONERROR](er, entry) | ||
if (er) { | ||
/* istanbul ignore else - we should always have a fd by now */ | ||
if (stream.fd) | ||
fs.close(stream.fd, () => {}) | ||
this[ONERROR](er, entry) | ||
fullyDone() | ||
return | ||
} | ||
if (--actions === 0) { | ||
fs.close(stream.fd, er => { | ||
if (er) | ||
this[ONERROR](er, entry) | ||
else | ||
this[UNPEND]() | ||
fullyDone() | ||
er ? this[ONERROR](er, entry) : this[UNPEND]() | ||
}) | ||
@@ -384,3 +402,6 @@ } | ||
if (tx !== entry) { | ||
tx.on('error', er => this[ONERROR](er, entry)) | ||
tx.on('error', er => { | ||
this[ONERROR](er, entry) | ||
fullyDone() | ||
}) | ||
entry.pipe(tx) | ||
@@ -395,4 +416,5 @@ } | ||
if (er) { | ||
this[ONERROR](er, entry) | ||
fullyDone() | ||
return this[ONERROR](er, entry) | ||
return | ||
} | ||
@@ -488,4 +510,5 @@ | ||
if (er) { | ||
this[ONERROR](er, entry) | ||
done() | ||
return this[ONERROR](er, entry) | ||
return | ||
} | ||
@@ -498,3 +521,2 @@ fs.lstat(entry.absolute, (er, st) => { | ||
this[MAKEFS](null, entry, done) | ||
else if (st.isDirectory()) { | ||
@@ -517,4 +539,7 @@ if (entry.type === 'Directory') { | ||
[MAKEFS] (er, entry, done) { | ||
if (er) | ||
return this[ONERROR](er, entry) | ||
if (er) { | ||
this[ONERROR](er, entry) | ||
done() | ||
return | ||
} | ||
@@ -543,6 +568,8 @@ switch (entry.type) { | ||
if (er) | ||
return this[ONERROR](er, entry) | ||
this[ONERROR](er, entry) | ||
else { | ||
this[UNPEND]() | ||
entry.resume() | ||
} | ||
done() | ||
this[UNPEND]() | ||
entry.resume() | ||
}) | ||
@@ -549,0 +576,0 @@ } |
@@ -24,2 +24,4 @@ 'use strict' | ||
const MODE = Symbol('mode') | ||
const AWAITDRAIN = Symbol('awaitDrain') | ||
const ONDRAIN = Symbol('ondrain') | ||
const warner = require('./warn-mixin.js') | ||
@@ -53,2 +55,11 @@ const winchars = require('./winchars.js') | ||
this.fd = null | ||
this.blockLen = null | ||
this.blockRemain = null | ||
this.buf = null | ||
this.offset = null | ||
this.length = null | ||
this.pos = null | ||
this.remain = null | ||
if (typeof opt.onwarn === 'function') | ||
@@ -144,3 +155,3 @@ this.on('warn', opt.onwarn) | ||
if (this.header.encode() && !this.noPax) { | ||
this.write(new Pax({ | ||
super.write(new Pax({ | ||
atime: this.portable ? null : this.header.atime, | ||
@@ -160,3 +171,3 @@ ctime: this.portable ? null : this.header.ctime, | ||
} | ||
this.write(this.header.block) | ||
super.write(this.header.block) | ||
} | ||
@@ -221,9 +232,16 @@ | ||
[ONOPENFILE] (fd) { | ||
const blockLen = 512 * Math.ceil(this.stat.size / 512) | ||
const bufLen = Math.min(blockLen, this.maxReadSize) | ||
const buf = Buffer.allocUnsafe(bufLen) | ||
this[READ](fd, buf, 0, buf.length, 0, this.stat.size, blockLen) | ||
this.fd = fd | ||
this.blockLen = 512 * Math.ceil(this.stat.size / 512) | ||
this.blockRemain = this.blockLen | ||
const bufLen = Math.min(this.blockLen, this.maxReadSize) | ||
this.buf = Buffer.allocUnsafe(bufLen) | ||
this.offset = 0 | ||
this.pos = 0 | ||
this.remain = this.stat.size | ||
this.length = this.buf.length | ||
this[READ]() | ||
} | ||
[READ] (fd, buf, offset, length, pos, remain, blockRemain) { | ||
[READ] () { | ||
const { fd, buf, offset, length, pos } = this | ||
fs.read(fd, buf, offset, length, pos, (er, bytesRead) => { | ||
@@ -233,14 +251,14 @@ if (er) { | ||
// this point we already have an error, don't need another one | ||
return this[CLOSE](fd, () => this.emit('error', er)) | ||
return this[CLOSE](() => this.emit('error', er)) | ||
} | ||
this[ONREAD](fd, buf, offset, length, pos, remain, blockRemain, bytesRead) | ||
this[ONREAD](bytesRead) | ||
}) | ||
} | ||
[CLOSE] (fd, cb) { | ||
fs.close(fd, cb) | ||
[CLOSE] (cb) { | ||
fs.close(this.fd, cb) | ||
} | ||
[ONREAD] (fd, buf, offset, length, pos, remain, blockRemain, bytesRead) { | ||
if (bytesRead <= 0 && remain > 0) { | ||
[ONREAD] (bytesRead) { | ||
if (bytesRead <= 0 && this.remain > 0) { | ||
const er = new Error('encountered unexpected EOF') | ||
@@ -250,6 +268,6 @@ er.path = this.absolute | ||
er.code = 'EOF' | ||
return this[CLOSE](fd, () => this.emit('error', er)) | ||
return this[CLOSE](() => this.emit('error', er)) | ||
} | ||
if (bytesRead > remain) { | ||
if (bytesRead > this.remain) { | ||
const er = new Error('did not encounter expected EOF') | ||
@@ -259,35 +277,61 @@ er.path = this.absolute | ||
er.code = 'EOF' | ||
return this[CLOSE](fd, () => this.emit('error', er)) | ||
return this[CLOSE](() => this.emit('error', er)) | ||
} | ||
// null out the rest of the buffer, if we could fit the block padding | ||
if (bytesRead === remain) { | ||
for (let i = bytesRead; i < length && bytesRead < blockRemain; i++) { | ||
buf[i + offset] = 0 | ||
// at the end of this loop, we've incremented bytesRead and this.remain | ||
// to be incremented up to the blockRemain level, as if we had expected | ||
// to get a null-padded file, and read it until the end. then we will | ||
// decrement both remain and blockRemain by bytesRead, and know that we | ||
// reached the expected EOF, without any null buffer to append. | ||
if (bytesRead === this.remain) { | ||
for (let i = bytesRead; i < this.length && bytesRead < this.blockRemain; i++) { | ||
this.buf[i + this.offset] = 0 | ||
bytesRead++ | ||
remain++ | ||
this.remain++ | ||
} | ||
} | ||
const writeBuf = offset === 0 && bytesRead === buf.length ? | ||
buf : buf.slice(offset, offset + bytesRead) | ||
remain -= bytesRead | ||
blockRemain -= bytesRead | ||
pos += bytesRead | ||
offset += bytesRead | ||
const writeBuf = this.offset === 0 && bytesRead === this.buf.length ? | ||
this.buf : this.buf.slice(this.offset, this.offset + bytesRead) | ||
this.write(writeBuf) | ||
const flushed = this.write(writeBuf) | ||
if (!flushed) | ||
this[AWAITDRAIN](() => this[ONDRAIN]()) | ||
else | ||
this[ONDRAIN]() | ||
} | ||
if (!remain) { | ||
if (blockRemain) | ||
this.write(Buffer.alloc(blockRemain)) | ||
return this[CLOSE](fd, er => er ? this.emit('error', er) : this.end()) | ||
[AWAITDRAIN] (cb) { | ||
this.once('drain', cb) | ||
} | ||
write (writeBuf) { | ||
if (this.blockRemain < writeBuf.length) { | ||
const er = new Error('writing more data than expected') | ||
er.path = this.absolute | ||
return this.emit('error', er) | ||
} | ||
this.remain -= writeBuf.length | ||
this.blockRemain -= writeBuf.length | ||
this.pos += writeBuf.length | ||
this.offset += writeBuf.length | ||
return super.write(writeBuf) | ||
} | ||
if (offset >= length) { | ||
buf = Buffer.allocUnsafe(length) | ||
offset = 0 | ||
[ONDRAIN] () { | ||
if (!this.remain) { | ||
if (this.blockRemain) | ||
super.write(Buffer.alloc(this.blockRemain)) | ||
return this[CLOSE](er => er ? this.emit('error', er) : this.end()) | ||
} | ||
length = buf.length - offset | ||
this[READ](fd, buf, offset, length, pos, remain, blockRemain) | ||
if (this.offset >= this.length) { | ||
// if we only have a smaller bit left to read, alloc a smaller buffer | ||
// otherwise, keep it the same length it was before. | ||
this.buf = Buffer.allocUnsafe(Math.min(this.blockRemain, this.buf.length)) | ||
this.offset = 0 | ||
} | ||
this.length = this.buf.length - this.offset | ||
this[READ]() | ||
} | ||
@@ -309,7 +353,8 @@ }) | ||
[READ] (fd, buf, offset, length, pos, remain, blockRemain) { | ||
[READ] () { | ||
let threw = true | ||
try { | ||
const { fd, buf, offset, length, pos } = this | ||
const bytesRead = fs.readSync(fd, buf, offset, length, pos) | ||
this[ONREAD](fd, buf, offset, length, pos, remain, blockRemain, bytesRead) | ||
this[ONREAD](bytesRead) | ||
threw = false | ||
@@ -321,3 +366,3 @@ } finally { | ||
try { | ||
this[CLOSE](fd, () => {}) | ||
this[CLOSE](() => {}) | ||
} catch (er) {} | ||
@@ -328,6 +373,10 @@ } | ||
[CLOSE] (fd, cb) { | ||
fs.closeSync(fd) | ||
[AWAITDRAIN] (cb) { | ||
cb() | ||
} | ||
[CLOSE] (cb) { | ||
fs.closeSync(this.fd) | ||
cb() | ||
} | ||
} | ||
@@ -435,3 +484,3 @@ | ||
if (this.blockRemain) | ||
this.write(Buffer.alloc(this.blockRemain)) | ||
super.write(Buffer.alloc(this.blockRemain)) | ||
return super.end() | ||
@@ -438,0 +487,0 @@ } |
@@ -5,3 +5,3 @@ { | ||
"description": "tar for node", | ||
"version": "6.1.4", | ||
"version": "6.1.5", | ||
"repository": { | ||
@@ -8,0 +8,0 @@ "type": "git", |
152433
3362