How to check if can write to a folder

Viewed 552

In julia, how do I check if the current is allowed to write to a folder?

I could do the python way, and just attempt to do it, and then fail fail and recover. (In my case I can definitely recover, I have a list of locations to attempt to write to, as fallbacks. I expect the first few not to work (The first few are shared locations, so only computer admins are likely to have permission to writer there)

4 Answers

Python has also os.access function. Maybe Julia will have something similar in the future. Now we could borrow idea. :)

It is implemented in posixmodule.c (also functionality for windows!) so if you are on posix you could simply mimic:

julia> const R_OK = 4  # readability
julia> const W_OK = 2  # writability
julia> const X_OK = 1  # executability
julia> const F_OK = 4  # existence

julia> access(path, mode) = ccall(:access, Cint, (Cstring, Cint), path, mode) == 0;

Small test:

julia> access("/root", W_OK)
false

julia> access("/tmp", W_OK)
true

(for windows it could be just a little more complicated... But I could not test it now)

EDIT:

Thanks to Matt B. we could use libuv support in Julia which has to be portable (although slower on posix systems):

julia> function uv_access(path, mode)
    local ret
    req = Libc.malloc(Base._sizeof_uv_fs)
    try
        ret = ccall(:uv_fs_access, Int32, (Ptr{Void}, Ptr{Void}, Cstring, Int64, Ptr{Void}), Base.eventloop(), req, path, mode, C_NULL)
        ccall(:uv_fs_req_cleanup, Void, (Ptr{Void},), req)
    finally
        Libc.free(req)
    end
    return ret, ret==0 ? "OK" : Base.struverror(ret)
end

julia> uv_access("/tmp", W_OK)
(0, "OK")

julia> uv_access("/root", W_OK)
(-13, "permission denied")

julia> uv_access("/nonexist", W_OK)
(-2, "no such file or directory")

Is the following sufficient:

julia> testdir(dirpath) = try (p,i) = mktemp(dirpath) ; rm(p) ; true catch false end
testdir (generic function with 1 method)

julia> testdir("/tmp")
true

julia> testdir("/root")
false

Returns true if dirpath is writable (by creating a temporary file inside a try-catch block). To find the first writable directory in a list, the following can be used:

julia> findfirst(testdir, ["/root","/tmp"])
2

Doing apropos("permissions"):

julia> apropos("permissions")
Base.Filesystem.gperm
Base.Filesystem.mkpath
Base.Filesystem.operm
Base.Filesystem.uperm
Base.Filesystem.mkdir
Base.Filesystem.chmod

shows a function called Base.Filesystem.uperm which seems to do exactly what you want it to:

help?> uperm
search: uperm supertype uppercase UpperTriangular isupper unescape_string unsafe_pointer_to_objref

  uperm(file)

  Gets the permissions of the owner of the file as a bitfield of

Value Description       
––––– ––––––––––––––––––
01    Execute Permission
02    Write Permission  
04    Read Permission   

  For allowed arguments, see stat.

Unfortunately it seems to be a bit buggy on my (old v7 nightly) build:

julia> uperm("/root")
0x07       # Uhhh I hope not?

I will update my build and raise a bug if one is not already present.


PS. In case it wasn't clear, I would expect to use this in combination with isdir to detect directory permissions specifically

I don't think that Dan Getz's answer will work on Windows because the temporary file created cannot be deleted while there is an open handle to it, but this amended version with a call to close does work:

function isfolderwritable(folder)
    try
        (p,i) = mktemp(folder) 
        close(i)
        rm(p) 
        return(true)
    catch
        return(false)
    end
end
Related