Line data Source code
1 : // SPDX-License-Identifier: GPL-3.0-or-later
2 : // Copyright (C) 2014 Andrea Mazzoleni
3 :
4 : #include "portable.h"
5 :
6 : #include "support.h"
7 : #include "elem.h"
8 : #include "state.h"
9 : #include "handle.h"
10 :
11 1 : void state_touch(struct snapraid_state* state)
12 : {
13 : tommy_node* i;
14 : char esc_buffer[ESC_MAX];
15 :
16 1 : msg_progress("Setting sub-second timestamps...\n");
17 :
18 : /* for all disks */
19 7 : for (i = state->disklist; i != 0; i = i->next) {
20 6 : struct snapraid_disk* disk = i->data;
21 : tommy_node* j;
22 :
23 : /* for all files */
24 5734 : for (j = disk->filelist; j != 0; j = j->next) {
25 5728 : struct snapraid_file* file = j->data;
26 :
27 : /*
28 : * If the file has a zero nanosecond timestamp
29 : * note that symbolic links are not in the file list
30 : * and then are not processed
31 : */
32 5728 : if (file->mtime_nsec == 0) {
33 : char path[PATH_MAX];
34 : struct stat st;
35 : int f;
36 : int ret;
37 : int nsec;
38 : int flags;
39 :
40 16 : pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub);
41 :
42 : /* set a new nanosecond timestamp different than 0 */
43 : do {
44 : uint32_t nano;
45 :
46 : /* get a random nanosecond value */
47 16 : if (randomize(&nano, sizeof(nano)) != 0) {
48 : /* LCOV_EXCL_START */
49 : log_fatal(errno, "Failed to retrieve random values.\n");
50 : exit(EXIT_FAILURE);
51 : /* LCOV_EXCL_STOP */
52 : }
53 :
54 16 : nsec = nano % 1000000000;
55 16 : } while (nsec == 0);
56 :
57 : /*
58 : * O_BINARY: open as binary file (Windows only)
59 : * O_NOFOLLOW: do not follow links to ensure to open the real file
60 : */
61 16 : flags = O_BINARY | O_NOFOLLOW;
62 : #ifdef _WIN32
63 : /* in Windows we must have write access at the file */
64 : flags |= O_RDWR;
65 : #else
66 : /* in all others platforms, read access is enough */
67 16 : flags |= O_RDONLY;
68 : #endif
69 :
70 : /* open it */
71 16 : f = open(path, flags);
72 16 : if (f == -1) {
73 : /* LCOV_EXCL_START */
74 : log_error(errno, "Error opening file '%s'. %s.\n", path, strerror(errno));
75 : continue;
76 : /* LCOV_EXCL_STOP */
77 : }
78 :
79 : /*
80 : * Get the present timestamp, that may be different than the one
81 : * in the content file
82 : */
83 16 : ret = fstat(f, &st);
84 16 : if (ret == -1) {
85 : /* LCOV_EXCL_START */
86 : close(f);
87 : log_error(errno, "Error accessing file '%s'. %s.\n", path, strerror(errno));
88 : continue;
89 : /* LCOV_EXCL_STOP */
90 : }
91 :
92 : /* set the tweaked modification time, with new nano seconds */
93 16 : ret = fmtime(f, st.st_mtime, nsec);
94 16 : if (ret != 0) {
95 : /* LCOV_EXCL_START */
96 : close(f);
97 : log_error(errno, "Error timing file '%s'. %s.\n", path, strerror(errno));
98 : continue;
99 : /* LCOV_EXCL_STOP */
100 : }
101 :
102 : /*
103 : * Uses fstat again to get the present timestamp
104 : * this is needed because the value read
105 : * may be different than the written one
106 : */
107 16 : ret = fstat(f, &st);
108 16 : if (ret == -1) {
109 : /* LCOV_EXCL_START */
110 : close(f);
111 : log_error(errno, "Error accessing file '%s'. %s.\n", path, strerror(errno));
112 : continue;
113 : /* LCOV_EXCL_STOP */
114 : }
115 :
116 : /* close it */
117 16 : ret = close(f);
118 16 : if (ret != 0) {
119 : /* LCOV_EXCL_START */
120 : log_error(errno, "Error closing file '%s'. %s.\n", path, strerror(errno));
121 : continue;
122 : /* LCOV_EXCL_STOP */
123 : }
124 :
125 : /*
126 : * Set the same nanosecond value in the content file
127 : * note that if the seconds value is already matching
128 : * the file won't be synced because the content file will
129 : * contain the new updated timestamp
130 : */
131 16 : file->mtime_nsec = STAT_NSEC(&st);
132 :
133 : /* state changed, we need to update it */
134 16 : state->need_write = 1;
135 :
136 16 : log_tag("touch:%s:%s: %" PRIu64 ".%d\n", disk->name, esc_tag(file->sub, esc_buffer), (uint64_t)st.st_mtime, STAT_NSEC(&st));
137 16 : msg_info("touch %s\n", fmt_term(disk, file->sub, esc_buffer));
138 : }
139 : }
140 : }
141 1 : }
142 :
|