Creating a Secure Temporary File
From Rosetta Code
Programming Task
This is a programming task. It lays out a problem which Rosetta Code users are encouraged to solve, using languages they know.
Contents |
[edit] Ada
Ada creates a temporary file whenever the create procedure is called with file name. That temporary file is automatically deleted at the end of the program creating the file.
This example creates a temporary file, writes to the file, then reads from the file.
with Ada.Text_Io; use Ada.Text_Io; procedure Temp_File is Temp : File_Type; Contents : String(1..80); Length : Natural; begin -- Create a temporary file Create(File => Temp); Put_Line(File => Temp, Item => "Hello World"); Reset(File => Temp, Mode => In_File); Get_Line(File => Temp, Item => Contents, Last => Length); Put_Line(Contents(1..Length)); end Temp_File;
[edit] D
Works with: Tango
module tempfile ; import tango.io.TempFile, tango.io.Stdout ; void main(char[][] args) { // create a temporary file that will be deleted automatically when out of scope auto tempTransient = new TempFile(TempFile.Transient) ; Stdout(tempTransient.path()).newline ; // create a temporary file, still persist after the TempFile object has been destroyed auto tempPermanent = new TempFile(TempFile.Permanent) ; Stdout(tempPermanent.path()).newline ; // both can only be accessed by the current user (the program?). }
[edit] OCaml
From the module Filename, one can use the functions temp_file or open_temp_file
# Filename.temp_file "prefix." ".suffix" ;; - : string = "/home/blue_prawn/tmp/prefix.301f82.suffix"
[edit] Python
Works with: Python version 2.3+
In both cases, the temporary file will be deleted automatically when the file is closed. The invisible file will not be accessible on UNIX-like systems. You can use os.link to preserve the visible temporary file contents.
>>> import tempfile >>> invisible = tempfile.TemporaryFile() >>> invisible.name '<fdopen>' >>> visible = tempfile.NamedTemporaryFile() >>> visible.name '/tmp/tmpZNfc_s' >>> visible.close() >>> invisible.close()
More low level way, if you have special needs. This was the only option before Python 2.3:
fd, path = tempfile.mkstemp()
try:
# use the path or the file descriptor
finally:
os.close(fd)
[edit] UNIX Shell
UNIX shell scripts cannot guarantee secure, race-free, exclusive access to an open file descriptor. The best approach to working around this limitation is to create a directory (the mkdir command is a wrapper around the atomic mkdir() system call) and then perform all temporary file operations thereunder.
RESTOREUMASK=$(umask)
TRY=0
while :; do
let TRY+=1 ## No spaces around += operator in let statement!
umask 0077
MYTMP=${TMPDIR:-/tmp}/$(basename $0).$$.$(date +%s).$TRY
trap "rm -fr $MYTMP" EXIT
mkdir "$MYTMP" 2>/dev/null && break
done
umask "$RESTOREUMASK"
cd ""$MYTMP" || {
echo "Temporary directory failure on $MYTMP" >&2
exit 1; }
Note that the shell special variable $$ (the PID of the currently exec()-ed shell) is unique at any given moment on a UNIX system, and $(date +%s) gives the time represented as a number of seconds since the UNIX epoch (GNU date or any other with the %s extension). So any name collision here is most likely "enemy action." This code will loop, picking new names and resetting the trap (clean-up command) until it succeeds in making a directory. (Simple changes to the code could limit the number of attempts or implement a timeout).

