Skip to content

Commit 5987d9a

Browse files
committed
Remove paths from dirCache when no longer dirs
1 parent fea8684 commit 5987d9a

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

lib/unpack.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,19 @@ class Unpack extends Parser {
461461
this.reservations.reserve(paths, done => this[CHECKFS2](entry, done))
462462
}
463463
[CHECKFS2] (entry, done) {
464+
// if we are not creating a directory, and the path is in the dirCache,
465+
// then that means we are about to delete the directory we created
466+
// previously, and it is no longer going to be a directory, and neither
467+
// is any of its children.
468+
if (entry.type !== 'Directory') {
469+
for (const path of this.dirCache.keys()) {
470+
if (path === entry.absolute ||
471+
path.indexOf(entry.absolute + '/') === 0 ||
472+
path.indexOf(entry.absolute + '\\') === 0)
473+
this.dirCache.delete(path)
474+
}
475+
}
476+
464477
this[MKDIR](path.dirname(entry.absolute), this.dmode, er => {
465478
if (er) {
466479
done()
@@ -528,6 +541,15 @@ class UnpackSync extends Unpack {
528541
}
529542

530543
[CHECKFS] (entry) {
544+
if (entry.type !== 'Directory') {
545+
for (const path of this.dirCache.keys()) {
546+
if (path === entry.absolute ||
547+
path.indexOf(entry.absolute + '/') === 0 ||
548+
path.indexOf(entry.absolute + '\\') === 0)
549+
this.dirCache.delete(path)
550+
}
551+
}
552+
531553
const er = this[MKDIR](path.dirname(entry.absolute), this.dmode, neverCalled)
532554
if (er)
533555
return this[ONERROR](er, entry)

test/unpack.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2579,3 +2579,56 @@ t.test('handle errors on fs.close', t => {
25792579
cwd: dir + '/sync', strict: true,
25802580
}).end(data), poop, 'sync')
25812581
})
2582+
2583+
t.test('drop entry from dirCache if no longer a directory', t => {
2584+
const dir = path.resolve(unpackdir, 'dir-cache-error')
2585+
mkdirp.sync(dir + '/sync/y')
2586+
mkdirp.sync(dir + '/async/y')
2587+
const data = makeTar([
2588+
{
2589+
path: 'x',
2590+
type: 'Directory',
2591+
},
2592+
{
2593+
path: 'x',
2594+
type: 'SymbolicLink',
2595+
linkpath: './y',
2596+
},
2597+
{
2598+
path: 'x/ginkoid',
2599+
type: 'File',
2600+
size: 'ginkoid'.length,
2601+
},
2602+
'ginkoid',
2603+
'',
2604+
'',
2605+
])
2606+
t.plan(2)
2607+
const WARNINGS = {}
2608+
const check = (t, path) => {
2609+
t.equal(fs.statSync(path + '/x').isDirectory(), true)
2610+
t.equal(fs.lstatSync(path + '/x').isSymbolicLink(), true)
2611+
t.equal(fs.statSync(path + '/y').isDirectory(), true)
2612+
t.strictSame(fs.readdirSync(path + '/y'), [])
2613+
t.throws(() => fs.readFileSync(path + '/x/ginkoid'), { code: 'ENOENT' })
2614+
t.strictSame(WARNINGS[path], [
2615+
'TAR_ENTRY_ERROR',
2616+
'Cannot extract through symbolic link',
2617+
])
2618+
t.end()
2619+
}
2620+
t.test('async', t => {
2621+
const path = dir + '/async'
2622+
new Unpack({ cwd: path })
2623+
.on('warn', (code, msg) => WARNINGS[path] = [code, msg])
2624+
.on('end', () => check(t, path))
2625+
.end(data)
2626+
})
2627+
t.test('sync', t => {
2628+
const path = dir + '/sync'
2629+
new UnpackSync({ cwd: path })
2630+
.on('warn', (code, msg) => WARNINGS[path] = [code, msg])
2631+
.end(data)
2632+
check(t, path)
2633+
})
2634+
})

0 commit comments

Comments
 (0)