fopen creates the file, so why is the fwrite failing? - php

I have this stupid little test PHP script running on a Ubuntu system inside an instance of a virtual server (Oracle Virtual Box) running on my pc:
<?
error_reporting(E_ALL);
ini_set('display_errors', 1); // show errors
echo "<p>test</p>";
$filename = "andy.txt";
$fh = fopen($filename, 'w') or die('fopen failed');
fwrite($fh, "qwerty") or die('fwrite failed');
fclose($fh);
?>
Despite all appropriate directory and file permissions being set, it is failing on the fwrite. The fopen works and creates the file, so write access is clearly enabled, but the fwrite dies, and the 'fwrite failed' message is output (no other error output is displayed).
The same script works perfectly well when I upload to my real server, so I am completely stumped as to why it won't write to the file; maybe it's something about my virtual server that is causing the problem.
Seems like such a pathetic thing, but it's driving me nuts! Considerable time Googling has failed to yield an answer, so can anybody here please provide some insight? Many thanks.

Not sure why the fwrite() call would die, as it returns the number of bytes written.
That said, have you tried with file_put_contents() instead? It's a simpler way of writing to a file, and is the recommended way since early PHP 5.
With it you only need to do the following
$filename = "andy.txt";
if(!file_put_contents ($contents, $filename)) {
// Write failed!
}
No need to bother with opening and closing the file pointer, as that's automatically handled by the function. :)

Solved! It was a disk space error on my virtual server. At the back of my mind, I knew I had seen this mentioned elsewhere as an issue with write fails, but in this case I failed to make the connection.
#ChristianF Thanks! Switching to file_put_contents() was very helpful, since it also failed, but gave me a meaningful error message:
'file_put_contents(): Only 0 of 6 bytes written, possibly out of free disk space'
Aha! Having recalled that growing log files can be a problem, I took it upon myself to delete everything inside /var/log (after saving them) and Presto! it now works! So, thank you for that tip - I will switch to using file_put_contents from now on. BTW: The contents of error.log itself was 2GB, while the remaining size of everything else in /var/log was only about 15MB, but deleting error.log by itself did not work, so I deleted everything.
#Clayton Smith Thank you, but removing the "or die('fwrite failed')" part did not result in any further error info - which is what is so frustrating: It's a shame that those error reporting directives at the start of the script didn't seem to do much.
#NaeiKinDus Thank you, but I don't think I have SELinux running (I'm afraid I don't know anything about this). Although I have a /etc/selinux directory present, there's no config file in it, just what appears to be a skeleton semanage.conf - whatever that is. Commands such as sestatus are not recognised.

Related

PHP's fgetcsv returning false at beginning of file

This is a PHP script running under Windows. It had been working but has recently stopped.
The file is opened and a valid file handle is returned: $fh = fopen($filename, 'r');
However, the very first time I call fgetcsv it returns false:
$headers = fgetcsv($fh, 6000, ',');
$line_no++;
if($headers === FALSE){
echo 'Error parsing file headers';
}
This is now happening on all csv files I try. Other changes I have tried to no avail are:
ini_set('auto_detect_line_endings', true); Right before opening the file
rewind($fh); Right after opening the file
Using both 0 or a number like 6000 for the second parameter, length.
Changing the file's line endings style from unix to Windows and Mac
It seems like something with Windows is causing this file not to parse.
Is there any way to return the actual error from fgetcsv? The documentation doesn't say there is, just that it returns false on any error. Are there other Windows settings that could be causing issues? The Windows security settings give everyone full control of the files.
The issue turned out to be that a change at the beginning of the script was using the same file as a lock file so the script wouldn't be run on the same file twice at the same time. Then, later in the script when I actually wanted to parse the file, I opened it again (which was successful), but then I couldn't actually read the contents.
The solution I used was to create a temporary lock file based on the filename instead of using the actual file. Eg: $filename.'.lock'
It was a silly mistake on my part, however it would have been much more helpful if PHP had returned or written an error/warning at some point.
The canonical way to debug this would be "print_r($headers)".
As fgetcsv returns an array, it must be empty or a non-array. If you can configure (or have configured) PHP to log errors to a known location (Windows with IIS would be "syslog" and should show up in the Event Viewer), you should be able to figure out what's wrong.

php fopen function dies, though I have file permissions set to read and write

I'm following a tutorial on php, and am having difficulty getting this to work. I set the appropriate directory permissions to read and write, but every time I run this, I get the die string.
The code is:
$ourFileName = "testFile.txt";
$ourFileHandle = fopen($ourFileName, 'w') or die("can't open file");
fclose($ourFileHandle);
As far as my basic understanding goes, if "testFile.txt" does not exist, fopen should create that file (I have basic knowledge of Python, and remember this same principle in that language). But it...it doesn't. Even if I create the aforementioned file, and put it up, that line of code still returns a die string.
My hosting account does not give me permission to execute. Is this a problem?
My server runs on Windows. I am using Dreamweaver CS5, on OSX 10.5.8.
I've done some searching on this, and see other people having similar issues - but none of them keyed to exactly my range of problems. Being that I'm a beginner, I feel that it might be something I'm overlooking.
Thanks!!
The 'or die' doesnt really do much for you other than killing the script...
Seeing as your code should work... Try debugging:
Put this at the top of your php
error_reporting(E_ALL);
ini_set('display_errors','1');
Problem fixed. I use godaddy, and had them switch my account - which was previously housed on a Windows server - over to a Linux one. With Windows, I didn't have as much control over file permissions. Now I do - and now that code works as it should.

PHP file_put_contents() error

Everytime I try to modify a file, I get this error and I don't know what it means:
A PHP Error was encountered
Severity: Warning
Message: file_put_contents() [function.file-put-contents]: Only 0 of 19463 bytes written, possibly out of free disk space
Filename: Template/String.php
Line Number: 369
I tried looking for solutions and so far none of them made sense, well, in my opinion.
Any thoughts? A little help here please. Thank you very much.
This is an old question but it comes up when Googling for the error message. Here is another possible cause for this error message.
The ext2/3/4 filesystems can reserve disk space for root. Often it is 5% of the drive. df shows the drive is not entirely used. Root can write to the drive. Non-root users will only be able to create files but not write any data to them. See dumpe2fs and tune2fs for more details.
This probably means that PHP is able to get a valid file descriptor, but is hitting a wall (such as a quota, sticky bit, etc) when actually trying to write the data.
It is also conceivable that you are writing (perhaps unwittingly) to a network file system that is having a problem with its peer.
More information regarding your platform would help (I've seen SELinux do strange things when improperly configured), but I think you get the gist of what to check.
It's just a permission to where you wanted to save the content, e.g. readonly or just like the error itself, no disk space.
You may need to increase the quota for that user on the server. You can confirm this by deleting a file and seeing if it will let you re-upload that file, but nothing further.
If you have Webmin, go to System > Disk Quota. (For a detailed explanation, see this wiki.)
If you do not have Webmin or a similar interface, you will need to look up how to manually edit the user quota settings depending on which Linux distro you are using.
If you do not have access to the server you will need to contact the person who does and ask what your disk quota is and if it can be increased.
For me I was also having the same set of errors on my login page. While exploring I found that the storage/logs/laravel.log file has grown up to the size of 24G. And clearing it solved the issue. To find out the size of directory use linux command du -sh * or du -sh <filename> . To clear up the log file using truncate command is the best option. Because oping with vim and deleting could be difficult because of Heavy size of the file. For truncating use the command truncate -s 0 <filename>
I went to the root directory
cd /
and searched for the folder that had the biggest space usage with
du -sh *
from there I was able to trace the file giving the headache, pluto.log in /var/log. this could be any file.
Maybe you have a previous lock on your target file, try to:
$fp = fopen('yourfile.etc', 'r+');
if (!flock($fp, LOCK_EX | LOCK_NB)) {
//this file is actually being used from another script / user, that's the problem.
} else {
//ok, there wasn't lock on it, must be something else
fclose($fp);
}

PHP Wamp is not finding a file which exists

I'm having a critical issue where my WAMP installation for PHP 5.3.0 is not finding a file which exists within my computer. Does anyone know anything about this? Possibly a PHP Bug?
Any help would be much appreciated.
Here is the variable which creates the file:
$baseNewsUrl = "C:/reviews/reviews/$platform/$fullname";
And here is the code which grabs the contents:
if(is_file($baseNewsUrl)){
$contents = file_get_contents($baseNewsUrl);
} else {
echo "File not found. " . "\r\n";
continue;
}
Here is the output of $baseNewsUrl: C:/reviews/reviews/GBA/r20107_GBA.htm
And the file does exist.
Check that the entire path leading up to your file is readable by the user PHP is running as (if you are using IIS, this might be something like "Network Service," although I am not particularly experienced with PHP on Windows). Also, check whether the INI directives "open_basedir" or perhaps "safe_mode" are set--these would give PHP self-imposed limits on which files are accessible.
Do a var_dump (not an echo) on your variable.
var_dump($baseNewsUrl);
and look at the actual contents. You may have some invisible garbage characters in there that's preventing Windows if you're doing this in a browser to make sure there's no empty tags (or other browser-render-invisible) characters.
If that doesn't reveal anything, remove the is_file check and try to open the file with file_get_contents (or any file related function) and var_dump it's contents. You'll either open the file, or PHP will spit out an error/warning/notice (either to your browser or to your error log) that should let you know why it can't open the file.
I'm gonna say this, and it very well might not be your problem but it is a recurring one for me. If you use skype on your computer, it has a somewhat known compatibility issue with WAMP. It cause's WAMP to be unstable, not load files properly.. everything.
on windows
$baseNewsUrl = "C:\\reviews\\reviews\\$platform\\$fullname";
It's due to Windows Vista and WAMP.

move_uploaded_file hangs?

I seem to have a bizarre error I just can't quite figure out. My website was working on one server, but when I transferred it to a new one it stopped working. I believe I've narrowed the error down to this line of code:
$ret = move_uploaded_file($tmp_name, $orig_path);
This is executed through an AJAX call so it's a little bit tricky to debug, but the script can send back an error code and then my JavaScript will alert it. So, I've wrapped it in two of these debug statements:
echo json_encode(array(
'success' => false,
'errno' => $tmp_name.' -> '.$orig_path,
));
exit;
$ret = move_uploaded_file($tmp_name, $orig_path);
echo json_encode(array(
'success' => false,
'errno' => 'no error',
));
exit;
The first one works fine and spits out something like:
error /tmp/phpk3RICU -> /home/username/Websites/website/photos/o/2-4a3354dd017a9.jpg
Perhaps I'm a bit of a linux noob, but I can't actually find /tmp/phpk3RICU on my system (is it deleted as soon as the script exits or what?). More on that in a sec though.
If I delete the first debug check and let move_uploaded_file run, the 2nd debug check never seems to get executed, which leads me to believe move_uploaded_file is hanging.
If instead of using $tmp_name I use a file I know doesn't exist, then the 2nd check DOES get executed. So... it seems like it just doesn't want to move that tmp file, but it's not reporting an error.
I'm running a fresh install of the LAMP stack on my Unbutu machine, installed through apt-get... let me know if you need more info.
Oh.. and don't know if it's relevant, but the file gets uploaded through flash.
Do you upload the file via the AJAX call?
Uploaded files are deleted as soon as the script you uploaded them to finishes executing - that's why you can't find it in /tmp.
Try telling PHP to spit out all errors:
error_reporting(E_ALL);
It could be a configuration discrepancy that is breaking it on one of your servers. From the move_uploaded_file() manual page:
Note: move_uploaded_file() is both
safe mode and open_basedir aware.
However, restrictions are placed only
on the destination path as to allow
the moving of uploaded files in which
filename may conflict with such
restrictions. move_uploaded_file()
ensures the safety of this operation
by allowing only those files uploaded
through PHP to be moved.
Ugh. The problem was with permissions. 755 was enough on the other server, but not for this server it seems... not really sure why, I guess PHP is running under a different user? I'm not really sure how the whole permissions stuff works. What really boggles me is why mkdir and move_uploaded_file didn't fail and return false...

Categories