Skip to content

Commit 232855e

Browse files
committed
Merge pull request #12819 from JuliaLang/jn/file_iswritable_cleanup
cleanup of Filesystem-related functions
2 parents 28cd3c7 + 9dae3ec commit 232855e

File tree

20 files changed

+475
-394
lines changed

20 files changed

+475
-394
lines changed

base/deprecated.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,3 +872,24 @@ end
872872
@deprecate chol(A::AbstractMatrix, ::Type{Val{:U}}) chol(A)
873873
@deprecate chol(A::Number, ::Type{Val{:L}}) ctranspose(chol(A))
874874
@deprecate chol(A::AbstractMatrix, ::Type{Val{:L}}) ctranspose(chol(A))
875+
876+
# Filesystem module updates
877+
878+
@deprecate_binding FS Filesystem
879+
880+
isreadable(path...) = isreadable(stat(path...))
881+
iswritable(path...) = iswritable(stat(path...))
882+
isexecutable(path...) = isexecutable(stat(path...))
883+
function isreadable(st::Filesystem.StatStruct)
884+
depwarn("isreadable is deprecated as it implied that the file would actually be readable by the user; consider using `isfile` instead. see also the system man page for `access`", :isreadable)
885+
return (st.mode & 0o444) > 0
886+
end
887+
function iswritable(st::Filesystem.StatStruct)
888+
depwarn("iswritable is deprecated as it implied that the file would actually be writable by the user; consider using `isfile` instead. see also the system man page for `access`", :iswritable)
889+
return (st.mode & 0o222) > 0
890+
end
891+
function isexecutable(st::Filesystem.StatStruct)
892+
depwarn("isexecutable is deprecated as it implied that the file would actually be executable by the user; consider using `isfile` instead. see also the system man page for `access`", :isexecutable)
893+
return (st.mode & 0o111) > 0
894+
end
895+
export isreadable, iswritable, isexecutable

base/docs/helpdb.jl

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2023,13 +2023,6 @@ Reseed the random number generator. If a `seed` is provided, the RNG will give a
20232023
"""
20242024
srand
20252025

2026-
doc"""
2027-
isexecutable(path) -> Bool
2028-
2029-
Returns `true` if the current user has permission to execute `path`, `false` otherwise.
2030-
"""
2031-
isexecutable
2032-
20332026
doc"""
20342027
acot(x)
20352028
@@ -5627,9 +5620,9 @@ Get the fully-qualified name of a module as a tuple of symbols. For example, `fu
56275620
fullname
56285621

56295622
doc"""
5630-
isreadable(path) -> Bool
5623+
isreadable(io) -> Bool
56315624
5632-
Returns `true` if the current user has permission to read `path`, `false` otherwise.
5625+
Returns `true` if the specified IO object is readable (if that can be determined).
56335626
"""
56345627
isreadable
56355628

@@ -10637,9 +10630,9 @@ Create a "value type" out of `c`, which must be an `isbits` value. The intent of
1063710630
Val
1063810631

1063910632
doc"""
10640-
iswritable(path) -> Bool
10633+
iswritable(io) -> Bool
1064110634
10642-
Returns `true` if the current user has permission to write to `path`, `false` otherwise.
10635+
Returns `true` if the specified IO object is writable (if that can be determined).
1064310636
"""
1064410637
iswritable
1064510638

base/file.jl

Lines changed: 113 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
# This file is a part of Julia. License is MIT: http://julialang.org/license
22

3+
# Operations with the file system (paths) ##
4+
5+
export
6+
cd,
7+
chmod,
8+
cp,
9+
cptree,
10+
mkdir,
11+
mkpath,
12+
mktemp,
13+
mktempdir,
14+
mv,
15+
pwd,
16+
rename,
17+
readlink,
18+
readdir,
19+
rm,
20+
samefile,
21+
sendfile,
22+
symlink,
23+
tempdir,
24+
tempname,
25+
touch,
26+
walkdir
27+
328
# get and set current directory
429

530
function pwd()
@@ -65,8 +90,8 @@ mkpath(path::AbstractString, mode::Signed) = throw(ArgumentError("mode must be a
6590

6691
function rm(path::AbstractString; recursive::Bool=false)
6792
if islink(path) || !isdir(path)
68-
@windows_only if !iswritable(path); chmod(path, 0o777); end
69-
FS.unlink(path)
93+
@windows_only if (filemode(path) & 0o222) == 0; chmod(path, 0o777); end # is writable on windows actually means "is deletable"
94+
unlink(path)
7095
else
7196
if recursive
7297
for p in readdir(path)
@@ -116,7 +141,7 @@ function cptree(src::AbstractString, dst::AbstractString; remove_destination::Bo
116141
cptree(srcname, joinpath(dst, name); remove_destination=remove_destination,
117142
follow_symlinks=follow_symlinks)
118143
else
119-
FS.sendfile(srcname, joinpath(dst, name))
144+
sendfile(srcname, joinpath(dst, name))
120145
end
121146
end
122147
end
@@ -129,23 +154,22 @@ function cp(src::AbstractString, dst::AbstractString; remove_destination::Bool=f
129154
elseif isdir(src)
130155
cptree(src, dst; remove_destination=remove_destination, follow_symlinks=follow_symlinks)
131156
else
132-
FS.sendfile(src, dst)
157+
sendfile(src, dst)
133158
end
134159
end
135160

136161
function mv(src::AbstractString, dst::AbstractString; remove_destination::Bool=false)
137162
checkfor_mv_cp_cptree(src, dst, "moving"; remove_destination=remove_destination)
138-
FS.rename(src, dst)
163+
rename(src, dst)
139164
end
140165

141166
function touch(path::AbstractString)
142-
f = FS.open(path,JL_O_WRONLY | JL_O_CREAT, 0o0666)
143-
@assert f.handle >= 0
167+
f = open(path, JL_O_WRONLY | JL_O_CREAT, 0o0666)
144168
try
145169
t = time()
146170
futime(f,t,t)
147171
finally
148-
FS.close(f)
172+
close(f)
149173
end
150174
end
151175

@@ -203,7 +227,7 @@ function tempname(temppath::AbstractString,uunique::UInt32)
203227
end
204228
function mktemp(parent=tempdir())
205229
filename = tempname(parent, UInt32(0))
206-
return (filename, open(filename,"r+"))
230+
return (filename, Base.open(filename, "r+"))
207231
end
208232
function mktempdir(parent=tempdir())
209233
seed::UInt32 = rand(UInt32)
@@ -330,3 +354,83 @@ function walkdir(root; topdown=true, follow_symlinks=false, onerror=throw)
330354
Task(_it)
331355
end
332356

357+
function unlink(p::AbstractString)
358+
err = ccall(:jl_fs_unlink, Int32, (Cstring,), p)
359+
uv_error("unlink", err)
360+
nothing
361+
end
362+
363+
# For move command
364+
function rename(src::AbstractString, dst::AbstractString)
365+
err = ccall(:jl_fs_rename, Int32, (Cstring, Cstring), src, dst)
366+
# on error, default to cp && rm
367+
if err < 0
368+
# remove_destination: is already done in the mv function
369+
cp(src, dst; remove_destination=false, follow_symlinks=false)
370+
rm(src; recursive=true)
371+
end
372+
nothing
373+
end
374+
375+
function sendfile(src::AbstractString, dst::AbstractString)
376+
local src_open = false,
377+
dst_open = false,
378+
src_file,
379+
dst_file
380+
try
381+
src_file = open(src, JL_O_RDONLY)
382+
src_open = true
383+
dst_file = open(dst, JL_O_CREAT | JL_O_TRUNC | JL_O_WRONLY,
384+
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH | S_IWOTH)
385+
dst_open = true
386+
387+
bytes = filesize(stat(src_file))
388+
sendfile(dst_file, src_file, Int64(0), Int(bytes))
389+
finally
390+
if src_open && isopen(src_file)
391+
close(src_file)
392+
end
393+
if dst_open && isopen(dst_file)
394+
close(dst_file)
395+
end
396+
end
397+
end
398+
399+
@windows_only const UV_FS_SYMLINK_JUNCTION = 0x0002
400+
function symlink(p::AbstractString, np::AbstractString)
401+
@windows_only if Base.windows_version() < Base.WINDOWS_VISTA_VER
402+
error("Windows XP does not support soft symlinks")
403+
end
404+
flags = 0
405+
@windows_only if isdir(p); flags |= UV_FS_SYMLINK_JUNCTION; p = abspath(p); end
406+
err = ccall(:jl_fs_symlink, Int32, (Cstring, Cstring, Cint), p, np, flags)
407+
@windows_only if err < 0
408+
Base.warn_once("Note: on Windows, creating file symlinks requires Administrator privileges.")
409+
end
410+
uv_error("symlink",err)
411+
end
412+
413+
function readlink(path::AbstractString)
414+
req = Libc.malloc(_sizeof_uv_fs)
415+
try
416+
ret = ccall(:uv_fs_readlink, Int32,
417+
(Ptr{Void}, Ptr{Void}, Cstring, Ptr{Void}),
418+
eventloop(), req, path, C_NULL)
419+
if ret < 0
420+
ccall(:uv_fs_req_cleanup, Void, (Ptr{Void}, ), req)
421+
uv_error("readlink", ret)
422+
assert(false)
423+
end
424+
tgt = bytestring(ccall(:jl_uv_fs_t_ptr, Ptr{Cchar}, (Ptr{Void}, ), req))
425+
ccall(:uv_fs_req_cleanup, Void, (Ptr{Void}, ), req)
426+
return tgt
427+
finally
428+
Libc.free(req)
429+
end
430+
end
431+
432+
function chmod(p::AbstractString, mode::Integer)
433+
err = ccall(:jl_fs_chmod, Int32, (Cstring, Cint), p, mode)
434+
uv_error("chmod",err)
435+
nothing
436+
end

0 commit comments

Comments
 (0)