Skip to content

Commit b9aaff5

Browse files
fattenederKristofferC
authored andcommitted
Move isexecutable, isreadable, iswritable to filesystem.jl (#53699)
This PR migrates the methods `isexecutable, isreadable, iswritable` from `Sys` to `Base`, but also generates an alias in `Sys` for backwards compatibility. Furthermore, `iswriteable` is renamed to `iswritable` in order to match the already existing `Base.iswritable` method. Suggested in #53320 (comment). (cherry picked from commit 8d31f33)
1 parent 22db541 commit b9aaff5

File tree

7 files changed

+97
-88
lines changed

7 files changed

+97
-88
lines changed

base/exports.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,7 @@ export
930930
isblockdev,
931931
ischardev,
932932
isdir,
933+
isexecutable,
933934
isfifo,
934935
isfile,
935936
islink,

base/filesystem.jl

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ import .Base:
140140
IOError, _UVError, _sizeof_uv_fs, check_open, close, eof, eventloop, fd, isopen,
141141
bytesavailable, position, read, read!, readavailable, seek, seekend, show,
142142
skip, stat, unsafe_read, unsafe_write, write, transcode, uv_error,
143-
setup_stdio, rawhandle, OS_HANDLE, INVALID_OS_HANDLE, windowserror, filesize
143+
setup_stdio, rawhandle, OS_HANDLE, INVALID_OS_HANDLE, windowserror, filesize,
144+
isexecutable, isreadable, iswritable
144145

145146
import .Base.RefValue
146147

@@ -365,5 +366,85 @@ function touch(f::File)
365366
f
366367
end
367368

369+
"""
370+
isexecutable(path::String)
371+
372+
Return `true` if the given `path` has executable permissions.
373+
374+
!!! note
375+
This permission may change before the user executes `path`,
376+
so it is recommended to execute the file and handle the error if that fails,
377+
rather than calling `isexecutable` first.
378+
379+
!!! note
380+
Prior to Julia 1.6, this did not correctly interrogate filesystem
381+
ACLs on Windows, therefore it would return `true` for any
382+
file. From Julia 1.6 on, it correctly determines whether the
383+
file is marked as executable or not.
384+
385+
See also [`ispath`](@ref), [`isreadable`](@ref), [`iswritable`](@ref).
386+
"""
387+
function isexecutable(path::String)
388+
# We use `access()` and `X_OK` to determine if a given path is
389+
# executable by the current user. `X_OK` comes from `unistd.h`.
390+
X_OK = 0x01
391+
return ccall(:jl_fs_access, Cint, (Cstring, Cint), path, X_OK) == 0
392+
end
393+
isexecutable(path::AbstractString) = isexecutable(String(path))
394+
395+
"""
396+
isreadable(path::String)
397+
398+
Return `true` if the access permissions for the given `path` permitted reading by the current user.
399+
400+
!!! note
401+
This permission may change before the user calls `open`,
402+
so it is recommended to just call `open` alone and handle the error if that fails,
403+
rather than calling `isreadable` first.
404+
405+
!!! note
406+
Currently this function does not correctly interrogate filesystem
407+
ACLs on Windows, therefore it can return wrong results.
408+
409+
!!! compat "Julia 1.11"
410+
This function requires at least Julia 1.11.
411+
412+
See also [`ispath`](@ref), [`isexecutable`](@ref), [`iswritable`](@ref).
413+
"""
414+
function isreadable(path::String)
415+
# We use `access()` and `R_OK` to determine if a given path is
416+
# readable by the current user. `R_OK` comes from `unistd.h`.
417+
R_OK = 0x04
418+
return ccall(:jl_fs_access, Cint, (Cstring, Cint), path, R_OK) == 0
419+
end
420+
isreadable(path::AbstractString) = isreadable(String(path))
421+
422+
"""
423+
iswritable(path::String)
424+
425+
Return `true` if the access permissions for the given `path` permitted writing by the current user.
426+
427+
!!! note
428+
This permission may change before the user calls `open`,
429+
so it is recommended to just call `open` alone and handle the error if that fails,
430+
rather than calling `iswritable` first.
431+
432+
!!! note
433+
Currently this function does not correctly interrogate filesystem
434+
ACLs on Windows, therefore it can return wrong results.
435+
436+
!!! compat "Julia 1.11"
437+
This function requires at least Julia 1.11.
438+
439+
See also [`ispath`](@ref), [`isexecutable`](@ref), [`isreadable`](@ref).
440+
"""
441+
function iswritable(path::String)
442+
# We use `access()` and `W_OK` to determine if a given path is
443+
# writeable by the current user. `W_OK` comes from `unistd.h`.
444+
W_OK = 0x02
445+
return ccall(:jl_fs_access, Cint, (Cstring, Cint), path, W_OK) == 0
446+
end
447+
iswritable(path::AbstractString) = iswritable(String(path))
448+
368449

369450
end

base/io.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ data has already been buffered. The result is a `Vector{UInt8}`.
131131
"""
132132
function readavailable end
133133

134+
function isexecutable end
135+
134136
"""
135137
isreadable(io) -> Bool
136138

base/sysinfo.jl

Lines changed: 4 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export BINDIR,
3434
isjsvm,
3535
isexecutable,
3636
isreadable,
37-
iswriteable,
37+
iswritable,
3838
username,
3939
which
4040

@@ -553,85 +553,9 @@ windows_version
553553

554554
const WINDOWS_VISTA_VER = v"6.0"
555555

556-
"""
557-
Sys.isexecutable(path::String)
558-
559-
Return `true` if the given `path` has executable permissions.
560-
561-
!!! note
562-
This permission may change before the user executes `path`,
563-
so it is recommended to execute the file and handle the error if that fails,
564-
rather than calling `isexecutable` first.
565-
566-
!!! note
567-
Prior to Julia 1.6, this did not correctly interrogate filesystem
568-
ACLs on Windows, therefore it would return `true` for any
569-
file. From Julia 1.6 on, it correctly determines whether the
570-
file is marked as executable or not.
571-
572-
See also [`ispath`](@ref), [`isreadable`](@ref), [`iswriteable`](@ref).
573-
"""
574-
function isexecutable(path::String)
575-
# We use `access()` and `X_OK` to determine if a given path is
576-
# executable by the current user. `X_OK` comes from `unistd.h`.
577-
X_OK = 0x01
578-
return ccall(:jl_fs_access, Cint, (Cstring, Cint), path, X_OK) == 0
579-
end
580-
isexecutable(path::AbstractString) = isexecutable(String(path))
581-
582-
"""
583-
Sys.isreadable(path::String)
584-
585-
Return `true` if the access permissions for the given `path` permitted reading by the current user.
586-
587-
!!! note
588-
This permission may change before the user calls `open`,
589-
so it is recommended to just call `open` alone and handle the error if that fails,
590-
rather than calling `isreadable` first.
591-
592-
!!! note
593-
Currently this function does not correctly interrogate filesystem
594-
ACLs on Windows, therefore it can return wrong results.
595-
596-
!!! compat "Julia 1.11"
597-
This function requires at least Julia 1.11.
598-
599-
See also [`ispath`](@ref), [`isexecutable`](@ref), [`iswriteable`](@ref).
600-
"""
601-
function isreadable(path::String)
602-
# We use `access()` and `R_OK` to determine if a given path is
603-
# readable by the current user. `R_OK` comes from `unistd.h`.
604-
R_OK = 0x04
605-
return ccall(:jl_fs_access, Cint, (Cstring, Cint), path, R_OK) == 0
606-
end
607-
isreadable(path::AbstractString) = isreadable(String(path))
608-
609-
"""
610-
Sys.iswriteable(path::String)
611-
612-
Return `true` if the access permissions for the given `path` permitted writing by the current user.
613-
614-
!!! note
615-
This permission may change before the user calls `open`,
616-
so it is recommended to just call `open` alone and handle the error if that fails,
617-
rather than calling `iswriteable` first.
618-
619-
!!! note
620-
Currently this function does not correctly interrogate filesystem
621-
ACLs on Windows, therefore it can return wrong results.
622-
623-
!!! compat "Julia 1.11"
624-
This function requires at least Julia 1.11.
625-
626-
See also [`ispath`](@ref), [`isexecutable`](@ref), [`isreadable`](@ref).
627-
"""
628-
function iswriteable(path::String)
629-
# We use `access()` and `W_OK` to determine if a given path is
630-
# writeable by the current user. `W_OK` comes from `unistd.h`.
631-
W_OK = 0x02
632-
return ccall(:jl_fs_access, Cint, (Cstring, Cint), path, W_OK) == 0
633-
end
634-
iswriteable(path::AbstractString) = iswriteable(String(path))
556+
const isexecutable = Base.isexecutable
557+
const isreadable = Base.isreadable
558+
const iswritable = Base.iswritable
635559

636560
"""
637561
Sys.which(program_name::String)

doc/src/base/base.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ Base.Sys.isjsvm
375375
Base.Sys.loadavg
376376
Base.Sys.isexecutable
377377
Base.Sys.isreadable
378-
Base.Sys.iswriteable
378+
Base.Sys.iswritable
379379
Base.Sys.username
380380
Base.@static
381381
```

doc/src/base/io-network.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Base.eof
3939
Base.isreadonly
4040
Base.iswritable
4141
Base.isreadable
42+
Base.isexecutable
4243
Base.isopen
4344
Base.fd
4445
Base.redirect_stdio

test/file.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1668,7 +1668,7 @@ else
16681668
)
16691669
end
16701670

1671-
@testset "chmod/isexecutable/isreadable/iswriteable" begin
1671+
@testset "chmod/isexecutable/isreadable/iswritable" begin
16721672
mktempdir() do dir
16731673
subdir = joinpath(dir, "subdir")
16741674
fpath = joinpath(dir, "subdir", "foo")
@@ -1685,27 +1685,27 @@ end
16851685
chmod(fpath, 0o644)
16861686
@test !Sys.isexecutable(fpath)
16871687
@test Sys.isreadable(fpath)
1688-
@test Sys.iswriteable(fpath) skip=Sys.iswindows()
1688+
@test Sys.iswritable(fpath) skip=Sys.iswindows()
16891689
chmod(fpath, 0o755)
16901690
@test Sys.isexecutable(fpath)
16911691
@test Sys.isreadable(fpath)
1692-
@test Sys.iswriteable(fpath) skip=Sys.iswindows()
1692+
@test Sys.iswritable(fpath) skip=Sys.iswindows()
16931693
chmod(fpath, 0o444)
16941694
@test !Sys.isexecutable(fpath)
16951695
@test Sys.isreadable(fpath)
1696-
@test !Sys.iswriteable(fpath)
1696+
@test !Sys.iswritable(fpath)
16971697
chmod(fpath, 0o244)
16981698
@test !Sys.isexecutable(fpath)
16991699
@test !Sys.isreadable(fpath) skip=Sys.iswindows()
1700-
@test Sys.iswriteable(fpath) skip=Sys.iswindows()
1700+
@test Sys.iswritable(fpath) skip=Sys.iswindows()
17011701

17021702
# Ensure that, on Windows, where inheritance is default,
17031703
# chmod still behaves as we expect.
17041704
if Sys.iswindows()
17051705
chmod(subdir, 0o666)
17061706
@test !Sys.isexecutable(fpath)
17071707
@test Sys.isreadable(fpath)
1708-
@test_skip Sys.iswriteable(fpath)
1708+
@test_skip Sys.iswritable(fpath)
17091709
end
17101710

17111711
# Reset permissions to all at the end, so it can be deleted properly.

0 commit comments

Comments
 (0)