@@ -554,15 +554,52 @@ end
554
554
555
555
const temp_prefix = " jl_"
556
556
557
- if Sys. iswindows ()
557
+ # Use `Libc.rand()` to generate random strings
558
+ function _rand_filename (len = 10 )
559
+ slug = Base. StringVector (len)
560
+ chars = b " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
561
+ for i = 1 : len
562
+ slug[i] = chars[(Libc. rand () % length (chars)) + 1 ]
563
+ end
564
+ return String (slug)
565
+ end
566
+
567
+
568
+ # Obtain a temporary filename.
569
+ function tempname (parent:: AbstractString = tempdir (); max_tries:: Int = 100 , cleanup:: Bool = true )
570
+ isdir (parent) || throw (ArgumentError (" $(repr (parent)) is not a directory" ))
571
+
572
+ prefix = joinpath (parent, temp_prefix)
573
+ filename = nothing
574
+ for i in 1 : max_tries
575
+ filename = string (prefix, _rand_filename ())
576
+ if ispath (filename)
577
+ filename = nothing
578
+ else
579
+ break
580
+ end
581
+ end
582
+
583
+ if filename === nothing
584
+ error (" tempname: max_tries exhausted" )
585
+ end
558
586
559
- function _win_tempname (temppath:: AbstractString , uunique:: UInt32 )
587
+ cleanup && temp_cleanup_later (filename)
588
+ return filename
589
+ end
590
+
591
+ if Sys. iswindows ()
592
+ # While this isn't a true analog of `mkstemp`, it _does_ create an
593
+ # empty file for us, ensuring that other simultaneous calls to
594
+ # `_win_mkstemp()` won't collide, so it's a better name for the
595
+ # function than `tempname()`.
596
+ function _win_mkstemp (temppath:: AbstractString )
560
597
tempp = cwstring (temppath)
561
598
temppfx = cwstring (temp_prefix)
562
599
tname = Vector {UInt16} (undef, 32767 )
563
600
uunique = ccall (:GetTempFileNameW , stdcall, UInt32,
564
601
(Ptr{UInt16}, Ptr{UInt16}, UInt32, Ptr{UInt16}),
565
- tempp, temppfx, uunique , tname)
602
+ tempp, temppfx, UInt32 ( 0 ) , tname)
566
603
windowserror (" GetTempFileName" , uunique == 0 )
567
604
lentname = something (findfirst (iszero, tname))
568
605
@assert lentname > 0
@@ -571,49 +608,13 @@ function _win_tempname(temppath::AbstractString, uunique::UInt32)
571
608
end
572
609
573
610
function mktemp (parent:: AbstractString = tempdir (); cleanup:: Bool = true )
574
- filename = _win_tempname (parent, UInt32 ( 0 ) )
611
+ filename = _win_mkstemp (parent)
575
612
cleanup && temp_cleanup_later (filename)
576
613
return (filename, Base. open (filename, " r+" ))
577
614
end
578
615
579
- # generate a random string from random bytes
580
- function _rand_string ()
581
- nchars = 10
582
- A = Vector {UInt8} (undef, nchars)
583
- windowserror (" SystemFunction036 (RtlGenRandom)" , 0 == ccall (
584
- (:SystemFunction036 , :Advapi32 ), stdcall, UInt8, (Ptr{Cvoid}, UInt32),
585
- A, sizeof (A)))
586
-
587
- slug = Base. StringVector (10 )
588
- chars = " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
589
- for i = 1 : nchars
590
- slug[i] = chars[(A[i] % length (chars)) + 1 ]
591
- end
592
- return name = String (slug)
593
- end
594
-
595
- function tempname (parent:: AbstractString = tempdir (); cleanup:: Bool = true )
596
- isdir (parent) || throw (ArgumentError (" $(repr (parent)) is not a directory" ))
597
- name = _rand_string ()
598
- filename = joinpath (parent, temp_prefix * name)
599
- @assert ! ispath (filename)
600
- cleanup && temp_cleanup_later (filename)
601
- return filename
602
- end
603
-
604
616
else # !windows
605
617
606
- # Obtain a temporary filename.
607
- function tempname (parent:: AbstractString = tempdir (); cleanup:: Bool = true )
608
- isdir (parent) || throw (ArgumentError (" $(repr (parent)) is not a directory" ))
609
- p = ccall (:tempnam , Cstring, (Cstring, Cstring), parent, temp_prefix)
610
- systemerror (:tempnam , p == C_NULL )
611
- s = unsafe_string (p)
612
- Libc. free (p)
613
- cleanup && temp_cleanup_later (s)
614
- return s
615
- end
616
-
617
618
# Create and return the name of a temporary file along with an IOStream
618
619
function mktemp (parent:: AbstractString = tempdir (); cleanup:: Bool = true )
619
620
b = joinpath (parent, temp_prefix * " XXXXXX" )
@@ -623,7 +624,6 @@ function mktemp(parent::AbstractString=tempdir(); cleanup::Bool=true)
623
624
return (b, fdio (p, true ))
624
625
end
625
626
626
-
627
627
end # os-test
628
628
629
629
0 commit comments