©
本文档使用 PHP中文网手册 发布
(PHP 4, PHP 5, PHP 7)
chmod — 改变文件模式
$filename
, int $mode
)
尝试将 filename
所指定文件的模式改成
mode
所给定的。
filename
文件的路径。
mode
注意 mode
不会被自动当成八进制数值,而且也不能用字符串(例如 "g+w")。要确保正确操作,需要给
mode
前面加上 0:
<?php
chmod ( "/somedir/somefile" , 755 ); // 十进制数,可能不对
chmod ( "/somedir/somefile" , "u+rwx,go+rx" ); // 字符串,不对
chmod ( "/somedir/somefile" , 0755 ); // 八进制数,正确的 mode 值
?>
mode
参数包含三个八进制数按顺序分别指定了所有者、所有者所在的组以及所有人的访问限制。每一部分都可以通过加入所需的权限来计算出所要的权限。数字 1
表示使文件可执行,数字 2 表示使文件可写,数字 4
表示使文件可读。加入这些数字来制定所需要的权限。有关 UNIX 系统的文件权限可以阅读手册“man 1
chmod”和“man 2 chmod”。
<?php
// Read and write for owner, nothing for everybody else
chmod ( "/somedir/somefile" , 0600 );
// Read and write for owner, read for everybody else
chmod ( "/somedir/somefile" , 0644 );
// Everything for owner, read and execute for others
chmod ( "/somedir/somefile" , 0755 );
// Everything for owner, read and execute for owner's group
chmod ( "/somedir/somefile" , 0750 );
?>
成功时返回 TRUE
, 或者在失败时返回 FALSE
。
Note:
当前用户指的是执行 PHP 的用户。很可能和通常的 shell 或者 FTP 用户不是同一个。在大多数系统下文件模式只能被文件所有者的用户改变。
Note: 此函数不能作用于远程文件,被检查的文件必须是可通过服务器的文件系统访问的。
Note:
当安全模式打开的时候,PHP 会检查所操作的文件是否和正在执行的脚本具有相同的 UID (所有者)。要注意的是,不能修改 SUID,SGID 和 sticky bits。
[#1] pinetree822 at nate dot com [2015-02-24 04:10:25]
function checkPermission($userPerm,$servicePerm)
{
if( !$userPerm || !$servicePerm ) return false;
if(!preg_match("/^[0-9]+$/",(string) $userPerm) || !preg_match("/^[0-9]+$/",(string) $servicePerm)) return false;
if( $userPerm==$servicePerm ) return true;
$i=0;
$tempPerm=0;
do {
$tempPerm= pow(2, $i++); // permission ? ?? ?? 1,2,4,8,16
$sumPerm += $tempPerm; // permission ?? 1,3,7,25
if( $sumPerm <= $userPerm ) $arrayPerm[$tempPerm] = true; // permission ???
else break;
} while (true);
return @$arrayPerm[$servicePerm];
}
function makePlusPermission($arrayPerm=array(),$perm=0)
{
if( $arrayPerm ) {
$add=@array_shift($arrayPerm);
if(!preg_match("/^[0-9]+$/",(string)$add)) $add=0;
$perm+=$add;
return makePlusPermission($arrayPerm,$perm);
}
$retVal = ((int)$arrayPerm+(int)$perm);//PHP_INT_MAX
return ($retVal < 0 ? 0 : $retVal);
}
function makeRejectPermission($rejectPerm=array(), $perm=0)
{
if( $rejectPerm ) {
$minus=@array_shift($rejectPerm);
if(!preg_match("/^[0-9]+$/",(string)$minus)) $minus=0;
$perm-=$minus;
echo '$perm = '.$perm. ',$minus = ' .$minus. '<br/>';
return makeRejectPermission($rejectPerm,$perm);
}
$retVal = ((int)$rejectPerm+(int)$perm);//PHP_INT_MAX
return ($retVal < 0 ? 0 : $retVal);
}
// ??? ??
$writePost = 1;
$readPost = 2;
$deletePost = 4;
$addUser = 8;
$deleteUser = 16;
$perm["access"] = 1;
$perm["list"] = 2;
$perm["list_more"] = 4;
$perm["read"] = 8;
$perm["read_more"] = 16;
$perm["delete"] = 32;
$perm["delete_more"] = 64;
$perm["modify"] = 128;
$perm["modify_more"] = 256;
$perm["upload"] = 512;
$perm["upload_more"] = 1024;
$perm["down"] = 2048;
$perm["down_more"] = 4096;
$perm["write"] = 8192;
$perm["write_more"] = 16384;
$perm["find"] = 32768;
$perm["find_more"] = 65536;
// 131072,262144,524288,1048576,2097152,4194304,8388608
//???.?? <1,2,4,8,16,32,64,128,256,512>
//org_chart_user_access,org_chart_group_acces
// ?? ??? ??
$administrator = makePlusPermission( array( $writePost, $readPost, $deletePost, $addUser, $deleteUser ) );
$administrator_modify = makeRejectPermission( array( $deleteUser ),$administrator );
$moderator = makePlusPermission( array( $readPost, $deletePost, $deleteUser ) );
$writer = makePlusPermission( array( $writePost , $readPost ) );
$guest = makePlusPermission( array( $readPost ) );
if( checkPermission($administrator, $deleteUser) ) {
echo '<br/>';
echo("Login administrator - Access organization Listen Function". '<br>');
}
if( checkPermission($administrators, $deleteUser) ) {
echo '<br/>';
echo("Login administrator - Access organization Listen Function". '<br>');
}else {
echo '<br/>';
echo("Login administrator - Error Access organization Listen Function". '<br>');
}
echo '$administrator = ' . $administrator. '<br>' ;
echo '$administrator_modify = ' . $administrator_modify ;
//printing
$perm = 15,
$minus = 16
Login administrator - Access organization Listen Function
Login administrator - Error Access organization Listen Function
$administrator = 31
$administrator_modify = 15
// Good luck, lock.......
[#2] pinetree822 at nate dot com [2015-02-24 04:09:21]
// ??? ??
$writePost = 1;
$readPost = 2;
$deletePost = 4;
$addUser = 8;
$deleteUser = 16;
$perm["access"] = 1;
$perm["list"] = 2;
$perm["list_more"] = 4;
$perm["read"] = 8;
$perm["read_more"] = 16;
$perm["delete"] = 32;
$perm["delete_more"] = 64;
$perm["modify"] = 128;
$perm["modify_more"] = 256;
$perm["upload"] = 512;
$perm["upload_more"] = 1024;
$perm["down"] = 2048;
$perm["down_more"] = 4096;
$perm["write"] = 8192;
$perm["write_more"] = 16384;
$perm["find"] = 32768;
$perm["find_more"] = 65536;
// 131072,262144,524288,1048576,2097152,4194304,8388608
//???.?? <1,2,4,8,16,32,64,128,256,512>
//org_chart_user_access,org_chart_group_acces
// ?? ??? ??
$administrator = makePlusPermission( array( $writePost, $readPost, $deletePost, $addUser, $deleteUser ) );
$administrator_modify = makeRejectPermission( array( $deleteUser ),$administrator );
$moderator = makePlusPermission( array( $readPost, $deletePost, $deleteUser ) );
$writer = makePlusPermission( array( $writePost , $readPost ) );
$guest = makePlusPermission( array( $readPost ) );
if( checkPermission($administrator, $deleteUser) ) {
echo '<br/>';
echo("Login administrator - Access organization Listen Function". '<br>');
}
if( checkPermission($administrators, $deleteUser) ) {
echo '<br/>';
echo("Login administrator - Access organization Listen Function". '<br>');
}else {
echo '<br/>';
echo("Login administrator - Error Access organization Listen Function". '<br>');
}
echo '$administrator = ' . $administrator. '<br>' ;
echo '$administrator_modify = ' . $administrator_modify ;
//printing
$perm = 15,$minus = 16
Login administrator - Access organization Listen Function
Login administrator - Error Access organization Listen Function
$administrator = 31
$administrator_modify = 15
// Good luck, lock.......
[#3] pinetree822 [2015-02-24 04:05:52]
new Think!
access mod
// ??? ??
$writePost = 1;
$readPost = 2;
$deletePost = 4;
$addUser = 8;
$deleteUser = 16;
$perm["access"] = 1;
$perm["list"] = 2;
$perm["list_more"] = 4;
$perm["read"] = 8;
$perm["read_more"] = 16;
$perm["delete"] = 32;
$perm["delete_more"] = 64;
$perm["modify"] = 128;
$perm["modify_more"] = 256;
$perm["upload"] = 512;
$perm["upload_more"] = 1024;
$perm["down"] = 2048;
$perm["down_more"] = 4096;
$perm["write"] = 8192;
$perm["write_more"] = 16384;
$perm["find"] = 32768;
$perm["find_more"] = 65536;
// 131072,262144,524288,1048576,2097152,4194304,8388608
//???.?? <1,2,4,8,16,32,64,128,256,512>
//org_chart_user_access,org_chart_group_acces
// ?? ??? ??
$administrator = makePlusPermission( array( $writePost, $readPost, $deletePost, $addUser, $deleteUser ) );
$administrator_modify = makeRejectPermission( array( $deleteUser ),$administrator );
$moderator = makePlusPermission( array( $readPost, $deletePost, $deleteUser ) );
$writer = makePlusPermission( array( $writePost , $readPost ) );
$guest = makePlusPermission( array( $readPost ) );
if( checkPermission($administrator, $deleteUser) ) {
echo '<br/>';
echo("Login administrator - Access organization Listen Function". '<br>');
}
if( checkPermission($administrators, $deleteUser) ) {
echo '<br/>';
echo("Login administrator - Access organization Listen Function". '<br>');
}else {
echo '<br/>';
echo("Login administrator - Error Access organization Listen Function". '<br>');
}
echo '$administrator = ' . $administrator. '<br>' ;
echo '$administrator_modify = ' . $administrator_modify ;
// printing
$perm = 15,$minus = 16
Login administrator - Access organization Listen Function
Login administrator - Error Access organization Listen Function
$administrator = 31
$administrator_modify = 15
// Good Luck,, lock,,^^
[#4] roger at imovelavenda dot com dot br [2014-05-02 19:59:23]
function chmod777($f) { chmod($f, 0777); }
array_map('chmod777', glob('/home/user/public_html/pdf*
//-------------------------------------------------------
// 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
?>
[#14] info at web-in-time dot eu [2007-01-04 13:11:44]
As you might have noticed there is a minor bug in webmaster at danopia dot 5gigs dot com's code:
You have to set $ftp_root variable outside the function chmod_open() and have to set it as global within the chmod_file() function.
With these patches the code really works fine. THX!
Ben
[#15] webmaster at danopia dot 5gigs dot com [2007-01-02 18:20:27]
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.
[#16] imoldgreg at o2 dot co dot uk [2006-11-30 17:32:33]
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!
[#17] memp [2005-08-22 15:04:11]
If you are storing your mode in a variable like
$mode = 0755;
you will run into the inevitable octal mode problem. An easy way around that is to use the octdec() function.
chmod("some_filename.ext", octdec($mode));
[#18] masha at mail dot ru [2005-07-10 21:23:49]
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)
[#19] alex at feidesign dot com [2005-04-01 04:20:47]
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.
[#20] PerfectWeb [2004-11-22 19:58:50]
As noted by others below... 1) you cannot pass a string to chmod() as the mode, and 2) decimals work as well as octals for the mode.
If you need to come up with the mode on the fly (maybe based on user input) and want to use something like:
$mode = '0'.$owner.$group.$public;
you can use your $mode (which is a string) with chmod like this:
<?php
// octal mode in a string i.e. '0755'
$mode = '0'.$owner.$group.$public;
$mode_dec = octdec($mode); // convert octal mode to decimal
chmod($filename, $mode_dec);
?>
[#21] fernando at gym-group dot com [2004-11-12 07:10:16]
[#22] Oliver Hankeln [2004-07-01 08:21:41]
Well, you don't need octals.
You need a value that can easily computed and remembered if printed in octal.
511 (decimal) is the same as 777 (octal).
So it's the same wether you write
chmod("foo",511)
or
chmod("foo",0777)
The latter is just better readable.
[#23] agrenier at assertex dot com [2004-04-02 05:11:09]
This function will chmod a $filename before writing to it if:
1 - It exists
2 - It is not writeable
3 - PHP has permission to chmod files
If PHP can't chmod, then the script will end. Otherwise it will attempt to write to a new file.
<?php
function file_write($filename, $flag, &$content) {
if (file_exists($filename)) {
if (!is_writable($filename)) {
if (!chmod($filename, 0666)) {
echo "Cannot change the mode of file ($filename)";
exit;
};
}
}
if (!$fp = @fopen($filename, $flag)) {
echo "Cannot open file ($filename)";
exit;
}
if (fwrite($fp, $content) === FALSE) {
echo "Cannot write to file ($filename)";
exit;
}
if (!fclose($fp)) {
echo "Cannot close file ($filename)";
exit;
}
}
?>
[#24] pmichaud at pobox dot com [2003-04-19 15:45:42]
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.
[#25] sticky bit avenger [2003-03-12 03:30:44]
Just a little hint. I was once adwised to set the 'sticky bit', i.e. use 1777 as chmod-value. Do NOT do this if you don't have root privileges. When 'sticky bit' is set ONLY the fileuser can delete it afterwards, typically 'httpd' or something like that in case of an upload-script for example. I was unaware of this and actually had to make a script for deleting these files as I could not do this from ftp/ssh even though I did have read/write/execute access to both files and folders. Use simply '0777' or similiar.
[#26] Half-Dead at nospam dot com [2002-11-08 02:42:59]
[Editor's note:
That is due the fact Win32 systems treat premissions. You do not really have any other levels but read-only.
Maxim]
On WinME with apache chmod also works to a certain limit.
What happens is that apparently only the first number is counted, so 0666 (read-write) is the same as 0777, 0644, 0600, etc, and 0444 (read-only) is the same as 477, 400, etc.
..didn't test 0500 series
[#27] jon at zend dot com [2001-10-15 08:37:34]
if 'mode' is held in a variable and is and octal value you need to convert it to decimal before passing it to the function:
chmod ($filename, octdec($mode))
[#28] gnettles2 at home dot com [2001-08-24 11:20:10]
Usually when you're trying to write to af file, you'll need to chmod the file to something like 666 or 755. You can use a command to chmod the file for you, which is especially useful when you're making a script where you're setting it up so that your users don't have to peform a bunch of actions to setup the script. When i wrote my news program script, I only had two files. install.php and config.php. All you had to do was chmod install.php to 666 and open it up in a web browser and answer a few questions. The script itself setup the rest of the files and chmodded them for you.