事象
PHP経由で複数階層にわたるディレクトリを作りたくて以下のようなコマンドを実行する
mkdir('./hoge/huga', 777, true);
しかしこれはエラーになり
以下のように1階層目のディレクトリだけができて終わってしまう。
drwxrwxrwx 3 user group 4096 Oct 10 09:19 .
drwxr-xr-x 7 user group 4096 Oct 10 04:00 ..
dr----x--t 2 user group 4096 Oct 15 08:00 hoge
解決法
(解決法って話でもないんですが)
ディレクトリ権限を指定する場合は4ケタの数字を指定する。
mkdir('./hoge/huga', 0777, true);
解説
777 ではなく 0777 ではないと
権限が 411 になってしまい
しかもユーザー権限が x ではなく t というものができるのか
順を追って説明します。
ディレクトリ権限の t とは
まず t とは何を表現するのか
これはスティッキービットと呼ばれるものだ。
スティッキービット(Sticky Bit)とは、ディレクトリに設定される特殊なアクセス権の事です。
スティッキービット(Sticky Bit)が設定されたディレクトリでは、すべてのユーザーがファイル・ディレクトリを書き込めますが、所有者だけ(rootは除く)しか削除できなくなります。
スティッキービット(Sticky Bit) - 特殊なアクセス権
上記のような特殊なアクセス権のことを指す。
そしてこのスティッキービットを設定する場合は
以下のように chmod を実行する
$ chmod 1777 dir
従来の権限設定に加えて、4ケタ目に1を指定することで
スティッキービットが設定される
PHPの権限変更の設定
PHPの chmod や mkdir の権限設定の引数はint型だが
0777 とか 0755 など、必ず0を指定するように書かれている。
理由としては chmod のリファレンスページに書かれている
自動的には 8 進数と見なされないので注意してください。 意図した操作を行うには、mode の前にゼロ(0)を付ける必要があります
PHP: chmod - Manual
そのため、従来のシェルスクリプトの $ chmod 777 を実現したいような場合は 0777 を指定しないと実現しない。
そのため 777 を指定すると、10進数を指定されたことが想定される、そのため8進数に置き換えた 1411 を指定したことになる。
結果、 1411 の権限を指定したことになるので
スティッキービットが適用された 411 が適応されて
ディレクトリが作られることになる。
余談:mkdirの権限
PHP の mkdir は umask の制限を受ける。
モードを八進数で指定したくなることもあるかもしれません。 その場合は先頭にゼロをつける必要があります。 また、モードは、現在設定されている umask の影響も受けます。 umask を変更するには umask() を使用します。
PHP: mkdir - Manual
umaskとmkdirの関係に関して以下のページがまとまっているので参照のこと。
【PHP】mkdirのパーミッション(属性)の指定が機能しない原因 – ysklog
大概は umask は 0022 が指定されているため
今回は影響なかったが、 1777 等を指定していたら
1755 とかになっていたハズ。
参考
参考URL
- 今さら聞きづらい「ファイルパーミッション」について (フェンリル | デベロッパーズブログ)
- chmod :SUID、GUID、スティッキービットまとめ - Qiita
- データ型
- ファイルの属性情報を探る 権限編 - ザリガニが見ていた...。
検証環境
Ubuntu
PHP 7.0.8