Skip to content

fopen() fails on Windows #29

@fietserwin

Description

@fietserwin

A WordPress plugin that uses your library consistently gived an error when the tar file being created tried to add a directory to a tar archive. This because a call to fopen() a folder on Windows will fail (actually the docs say it may succeed on a folder: refsect1-function.fopen-notes, apparently on Linux it succeeds but that is not guaranteed, on Windows it doesn't)

However as a directory does not contain data and we only want to write the header block with a.o. the access rights, there’s no need to make that call to fopen(), nor write any contents block as a tar archive expects 0 or more file contents blocks after the header block, so it is correct to not write anything to the archive when the file size is 0 (empty file or directory).

I changed that part of code to only call fopen() when it is a file that is not empty. This prevents the fopen on Windows on a folder and it saves a few system calls (fopen(), feof(), fclose() for each folder and empty file) on all OS's.

php-archive/src/Tar.php, method addFile(),line 249 and further:
`

    if ($this->closed) {
        throw new ArchiveIOException('Archive has been closed, files can no longer be added');
    }

    // create file header
    $this->writeFileHeader($fileinfo);

    // write data, but only if we have data to write.
    // note: on Windows fopen() on a directory will fail, so we prevent
    // errors on Windows by testing if we have data to write.
    if (!$fileinfo->getIsdir() && $fileinfo->getSize() > 0) {
        $read = 0;
        $fp = @fopen($file, 'rb');
        if (!$fp) {
            throw new ArchiveIOException('Could not open file for reading: ' . $file);
        }
        while (!feof($fp)) {
            $data = fread($fp, 512);
            $read += strlen($data);
            if ($data === false) {
                break;
            }
            if ($data === '') {
                break;
            }
            $packed = pack("a512", $data);
            $this->writebytes($packed);
        }
        fclose($fp);

        if ($read != $fileinfo->getSize()) {
            $this->close();
            throw new ArchiveCorruptedException("The size of $file changed while reading, archive corrupted. read $read expected ".$fileinfo->getSize());
        }
    }
    ...`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions