-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mktempdir() now supports prefix. #23237
Changes from 4 commits
5a002bf
2767355
0f4baee
92f70e2
aa3d2be
03c5d7d
8809617
50e7208
b92e612
2406b6e
5e8eecd
b46c74c
9ab6aca
6922ce8
c44461a
ceeb591
daa5575
9944d3d
90a3300
4d4b9ce
706e720
2301d70
14d0b4a
03660a4
d9b7850
11aeba3
f82fc0f
149d108
8c49303
c301095
9b3b2ff
182336d
62d8671
7754b61
6347dbd
0d95a1f
119cf4c
991e26a
299aa48
fc6b0ef
9f61878
ab0ac5e
fd06baa
b510714
de7b893
e89d150
3588102
8150f66
7a54a2f
a059bd7
f6e0fca
6ad3f6e
e6dcc49
27aff73
77c2439
e545c65
c5d5e9a
9f00d84
9ac2b57
e134a36
f9527b7
df9be70
0c10166
5b12051
ff706aa
869112d
05037f5
144c46b
6ff8d13
a48a7d2
d9dde5d
e5c6402
9db5eeb
5645fb2
3f91250
89772d4
6a47db8
4d8f616
7d60a81
36990c7
46bff1b
99c8407
9089b13
15fb3db
109b0b4
d8e5b96
8522ff0
709a639
3573522
1c75a4d
9454cd4
90c91e3
881ab49
e07eabb
c3f5917
644c53c
e9ab77d
7f1623e
00e2075
b104cee
3cb9eb9
b9ce52f
afa6af1
488febc
440b18d
9c6e496
a969c2a
104a81c
f4bb1ba
09f727e
ecf284d
7e35ac6
9d6c9bd
8f6f5aa
88b6487
6210e24
c64a6cc
383b919
b729e58
44fe78c
e0ca7d0
99173bb
bad1329
917e8af
e564008
d4a5553
fc54dc4
a848012
43ced35
6792ad5
aee1aab
92ff781
45b0013
b8536bf
9edfa55
3c68dcd
6a1e339
797e87b
61ee70d
dd7feae
adae830
9cf7505
c2cbef2
2d962c1
8422d50
f5b96f7
81b839d
f4edae1
9cdec25
7e2e6c9
d0bae2b
2e6d908
22ea732
d11a235
ec601e9
e2a4c72
e235f65
75ec2b9
a3de583
c73da15
063f0f8
54a2b01
fdef237
e2ea895
ef2fd5f
447ca30
dbd1574
e0658f2
47986fa
5c6f423
dc4f140
4f8a612
4c0a3e6
ff59aad
10ae1b9
7b6a554
b83b7e9
560aca9
a562e33
f61db81
2bb430e
890080f
503a091
582ba82
be83cac
4502ee4
30530e0
2526b40
a612851
10cf8a2
c31fdea
0e1eb8b
ac37603
54b99d0
0f7ca71
2a133fc
bc68f48
8183c0f
61e4a26
2bdcd5f
f32499f
7bb0d53
1ca3510
508c9f5
d6c9902
db80d86
e21f35a
c5dff37
10af910
e05bd6b
10ed407
5f708e8
34df23e
1c0131c
1e7cc54
f569169
ac148ce
b83c228
8052341
7e7300e
4d9b107
1875957
caad8b2
4c8e693
a06dbef
6d1680a
bc12af5
22987e3
172f36e
15b29bc
45cf132
08c8579
8e12b60
edae2ec
328e099
2a81ce7
a7fe6fb
34b85e4
d33de07
0c13682
7ef0453
9ba55d5
4e9aa66
85aaf04
5e46435
cdc2557
ec07815
b77c048
22c4149
7ab5498
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -254,6 +254,8 @@ function touch(path::AbstractString) | |
end | ||
end | ||
|
||
const temp_prefix = "jl_" | ||
|
||
if Sys.iswindows() | ||
|
||
function tempdir() | ||
|
@@ -265,12 +267,16 @@ function tempdir() | |
resize!(temppath,lentemppath) | ||
return transcode(String, temppath) | ||
end | ||
|
||
tempname(uunique::UInt32=UInt32(0)) = tempname(tempdir(), uunique) | ||
const temp_prefix = cwstring("jl_") | ||
|
||
function tempname(temppath::AbstractString,uunique::UInt32) | ||
tempp = cwstring(temppath) | ||
temppfx = cwstring(temp_prefix) | ||
tname = Vector{UInt16}(32767) | ||
uunique = ccall(:GetTempFileNameW,stdcall,UInt32,(Ptr{UInt16},Ptr{UInt16},UInt32,Ptr{UInt16}), tempp,temp_prefix,uunique,tname) | ||
uunique = ccall(:GetTempFileNameW,stdcall,UInt32, | ||
(Ptr{UInt16}, Ptr{UInt16}, UInt32, Ptr{UInt16}), | ||
tempp, temppfx, uunique, tname) | ||
lentname = findfirst(tname,0)-1 | ||
if uunique == 0 || lentname <= 0 | ||
error("GetTempFileName failed: $(Libc.FormatMessage())") | ||
|
@@ -284,22 +290,6 @@ function mktemp(parent=tempdir()) | |
return (filename, Base.open(filename, "r+")) | ||
end | ||
|
||
function mktempdir(parent=tempdir()) | ||
seed::UInt32 = rand(UInt32) | ||
while true | ||
if (seed & typemax(UInt16)) == 0 | ||
seed += 1 | ||
end | ||
filename = tempname(parent, seed) | ||
ret = ccall(:_wmkdir, Int32, (Ptr{UInt16},), cwstring(filename)) | ||
if ret == 0 | ||
return filename | ||
end | ||
systemerror(:mktempdir, Libc.errno()!=Libc.EEXIST) | ||
seed += 1 | ||
end | ||
end | ||
|
||
else # !windows | ||
# Obtain a temporary filename. | ||
function tempname() | ||
|
@@ -322,13 +312,6 @@ function mktemp(parent=tempdir()) | |
return (b, fdio(p, true)) | ||
end | ||
|
||
# Create and return the name of a temporary directory | ||
function mktempdir(parent=tempdir()) | ||
b = joinpath(parent, "tmpXXXXXX") | ||
p = ccall(:mkdtemp, Cstring, (Cstring,), b) | ||
systemerror(:mktempdir, p == C_NULL) | ||
return unsafe_string(p) | ||
end | ||
|
||
end # os-test | ||
|
||
|
@@ -356,12 +339,33 @@ is an open file object for this path. | |
mktemp(parent) | ||
|
||
""" | ||
mktempdir(parent=tempdir()) | ||
mktempdir(parent=tempdir(); prefix="$temp_prefix") | ||
|
||
Create a temporary directory in the `parent` directory and return its path. | ||
If `parent` does not exist, throw an error. | ||
If `parent` does not exist, throw an error. An optional `prefix` to the directory name can | ||
be provided. | ||
""" | ||
mktempdir(parent) | ||
function mktempdir(parent=tempdir(); prefix="$temp_prefix") | ||
template = prefix*"XXXXXX" | ||
tpath = joinpath(parent, template) | ||
|
||
req = Libc.malloc(_sizeof_uv_fs) | ||
try | ||
ret = ccall(:uv_fs_mkdtemp, Int32, | ||
(Ptr{Void}, Ptr{Void}, Cstring, Ptr{Void}), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incorrect indentation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I followed the same indentation as
|
||
eventloop(), req, tpath, C_NULL) | ||
if ret < 0 | ||
ccall(:uv_fs_req_cleanup, Void, (Ptr{Void},), req) | ||
uv_error("mktempdir", ret) | ||
assert(false) | ||
end | ||
path = unsafe_string(ccall(:jl_uv_fs_t_path, Ptr{Cchar}, (Ptr{Void},), req)) | ||
ccall(:uv_fs_req_cleanup, Void, (Ptr{Void},), req) | ||
return path | ||
finally | ||
Libc.free(req) | ||
end | ||
end | ||
|
||
|
||
""" | ||
|
@@ -381,13 +385,14 @@ function mktemp(fn::Function, parent=tempdir()) | |
end | ||
|
||
""" | ||
mktempdir(f::Function, parent=tempdir()) | ||
mktempdir(f::Function, parent=tempdir(); prefix="$temp_prefix") | ||
|
||
Apply the function `f` to the result of [`mktempdir(parent)`](@ref) and remove the | ||
temporary directory upon completion. | ||
Apply the function `f` to the result of [`mktempdir(parent; prefix)`](@ref) and remove the | ||
temporary directory upon completion. An optional `prefix` to the directory name can | ||
be provided. | ||
""" | ||
function mktempdir(fn::Function, parent=tempdir()) | ||
tmpdir = mktempdir(parent) | ||
function mktempdir(fn::Function, parent=tempdir(); prefix="$temp_prefix") | ||
tmpdir = mktempdir(parent; prefix=prefix) | ||
try | ||
fn(tmpdir) | ||
finally | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1156,3 +1156,46 @@ if !Sys.iswindows() | |
test_22566() | ||
end | ||
end # !Sys.iswindows | ||
|
||
function test_22922() | ||
def_prefix = "jl_" | ||
tst_prefix = "ABCDEF" | ||
mktempdir() do tmpdir | ||
filename = basename(tmpdir) | ||
@test startswith(filename, def_prefix) | ||
end | ||
mktempdir(; prefix=tst_prefix) do tmpdir | ||
filename = basename(tmpdir) | ||
@test startswith(filename, tst_prefix) | ||
end | ||
# Special character prefix tests | ||
tst_prefix="#!@%^&()" | ||
mktempdir(; prefix=tst_prefix) do tmpdir | ||
filename = basename(tmpdir) | ||
@test startswith(filename, tst_prefix) | ||
end | ||
|
||
# Behavioral differences across OS types | ||
if Sys.iswindows() | ||
@test_throws Base.UVError mktempdir(; prefix="*") | ||
@test_throws Base.UVError mktempdir(; prefix="cdcdccd/") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Give me a couple of days. My windows VM is needs some fixing before I can test this. I am a native Linux programmer :-). |
||
else | ||
# '/' is accepted in a prefix but affects the overall path and permissions. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That comment sounds misleading, since There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The whole behavior is very messy. I think we should just not accept '/' in prefix. Some samples:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not too worried about this, as these behaviors make sense, but differences between OSes are annoying. What happens with |
||
@test_throws Base.UVError mktempdir(; prefix="/") | ||
|
||
# The file created will be of format "/tmp/XXXXXX" | ||
mktempdir("/"; prefix="tmp/") do tmpdir | ||
filename = basename(tmpdir) | ||
@test length(filename) == 6 | ||
end | ||
end | ||
|
||
# Unicode test | ||
tst_prefix="\u2200x\u2203y" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Directly use the Unicode chars, that's clearer. |
||
mktempdir(; prefix=tst_prefix) do tmpdir | ||
filename = basename(tmpdir) | ||
@test startswith(filename, tst_prefix) | ||
end | ||
end | ||
|
||
test_22922() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you use the same approach as for
readlink
, butreaddir
uses a different strategy, by usingzeros
, which allows skipping thetry... finally
. @vtjnash Which approach is recommended?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I now get the approach here. In
jl_uv.c
all request structures are allocated in stack (declared as local var) and passed on to the function in the c-layer. The cleanup is carried out on the address to the request like&req
. In the Julia layer you cannot have a stack variable sozero
is a means to create a Juliaarray{UInt8}
which will be memory managed in the Julia layer. Hence, no special action on a throw and clean up will be called on this object after the request object is used in theccall
. The approach is a bit hard to understand initially. Aretry
...catch
overheads very significant? I can change the code to thezero
approach.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would think the simplest approach is the best one, but others must know better.