読者です 読者をやめる 読者になる 読者になる

モノノフ日記

普通の日記です

symfonyを1.0.11にupgradeしようとしたときのメモ

php symfony

なんかすんなりupgradeできなかったのでメモっとく。

  • 普通にPEARからupgradeしようとしたらエラー
$ sudo pear upgrade symfony/symfony
downloading symfony-1.0.11.tgz ...
Starting to download symfony-1.0.11.tgz (1,912,922 bytes)
.....................................................done: 1,912,922 bytes
Could not get contents of package "/tmp/pear/cache/symfony-1.0.11.tgz". Invalid tgz file.
Download of "symfony/symfony" succeeded, but it is not a valid package archive
Error: cannot download "symfony/symfony"
Download failed
upgrade failed
  • grepでエラーメッセージの一部を探してみた
$ grep -R 'Invalid tgz file.' /usr/local/lib/php
/usr/local/lib/php/PEAR/PackageFile.php:                                     '. Invalid tgz file.');
  • PackageFile.php(300〜323行目)
<?php
        $tar = new Archive_Tar($file);
        if ($this->_debug <= 1) {
            $tar->pushErrorHandling(PEAR_ERROR_RETURN);
        }
        $content = $tar->listContent();
        if ($this->_debug <= 1) {
            $tar->popErrorHandling();
        }
        if (!is_array($content)) {
            if (is_string($file) && strlen($file < 255) &&
                  (!file_exists($file) || !@is_file($file))) {
                $ret = PEAR::raiseError("could not open file \"$file\"");
                return $ret;
            }
            $file = realpath($file);
            $ret = PEAR::raiseError("Could not get contents of package \"$file\"".
                                     '. Invalid tgz file.');
            return $ret;
        } else {
            if (!count($content) && !@is_file($file)) {
                $ret = PEAR::raiseError("could not open file \"$file\"");
                return $ret;
            }
        }

Archive_TarクラスのコンストラクタかlistContentメソッドがおかしいみたいなのでvar_dumpデバッグしてみる

  • PackageFile.php(300〜304行目あたり)
<?php
        $tar = new Archive_Tar($file);
        if ($this->_debug <= 1) {
            $tar->pushErrorHandling(PEAR_ERROR_RETURN);
        }
        $content = $tar->listContent();
        var_dump($tar);
        var_dump($content);
  • var_dump結果
object(Archive_Tar)#1 (12) {
  ["_tarname"]=>
  string(34) "/tmp/pear/cache/symfony-1.0.11.tgz"
  ["_compress"]=>
  bool(true)
  ["_compress_type"]=>
  string(2) "gz"
  ["_separator"]=>
  string(1) " "
  ["_file"]=>
  int(0)
  ["_temp_tarname"]=>
  string(0) ""
  ["_debug"]=>
  bool(false)
  ["_default_error_mode"]=>
  NULL
  ["_default_error_options"]=>
  NULL
  ["_default_error_handler"]=>
  string(0) ""
  ["_error_class"]=>
  string(10) "PEAR_Error"
  ["_expected_errors"]=>
  array(0) {
  }
}
int(0)

listContent()をチェック

  • Tar.php(215〜228行目)
<?php
    function listContent()
    {
        $v_list_detail = array();

        if ($this->_openRead()) {
            if (!$this->_extractList('', $v_list_detail, "list", '', '')) {
                unset($v_list_detail);
                $v_list_detail = 0;
            }
            $this->_close();
        }

        return $v_list_detail;
    }

_extractList()がfalseになってるのが元凶ぽい。とりあえず1430行目以降あたりからデバッグプリントを順番にしていこうと考える

  • Tar.php(1390〜1408行目)
<?php
    while (strlen($v_binary_data = $this->_readBlock()) != 0)
    {
      $v_extract_file = FALSE;
      $v_extraction_stopped = 0;

      if (!$this->_readHeader($v_binary_data, $v_header)) {
        var_dump('debug');
        return false;
      }

      if ($v_header['filename'] == '') {
        continue;
      }

      // ----- Look for long filename
      if ($v_header['typeflag'] == 'L') {
        if (!$this->_readLongHeader($v_header))
          return false;
      }

var_dumpデバッグ1発目でヒットw _readHeader()をミスってる模様。
斜め読みすると、_readBlock()でgzファイルから512バイトずつ読んで、_readHeaderでヘッダーをチェックしてる処理。
だから、_readBlock()の結果を出力させてみた。

  • _readBlock()出力結果の最後の方
string(512) "symfony-1.0.11/lib/vendor/propel-generator/classes/propel/phing/AbstractPropelDataModelTask.php100644     41   1751       45123 10745327731  26136 "
string(512) "symfony-1.0.11/lib/vendor/propel-generator/classes/propel/phing/PropelOldSQLTask.php100644     41   1751       20716 10745327731  23717 "
string(512) "symfony-1.0.11/lib/vendor/propel-generator/classes/propel/phing/PropelGraphvizTask.php100644     41   1751       10143 10745327731  24404 "
string(512) "symfony-1.0.11/lib/vendor/propel-generator/classes/propel/phing/PropelSQLTask.php100644     41   1751       16357 10745327731  23266 "
string(512) "symfony-1.0.11/lib/vendor/propel-generator/classes/propel/phing/PropelDataDumpTask.php100644     41   1751       24752 10745327731  24324 "
string(512) "symfony-1.0.11/lib/vendor/propel-generator/classes/propel/engine/EngineException.php100644     41   1751        2624 10745327731  24016 "
string(512) "././@LongLink000        144 0             4475 L"
string(512) "       @gzwrite($p_dest, $v_buffer, $v_read_size);
        $p_size -= $v_read_size;
      }
    }
    else if ($p_mode==3)
    {
      while ($p_size != 0)
      {
        $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
                                ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
        $v_buffer = @gzread($p_src, $v_read_size);
        @gzwrite($p_dest, $v_buffer, $v_read_size);
        $p_size -= $v_read_size;
      }
    }

    // ----- Return
    return $v_result;
  }
  // ------------------------"

明らかに最後がおかしい。。。tgzファイル内にいらない情報が混ざってるのか?
ちなみに他のtgzファイルの解凍は問題無くできているのでsymfonyのtgzファイルに問題がありそう。

シェル上からは普通にtgzファイルを解凍できるので、このエラーチェックをコメントアウトしてupgradeしてみた

  • Tar.php(1435〜1437行目あたり)
//       if (!$this->_readHeader($v_binary_data, $v_header)) {
//         return false;
//       }
$ sudo pear upgrade symfony/symfony
downloading symfony-1.0.11.tgz ...
Starting to download symfony-1.0.11.tgz (1,912,922 bytes)
.....................................................done: 1,912,922 bytes
upgrade ok: channel://pear.symfony-project.com/symfony-1.0.11

普通にupgradeできた。しかし根本的な原因解決になってない罠・・・orz