Provided by: manpages-ja-dev_0.5.0.0.20221215+dfsg-1_all bug

名前

       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:
                _POSIX_C_SOURCE >= 200809L
           Before 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() では、 ファイルは 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  is  NULL, or both tv_nsec values are UTIME_NOW, and the effective user ID of
              the caller does not match the owner of the file, the caller  does  not  have  write
              access  to  the file, and the caller is not privileged (Linux: does not have either
              the CAP_FOWNER or the CAP_DAC_OVERRIDE capability).

       EBADF  (futimens()) fd が有効なファイルディスクリプターでない。

       EBADF  (utimensat()) pathname が相対パスだが、 dirfdAT_FDCWD  でも有効なファイルディス
              クリプターでもない。

       EFAULT times が無効なアドレスを指している。 dirfdAT_FDCWDpathname が NULL か無効な
              アドレスである。

       EINVAL flags に無効な値が指定された。

       EINVAL tv_nsec フィールドの一つが無効な値である (0 から  999,999,999  までの値の範囲外の値
              で、 UTIME_NOW でも UTIME_NOW でもない)。 tv_sec フィールドの一つが無効な値である。

       EINVAL pathname  が NULL で、 dirfdAT_FDCWD ではなく、 flagsAT_SYMLINK_NOFOLLOW が
              指定されている。

       ELOOP  (utimensat()) pathname を解決する際に遭遇したシンボリックリンクが多すぎた。

       ENAMETOOLONG
              (utimensat()) pathname が長すぎる。

       ENOENT (utimensat()) pathname の構成要素が存在するディレクトリかファイルを参照していない。
              pathname が空文字列である。

       ENOTDIR
              (utimensat())  pathname が相対パスだが、 dirfdAT_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 で初めて登場した。

属性

       この節で使用されている用語の説明については、 attributes(7) を参照。

       ┌────────────────────────┬───────────────┬─────────┐
       │インターフェース属性      │
       ├────────────────────────┼───────────────┼─────────┤
       │ utimensat(),           │ Thread safety │ MT-Safe │
       │futimens()              │               │         │
       └────────────────────────┴───────────────┴─────────┘

準拠

       futimens() と utimensat() は POSIX.1-2008 で規定されている。

注意

       utimensat() が登場した結果、 futimesat(2) は非推奨となった。

       Linux では、 変更不可 (immutable) の属性が付いたファイルのタイムスタンプを変更することはで
       きず、 また、 追記のみ (append-only) の属性が付いたファイルで可能な変更は、 タイムスタンプ
       を現在時刻に設定することだけである。 (これは Linux の utime(2) や utimes()  の昔からの動作
       と一貫性がある動作である)。

       両方の  tv_nsec  フィールドに  UTIME_OMIT が指定された場合、 utimensat() の Linux 実装は、
       dirfdpathname が参照するファイルが存在しない場合でも成功する。

   C library/kernel ABI differences
       Linux では、 futimens() は utimensat()  システムコールを使って実装されているライブラリ関数
       である。  これを可能にするため、 Linux の utimensat() システムコールは非標準の機能を実装し
       ている。 pathname が NULL の場合、 呼び出しはファイルディスクリプター dirfd が参照するファ
       イルのタイムスタンプを変更する (ファイルディスクリプターはどのタイプのファイルを参照してい
       てもよい)。 この機能を利用して、 futimens(fd, times) は以下のように実装されている。

            utimensat(fd, NULL, times, 0);

       Note, however, that the glibc wrapper for utimensat()  disallows passing NULL as the value
       for pathname: the wrapper function returns the error EINVAL in this case.

バグ

       カーネル  2.6.26 より前では utimensat() と futimens() にはいくつかの悩ましいバグがあった。
       これらのバグは、 ドラフト版の POSIX.1 規格との不整合や、 以前からの Linux での動作との違い
       である。

       *  POSIX.1  では、  tv_nsec  フィールドの一つが  UTIME_NOWUTIME_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), inode(7),
       path_resolution(7), symlink(7)

この文書について

       この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの
       説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。