一系列用于改变文件访问时间( access )和修改时间( modification )的系统调用
futimens, utimensat - change file timestamps with nanosecond precision
futimens, utimensat 提供纳秒尺寸,通过使用timespec结构体。
#include <fcntl.h> /* Definition of AT_* constants */
#include <sys/stat.h>
int futimens(int fd, const struct timespec times[2]);
int utimensat(int dirfd, const char *pathname,
const struct timespec times[2], int flags);
//Return: 0 if OK, -1 on error
结构体:timespec
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
futimens
times[0]存放的access time,times[1]存放modification time.这两个时间是日历时间(calendar time)。
timestamps(时间戳)可以用下面4种方法来指定:
1. times是NULL指针。这样timestamps被设置为当前时间。
2. times为timespec结构体数组。如果tv_nsec field为特殊值UTIME_NOW,相应的timestamp被设定为当前时间。相应的tv_secfield被忽略。
3. times为timespec结构体数组。如果tv_nsec field为特殊值UTIME_OMIT,相应的timestamp不改变。相应的tv_secfield被忽略。
4. times为timespec结构体数组。如果tv_nsec field为UTIME_OMIT和UTIME_NOW以外的值,timestamp相应地被设置为tv_sec和tv_nsec field的值。
需要执行这些系统调用的权限由times 参数决定:
- If
timesis a null pointer or if eithertv_nsec fieldis set toUTIME_NOW, either the effective user ID of the process must equal the owner ID of the file, the process must have write permission for the file, or the process must be a superuser process. - If
timesis a non-null pointer and eithertv_nsec fieldhas a value other thanUTIME_NOWorUTIME_OMIT, the effective user ID of the process must equal the owner ID of the file, or the process must be a superuser process. Merely having write permission for the file is not adequate(仅仅有文件的write权限是不够的). - If
timesis a non-null pointer and bothtv_nsec fieldsare set toUTIME_OMIT, no permissions checks are performed.
With futimens, you need to open the file to change its times.
utimensat
The utimensat function provides a way to change a file’s times using the file’s name. The pathname argument is evaluated relative to the dirfd argument, which is either a file descriptor of an open directory or the special value AT_FDCWDto force evaluation relative to the current directory of the calling process. If pathname specifies an absolute pathname(绝对路径), then the dirfd argument is ignored.
The flag argument to utimensat can be used to further modify the default behavior. If the AT_SYMLINK_NOFOLLOW flag is set, then the times of the symbolic link itself are changed (if the pathname refers to a symbolic link). The default behavior is to follow a symbolic link and modify the times of the file to which the link refers.
Both futimens and utimensat are included in POSIX.1.(如上介绍到两种系统调用都是包含在POSIX1规范中的)
utime, utimes - change file last access and modification times
#include <sys/types.h>
#include <utime.h>
int utime(const char *filename, const struct utimbuf *times);
#include <sys/time.h>
int utimes(const char *filename, const struct timeval times[2]);
//Return 0 if OK, -1 on error
需要注意的是这两个函数修改的是秒和毫秒(ms)不是纳秒
struct timeval {
time_t tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
我们发现,changed-status time,st_ctim—inode最后修改的时间,我们是无法指定其值的,该值会在调用utime的时候自动更新。
在一些Unix版本的命令中,touch使用了这些系统调用之一。此外tar、cpio等标准archive存档程序中也使用了这些系统调用来设置文件时间。
Example
使用open的O_TRUNC截断文件长度到0,但是不改变他们的access time或者modification time.为了达到这一目的,我们先用stat获取时间,然后截断文件,最后使用futimens来重置(reset)时间
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int fd;
struct stat timebuf;
struct timespec times[2];
/*先确定命令行参数合法性*/
if(argc != 2)
{
fprintf(stderr, "usage: a.out <file pathname>\n");
exit(-1);
}
/*获取文件截断前数据*/
if(stat(argv[1], &timebuf) != 0)
{
fprintf(stderr, "stat error!\n");
exit(-1);
}
/*用open截短文件*/
if((fd = open(argv[1], O_TRUNC)) < 0)
{
fprintf(stderr, "open error: %s\n", strerror(errno));
exit(-1);
}
times[0] = timebuf.st_atim;
times[1] = timebuf.st_mtim;
/*设置文件时间与截断前一致*/
if(futimens(fd, times) != 0)
{
fprintf(stderr, "futimens error: %s\n", strerror(errno));
exit(-1);
}
close(fd);
return 0;
}
验证:
$ls -l file
$./a.out file
$ls -l `check time`
$ls -lu `check last-access time`
$ls -lc `check changed-status time`
你会发现last-modification和last-access时间都没有改变,但是changed-status times已经被更改到程序运行的时间
文件时间戳调整
本文介绍了futimens和utimensat两个系统调用,用于精确到纳秒级别改变文件的访问时间和修改时间。同时展示了如何使用这些函数保持文件的时间戳不变,并提供了一个具体的代码示例。
712

被折叠的 条评论
为什么被折叠?



