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/ に書かれている。