Заметки о PHP: восьмеричные числа и права доступа

Быть может странно, но, несмотря на свою полезность, неявное преобразование типов в PHP подставило мне подножку при разработке скрипта. Ситуация проста — мне было необходимо написать скрипт, который забирал настройки из таблицы БД MySQL — права и нужную директорию — и создавал в ней вложенную директорию с заданными правами, а также менять права доступа на существующие файлы. Права хранятся в виде числа — 777, например (полный доступ к директории для всех пользователей в UNIX-like системах). Если я задам число в коде как восьмеричное, то все будет в порядке (Я опустил получение данных из базы, т.к. это принципиально не важно):

$dir="/path/to/dir/";
$createDir="somedir";
$permissions=0775; //так задается число в восьмеричной системе исчисления
mkdir ($dir.$createDir,$permissions);
// или при смене прав
chmod($dir.$createDir,$permissions);

Функции mkdir и chmod в качестве второго параметра — прав доступа — принимают восьмеричное число. И видно, что это работает. Но, только до тех пор, пока нет необходимости получать это число откуда-нибудь еще, а не из переменной в скрипте, тип и система исчисления которой явно заданы. К чему это приводит? Посмотрим:

$dir="/path/to/dir/";
$createDir="somedir";
$permissions=775; //десятичное число
mkdir ($dir.$createDir,$permissions);
// или при смене прав
chmod($dir.$createDir,$permissions);
$dir="/path/to/dir/";
$createDir="somedir";
$permissions="775"; //строка
mkdir ($dir.$createDir,$permissions);
// или при смене прав
chmod($dir.$createDir,$permissions);
Бах! И мы получили кривые права. В описании функции chmod мягонько так написано, что «возможна» ошибка в такой ситуации. Но не объясняется почему. А дело всё в неявном преобразовании типов данных PHP. Когда в функцию передается строковый параметр, он автоматически преобразуется в число (т.к. входной параметр — число). Но при этом почему-то не учитывается, в какой системе счисления это число. И это не смотря на то, что входной праметр прав у chmod и mkdir — восьмеричное число, и об этом указывается в документации. И, конечно же, по первому примеру видно, что PHP умеет работать с восьмеричными числами.
Для преобразования числа восьмеричной системы в PHP есть три функции — decoct (из десятичной в восьмеричную), octdec (из восьмеричной в десятичную) и base_convert (из какой-то в какую-то, например из двоичной в восьмеричную). octdec() возвращает действительное число, а вот две другие — decoct и base_convert — почему-то строку. И вот тут я напарываюсь на интересный момент — эти функции нормально отрабатывают, возвращают восьмеричные значения, но, похоже, что передать параметр с их помощью у меня не получится. А все потому, что возвращают они строковое значение, которое при передаче в функцию будет преобразовано в десятичный int, неправильно обработано функцией, и в результате — кривые права доступа к файлу. Получается, что всё равно придется что-то «хардкодить» — либо права доступа, либо команду UNIX-like систем chmod:
`chmod {$permissions} {$pathToFile}`;
И то, и другое — те еще «костыли»: первый не позволит гибко менять права доступа, второй не будет работать, скажем, в Windows. Благо chmod в Windows вообще эффекта не имеет. Побочный плюс второго варианта в том, что можно использовать синтаксис команды chmod, который весьма мощен и позволяет гибко и просто выставлять права доступа на файлы. Минус второго варианта — в платформозависимости кода и возможных при этом проблемах.

Похожие статьи:

Запись опубликована в рубрике php с тэгами , , , , , , , . Создать закладку на запись. Оставить комментарий или trackback: Trackback URL.

2 комментариев

  1. Опубликован 23 марта 2010 в 13:28 | Прямая ссылка

    А если сваять обертку подобного типа:

    function chmodx ($file,$p_user,$p_group,$p_other) {

    $perm = $p_user * 64 + $p_group * 8 + $p_other;

    chmod ($file,$perm);

    }

    И запускать как chmodx ($file,7,7,5)?

  2. Опубликован 23 марта 2010 в 13:46 | Прямая ссылка

    Ilviann Zed, отличный вариант, лучше чем то, что я предлагал))

Оставить комментарий

Ваш e-mail никогда не будет опубликован или передан третьим лицам. Обязательные поля отмечены *

*
*