- Tcl offered file tempfile for creating temporary files.
- Tcllib provides commands for tempdir and tempfile:
http://tcllib.sourceforge.net/doc/fileutil.html
The temp directory is put in to different environment variables on different systems. Examples are:Mac OS X: TMPDIR (tested on 10.8.5) Windows 2000: TMP and TEMP (tested on Windows 2000 SP3) CygWin: TMP and TEMP (tested on Cygwin 1.7.9)A scriptlet to do this:
set tmpdir [pwd]
if {[file exists "/tmp"]} { set tmpdir "/tmp"}
catch {set tmpdir $::env(TRASH_FOLDER)} ;# very old Machintosh. Mac OS X doesn't have this.
catch {set tmpdir $::env(TMP)}
catch {set tmpdir $::env(TEMP)}If you just want one temp file:set filename [file join $tmpdir [pid]]If you want multiple tmpfiles, consider appending things like the application name, counter, time stamp, etc. For example:
set file [file join $tmpdir $appname.[pid].[incr ::globalCounter]]DKF - Or create in a subdirectory/subfolder
if {![file exists [file join $tmpdir [pid]]]} {
file mkdir [file join $tmpdir [pid]]
}
set file [file join $tmpdir [pid] [incr ::globalCounter]]Michael Schlenker - Be aware of potential race conditions while opening temp files. The linux secure programming howto has some nice examples for the linux platform: http://en.tldp.org/HOWTO/Secure-Programs-HOWTO/avoid-race.html
To be sure to get a new tempfile (and not some evil symlink) try something like: set access [list RDWR CREAT EXCL TRUNC]
set perm 0600
if {[catch {open $file $access $perm} fid ]} {
# something went wrong
error "Could not open tempfile."
}
# ok everything went wellI had some luck with the following procedure on a UNIX box. Maybe, somebody can check if it works for windows.
proc tempfile {prefix suffix} {
set chars "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
set nrand_chars 10
set maxtries 10
set access [list RDWR CREAT EXCL TRUNC]
set permission 0600
set channel ""
set checked_dir_writable 0
set mypid [pid]
for {set i 0} {$i < $maxtries} {incr i} {
set newname $prefix
for {set j 0} {$j < $nrand_chars} {incr j} {
append newname [string index $chars \
[expr ([clock clicks] ^ $mypid) % 62]]
}
append newname $suffix
if {[file exists $newname]} {
after 1
} else {
if {[catch {open $newname $access $permission} channel]} {
if {!$checked_dir_writable} {
set dirname [file dirname $newname]
if {![file writable $dirname]} {
error "Directory $dirname is not writable"
}
set checked_dir_writable 1
}
} else {
# Success
return [list $newname $channel]
}
}
}
if {[string compare $channel ""]} {
error "Failed to open a temporary file: $chanel"
} else {
error "Failed to find an unused temporary file name"
}
}Igor VolobouevStu - My version of mkstemp(3)
proc randazAZchar {} {
return [format %c [expr {int(rand() * 26) + [expr {int(rand() * 10) > 5 ? 97 : 65}]}]]
}
proc randazAZstring {length} {
set s {}
for {set i $length} {$i > 0} {incr i -1} {append s [randazAZchar]}
return $s
}
proc makeTempFile {template} {
if {[set xi [string first "X" $template]] == -1} {
set n $template
set p {}
set rl 0
} else {
set n [string range $template 0 [expr {$xi - 1}]]
set p [pid]
set rl [expr {[string length $template] - $xi - [string length $p]}]
if {$rl < 0} {
set p [string range $p 0 end-[expr {$rl * -1}]]
set rl 0
}
}
for {set i [expr {int(pow(26, ($rl <= 6 ? $rl : 6)))}]} {$i > 0} {incr i -1} {
set fn $n[randazAZstring $rl]$p
if {![catch {open $fn {CREAT EXCL RDWR} 0600} fd]} {
file delete $fn
return $fd
}
if {[lindex $::errorCode 1] ne "EEXIST" || [lindex $::errorCode 0] ne "POSIX"} {
break
}
}
return -code error -errorcode $::errorCode $fd
}wldHave a look at GUID and UUID for generating unique filenames for temp-files.
