2

Is there some url/stream that fopen will successfully open on most PHP installations? /dev/null is not available or openable on some systems. Something like php://temp should be a fairly safe bet, right?

The application for this code that guarantees a file resource, instead of the mixed filetype of bool|resource you have with fopen:

/**
 * @return resource
 */
function openFileWithResourceGuarantee() {
    $fh = @fopen('/write/protected/location.txt', 'w');
    if ( $fh === false ) {
        error_log('Could not open /write/protected/location.txt');
        $fh = fopen('php://temp');
    }
    return $fh;
}

In PHP 7 with strict types, the above function should guarantee a resource and avoid bools. I know that resources are not official types, but still want to be as type-safe as possible.

chiborg
  • 26,978
  • 14
  • 97
  • 115
  • `php://temp` should work fine, but might not be the best place to actually log things since it's designed to be transient. It actually won't touch the filesystem at all unless you write more than the defined memory limit (2mb by default), so it'll be lost as soon as the script exits. [`tmpfile`](http://php.net/manual/en/function.tmpfile.php) might be another option. – iainn Aug 31 '18 at 13:13
  • Take a look at `sys_get_temp_dir` which should work on pretty much every OS that runs PHP: https://secure.php.net/manual/en/function.sys-get-temp-dir.php – Loek Aug 31 '18 at 13:14
  • 1
    If logging errors is the purpose here, then why not use http://php.net/manual/en/function.error-log.php to begin with? With message_type=0 this already takes local settings as to _where_ errors should be logged into account. – misorude Aug 31 '18 at 13:14
  • [If that helps](http://php.net/manual/en/wrappers.php.php) – AymDev Aug 31 '18 at 13:15
  • The `Do some error logging here` comment is just to indicate that I want to have some signal that opening the file failed. I'll edit the example. – chiborg Aug 31 '18 at 13:49
  • @chiborg I'm still not really following, sorry. Why do you want a file pointer to an essentially random location? Reading from or writing to it doesn't serve any purpose, so why not just throw an exception (or return/break/etc) and your code can carry on from somewhere else? – iainn Aug 31 '18 at 14:27

2 Answers2

2

php://memory should be universally available.

weirdan
  • 2,499
  • 23
  • 27
0

If you need a stream for writing errors to why are you not writing to php://stderr?

Example from the docs:

When logging to apache on windows, both error_log and also trigger_error result in an apache status of error on the front of the message. This is bad if all you want to do is log information. However you can simply log to stderr however you will have to do all message assembly:

LogToApache($Message) {
        $stderr = fopen('php://stderr', 'w'); 
        fwrite($stderr,$Message); 
        fclose($stderr); 
}

Note: php://stderr is sometimes the same as php://stdout, but not always.

For streams see: http://php.net/manual/en/wrappers.php.php

Something like php://temp should be a fairly safe bet, right?

As @weirdan already pointed out php://memory is probably safer as it does not even need to create any file. Memory access MUST be possible. From the docs:

php://memory and php://temp are read-write streams that allow temporary data to be stored in a file-like wrapper. The only difference between the two is that php://memory will always store its data in memory, whereas php://temp will use a temporary file once the amount of data stored hits a predefined limit (the default is 2 MB). The location of this temporary file is determined in the same way as the sys_get_temp_dir() function.

Not sure if this answers your question completely but does it lead you into the right direction?

Blackbam
  • 17,496
  • 26
  • 97
  • 150