Same name and namespace in other branches
  1. 5.x includes/install.inc \drupal_install_fix_file()
  2. 6.x includes/install.inc \drupal_install_fix_file()
  3. 7.x includes/install.inc \drupal_install_fix_file()
  4. 8.9.x core/includes/install.inc \drupal_install_fix_file()
  5. 9 core/includes/install.inc \drupal_install_fix_file()

Attempts to fix file permissions.

The general approach here is that, because we do not know the security setup of the webserver, we apply our permission changes to all three digits of the file permission (i.e. user, group and all).

To ensure that the values behave as expected (and numbers don't carry from one digit to the next) we do the calculation on the octal value using bitwise operations. This lets us remove, for example, 0222 from 0700 and get the correct value of 0500.

Parameters

$file: The name of the file with permissions to fix.

$mask: The desired permissions for the file.

$message: (optional) Whether to output messages. Defaults to TRUE.

Return value

bool TRUE/FALSE whether or not we were able to fix the file's permissions.

1 call to drupal_install_fix_file()
drupal_verify_install_file in core/includes/install.inc
Verifies the state of the specified file.

File

core/includes/install.inc, line 723
API functions for installing modules and themes.

Code

function drupal_install_fix_file($file, $mask, $message = TRUE) {

  // If $file does not exist, fileperms() issues a PHP warning.
  if (!file_exists($file)) {
    return FALSE;
  }
  $mod = fileperms($file) & 0777;
  $masks = [
    FILE_READABLE,
    FILE_WRITABLE,
    FILE_EXECUTABLE,
    FILE_NOT_READABLE,
    FILE_NOT_WRITABLE,
    FILE_NOT_EXECUTABLE,
  ];

  // FILE_READABLE, FILE_WRITABLE, and FILE_EXECUTABLE permission strings
  // can theoretically be 0400, 0200, and 0100 respectively, but to be safe
  // we set all three access types in case the administrator intends to
  // change the owner of settings.php after installation.
  foreach ($masks as $m) {
    if ($mask & $m) {
      switch ($m) {
        case FILE_READABLE:
          if (!is_readable($file)) {
            $mod |= 0444;
          }
          break;
        case FILE_WRITABLE:
          if (!is_writable($file)) {
            $mod |= 0222;
          }
          break;
        case FILE_EXECUTABLE:
          if (!is_executable($file)) {
            $mod |= 0111;
          }
          break;
        case FILE_NOT_READABLE:
          if (is_readable($file)) {
            $mod &= ~0444;
          }
          break;
        case FILE_NOT_WRITABLE:
          if (is_writable($file)) {
            $mod &= ~0222;
          }
          break;
        case FILE_NOT_EXECUTABLE:
          if (is_executable($file)) {
            $mod &= ~0111;
          }
          break;
      }
    }
  }

  // chmod() will work if the web server is running as owner of the file.
  if (@chmod($file, $mod)) {
    return TRUE;
  }
  else {
    return FALSE;
  }
}