PHP fopen 'x+' doesn't work on ubuntu - php

I created an application which has an caching script on an Windows/Wamp environment. This script's caching function is only allowed to run once at the same time.
To achieve this I used a 'locking file' with check to see if it exists.
On windows this script continues to work fine. But now it is moved to an Ubuntu environment is doesn't work.
<?php
date_default_timezone_set('Europe/Amsterdam');
ini_set('max_execution_time', 300);
ignore_user_abort(true);
$path = 'locked.txt';
if ($lock = fopen($path,'x+')) {
fwrite($lock,time());
fclose($lock);
sleep(10);
unlink($path);
}
?>
Error: fopen(locked.txt): failed to open stream: Permission denied

From the PHP documentation (paraphrased a bit):
x+ Create and open for reading and writing; place the file pointer at the beginning of the file. If the file already exists, the fopen() call will fail by returning FALSE and generating an error of level E_WARNING. If the file does not exist, attempt to create it. This is equivalent to specifying O_EXCL|O_CREAT flags for the underlying open(2) system call.
From your description you are attempting to use a file as a lock file using the "x+" flag to ensure you're not locking a file already locked.
The problem is that migrating from windows to *NIX systems (like Ubuntu) you will need to familiarise yourself with the difference in the permissions system.
The short story is:
Each file and folder "belongs" to a user.
The user who wants to create a file in a directory needs at least an execute and write permission on that directory.
Having this in mind you need to ensure that the current user has write and execute permissions on the directory with the script and to actually execute the script they will also need read permissions on the directory (in addition to read permissions on the script). Ensure that the directory has read-write-execute permissions (flag no. 7) for the user running the script.
If you're running the script via a web interface this user will be www-data .
In general chmod 777 /directory/with/script should work and grant read-write-execute permissions on the directory for all users.

Related

PHP fopen() creating file without permissions to modify it

Executing the following from a PHP script called by apache:
$h = fopen(getcwd()."tmp.txt","w");
fprintf($h,"hi");
fclose($h);
generates a file owned by my personal userid with 644 permissions. However, executing the script again results in an error, since Apache/PHP is running as user wwwrun and so doesn't have the permissions to overwrite the file or to chmod it.
The directory that the files are being placed is in my home directory and has 777 permissions. How can I get PHP to either create the file as owned by wwwrun, or create it with 666 permissions, or do something else, to allow it to be overwritten by PHP.
I am ideally looking for a solution which also applies to the situation where the file is created by PHP via an external program called with the exec function; this seems to suffer from the same problem, in that the external program runs as wwwrun, but files created by the external program are owned by my personal userid.
It turns out the directory in question was mounted on a file system that doesn't support linux file permissions.

Operation not permitted - unlink on local machine

Im trying to unlink a folder on the local version of my site.
I get the error:
operation not permitted
Any ideas how I can get unlink to work on my local machine? Im using MAMP.
See the documentation:
unlink — Deletes a file
and
See Also: rmdir() - Removes directory
You have a directory. You need to use rmdir, not unlink.
It means the script is not allowed to delete the folder. This can have various reasons - the most likely one is that you are trying to unlink() a folder instead of using rmdir() to delete it.
Here are the possible reasons for "operation not permitted" (EPERM) from the unlink(2) man page:
EPERM The system does not allow unlinking of directories, or unlinking of directories requires privileges that the calling process
doesn't have. (This is the POSIX prescribed error return; as noted
above, Linux returns EISDIR for this case.)
EPERM (Linux only)
The file system does not allow unlinking of files.
EPERM or EACCES
The directory containing pathname has the sticky bit (S_ISVTX) set and the process's effective UID is neither the UID of
the file to be deleted nor that of the directory containing it,
and the process is not privileged (Linux: does not have the CAP_FOWNER capability).
This is a permissions problem.
Try giving the file you want unlink permissions like CHMOD 666.
You probably created the file yourself and want PHP (another user then yourself, probably Apache or www-data depending on how MAMP is installed) to delete the file for you - without the right permissions, this cannot be done.

Permission denied mkdir for cron and browser

We have an PHP XML parsing script that uploads photos to a folder structure like /content/images/2012/05/31/%object_id%/. This parser runs primarily as a DirectAdmin cronjob. We run into many problems getting the folder permissions right to enable the uploading in that directory for both the cronjob as running the parser via the browser.
According to print_r(posix_getpwuid(fileowner($directory))); the owner of the directory is is the same as get_current_user(). Nevertheless I receive: Warning: mkdir() [function.mkdir]: Permission denied when running the script via the browser. It works fine when running it as a cron job.
All folders have chmod 0777 and new folders are created as such;
mkdir($path,0777,true);
Naturally we have the same permission problems with uploading and/or deleting the files themselves.
Is there any way to enable all the file actions running both as a cron job and through the browser?
We are running Linux with PHP Version 5.2.17.
Couple of thinks to note: get_current_user gets the owner of the .php file (i.e. the script) but NOT the name of the user that is running the php script. Invariably these are different as the file will be uploaded by you (a regular user) and php/apache will run as a different user (often called "apache" or "www".) You need the latter of these two. suggested snippet from the php manual to get this is:
$processUser = posix_getpwuid(posix_geteuid());
print $processUser['name'];
(http://php.net/manual/en/function.get-current-user.php - see comments)
To solve you current problem, though, my strong suggestion is to run the cron as the same user that the php/apache is running as (check man page on crontab) - the user should be the one in that snippet above, CHOWN the files and directories to that same user (they will currently be root) and to a group that is shared between you and the FTP client. Then make sure the user and group have read+write permissions so you can also edit from ftp. Make sure you change permissions on both directores (775) and files (644) as your script creates them.
Also note that if you mkdir(), then the directory above must also have write permissions for the user (and this might actually be your initial problem, and why only root/cron can write there).

open a file in PHP CLI

The file was created by apache using mkdir() and fopen() etc..
How do i let my php CLI program be allowed to read that file that apache (that is what it says the user is) created so i dont get this error:
Warning: file_get_contents(./sessions/nl2larsjl6n3315mesghmspts7.txt): failed to open stream: No such file or directory in /var/www/html/cli.php on line 58
in the cli this my code for getting the file:
$alert = file_get_contents('./sessions/'.$sessionID.'.txt');
Short answer:
when you create it, you should run chmod(0777) on it.
Long answer:
chmod(0777) means "world readable and writable, and not actually recommended. Checkout http://en.wikipedia.org/wiki/Filesystem_permissions, http://www.linuxforums.org/articles/file-permissions_94.html for a complete explanation on these numbers.
Basically if you need it to be writable by a user, and readable by any user, do a chmod(0644)
EDit: i was quick to wrinte an answer... without reading the question carefully.
You seem to try and open the file from a different directory than the folder where you created it.
Try and see the result on echo getpwd() in the CLI script and then in the script running under www. I bet you will see different locations.
When executing CLI scripts you should either do a chdir() before running the command or use absolute paths at all times for the files you access.
I personally prefer the chdir() method.

PHP Cannot write to file even though it has 777 permissions

Im trying to make a php file write to a file that resides in the same folder. Both the php file and the file its trying to write to have their permissions set to 777 (its a linux server) as well as the folder they reside in. Whenever I called fopen() with the 'w' or 'w+' mode, the function just returns false. Its on my school's webserver, so there is no way I can get root access to change the owner of the file to the same user as apache. Does anyone know whats wrong?
Update:
As a test, I was using this code:
$handle = fopen("test.txt", 'w');
if($handle === FALSE)
echo "\nfailed";
else
echo "\nsuccess";
fclose($handle);
The output now with error reporting enabled is:
Warning: fopen(test.txt) [function.fopen]: failed to open stream: Permission denied in /<snip>/public_html/test.php on line 58
failed
Warning: fclose(): supplied argument is not a valid stream resource in /<snip>/public_html/test.php on line 63
Above that is some code I copied from the php website for the fileperms() function which checks the permissions of the text file, and its reporting -rwxrwxrwx
The ls -al output of the relevant files is
ls -al *test*
-rwxrwxrwx 1 mag5 30 1475 Dec 9 00:02 test.php*
-rwxrwxrwx 1 mag5 30 8 Dec 8 14:54 test.txt*
Also Im not sure if this matters, but my school uses something called the Andrew File system (http://en.wikipedia.org/wiki/Andrew_File_System).
Telanor, AFS is a very big clue.
AFS (Andrew File System) has a whole level of directory permissions beyond that of traditional unix filesystems. Check AFS permissions on the directory to make sure you have the ability to access files in the directory. Also it may not be your permissions that matter, but the permissions of the webserver (or rather the userid it's running under). It's been a long time since I used AFS so I don't know the commands offhand to check directory permissions.
Do this instead:
$fh = fopen($filename, "a");
I imagine the problem is that you don't have the correct permissions for the directory. When you attempt to delete a file you need write permission in the directory and "w" will do that.
Alternatively, if you need to truncate/delete the file, change the directory permission so you have write permissions.
More than likely php is not running as the same user as the owner of the file. Have you tried creating a new file in the directory using php (just make a randomly named file in the same directory)?
There's a couple reasons this could fail. Based on the information around, it isn't a problem with file permissions. The first, and possibly most likely, is that your web server is running in a configuration that it has read-only access to the entire filesystem. This could be because NFS is mounted read-only, or because PHP or the server is configured in such a way as to prevent writing.
Also, please, never set a file to be 777. Even 666 is dangerous enough. This is especially true in a shared environment like a school server.
At this point, assuming you have limited control over the server environment, you should ask your administrator for more information.
It is like MadCoder says.
From the AFS Docs:
AFS ACLs work in conjunction with the standard Unix "owner" permissions. Only the owner permissions have an effect on AFS file access; Unix permissions for "group" and "other" do not affect AFS file access.
These rules apply. A user with appropriate AFS permissions can:
read a file only if the UNIX "owner read" mode is set.
write to a file only if the UNIX owner "read" and "write" modes are set.
execute a file only if the UNIX owner "read" and "execute" modes are set.
To set the AFS permissions, you need to use the fs setacl command.

Categories