てもとツール
ガイド

umaskを引き算で覚えると合わない理由|666と777の差

umask は基準値からの引き算ではありません。ディレクトリでは引き算でも必ず合うのに、ファイルでは 512 通りのうち 64 通りしか合わない、という非対称な事情があります。合う値と合わない値を実数で並べ、桁を見るだけの見分け方までまとめました。

公開読了目安 約5分

この記事の要点

  • umaskは引き算ではなくビットごとの除去
  • ディレクトリは512通り全部で引き算が合う
  • ファイルは512通り中64通りしか合わない
  • 022と002は合う側なので気づけない
  • 奇数の桁が1つでもあればずれる
目次

umask 022 を設定するとファイルは 644 になります。666 − 022 = 644 なので、引き算で覚えている人は多いはずです。

その覚え方は、普段は正しい答えを返します。だから間違っていることに気づく機会がほとんどありません。

引き算の答えが出ても、それは別の数

umask 007 を考えます。引き算なら 666 − 007 で、1 の位は 6 − 7 です。

桁だけ見ると足りませんが、8 進数の引き算は借りられます。0666 − 0007 はきちんと 0657 になります。

umask 077 のときの表示。666 を要求して作られるファイルは 600 rw-------、その下に 666 AND NOT 077 と計算式が出ている

ところが実際に作られるファイルは 660 です。umask は引き算ではなく、基準値から umask のビットを取り除く計算だからです。

6 は 2 進数で 110、7 は 111 です。110 から 111 のビットを取り除くと 000 になり、1 の位は 0 になります。

つまり引き算は「計算できない」のではなく、計算できてしまうのに違う数を返すのが厄介なところです。

よく使う値でも静かにずれる

007 のように大きく外れる値なら、結果を見て気づけるかもしれません。もっと厄介なのは、引き算の答えが正解と 1 桁しか違わない場合です。

umask 023 がその例です。引き算なら 666 − 023 = 643 で、正解の 644 と 1 の位しか違いません。

umask 023 の食い違いの通知。ファイルは引き算だと 643 だが答えは 644 であること、ディレクトリは引き算でも同じ 754 になることが 2 行で並んでいる

1 の位を見ると、引き算は 3(-wx)、正しい答えは 4(r--)です。読みと書きが入れ替わっています。

理由は同じです。6 は 110、3 は 011 で、110 から 011 のビットを取り除くと 100、つまり 4 になります。

桁ごとに独立して起きる

この食い違いは桁ごとに起きます。ある桁だけ引き算と一致して、別の桁だけずれる、ということが普通に起こります。

だから「答えが 3 桁とも大きく違う」とは限りません。1 桁だけ静かに違う結果になります。

ディレクトリでは引き算が必ず合う

もう 1 つ、気づきにくくしている事情があります。ディレクトリの基準値は 777 です。

7 は 3 ビットすべてが立っている数なので、どの値を引いても、ビットを取り除いた結果と一致します。7 − d と 7 からのビット除去は、d が 0 から 7 のどれであっても同じ値になります。

つまり ディレクトリだけを見ているあいだは、引き算の覚え方で一度も間違えません。umask の確認をディレクトリで済ませていると、ずれに出会う機会がありません。

ファイルの基準値は 666 です。1 の位のビットが最初から立っていないので、umask 側にそのビットが混ざった瞬間にずれ始めます。

数えてみると偏りがはっきりする

3 桁の umask は 000 から 777 まで 512 通りあります。ファイル側で引き算がどうなるかを全部数えると、次のようになりました。

引き算の結果通り数内容
そのまま合う643 桁とも 0・2・4・6 のとき
引けるが答えが違う375奇数の桁があり、値が 666 以下のとき
引き算の答えが負になる73umask 自体が 666 より大きいとき

合うのは全体の 1 割ちょっとです。それなのに気づかれないのは、よく使う値がその 1 割に入っているからです。

umask 022 のときの表示。ファイルもディレクトリも引き算でも同じ値になる、と 2 行で出ている

022 は各桁が 0・2・2 で、002 は 0・0・2 です。どちらも 0・2・4・6 だけでできているので、引き算でも答えが合います。

一方 023 は 643、027 は 637、013 は 653 という答えを返します。どれも正解とは違います。

見分け方は「奇数の桁があるか」

覚え方を直すのがいちばんですが、手元で素早く判断したいときの目安は 1 つです。

奇数の桁が 1 つでもあれば、引き算の答えは正解と違います。

逆に言うと、3 桁すべてが 0・2・4・6 の偶数なら引き算でも合います。022 002 066 246 などがこれに当たります。

理由は基準値の 6 にあります。6 は 2 進数で 110 で、1 の位のビットを持っていません。そこから奇数(1 の位が立った数)のビットを引こうとしても、もともと無いものは減りません。

実際の値はchmodパーミッション計算の umask 欄で確かめられます。ファイルとディレクトリの両方について、引き算との食い違いまで並びます。

666 と 777 は「よく使われる要求モード」

もう 1 つ、正確に言っておくことがあります。umask だけで新しいファイルの権限が決まるわけではありません。

決まるのは「作る側のプログラムが要求したモード」から umask のビットを取り除いた値です。666 と 777 は、その要求としてよく使われる値にすぎません。

たとえば cp は元ファイル由来のモードを要求します。600 を要求するプログラムなら、umask が 022 でも結果は 600 のままです。

この記事の数はすべて「666 を要求したファイル」「777 を要求したディレクトリ」の話として読んでください。

設定ファイルに書くときに気をつけること

umask はシェルの設定や systemd のユニットに書かれることがあります。そこに書いた値が意図どおりかは、ファイル側で確かめてください。

ディレクトリ側だけを見て「引き算どおりだから合っている」と判断すると、ファイルの側で 1 桁ずれたまま運用が続きます。

読み方の基本のほうでつまずいているなら、755とrwxr-xr-xを行き来する手順に数字と記号の対応をまとめてあります。

参考にした仕様

umask がファイル作成時のモード生成マスクであることは、The Open Group の仕様書に書かれています。chmod の記号指定で相手を省略したときに同じマスクが効くことも同じ仕様書の定めです。

本文の計算はその定義に沿っています。実装側の確認には Linux の inode(7) も参照しました。

あわせて読みたい

同じテーマ・関連ツールの記事です。