diff --git a/base/file.jl b/base/file.jl index e557ffe9d1106..c3d246f61835b 100644 --- a/base/file.jl +++ b/base/file.jl @@ -554,76 +554,25 @@ end const temp_prefix = "jl_" -if Sys.iswindows() - -function _win_tempname(temppath::AbstractString, uunique::UInt32) - tempp = cwstring(temppath) - temppfx = cwstring(temp_prefix) - tname = Vector{UInt16}(undef, 32767) - uunique = ccall(:GetTempFileNameW, stdcall, UInt32, - (Ptr{UInt16}, Ptr{UInt16}, UInt32, Ptr{UInt16}), - tempp, temppfx, uunique, tname) - windowserror("GetTempFileName", uunique == 0) - lentname = something(findfirst(iszero, tname)) - @assert lentname > 0 - resize!(tname, lentname - 1) - return transcode(String, tname) -end - -function mktemp(parent::AbstractString=tempdir(); cleanup::Bool=true) - filename = _win_tempname(parent, UInt32(0)) - cleanup && temp_cleanup_later(filename) - return (filename, Base.open(filename, "r+")) -end - -# generate a random string from random bytes -function _rand_string() - nchars = 10 - A = Vector{UInt8}(undef, nchars) - windowserror("SystemFunction036 (RtlGenRandom)", 0 == ccall( - (:SystemFunction036, :Advapi32), stdcall, UInt8, (Ptr{Cvoid}, UInt32), - A, sizeof(A))) - - slug = Base.StringVector(10) +# Use `Libc.rand()` to generate random strings +function _rand_filename(len = 10) + slug = Base.StringVector(len) chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - for i = 1:nchars - slug[i] = chars[(A[i] % length(chars)) + 1] + for i = 1:len + slug[i] = chars[(Libc.rand() % length(chars)) + 1] end - return name = String(slug) + return String(slug) end -function tempname(parent::AbstractString=tempdir(); cleanup::Bool=true) - isdir(parent) || throw(ArgumentError("$(repr(parent)) is not a directory")) - name = _rand_string() - filename = joinpath(parent, temp_prefix * name) - @assert !ispath(filename) - cleanup && temp_cleanup_later(filename) - return filename -end - -else # !windows - -# Based of musl __randname -function _rand_string() - r = Base.rand(UInt) # FIXME: https://git.musl-libc.org/cgit/musl/tree/src/temp/__randname.c - buf = Vector{Char}(undef, 6) - for i in 1:6 - buf[i] = 'A'+(r&15)+(r&16)*2; - r >>= 5 - end - String(buf) -end # Obtain a temporary filename. -function tempname(parent::AbstractString=tempdir(); cleanup::Bool=true) +function tempname(parent::AbstractString=tempdir(); max_tries::Int = 100, cleanup::Bool=true) isdir(parent) || throw(ArgumentError("$(repr(parent)) is not a directory")) prefix = joinpath(parent, temp_prefix) - MAX_TRIES = 100 - filename = nothing - for i in 1:MAX_TRIES - filename = string(prefix, _rand_string()) + for i in 1:max_tries + filename = string(prefix, _rand_filename()) if ispath(filename) filename = nothing else @@ -632,13 +581,36 @@ function tempname(parent::AbstractString=tempdir(); cleanup::Bool=true) end if filename === nothing - error("tempname: MAX_TRIES exhausted") + error("tempname: max_tries exhausted") end cleanup && temp_cleanup_later(filename) return filename end +if Sys.iswindows() +function _win_tempname(temppath::AbstractString, uunique::UInt32) + tempp = cwstring(temppath) + temppfx = cwstring(temp_prefix) + tname = Vector{UInt16}(undef, 32767) + uunique = ccall(:GetTempFileNameW, stdcall, UInt32, + (Ptr{UInt16}, Ptr{UInt16}, UInt32, Ptr{UInt16}), + tempp, temppfx, uunique, tname) + windowserror("GetTempFileName", uunique == 0) + lentname = something(findfirst(iszero, tname)) + @assert lentname > 0 + resize!(tname, lentname - 1) + return transcode(String, tname) +end + +function mktemp(parent::AbstractString=tempdir(); cleanup::Bool=true) + filename = _win_tempname(parent, UInt32(0)) + cleanup && temp_cleanup_later(filename) + return (filename, Base.open(filename, "r+")) +end + +else # !windows + # Create and return the name of a temporary file along with an IOStream function mktemp(parent::AbstractString=tempdir(); cleanup::Bool=true) b = joinpath(parent, temp_prefix * "XXXXXX") @@ -648,7 +620,6 @@ function mktemp(parent::AbstractString=tempdir(); cleanup::Bool=true) return (b, fdio(p, true)) end - end # os-test diff --git a/test/file.jl b/test/file.jl index b4983ac5e61c5..a7c0b6dca125d 100644 --- a/test/file.jl +++ b/test/file.jl @@ -117,7 +117,7 @@ end # 38873: check that `TMPDIR` being set does not # override the parent argument to `tempname`. mktempdir() do d - whithenv("TMPDIR"=>tmpdir()) do + withenv("TMPDIR"=>tempdir()) do t = tempname(d) @test dirname(t) == d end