Skip to content

Commit e551cec

Browse files
committed
make tempname on windows match unix behavior. fixes #9053
also deprecate `tempname(::UInt32)` and add a warning to the docs.
1 parent f8bc37b commit e551cec

File tree

4 files changed

+39
-15
lines changed

4 files changed

+39
-15
lines changed

NEWS.md

+3
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,9 @@ This section lists changes that do not have deprecation warnings.
385385
to get the old behavior (only "space" characters are considered as
386386
word separators), use the keyword `wordsep=isspace`.
387387

388+
* The `tempname` function used to create a file on Windows but not on other
389+
platforms. It now never creates a file ([#9053]).
390+
388391
Library improvements
389392
--------------------
390393

base/deprecated.jl

+7
Original file line numberDiff line numberDiff line change
@@ -2785,6 +2785,13 @@ end
27852785

27862786
@deprecate findin(a, b) find(occursin(b), a)
27872787

2788+
# issue #9053
2789+
2790+
if Sys.iswindows()
2791+
function Filesystem.tempname(uunique::UInt32)
2792+
error("`tempname(::UInt32)` is discontinued.")
2793+
end
2794+
end
27882795

27892796
# END 0.7 deprecations
27902797

base/file.jl

+24-4
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,9 @@ function tempdir()
265265
resize!(temppath,lentemppath)
266266
return transcode(String, temppath)
267267
end
268-
tempname(uunique::UInt32=UInt32(0)) = tempname(tempdir(), uunique)
268+
269269
const temp_prefix = cwstring("jl_")
270-
function tempname(temppath::AbstractString,uunique::UInt32)
270+
function _win_tempname(temppath::AbstractString, uunique::UInt32)
271271
tempp = cwstring(temppath)
272272
tname = Vector{UInt16}(uninitialized, 32767)
273273
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)
280280
end
281281

282282
function mktemp(parent=tempdir())
283-
filename = tempname(parent, UInt32(0))
283+
filename = _win_tempname(parent, UInt32(0))
284284
return (filename, Base.open(filename, "r+"))
285285
end
286286

@@ -290,7 +290,7 @@ function mktempdir(parent=tempdir())
290290
if (seed & typemax(UInt16)) == 0
291291
seed += 1
292292
end
293-
filename = tempname(parent, seed)
293+
filename = _win_tempname(parent, seed)
294294
ret = ccall(:_wmkdir, Int32, (Ptr{UInt16},), cwstring(filename))
295295
if ret == 0
296296
return filename
@@ -300,6 +300,20 @@ function mktempdir(parent=tempdir())
300300
end
301301
end
302302

303+
function tempname()
304+
seed::UInt32 = rand(UInt32)
305+
while true
306+
if (seed & typemax(UInt16)) == 0
307+
seed += 1
308+
end
309+
filename = _win_tempname(parent, seed)
310+
if filemode(filename) == 0
311+
return filename
312+
end
313+
seed += 1
314+
end
315+
end
316+
303317
else # !windows
304318
# Obtain a temporary filename.
305319
function tempname()
@@ -344,6 +358,12 @@ tempdir()
344358
tempname()
345359
346360
Generate a unique temporary file path.
361+
362+
!!! warning
363+
364+
This can lead to race conditions if another process obtains the same
365+
file name and creates the file before you are able to.
366+
Using [`mktemp()`](@ref) is recommended instead.
347367
"""
348368
tempname()
349369

base/pkg/entry.jl

+5-11
Original file line numberDiff line numberDiff line change
@@ -633,19 +633,13 @@ function build!(pkgs::Vector, seen::Set, errfile::AbstractString)
633633
end
634634

635635
function build!(pkgs::Vector, errs::Dict, seen::Set=Set())
636-
errfile = tempname()
637-
touch(errfile) # create empty file
638-
try
636+
mktemp() do errfile, f
639637
build!(pkgs, seen, errfile)
640-
open(errfile, "r") do f
641-
while !eof(f)
642-
pkg = deserialize(f)
643-
err = deserialize(f)
644-
errs[pkg] = err
645-
end
638+
while !eof(f)
639+
pkg = deserialize(f)
640+
err = deserialize(f)
641+
errs[pkg] = err
646642
end
647-
finally
648-
isfile(errfile) && Base.rm(errfile)
649643
end
650644
end
651645

0 commit comments

Comments
 (0)