@@ -301,11 +301,12 @@ export function patcher(roots: string[]): () => void {
301301 ) {
302302 if ( err ) return cb ( err )
303303 const resolved = resolvePathLike ( args [ 0 ] )
304- const str = path . resolve ( path . dirname ( resolved ) , p ! )
305- const escapedRoot : string | false = isEscape ( resolved , str )
304+ const linkTarget = p !
305+ const targetAbs = path . resolve ( path . dirname ( resolved ) , linkTarget )
306+ const escapedRoot : string | false = isEscape ( resolved , targetAbs )
306307 if ( escapedRoot ) {
307308 const escapedRoots = [ escapedRoot ]
308- return nextHop ( str , readlinkNextHopCb )
309+ return nextHop ( targetAbs , readlinkNextHopCb )
309310
310311 function readlinkNextHopCb ( next : string | undefined | false ) {
311312 if ( ! next ) {
@@ -319,16 +320,20 @@ export function patcher(roots: string[]): () => void {
319320 }
320321 const r = path . resolve (
321322 path . dirname ( resolved ) ,
322- path . relative ( path . dirname ( str ) , next )
323+ path . relative ( path . dirname ( targetAbs ) , next )
323324 )
324325 if ( r != resolved && ! isEscape ( resolved , r , escapedRoots ) ) {
325- return cb ( null , r )
326+ if ( path . isAbsolute ( linkTarget ) ) {
327+ return cb ( null , r )
328+ }
329+ const rel = path . relative ( path . dirname ( resolved ) , r )
330+ return cb ( null , rel || '.' )
326331 }
327332 // The escape from the root is not mappable back into the root; throw EINVAL
328333 return cb ( einval ( 'readlink' , args [ 0 ] ) )
329334 }
330335 } else {
331- return cb ( null , str )
336+ return cb ( null , linkTarget )
332337 }
333338 }
334339
@@ -339,15 +344,12 @@ export function patcher(roots: string[]): () => void {
339344 ...args : Parameters < typeof origReadlinkSync >
340345 ) {
341346 const resolved = resolvePathLike ( args [ 0 ] )
347+ const linkTarget = origReadlinkSync ( ...args )
348+ const targetAbs = path . resolve ( path . dirname ( resolved ) , linkTarget )
342349
343- const str = path . resolve (
344- path . dirname ( resolved ) ,
345- origReadlinkSync ( ...args )
346- )
347-
348- const escapedRoot : string | false = isEscape ( resolved , str )
350+ const escapedRoot : string | false = isEscape ( resolved , targetAbs )
349351 if ( escapedRoot ) {
350- const next = nextHopSync ( str )
352+ const next = nextHopSync ( targetAbs )
351353 if ( ! next ) {
352354 if ( next == undefined ) {
353355 // The escape from the root is not mappable back into the root; throw EINVAL
@@ -359,15 +361,19 @@ export function patcher(roots: string[]): () => void {
359361 }
360362 const r = path . resolve (
361363 path . dirname ( resolved ) ,
362- path . relative ( path . dirname ( str ) , next )
364+ path . relative ( path . dirname ( targetAbs ) , next )
363365 )
364366 if ( r != resolved && ! isEscape ( resolved , r , [ escapedRoot ] ) ) {
365- return r
367+ if ( path . isAbsolute ( linkTarget ) ) {
368+ return r
369+ }
370+ const rel = path . relative ( path . dirname ( resolved ) , r )
371+ return rel || '.'
366372 }
367373 // The escape from the root is not mappable back into the root; throw EINVAL
368374 throw einval ( 'readlink' , args [ 0 ] )
369375 }
370- return str
376+ return linkTarget
371377 }
372378
373379 // =========================================================================
0 commit comments