@@ -52,6 +52,15 @@ const WriteEntry = warner(class WriteEntry extends MiniPass {
5252 this . noMtime = ! ! opt . noMtime
5353 this . mtime = opt . mtime || null
5454
55+ this . fd = null
56+ this . blockLen = null
57+ this . blockRemain = null
58+ this . buf = null
59+ this . offset = null
60+ this . length = null
61+ this . pos = null
62+ this . remain = null
63+
5564 if ( typeof opt . onwarn === 'function' )
5665 this . on ( 'warn' , opt . onwarn )
5766
@@ -208,75 +217,89 @@ const WriteEntry = warner(class WriteEntry extends MiniPass {
208217 }
209218
210219 [ ONOPENFILE ] ( fd ) {
211- const blockLen = 512 * Math . ceil ( this . stat . size / 512 )
212- const bufLen = Math . min ( blockLen , this . maxReadSize )
213- const buf = Buffer . allocUnsafe ( bufLen )
214- this [ READ ] ( fd , buf , 0 , buf . length , 0 , this . stat . size , blockLen )
220+ this . fd = fd
221+ this . blockLen = 512 * Math . ceil ( this . stat . size / 512 )
222+ this . blockRemain = this . blockLen
223+ const bufLen = Math . min ( this . blockLen , this . maxReadSize )
224+ this . buf = Buffer . allocUnsafe ( bufLen )
225+ this . offset = 0
226+ this . pos = 0
227+ this . remain = this . stat . size
228+ this . length = this . buf . length
229+ this [ READ ] ( this . stat . size )
215230 }
216231
217- [ READ ] ( fd , buf , offset , length , pos , remain , blockRemain ) {
232+ [ READ ] ( ) {
233+ const { fd, buf, offset, length, pos } = this
218234 fs . read ( fd , buf , offset , length , pos , ( er , bytesRead ) => {
219- if ( er )
220- return this [ CLOSE ] ( fd , _ => this . emit ( 'error' , er ) )
221- this [ ONREAD ] ( fd , buf , offset , length , pos , remain , blockRemain , bytesRead )
235+ if ( er ) {
236+ // ignoring the error from close(2) is a bad practice, but at
237+ // this point we already have an error, don't need another one
238+ return this [ CLOSE ] ( ( ) => this . emit ( 'error' , er ) )
239+ }
240+ this [ ONREAD ] ( bytesRead )
222241 } )
223242 }
224243
225- [ CLOSE ] ( fd , cb ) {
226- fs . close ( fd , cb )
244+ [ CLOSE ] ( cb ) {
245+ fs . close ( this . fd , cb )
227246 }
228247
229- [ ONREAD ] ( fd , buf , offset , length , pos , remain , blockRemain , bytesRead ) {
230- if ( bytesRead <= 0 && remain > 0 ) {
248+ [ ONREAD ] ( bytesRead ) {
249+ if ( bytesRead <= 0 && this . remain > 0 ) {
231250 const er = new Error ( 'encountered unexpected EOF' )
232251 er . path = this . absolute
233252 er . syscall = 'read'
234253 er . code = 'EOF'
235- this [ CLOSE ] ( fd , _ => _ )
236- return this . emit ( 'error' , er )
254+ return this [ CLOSE ] ( ( ) => this . emit ( 'error' , er ) )
237255 }
238256
239- if ( bytesRead > remain ) {
257+ if ( bytesRead > this . remain ) {
240258 const er = new Error ( 'did not encounter expected EOF' )
241259 er . path = this . absolute
242260 er . syscall = 'read'
243261 er . code = 'EOF'
244- this [ CLOSE ] ( fd , _ => _ )
245- return this . emit ( 'error' , er )
262+ return this [ CLOSE ] ( ( ) => this . emit ( 'error' , er ) )
246263 }
247264
248265 // null out the rest of the buffer, if we could fit the block padding
249- if ( bytesRead === remain ) {
250- for ( let i = bytesRead ; i < length && bytesRead < blockRemain ; i ++ ) {
251- buf [ i + offset ] = 0
252- bytesRead ++
253- remain ++
266+ // at the end of this loop, we've incremented bytesRead and this.remain
267+ // to be incremented up to the blockRemain level, as if we had expected
268+ // to get a null-padded file, and read it until the end. then we will
269+ // decrement both remain and blockRemain by bytesRead, and know that we
270+ // reached the expected EOF, without any null buffer to append.
271+ if ( bytesRead === this . remain ) {
272+ for ( let i = bytesRead ; i < this . length && bytesRead < this . blockRemain ; i ++ ) {
273+ this . buf [ i + this . offset ] = 0
274+ bytesRead ++
275+ this . remain ++
254276 }
255277 }
256278
257- const writeBuf = offset === 0 && bytesRead === buf . length ?
258- buf : buf . slice ( offset , offset + bytesRead )
259- remain -= bytesRead
260- blockRemain -= bytesRead
261- pos += bytesRead
262- offset += bytesRead
279+ const writeBuf = this . offset === 0 && bytesRead === this . buf . length ?
280+ this . buf : this . buf . slice ( this . offset , this . offset + bytesRead )
281+ this . remain -= bytesRead
282+ this . blockRemain -= bytesRead
283+ this . pos += bytesRead
284+ this . offset += bytesRead
263285
264286 this . write ( writeBuf )
265287
266- if ( ! remain ) {
267- if ( blockRemain )
268- this . write ( Buffer . alloc ( blockRemain ) )
269- this . end ( )
270- this [ CLOSE ] ( fd , _ => _ )
271- return
288+ if ( ! this . remain ) {
289+ if ( this . blockRemain )
290+ this . write ( Buffer . alloc ( this . blockRemain ) )
291+ return this [ CLOSE ] ( /* istanbul ignore next - legacy */
292+ er => er ? this . emit ( 'error' , er ) : this . end ( ) )
272293 }
273294
274- if ( offset >= length ) {
275- buf = Buffer . allocUnsafe ( length )
276- offset = 0
295+ if ( this . offset >= this . length ) {
296+ // if we only have a smaller bit left to read, alloc a smaller buffer
297+ // otherwise, keep it the same length it was before.
298+ this . buf = Buffer . allocUnsafe ( Math . min ( this . blockRemain , this . buf . length ) )
299+ this . offset = 0
277300 }
278- length = buf . length - offset
279- this [ READ ] ( fd , buf , offset , length , pos , remain , blockRemain )
301+ this . length = this . buf . length - this . offset
302+ this [ READ ] ( )
280303 }
281304} )
282305
@@ -297,20 +320,27 @@ class WriteEntrySync extends WriteEntry {
297320 this [ ONOPENFILE ] ( fs . openSync ( this . absolute , 'r' ) )
298321 }
299322
300- [ READ ] ( fd , buf , offset , length , pos , remain , blockRemain ) {
323+ [ READ ] ( ) {
301324 let threw = true
302325 try {
326+ const { fd, buf, offset, length, pos } = this
303327 const bytesRead = fs . readSync ( fd , buf , offset , length , pos )
304- this [ ONREAD ] ( fd , buf , offset , length , pos , remain , blockRemain , bytesRead )
328+ this [ ONREAD ] ( bytesRead )
305329 threw = false
306330 } finally {
307- if ( threw )
308- try { this [ CLOSE ] ( fd ) } catch ( er ) { }
331+ // ignoring the error from close(2) is a bad practice, but at
332+ // this point we already have an error, don't need another one
333+ if ( threw ) {
334+ try {
335+ this [ CLOSE ] ( ( ) => { } )
336+ } catch ( er ) { }
337+ }
309338 }
310339 }
311340
312- [ CLOSE ] ( fd ) {
313- fs . closeSync ( fd )
341+ [ CLOSE ] ( cb ) {
342+ fs . closeSync ( this . fd )
343+ cb ( )
314344 }
315345}
316346
0 commit comments