用C语言实现linux 下 touch 命令的操作:
touch:创建文件或者修改文件或目录的时间戳。
实现效果:
可添加三个参数:
-c : --no-create do not create any files 不创建不存在的文件
-a : change only the access time 只修改文件的访问时间
-m : change only the modification time 只修改文件的修改时间
涉及的函数:
1.getopt()函数:解析命令行参数
/*函数原型*/
#include <unistd.h>
int getopt(int argc, char * const argv[], const char *optstring);
extern char *optarg;
extern int optind, // 初始化值为1,下一次调用getopt时,从optind存储的位置重新开始检查选项。
extern int opterr, // 初始化值为1,当opterr=0时,getopt不向stderr输出错误信息。
extern int optopt; /*当命令行选项字符不包括在optstring中或者选项缺少必
要的参数时,该选项存储在optopt中, getopt返回'?’。*/
2.open()
int open(constchar*pathname, int flags);
int open(constchar*pathname, int flags, mode_t mode);
作用:打开和创建文件。返回值:成功则返回文件描述符,否则返回 -1。
3.utimensat()
#include <sys/stat.h>
int utimensat(int dirfd, const char *pathname,const struct timespec times[2], intflags);
作用:utimensat
是以纳秒级的精度改变文件的时间戳。utimensat()
通过文件的路径(pathname
)获得文件。
这个系统调用函数都是通过一个时间数组 times
来改变时间戳的,times[0]
修改最后一次访问的时间(access time),times[1]
修改最后修改的时间 (modify time)。该时间数组是由秒和纳秒两个部分组成,数据结构如下:
struct timespec {
time_t tv_sec; /* 秒 */
long tv_nsec; /* 纳秒 */
};
当 times[x].tv_sec = UTIME_OMIT;
相应的时间戳不变,times[x].tv_sec = UTIME_NOW;
相应的时间戳变成当前时间
#include<fcntl.h>
#include<sys/stat.h>
#include<stdio.h>
#include<getopt.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdbool.h>
#include<sys/time.h>
#include<time.h>
#define CH_ATIME 1
#define CH_MTIME 2
/*定义创建文件时的模式,此处对用户,组,其他设置的权限都是可读可写的*/
#define MODE_RW_UGO (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
static int change_times;//标志文件access time和modify time 的改变情况
static bool no_creat; //如果有(-c) 选项,并且不存在命令行中输入的文件名,则不创建
static struct timespec newtime[2];//当设置新的access time 和 modify time 的时候使用
static bool mytouch(const char *file)
{
bool ok;
int fd = -1;
if(!no_creat) //如果没有加-c,则在文件不存在的时候创建一个新文件
{
fd = open(file,O_CREAT | O_WRONLY,MODE_RW_UGO);
}
if(change_times != (CH_ATIME | CH_MTIME))
{
if(change_times == CH_MTIME)
{
newtime[0].tv_nsec = UTIME_OMIT;
}
else
{
newtime[1].tv_nsec = UTIME_OMIT;
}
}
ok = (utimensat(AT_FDCWD,file,newtime,0) == 0);
return false;
}
int main(int argc,char **argv)
{
int c;
bool ok = true;
change_times = 0;
no_creat = false;
while((c = getopt(argc,argv,"acm")) != -1)
{
switch(c)
{
case 'a':
change_times |= CH_ATIME;
break;
case 'c':
no_creat = true;
break;
case 'm':
change_times |= CH_MTIME;
break;
default:
printf("fault option!\n");
}
}
if(change_times == 0)
{
change_times = CH_ATIME | CH_MTIME;
}
newtime[0].tv_nsec = UTIME_NOW;
newtime[1].tv_nsec = UTIME_NOW;
if(optind == argc)
{
printf("misssing file operand\n");
}
for(;optind < argc; ++optind)
{
ok &= mytouch(argv[optind]);
}
exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
}