Skip to content

Commit d759b5b

Browse files
musmKeno
authored andcommitted
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
1 parent ca5642d commit d759b5b

File tree

2 files changed

+31
-12
lines changed

2 files changed

+31
-12
lines changed

base/file.jl

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -517,20 +517,27 @@ function mktemp(parent::AbstractString=tempdir(); cleanup::Bool=true)
517517
return (filename, Base.open(filename, "r+"))
518518
end
519519

520+
# generate a random string from random bytes
521+
function _rand_string()
522+
nchars = 10
523+
A = Vector{UInt8}(undef, nchars)
524+
ccall((:SystemFunction036, :Advapi32), stdcall, UInt8, (Ptr{Cvoid}, UInt32), A, sizeof(A))
525+
526+
slug = Base.StringVector(10)
527+
chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
528+
for i = 1:nchars
529+
slug[i] = chars[(A[i] % length(chars)) + 1]
530+
end
531+
return name = String(slug)
532+
end
533+
520534
function tempname(parent::AbstractString=tempdir(); cleanup::Bool=true)
521535
isdir(parent) || throw(ArgumentError("$(repr(parent)) is not a directory"))
522-
seed::UInt32 = rand(UInt32)
523-
while true
524-
if (seed & typemax(UInt16)) == 0
525-
seed += 1
526-
end
527-
filename = _win_tempname(parent, seed)
528-
if !ispath(filename)
529-
cleanup && temp_cleanup_later(filename)
530-
return filename
531-
end
532-
seed += 1
533-
end
536+
name = _rand_string()
537+
filename = joinpath(parent, temp_prefix * name)
538+
@assert !ispath(filename)
539+
cleanup && temp_cleanup_later(filename)
540+
return filename
534541
end
535542

536543
else # !windows

test/file.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,18 @@ end
5050

5151
using Random
5252

53+
@testset "that temp names are actually unique" begin
54+
temps = [tempname(cleanup=false) for _ = 1:100]
55+
@test allunique(temps)
56+
temps = map(1:100) do _
57+
path, io = mktemp(cleanup=false)
58+
close(io)
59+
rm(path, force=true)
60+
return path
61+
end
62+
@test allunique(temps)
63+
end
64+
5365
@testset "tempname with parent" begin
5466
t = tempname()
5567
@test dirname(t) == tempdir()

0 commit comments

Comments
 (0)