@@ -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
145146import . Base. RefValue
146147
@@ -365,5 +366,85 @@ function touch(f::File)
365366 f
366367end
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
369450end
0 commit comments