summaryrefslogtreecommitdiffstats
path: root/gl/stat-time.h
diff options
context:
space:
mode:
Diffstat (limited to 'gl/stat-time.h')
-rw-r--r--gl/stat-time.h60
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
210stat_time_normalize (int result, _GL_UNUSED struct stat *st) 204stat_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;