Test if a directory is writable by a given UID?

Bill Karwin picture Bill Karwin · Dec 31, 2012 · Viewed 55.3k times · Source

We can test if a directory is writable by the uid of the current process:

if [ -w $directory ] ; then echo 'Eureka!' ; fi

But can anyone suggest a way to test if a directory is writable by some other uid?

My scenario is that I am administering a MySQL Server instance, and I want to change the location of the slow-query log file temporarily. I can do this by executing a MySQL command SET GLOBAL slow_query_log_file='$new_log_filename' and then disable & enable query logging to make mysqld start using that file.

But I'd like my script to check that the uid of the mysqld process has permissions to create that new log file. So I'd like to do something like (pseudocode):

$ if [ -w-as-mysql-uid `basename $new_log_filename` ] ; then echo 'Eureka!' ; fi

But of course that's an imaginary test predicate.

Clarification: I would like a solution that doesn't rely on su because I can't assume the user of my script has su privilege.

Answer

chepner picture chepner · Dec 31, 2012

Here's a long, roundabout way of checking.

USER=johndoe
DIR=/path/to/somewhere

# Use -L to get information about the target of a symlink,
# not the link itself, as pointed out in the comments
INFO=( $(stat -L -c "%a %G %U" "$DIR") )
PERM=${INFO[0]}
GROUP=${INFO[1]}
OWNER=${INFO[2]}

ACCESS=no
if (( ($PERM & 0002) != 0 )); then
    # Everyone has write access
    ACCESS=yes
elif (( ($PERM & 0020) != 0 )); then
    # Some group has write access.
    # Is user in that group?
    gs=( $(groups $USER) )
    for g in "${gs[@]}"; do
        if [[ $GROUP == $g ]]; then
            ACCESS=yes
            break
        fi
    done
elif (( ($PERM & 0200) != 0 )); then
    # The owner has write access.
    # Does the user own the file?
    [[ $USER == $OWNER ]] && ACCESS=yes
fi