Question: I am uncompressing a .gz-file and putting the output into `tar` with php.
My code looks like 

```
$tar = proc_open('tar -xvf -', array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'a')), &$pipes);
$datalen = filesize('archive.tar.gz');
$datapos = 0;
$data = gzopen('archive.tar.gz', 'rb');
while (!gzeof($data))
{
    $step = 512;
    fwrite($pipes[0], gzread($data, $step));
    $datapos += $step;
}
gzclose($data);
proc_close($tar);

```

It works great (tar extracts a couple directories and files) until a bit more than halfway in (according to my `$datapos`) the compressed file, then the script will get stuck at the `fwrite($pipes...)` line forever (i waited a few minutes for it to advance).

The compressed archive is 8425648 bytes (8.1M) large, the uncompressed archive is 36720640 bytes (36M) large.

What am I possibly doing wrong here, since I havn't found any resources considering a similar issue?

I'm running php5-cli version 5.3.3-7+squeeze3 (with Suhosin 0.9.32.1) on a 2.6.32-5-amd64 linux machine.

Answer: 
`1 => array('pipe', 'w')`

You have tar giving you data (file names) on stdout. You should empty that buffer. (I normally just read it.)

You can also send it to a file so you don't have to deal with it.

`1 => array('file', '[file for filelist output]', 'a')`

if you're on Linux, I like to do

`1 => array('file', '/dev/null', 'a')`

[Edit: Once it outputs enough, it'll wait for you to read from standard out, which is where you are hanging.]
Your problem is one of buffer, like [@EPB](https://stackoverflow.com/a/11231062/492901) said. Empty the stream buffer (e.g.: using `fread` on `$pipes[1]` in non-blocking mode; or simply remove the `v` switch).

I want to point out however, that `$datalen` will contain the compressed length of the data, while `$datapos` will contain the uncompressed one, because the `$step` passed to `gzread` is the *uncompressed length to read* in bytes. If you want to populate `$datalen` with the actual uncompressed archive size, use something like this:

```
$info = shell_exec('gzip -l archive.tar.gz');
$temp = preg_split('/\s+/', $info);
$datalen = $temp[6]; // the actual uncompressed filesize

```

Otherwise you'd end up with `$datapos` always being bigger than `$datalen`.