Umask: примеры (PHP)

Контроль создания файлов через маску прав в PHP
Раздел: Работа с файловой системой
umask(int mask): int

Функция umask в PHP

Описание и назначение

Функция umask() изменяет текущую маску прав доступа (user file creation mask) для процесса. Эта маска определяет, какие биты прав доступа будут автоматически отключаться при создании новых файлов или директорий функциями вроде fopen(), mkdir() или tempnam().

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

Функция используется в сценариях, требующих контроля прав доступа к создаваемым файловым объектам. Типичные случаи включают генерацию конфигурационных файлов, работу с временными данными или обеспечение безопасности в многопользовательских средах.

Аргументы функции

Функция принимает один необязательный параметр:

  • $mask (int|null) - Новая маска прав доступа, представленная в виде целого числа. Часто используется восьмеричная запись. Если передано значение null, функция вернет текущую маску без ее изменения. В версиях PHP до 8.0.0 этот параметр был обязательным.

Возвращаемое значение - предыдущее значение маски в виде целого числа.

Базовые примеры использования

Получение текущей маски

Код для определения текущей установленной маски.

$current_mask = umask();
echo "Текущая маска: " . decoct($current_mask) . "\n";
Текущая маска: 18
Установка новой маски

Изменение маски для текущего процесса.

$old_mask = umask(0);
echo "Предыдущая маска: " . decoct($old_mask) . "\n";
echo "Новая маска: " . decoct(umask()) . "\n";
Предыдущая маска: 18
Новая маска: 0
Создание файла с учетом маски

Демонстрация влияния маски на права нового файла.

umask(022);
$file = fopen('test.txt', 'w');
fclose($file);
echo 'Права файла: ' . decoct(fileperms('test.txt') & 0777);
unlink('test.txt');
Права файла: 644

Аналоги в PHP

Функция chmod()

Позволяет явно задавать права доступа для уже существующего файла или директории. В отличие от umask(), которая влияет на будущие объекты, chmod() изменяет права уже созданных.

Параметр контекста stream_context_create()

При использовании функций работы с файлами можно задавать конкретные права через контекст потока, что дает точечный контроль без изменения глобальной маски процесса.

Выбор метода

umask() предпочтительнее для установки базовых правил на уровне всего скрипта. chmod() или контексты потоков применяются для индивидуальной настройки конкретных объектов.

Распространенные ошибки

Непонимание восьмеричного формата

Использование десятичного числа вместо восьмеричного приводит к неожиданным правам доступа.

// Ошибка: передача десятичного числа 22 вместо восьмеричного 022
umask(22); // Восьмеричное значение 026
$file = fopen('error.txt', 'w');
fclose($file);
echo decoct(fileperms('error.txt') & 0777); // Результат может быть не 644
unlink('error.txt');
640
Глобальное влияние маски

Установка маски влияет на весь процесс, что может затронуть другие части кода или сторонние библиотеки.

umask(0); // Установка "открытой" маски
// Код сторонней библиотеки создаст файл с правами 666
// ...
umask(022); // Восстановление маски только после всего кода
Игнорирование возвращаемого значения

Потеря предыдущего значения маски осложняет его восстановление.

// Проблемный код
umask(0);
// Создание файлов...
// Как восстановить старое значение?

Изменения в версиях PHP

PHP 8.0.0

Параметр $mask стал необязательным (nullable). Теперь можно вызвать umask() без аргументов для получения текущей маски, что раньше требовало передачи значения null.

// До PHP 8.0.0
$current = umask(null);
// Начиная с PHP 8.0.0
$current = umask();
Предыдущие версии

В PHP 4 и 5 параметр был обязательным. Отсутствие поддержки null могло приводить к предупреждениям.

Расширенные примеры применения

Временное изменение маски

Безопасное изменение маски только для определенного блока кода с гарантированным восстановлением.

Пример php
function createSecureFile($filename, $content) {
    $oldMask = umask(077); // Запретить доступ всем, кроме владельца
    $file = fopen($filename, 'w');
    fwrite($file, $content);
    fclose($file);
    umask($oldMask); // Восстановить исходную маску
    return $filename;
}

$file = createSecureFile('secret.txt', 'data');
echo 'Права файла: ' . decoct(fileperms('secret.txt') & 0777);
unlink('secret.txt');
Права файла: 600
Работа с директориями

Маска влияет и на создаваемые директории через mkdir().

Пример php
umask(027); // Группа: чтение-запись, остальные: нет доступа
mkdir('private_dir', 0755); // Фактические права: 0755 & ~027 = 0750
echo 'Права директории: ' . decoct(fileperms('private_dir') & 0777);
rmdir('private_dir');
Права директории: 750
Интерактивное вычисление прав

Функция для предсказания итоговых прав файла с учетом текущей маски.

Пример php
function getFinalPermissions($basePermissions) {
    $currentMask = umask();
    $final = $basePermissions & ~$currentMask;
    umask($currentMask); // Не меняем исходную маску
    return $final;
}

umask(022);
$base = 0666; // Базовые права для файла
$final = getFinalPermissions($base);
echo 'При маске ' . decoct(umask()) . ' и базовых правах ' . decoct($base) . '\n';
echo 'Фактические права будут: ' . decoct($final);
При маске 22 и базовых правах 666
Фактические права будут: 644
Маска для разных типов файлов

Использование разных масок для файлов и директорий в рамках одного процесса.

Пример php
// Установка общей маски
umask(022);

// Создание директории с одними правами
mkdir('docs', 0755); // Права: 755 & ~022 = 755

// Временное изменение маски для файлов
$old = umask(027);
$file = fopen('docs/internal.txt', 'w');
fclose($file); // Права: 666 & ~027 = 640
umask($old);

echo 'Права директории: ' . decoct(fileperms('docs') & 0777) . '\n';
echo 'Права файла: ' . decoct(fileperms('docs/internal.txt') & 0777);

unlink('docs/internal.txt');
rmdir('docs');
Права директории: 755
Права файла: 640

Аналоги в других языках

Python: os.umask()

Работает аналогично, устанавливает маску для текущего процесса.

import os
old_mask = os.umask(0o022)
print(f'Старая маска: {old_mask:03o}')
print(f'Новая маска: {os.umask(old_mask):03o}')
Старая маска: 022
Новая маска: 022
Node.js (JavaScript): process.umask()

Функция в объекте process. Может принимать строковое представление.

const oldMask = process.umask(0o022);
console.log(`Старая маска: 0${oldMask.toString(8)}`);
console.log(`Новая маска: 0${process.umask().toString(8)}`);
Старая маска: 022
Новая маска: 022
Bash/Shell: команда umask

Встроенная команда оболочки, влияющая на все создаваемые файлы в сессии.

umask 022
touch testfile
ls -l testfile
rm testfile
-rw-r--r-- 1 user group 0 Jan 1 12:00 testfile
Основное отличие

В PHP функция возвращает предыдущее значение маски, в то время как в Python и Node.js она может возвращать текущую маску при вызове без аргументов.

PHP umask function comments

En
Umask Changes the current umask