]>
Commit | Line | Data |
---|---|---|
0ea9ca07 AR |
1 | /* |
2 | * This program can either change modification time of the given | |
01689909 | 3 | * file(s) or just print it. The program does not change atime or |
9517e6b8 | 4 | * ctime (their values are explicitly preserved). |
0ea9ca07 AR |
5 | * |
6 | * The mtime can be changed to an absolute value: | |
7 | * | |
0e496492 | 8 | * test-tool chmtime =<seconds> file... |
0ea9ca07 AR |
9 | * |
10 | * Relative to the current time as returned by time(3): | |
11 | * | |
0e496492 | 12 | * test-tool chmtime =+<seconds> (or =-<seconds>) file... |
0ea9ca07 AR |
13 | * |
14 | * Or relative to the current mtime of the file: | |
15 | * | |
0e496492 NTND |
16 | * test-tool chmtime <seconds> file... |
17 | * test-tool chmtime +<seconds> (or -<seconds>) file... | |
0ea9ca07 AR |
18 | * |
19 | * Examples: | |
20 | * | |
decf711f PSU |
21 | * To print the mtime and the file name use --verbose and set |
22 | * the file mtime offset to 0: | |
0ea9ca07 | 23 | * |
0e496492 | 24 | * test-tool chmtime -v +0 file |
0ea9ca07 | 25 | * |
decf711f PSU |
26 | * To print only the mtime use --get: |
27 | * | |
deb9845a | 28 | * test-tool chmtime --get file |
decf711f | 29 | * |
0ea9ca07 AR |
30 | * To set the mtime to current time: |
31 | * | |
0e496492 | 32 | * test-tool chmtime =+0 file |
0ea9ca07 | 33 | * |
decf711f PSU |
34 | * To set the file mtime offset to +1 and print the new value: |
35 | * | |
deb9845a | 36 | * test-tool chmtime --get +1 file |
decf711f | 37 | * |
0ea9ca07 | 38 | */ |
0e496492 | 39 | #include "test-tool.h" |
17e48368 EW |
40 | #include "git-compat-util.h" |
41 | #include <utime.h> | |
42 | ||
decf711f PSU |
43 | static const char usage_str[] = |
44 | "(-v|--verbose|-g|--get) (+|=|=+|=-|-)<seconds> <file>..."; | |
17e48368 | 45 | |
0ea9ca07 | 46 | static int timespec_arg(const char *arg, long int *set_time, int *set_eq) |
17e48368 | 47 | { |
17e48368 | 48 | char *test; |
0ea9ca07 AR |
49 | const char *timespec = arg; |
50 | *set_eq = (*timespec == '=') ? 1 : 0; | |
51 | if (*set_eq) { | |
17e48368 EW |
52 | timespec++; |
53 | if (*timespec == '+') { | |
0ea9ca07 | 54 | *set_eq = 2; /* relative "in the future" */ |
17e48368 EW |
55 | timespec++; |
56 | } | |
57 | } | |
0ea9ca07 | 58 | *set_time = strtol(timespec, &test, 10); |
17e48368 | 59 | if (*test) { |
0ea9ca07 | 60 | return 0; |
17e48368 | 61 | } |
0ea9ca07 | 62 | if ((*set_eq && *set_time < 0) || *set_eq == 2) { |
17e48368 | 63 | time_t now = time(NULL); |
0ea9ca07 | 64 | *set_time += now; |
17e48368 | 65 | } |
0ea9ca07 AR |
66 | return 1; |
67 | } | |
68 | ||
0e496492 | 69 | int cmd__chmtime(int argc, const char **argv) |
0ea9ca07 AR |
70 | { |
71 | static int verbose; | |
decf711f | 72 | static int get; |
17e48368 | 73 | |
0ea9ca07 AR |
74 | int i = 1; |
75 | /* no mtime change by default */ | |
76 | int set_eq = 0; | |
77 | long int set_time = 0; | |
78 | ||
79 | if (argc < 3) | |
80 | goto usage; | |
81 | ||
decf711f PSU |
82 | if (strcmp(argv[i], "--get") == 0 || strcmp(argv[i], "-g") == 0) { |
83 | get = 1; | |
84 | ++i; | |
85 | } else if (strcmp(argv[i], "--verbose") == 0 || strcmp(argv[i], "-v") == 0) { | |
0ea9ca07 AR |
86 | verbose = 1; |
87 | ++i; | |
88 | } | |
decf711f PSU |
89 | |
90 | if (i == argc) { | |
91 | goto usage; | |
92 | } | |
93 | ||
94 | if (timespec_arg(argv[i], &set_time, &set_eq)) { | |
0ea9ca07 | 95 | ++i; |
decf711f PSU |
96 | } else { |
97 | if (get == 0) { | |
98 | fprintf(stderr, "Not a base-10 integer: %s\n", argv[i] + 1); | |
99 | goto usage; | |
100 | } | |
101 | } | |
102 | ||
103 | if (i == argc) | |
0ea9ca07 AR |
104 | goto usage; |
105 | ||
106 | for (; i < argc; i++) { | |
17e48368 EW |
107 | struct stat sb; |
108 | struct utimbuf utb; | |
decf711f | 109 | uintmax_t mtime; |
17e48368 EW |
110 | |
111 | if (stat(argv[i], &sb) < 0) { | |
7e5aa13d | 112 | fprintf(stderr, "Failed to stat %s: %s. Skipping\n", |
17e48368 | 113 | argv[i], strerror(errno)); |
7e5aa13d | 114 | continue; |
17e48368 EW |
115 | } |
116 | ||
380395d0 | 117 | #ifdef GIT_WINDOWS_NATIVE |
d9b26333 JS |
118 | if (!(sb.st_mode & S_IWUSR) && |
119 | chmod(argv[i], sb.st_mode | S_IWUSR)) { | |
120 | fprintf(stderr, "Could not make user-writable %s: %s", | |
121 | argv[i], strerror(errno)); | |
926e8944 | 122 | return 1; |
d9b26333 JS |
123 | } |
124 | #endif | |
125 | ||
17e48368 EW |
126 | utb.actime = sb.st_atime; |
127 | utb.modtime = set_eq ? set_time : sb.st_mtime + set_time; | |
128 | ||
decf711f PSU |
129 | mtime = utb.modtime < 0 ? 0: utb.modtime; |
130 | if (get) { | |
131 | printf("%"PRIuMAX"\n", mtime); | |
132 | } else if (verbose) { | |
0ea9ca07 AR |
133 | printf("%"PRIuMAX"\t%s\n", mtime, argv[i]); |
134 | } | |
135 | ||
136 | if (utb.modtime != sb.st_mtime && utime(argv[i], &utb) < 0) { | |
17e48368 EW |
137 | fprintf(stderr, "Failed to modify time on %s: %s\n", |
138 | argv[i], strerror(errno)); | |
926e8944 | 139 | return 1; |
17e48368 EW |
140 | } |
141 | } | |
142 | ||
143 | return 0; | |
144 | ||
145 | usage: | |
b978403a | 146 | fprintf(stderr, "usage: %s %s\n", argv[0], usage_str); |
926e8944 | 147 | return 1; |
17e48368 | 148 | } |