W3docs

fileperms()

Функция fileperms() возвращает права доступа к файлу в виде целого числа, включая биты типа файла и биты доступа Unix.

Функция PHP fileperms() считывает биты прав доступа и типа файла из файловой системы и возвращает их в виде единого целого числа (Unix file mode). На этой странице рассматривается, что именно содержится в этом числе, как преобразовать его в привычный восьмеричный вид наподобие 0644, типичная ловушка, которая подстерегает почти каждого при первом знакомстве с функцией, а также способ получить строку в формате ls -l. На не-Unix системах, таких как Windows, значение менее информативно, однако функция по-прежнему работает.

Что такое функция fileperms()?

Функция fileperms() возвращает права доступа к файлу, указанному в параметре filename, в виде целого числа, либо false при ошибке (например, если файл не существует). Это целое число кодирует одновременно тип файла (обычный файл, каталог, символическая ссылка и т.д.) и биты доступа (чтение/запись/выполнение для владельца, группы и остальных).

Синтаксис

fileperms(string $filename): int|false
  • $filename — путь к файлу или каталогу для проверки.

Поскольку результат является «сырым» целым числом, перед отображением его пользователю практически всегда следует преобразовать в восьмеричный вид с помощью sprintf():

sprintf('%o', fileperms($filename));

Ловушка: значение — это не просто 0644

Главная неожиданность состоит в том, что fileperms() возвращает не 0644. Функция возвращает полный режим, включающий биты типа файла. Обычный файл с правами 0644 сообщает восьмеричный режим 100644, а каталог с правами 075540755:

<?php

$filename = 'demo.txt';
file_put_contents($filename, 'demo');
chmod($filename, 0644);

$perms = fileperms($filename);

echo $perms, "\n";                       // 33188  (decimal)
echo sprintf('%o', $perms), "\n";        // 100644 (octal, includes type bits)
echo sprintf('%o', $perms & 0777), "\n"; // 644    (permission bits only)
echo substr(sprintf('%o', $perms), -4);  // 0644   (last four octal digits)

Чтобы получить только биты прав доступа, наложите маску & 0777 (она отсекает всё выше трёх нижних восьмеричных цифр) или возьмите последние цифры восьмеричной строки с помощью substr(). Используйте маскирование, когда нужно сравнить число с константой; используйте substr(), когда нужна строка, дополненная до четырёх цифр.

Чтение прав доступа к существующему файлу

В реальном коде сначала проверьте существование файла, чтобы не получить предупреждение при его отсутствии:

<?php

$filename = 'demo.txt';
file_put_contents($filename, 'demo');
chmod($filename, 0644);

if (file_exists($filename)) {
    $perms = fileperms($filename);
    printf("%s -> %s\n", $filename, substr(sprintf('%o', $perms), -4));
    // demo.txt -> 0644
} else {
    echo "File not found.\n";
}

Смотрите file_exists() для проверки существования файла и is_readable(), если важно знать, может ли ваш процесс фактически прочитать файл, а не просто узнать его «сырой» режим.

Преобразование режима в строку формата ls -l

Биты, возвращаемые fileperms(), напрямую соответствуют нотации -rw-r--r--, выводимой командой ls -l. Старшие биты определяют символ типа; младшие девять бит — это тройки rwx для владельца, группы и остальных. Следующий фрагмент (адаптирован из официального руководства PHP) формирует такую строку:

<?php

$filename = 'demo.txt';
file_put_contents($filename, 'demo');
chmod($filename, 0644);

$perms = fileperms($filename);

switch ($perms & 0xF000) {
    case 0xC000: $info = 's'; break; // socket
    case 0xA000: $info = 'l'; break; // symbolic link
    case 0x8000: $info = '-'; break; // regular file
    case 0x6000: $info = 'b'; break; // block special
    case 0x4000: $info = 'd'; break; // directory
    case 0x2000: $info = 'c'; break; // character special
    case 0x1000: $info = 'p'; break; // FIFO pipe
    default:     $info = 'u';        // unknown
}

// Owner
$info .= ($perms & 0x0100) ? 'r' : '-';
$info .= ($perms & 0x0080) ? 'w' : '-';
$info .= ($perms & 0x0040)
    ? (($perms & 0x0800) ? 's' : 'x')
    : (($perms & 0x0800) ? 'S' : '-');
// Group
$info .= ($perms & 0x0020) ? 'r' : '-';
$info .= ($perms & 0x0010) ? 'w' : '-';
$info .= ($perms & 0x0008)
    ? (($perms & 0x0400) ? 's' : 'x')
    : (($perms & 0x0400) ? 'S' : '-');
// Other
$info .= ($perms & 0x0004) ? 'r' : '-';
$info .= ($perms & 0x0002) ? 'w' : '-';
$info .= ($perms & 0x0001)
    ? (($perms & 0x0200) ? 't' : 'x')
    : (($perms & 0x0200) ? 'T' : '-');

echo $info; // -rw-r--r--

Когда это применяется?

  • Аудит — журналируйте или отображайте права доступа к каталогам загрузок, конфигурационным файлам или папкам кэша.
  • Диагностика — убедитесь, что скрипт развёртывания установил 0755/0644 правильно, а не действуйте наугад.
  • Условное исправление — прочитайте текущий режим и, если он слишком открытый, ограничьте его с помощью chmod().

Ловушки и советы

  • Всегда накладывайте маску & 0777 (или обрезайте строку) перед сравнением с литералом вроде 0644 — иначе биты типа делают любое сравнение заведомо ложным.
  • Результаты кэшируются. PHP кэширует данные stat, поэтому если вы изменили права доступа и затем перечитываете их в рамках того же запроса, сначала вызовите clearstatcache().
  • При ошибке возвращается false, а не 0. Права доступа 0 технически допустимы, поэтому при необходимости различить реальный режим 0 и ошибку используйте ===.
  • Ограниченная поддержка Windows. Биты выполнения и биты группы/остальных не имеют смысла в Windows, поэтому значение отражает лишь то, что предоставляет данная платформа.
  • Для получения полного набора метаданных файла (размер, владелец, временные метки) за один вызов используйте stat(); filetype() возвращает только тип в виде слова, например file или dir.

Заключение

fileperms() возвращает полный Unix file mode в виде целого числа, объединяя тип файла с битами доступа. Преобразуйте его в восьмеричный вид с помощью sprintf('%o', ...), не забывайте накладывать маску & 0777 (или брать последние цифры), чтобы выделить биты прав доступа, и используйте chmod() в паре, когда нужно изменить права, а не просто прочитать их.

Практика

Практика
Какие из следующих утверждений о правах доступа к файлам в PHP верны?
Какие из следующих утверждений о правах доступа к файлам в PHP верны?
Was this page helpful?