Skip to content

Commit 46fe350

Browse files
committed
Remove paths from dirCache when no longer dirs
1 parent df3aa4d commit 46fe350

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

lib/unpack.js

+23
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,20 @@ class Unpack extends Parser {
414414
// check if a thing is there, and if so, try to clobber it
415415
[CHECKFS] (entry) {
416416
this[PEND]()
417+
418+
// if we are not creating a directory, and the path is in the dirCache,
419+
// then that means we are about to delete the directory we created
420+
// previously, and it is no longer going to be a directory, and neither
421+
// is any of its children.
422+
if (entry.type !== 'Directory') {
423+
for (const path of this.dirCache.keys()) {
424+
if (path === entry.absolute ||
425+
path.indexOf(entry.absolute + '/') === 0 ||
426+
path.indexOf(entry.absolute + '\\') === 0)
427+
this.dirCache.delete(path)
428+
}
429+
}
430+
417431
this[MKDIR](path.dirname(entry.absolute), this.dmode, er => {
418432
if (er)
419433
return this[ONERROR](er, entry)
@@ -475,6 +489,15 @@ class UnpackSync extends Unpack {
475489
}
476490

477491
[CHECKFS] (entry) {
492+
if (entry.type !== 'Directory') {
493+
for (const path of this.dirCache.keys()) {
494+
if (path === entry.absolute ||
495+
path.indexOf(entry.absolute + '/') === 0 ||
496+
path.indexOf(entry.absolute + '\\') === 0)
497+
this.dirCache.delete(path)
498+
}
499+
}
500+
478501
const er = this[MKDIR](path.dirname(entry.absolute), this.dmode)
479502
if (er)
480503
return this[ONERROR](er, entry)

test/unpack.js

+52
Original file line numberDiff line numberDiff line change
@@ -2493,3 +2493,55 @@ t.test('do not reuse hardlinks, only nlink=1 files', t => {
24932493

24942494
t.end()
24952495
})
2496+
2497+
t.test('drop entry from dirCache if no longer a directory', t => {
2498+
const dir = path.resolve(unpackdir, 'dir-cache-error')
2499+
mkdirp.sync(dir + '/sync/y')
2500+
mkdirp.sync(dir + '/async/y')
2501+
const data = makeTar([
2502+
{
2503+
path: 'x',
2504+
type: 'Directory',
2505+
},
2506+
{
2507+
path: 'x',
2508+
type: 'SymbolicLink',
2509+
linkpath: './y',
2510+
},
2511+
{
2512+
path: 'x/ginkoid',
2513+
type: 'File',
2514+
size: 'ginkoid'.length,
2515+
},
2516+
'ginkoid',
2517+
'',
2518+
'',
2519+
])
2520+
t.plan(2)
2521+
const WARNINGS = {}
2522+
const check = (t, path) => {
2523+
t.equal(fs.statSync(path + '/x').isDirectory(), true)
2524+
t.equal(fs.lstatSync(path + '/x').isSymbolicLink(), true)
2525+
t.equal(fs.statSync(path + '/y').isDirectory(), true)
2526+
t.strictSame(fs.readdirSync(path + '/y'), [])
2527+
t.throws(() => fs.readFileSync(path + '/x/ginkoid'), { code: 'ENOENT' })
2528+
t.strictSame(WARNINGS[path], [
2529+
'Cannot extract through symbolic link',
2530+
])
2531+
t.end()
2532+
}
2533+
t.test('async', t => {
2534+
const path = dir + '/async'
2535+
new Unpack({ cwd: path })
2536+
.on('warn', (msg) => WARNINGS[path] = [msg])
2537+
.on('end', () => check(t, path))
2538+
.end(data)
2539+
})
2540+
t.test('sync', t => {
2541+
const path = dir + '/sync'
2542+
new UnpackSync({ cwd: path })
2543+
.on('warn', (msg) => WARNINGS[path] = [msg])
2544+
.end(data)
2545+
check(t, path)
2546+
})
2547+
})

0 commit comments

Comments
 (0)