@@ -49,6 +49,15 @@ const WriteEntry = warner(class WriteEntry extends MiniPass {
49
49
this . noMtime = ! ! opt . noMtime
50
50
this . mtime = opt . mtime || null
51
51
52
+ this . fd = null
53
+ this . blockLen = null
54
+ this . blockRemain = null
55
+ this . buf = null
56
+ this . offset = null
57
+ this . length = null
58
+ this . pos = null
59
+ this . remain = null
60
+
52
61
if ( typeof opt . onwarn === 'function' )
53
62
this . on ( 'warn' , opt . onwarn )
54
63
@@ -214,74 +223,88 @@ const WriteEntry = warner(class WriteEntry extends MiniPass {
214
223
}
215
224
216
225
[ ONOPENFILE ] ( fd ) {
217
- const blockLen = 512 * Math . ceil ( this . stat . size / 512 )
218
- const bufLen = Math . min ( blockLen , this . maxReadSize )
219
- const buf = Buffer . allocUnsafe ( bufLen )
220
- this [ READ ] ( fd , buf , 0 , buf . length , 0 , this . stat . size , blockLen )
226
+ this . fd = fd
227
+ this . blockLen = 512 * Math . ceil ( this . stat . size / 512 )
228
+ this . blockRemain = this . blockLen
229
+ const bufLen = Math . min ( this . blockLen , this . maxReadSize )
230
+ this . buf = Buffer . allocUnsafe ( bufLen )
231
+ this . offset = 0
232
+ this . pos = 0
233
+ this . remain = this . stat . size
234
+ this . length = this . buf . length
235
+ this [ READ ] ( this . stat . size )
221
236
}
222
237
223
- [ READ ] ( fd , buf , offset , length , pos , remain , blockRemain ) {
238
+ [ READ ] ( ) {
239
+ const { fd, buf, offset, length, pos } = this
224
240
fs . read ( fd , buf , offset , length , pos , ( er , bytesRead ) => {
225
241
if ( er ) {
226
242
// ignoring the error from close(2) is a bad practice, but at
227
243
// this point we already have an error, don't need another one
228
- return this [ CLOSE ] ( fd , ( ) => this . emit ( 'error' , er ) )
244
+ return this [ CLOSE ] ( ( ) => this . emit ( 'error' , er ) )
229
245
}
230
- this [ ONREAD ] ( fd , buf , offset , length , pos , remain , blockRemain , bytesRead )
246
+ this [ ONREAD ] ( bytesRead )
231
247
} )
232
248
}
233
249
234
- [ CLOSE ] ( fd , cb ) {
235
- fs . close ( fd , cb )
250
+ [ CLOSE ] ( cb ) {
251
+ fs . close ( this . fd , cb )
236
252
}
237
253
238
- [ ONREAD ] ( fd , buf , offset , length , pos , remain , blockRemain , bytesRead ) {
239
- if ( bytesRead <= 0 && remain > 0 ) {
254
+ [ ONREAD ] ( bytesRead ) {
255
+ if ( bytesRead <= 0 && this . remain > 0 ) {
240
256
const er = new Error ( 'encountered unexpected EOF' )
241
257
er . path = this . absolute
242
258
er . syscall = 'read'
243
259
er . code = 'EOF'
244
- return this [ CLOSE ] ( fd , ( ) => this . emit ( 'error' , er ) )
260
+ return this [ CLOSE ] ( ( ) => this . emit ( 'error' , er ) )
245
261
}
246
262
247
- if ( bytesRead > remain ) {
263
+ if ( bytesRead > this . remain ) {
248
264
const er = new Error ( 'did not encounter expected EOF' )
249
265
er . path = this . absolute
250
266
er . syscall = 'read'
251
267
er . code = 'EOF'
252
- return this [ CLOSE ] ( fd , ( ) => this . emit ( 'error' , er ) )
268
+ return this [ CLOSE ] ( ( ) => this . emit ( 'error' , er ) )
253
269
}
254
270
255
271
// null out the rest of the buffer, if we could fit the block padding
256
- if ( bytesRead === remain ) {
257
- for ( let i = bytesRead ; i < length && bytesRead < blockRemain ; i ++ ) {
258
- buf [ i + offset ] = 0
272
+ // at the end of this loop, we've incremented bytesRead and this.remain
273
+ // to be incremented up to the blockRemain level, as if we had expected
274
+ // to get a null-padded file, and read it until the end. then we will
275
+ // decrement both remain and blockRemain by bytesRead, and know that we
276
+ // reached the expected EOF, without any null buffer to append.
277
+ if ( bytesRead === this . remain ) {
278
+ for ( let i = bytesRead ; i < this . length && bytesRead < this . blockRemain ; i ++ ) {
279
+ this . buf [ i + this . offset ] = 0
259
280
bytesRead ++
260
- remain ++
281
+ this . remain ++
261
282
}
262
283
}
263
284
264
- const writeBuf = offset === 0 && bytesRead === buf . length ?
265
- buf : buf . slice ( offset , offset + bytesRead )
266
- remain -= bytesRead
267
- blockRemain -= bytesRead
268
- pos += bytesRead
269
- offset += bytesRead
285
+ const writeBuf = this . offset === 0 && bytesRead === this . buf . length ?
286
+ this . buf : this . buf . slice ( this . offset , this . offset + bytesRead )
287
+ this . remain -= bytesRead
288
+ this . blockRemain -= bytesRead
289
+ this . pos += bytesRead
290
+ this . offset += bytesRead
270
291
271
292
this . write ( writeBuf )
272
293
273
- if ( ! remain ) {
274
- if ( blockRemain )
275
- this . write ( Buffer . alloc ( blockRemain ) )
276
- return this [ CLOSE ] ( fd , er => er ? this . emit ( 'error' , er ) : this . end ( ) )
294
+ if ( ! this . remain ) {
295
+ if ( this . blockRemain )
296
+ this . write ( Buffer . alloc ( this . blockRemain ) )
297
+ return this [ CLOSE ] ( er => er ? this . emit ( 'error' , er ) : this . end ( ) )
277
298
}
278
299
279
- if ( offset >= length ) {
280
- buf = Buffer . allocUnsafe ( length )
281
- offset = 0
300
+ if ( this . offset >= this . length ) {
301
+ // if we only have a smaller bit left to read, alloc a smaller buffer
302
+ // otherwise, keep it the same length it was before.
303
+ this . buf = Buffer . allocUnsafe ( Math . min ( this . blockRemain , this . buf . length ) )
304
+ this . offset = 0
282
305
}
283
- length = buf . length - offset
284
- this [ READ ] ( fd , buf , offset , length , pos , remain , blockRemain )
306
+ this . length = this . buf . length - this . offset
307
+ this [ READ ] ( )
285
308
}
286
309
} )
287
310
@@ -298,25 +321,26 @@ class WriteEntrySync extends WriteEntry {
298
321
this [ ONOPENFILE ] ( fs . openSync ( this . absolute , 'r' ) )
299
322
}
300
323
301
- [ READ ] ( fd , buf , offset , length , pos , remain , blockRemain ) {
324
+ [ READ ] ( ) {
302
325
let threw = true
303
326
try {
327
+ const { fd, buf, offset, length, pos } = this
304
328
const bytesRead = fs . readSync ( fd , buf , offset , length , pos )
305
- this [ ONREAD ] ( fd , buf , offset , length , pos , remain , blockRemain , bytesRead )
329
+ this [ ONREAD ] ( bytesRead )
306
330
threw = false
307
331
} finally {
308
332
// ignoring the error from close(2) is a bad practice, but at
309
333
// this point we already have an error, don't need another one
310
334
if ( threw ) {
311
335
try {
312
- this [ CLOSE ] ( fd , ( ) => { } )
336
+ this [ CLOSE ] ( ( ) => { } )
313
337
} catch ( er ) { }
314
338
}
315
339
}
316
340
}
317
341
318
- [ CLOSE ] ( fd , cb ) {
319
- fs . closeSync ( fd )
342
+ [ CLOSE ] ( cb ) {
343
+ fs . closeSync ( this . fd )
320
344
cb ( )
321
345
}
322
346
}
0 commit comments