【PHP】 プログラムでパーミッションを取得する
更新日:2020/01/28
PHPでファイルやディレクトリのパーミッションを取得して、rやwなどの文字で出力してみます。
ファイル・ディレクトリのパーミッションを取得する関数
PHPでファイル・ディレクトリのパーミッションを取得するには、fileperms関数を使用します。
fileperms関数
fileperms ( string $filename ) : int
ファイルのパスを引数として渡すと、ファイルのパーミッションが整数で返ります。
取得できないときは、E_WARNING例外が発生します。
使用例
$ php -r "echo fileperms('index.php');" 33188
整数ではわかりにくいですね。
decoct関数を使用すると、整数値を8進数の文字列に変換してくれます。
結果を8進数で表示
$ php -r "echo decoct(fileperms('index.php'));"
100644
馴染みのある結果を取得できました。
最初の2桁は、ファイルかディレクトリかなどのタイプが設定されています。
https://www.php.net/manual/ja/function.fileperms.phpに掲載されている例を見ると、タイプは次のような値になっているようです。
8進数 | 16進数 | ファイルタイプ |
---|---|---|
0140000 | C000 | ソケット |
120000 | A000 | シンボリックリンク |
100000 | 8000 | 通常のファイル |
60000 | 6000 | ブロックスペシャルファイル |
40000 | 4000 | ディレクトリ |
20000 | 2000 | キャラクタスペシャルファイル |
10000 | 1000 | FIFO パイプ |
fileperms関数で取得したパーミッション値からファイルタイプを取得するには、次のようにビット演算子を使用します。
ファイルタイプを判断するPHPコード
<?php
$type = fileperms('index.php') & 0770000;
if( $type === 0100000) echo '通常ファイル';
PHPでは、数値の前に「0(ゼロ)」をつけると8進数として扱われます。
fileperms関数の使用例
https://www.php.net/manual/ja/function.fileperms.phpに掲載されている例を元に、パーミッションを分析する関数を作成してみます。
getPermissionクラス
class getPermission{
const FIleType=[
0140000=>[ 's' , 'ソケット' ],
0120000=>[ 'l' , 'シンボリックリンク' ],
0100000=>[ '-' , '通常のファイル' ],
060000=>[ 'b' , 'ブロックスペシャルファイル' ],
040000=>[ 'd' , 'ディレクトリ' ],
020000=>[ 'c' , 'キャラクタスペシャルファイル' ],
010000=>[ 'p' , 'FIFO パイプ' ],
];
const FIleTypeUnKown = [ 'u' , '不明なタイプ' ];
const ReadFlg=[ 'on' => 'r ', 'off'=> '-' ];
const WriteFlg=[ 'on' => 'w' , 'off' => '-' ];
const ExcuteFlg=[ [ 'on' => 's' , 'off' => 'x' ] , [ 'on' => 'S' , 'off' => '-' ] ];
const ExcuteGlobalFlg
=[ [ 'on' => 't' , 'off' => 'x' ] , [ 'on' => 'T' , 'off' => '-' ] ];
public static function getData( $filepath ){
// ファイル存在しないならfalse
if( !file_exists( $filepath )) return false;
// パーミッション取得
$permission=fileperms( $filepath );
// ファイルタイプ取得
$type = self::getType( $permission );
// 8進数で4桁目の一桁目にシフト
$flg = ( $permission & 07000) >> 9;
// パーミッションを個別に分析
// Owner部
$r = self::getPerm(
( $permission & 0700 ) >> 6 , // 8進数で3桁目を一桁目にシフト
$flg & 4, // 3ビット目だけ残す
self::ExcuteFlg);
// Group部
$gp = self::getPerm(
( $permission & 0070) >> 3 , $flg & 2 , self::ExcuteFlg);
// Global部
$gl = self::getPerm(
( $permission & 0007) , $flg & 1 , self::ExcuteGlobalFlg);
return [
'value' => $permission,
'type' => $type,
'permission' => $type[0]
. $r[ 'permission' ] . $gp[ 'permission' ] . $gl[ 'permission' ],
'owner' => $r,
'group' => $gp,
'global' => $gl,
];
}
// ファイルタイプ取得関数
private static function getType( $permission ){
$type = $permission & 0770000;
return array_key_exists( $type , self::FIleType ) ? self::FIleType[ $type ] : self::FIleTypeUnKown;
}
// パーミッションを個別に分析する関数
private static function getPerm( $perm , $flg , $globalflg ){
$r = ( $perm & 0004) ? self::ReadFlg[ 'on' ] : self::ReadFlg[ 'off' ];
$w = ( $perm & 0002) ? self::WriteFlg[ 'on' ] : self::WriteFlg[ 'off' ];
$x = ( $perm & 0001) ?
( $flg ? $globalflg[0][ 'on' ] : $globalflg[0][ 'off' ])
:( $flg ? $globalflg[1][ 'on' ] : $globalflg[1][ 'off' ]);
return [
'permission' =>$r . $w . $x,
'read' => $r ,
'write' => $w ,
'excute' => $x
];
}
}
getData関数を実行すると、配列が返ります。
汎用性を考慮して、取得できるデータ量が多めなので余分な部分は削ってください。
getData()の返り値
返り値:配列[
'value' => fileperms()の結果,
'type' => [ ファイルタイプ
0 => 表示用文字
1 => 説明
],
'permission' => ファイルパーミッションの文字列,
'owner' => [ // 所有者のパーミッション
'permission' => パーミッションの文字列
'read' => 読み込み可否の文字
'write' => 書き込み可否の文字
'excute' => 実行可否の文字
],
'group' => [ // グループのパーミッション
・・・ 'owner' と同じ
],
'global' => [ // その他のパーミッション
・・・ 'owner' と同じ
],
];
使用例
$files=glob('*');
foreach($filesas$file_name){
$p=getPermission::getData( $file_name );
echo$file_name.':'.$p[ 'permission' ] . PHP_EOL;
}
実行結果
abc.txt : -rw-rw-r--
adir : drwxrwxrwx
問題点
僕の環境では、シンボリックリンクしたファイルとされたファイルに対して、fileperms関数の返り値が同じ値になりました。
そのためシンボリックリンクかどうかの判断ができませんでした。
is_link()などを併用してチェックしたほうがいいかもしれません。
更新日:2020/01/28
関連記事
スポンサーリンク
記事の内容について
こんにちはけーちゃんです。
説明するのって難しいですね。
「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。
裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。
掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。
ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php
このサイトは、リンクフリーです。大歓迎です。