• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <string.h>
3 #include <sys/types.h>
4 #include <fcntl.h>
5 #include <sys/stat.h>
6 #include <stdlib.h>
7 #include <fcntl.h>
8 #include <time.h>
9 
usage(void)10 static void usage(void)
11 {
12         fprintf(stderr, "touch: usage: touch [-alm] [-t YYYYMMDD[.hhmmss]] <file>\n");
13         exit(1);
14 }
15 
parse_time(char * s)16 static time_t parse_time(char *s)
17 {
18     struct tm tm;
19     int day = atoi(s);
20     int hour = 0;
21 
22     while (*s && *s != '.') {
23         s++;
24     }
25 
26     if (*s) {
27         s++;
28         hour = atoi(s);
29     }
30 
31     tm.tm_year = day / 10000 - 1900;
32     tm.tm_mon = (day % 10000) / 100 - 1;
33     tm.tm_mday = day % 100;
34     tm.tm_hour = hour / 10000;
35     tm.tm_min = (hour % 10000) / 100;
36     tm.tm_sec = hour % 100;
37     tm.tm_isdst = -1;
38 
39     return mktime(&tm);
40 }
41 
touch_main(int argc,char * argv[])42 int touch_main(int argc, char *argv[])
43 {
44         int i, fd, aflag = 0, mflag = 0, debug = 0, flags = 0;
45         struct timespec specified_time, times[2];
46         char *file = 0;
47 
48         specified_time.tv_nsec = UTIME_NOW;
49 
50         for (i = 1; i < argc; i++) {
51             if (argv[i][0] == '-') {
52                 /* an option */
53                 const char *arg = argv[i]+1;
54                 while (arg[0]) {
55                     switch (arg[0]) {
56                     case 'a': aflag = 1; break;
57                     case 'm': mflag = 1; break;
58                     case 't':
59                         if ((i+1) >= argc)
60                             usage();
61                         specified_time.tv_sec = parse_time(argv[++i]);
62                         if (specified_time.tv_sec == -1) {
63                             fprintf(stderr, "touch: invalid timestamp specified\n");
64                             exit(1);
65                         }
66                         specified_time.tv_nsec = 0;
67                         break;
68                     case 'l': flags |= AT_SYMLINK_NOFOLLOW; break;
69                     case 'd': debug = 1; break;
70                     default:
71                         usage();
72                     }
73                     arg++;
74                 }
75             } else {
76                 /* not an option, and only accept one filename */
77                 if (i+1 != argc)
78                     usage();
79                 file = argv[i];
80             }
81         }
82 
83         if (! file) {
84             fprintf(stderr, "touch: no file specified\n");
85             exit(1);
86         }
87 
88         if (access(file, F_OK))
89             if ((fd=creat(file, 0666)) != -1)
90                 close(fd);
91 
92         if ((mflag == 0) && (aflag == 0))
93             aflag = mflag = 1;
94 
95         if (aflag)
96             times[0] = specified_time;
97         else
98             times[0].tv_nsec = UTIME_OMIT;
99 
100         if (mflag)
101             times[1] = specified_time;
102         else
103             times[1].tv_nsec = UTIME_OMIT;
104 
105         if (debug) {
106             fprintf(stderr, "file = %s\n", file);
107             fprintf(stderr, "times[0].tv_sec = %ld, times[0].tv_nsec = %ld\n", times[0].tv_sec, times[0].tv_nsec);
108             fprintf(stderr, "times[1].tv_sec = %ld, times[1].tv_nsec = %ld\n", times[1].tv_sec, times[1].tv_nsec);
109             fprintf(stderr, "flags = 0x%8.8x\n", flags);
110         }
111 
112         return utimensat(AT_FDCWD, file, times, flags);
113 }
114 
115