ID:               21641
 Updated by:       [EMAIL PROTECTED]
 Reported By:      [EMAIL PROTECTED]
-Status:           Open
+Status:           Bogus
 Bug Type:         Filesystem function related
 Operating System: Linux 2.4.18
 PHP Version:      4CVS-2003-01-14 (stable)
 New Comment:

function stream_read($count)
{
    if ($count + $this->pos > $this->size) {
        $count = $this->size - $this->pos;
    }
    $data = shmop_read($this->shm,$this->pos,$count);
    $this->pos += strlen($data);
    return $data;
}



Previous Comments:
------------------------------------------------------------------------

[2003-01-14 15:31:47] [EMAIL PROTECTED]

I don't understand. In the shared memory example, how am I supposed to
be able to read just four bytes from the stream? When I pass 4 to
fread(), stream_open() gets 8192 $count. I can do the math just fine in
stream_open() to trim that to 8191 (or whatever's left between the
current position and the size of the segment), but that assumes that
the fread() call was to read the rest of the segment. It's not. It's
only for four bytes.

------------------------------------------------------------------------

[2003-01-14 15:25:57] [EMAIL PROTECTED]

Not a bug.
Your stream should keep track of the maximum size available, and is
responsible for keeping within range of the functions it calls.
You already have a size and a position, you should be able to determine
the maximum readable size using that information.
If you don't want to see an error, you can use the @ operator.


------------------------------------------------------------------------

[2003-01-14 15:20:44] [EMAIL PROTECTED]

However, this causes problems for smaller values when the function that
stream_read() is calling doesn't like it when the byte count is larger
than its size. Consider this code (from the shared memory stream
wrapper I am working on)

    function stream_read($count)
    {
        $data = shmop_read($this->shm,$this->pos,$count);
        $this->pos += strlen($data);
        return $data;
    }

If the shared memory segment that $this->shm points to is less than
8192 bytes long, then shmop_read() complains that the count is out of
range. Here's some sample code if you want to try (thanks to Xavier
Noguer [[EMAIL PROTECTED]] who reported this to me):

<?php

class Stream_SHM {
    var $pos = 0;
    var $shm_key;
    var $size = 16384; // default size: 16k
    var $shm;

    function stream_open($path, $mode, $options, &$opened_path)
    {
        $url = parse_url($path);
        $this->shm_key = $url['host'];
        if ((! intval($this->shm_key)) && (!
preg_match('/^0x[0-9a-f]+$/i',
                                                       
$this->shm_key))) {
            if ($options & STREAM_REPORT_ERRORS) {
                trigger_error("Stream_SHM::stream_open: $this->shm_key
is not a valid shm key.",E_USER_ERROR);
            }
            return false;
        }
        if (intval($url['port'])) {
            $this->size = intval($url['port']);
        }
        if (($mode != 'a') && ($mode != 'c') && 
            ($mode != 'w') && ($mode != 'n')) {
            if ($options & STREAM_REPORT_ERRORS) {
                trigger_error("Stream_SHM::stream_open: $mode is not a
valid mode (must be one of: a c n w)",E_USER_ERROR);
            }
            return false;
        }
        if (! ($this->shm =
shmop_open($this->shm_key,$mode,0600,$this->size))) {
            if ($options & STREAM_REPORT_ERRORS) {
                trigger_error('Stream_SHM::stream_open: shmop_open()
failed');
            }
            return false;
        }
        $this->size = shmop_size($this->shm);
        return true;
    }

    function stream_close()
    {
        shmop_close($this->shm);
    }

    function stream_read($count)
    {
        $data = shmop_read($this->shm,$this->pos,$count);
        $this->pos += strlen($data);
        return $data;
    }

    function stream_write($data)
    {
        $count = shmop_write($this->shm,$data,$this->pos);
        $this->pos += $count;
        return $count;
    }
    function stream_eof()
    {
        return ($this->pos == ($this->size - 1));
    }
    function stream_tell()
    {
        return $this->pos;
    }
    function stream_seek($offset,$whence)
    {
        switch ($whence) {
        case SEEK_SET:
            if (($offset >= 0) && ($offset < $this->size)) {
                $this->pos = $offset;
                return true;
            } else {
                return false;
            }
            break;
        case SEEK_CUR:
            if (($offset >= 0) && (($this->pos + $offset) <
$this->size)) {
                $this->pos += $offset;
                return true;
            } else {
                return false;
            }
            break;
        case SEEK_END:
            if (($this->size + $offset) >= 0) {
                $this->pos = $this->size + $offset;
                return true;
            } else {
                return false;
            }
            break;
        default:
            return false;
        }
    }

    function stream_flush()
    {
        return true;
    }
}
  stream_register_wrapper('shm', 'Stream_SHM') 
     or die("Can't register shm on Stream_SHM");


  echo "\nUsing shm://0x0000:8192/\n";
  $mem = fopen("shm://0x0000:8192/","c");
  fwrite($mem, "hola\n");
  rewind($mem);
  $data = fread($mem, 4);
  echo "$data\n";
  fclose($mem);

  echo "\nUsing shm://0x0000:8191/\n";
  $mem = fopen("shm://0x0000:8191/","c");
  fwrite($mem, "hola\n");
  rewind($mem);
     $data = fread($mem, 4);
  echo "$data\n";
  fclose($mem);

  echo "\nUsing shmop_open() with size = 8191\n";
//shm://0x0000:8191/";
  $mem = shmop_open(0x0000, "c", 0600, 8191);
  $shm_bytes_written = shmop_write($mem, "hola", 0);
  $data = shmop_read($mem, 0, 4);
  echo "$data\n";
  shmop_close($mem);
?>

The first example, with the stream and an 8192 byte segment, works
fine. The last example, without the stream and with an 8191 byte
segment, works fine. The middle example, however, with the stream and
an 8191 byte segment fails, because the call to shmop_read() throws a
"count is out of range" error.

------------------------------------------------------------------------

[2003-01-14 15:09:37] [EMAIL PROTECTED]

This is not a bug; PHP uses an internal read buffer 8192 bytes in
length in order to be more efficient.
You should note that fread() returns the correct number of bytes to
your script.

------------------------------------------------------------------------

[2003-01-14 14:59:09] [EMAIL PROTECTED]

The stream_read() method of a class registered with
stream_register_wrapper() is always passed 8192 as a count of bytes to
read no matter what the second argument is to an fread() on that
stream. This is reproduceable with the following class and test code:

<?php
class Stream_File {
    var $fn;
    var $fp;

    function stream_open($path, $mode, $options, &$opened_path)
    {
        $url = parse_url($path);
        $this->fp = fopen($this->fn = $url['path'],$mode);
        return ($this->fp ? true : false);
    }

    function stream_close()
    {
        fclose($this->fp);
    }

    function stream_read($count)
    {
        error_log("stream_read: $count ");
        return fread($this->fp,$count);
    }
    
    function stream_write($data)
    {
        return fwrite($this->fp,$data);
    }
    function stream_eof()
    {
        return feof($this->fp);
    }
    function stream_tell()
    {
        return ftell($this->fp);
    }
    function stream_seek($offset,$whence)
    {
        return fseek($this->fp,$offset,$whence);
    }
    function stream_flush()
    {
        return fflush($this->fp);
    }
}

stream_register_wrapper('filetest', 'Stream_File') or die("Can't
register filetest on Stream_File");

$fp = fopen("filetest://localhost/tmp/hello","w+");
fwrite($fp, "testing\n");
rewind($fp);
$data = fread($fp, 10);
echo "$data\n";
rewind($fp);
$data = fread($fp,32000);
echo "$data\n";
fclose($fp);
?>

Each time fread() is called on the stream, the error_log() call in
stream_read() prints:

stream_read: 8192

instead of "stream_read: 10" or "stream_read: 32000"


------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=21641&edit=1

Reply via email to