Search code examples
phpapacheterminalfile-permissions

PHP 'is_writable' returning false, although viewing it from the terminal shows 775


I'm having trouble setting up a development server based off of a clone from our production server. We use a CMS and it seems that some of its scripts are having permissions issues. Trying to get to the bottom of it we've set up a PHP script to test the permissions, as well as gotten into the terminal to compare its findings.

Our test script is as below

//try one of the essential folders of the CMS
$path= '[our_base_dir]/html/cms/content'

echo $path.' is'.(!is_writable($path) ? ' NOT' : '').' writable.<br/>';

which prints

[our_base_dir]/html/cms/content is NOT writable.

However, when going into the terminal, I don't see why that would be. Here is the output of that:

$ getfacl content
# file: content
# owner: cchapman
# group: cchapman
user::rwx
user:apache:rw-
group::rwx
mask::rwx
other::r-x

and

$ grep 'cchapman' /etc/group
cms:x:510:cchapman,apache
cchapman:x:512:cms,apache

I believe the apache user is the user that needs to have the write access, and the cms and cchapman users would just be the file owners depending on how they were created. In any case, all three should be able to read and write each other's files based on the group permissions.

This is the same at the file level as well as the directory level. My only thought is that there is something going wrong with how the Apache user is treated at the file level. Could that be it? Or what else would be giving the different access permissions?


Solution

  • I suspect my comment is actually the answer, so I'll post it as one:

    By calling is_writable on the path string /html/cms/content, you're checking to see if the absolute path /html/cms/content is writable or not. I believe what you want is:

    $path = realpath('./html/cms/content');//note the .
    if (is_writable($path))
        printf('"%s" is writable', $path);
    

    If the path you're checking really is /html/cms/content, which to me seems odd (I'd expect /var/www/base_dir/html/cms/content or something), then make sure to get the realpath (ie: no symlinks and all that). So always call realpath (as I've done in the snippet above).

    Other than that: You have an apache user, that's fine, but are you sure that the script is being executed by that user? www-data and nobody are quite common, too. Check what user is actually running your code, and make sure that user has the appropriate rights, too.