@@ -94,6 +94,17 @@ const uint32 = (a, b, c) =>
9494 : b === b >>> 0 ? b
9595 : c
9696
97+ const pruneCache = ( cache , abs ) => {
98+ // clear the cache if it's a case-insensitive match, since we can't
99+ // know if the current file system is case-sensitive or not.
100+ abs = normPath ( abs ) . toLowerCase ( )
101+ for ( const path of cache . keys ( ) ) {
102+ const plower = path . toLowerCase ( )
103+ if ( plower === abs || plower . toLowerCase ( ) . indexOf ( abs + '/' ) === 0 )
104+ cache . delete ( path )
105+ }
106+ }
107+
97108class Unpack extends Parser {
98109 constructor ( opt ) {
99110 if ( ! opt )
@@ -170,7 +181,7 @@ class Unpack extends Parser {
170181 // links, and removes symlink directories rather than erroring
171182 this . unlink = ! ! opt . unlink
172183
173- this . cwd = path . resolve ( opt . cwd || process . cwd ( ) )
184+ this . cwd = normPath ( path . resolve ( opt . cwd || process . cwd ( ) ) )
174185 this . strip = + opt . strip || 0
175186 this . processUmask = process . umask ( )
176187 this . umask = typeof opt . umask === 'number' ? opt . umask : this . processUmask
@@ -191,24 +202,24 @@ class Unpack extends Parser {
191202
192203 [ CHECKPATH ] ( entry ) {
193204 if ( this . strip ) {
194- const parts = entry . path . split ( / \/ | \\ / )
205+ const parts = normPath ( entry . path ) . split ( '/' )
195206 if ( parts . length < this . strip )
196207 return false
197208 entry . path = parts . slice ( this . strip ) . join ( '/' )
198209 if ( entry . path === '' && entry . type !== 'Directory' && entry . type !== 'GNUDumpDir' )
199210 return false
200211
201212 if ( entry . type === 'Link' ) {
202- const linkparts = entry . linkpath . split ( / \/ | \\ / )
213+ const linkparts = normPath ( entry . linkpath ) . split ( '/' )
203214 if ( linkparts . length >= this . strip )
204215 entry . linkpath = linkparts . slice ( this . strip ) . join ( '/' )
205216 }
206217 }
207218
208219 if ( ! this . preservePaths ) {
209- const p = entry . path
210- if ( p . match ( / ( ^ | \/ | \\ ) \. \. ( \\ | \/ | $ ) / ) ) {
211- this . warn ( ' path contains \ '..\'' , p )
220+ const p = normPath ( entry . path )
221+ if ( p . split ( '/' ) . includes ( '..' ) ) {
222+ this . warn ( ` path contains '..'` , p )
212223 return false
213224 }
214225
@@ -229,9 +240,9 @@ class Unpack extends Parser {
229240 }
230241
231242 if ( path . isAbsolute ( entry . path ) )
232- entry . absolute = entry . path
243+ entry . absolute = normPath ( entry . path )
233244 else
234- entry . absolute = path . resolve ( this . cwd , entry . path )
245+ entry . absolute = normPath ( path . resolve ( this . cwd , entry . path ) )
235246
236247 return true
237248 }
@@ -276,7 +287,7 @@ class Unpack extends Parser {
276287 }
277288
278289 [ MKDIR ] ( dir , mode , cb ) {
279- mkdir ( dir , {
290+ mkdir ( normPath ( dir ) , {
280291 uid : this . uid ,
281292 gid : this . gid ,
282293 processUid : this . processUid ,
@@ -408,7 +419,8 @@ class Unpack extends Parser {
408419 }
409420
410421 [ HARDLINK ] ( entry , done ) {
411- this [ LINK ] ( entry , path . resolve ( this . cwd , entry . linkpath ) , 'link' , done )
422+ const linkpath = normPath ( path . resolve ( this . cwd , entry . linkpath ) )
423+ this [ LINK ] ( entry , linkpath , 'link' , done )
412424 }
413425
414426 [ PEND ] ( ) {
@@ -444,14 +456,8 @@ class Unpack extends Parser {
444456 // then that means we are about to delete the directory we created
445457 // previously, and it is no longer going to be a directory, and neither
446458 // is any of its children.
447- if ( entry . type !== 'Directory' ) {
448- for ( const path of this . dirCache . keys ( ) ) {
449- if ( path === entry . absolute ||
450- path . indexOf ( entry . absolute + '/' ) === 0 ||
451- path . indexOf ( entry . absolute + '\\' ) === 0 )
452- this . dirCache . delete ( path )
453- }
454- }
459+ if ( entry . type !== 'Directory' )
460+ pruneCache ( this . dirCache , entry . absolute )
455461
456462 const paths = [ entry . path ]
457463 if ( entry . linkpath )
@@ -508,7 +514,7 @@ class Unpack extends Parser {
508514 }
509515
510516 [ LINK ] ( entry , linkpath , link , done ) {
511- // XXX: get the type ('file ' or 'dir ') for windows
517+ // XXX: get the type ('symlink ' or 'junction ') for windows
512518 fs [ link ] ( linkpath , entry . absolute , er => {
513519 if ( er )
514520 return this [ ONERROR ] ( er , entry )
@@ -525,14 +531,8 @@ class UnpackSync extends Unpack {
525531 }
526532
527533 [ CHECKFS ] ( entry ) {
528- if ( entry . type !== 'Directory' ) {
529- for ( const path of this . dirCache . keys ( ) ) {
530- if ( path === entry . absolute ||
531- path . indexOf ( entry . absolute + '/' ) === 0 ||
532- path . indexOf ( entry . absolute + '\\' ) === 0 )
533- this . dirCache . delete ( path )
534- }
535- }
534+ if ( entry . type !== 'Directory' )
535+ pruneCache ( this . dirCache , entry . absolute )
536536
537537 const er = this [ MKDIR ] ( path . dirname ( entry . absolute ) , this . dmode , neverCalled )
538538 if ( er )
@@ -650,7 +650,7 @@ class UnpackSync extends Unpack {
650650
651651 [ MKDIR ] ( dir , mode ) {
652652 try {
653- return mkdir . sync ( dir , {
653+ return mkdir . sync ( normPath ( dir ) , {
654654 uid : this . uid ,
655655 gid : this . gid ,
656656 processUid : this . processUid ,
0 commit comments