From 8f6734b670ac07b434947571ce523c038e93e76c Mon Sep 17 00:00:00 2001 From: Mustafa M Date: Sat, 18 Jan 2020 13:21:19 -0500 Subject: [PATCH] Use UUID's to generate random tempname on Windows (#33785) * Use UIUD to create random tempname on Windows * Use underscores and remove extension * Truncate to 10 chars the UUID * Generate the random name from a random byte array * Update file.jl --- base/file.jl | 31 +++++++++++++++++++------------ test/file.jl | 12 ++++++++++++ 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/base/file.jl b/base/file.jl index 094327922dcc5f..6d4fca5fda8c58 100644 --- a/base/file.jl +++ b/base/file.jl @@ -517,20 +517,27 @@ function mktemp(parent::AbstractString=tempdir(); cleanup::Bool=true) return (filename, Base.open(filename, "r+")) end +# generate a random string from random bytes +function _rand_string() + nchars = 10 + A = Vector{UInt8}(undef, nchars) + ccall((:SystemFunction036, :Advapi32), stdcall, UInt8, (Ptr{Cvoid}, UInt32), A, sizeof(A)) + + slug = Base.StringVector(10) + chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + for i = 1:nchars + slug[i] = chars[(A[i] % length(chars)) + 1] + end + return name = String(slug) +end + function tempname(parent::AbstractString=tempdir(); cleanup::Bool=true) isdir(parent) || throw(ArgumentError("$(repr(parent)) is not a directory")) - seed::UInt32 = rand(UInt32) - while true - if (seed & typemax(UInt16)) == 0 - seed += 1 - end - filename = _win_tempname(parent, seed) - if !ispath(filename) - cleanup && temp_cleanup_later(filename) - return filename - end - seed += 1 - end + name = _rand_string() + filename = joinpath(parent, temp_prefix * name) + @assert !ispath(filename) + cleanup && temp_cleanup_later(filename) + return filename end else # !windows diff --git a/test/file.jl b/test/file.jl index e15807c0adccb2..ae3ce717060e08 100644 --- a/test/file.jl +++ b/test/file.jl @@ -50,6 +50,18 @@ end using Random +@testset "that temp names are actually unique" begin + temps = [tempname(cleanup=false) for _ = 1:100] + @test allunique(temps) + temps = map(1:100) do _ + path, io = mktemp(cleanup=false) + close(io) + rm(path, force=true) + return path + end + @test allunique(temps) +end + @testset "tempname with parent" begin t = tempname() @test dirname(t) == tempdir()