Secure temporary file
You are encouraged to solve this task according to the task description, using any language you may know.
Contents |
[edit] Ada
Ada creates a temporary file whenever the create procedure is called without 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] BBC BASIC
The file is automatically deleted when closed.
file% = FNopentempfile
IF file% = 0 ERROR 100, "Failed to open temp file"
PRINT #file%, "Hello world!"
PTR#file% = 0
INPUT #file%, message$
CLOSE #file%
PRINT message$
END
DEF FNopentempfile
LOCAL pname%, hfile%, chan%
OPEN_EXISTING = 3
FILE_FLAG_DELETE_ON_CLOSE = &4000000
GENERIC_READ = &80000000
GENERIC_WRITE = &40000000
INVALID_HANDLE_VALUE = -1
DIM pname% LOCAL 260
FOR chan% = 5 TO 12
IF @hfile%(chan%) = 0 EXIT FOR
NEXT
IF chan% > 12 THEN = 0
SYS "GetTempFileName", @tmp$, "BBC", 0, pname%
SYS "CreateFile", $$pname%, GENERIC_READ OR GENERIC_WRITE, 0, 0, \
\ OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0 TO hfile%
IF hfile% = INVALID_HANDLE_VALUE THEN = 0
@hfile%(chan%) = hfile%
= chan%
Output:
Hello world!
[edit] C
#include <stdlib.h>The following
#include <stdio.h>
int main(void)
{
FILE *fh = tmpfile(); /* file is automatically deleted when program exits */
/* do stuff with stream "fh" */
fclose(fh);
/* The C standard library also has a tmpnam() function to create a file
for you to open later. But you should not use it because someone else might
be able to open the file from the time it is created by this function to the
time you open it. */
return 0;
}
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char filename[] = "/tmp/prefixXXXXXX";
int fd = mkstemp(filename);
puts(filename);
/* do stuff with file descriptor "fd" */
close(fd);
return 0;
}
[edit] C#
using System;
using System.IO;
Console.WriteLine(Path.GetTempFileName());
[edit] Clojure
user=> (doto (java.io.File/createTempFile "pre" ".suff") .deleteOnExit)
#<File /tmp/pre8116759964152254766.suff>
[edit] D
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] Go
import "io/ioutil"
file_obj, err := ioutil.TempFile("", "foo")
[edit] Groovy
Follows technique of Java example
def file = File.createTempFile( "xxx", ".txt" )
file.deleteOnExit()
println file
Output:
C:\DOCUME~1\ROGER~1.GLO\LOCALS~1\Temp\xxx8918700806071036530.txt
[edit] Haskell
import System.IO
main = do (pathOfTempFile, h) <- openTempFile "." "prefix.suffix" -- first argument is path to directory where you want to put it
-- do stuff with it here; "h" is the Handle to the opened file
return ()
[edit] HicEst
! The "scratch" option opens a file exclusively for the current process.
! A scratch file is automatically deleted upon process termination.
OPEN( FIle='TemporaryAndExclusive', SCRatch, IOStat=ErrNr)
WRITE(FIle='TemporaryAndExclusive') "something"
WRITE(FIle='TemporaryAndExclusive', CLoSe=1) ! explicit "close" deletes file
! Without "scratch" access can be controlled by "denyread", "denywrite", "denyreadwrite" options.
OPEN( FIle='DenyForOthers', DenyREAdWRIte, IOStat=ErrNr)
WRITE(FIle='DenyForOthers') "something"
WRITE(FIle='DenyForOthers', DELETE=1)
[edit] Java
import java.io.File;
try {
// Create temp file
File filename = File.createTempFile("prefix", ".suffix");
// Delete temp file when program exits
filename.deleteOnExit();
System.out.println(filename);
} catch (IOException e) {
}
[edit] Lua
fp = io.tmpfile()
-- do some file operations
fp:close()
[edit] Mathematica
tmp = OpenWrite[]
Close[tmp]
[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] Octave
Octave has several related functions
[FID, MSG] = tmpfile(); % Return the file ID corresponding to a new temporary
filename = tmpnam (...); % generates temporary file name, but does not open file
[FID, NAME, MSG] = mkstemp (TEMPLATE, DELETE); % Return the file ID corresponding to a new temporary file with a unique name created from TEMPLATE.
[edit] Pascal
Program TempFileDemo;
uses
SysUtils;
var
tempFile: text;
begin
assign (Tempfile, GetTempFileName);
rewrite (tempFile);
writeln (tempFile, 5);
close (tempFile);
end.
[edit] Perl
function interface:
use File::Temp qw(tempfile);
$fh = tempfile();
($fh2, $filename) = tempfile(); # this file stays around by default
print "$filename\n";
close $fh;
close $fh2;
object-oriented interface:
use File::Temp;
$fh = new File::Temp;
print $fh->filename, "\n";
close $fh;
[edit] PHP
$fh = tmpfile();
// do stuff with $fh
fclose($fh);
// file removed when closed
// or:
$filename = tempnam('/tmp', 'prefix');
echo "$filename\n";
// open $filename and do stuff with it
[edit] PicoLisp
The 'tmp' function returns temporary file names which are exclusively for the current process (based on the process ID). These files are automatically deleted upon process termination. Background tasks within a single PicoLisp process is always non-preemptive, therefore dedicated locks are usually not necessary. If they are (e.g. because such a file name is passed to a child process), explicit locks with the 'ctl' functions are possible.
: (out (tmp "foo") (println 123)) # Write tempfile
-> 123
: (in (tmp "foo") (read)) # Read tempfile
-> 123
: (let F (tmp "foo")
(ctl F # Get exclusive lock
(let N (in F (read)) # Atomic increment
(out F (println (inc N))) ) ) )
-> 124
[edit] PureBasic
Procedure.s TempFile()
Protected a, Result$
For a = 0 To 9999
Result$ = GetTemporaryDirectory() + StringField(GetFilePart(ProgramFilename()),1,".")
Result$ + "_" + Str(ElapsedMilliseconds()) + "_(" + RSet(Str(a),4,"0") + ").tmp"
If FileSize(Result$) = -1 ; -1 = File not found
ProcedureReturn Result$
EndIf
Next
ProcedureReturn ""
EndProcedure
Define File, File$
File$ = TempFile()
If File$ <> ""
File = CreateFile(#PB_Any, File$)
If File <> 0
WriteString(File, "Some temporary data here...")
CloseFile(File)
EndIf
EndIf
[edit] Python
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] Racket
#lang racket
(make-temporary-file)
[edit] Ruby
irb(main):001:0> require 'tempfile'
=> true
irb(main):002:0> f = Tempfile.new('foo')
=> #<File:/tmp/foo20081226-307-10p746n-0>
irb(main):003:0> f.path
=> "/tmp/foo20081226-307-10p746n-0"
irb(main):004:0> f.close
=> nil
[edit] Scala
Basically same as Java version.
import java.io.File
try {
// Create temp file
val filename = File.createTempFile("prefix", ".suffix")
// Delete temp file when program exits
filename.deleteOnExit
System.out.println(filename)
} catch {
case _: java.io.IOException =>
}
[edit] Standard ML
val filename = OS.FileSys.tmpName ();
[edit] Tcl
Will store the name of the file in the variable filenameVar and an open read-write channel on the file in the variable chan.
set chan [file tempfile filenameVar]
Note that because we're asking for the filename in the script, Tcl does not automatically clean the file. (There are cases where auto-cleaning would be really unwanted.) If we hadn't asked for it, the file would be automatically deleted (at a time that depends on platform constraints).
[edit] TUSCRIPT
$$ MODE TUSCRIPT
tmpfile="test.txt"
ERROR/STOP CREATE (tmpfile,seq-E,-std-)
text="hello world"
FILE $tmpfile = text
- tmpfile "test.txt" can only be accessed by one user an will be deleted upon programm termination
[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
TRY=$(( TRY + 1 ))
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).
- Programming Tasks
- Programming environment operations
- Ada
- BBC BASIC
- C
- C sharp
- Clojure
- D
- Go
- Groovy
- Haskell
- HicEst
- Java
- Lua
- Mathematica
- OCaml
- Octave
- Pascal
- SysUtils
- Perl
- PHP
- PicoLisp
- PureBasic
- Python
- Racket
- Ruby
- Scala
- Standard ML
- Tcl
- TUSCRIPT
- UNIX Shell
- HTML/Omit
- Locomotive Basic/Omit
- Lotus 123 Macro Scripting/Omit
- Maxima/Omit
- ML/I/Omit
- Openscad/Omit
- PARI/GP/Omit
- TI-89 BASIC/Omit
- ZX Spectrum Basic/Omit
- File handling