MKTEMP(3)

名称
mktemp - 一意な一時ファイル名を作成

ライブラリ
libc

書式
<unistd.h> char * mktemp(char *template) int mkstemp(char *template) int mkstemps(char *template, int suffixlen) char * mkdtemp(char *template)

解説
mktemp() 関数は、与えられたファイル名テンプレートの一部を書き換えて ファイル名を作成します。 このファイル名は、関数が呼ばれた時に存在していないことが保証されており、 アプリケーションでの使用に適しています。 テンプレートとしては、 /tmp/temp.XXXXXX のように、任意のファイル名に数桁の文字 ‘X’ が付いているものが使用されます。 後ろに続く ‘X’ は、英数字の一意の組合せに置き換えられます。 mktemp() が戻す一意的なファイル名の数は、 ‘X’ の数によって決まります。 ‘X’ が 6 桁である場合、56800235584 (62 ** 6) 通りの可能な一時ファイル名から mktemp() によって一つ選ばれます。

mkstemp() 関数は、テンプレートを同じように置き換え、 モード 0600 でテンプレートファイルを作成し、 読み書き用としてオープンしたファイル記述子を返します。 こうすることにより、ファイルの存在を確認することと 使用するためにオープンすることとの間の競合状態を避けられます。

mkstemps() は、テンプレートにサフィックスを含めることができることを除いて mkstemp() と同様に動作します。 テンプレートは、 /tmp/tmpXXXXXXsuffix という形式である必要があります。 mkstemps() は、サフィックス文字列の長さを必要とします。

mkdtemp() 関数は、テンプレートを mktemp(3) と同じように置き換え、 モード 0700 でテンプレートディレクトリを作成します。

戻り値
成功した場合、 mktemp() 関数と mkdtemp() 関数は、テンプレートへのポインタを返し、失敗した場合 NULL を返します。 mkstemp() 関数と mkstemps() 関数は、適切なファイルを作成できない場合に -1 を返します。 どの関数呼出しでもエラーが発生すると、エラーコードがグローバル変数 errno に書き込まれます。

エラー
mkstemp(), mkstemps(), mkdtemp() 関数は、以下の値のうち 1 つを errno に設定します。

[ENOTDIR]
    テンプレートのパス名部分が、存在するディレクトリではありません。

mkstemp(), mkstemps(), mkdtemp() 関数は、 stat(2) 関数で規定されるどの値も errno に設定する可能性があります。

mkstemp() 関数と mkstemps() 関数は、 open(2) 関数で規定されるどの値も errno に設定する可能性があります。

mkdtemp() 関数は、 mkdir(2) 関数で規定されるどの値も errno に設定する可能性があります。

注
コアダンプを引き起こす問題としてよくあるものは、プログラマが、 mktemp(), mkstemp(), mkstemps(), mkdtemp() に読込み専用文字列を渡しているものです。 この問題は、 isoC コンパイラが普及する前に開発されたプログラムで多く見られます。 たとえば引数 "/tmp/tempfile.XXXXXX" を指定して mkstemp() を呼び出すと、 mkstemp() が、指定された文字列定数を書き換えようとしてコアダンプが起こります。 問題を起こすプログラムが、このような関数呼出しを頻繁に行っている場合は、 メモリの書込み可能セグメントへ文字列定数を 保持するようにプログラムをコンパイルすることもできます。 詳細については、 gcc(1) を参照してください。

バグ
この関数群は推測可能なファイル名を生成しますが、 ‘X’ の数を多くし作成可能な一時ファイル名の数を増やすことで、 推測される危険を最小化します。 mktemp() では、あるファイルが存在するかのテスト ( mktemp() 関数呼び出しの中) と、そのファイルを使用するためのオープン (その後のユーザアプリケーションの中) との間で競合が発生し、 これはセキュリティの面から見て、とても危険です。 mkstemp() には競合状態がありませんので、 可能な限り、この関数を使うべきでしょう。 もし mkstemp() が使用できない場合は、 mktemp() で生成されたファイル名を open(2) で開く時に O_EXCL フラグをつけるようにし、 失敗していないか戻り値をテストすべきでしょう。 こうすることによって、攻撃者がファイルの内容を操作したり 読んだりする意図を持ってファイルを既に作成していても、 プログラムが無闇に動作を継続することがなくなります。

関連項目
chmod(2), getpid(2), mkdir(2), open(2), stat(2)

歴史
mktemp() 関数は、 AT&T UNIX で登場しました。 mkstemp() 関数は、 4.4BSD で登場しました。 mkdtemp() 関数は、 OpenBSD 2.2 ではじめて登場し、その後 FreeBSD 3.2 で登場しました。 mkstemps() は OpenBSD 2.4 ではじめて登場し、その後 FreeBSD 3.4 で登場しました。