2016-11-02 15:40:40 +0700, Robert Elz: [...] > | If 'mktemp' were a POSIX standard utility, this wouldn't be an issue, > | but it's not, so it is. > > mktemp certainly makes it easier (and more efficient) to create unique > filenames (and is now ubiquitous enough that it probably ought be added) > but it isn't required - locking can be done without it, and with locking > a scheme can be written which creates files as needed (the lock file isn't > the file ultimately to be created, just a lock - when the lock is owned, > the script no longer needs atomic operations, it can test and create quite > safely.) [...]
You're looking at it from the point of view of locking. As you say, ln or mkdir can be used for that instead. set -C is often used as a way to create a temp file (a poor man's mktemp). And as currently implemented it is not safe. A typical implementation of mktemp as a POSIX shell function is: mktemp() { mktemp_prefix=${TMPDIR:-/tmp}/$1.$$ mktemp_suffix= mktemp_fd=${2-1} case $- in (*C*) mktemp_restore=;; (*) mktemp_restore="set +C"; set -C;; esac mktemp_mask=$(umask) umask 077 || return mktemp_ret=0 mktemp_n=0 until REPLY=$mktemp_prefix$mktemp_suffix eval 'command exec '"$mktemp_fd"'<> "$REPLY"' 2> /dev/null && [ -f "$REPLY" ] && [ ! -L "$REPLY" ] do mktemp_n=$((mktemp_n + 1)) if [ "$mktemp_n" -gt 20 ]; then echo >&2 "Unable to create a temp file after $mktemp_n attemps" eval "command exec $mktemp_fd>&-" 2> /dev/null REPLY= mktemp_ret=1 break fi mktemp_suffix=.$mktemp_n done eval "$mktemp_restore" umask "$mktemp_mask" return "$mktemp_ret" } mktemp "${0##*/}.tmp" 3 || exit echo test >&3 rm -f "$REPLY" Here, the fact that set -C has an internal race condition matters as much as the fact that it will happily open non-regular files. Our [ -f "$REPLY" ] is also racy. The race in set -C means an attacker can make you clobber any file, but even if that race window is closed, that still means an attacker can make you open or clobber any device/fifo file. At the moment, there's no way (that I know) to create a temp file reliably with POSIX utilities (though it may be possible to create a temp dir reliably, which is generally a better idea than creating a temp file in a world writable directory anyway). Or IOW, rather than adding a O_NOCLOBBER open flag to fix that (not very useful) "set -C", it would be more useful to add a proper shell interface to O_EXCL. One to O_NOFOLLOW (or to any arbitrary open flag supported by the system as suggested in that zsh ML thread) would be welcome as well. -- Stephane