UTIMENSAT(2) | Linux Programmer's Manual | UTIMENSAT(2) |
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():
futimens():
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 が指定するためには)、 以下のいずれかが必要である。
両方のタイムスタンプを現在時刻に設定する以外の変更するには (times が NULL 以外、 または どちらの tv_nsec フィールドも UTIME_NOW でなくどちらの tv_nsec フィールドも UTIME_OMIT でもない場合)、 上記の条件 2 か条件 3 が必要である。
両方の tv_nsec フィールドに UTIME_OMIT が指定された場合、 ファイルの所有権やアクセス許可のチェックは行われず、 ファイルのタイムスタンプは変更されないが、 それ以外のエラー条件はこの場合も検出される。
pathname が相対パスの場合、 デフォルトでは、 オープンしたファイルディスクリプター dirfd が参照するディレクトリに対する相対パスと解釈される (utimes(2) のようにカレントワーキングディレクトリに対する相対パスと解釈されるわけではない)。 なぜこのシステムコールが役に立つのかの説明は openat(2) を参照。
pathname が相対パスで dirfd が特別な値 AT_FDCWD の場合、 pathname は (utimes(2) 同様) 呼び出したプロセスのカレントワーキングディレクトリに対する相対パスと解釈される。
pathname が絶対パスの場合、 dirfd は無視される。
flags フィールドはビットマスクで、 0 か <fcntl.h> で定義されている以下の定数を指定できる。
成功すると、 utimensat() と futimens() は 0 を返す。 エラーの場合、 -1 を返し、 errno にエラーを示す値を設定する。
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 での動作との違いである。
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/ に書かれている。
2015-01-22 | Linux |