12000


Mac OSX上でPHP 5.6.2を使っています。

以下のディレクトリ構成を`zip -ry`して圧縮ファイルを作成しました。  
このファイルをunzipコマンドで解凍すると、シンボリックリンクを正しく抽出できるのですが、PHPのZipArchiveクラスを使って解凍すると、ただのファイルになってしまいます。

PHPを使って、シンボリックリンクを正しく解凍するよい方法はないでしょうか？  
なお、圧縮ファイルの種類や、PHPのライブラリの種類は問いません。

### 圧縮ファイルの作成

シンボリックリンクを含んでいます。

[code]

    $ tree samples
    samples
    ├── symlinks
    │   ├── text1.txt -> ../text1.txt
    │   └── text2.txt -> ../text2.txt
    ├── text1.txt
    └── text2.txt
    
    $ zip -ry samples.zip samples
    
[/code]

### unzipで解凍

シンボリックリンクを正しく解凍できています。

[code]

    $ unzip samples.zip -d tmp
    $ tree tmp
    tmp
    └── samples
        ├── symlinks
        │   ├── text1.txt -> ../text1.txt
        │   └── text2.txt -> ../text2.txt
        ├── text1.txt
        └── text2.txt
    
[/code]

### PHPで解凍

シンボリックリンクがただのファイルになってしまいました。

[code]

    $ php unzip.php 
    $ tree tmp
    tmp
    └── samples
        ├── symlinks
        │   ├── text1.txt
        │   └── text2.txt
        ├── text1.txt
        └── text2.txt
    
[/code]

PHPの解凍用プログラム

[code]

    <?php // unzip.php
    
    $zip = new ZipArchive;
    $zip->open("samples.zip");
    $zip->extractTo("tmp");
    $zip->close();
    
[/code]


CC BY-SA 3.0
2015-07-03T12:31:14.307
11999
2015-07-05T01:45:58.800
2015-07-05T01:45:58.800
9529
9529
question
php
PHPでシンボリックリンクを含む圧縮ファイルを解凍したい


`php5.6.0`で追加された[`getExternalAttributesIndex`](http://php.net/manual/ja/ziparchive.getexternalattributesindex.php)を利用するとシンボリックリンクかどうかが判定できます。

[code]

    <?php
    
    function extractToSym($zip, $dir)
    {
      for ($idx=0; $s = $zip->statIndex($idx); $idx++) {
        if ($zip->getExternalAttributesIndex($idx, $opsys, $attr) && $opsys == ZipArchive::OPSYS_UNIX) {
          if ((($attr >> 16) & 0120000) === 0120000) {
            symlink($zip->getFromIndex($idx), $dir . '/' . $s['name']);
          } else {
            $zip->extractTo($dir, $s['name']);
          }
        }
      }
    }
    
    $zip = new ZipArchive();
    if ($zip->open('samples.zip') === TRUE) {
      extractToSym($zip, '.');
      $zip->close();
    }
    
[/code]

**追記:**

zipファイルの`ExternalAttributes`について、ドキュメントは見つかりませんでしたが[`Info-
ZIP`](http://sourceforge.net/projects/infozip/?source=typ_redirect)のソースコードを見る限りでは、この数値は`stat`構造体の`st_mode`フィールドの値を16bit左にシフトしたもののようです。

[code]

    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
    
[/code]

[`sys/stat.h`](http://linuxjm.osdn.jp/html/LDP_man-
pages/man2/stat.2.html)ではシンボリックリンクのフラグが`0120000`と定義されています。

ソースコードを見る限りではwindowsでも似たような構造になっているようですが、手元に確認できる環境がないので詳しくは分かりません。


CC BY-SA 3.0
2015-07-03T13:19:33.980
12000
2015-07-04T10:53:12.737
2015-07-04T10:53:12.737
3639
3639
11999
answer