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

@ -1,2 +1,3 @@
deltest2
/destruct
/x

View file

@ -1 +1 @@
redo deltest deltest2 deltest3
redo deltest deltest2 deltest3 deltest4

View file

@ -1,2 +1,2 @@
rm -rf destruct
rm -rf destruct x
rm -f deltest2 *~ .*~

View file

@ -0,0 +1,3 @@
rm -rf x
mkdir x
echo 'stdout'

View file

@ -0,0 +1,4 @@
rm -rf x
mkdir x
echo 'redir' >$3

View file

@ -10,7 +10,7 @@ cat >destruct2.do <<-EOF
echo 'stdout'
EOF
# deleting unused stdout file is a warning only
# deleting unused stdout file is a warning at most
redo destruct1 2>destruct1.log || exit 11
[ "$(cat destruct1)" = "redir" ] || exit 12

15
t/202-del/deltest4.do Normal file
View file

@ -0,0 +1,15 @@
rm -rf x
redo x/a.spam2
[ "$(cat x/a.spam2)" = "redir" ] || exit 11
redo x/a.spam2
[ "$(cat x/a.spam2)" = "redir" ] || exit 12
redo x/b.spam2
[ "$(cat x/b.spam2)" = "redir" ] || exit 13
rm -rf x
redo x/a.spam1
[ "$(cat x/a.spam1)" = "stdout" ] || exit 21
redo x/a.spam1
[ "$(cat x/a.spam1)" = "stdout" ] || exit 22
redo x/b.spam1
[ "$(cat x/b.spam1)" = "stdout" ] || exit 23