Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I'm using dd with "excl" option. If interrupted with CTRL+C "dd" leaves the the file it has created and not finished to write. I need to clean it up in such case with the trap INT. However, I don't know how to test in such case whether the file existed already before or it was created by dd. In other words whether "excl" has initiated exit from dd or something else. Exit status might not tell it right inside the trap, since other commands can return the same code. Putting the if [ -e file ] before dd would work, but is not atomic. The file can get created by some other app in between. Just need some elegant solution.

share|improve this question
    
All came up now is this: is safe, but in worst case will create file and then delete it instead of not creating in the first place. set +e; if [ -e "$out" ]; then exit 3; fi; dd if=/dev/zero of="$out${$}" bs=256K count=$(($size*4)) conv=excl || { rm -rf $out${$}; exit 4; } mv -n "$out${$}" "$out" || { rm -rf $out${$}; exit 5; } trap cleanup INT TERM ERR EXIT set -e –  azerIO May 12 '11 at 14:06
    
in other words create the file with dd and then try to use "mv" it is atomic to rename it to real name, if error occurs then delete the temporerly named file. Put file test before dd to exclude 99% of the cases when file will not be created because it already exists. Trap must be set correctly also, but its minorr –  azerIO May 12 '11 at 14:18
    
@azerIO: But now you don't know if "$out\$" existed before or was created by you. –  grawity May 12 '11 at 16:08
    
${$} is a PID, so its unique. On finishing it is deleted. –  azerIO May 12 '11 at 16:40
1  
@azerIO: I see. (I thought ${$} equals \$ for some reason.) However, PIDs are only unique for a very short time. I'm used to multi-user servers, so I tend to consider the possibility of network-mounted directories or of malicious users trying to guess the filename... and of course, junk left over after a program crash. Most programs use mktemp or similar methods to ensure the uniqueness of a temporary file. –  grawity May 12 '11 at 19:25

1 Answer 1

up vote 3 down vote accepted

bash and file redirection:

cleanup() {
    exec {fd}>&-
    rm -f "$out"
}

set -e
set -o noclobber
# with noclobber, redirection will fail if output file exists
exec {fd}>"$out" || exit 3
trap "cleanup; exit 4" INT TERM ERR EXIT
# write to already opened file
dd if=/dev/zero of=/dev/fd/$fd bs=256k count=$(( size*4 ))
# alternative to /dev/fd/$fd is redirecting with >&$fd
exec {fd}>&-

Temporary files:

cleanup() {
    rm -f "$temp"
}

set -e
temp=$(mktemp "${out}_XXXXXX") || exit 3
trap "cleanup; exit 4" INT TERM ERR EXIT
dd if=/dev/zero of="$temp" bs=256k count=$(( size*4 ))
mv -n "$temp" "$out"
share|improve this answer
    
The second one is the one I use. In both cases you've described there is a gap between dd and the file existance checking command. If the file gets created in that gap, then we'll overwrite it with dd. If teh excl option is specified with dd then it will not overwrite even in such case. However, on error you won't know whether the file existed and the error occured because of excl or for some other reason. I guess the exit code must be checked, but that's not portable... –  azerIO May 12 '11 at 16:51
    
sorry, I meant this holds only with first solution in second one the drawback is that the file might get created by dd(say 2G) and then it will discover that such name exists, so it has to delete it. Or maybe I could just return it but with a different name... –  azerIO May 12 '11 at 17:01
1  
@azerIO: In both of my examples, the file creation is atomic: in #1, exec {fd}>"$out" dies if $out already exists, so it would work perfectly for your usage. –  grawity May 12 '11 at 19:22
    
My question is: what if after {fd}>"$out" and between dd there a file gets created with the same name? You'll overwrite it or am I missing something? Btw. why not doing filetest via if [ -e "$file" ]? –  azerIO May 12 '11 at 22:30
1  
@azerIO: 1) Impossible, as the > operator itself creates the file (but due to noclobber, only if it did not exist). 2) Because [ is not atomic, as you said yourself. –  grawity May 13 '11 at 4:42

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.