chmod

(PHP 4, PHP 5, PHP 7, PHP 8)

chmodChange le mode du fichier

Description

chmod(string $filename, int $permissions): bool

Remplace le mode du fichier filename par le mode permissions.

Liste de paramètres

filename

Chemin vers le fichier.

permissions

Il est à noter que le mode permissions est considéré comme un nombre en notation octale, aussi, afin de vous en assurer, vous pouvez préfixer le mode permissions par un zéro. Les chaînes comme "g+w" ne fonctionneront pas correctement :

<?php
chmod
("/somedir/somefile", 755); // notation décimale : probablement faux
chmod("/somedir/somefile", "u+rwx,go+rx"); // chaîne : incorrect
chmod("/somedir/somefile", 0755); // notation octale : valeur du mode correcte
?>

Le paramètre permissions est constitué de trois valeurs octales qui spécifient les droits pour le propriétaire, le groupe du propriétaire et les autres, respectivement. Chaque composant peut être calculé en ajoutant les droits désirés. Le chiffre 1 donne les droits d'exécution, le chiffre 2 les droits d'écriture et le chiffre 4 les droits de lecture. Ajoutez simplement ces nombres pour spécifier les droits voulus. Vous pouvez aussi lire le manuel des systèmes Unix avec man 1 chmod et man 2 chmod.

<?php
// Lecture et écriture pour le propriétaire, rien pour les autres
chmod("/somedir/somefile", 0600);

// Lecture et écriture pour le propriétaire, lecture pour les autres
chmod("/somedir/somefile", 0644);

// Tout pour le propriétaire, lecture et exécution pour les autres
chmod("/somedir/somefile", 0755);

// Tout pour le propriétaire, lecture exécution pour le groupe, rien pour les autres
chmod("/somedir/somefile", 0750);
?>

Valeurs de retour

Cette fonction retourne true en cas de succès ou false si une erreur survient.

Erreurs / Exceptions

En cas d'échec, une erreur E_WARNING est émis.

Notes

Note:

L'utilisateur courant est l'utilisateur avec lequel PHP fonctionne. Il est probablement différent de l'utilisateur que vous utilisez en mode Shell ou FTP. Le mode ne peut être modifié que par l'utilisateur à qui appartient le fichier sur la plupart des systèmes.

Note: Cette fonction ne fonctionne pas avec les fichiers distants, car le fichier examiné doit être accessible sur le système de fichiers du serveur.

Voir aussi

  • chown() - Change le propriétaire du fichier
  • chgrp() - Change le groupe d'un fichier
  • fileperms() - Lit les droits d'un fichier
  • stat() - Renvoie les informations à propos d'un fichier

add a note add a note

User Contributed Notes 17 notes

up
52
MethodicalFool
13 years ago
BEWARE, a couple of the examples in the comments suggest doing something like this:

chmod(file_or_dir_name, intval($mode, 8));

However, if $mode is an integer then intval( ) won't modify it.  So, this code...

$mode = 644;
chmod('/tmp/test', intval($mode, 8));

...produces permissions that look like this:

1--w----r-T

Instead, use octdec( ), like this:

chmod(file_or_dir_name, octdec($mode));

See also: http://www.php.net/manual/en/function.octdec.php
up
32
Geoff W
14 years ago
BEWARE using quotes around the second parameter...

If you use quotes eg

chmod (file, "0644");

php will not complain but will do an implicit conversion to an int before running chmod. Unfortunately the implicit conversion doesn't take into account the octal string so you end up with an integer version 644, which is 1204 octal
up
28
masha at mail dot ru
18 years ago
Usefull reference:

Value    Permission Level
400    Owner Read
200    Owner Write
100    Owner Execute
40    Group Read
20    Group Write
10    Group Execute
4    Global Read
2    Global Write
1    Global Execute

(taken from http://www.onlamp.com/pub/a/php/2003/02/06/php_foundations.html)
up
15
pmichaud at pobox dot com
20 years ago
In the previous post, stickybit avenger writes:
    Just a little hint. I was once adwised to set the 'sticky bit', i.e. use 1777 as chmod-value...

Note that in order to set the sticky bit on a file one must use '01777' (oct) and not '1777' (dec) as the parameter to chmod:

<?php
    chmod
("file",01777);   // correct
    
chmod("file",1777);    // incorrect, same as chmod("file",01023), causing no owner permissions!
?>

Rule of thumb: always prefix octal mode values with a zero.
up
15
Anonymous
15 years ago
Changes file mode recursive in $pathname to $filemode

<?php

$iterator
= new RecursiveIteratorIterator(new RecursiveDirectoryIterator($pathname));

foreach(
$iterator as $item) {
   
chmod($item, $filemode);
}

?>
up
5
alex at feidesign dot com
18 years ago
If you cannot chmod files/directories with PHP because of safe_mode restrictions, but you can use FTP to chmod them, simply use PHP's FTP-functions (eg. ftp_chmod or ftp_site) instead. Not as efficient, but works.
up
6
paul maybe at squirrel mail org
15 years ago
Note that info at rvgate dot nl's chmodnum function produces INCORRECT results.  The resutls are base-10 numbers that only LOOK like they are octal numbers.  The function also ignores setuid, setgid and sticky bits, and will produce incorrect numbers if such a file is encountered.  Instead, this brute-force code works.  Maybe there is something more slick, but this isn't too CPU-intensive (note that it assumes you've error-checked that you indeed have a 10-character string!):

<?php
      $permissions
= 'drwxr-xr-x'// or whatever
     
$mode = 0;

      if (
$permissions[1] == 'r') $mode += 0400;
      if (
$permissions[2] == 'w') $mode += 0200;
      if (
$permissions[3] == 'x') $mode += 0100;
      else if (
$permissions[3] == 's') $mode += 04100;
      else if (
$permissions[3] == 'S') $mode += 04000;

      if (
$permissions[4] == 'r') $mode += 040;
      if (
$permissions[5] == 'w') $mode += 020;
      if (
$permissions[6] == 'x') $mode += 010;
      else if (
$permissions[6] == 's') $mode += 02010;
      else if (
$permissions[6] == 'S') $mode += 02000;

      if (
$permissions[7] == 'r') $mode += 04;
      if (
$permissions[8] == 'w') $mode += 02;
      if (
$permissions[9] == 'x') $mode += 01;
      else if (
$permissions[9] == 't') $mode += 01001;
      else if (
$permissions[9] == 'T') $mode += 01000;

     
printf('Mode is %d decimal and %o octal', $mode, $mode);
?>
up
1
chris at ocproducts dot com
4 years ago
Windows has a very different file permission model to Unix and integrates them only minimally.

On Windows, all this function can do is to change the "read only" flag, which is turned on if $mode & 0200 does not pass.
i.e. it only checks if u+w is missing from the bitmask, and if it is, it sets the read only flag.

The executable flag cannot be set as Windows determines it based on file extension.
The write flag cannot be set as Windows determines write access based on ACLs, which are not integrated here.
up
4
imoldgreg at o2 dot co dot uk
17 years ago
an update to 'neil at 11 out of 10's code for changing mode using FTP.

changes: proper array added within the function (better for those of us who only need to connect to one ftp server) so only the mode and directory name need to be passed.

the octal added, for completeness and predictable stability.

<?php
function changemode($xcite)
{
$ftp_details = array(
ftp_user_name => 'username',
ftp_user_pass => 'password',
ftp_user_root => '/public_html/',
ftp_server => 'ftp.something.org'
);

$path = "public";
$mod = intval($xcite, 8);

  
// extract ftp details (array keys as variable names)
  
extract ($ftp_details);
  
  
// set up basic connection
  
$conn_id = ftp_connect($ftp_server);
  
  
// login with username and password
  
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
  
  
// try to chmod $path directory
  
if (ftp_site($conn_id, 'CHMOD '.$mod.' '.$ftp_root.$path) !== false) {
      
$success=TRUE;
   }
   else {
      
$success=FALSE;
   }

  
// close the connection
  
ftp_close($conn_id);
    return
$success;
}

?>

for those of you, like me, who were looking for a way to make an 'un-hackable' uploader, here's the closest i got, now for a field test, good luck!
up
2
Andrey P.
13 years ago
I was trying to change permissions of a folder with chmod command with FTP connection. (I needed a writable folder to upload pictures with php)

I got the following respond:
"SITE CHMOD 777 uploads: command not understood"

The reason: Server is running under Windows system that does not allow to set file permissions via FTP. Conversely, the UNIX-running servers allow that.

Solutions:

1. If your web hosting provider has a web-based control panel that lets you set file permissions, then you need to login there and make changes.

2. It is possible to contact the hosting provider and ask them about this issue; maybe they can make the changes.

3. It is possible to change the hosting provider that has servers run on UNIX, and keep the site there.
up
1
Ambriel_Angel at www dot ambriels dot net/entry
16 years ago
<?php
error_reporting
(E_ERROR | E_PARSE);
/* Makes is so Directories are not browseable to the public,
removing only the Public = Read permission, while leaving
the other chmod permissions for the file in tact.

If you have exectue already on, and read off, public viewers will only
be able to view files through links, but not browse
around to see what's inside of directories and see what
you've got laying around. */
//-------------------------------------------------------
// Get file mode
// Get file permissions supported by chmod
function getmod($filename) {
  
$val = 0;
  
$perms = fileperms($filename);
  
// Owner; User
  
$val += (($perms & 0x0100) ? 0x0100 : 0x0000); //Read
  
$val += (($perms & 0x0080) ? 0x0080 : 0x0000); //Write
  
$val += (($perms & 0x0040) ? 0x0040 : 0x0000); //Execute

   // Group
  
$val += (($perms & 0x0020) ? 0x0020 : 0x0000); //Read
  
$val += (($perms & 0x0010) ? 0x0010 : 0x0000); //Write
  
$val += (($perms & 0x0008) ? 0x0008 : 0x0000); //Execute

   // Global; World
  
$val += (($perms & 0x0004) ? 0x0004 : 0x0000); //Read
  
$val += (($perms & 0x0002) ? 0x0002 : 0x0000); //Write
  
$val += (($perms & 0x0001) ? 0x0001 : 0x0000); //Execute

   // Misc
  
$val += (($perms & 0x40000) ? 0x40000 : 0x0000); //temporary file (01000000)
  
$val += (($perms & 0x80000) ? 0x80000 : 0x0000); //compressed file (02000000)
  
$val += (($perms & 0x100000) ? 0x100000 : 0x0000); //sparse file (04000000)
  
$val += (($perms & 0x0800) ? 0x0800 : 0x0000); //Hidden file (setuid bit) (04000)
  
$val += (($perms & 0x0400) ? 0x0400 : 0x0000); //System file (setgid bit) (02000)
  
$val += (($perms & 0x0200) ? 0x0200 : 0x0000); //Archive bit (sticky bit) (01000)

  
return $val;
}

//-------------------------------------------------------
// Find out if file has mode
function hasmod($perms, $permission) {

# User Read = 0400 (256), Write = 0200 (128), Execute = 0100 (64)
# Group Read = 0040 (32), Write = 0020 (16), Execute = 0010 (8)
# Public Read = 0004 (4), Write = 0002 (2), Execute = 0001 (1)

   
return (($perms & $permission) == $permission);
}

//-------------------------------------------------------
// Take the read option off of all the subdirectories of the included path
function pathlock($dir, $listall = false, $testrun = true) {
   echo
"START @ " . date("F j, Y, h:i:s A") . "<br><br>";
   echo (
$testrun ? '**Test Run Activated (no changes will be made).**<br><br>' : '**Live Run Activated.**<br><br>');
   echo
$dir . " is our directory.<br><br>\n";
   echo
"[...IN PROGRESS...]<br><br>";

  
$file_list = '';
  
$stack[] = $dir;
 
   while (
$stack) {
     
$current_dir = array_pop($stack);
      if (
$dh = opendir($current_dir)) {
          while ((
$file = readdir($dh)) !== false) {
              if (
$file !== '.' AND $file !== '..') {
                 
$current_file = "{$current_dir}/{$file}";
               if (
is_dir($current_file)) {
                     
// BEG ADD PATH   
                  
$mode = getmod($current_file);    //Get the mode
                     
$HasPubRead = hasmod($mode,4);
                   if (
$HasPubRead || $listall) {    // Can the public read this dir?
                  //======================================
                   
$ch = true;
                 
$take = 0;
                      
// Change the mode:
                    
if ($HasPubRead) {
                         
$take = 4;         // Value for Public Read. 4 is the same in octal and decimal.
                         
if (!$testrun) {
                             
$ch = chmod($current_file, $mode-$take);
                          }
                      }

                    echo
$current_file . ",current=" . decoct($mode) .
                        ((
$mode!==$mode-$take) ? ",new=" . decoct($mode-$take) : '') .
                        (
$ch ? '' : ',FAILED') . "<br>\n";
                   }
// end if hasmod
                   // END ADD PATH                          
                     
$stack[] = $current_file;
                  }
// if if_dir
             
} //if ($file !== '.' AND $file !== '..')
         
} //while (($file = readdir($dh)) !== false)
     
} //if ($dh = opendir($current_dir))
} // while ($stack)

   
echo "<br>COMPLETE @ " . date("F j, Y, h:i:s A") . "<br>\n";
return;
  
//return $path_list;
} // end function

//-------------------------------------------------------
    //listall Show all folders, even one's we're not going to process?
    //testrun Do a test run without making any changes
   
pathlock($_SERVER["DOCUMENT_ROOT"],false,true); // listall?=false, testrun?=true

?>
up
0
no at no dot es
3 years ago
use a stored string for the mask is a pain
ex: $mask contains a string 0755
int($mask) not work (return 755)
the only way i found is use octdec($mask)
up
0
h dot kuppens at cs dot ru dot nl
12 years ago
For recursive chmod'ing both files and directories in one step you can use the function below. Note that this function has one argument for directory permissions and one for file permissions.
In this way you can apply the 'x' permission on directories, and skip it on directories. This function also skips links.

Example usage :

   chmod_R( 'mydir', 0666, 0777);

Makes all files and directories within mydir/ directory accessible for everyone, but doesn't make the files executable.

I guess for very deeply nested directories the recursion with php can become problematic, but I can be wrong because I never investigated this.

<?php
function chmod_R($path, $filemode, $dirmode) {
    if (
is_dir($path) ) {
        if (!
chmod($path, $dirmode)) {
           
$dirmode_str=decoct($dirmode);
            print
"Failed applying filemode '$dirmode_str' on directory '$path'\n";
            print
"  `-> the directory '$path' will be skipped from recursive chmod\n";
            return;
        }
       
$dh = opendir($path);
        while ((
$file = readdir($dh)) !== false) {
            if(
$file != '.' && $file != '..') {  // skip self and parent pointing directories
               
$fullpath = $path.'/'.$file;
               
chmod_R($fullpath, $filemode,$dirmode);
            }
        }
       
closedir($dh);
    } else {
        if (
is_link($path)) {
            print
"link '$path' is skipped\n";
            return;
        }
        if (!
chmod($path, $filemode)) {
           
$filemode_str=decoct($filemode);
            print
"Failed applying filemode '$filemode_str' on file '$path'\n";
            return;
        }
    }
}
?>
up
0
sander
14 years ago
if you want to chmod directories too, use this

<?php
$iterator
= new RecursiveIteratorIterator(new RecursiveDirectoryIterator($pathname), RecursiveIteratorIterator::SELF_FIRST);

foreach(
$iterator as $item) {
   
chmod($item, $filemode);
}
?>
up
0
webmaster at danopia dot 5gigs dot com
17 years ago
Thanks for your code, "imoldgreg at o2 dot co dot uk". I am using it for an instalation script that has to CHMOD a bunch of files. I have found it faster to use the same connectino for each, as shown below.

<?php

// Thanks to "imoldgreg at o2 dot co dot uk" for the base 'CHMOD via FTP' script.

function chmod_open()
{
   
// Use your own FTP info
   
$ftp_user_name = 'chmod@XXXXXXXXX.com';
   
$ftp_user_pass = 'XXXXXXXXXX';
   
$ftp_root = '/';
   
$ftp_server = 'localhost';
   
$conn_id = ftp_connect($ftp_server);
   
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
    return
$conn_id;
}

function
chmod_file($conn_id, $permissions, $path)
{
    if (
ftp_site($conn_id, 'CHMOD ' . $permissions . ' ' . $ftp_root . $path) !== false)
    {
        return
TRUE;
    }
    else
    {
        return
FALSE;
    }
}

function
chmod_close($conn_id)
{
   
ftp_close($conn_id);
}

// CHMOD the required setup files

// Connect to the FTP
$conn_id = chmod_open();

// CHMOD each file and echo the results
echo chmod_file($conn_id, 777, 'master/cache/') ? 'CHMODed successfully!' : 'Error';
echo
chmod_file($conn_id, 777, 'master/files/') ? 'CHMODed successfully!' : 'Error';
echo
chmod_file($conn_id, 777, 'master/store/') ? 'CHMODed successfully!' : 'Error';
echo
chmod_file($conn_id, 766, 'master/config.php') ? 'CHMODed successfully!' : 'Error';
echo
chmod_file($conn_id, 777, 'master/images/avatars/upload/') ? 'CHMODed successfully!' : 'Error';

// Close the connection
chmod_close($conn_id);

?>

Here, the same FTP connection is used for each CHMOD command, making the execute time lower. This is essential for me, since my script is also copying a bunch of files.
up
-1
nicolas at infosoft dot inf dot br
15 years ago
I use the code of haasje@welmers.net, but have a lite alteration. (linux symlink)

<?php
function chmod_R($path, $filemode) {
    if (!
is_dir($path))
        return
chmod($path, $filemode);

   
$dh = opendir($path);
    while ((
$file = readdir($dh)) !== false) {
        if(
$file != '.' && $file != '..') {
           
$fullpath = $path.'/'.$file;
            if(
is_link($fullpath))
                return
FALSE;
            elseif(!
is_dir($fullpath))
                if (!
chmod($fullpath, $filemode))
                    return
FALSE;
            elseif(!
chmod_R($fullpath, $filemode))
                return
FALSE;
        }
    }

   
closedir($dh);

    if(
chmod($path, $filemode))
        return
TRUE;
    else
        return
FALSE;
}
?>
thanks alls
up
-1
Tuckbros
3 years ago
Just an update of the solution with octdec. You have to give octdec the string as a parameter.

$mode = '644';
chmod(file_or_dir_name, octdec($mode));

See also: http://www.php.net/manual/en/function.octdec.php
To Top