Mercurial > gnulib
annotate lib/utimecmp.c @ 40235:5a52ef2d4772
all: Update URLs to msdn.microsoft.com.
* lib/stat-w32.c et al.: Update URLs after most of msdn.microsoft.com
was moved to docs.microsoft.com.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Thu, 14 Mar 2019 09:49:24 +0100 |
parents | b06060465f09 |
children |
rev | line source |
---|---|
18663
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
1 /* utimecmp.c -- compare file timestamps |
5148 | 2 |
40057
b06060465f09
maint: Run 'make update-copyright'
Paul Eggert <eggert@cs.ucla.edu>
parents:
19595
diff
changeset
|
3 Copyright (C) 2004-2007, 2009-2019 Free Software Foundation, Inc. |
5148 | 4 |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8223
diff
changeset
|
5 This program is free software: you can redistribute it and/or modify |
5148 | 6 it under the terms of the GNU General Public License as published by |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8223
diff
changeset
|
7 the Free Software Foundation; either version 3 of the License, or |
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8223
diff
changeset
|
8 (at your option) any later version. |
5148 | 9 |
10 This program is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 GNU General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU General Public License | |
19190 | 16 along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
5148 | 17 |
18 /* Written by Paul Eggert. */ | |
19 | |
7302
8a1a9361108c
* _fpending.c: Include <config.h> unconditionally, since we no
Paul Eggert <eggert@cs.ucla.edu>
parents:
7162
diff
changeset
|
20 #include <config.h> |
5148 | 21 |
22 #include "utimecmp.h" | |
23 | |
19534
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
24 #include <fcntl.h> |
5148 | 25 #include <limits.h> |
26 #include <stdbool.h> | |
7162
19c2e5121b2f
Add and change modules to make it easier for coreutils to use
Paul Eggert <eggert@cs.ucla.edu>
parents:
6323
diff
changeset
|
27 #include <stdint.h> |
5148 | 28 #include <stdlib.h> |
19534
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
29 #include <sys/stat.h> |
8223
ca249819379f
* lib/getdate.h (includes): Include <time.h>, not "timespec.h".
Eric Blake <ebb9@byu.net>
parents:
7406
diff
changeset
|
30 #include <time.h> |
12159
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
31 #include <unistd.h> |
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
32 |
19534
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
33 #include "dirname.h" |
5148 | 34 #include "hash.h" |
5691
ec62790f0938
Factor int-properties macros into a single file, except for
Paul Eggert <eggert@cs.ucla.edu>
parents:
5148
diff
changeset
|
35 #include "intprops.h" |
6238
245950d70306
* utimecmp.c: Include stat-time.h.
Paul Eggert <eggert@cs.ucla.edu>
parents:
5848
diff
changeset
|
36 #include "stat-time.h" |
6323
af09cfa36fd5
* modules/exclude (Depends-on): Depend on verify.
Paul Eggert <eggert@cs.ucla.edu>
parents:
6259
diff
changeset
|
37 #include "verify.h" |
5148 | 38 |
39 #ifndef MAX | |
40 # define MAX(a, b) ((a) > (b) ? (a) : (b)) | |
41 #endif | |
42 | |
12727
fd5b0bf2a8e9
utimecmp: avoid new warning from upcoming gcc-4.5.0
Jim Meyering <meyering@redhat.com>
parents:
12559
diff
changeset
|
43 #define BILLION (1000 * 1000 * 1000) |
5148 | 44 |
45 /* Best possible resolution that utimens can set and stat can return, | |
46 due to system-call limitations. It must be a power of 10 that is | |
47 no greater than 1 billion. */ | |
12159
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
48 #if HAVE_UTIMENSAT |
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
49 enum { SYSCALL_RESOLUTION = 1 }; |
19595
beb2ad957aca
Simplify code. Drop support for Borland C++ on Windows.
Bruno Haible <bruno@clisp.org>
parents:
19534
diff
changeset
|
50 #elif defined _WIN32 && ! defined __CYGWIN__ |
18842
3f720a2a9979
utimecmp: Add support for native Windows.
Bruno Haible <bruno@clisp.org>
parents:
18663
diff
changeset
|
51 /* On native Windows, file times have 100 ns resolution. See |
40235
5a52ef2d4772
all: Update URLs to msdn.microsoft.com.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
52 <https://docs.microsoft.com/en-us/windows/desktop/api/minwinbase/ns-minwinbase-filetime> */ |
18842
3f720a2a9979
utimecmp: Add support for native Windows.
Bruno Haible <bruno@clisp.org>
parents:
18663
diff
changeset
|
53 enum { SYSCALL_RESOLUTION = 100 }; |
12159
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
54 #elif ((HAVE_FUTIMESAT || HAVE_WORKING_UTIMES) \ |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
55 && (defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
56 || defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
57 || defined HAVE_STRUCT_STAT_ST_ATIMENSEC \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
58 || defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC \ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
59 || defined HAVE_STRUCT_STAT_ST_SPARE1)) |
5148 | 60 enum { SYSCALL_RESOLUTION = 1000 }; |
61 #else | |
62 enum { SYSCALL_RESOLUTION = BILLION }; | |
63 #endif | |
64 | |
18663
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
65 /* Describe a file system and its timestamp resolution in nanoseconds. */ |
5148 | 66 struct fs_res |
67 { | |
68 /* Device number of file system. */ | |
69 dev_t dev; | |
70 | |
18663
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
71 /* An upper bound on the timestamp resolution of this file system, |
5148 | 72 ignoring any resolution that cannot be set via utimens. It is |
73 represented by an integer count of nanoseconds. It must be | |
74 either 2 billion, or a power of 10 that is no greater than a | |
75 billion and is no less than SYSCALL_RESOLUTION. */ | |
76 int resolution; | |
77 | |
78 /* True if RESOLUTION is known to be exact, and is not merely an | |
79 upper bound on the true resolution. */ | |
80 bool exact; | |
81 }; | |
82 | |
83 /* Hash some device info. */ | |
84 static size_t | |
85 dev_info_hash (void const *x, size_t table_size) | |
86 { | |
87 struct fs_res const *p = x; | |
88 | |
89 /* Beware signed arithmetic gotchas. */ | |
90 if (TYPE_SIGNED (dev_t) && SIZE_MAX < MAX (INT_MAX, TYPE_MAXIMUM (dev_t))) | |
91 { | |
92 uintmax_t dev = p->dev; | |
93 return dev % table_size; | |
94 } | |
95 | |
96 return p->dev % table_size; | |
97 } | |
98 | |
99 /* Compare two dev_info structs. */ | |
100 static bool | |
101 dev_info_compare (void const *x, void const *y) | |
102 { | |
103 struct fs_res const *a = x; | |
104 struct fs_res const *b = y; | |
105 return a->dev == b->dev; | |
106 } | |
107 | |
19534
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
108 /* Return -1, 0, 1 based on whether the destination file (relative |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
109 to openat-like directory file descriptor DFD with name |
5148 | 110 DST_NAME and status DST_STAT) is older than SRC_STAT, the same age |
111 as SRC_STAT, or newer than SRC_STAT, respectively. | |
112 | |
12159
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
113 DST_NAME may be NULL if OPTIONS is 0. |
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
114 |
5148 | 115 If OPTIONS & UTIMECMP_TRUNCATE_SOURCE, do the comparison after SRC is |
116 converted to the destination's timestamp resolution as filtered through | |
117 utimens. In this case, return -2 if the exact answer cannot be | |
18663
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
118 determined; this can happen only if the timestamps are very close and |
5148 | 119 there is some trouble accessing the file system (e.g., the user does not |
18663
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
120 have permission to futz with the destination's timestamps). */ |
5148 | 121 |
122 int | |
123 utimecmp (char const *dst_name, | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
124 struct stat const *dst_stat, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
125 struct stat const *src_stat, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
126 int options) |
5148 | 127 { |
19534
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
128 return utimecmpat (AT_FDCWD, dst_name, dst_stat, src_stat, options); |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
129 } |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
130 |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
131 int |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
132 utimecmpat (int dfd, char const *dst_name, |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
133 struct stat const *dst_stat, |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
134 struct stat const *src_stat, |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
135 int options) |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
136 { |
5148 | 137 /* Things to watch out for: |
138 | |
139 The code uses a static hash table internally and is not safe in the | |
14642
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
140 presence of signals, multiple threads, etc. However, memory pressure |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
141 that prevents use of the hash table is not fatal - we just fall back |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
142 to redoing the computations on every call in that case. |
5148 | 143 |
144 int and long int might be 32 bits. Many of the calculations store | |
145 numbers up to 2 billion, and multiply by 10; they have to avoid | |
146 multiplying 2 billion by 10, as this exceeds 32-bit capabilities. | |
147 | |
148 time_t might be unsigned. */ | |
149 | |
6323
af09cfa36fd5
* modules/exclude (Depends-on): Depend on verify.
Paul Eggert <eggert@cs.ucla.edu>
parents:
6259
diff
changeset
|
150 verify (TYPE_IS_INTEGER (time_t)); |
5148 | 151 |
18663
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
152 /* Destination and source timestamps. */ |
5148 | 153 time_t dst_s = dst_stat->st_mtime; |
154 time_t src_s = src_stat->st_mtime; | |
6238
245950d70306
* utimecmp.c: Include stat-time.h.
Paul Eggert <eggert@cs.ucla.edu>
parents:
5848
diff
changeset
|
155 int dst_ns = get_stat_mtime_ns (dst_stat); |
245950d70306
* utimecmp.c: Include stat-time.h.
Paul Eggert <eggert@cs.ucla.edu>
parents:
5848
diff
changeset
|
156 int src_ns = get_stat_mtime_ns (src_stat); |
5148 | 157 |
158 if (options & UTIMECMP_TRUNCATE_SOURCE) | |
159 { | |
18663
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
160 /* Look up the timestamp resolution for the destination device. */ |
5148 | 161 |
14642
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
162 /* Hash table for caching information learned about devices. */ |
5148 | 163 static Hash_table *ht; |
164 | |
165 /* Information about the destination file system. */ | |
166 static struct fs_res *new_dst_res; | |
14642
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
167 struct fs_res *dst_res = NULL; |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
168 struct fs_res tmp_dst_res; |
5148 | 169 |
18663
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
170 /* timestamp resolution in nanoseconds. */ |
5148 | 171 int res; |
172 | |
12159
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
173 /* Quick exit, if possible. Since the worst resolution is 2 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
174 seconds, anything that differs by more than that does not |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
175 needs source truncation. */ |
12159
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
176 if (dst_s == src_s && dst_ns == src_ns) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
177 return 0; |
12159
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
178 if (dst_s <= src_s - 2) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
179 return -1; |
12159
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
180 if (src_s <= dst_s - 2) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
181 return 1; |
12159
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
182 |
14642
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
183 /* Try to do a hash lookup, but fall back to stack variables and |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
184 recomputation on low memory situations. */ |
5148 | 185 if (! ht) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
186 ht = hash_initialize (16, NULL, dev_info_hash, dev_info_compare, free); |
14642
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
187 if (ht) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
188 { |
14642
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
189 if (! new_dst_res) |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
190 { |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
191 new_dst_res = malloc (sizeof *new_dst_res); |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
192 if (!new_dst_res) |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
193 goto low_memory; |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
194 new_dst_res->resolution = 2 * BILLION; |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
195 new_dst_res->exact = false; |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
196 } |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
197 new_dst_res->dev = dst_stat->st_dev; |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
198 dst_res = hash_insert (ht, new_dst_res); |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
199 if (! dst_res) |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
200 goto low_memory; |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
201 |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
202 if (dst_res == new_dst_res) |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
203 { |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
204 /* NEW_DST_RES is now in use in the hash table, so allocate a |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
205 new entry next time. */ |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
206 new_dst_res = NULL; |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
207 } |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
208 } |
14642
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
209 else |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
210 { |
14642
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
211 low_memory: |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
212 if (ht) |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
213 { |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
214 tmp_dst_res.dev = dst_stat->st_dev; |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
215 dst_res = hash_lookup (ht, &tmp_dst_res); |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
216 } |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
217 if (!dst_res) |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
218 { |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
219 dst_res = &tmp_dst_res; |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
220 dst_res->resolution = 2 * BILLION; |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
221 dst_res->exact = false; |
1e0bf20577a1
utimecmp: drop dependency on xmalloc
Eric Blake <eblake@redhat.com>
parents:
14079
diff
changeset
|
222 } |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
223 } |
5148 | 224 |
225 res = dst_res->resolution; | |
226 | |
12159
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
227 #ifdef _PC_TIMESTAMP_RESOLUTION |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
228 /* If the system will tell us the resolution, we're set! */ |
12159
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
229 if (! dst_res->exact) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
230 { |
19534
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
231 res = -1; |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
232 if (dfd == AT_FDCWD) |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
233 res = pathconf (dst_name, _PC_TIMESTAMP_RESOLUTION); |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
234 else |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
235 { |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
236 char *dstdir = mdir_name (dst_name); |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
237 if (dstdir) |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
238 { |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
239 int destdirfd = openat (dfd, dstdir, |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
240 O_SEARCH | O_CLOEXEC | O_DIRECTORY); |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
241 if (0 <= destdirfd) |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
242 { |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
243 res = fpathconf (destdirfd, _PC_TIMESTAMP_RESOLUTION); |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
244 close (destdirfd); |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
245 } |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
246 free (dstdir); |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
247 } |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
248 } |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
249 if (0 < res) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
250 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
251 dst_res->resolution = res; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
252 dst_res->exact = true; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
253 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
254 } |
12159
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
255 #endif |
0ae159ba1adf
utimecmp: support symlink timestamps
Eric Blake <ebb9@byu.net>
parents:
9309
diff
changeset
|
256 |
5148 | 257 if (! dst_res->exact) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
258 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
259 /* This file system's resolution is not known exactly. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
260 Deduce it, and store the result in the hash table. */ |
5148 | 261 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
262 time_t dst_a_s = dst_stat->st_atime; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
263 time_t dst_c_s = dst_stat->st_ctime; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
264 time_t dst_m_s = dst_s; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
265 int dst_a_ns = get_stat_atime_ns (dst_stat); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
266 int dst_c_ns = get_stat_ctime_ns (dst_stat); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
267 int dst_m_ns = dst_ns; |
5148 | 268 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
269 /* Set RES to an upper bound on the file system resolution |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
270 (after truncation due to SYSCALL_RESOLUTION) by inspecting |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
271 the atime, ctime and mtime of the existing destination. |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
272 We don't know of any file system that stores atime or |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
273 ctime with a higher precision than mtime, so it's valid to |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
274 look at them too. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
275 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
276 bool odd_second = (dst_a_s | dst_c_s | dst_m_s) & 1; |
5148 | 277 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
278 if (SYSCALL_RESOLUTION == BILLION) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
279 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
280 if (odd_second | dst_a_ns | dst_c_ns | dst_m_ns) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
281 res = BILLION; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
282 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
283 else |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
284 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
285 int a = dst_a_ns; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
286 int c = dst_c_ns; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
287 int m = dst_m_ns; |
5148 | 288 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
289 /* Write it this way to avoid mistaken GCC warning |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
290 about integer overflow in constant expression. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
291 int SR10 = SYSCALL_RESOLUTION; SR10 *= 10; |
5148 | 292 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
293 if ((a % SR10 | c % SR10 | m % SR10) != 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
294 res = SYSCALL_RESOLUTION; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
295 else |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
296 for (res = SR10, a /= SR10, c /= SR10, m /= SR10; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
297 (res < dst_res->resolution |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
298 && (a % 10 | c % 10 | m % 10) == 0); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
299 res *= 10, a /= 10, c /= 10, m /= 10) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
300 if (res == BILLION) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
301 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
302 if (! odd_second) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
303 res *= 2; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
304 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
305 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
306 } |
5148 | 307 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
308 dst_res->resolution = res; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
309 } |
5148 | 310 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
311 if (SYSCALL_RESOLUTION < res) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
312 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
313 struct timespec timespec[2]; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
314 struct stat dst_status; |
5148 | 315 |
18663
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
316 /* Ignore source timestamp information that must necessarily |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
317 be lost when filtered through utimens. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
318 src_ns -= src_ns % SYSCALL_RESOLUTION; |
5148 | 319 |
18663
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
320 /* If the timestamps disagree widely enough, there's no need |
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
321 to interrogate the file system to deduce the exact |
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
322 timestamp resolution; return the answer directly. */ |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
323 { |
18441
c204ad2f4289
utimecmp: avoid new GCC 7 warning from -Wbool-operation
Jim Meyering <meyering@fb.com>
parents:
18294
diff
changeset
|
324 time_t s = src_s & ~ (res == 2 * BILLION ? 1 : 0); |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
325 if (src_s < dst_s || (src_s == dst_s && src_ns <= dst_ns)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
326 return 1; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
327 if (dst_s < s |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
328 || (dst_s == s && dst_ns < src_ns - src_ns % res)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
329 return -1; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
330 } |
5148 | 331 |
18663
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
332 /* Determine the actual timestamp resolution for the |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
333 destination file system (after truncation due to |
18663
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
334 SYSCALL_RESOLUTION) by setting the access timestamp of the |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
335 destination to the existing access time, except with |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
336 trailing nonzero digits. */ |
5148 | 337 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
338 timespec[0].tv_sec = dst_a_s; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
339 timespec[0].tv_nsec = dst_a_ns; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
340 timespec[1].tv_sec = dst_m_s | (res == 2 * BILLION); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
341 timespec[1].tv_nsec = dst_m_ns + res / 9; |
5148 | 342 |
19534
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
343 if (utimensat (dfd, dst_name, timespec, AT_SYMLINK_NOFOLLOW)) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
344 return -2; |
5148 | 345 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
346 /* Read the modification time that was set. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
347 { |
19534
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
348 int stat_result |
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
349 = fstatat (dfd, dst_name, &dst_status, AT_SYMLINK_NOFOLLOW); |
5148 | 350 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
351 if (stat_result |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
352 | (dst_status.st_mtime ^ dst_m_s) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
353 | (get_stat_mtime_ns (&dst_status) ^ dst_m_ns)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
354 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
355 /* The modification time changed, or we can't tell whether |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
356 it changed. Change it back as best we can. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
357 timespec[1].tv_sec = dst_m_s; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
358 timespec[1].tv_nsec = dst_m_ns; |
19534
e64c6a43dc9c
utimecmp: new function utimecmpat
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
359 utimensat (dfd, dst_name, timespec, AT_SYMLINK_NOFOLLOW); |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
360 } |
5148 | 361 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
362 if (stat_result != 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
363 return -2; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
364 } |
5148 | 365 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
366 /* Determine the exact resolution from the modification time |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
367 that was read back. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
368 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
369 int old_res = res; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
370 int a = (BILLION * (dst_status.st_mtime & 1) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
371 + get_stat_mtime_ns (&dst_status)); |
5148 | 372 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
373 res = SYSCALL_RESOLUTION; |
5148 | 374 |
13914
cc15a32c0446
utimecmp: fine-grained src to nearby coarse-grained dest
Paul Eggert <eggert@cs.ucla.edu>
parents:
12727
diff
changeset
|
375 for (a /= res; a % 10 == 0; a /= 10) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
376 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
377 if (res == BILLION) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
378 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
379 res *= 2; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
380 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
381 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
382 res *= 10; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
383 if (res == old_res) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
384 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
385 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
386 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
387 } |
5148 | 388 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
389 dst_res->resolution = res; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
390 dst_res->exact = true; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
391 } |
5148 | 392 |
18663
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
393 /* Truncate the source's timestamp according to the resolution. */ |
18441
c204ad2f4289
utimecmp: avoid new GCC 7 warning from -Wbool-operation
Jim Meyering <meyering@fb.com>
parents:
18294
diff
changeset
|
394 src_s &= ~ (res == 2 * BILLION ? 1 : 0); |
5148 | 395 src_ns -= src_ns % res; |
396 } | |
397 | |
18663
caf9d6314c8f
maint: time stamp -> timestamp
Paul Eggert <eggert@cs.ucla.edu>
parents:
18626
diff
changeset
|
398 /* Compare the timestamps and return -1, 0, 1 accordingly. */ |
5148 | 399 return (dst_s < src_s ? -1 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
400 : dst_s > src_s ? 1 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
401 : dst_ns < src_ns ? -1 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12159
diff
changeset
|
402 : dst_ns > src_ns); |
5148 | 403 } |