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, а каталог с правами 0755 — 40755:
<?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() в паре, когда нужно изменить права, а не просто прочитать их.