Use mkstemp() to create the stdout temp file, and simplify $3 path.

Previously, we'd try to put the stdout temp file in the same dir as the
target, if that dir exists.  Otherwise we'd walk up the directory tree
looking for a good place.  But this would go wrong if the directory we
chose got *deleted* during the run of the .do file.

Instead, we switch to an entirely new design: we use mkstemp() to
generate a temp file in the standard temp file location (probably
/tmp), then open it and immediately delete it, so the .do file can't
cause any unexpected behaviour.  After the .do file exits, we use our
still-open fd to the stdout file to read the content back out.

In the old implementation, we also put the $3 in the "adjusted"
location that depended whether the target dir already existed, just for
consistency.  But that was never necessary: we didn't create the $3
file, and if the .do script wants to write to $3, it should create the
target dir first anyway.  So change it to *always* use a $3 temp
filename in the target dir, which is much simpler and so has fewer edge
cases.

Add t/202-del/deltest4 with some tests for all these edge cases.

Reported-by: Jeff Stearns <jeff.stearns@gmail.com>
This commit is contained in:
Avery Pennarun 2018-12-12 03:37:44 +00:00
commit d95277d121
10 changed files with 177 additions and 119 deletions

View file

@ -102,31 +102,32 @@ check_s "" "$_dirsplit_base"
SECTION _relpath
check "a/b/c" _relpath "$PWD/a/b/c"
check "../a/b/c" _relpath "$PWD/../a/b/c"
check "" _relpath "$PWD"
(cd / && check "a/b/c" _relpath a/b/c)
(cd / && check "a/b/c" _relpath /a/b/c)
(cd / && check "" _relpath /)
(cd /usr/bin && check "../lib" _relpath /usr/lib)
(cd /usr/bin && check "../lib/" _relpath /usr/lib/)
(cd /usr/bin && check "../.." _relpath /)
(cd fakedir && check ".." _relpath ..)
(cd fakedir && check "../" _relpath ../)
(cd fakedir && check "../fakedir" _relpath ../fakedir)
x=$PWD/x
check "a/b/c" _relpath "$x/a/b/c" "$x"
check "../a/b/c" _relpath "$x/../a/b/c" "$x"
check "" _relpath "$x" "$x"
check "a/b/c" _relpath a/b/c "/"
check "a/b/c" _relpath /a/b/c "/"
check "" _relpath / "/"
check "../lib" _relpath /usr/lib "/usr/bin"
check "../lib/" _relpath /usr/lib/ "/usr/bin"
check "../.." _relpath / "/usr/bin"
check ".." _relpath .. "$PWD/fakedir"
check "../" _relpath ../ "$PWD/fakedir"
check "../fakedir" _relpath ../fakedir "$PWD/fakedir"
SECTION _normpath
check "/usr/lib" _normpath /usr/../usr/bin/../lib
check "/" _normpath /a/b/c/../../..
check "/" _normpath /
check "../a" _normpath ../a
(cd fakedir && check "../a/b" _normpath ../a/b)
(cd fakedir && check ".." _normpath ..)
(cd / && check "tuv" _normpath a/b/../../tuv)
(cd / && check "" _normpath a/b/../..)
check ".." _normpath ../
check ".." _normpath ..
check "/usr/lib" _normpath /usr/../usr/bin/../lib "$x"
check "/" _normpath /a/b/c/../../.. "$x"
check "/" _normpath / "$x"
check "../a" _normpath ../a "$x"
check "../a/b" _normpath ../a/b "$x/fakedir"
check ".." _normpath .. "$x/fakedir"
check "tuv" _normpath a/b/../../tuv "/"
check "" _normpath a/b/../.. "/"
check ".." _normpath ../ "$x"
check ".." _normpath .. "$x"
SECTION _find_dofile