概述
#include <sys/stat.h>
int futimens(int fd, const struct timespec times[2]);
int utimensat(int fd, const char *path, const struct timespec times[2], int flag);
两个函数返回值:若成功,返回0;若出错,返回-1
(1)如果times参数是一个空指针,则访问时间和修改时间两者都设置为当前时间。
以一个图片为例,在/home/zhihui/Pictures 路径下有一个文件:book.jpg
现将修改时间mtime,访问时间atime,i节点更改时间ctime 输出如下:
现修改这个文件的访问时间和修改时间
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
int main() {
struct timespec time[2];
int fd;
fd = open("/home/zhihui/Pictures/book.jpg",O_RDONLY);
if(fd == -1){
printf("open file failed.n");
}
else{
if(-1 == futimens(fd,NULL)){
printf("modify time failed.n");
}
else{
printf("modify time cucceed.n");
}
}
return 0;
}
由下图可见,当times参数空指针时,文件的访问时间,修改时间(包括i节点修改时间)都变为Nov 1 11:18
(2)如果times参数指向两个timespec结构的数组,任一数组元素的tv_nsec字段的值为UTIME_NOW,相应的时间戳就设置为当前时间,忽略相应的tv_sec字段。
代码如下,我们仅将time[0]的tv_nsec设置为UTIME_NOW 其他成员采用系统默认值。
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
int main() {
struct timespec time[2];
time[0].tv_nsec = UTIME_NOW;
int fd;
fd = open("/home/zhihui/Pictures/book.jpg",O_RDONLY);
if(fd == -1){
printf("open file failed.n");
}
else{
if(-1 == futimens(fd,time)){
printf("modify time failed.n");
}
else{
printf("modify time cucceed.n");
}
}
return 0;
}
运行后结果如下:
$ ls -al | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Feb 18 1970 book.jpg
$ ls -al --time=atime | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Nov 1 11:36 book.jpg
$ ls -al --time=ctime | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Nov 1 11:36 book.jpg
值得注意的一点是,文件的修改时间(mtime)变为了Feb 18 1970
只有atime和ctime变为了当前时间。
我们对上面的代码稍作修改
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
int main() {
struct timespec time[2];
time[0].tv_nsec = UTIME_NOW;
time[1].tv_nsec = UTIME_NOW;
int fd;
fd = open("/home/zhihui/Pictures/book.jpg",O_RDONLY);
if(fd == -1){
printf("open file failed.n");
}
else{
if(-1 == futimens(fd,time)){
printf("modify time failed.n");
}
else{
printf("modify time cucceed.n");
}
}
return 0;
}
增加了
time[1].tv_nsec = UTIME_NOW;
因为第一个time的第一个元素包含访问时间,第二个元素包含修改时间。将两个时间都设置为UTIME_NOW
运行结果如下
$ ls -al | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Nov 1 11:41 book.jpg
$ ls -al --time=atime | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Nov 1 11:41 book.jpg
$ ls -al --time=ctime | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Nov 1 11:41 book.jpg
可以看到,文件的mtime 也变成了当前时间。
再做一点修改,将time[0].tv_nsec = UTIME_NOW;这一行注释
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
int main() {
struct timespec time[2];
// time[0].tv_nsec = UTIME_NOW;
time[1].tv_nsec = UTIME_NOW;
int fd;
fd = open("/home/zhihui/Pictures/book.jpg",O_RDONLY);
if(fd == -1){
printf("open file failed.n");
}
else{
if(-1 == futimens(fd,time)){
printf("modify time failed.n");
}
else{
printf("modify time cucceed.n");
}
}
return 0;
}
运行结果如下
$ ls -al | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Nov 1 11:46 book.jpg
$ ls -al --time=atime | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Dec 6 4461538 book.jpg
$ ls -al --time=ctime | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Nov 1 11:46 book.jpg
值得注意的是,atime 变成了Dec 6 4461538,由于访问时间未定义,因此呈现出来的时间格式也不正常。
现在再回过头来看这句话:如果times参数指向两个timespec结构的数组,任一数组元素的tv_nsec字段的值为UTIME_NOW,相应的时间戳就设置为当前时间,忽略相应的tv_sec字段。
也就是说,只将第一个数组元素的tv_nsec置为UTIME_NOW,则对应的访问时间就变成当前时间,只将第二个数组元素的tv_nsec置为UTIME_NOW,则对应的修改时间就变成当前时间。但是无论是那个元素的tv_nsec置为UTIME_NOW,文件的ctime即i节点修改时间都会变为当前时间。
(3)如果times参数指向两个timespec结构的数组,任一数组元素的tv_nsec字段的值为UTIME_OMIT,相应的时间戳保持不变,忽略相应的tv_sec字段。
我们读取文件a的访问时间和修改时间,并将这个时间存储到time结构体中.然后将文件b的时间状态设为当前时间,再用time结构体中保存的时间去设置文件b的访问时间和修改时间并将time结构体数组其中一个元素的tv_nsec设置为UTIME_OMIT。比如,在目录/home/zhihui/Pictures 下有文件 container.odg ,我们先从命令行查询这个文件的时间信息,得到如下信息:
$ ls -al | grep container.odg
-rw-rw-r-- 1 zhihui zhihui 269171 Sep 12 09:24 container.odg
$ ls -al --time=ctime | grep container.odg
-rw-rw-r-- 1 zhihui zhihui 269171 Sep 12 09:24 container.odg
$ ls -al --time=atime -h | grep container.odg
-rw-rw-r-- 1 zhihui zhihui 263K Sep 12 09:24 container.odg
编写如下代码
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
struct timespec time[2];
struct stat buf[10];
int fd;
fd = open("/home/zhihui/Pictures/container.odg",O_RDONLY);
fstat(fd,buf);
close(fd);
time[0] = buf[0].st_atim;
time[1] = buf[0].st_mtim;
time[1].tv_nsec = UTIME_OMIT;
fd = open("/home/zhihui/Pictures/book.jpg",O_RDONLY);
if(fd == -1){
printf("open file failed.n");
}
else{
if(-1 == futimens(fd,NULL)){ //设为当前时间
printf("modify time failed.n");
}
else{
printf("modify time cucceed.n");
}
if(-1 == futimens(fd,time)){
printf("modify time failed.n");
}
else{
printf("modify time cucceed.n");
}
}
close(fd);
return 0;
}
执行结果如下:
$ ls -al | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Nov 1 18:19 book.jpg
$ ls -al --time=ctime | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Nov 1 18:19 book.jpg
$ ls -al --time=atime | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Sep 12 09:24 book.jpg
我们将time0设置为了和container.odg的访问时间时间 Sep 12 09:24 ,time[0]改变的是文件的访问时间,所以我们看到atime 变为了Sep 12 09:24。另一方面time[1]的tv_nsec被设置为UTIME_OMIT,因此time[1]的tv_sec总的数据被忽略,因而文件的修改时间依然是当前时间。
(4)如果 times 参数指向两个 timespec 结构的数组,且 tv_nsec 字段的值为既不是UTIME_NOW 也不是 UTIME_OMIT,在这种情
况下,相应的时间戳设置为相应的 tv_sec 和tv_nsec字段的值。
我们使用和上面相同的方法。查询文件a的访问时间和修改时间,并将这个时间存储到time结构体中.然后将文件b的时间状态设为当前时间,再用time结构体中保存的时间去设置文件b的访问时间和修改时间
编写如下代码:
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
struct timespec time[2];
struct stat buf[10];
int fd;
fd = open("/home/zhihui/Pictures/container.odg",O_RDONLY);
fstat(fd,buf);
close(fd);
time[0] = buf[0].st_atim;
time[1] = buf[0].st_mtim;
fd = open("/home/zhihui/Pictures/book.jpg",O_RDONLY);
if(fd == -1){
printf("open file failed.n");
}
else{
if(-1 == futimens(fd,NULL)){ //设为当前时间
printf("modify time failed.n");
}
else{
printf("modify time cucceed.n");
}
if(-1 == futimens(fd,time)){
printf("modify time failed.n");
}
else{
printf("modify time cucceed.n");
}
}
close(fd);
return 0;
}
$ ls -al | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Sep 12 09:24 book.jpg
$ ls -al --time=ctime | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Nov 1 18:36 book.jpg
$ ls -al --time=atime | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Sep 12 09:24 book.jpg
可以看到文件的读取时间和修改时间都已经改变。
utimes函数对路径名进行操作。times参数是指向包含两个时间戳(访问时间和修改时间)元素的数组的指针,两个时间戳是用秒和微妙表示的。
struct timeval {
time_t tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
编写如下代码,将文件读取时间设置为1970年1月3号,文件修改时间设置为1970年1月4号:
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
int main() {
struct timeval time[2];
time[0].tv_sec = 2 * 24*60*60 + 26 * 60;
time[0].tv_usec = 0;
time[1].tv_sec = 3 * 24*60*60 + 44 * 60;
time[1].tv_usec = 0;
if(-1 == utimes("/home/zhihui/Pictures/book.jpg",time)){
printf("modify time failed.n");
}
else{
printf("modify time cucceed.n");
}
return 0;
}
运行结果如下:
$ ls -al | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Jan 4 1970 book.jpg
$ ls -al --time=ctime | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Nov 1 19:40 book.jpg
$ ls -al --time=atime | grep book
-rw-rw-r-- 1 zhihui zhihui 26786 Jan 3 1970 book.jpg
最后
以上就是怕黑百合为你收集整理的修改文件时间信息的函数futimens、utimensat和utimes的全部内容,希望文章能够帮你解决修改文件时间信息的函数futimens、utimensat和utimes所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复