- Tumbleweed 20260815-1.1
- Leap-16.0
- Leap-15.6
| utimensat(2) | System Calls Manual | utimensat(2) |
名前¶
utimensat, futimens - ファイルのタイムスタンプをナノ秒精度で変更する
ライブラリ¶
標準 C ライブラリ (libc, -lc)
書式¶
#include <fcntl.h> /* Definition of AT_* constants */ #include <sys/stat.h>
int utimensat(int dirfd, const char *path,
const struct timespec times[_Nullable 2], int flags);
int futimens(int fd, const struct timespec times[_Nullable 2]);
utimensat():
glibc 2.10 から:
_POSIX_C_SOURCE >= 200809L
glibc 2.10 まで:
_ATFILE_SOURCE
futimens():
Since glibc 2.10:
_POSIX_C_SOURCE >= 200809L
Before glibc 2.10:
_GNU_SOURCE
説明¶
utimensat() と futimens() はファイルのタイムスタンプをナノ秒精度で更新します。ファイルのタイムスタンプをセットする際に、昔からある utime(2) と utimes(2) で指定できるのはそれぞれ秒精度とマイクロ秒精度であり、この点が異なります。
utimensat() では、 ファイルは path で渡されるパス名で指定されます。futimens() では、 タイムスタンプを更新するファイルはオープンしたファイルディスクリプタ fd で指定されます。
どちらのシステムコールでも、 ファイルの新しいタイムスタンプは配列 times で指定されます。times[0] は新しい「最終アクセス時刻」 (atime) を指定し、 times[1] は新しい「最終更新時刻」 (mtime) を指定します。 times の各要素では、 時刻を、 紀元 (Epoch; 1970-01-01 00:00:00 +0000 (UTC)) からの秒数とナノ秒として指定します。この情報は timespec(3) 構造体で渡されます。
ファイルの更新後のタイムスタンプは、 指定された時刻を超えないファイルシステムがサポートする最大の値に設定されます。
それぞれの timespec 構造体の tv_nsec フィールドには UTIME_NOW を指定することができ、 その場合はファイルの対応するタイムスタンプは現在時刻に設定されます。 timespec 構造体の tv_nsec フィールドには UTIME_OMIT を指定することができ、 その場合はファイルの対応するタイムスタンプは変更されないままとなります。このどちらの場合も、 対応する tv_sec フィールドの値は無視されます。
times が NULL の場合、 両方のタイムスタンプが現在時刻に設定されます。
ステータス変更時刻 (ctime)は、他のタイムスタンプが実際に変更されない場合でも、現在の時刻に設定されます。
アクセス許可の要件¶
ファイルの両方のタイムスタンプを現在時刻に設定するためには (すなわち times が NULL か、 両方の tv_nsec フィールドに UTIME_NOW が指定するためには)、 以下のいずれかが必要です。
- •
- 呼び出し元がファイルに対する書き込み許可を持っています。
- •
- 呼び出し元の実効ユーザー ID がファイルの所有者と一致しています。
- •
- 呼び出し元が適切な特権を持っています。
両方のタイムスタンプを現在時刻に設定する以外の変更するには (times が NULL 以外、 または どちらの tv_nsec フィールドも UTIME_NOW でなくどちらの tv_nsec フィールドも UTIME_OMIT でもない場合)、 上記の条件 2 か条件 3 が必要です。
両方の tv_nsec フィールドに UTIME_OMIT が指定された場合、 ファイルの所有権やアクセス許可のチェックは行われず、 ファイルのタイムスタンプは変更されませんが、 それ以外のエラー条件はこの場合も検出されます。
utimensat() 固有の内容¶
path が相対パスの場合、既定では、 オープンしたファイルディスクリプター dirfd が参照するディレクトリに対する相対パスと解釈されます (utimes(2) のようにカレントワーキングディレクトリに対する相対パスと解釈されるわけではありません)。なぜこのシステムコールが役に立つのかの説明は openat(2) を参照。
path が相対パスで dirfd が特別な値 AT_FDCWD の場合、 path は (utimes(2) 同様) 呼び出したプロセスのカレントワーキングディレクトリに対する相対パスと解釈されます。
path が絶対パスの場合、 dirfd は無視されます。
flags 引数はビットマスクで、<fcntl.h> で定義される以下の値の 0個以上の OR で生成されます:
- AT_EMPTY_PATH (Linux 5.8 以降)
- path が空の文字列の場合は、 dirfd によって参照されるファイルを操作します(open(2) O_PATH フラグを使用して取得された可能性があります)。この場合、dirfd はディレクトリのみでなく任意のタイプのファイルを参照できます。 dirfd が AT_FDCWD の場合、呼び出しはカレント・ワーキング・ディレクトリを操作します。このフラグは Linux 固有です。 _GNU_SOURCE を定義してその定義を取得してください。
- AT_SYMLINK_NOFOLLOW
- path がシンボリックリンクの場合に、 リンクが参照するファイルではなくリンク自身のタイムスタンプを更新します。
返り値¶
成功すると、 utimensat() と futimens() は 0 を返す。 エラーの場合、 -1 を返し、 errno にエラーを示す値を設定します。
エラー¶
- EACCES
- times がNULLか、 tv_nsec の値が両方とも UTIME_NOW で、呼び出し元の実効ユーザー ID がファイルの所有者と一致せず、呼び出し元にファイルへの書き込みアクセス権がなく、呼び出し元に特権がありません(Linux: CAP_FOWNER も CAP_DAC_OVERRIDE ケーパビリティもない)。
- EBADF
- (futimens()) fd が有効なファイルディスクリプターではありません。
- EBADF
- (utimensat()) path が相対パスだが、 dirfd が AT_FDCWD でも有効なファイルディスクリプターでもありません。
- EFAULT
- times が無効なアドレスを指しています。dirfd が AT_FDCWD で path が NULL か無効なアドレスです。
- EINVAL
- flags に無効な値が指定されました。
- EINVAL
- tv_nsec フィールドの一つが無効な値です (0 から 999,999,999 までの値の範囲外の値で、 UTIME_NOW でも UTIME_NOW でもありません)。 tv_sec フィールドの一つが無効な値です。
- EINVAL
- path が NULL で、 dirfd が AT_FDCWD ではなく、 flags に AT_SYMLINK_NOFOLLOW が指定されています。
- ELOOP
- (utimensat()) path を解決する際に遭遇したシンボリックリンクが多すぎました。
- ENAMETOOLONG
- (utimensat()) path が長すぎます。
- ENOENT
- (utimensat()) path の構成要素が存在するディレクトリかファイルを参照していないか、path が空文字列です。
- ENOTDIR
- (utimensat()) path が相対パスですが、 dirfd が AT_FDCWD でもディレクトリを参照するファイルディスクリプターでもありません。あるいは path の構成要素の接頭辞がディレクトリではありません。
- EPERM
- 呼び出し元がタイムスタンプの一方もしくは両方を現在時刻以外の値に更新しようとしたか、 もしくはタイムスタンプの一方を現在時刻に変更し、もう一方は変更しないままにしようとしました (すなわち times が NULL 以外で、 どちらの tv_nsec フィールドも UTIME_NOW でもなく、 どちらの tv_nsec フィールドも UTIME_OMIT でもない) 場合で、 以下のいずれかにあてはまります。
- •
- 呼び出し元の実効ユーザー ID がファイルの所有者と一致せず、 呼び出し元が特権を持っていません (Linux では、ケーパビリティー CAP_FOWNER を持っていません)。
- •
- ファイルに追記のみか変更不可 (immutable) の属性が付いています (chattr(1) 参照)。
属性¶
この節で使用されている用語の説明については、 attributes(7) を参照してください。
| インターフェース | 属性 | 値 |
| utimensat(), futimens() | Thread safety | MT-Safe |
バージョン¶
C library/kernel ABI differences¶
Linux では、 futimens() は utimensat() システムコールを使って実装されているライブラリ関数です。これを可能にするため、 Linux の utimensat() システムコールは非標準の機能を実装しています。 path が NULL の場合、 呼び出しはファイルディスクリプタ dirfd が参照するファイルのタイムスタンプを変更します (ファイルディスクリプタはどのタイプのファイルを参照していてもよい)。 この機能を利用して、 futimens(fd, times) は以下のように実装されています:
utimensat(fd, NULL, times, 0);
しかし、utimensat() の glibc ラッパは、 path の値として NULL を渡すことを許可していないことに注意。この場合、ラッパはエラー EINVAL を返します。
標準¶
POSIX.1-2024.
履歴¶
- utimensat()
- Linux 2.6.22, glibc 2.6. POSIX.1-2008.
- futimens()
- glibc 2.6. POSIX.1-2008.
注意¶
utimensat() は futimesat(2) を非推奨としています。
Linux では、 変更不可 (immutable) の属性が付いたファイルのタイムスタンプを変更することはできず、また、 追記のみ (append-only) の属性が付いたファイルで可能な変更は、 タイムスタンプを現在時刻に設定することだけです。(これは Linux の utime(2) や utimes() の昔からの動作と一貫性がある動作です)。
両方の tv_nsec フィールドに UTIME_OMIT が指定された場合、 utimensat() の Linux 実装は、 dirfd と path が参照するファイルが存在しない場合でも成功します。
バグ¶
カーネル 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), touch(1), futimesat(2), openat(2), stat(2), utimes(2), futimes(3), timespec(3), inode(7), path_resolution(7), symlink(7)
| 2025-10-29 | Linux man-pages (未リリース) |