mkdirでディレクトリに「0777」が設定できない場合の解決法

PHPプログラムを使用して誰でも読み書きできるディレクトリを作成したい場合に以下のようにmkdirコマンドとchmodコマンドを組み合わせて使用します。

$path = "/mydir/";
mkdir($path, 0777, true);  //この行の「0777」は何でも良い
chmod($path, 0777);

2行目のmkdirコマンドで0777にならない理由として、umaskが「022」のように事前に設定されていることがあります。 設定されていた場合は「0777」が「022」にマスクされてしまい、「0755」になってしまいます。

mkdir:0777 ↓この方向にマスクされます。
umask: 022
-----------------
結果:0755 ←マスク値(022)によって最終的にこの値になる。

そのため、次の行のchmod関数で明示的に0777に変更する必要があるわけです。

このマスク値は作成される全てのディレクトリに適用されることを覚えておきましょう。

umask値を調べるには、umask()を引数なしで実行し、返り値を見てみましょう。

サブディレクトリを含めてmkdirすると…

サブディレクトリまで含めて全てを0777に設定したい場合は少々複雑になります。 というのも、例えば作成したいディレクトリが「/2012/03/22/」のように複数の階層になっている場合を想定してみましょう。

$path = "/2012/03/22/";
mkdir($path, 0777, true);
chmod($path, 0777);

このようにしても、chmodは「22」という末端のディレクトリにしか適用されないため、途中の「2012」や「03」ディレクトリはumaskのマスク値を通した「0755」が設定されてしまうのです。

ディレクトリ名 2012/ 03/ 22/
適用される要素 設定値&umask 設定値&umask chmod
適用される値 0755 0755 0777

umask()を使ってマスクを一時的に無効にして解決

途中の「2012」「03」ディレクトリも含めて「0777」に設定したい場合は、umask関数を使ってマスクを一時的になくしてしまう方法が有効です。

PHPマニュアルのumaskの説明にありますが、マルチスレッドな Web サーバでこの関数を使用することは避けてください。

$path = "/2012/03/22/";
$mask = umask();  //事前のマスク値を退避
umask(000);  //マスクを無効にする
mkdir($path, 0777, true); //マスクが無効になっているので全てのディレクトリが0777になる
umask($mask);  //マスク値をもとに戻す

こうしてマスク値をなくしたわけですね。

mkdir:0777 ↓この方向にマスクされます。
umask: 000
-----------------
結果:0777 ←マスク値がなくなったので全てに「0777」が適用される

お役に立ちましたでしょうか?

このページをシェアする

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

2012-03-20