Skip to content

Commit 85d3a94

Browse files
committed
Remove paths from dirCache when no longer dirs
1 parent 9c393bb commit 85d3a94

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
@@ -313,6 +313,20 @@ class Unpack extends Parser {
313313
// check if a thing is there, and if so, try to clobber it
314314
[CHECKFS] (entry) {
315315
this[PEND]()
316+
317+
// if we are not creating a directory, and the path is in the dirCache,
318+
// then that means we are about to delete the directory we created
319+
// previously, and it is no longer going to be a directory, and neither
320+
// is any of its children.
321+
if (entry.type !== 'Directory') {
322+
for (const path of this.dirCache.keys()) {
323+
if (path === entry.absolute ||
324+
path.indexOf(entry.absolute + '/') === 0 ||
325+
path.indexOf(entry.absolute + '\\') === 0)
326+
this.dirCache.delete(path)
327+
}
328+
}
329+
316330
this[MKDIR](path.dirname(entry.absolute), this.dmode, er => {
317331
if (er)
318332
return this[ONERROR](er, entry)
@@ -374,6 +388,15 @@ class UnpackSync extends Unpack {
374388
}
375389

376390
[CHECKFS] (entry) {
391+
if (entry.type !== 'Directory') {
392+
for (const path of this.dirCache.keys()) {
393+
if (path === entry.absolute ||
394+
path.indexOf(entry.absolute + '/') === 0 ||
395+
path.indexOf(entry.absolute + '\\') === 0)
396+
this.dirCache.delete(path)
397+
}
398+
}
399+
377400
const er = this[MKDIR](path.dirname(entry.absolute), this.dmode)
378401
if (er)
379402
return this[ONERROR](er, entry)

test/unpack.js

+52
Original file line numberDiff line numberDiff line change
@@ -1890,3 +1890,55 @@ t.test('chown implicit dirs and also the entries', t => {
18901890

18911891
return tests()
18921892
})
1893+
1894+
t.test('drop entry from dirCache if no longer a directory', t => {
1895+
const dir = path.resolve(unpackdir, 'dir-cache-error')
1896+
mkdirp.sync(dir + '/sync/y')
1897+
mkdirp.sync(dir + '/async/y')
1898+
const data = makeTar([
1899+
{
1900+
path: 'x',
1901+
type: 'Directory',
1902+
},
1903+
{
1904+
path: 'x',
1905+
type: 'SymbolicLink',
1906+
linkpath: './y',
1907+
},
1908+
{
1909+
path: 'x/ginkoid',
1910+
type: 'File',
1911+
size: 'ginkoid'.length,
1912+
},
1913+
'ginkoid',
1914+
'',
1915+
'',
1916+
])
1917+
t.plan(2)
1918+
const WARNINGS = {}
1919+
const check = (t, path) => {
1920+
t.equal(fs.statSync(path + '/x').isDirectory(), true)
1921+
t.equal(fs.lstatSync(path + '/x').isSymbolicLink(), true)
1922+
t.equal(fs.statSync(path + '/y').isDirectory(), true)
1923+
t.strictSame(fs.readdirSync(path + '/y'), [])
1924+
t.throws(() => fs.readFileSync(path + '/x/ginkoid'), { code: 'ENOENT' })
1925+
t.strictSame(WARNINGS[path], [
1926+
'Cannot extract through symbolic link',
1927+
])
1928+
t.end()
1929+
}
1930+
t.test('async', t => {
1931+
const path = dir + '/async'
1932+
new Unpack({ cwd: path })
1933+
.on('warn', (msg) => WARNINGS[path] = [msg])
1934+
.on('end', () => check(t, path))
1935+
.end(data)
1936+
})
1937+
t.test('sync', t => {
1938+
const path = dir + '/sync'
1939+
new UnpackSync({ cwd: path })
1940+
.on('warn', (msg) => WARNINGS[path] = [msg])
1941+
.end(data)
1942+
check(t, path)
1943+
})
1944+
})

0 commit comments

Comments
 (0)