diff options
Diffstat (limited to 'gl/stat-time.h')
-rw-r--r-- | gl/stat-time.h | 60 |
1 files changed, 27 insertions, 33 deletions
diff --git a/gl/stat-time.h b/gl/stat-time.h index 92aa1e6..3cd8478 100644 --- a/gl/stat-time.h +++ b/gl/stat-time.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* stat-related time functions. | 1 | /* stat-related time functions. |
2 | 2 | ||
3 | Copyright (C) 2005, 2007, 2009-2023 Free Software Foundation, Inc. | 3 | Copyright (C) 2005, 2007, 2009-2024 Free Software Foundation, Inc. |
4 | 4 | ||
5 | This file is free software: you can redistribute it and/or modify | 5 | This file is free software: you can redistribute it and/or modify |
6 | it under the terms of the GNU Lesser General Public License as | 6 | it under the terms of the GNU Lesser General Public License as |
@@ -20,15 +20,18 @@ | |||
20 | #ifndef STAT_TIME_H | 20 | #ifndef STAT_TIME_H |
21 | #define STAT_TIME_H 1 | 21 | #define STAT_TIME_H 1 |
22 | 22 | ||
23 | /* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE, _GL_UNUSED, | ||
24 | _GL_ATTRIBUTE_PURE, HAVE_STRUCT_STAT_*. */ | ||
25 | #if !_GL_CONFIG_H_INCLUDED | ||
26 | #error "Please include config.h first." | ||
27 | #endif | ||
28 | |||
23 | #include <errno.h> | 29 | #include <errno.h> |
24 | #include <stdckdint.h> | 30 | #include <stdckdint.h> |
25 | #include <stddef.h> | 31 | #include <stddef.h> |
26 | #include <sys/stat.h> | 32 | #include <sys/stat.h> |
27 | #include <time.h> | 33 | #include <time.h> |
28 | 34 | ||
29 | #ifndef _GL_INLINE_HEADER_BEGIN | ||
30 | #error "Please include config.h first." | ||
31 | #endif | ||
32 | _GL_INLINE_HEADER_BEGIN | 35 | _GL_INLINE_HEADER_BEGIN |
33 | #ifndef _GL_STAT_TIME_INLINE | 36 | #ifndef _GL_STAT_TIME_INLINE |
34 | # define _GL_STAT_TIME_INLINE _GL_INLINE | 37 | # define _GL_STAT_TIME_INLINE _GL_INLINE |
@@ -49,11 +52,13 @@ extern "C" { | |||
49 | #if _GL_WINDOWS_STAT_TIMESPEC || defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC | 52 | #if _GL_WINDOWS_STAT_TIMESPEC || defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC |
50 | # if _GL_WINDOWS_STAT_TIMESPEC || defined TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC | 53 | # if _GL_WINDOWS_STAT_TIMESPEC || defined TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC |
51 | # define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim) | 54 | # define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim) |
55 | # define STAT_TIMESPEC_OFFSETOF(st_xtim) offsetof (struct stat, st_xtim) | ||
52 | # else | 56 | # else |
53 | # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec) | 57 | # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec) |
54 | # endif | 58 | # endif |
55 | #elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC | 59 | #elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC |
56 | # define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec) | 60 | # define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec) |
61 | # define STAT_TIMESPEC_OFFSETOF(st_xtim) offsetof (struct stat, st_xtim##espec) | ||
57 | #elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC | 62 | #elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC |
58 | # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec) | 63 | # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec) |
59 | #elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC | 64 | #elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC |
@@ -119,10 +124,8 @@ get_stat_atime (struct stat const *st) | |||
119 | #ifdef STAT_TIMESPEC | 124 | #ifdef STAT_TIMESPEC |
120 | return STAT_TIMESPEC (st, st_atim); | 125 | return STAT_TIMESPEC (st, st_atim); |
121 | #else | 126 | #else |
122 | struct timespec t; | 127 | return (struct timespec) { .tv_sec = st->st_atime, |
123 | t.tv_sec = st->st_atime; | 128 | .tv_nsec = get_stat_atime_ns (st) }; |
124 | t.tv_nsec = get_stat_atime_ns (st); | ||
125 | return t; | ||
126 | #endif | 129 | #endif |
127 | } | 130 | } |
128 | 131 | ||
@@ -133,10 +136,8 @@ get_stat_ctime (struct stat const *st) | |||
133 | #ifdef STAT_TIMESPEC | 136 | #ifdef STAT_TIMESPEC |
134 | return STAT_TIMESPEC (st, st_ctim); | 137 | return STAT_TIMESPEC (st, st_ctim); |
135 | #else | 138 | #else |
136 | struct timespec t; | 139 | return (struct timespec) { .tv_sec = st->st_ctime, |
137 | t.tv_sec = st->st_ctime; | 140 | .tv_nsec = get_stat_ctime_ns (st) }; |
138 | t.tv_nsec = get_stat_ctime_ns (st); | ||
139 | return t; | ||
140 | #endif | 141 | #endif |
141 | } | 142 | } |
142 | 143 | ||
@@ -147,10 +148,8 @@ get_stat_mtime (struct stat const *st) | |||
147 | #ifdef STAT_TIMESPEC | 148 | #ifdef STAT_TIMESPEC |
148 | return STAT_TIMESPEC (st, st_mtim); | 149 | return STAT_TIMESPEC (st, st_mtim); |
149 | #else | 150 | #else |
150 | struct timespec t; | 151 | return (struct timespec) { .tv_sec = st->st_mtime, |
151 | t.tv_sec = st->st_mtime; | 152 | .tv_nsec = get_stat_mtime_ns (st) }; |
152 | t.tv_nsec = get_stat_mtime_ns (st); | ||
153 | return t; | ||
154 | #endif | 153 | #endif |
155 | } | 154 | } |
156 | 155 | ||
@@ -165,8 +164,8 @@ get_stat_birthtime (_GL_UNUSED struct stat const *st) | |||
165 | || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC) | 164 | || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC) |
166 | t = STAT_TIMESPEC (st, st_birthtim); | 165 | t = STAT_TIMESPEC (st, st_birthtim); |
167 | #elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC | 166 | #elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC |
168 | t.tv_sec = st->st_birthtime; | 167 | t = (struct timespec) { .tv_sec = st->st_birthtime, |
169 | t.tv_nsec = st->st_birthtimensec; | 168 | .tv_nsec = st->st_birthtimensec }; |
170 | #elif defined _WIN32 && ! defined __CYGWIN__ | 169 | #elif defined _WIN32 && ! defined __CYGWIN__ |
171 | /* Native Windows platforms (but not Cygwin) put the "file creation | 170 | /* Native Windows platforms (but not Cygwin) put the "file creation |
172 | time" in st_ctime (!). See | 171 | time" in st_ctime (!). See |
@@ -174,13 +173,11 @@ get_stat_birthtime (_GL_UNUSED struct stat const *st) | |||
174 | # if _GL_WINDOWS_STAT_TIMESPEC | 173 | # if _GL_WINDOWS_STAT_TIMESPEC |
175 | t = st->st_ctim; | 174 | t = st->st_ctim; |
176 | # else | 175 | # else |
177 | t.tv_sec = st->st_ctime; | 176 | t = (struct timespec) { .tv_sec = st->st_ctime }; |
178 | t.tv_nsec = 0; | ||
179 | # endif | 177 | # endif |
180 | #else | 178 | #else |
181 | /* Birth time is not supported. */ | 179 | /* Birth time is not supported. */ |
182 | t.tv_sec = -1; | 180 | t = (struct timespec) { .tv_sec = -1, .tv_nsec = -1 }; |
183 | t.tv_nsec = -1; | ||
184 | #endif | 181 | #endif |
185 | 182 | ||
186 | #if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \ | 183 | #if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \ |
@@ -192,30 +189,28 @@ get_stat_birthtime (_GL_UNUSED struct stat const *st) | |||
192 | sometimes returns junk in the birth time fields; work around this | 189 | sometimes returns junk in the birth time fields; work around this |
193 | bug if it is detected. */ | 190 | bug if it is detected. */ |
194 | if (! (t.tv_sec && 0 <= t.tv_nsec && t.tv_nsec < 1000000000)) | 191 | if (! (t.tv_sec && 0 <= t.tv_nsec && t.tv_nsec < 1000000000)) |
195 | { | 192 | t = (struct timespec) { .tv_sec = -1, .tv_nsec = -1 }; |
196 | t.tv_sec = -1; | ||
197 | t.tv_nsec = -1; | ||
198 | } | ||
199 | #endif | 193 | #endif |
200 | 194 | ||
201 | return t; | 195 | return t; |
202 | } | 196 | } |
203 | 197 | ||
204 | /* If a stat-like function returned RESULT, normalize the timestamps | 198 | /* If a stat-like function returned RESULT, normalize the timestamps |
205 | in *ST, in case this platform suffers from the Solaris 11 bug where | 199 | in *ST, if this platform suffers from a macOS and Solaris bug where |
206 | tv_nsec might be negative. Return the adjusted RESULT, setting | 200 | tv_nsec might be negative. Return the adjusted RESULT, setting |
207 | errno to EOVERFLOW if normalization overflowed. This function | 201 | errno to EOVERFLOW if normalization overflowed. This function |
208 | is intended to be private to this .h file. */ | 202 | is intended to be private to this .h file. */ |
209 | _GL_STAT_TIME_INLINE int | 203 | _GL_STAT_TIME_INLINE int |
210 | stat_time_normalize (int result, _GL_UNUSED struct stat *st) | 204 | stat_time_normalize (int result, _GL_UNUSED struct stat *st) |
211 | { | 205 | { |
212 | #if defined __sun && defined STAT_TIMESPEC | 206 | #if (((defined __APPLE__ && defined __MACH__) || defined __sun) \ |
207 | && defined STAT_TIMESPEC_OFFSETOF) | ||
213 | if (result == 0) | 208 | if (result == 0) |
214 | { | 209 | { |
215 | long int timespec_hz = 1000000000; | 210 | long int timespec_hz = 1000000000; |
216 | short int const ts_off[] = { offsetof (struct stat, st_atim), | 211 | short int const ts_off[] = { STAT_TIMESPEC_OFFSETOF (st_atim), |
217 | offsetof (struct stat, st_mtim), | 212 | STAT_TIMESPEC_OFFSETOF (st_mtim), |
218 | offsetof (struct stat, st_ctim) }; | 213 | STAT_TIMESPEC_OFFSETOF (st_ctim) }; |
219 | int i; | 214 | int i; |
220 | for (i = 0; i < sizeof ts_off / sizeof *ts_off; i++) | 215 | for (i = 0; i < sizeof ts_off / sizeof *ts_off; i++) |
221 | { | 216 | { |
@@ -229,8 +224,7 @@ stat_time_normalize (int result, _GL_UNUSED struct stat *st) | |||
229 | } | 224 | } |
230 | ts->tv_nsec = r; | 225 | ts->tv_nsec = r; |
231 | /* Overflow is possible, as Solaris 11 stat can yield | 226 | /* Overflow is possible, as Solaris 11 stat can yield |
232 | tv_sec == TYPE_MINIMUM (time_t) && tv_nsec == -1000000000. | 227 | tv_sec == TYPE_MINIMUM (time_t) && tv_nsec == -1000000000. */ |
233 | INT_ADD_WRAPV is OK, since time_t is signed on Solaris. */ | ||
234 | if (ckd_add (&ts->tv_sec, q, ts->tv_sec)) | 228 | if (ckd_add (&ts->tv_sec, q, ts->tv_sec)) |
235 | { | 229 | { |
236 | errno = EOVERFLOW; | 230 | errno = EOVERFLOW; |