Skip to content

Conversation

@Girgias
Copy link
Member

@Girgias Girgias commented Jan 16, 2023

RFC: https://wiki.php.net/rfc/file-descriptor-function

The purpose of this function is to retrieve the underlying file descriptors for PHP streams when they exist.
It is currently possible to achieve this result by using FFI and stubbing the Zend engine (see: https://github.com/ppelisset/php-fileno).
This can be needed when trying to interact with a USB device, as this is the use case @ppelisset has.

Test should be based of #10173 when it gets merged.

* It is only used here so that the buffered data warning is not displayed.
*/
if (php_stream_can_cast(stream, PHP_STREAM_AS_FD | PHP_STREAM_CAST_INTERNAL) == FAILURE) {
zend_argument_type_error(1, "cannot represent as a file descriptor");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
zend_argument_type_error(1, "cannot represent as a file descriptor");
zend_argument_type_error(1, "cannot be represented as a file descriptor");

@azjezz
Copy link

azjezz commented Feb 1, 2023

it think we miss a test case for closed resources, i.e:

$fp = fopen('somefile.txt', 'wb+');
fclose($fp);

try {
  var_dump(file_descriptor($fp));
} catch ( ... ) {
  ...
}


php_stream_from_zval(stream, zsrc);

/* TODO Should support streams that can be cast with PHP_STREAM_AS_FD_FOR_SELECT ? */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general PHP_STREAM_AS_FD should be supported if PHP_STREAM_AS_FD_FOR_SELECT which should be the case for all core stream wrappers - I just checked and don't see a case where it would be different. So I wouldn't bother with checking PHP_STREAM_AS_FD_FOR_SELECT as well.

Copy link
Member

@bukka bukka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good in general. The test failure seems related as you probably know.

@Girgias Girgias requested a review from kocsismate as a code owner April 15, 2024 15:43
@7snovic
Copy link
Contributor

7snovic commented Jan 11, 2026

@Girgias Any updates with this PR?

@Girgias
Copy link
Member Author

Girgias commented Jan 11, 2026

@Girgias Any updates with this PR?

Requires an RFC and people didn't seem to find the motivation strong enough.

What is the reason you want this function? As it may help me push this through the RFC process.

@7snovic
Copy link
Contributor

7snovic commented Jan 12, 2026

@Girgias I was integrating a C function into my PHP app using FFI. The C function requires a raw OS file descriptor.

For now, I'd tried the mentioned library php-fileno, It works but seems like it is extremely redundant and something like file_descriptor() is needed to be native in PHP.

Also, I used AI to get me some work around, cuz using a composer package is not the ideal thing in my case [app with only two files, x.php, x.c that needs to be portable as much as it can be]. I ended up with something like:

function get_real_fd($resource) {
    // 1. Get the Inode of the PHP resource
    $stat = fstat($resource);
    if (!isset($stat['ino'])) return false;
    $target_inode = $stat['ino'];

    // 2. Scan /proc/self/fd to find the matching FD
    $fds = scandir('/proc/self/fd');
    foreach ($fds as $fd) {
        if ($fd === '.' || $fd === '..') continue;

        // Stat the FD link to see if it matches our resource's inode
        $fd_stat = stat("/proc/self/fd/$fd");
        if ($fd_stat && $fd_stat['ino'] == $target_inode) {
            return (int)$fd;
        }
    }
    return false;
}

It works too, the good thing is that this will be working across most known Linux distros. But, it obviously seems like it won't work on Windows, macOS ... etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants