I use this code to make folder in web site.
mkdir("folder/folder",0744,true);
But in practical "folder" permission is 600.
what's problem?
The mode may be affected by your current umask.
Do something like this:
$old_umask = umask(0);
mkdir('folder/folder', 0744);
umask($old_umask);
Related
I'm trying to create a directory on my server using PHP with the command:
mkdir("test", 0777);
But it doesn't give full permissions, only these:
rwxr-xr-x
The mode is modified by your current umask, which is 022 in this case.
The way the umask works is a subtractive one. You take the initial permission given to mkdir and subtract the umask to get the actual permission:
0777
- 0022
======
0755 = rwxr-xr-x.
If you don't want this to happen, you need to set your umask temporarily to zero so it has no effect. You can do this with the following snippet:
$oldmask = umask(0);
mkdir("test", 0777);
umask($oldmask);
The first line changes the umask to zero while storing the previous one into $oldmask. The second line makes the directory using the desired permissions and (now irrelevant) umask. The third line restores the umask to what it was originally.
See the PHP doco for umask and mkdir for more details.
The creation of files and directories is affected by the setting of umask. You can create files with a particular set of permissions by manipulating umask as follows :-
$old = umask(0);
mkdir("test", 0777);
umask($old);
Avoid using this function in multithreaded webservers. It is better to change the file permissions with chmod() after creating the file.
Example:
$dir = "test";
$permit = 0777;
mkdir($dir);
chmod($dir, $permit);
For those who tried
mkdir('path', 777);
and it did not work.
It is because, apparently, the 0 preceding the file mode is very important which tells chmod to interpret the passed number as an Octal instead of a decimal.
Reference
Ps. This is not a solution to the question but only an add-on to the accepted anwser
Probably, your umask is set to exclude those
In my case, I have to use the following way for centos7, which solved the problem
$oldmask = umask(000);//it will set the new umask and returns the old one
mkdir("test", 0777);
umask($oldmask);//reset the old umask
More details can be found at
https://www.php.net/manual/en/function.umask.php
How do I set permissions for folders below 777?
mkdir(getcwd() . '/public/profile/usr'.$user->getId(), 0777, true);
mkdir(getcwd() . '/public/profile/usr'.$user->getId() . '/patients', 0777, true);
mkdir(getcwd() . '/public/profile/usr'.$user->getId() . '/picture', 0777, true);
Folder permissions for these are the type below:
drwxr-xr-x
And I want it set to:
drwxrwxrwx
Can you tell me please how to solve this problem?
First off, there is never a good reason to set folder or file permissions to 777. People that feel the need to do this usually either are blindly following a (bad) online tutorial or have an underlying security/permissions problem that they are unable to fix. Usually any uploading/writing problems can be fixed by setting the proper owner/group on the folder (usually the www-data or apache user), 777 means that anybody can write or execute anything in those folders. You're basically leaving your back door open and unlocked in a bad neighbourhood. Also see How will a server become vulnerable with chmod 777? for further details.
That being said, I've seen problems like this with mkdir() before, it is usually because of a certain umask on the system being set, forcing newly created folders to have 755 permissions. Doing a specific chmod() call will do the trick though:
mkdir(getcwd() . '/public/profile/usr'.$user->getId(), 0777, true);
chmod(getcwd() . '/public/profile/usr'.$user->getId(), 777);
// And so on...
But, the better solution: fix your permissions/security issue. Just set the proper owner (the process that PHP is running under), this will avoid having to set 777 permissions, but will allow proper upload handling. This should already be the default, but you can force it with:
// This will get the user the PHP process is running under on Linux machines:
$user = `whoami`;
mkdir(getcwd() . '/public/profile/usr'.$user->getId(), 0755, true);
chown(getcwd() . '/public/profile/usr'.$user->getId(), $user);
// And so on
This will set 755 permissions on the folder and set ownership to the PHP process, meaning that PHP has full permissions on the folder, but any other users do not. This is more secure, yet no less convenient.
The problem might also be caused by SELinux, in which case chmod 777 is not going to help you much anyway. Usually the httpd_public_content_rw_t context is required on upload folders.
Check this post: http://php.net/manual/de/function.mkdir.php
Answer from there...
When using the recursive parameter bear in mind that if you're using chmod() after mkdir() to set the mode without it being modified by the value of uchar() you need to call chmod() on all created directories. ie:
<?php
mkdir('/test1/test2', 0777, true);
chmod('/test1/test2', 0777);
?>
May result in "/test1/test2" having a mode of 0777 but "/test1" still having a mode of 0755 from the mkdir() call. You'd need to do:
<?php
mkdir('/test1/test2', 0777, true);
chmod('/test1', 0777);
chmod('/test1/test2', 0777);
?>
Here is one of the many possible ways of doing it:
<?php
$baseDir = getcwd() . '/public/profile/usr'. $user->getId();
$arrFolders = array('/patients', '/picture');
// FIRST chmod THE BASE DIRECTORY TO HAVE THE PERMISSIONS YOU WANT:
chmod($baseDir, 0777);
// LOOP THROUGH THE ARRAY OF FOLDERS YOU WANT TO CREATE & CREATE THEM WITH APPROPRIATE PERMISSIONS:
foreach($arrFolders as $folder){
try{
mkdir($baseDir . $folder, 0777, true);
}catch(Exception $e){
// HANDLE ANY EXCEPTION SHOULD ONE OCCUR...
}
}
I have read this:-
Why can't PHP create a directory with 777 permissions?
and I can see a new folder being created by applying the following:-
// Desired folder structure
$structure = "../../../".$flash_dir."HELLO";
// To create the nested structure, the $recursive parameter
// to mkdir() must be specified.
$oldmask = umask(0);
mkdir($structure, 0777);
umask($oldmask);
when viewing the file permission of HELLO with DreamWeaver, it is 777. However, I suspect it is a Linux 0777 rather than a Windows 777, therefore I still cannot upload things to HELLO.
Will there be any alternative method to create a directory with windows 777? Thanks!
PS. when I manual create a new directory and right click it to set 777, it works perfectly, so I really think it's related to Linux vs Windows~
0777 is exactly the same thing as 777
But I still can't say what the problem is. I would try to chmod it again after you've created it.
$oldmask = umask(0);
chmod($structure, 0777);
umask($oldmask);
I can't understand why I have to use chmod to get the correct permissions..
The file is created succesfully but with 0755 and not 0775 that I specify in mkdir .
( http://php.net/manual/en/function.mkdir.php )
I have to do chmod after mkdir to set the correct permissions.
Safe mode is off in php.ini and the folder belongs to php's group and owner (www-data)
This doesn't work:
if(!is_dir("/var/www/customers/$username/$project_name"))
{
mkdir("/var/www/customers/$username/$project_name",0775);
}
But this does:
if(!is_dir("/var/www/customers/$username/$project_name"))
{
mkdir("/var/www/customers/$username/$project_name");
chmod("/var/www/customers/$username/$project_name",0775);
}
Yes, it's because of umask...
from comments of docs: http://php.net/manual/en/function.mkdir.php
You might notice that when you create
a new directory using this code:
mkdir($dir, 0777);
The created folder actually has
permissions of 0755, instead of the
specified
0777. Why is this you ask? Because of umask(): http://php.net/manual/en/function.umask.php
The default value of umask, at least
on my setup, is 18. Which is 22 octal,
or
0022. This means that when you use mkdir() to CHMOD the created folder to
0777, PHP takes 0777 and substracts
the current value of umask, in our
case 0022, so the result is 0755 -
which is not what you wanted,
probably.
The "fix" for this is simple, include
this line:
$old_umask = umask(0);
Right before creating a folder with
mkdir() to have the actual value you
put be used as the CHMOD. If you would
like to return umask to its original
value when you're done, use this:
umask($old_umask);
I think you may have to modify your umask.
As noted on the mkdir manpage:
The mode is also modified by the current umask, which you can change using umask().
Now, looking at the umask() manpage, one of the comment listed confirms my inner thought:
"It is better to change the file permissions with chmod() after creating the file."
In other words, I believe the way you are doing it is more secure:
Set your umask so that files are created private to your user, then use chmod to open them up.
Try calling this function before you make your directory: clearstatcache(); Also, maybe you should check if you can do it using just mkdir if you siwtch to another user.
Figured PHP's rename would be my best bet. I didn't see many examples on how to use relative URLs in it though, so I kind of compromised. Either way, this give me permission denied:
I want to do this:
$file = "../data.csv";
rename("$file", "../history/newname.csv");
Where ../ of course would go back 1 directory from where the script is being ran. I couldn't figure out a way...so I did this instead:
$file = "data.csv";
$path = dirname(realpath("../".$file));
rename("$path/$file", "$path/history/newname.csv");
However I am getting permission denied (yes the history folder is owned by www-data, and yes data.csv is owned by www-data). I thought it was weird so I tried a simple test:
rename( 'tempfile.txt', 'tempfile2.txt' );
and I made sure www-data had full control over tempfile.txt...still got permission denied. Why? does the file your renaming it to have to exist? can you not rename like linux's mv? So I instead just copy() and unlink()?
In order to move a file from "../" to "../history/", a process needs write permission to both "../" and "../history/".
In your example, you're obviously lacking write permission to "../". Permissions for the file being moved are not relevant, by the way.
Not only ownership plays a role, but also file permissions. Make sure that the permissions are set up correctly on the source file and destination directory (e.g. chmod 644 data.csv).
Is www-data the same user as Apache?
Edit: Take care to provide existing, absolute paths to realpath(). Also beware of the following:
$path = dirname(realpath("../".$file));
This might yield nothing, because the file ../data.csv might not exist. I.e., the result of realpath() on a non-existent file is false.
Here's some code that might work better for you:
$file = "data.csv";
$path1 = realpath($file);
$path2 = realpath(dirname($file).'/..').'/history/newname.csv';
rename($path1, $path2);
You should be extremely careful that $file cannot be edited by the visitor, because he could change a request manipulate which file is renamed to where.