diff --git a/NEWS.md b/NEWS.md index ed8e1d1399b76..2b1660c359667 100644 --- a/NEWS.md +++ b/NEWS.md @@ -385,6 +385,9 @@ This section lists changes that do not have deprecation warnings. to get the old behavior (only "space" characters are considered as word separators), use the keyword `wordsep=isspace`. + * The `tempname` function used to create a file on Windows but not on other + platforms. It now never creates a file ([#9053]). + Library improvements -------------------- diff --git a/base/deprecated.jl b/base/deprecated.jl index d21c9c483d98b..919910f43bd94 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2785,6 +2785,13 @@ end @deprecate findin(a, b) find(occursin(b), a) +# issue #9053 + +if Sys.iswindows() +function Filesystem.tempname(uunique::UInt32) + error("`tempname(::UInt32)` is discontinued.") +end +end # END 0.7 deprecations diff --git a/base/file.jl b/base/file.jl index 846da9b8eddae..65899278136c7 100644 --- a/base/file.jl +++ b/base/file.jl @@ -265,9 +265,9 @@ function tempdir() resize!(temppath,lentemppath) return transcode(String, temppath) end -tempname(uunique::UInt32=UInt32(0)) = tempname(tempdir(), uunique) + const temp_prefix = cwstring("jl_") -function tempname(temppath::AbstractString,uunique::UInt32) +function _win_tempname(temppath::AbstractString, uunique::UInt32) tempp = cwstring(temppath) tname = Vector{UInt16}(uninitialized, 32767) uunique = ccall(:GetTempFileNameW,stdcall,UInt32,(Ptr{UInt16},Ptr{UInt16},UInt32,Ptr{UInt16}), tempp,temp_prefix,uunique,tname) @@ -280,7 +280,7 @@ function tempname(temppath::AbstractString,uunique::UInt32) end function mktemp(parent=tempdir()) - filename = tempname(parent, UInt32(0)) + filename = _win_tempname(parent, UInt32(0)) return (filename, Base.open(filename, "r+")) end @@ -290,7 +290,7 @@ function mktempdir(parent=tempdir()) if (seed & typemax(UInt16)) == 0 seed += 1 end - filename = tempname(parent, seed) + filename = _win_tempname(parent, seed) ret = ccall(:_wmkdir, Int32, (Ptr{UInt16},), cwstring(filename)) if ret == 0 return filename @@ -300,6 +300,20 @@ function mktempdir(parent=tempdir()) end end +function tempname() + seed::UInt32 = rand(UInt32) + while true + if (seed & typemax(UInt16)) == 0 + seed += 1 + end + filename = _win_tempname(parent, seed) + if filemode(filename) == 0 + return filename + end + seed += 1 + end +end + else # !windows # Obtain a temporary filename. function tempname() @@ -344,6 +358,12 @@ tempdir() tempname() Generate a unique temporary file path. + +!!! warning + + This can lead to race conditions if another process obtains the same + file name and creates the file before you are able to. + Using [`mktemp()`](@ref) is recommended instead. """ tempname() diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index fb6c808eb161c..1331f8571a599 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -633,19 +633,13 @@ function build!(pkgs::Vector, seen::Set, errfile::AbstractString) end function build!(pkgs::Vector, errs::Dict, seen::Set=Set()) - errfile = tempname() - touch(errfile) # create empty file - try + mktemp() do errfile, f build!(pkgs, seen, errfile) - open(errfile, "r") do f - while !eof(f) - pkg = deserialize(f) - err = deserialize(f) - errs[pkg] = err - end + while !eof(f) + pkg = deserialize(f) + err = deserialize(f) + errs[pkg] = err end - finally - isfile(errfile) && Base.rm(errfile) end end