Provided by: manpages-ja-dev_0.5.0.0.20210215+dfsg-1_all
名前
utimensat, futimens - ファイルのタイムスタンプをナノ秒精度で変更する
書式
#include <fcntl.h> /* AT_* 定数の定義 */ #include <sys/stat.h> int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags); int futimens(int fd, const struct timespec times[2]); glibc 向けの機能検査マクロの要件 (feature_test_macros(7) 参照): utimensat(): Since glibc 2.10: _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L Before glibc 2.10: _ATFILE_SOURCE futimens(): Since glibc 2.10: _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L Before glibc 2.10: _GNU_SOURCE
説明
utimensat() と futimens() はファイルのタイムスタンプをナノ秒精度で更新する。 ファイルのタ イムスタンプをセットする際に、 昔からある utime(2) と utimes(2) で指定できるのはそれぞれ秒 精度とマイクロ秒精度であり、 この点が異なる点である。 utimensat() では、 ファイルは pathname で渡されるパス名で指定される。 futimens() では、 タ イムスタンプを更新するファイルはオープンしたファイルディスクリプター fd で指定される。 どちらのシステムコールでも、 ファイルの新しいタイムスタンプは配列 times で指定される。 times[0] は新しい「最終アクセス時刻」 (atime) を指定し、 times[1] は新しい「最終修正時刻」 (mtime) を指定する。 times の各要素では、 時刻を、 紀元 (Epoch; 1970-01-01 00:00:00 +0000 (UTC)) からの秒数とナノ秒として指定する。 この情報は以下の形式の構造体で渡す。 struct timespec { time_t tv_sec; /* 秒 */ long tv_nsec; /* ナノ秒 */ }; ファイルの更新後のタイムスタンプは、 指定された時刻を超えないファイルシステムがサポートす る最大の値に設定される。 それぞれの timespec 構造体の tv_nsec フィールドには UTIME_NOW を指定することができ、 その 場合はファイルの対応するタイムスタンプは現在時刻に設定される。 timespec 構造体の tv_nsec フィールドには UTIME_OMIT を指定することができ、 その場合はファイルの対応するタイムスタン プは変更されないままとなる。 このどちらの場合も、 対応する tv_sec フィールドの値は無視され る。 times が NULL の場合、 両方のタイムスタンプが現在時刻に設定される。 アクセス許可の要件 ファイルの両方のタイムスタンプを現在時刻に設定するためには (すなわち times が NULL か、 両 方の tv_nsec フィールドに UTIME_NOW が指定するためには)、 以下のいずれかが必要である。 1. 呼び出し元がファイルに対する書き込み許可を持っている。 2. 呼び出し元の実効ユーザー ID がファイルの所有者と一致している。 3. 呼び出し元が適切な特権を持っている。 両方のタイムスタンプを現在時刻に設定する以外の変更するには (times が NULL 以外、 または ど ちらの tv_nsec フィールドも UTIME_NOW でなくどちらの tv_nsec フィールドも UTIME_OMIT でも ない場合)、 上記の条件 2 か条件 3 が必要である。 両方の tv_nsec フィールドに UTIME_OMIT が指定された場合、 ファイルの所有権やアクセス許可の チェックは行われず、 ファイルのタイムスタンプは変更されないが、 それ以外のエラー条件はこの 場合も検出される。 utimensat() 固有の内容 pathname が相対パスの場合、 デフォルトでは、 オープンしたファイルディスクリプター dirfd が 参照するディレクトリに対する相対パスと解釈される (utimes(2) のようにカレントワーキングディ レクトリに対する相対パスと解釈されるわけではない)。 なぜこのシステムコールが役に立つのかの 説明は openat(2) を参照。 pathname が相対パスで dirfd が特別な値 AT_FDCWD の場合、 pathname は (utimes(2) 同様) 呼び 出したプロセスのカレントワーキングディレクトリに対する相対パスと解釈される。 pathname が絶対パスの場合、 dirfd は無視される。 flags フィールドはビットマスクで、 0 か <fcntl.h> で定義されている以下の定数を指定できる。 AT_SYMLINK_NOFOLLOW pathname がシンボリックリンクの場合に、 リンクが参照するファイルではなくリンク自身 のタイムスタンプを更新する。
返り値
成功すると、 utimensat() と futimens() は 0 を返す。 エラーの場合、 -1 を返し、 errno にエ ラーを示す値を設定する。
エラー
EACCES times が NULL か両方の tv_nsec の値が UTIME_NOW で、 以下のいずれかにあてはまる。 * 呼び出し元の実効ユーザー ID がファイルの所有者と一致せず、 呼び出し元がそのファイ ルに対する書き込みアクセス許可を持っておらず、 呼び出し元が特権を持っていない (Linux では、ケーパビリティー CAP_FOWNER か CAP_DAC_OVERRIDE を持っていない)。 * ファイルが immutable (変更不可) の属性が付いている (chattr(1) 参照)。 EBADF (futimens()) fd が有効なファイルディスクリプターでない。 EBADF (utimensat()) pathname が相対パスだが、 dirfd が AT_FDCWD でも有効なファイルディス クリプターでもない。 EFAULT times が無効なアドレスを指している。 dirfd が AT_FDCWD で pathname が NULL か無効な アドレスである。 EINVAL flags に無効な値が指定された。 EINVAL tv_nsec フィールドの一つが無効な値である (0 から 999,999,999 までの値の範囲外の値 で、 UTIME_NOW でも UTIME_NOW でもない)。 tv_sec フィールドの一つが無効な値である。 EINVAL pathname が NULL で、 dirfd が AT_FDCWD ではなく、 flags に AT_SYMLINK_NOFOLLOW が 指定されている。 ELOOP (utimensat()) pathname を解決する際に遭遇したシンボリックリンクが多すぎた。 ENAMETOOLONG (utimensat()) pathname が長すぎる。 ENOENT (utimensat()) pathname の構成要素が存在するディレクトリかファイルを参照していない。 pathname が空文字列である。 ENOTDIR (utimensat()) pathname が相対パスだが、 dirfd が AT_FDCWD でもディレクトリを参照す るファイルディスクリプターでもない。 pathname の構成要素のディレクトリ部分がディレ クトリではない。 EPERM 呼び出し元がタイムスタンプの一方もしくは両方を現在時刻以外の値に更新しようとした か、 もしくはタイムスタンプの一方を現在時刻に変更し、もう一方は変更しないままにしよ うとした (すなわち times が NULL 以外で、 どちらの tv_nsec フィールドも UTIME_NOW でもなく、 どちらの tv_nsec フィールドも UTIME_OMIT でもない) 場合で、 以下のいずれ かにあてはまる。 * 呼び出し元の実効ユーザー ID がファイルの所有者と一致せず、 呼び出し元が特権を持っ ていない (Linux では、ケーパビリティー CAP_FOWNER を持っていない)。 * ファイルに追記のみか変更不可 (immutable) の属性が付いている (chattr(1) 参照)。 EROFS ファイルが読み込み専用のファイルシステム上にある。 ESRCH (utimensat()) pathname の構成要素のディレクトリ部分のいずれかで検索許可がなかった。
バージョン
utimensat() はカーネル 2.6.22 で Linux に追加された。 glibc のサポートはバージョン 2.6 で 追加された。 futimens() のサポートは glibc 2.6 で初めて登場した。
準拠
futimens() と utimensat() は POSIX.1-2008 で規定されている。
注意
utimensat() が登場した結果、 futimesat(2) は非推奨となった。 Linux では、 変更不可 (immutable) の属性が付いたファイルのタイムスタンプを変更することはで きず、 また、 追記のみ (append-only) の属性が付いたファイルで可能な変更は、 タイムスタンプ を現在時刻に設定することだけである。 (これは Linux の utime(2) や utimes() の昔からの動作 と一貫性がある動作である)。 Linux では、 futimens() は utimensat() システムコールを使って実装されているライブラリ関数 である。 これを可能にするため、 Linux の utimensat() システムコールは非標準の機能を実装し ている。 pathname が NULL の場合、 呼び出しはファイルディスクリプター dirfd が参照するファ イルのタイムスタンプを変更する (ファイルディスクリプターはどのタイプのファイルを参照してい てもよい)。 この機能を利用して、 futimens(fd, times) は以下のように実装されている。 utimensat(fd, NULL, times, 0); 両方の tv_nsec フィールドに UTIME_OMIT が指定された場合、 utimensat() の Linux 実装は、 dirfd と pathname が参照するファイルが存在しない場合でも成功する。
バグ
カーネル 2.6.26 より前では utimensat() と futimens() にはいくつかの悩ましいバグがあった。 これらのバグは、 ドラフト版の POSIX.1 規格との不整合や、 以前からの Linux での動作との違い である。 * POSIX.1 では、 tv_nsec フィールドの一つが UTIME_NOW か UTIME_OMIT の場合、 対応する tv_sec フィールドは無視されると規定されている。 しかし、 tv_sec フィールドの値を 0 にす る必要があった (さもなければエラー EINVAL となった)。 * いくつかのバグのため、 アクセス許可のチェックにおいて、両方の tv_nsec フィールドが UTIME_NOW に設定された場合が、 常に times に NULL が設定された場合と同じに扱われるわけで はなく、 tv_nsec の一つが UTIME_NOW でもう一方が UTIME_OMIT の場合が、 times に任意の値 が入った構造体の配列へのポインターが指定された場合と 同じように扱われるわけではない。 そ の結果、いくつかの場合では、 a) ファイルのタイムスタンプが、 更新を実行する許可を持たな いプロセスによって更新されることがある、 b) ファイルのタンプスタンプが、 更新を実行する 許可を持つプロセスによって更新できないことがある、 c) エラーの場合に間違った errno 値が 返る。 * POSIX.1 では、 ファイルの書き込み許可を持つプロセス (a process that has write access to the file) は、そのファイルに対して times に NULL や 両方の tv_nsec フィールドが UTIME_NOW の構造体の配列を指定して呼び出しを行い、 両方のタイムスタンプを現在時刻に更新 することができると規定されている。 しかし、 futimens() では、 ファイルディスクリプターの アクセス許可が書き込みを許可しているか (access mode of the file descriptor allows writing)のチェックが行われる。
関連項目
chattr(1), futimesat(2), openat(2), stat(2), utimes(2), futimes(3), path_resolution(7), symlink(7)
この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.79 の一部 である。プロジェクト の説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。