[PHP]fileperms関数完全ガイド!ファイルパーミッションの取得・設定方法を詳しく解説

PHP

こんにちは!今回はPHPのfileperms関数について、実践的な使い方から応用例まで、徹底的に解説していきます。

fileperms関数の基本情報

構文

int fileperms ( string $filename )

戻り値

  • 成功時:ファイルのパーミッション(整数値)
  • 失敗時:false

基本的な使用例

シンプルな例

$filename = 'example.txt';
$perms = fileperms($filename);

// 8進数形式で表示(一般的な表示形式)
echo substr(sprintf('%o', $perms), -4); // 例:0644

より詳細な情報を取得する例

function getFilePermissions($filename) {
    $perms = fileperms($filename);

    switch ($perms & 0xF000) {
        case 0xC000: // ソケット
            $type = 's';
            break;
        case 0xA000: // シンボリックリンク
            $type = 'l';
            break;
        case 0x8000: // 通常のファイル
            $type = '-';
            break;
        case 0x6000: // ブロックスペシャルファイル
            $type = 'b';
            break;
        case 0x4000: // ディレクトリ
            $type = 'd';
            break;
        case 0x2000: // キャラクタスペシャルファイル
            $type = 'c';
            break;
        case 0x1000: // FIFO パイプ
            $type = 'p';
            break;
        default:
            $type = '?';
    }

    // 所有者の権限
    $info = $type;
    $info .= (($perms & 0x0100) ? 'r' : '-');
    $info .= (($perms & 0x0080) ? 'w' : '-');
    $info .= (($perms & 0x0040) ? (($perms & 0x0800) ? 's' : 'x' ) : (($perms & 0x0800) ? 'S' : '-'));

    // グループの権限
    $info .= (($perms & 0x0020) ? 'r' : '-');
    $info .= (($perms & 0x0010) ? 'w' : '-');
    $info .= (($perms & 0x0008) ? (($perms & 0x0400) ? 's' : 'x' ) : (($perms & 0x0400) ? 'S' : '-'));

    // その他の権限
    $info .= (($perms & 0x0004) ? 'r' : '-');
    $info .= (($perms & 0x0002) ? 'w' : '-');
    $info .= (($perms & 0x0001) ? (($perms & 0x0200) ? 't' : 'x' ) : (($perms & 0x0200) ? 'T' : '-'));

    return $info;
}

パーミッション確認のユーティリティ関数

読み取り・書き込み・実行権限のチェック

function checkFilePermissions($filename) {
    $perms = fileperms($filename);

    return [
        'is_readable' => is_readable($filename),
        'is_writable' => is_writable($filename),
        'is_executable' => is_executable($filename),
        'numeric_perms' => substr(sprintf('%o', $perms), -4),
        'symbolic_perms' => getFilePermissions($filename)
    ];
}

セキュリティチェック

function isSecurePermissions($filename) {
    $perms = fileperms($filename);
    $octal = substr(sprintf('%o', $perms), -4);

    // 推奨されるパーミッション
    $secure_file_perms = '0644';      // 通常のファイル
    $secure_dir_perms = '0755';       // ディレクトリ

    $is_directory = is_dir($filename);
    $recommended = $is_directory ? $secure_dir_perms : $secure_file_perms;

    return [
        'is_secure' => $octal <= $recommended,
        'current_perms' => $octal,
        'recommended_perms' => $recommended,
        'file_type' => $is_directory ? 'directory' : 'file'
    ];
}

実践的な使用例

ディレクトリ内のファイル権限チェック

function checkDirectoryPermissions($directory) {
    $results = [];
    $dir = new RecursiveDirectoryIterator($directory);
    $iterator = new RecursiveIteratorIterator($dir);

    foreach ($iterator as $file) {
        if ($file->isDir()) continue; // スキップ . と ..

        $path = $file->getPathname();
        $perms = fileperms($path);

        $results[] = [
            'path' => $path,
            'perms' => substr(sprintf('%o', $perms), -4),
            'symbolic' => getFilePermissions($path),
            'security_check' => isSecurePermissions($path)
        ];
    }

    return $results;
}

パーミッション修正の自動化

function fixFilePermissions($directory, $file_perms = 0644, $dir_perms = 0755) {
    $results = [];

    try {
        $dir = new RecursiveDirectoryIterator($directory);
        $iterator = new RecursiveIteratorIterator($dir);

        foreach ($iterator as $file) {
            $path = $file->getPathname();
            $is_dir = $file->isDir();

            // . と .. をスキップ
            if ($file->getFilename() == '.' || $file->getFilename() == '..') {
                continue;
            }

            $current_perms = fileperms($path);
            $desired_perms = $is_dir ? $dir_perms : $file_perms;

            if (($current_perms & 0777) != $desired_perms) {
                if (chmod($path, $desired_perms)) {
                    $results[] = [
                        'path' => $path,
                        'status' => 'fixed',
                        'old_perms' => substr(sprintf('%o', $current_perms), -4),
                        'new_perms' => sprintf('%o', $desired_perms)
                    ];
                } else {
                    $results[] = [
                        'path' => $path,
                        'status' => 'failed',
                        'error' => 'Unable to change permissions'
                    ];
                }
            }
        }
    } catch (Exception $e) {
        $results[] = [
            'status' => 'error',
            'message' => $e->getMessage()
        ];
    }

    return $results;
}

エラーハンドリング

包括的なエラーハンドリング例

function safeFilePerms($filename) {
    try {
        if (!file_exists($filename)) {
            throw new Exception('File does not exist: ' . $filename);
        }

        $perms = fileperms($filename);
        if ($perms === false) {
            throw new Exception('Unable to get file permissions');
        }

        return [
            'success' => true,
            'permissions' => [
                'octal' => substr(sprintf('%o', $perms), -4),
                'symbolic' => getFilePermissions($filename),
                'security' => isSecurePermissions($filename)
            ]
        ];

    } catch (Exception $e) {
        error_log('File permission error: ' . $e->getMessage());
        return [
            'success' => false,
            'error' => $e->getMessage()
        ];
    }
}

セキュリティのベストプラクティス

  1. 常にファイルの存在確認を行う
  2. パーミッションは必要最小限に設定する
  3. 重要なファイルは定期的にパーミッションをチェックする
  4. エラーはログに記録する
  5. パーミッション変更前にバックアップを作成する

まとめ

fileperms関数は、ファイルシステムのセキュリティ管理において重要な役割を果たします。適切に使用することで、以下のようなメリットがあります:

  • ファイルシステムのセキュリティ強化
  • 問題の早期発見と対応
  • 自動化による管理効率の向上
  • コンプライアンス要件への対応

実装の際は、必ずエラーハンドリングを考慮し、セキュリティのベストプラクティスに従うようにしましょう。

ご質問やご不明な点がありましたら、お気軽にコメントください!

タイトルとURLをコピーしました