UTIMENSAT - Linux手册页

时间:2019-08-20 17:59:36  来源:igfitidea点击:

Linux程序员手册 第2部分
更新日期: 2020-06-09

名称

utimensat,futimens-以纳秒级精度更改文件时间戳

语法

#include <fcntl.h>           /* Definition of AT_* constants */
#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()可以通过路径名中指定的路径名​​指定文件。使用futimens(),可以通过打开的文件描述符fd指定要更新其时间戳的文件。

对于这两个调用,新文件的时间戳记均在数组时间中指定:times [0]指定新的"上次访问时间"(atime); times [1]指定新的"上次修改时间"(mtime)。时间的每个元素都将时间指定为自1970年1月1日00:00:00 +0000(UTC)以来的秒数和纳秒数。此信息以以下形式的结构传递:

struct timespec {
    time_t tv_sec;        /* seconds */
    long   tv_nsec;       /* nanoseconds */
};

更新的文件时间戳记设置为文件系统支持的最大值,该最大值不大于指定的时间。

如果时间规范结构之一的tv_nsec字段具有特殊值UTIME_NOW,则将相应的文件时间戳记设置为当前时间。如果时间规范结构之一的tv_nsec字段具有特殊值UTIME_OMIT,则相应的文件时间戳保持不变。在这两种情况下,都会忽略相应的tv_sec字段的值。

如果times为NULL,则两个时间戳都设置为当前时间。

Permissions requirements

要将两个文件时间戳都设置为当前时间(即,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() specifics

如果路径名是相对的,则默认情况下它是相对于打开文件描述符dirfd所引用的目录解释的(而不是相对于调用进程的当前工作目录,如utimes(2)对相对路径名所做的那样) )。请参阅openat(2),以获取有关为什么这样做有用的解释。

如果路径名是相对的并且dirfd是特殊值AT_FDCWD,则路径名将相对于调用进程的当前工作目录进行解释(如utimes(2))。

如果路径名是绝对的,则dirfd被忽略。

标志字段是一个位掩码,可以为0,或包含以下常量,定义如下:

AT_SYMLINK_NOFOLLOW
如果路径名指定了符号链接,则更新该链接的时间戳,而不是它所引用的文件。

返回值

成功时,utimensat()和futimens()返回0。错误时,返回-1并设置errno以指示错误。

错误说明

EACCES
times为NULL或两个tv_nsec值均为UTIME_NOW,并且调用者的有效用户ID与文件的所有者不匹配,调用者没有对该文件的写访问权,并且该调用者没有特权(Linux:没有)具有CAP_FOWNER或CAP_DAC_OVERRIDE功能)。
EBADF
(futimens())fd不是有效的文件描述符。
EBADF
(utimensat())路径名是相对路径名,但dirfd既不是AT_FDCWD也不是有效的文件描述符。
EFAULT
指向无效地址的时间;或者,dirfd是AT_FDCWD,并且路径名是NULL或无效的地址。
EINVAL
标志中的值无效。
EINVAL
tv_nsec字段之一中的值无效(值在0到999,999,999范围之外,并且不是UTIME_NOW或UTIME_OMIT);或tv_sec字段之一中的值无效。
EINVAL
路径名是NULL,dirfd不是AT_FDCWD,并且标志包含AT_SYMLINK_NOFOLLOW。
ELOOP
(utimensat())解析路径名时遇到太多符号链接。
ENAMETOOLONG
(utimensat())路径名太长。
ENOENT
(utimensat())路径名的组件未引用现有目录或文件,或者路径名是空字符串。
ENOTDIR
(utimensat())路径名是相对路径名,但dirfd既不是AT_FDCWD也不是引用目录的文件描述符;或者,路径名的前缀组成部分之一不是目录。
EPERM
The caller attempted to change one or both timestamps to a value other than the current time, or to change one of the timestamps to the current time while leaving the other timestamp unchanged, (i.e., times

is not NULL, neither
tv_nsec

field is
UTIME_NOW,

and neither
tv_nsec

field is
UTIME_OMIT)

and either:

*
调用者的有效用户ID与文件的所有者不匹配,并且调用者没有特权(Linux:不具有CAP_FOWNER功能);要么,
*
该文件被标记为仅追加或不可变(请参见chattr(1))。
EROFS
该文件位于只读文件系统上。
ESRCH
(utimensat())拒绝对路径名的前缀组件之一进行搜索。

版本

utimensat()在内核2.6.22中添加到Linux; glibc支持是在2.6版中添加的。

futimens()的支持最早出现在glibc 2.6中。

属性

有关本节中使用的术语的说明,请参见attribute(7)。

InterfaceAttributeValue
utimensat(),futimens()Thread safetyMT-Safe

遵循规范

futimens()和utimensat()在POSIX.1-2008中指定。

备注

utimensat()已过时futimesat(2)。

在Linux上,不能更改标记为不可变的文件的时间戳,标记为append-only的文件唯一允许的更改是将时间戳设置为当前时间。 (这与utime(2)和utimes(2)在Linux上的历史行为一致。)

如果将两个tv_nsec字段都指定为UTIME_OMIT,则即使dirfd和路径名引用的文件不存在,utimensat()的Linux实现也会成功。

C library/kernel ABI differences

在Linux上,futimens()是在utimensat()系统调用之上实现的库函数。为此,Linux utimensat()系统调用实现了非标准功能:如果路径名为NULL,则该调用将修改文件描述符dirfd引用的文件的时间戳(该文件描述符可以引用任何类型的文件)。使用此功能,调用futimens(fd,times)实现为:

utimensat(fd, NULL, times, 0);

但是请注意,用于utimensat()的glibc包装器不允许传递NULL作为路径名的值:在这种情况下,包装器函数返回错误EINVAL。

BUGS

在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的情况并不总是与将时间指定为NULL的情况相同,而一个tv_nsec值为UTIME_NOW且另一个值为UTIME_OMIT的情况则不是"与将时间指定为指向包含任意时间值的结构数组的指针一样。结果,在某些情况下:a)文件时间戳可以由不具有执行更新权限的进程来更新; b)文件时间戳不能由具有执行更新权限的进程更新; c)发生错误时返回错误的errno值。
*
POSIX.1说,具有对文件写访问权限的进程可以使用NULL或带有指向两个tv_nsec字段均为UTIME_NOW的结构数组的时间进行调用,以便将两个时间戳都更新为当前时间。 。但是,futimens()会检查文件描述符的访问模式是否允许写入。

另外参见

chattr(1),touch(1),futimesat(2),openat(2),stat(2),utimes(2),futimes(3),inode(7),path_resolution(7),symlink(7)

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/