root/maint/gnulib/lib/stat-time.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. get_stat_atime_ns
  2. get_stat_ctime_ns
  3. get_stat_mtime_ns
  4. get_stat_birthtime_ns
  5. get_stat_atime
  6. get_stat_ctime
  7. get_stat_mtime
  8. get_stat_birthtime
  9. stat_time_normalize

   1 /* stat-related time functions.
   2 
   3    Copyright (C) 2005, 2007, 2009-2021 Free Software Foundation, Inc.
   4 
   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
   7    published by the Free Software Foundation; either version 2.1 of the
   8    License, or (at your option) any later version.
   9 
  10    This file 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 Lesser General Public License for more details.
  14 
  15    You should have received a copy of the GNU Lesser General Public License
  16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  17 
  18 /* Written by Paul Eggert.  */
  19 
  20 #ifndef STAT_TIME_H
  21 #define STAT_TIME_H 1
  22 
  23 #include "intprops.h"
  24 
  25 #include <errno.h>
  26 #include <stddef.h>
  27 #include <sys/stat.h>
  28 #include <time.h>
  29 
  30 #ifndef _GL_INLINE_HEADER_BEGIN
  31  #error "Please include config.h first."
  32 #endif
  33 _GL_INLINE_HEADER_BEGIN
  34 #ifndef _GL_STAT_TIME_INLINE
  35 # define _GL_STAT_TIME_INLINE _GL_INLINE
  36 #endif
  37 
  38 #ifdef __cplusplus
  39 extern "C" {
  40 #endif
  41 
  42 /* STAT_TIMESPEC (ST, ST_XTIM) is the ST_XTIM member for *ST of type
  43    struct timespec, if available.  If not, then STAT_TIMESPEC_NS (ST,
  44    ST_XTIM) is the nanosecond component of the ST_XTIM member for *ST,
  45    if available.  ST_XTIM can be st_atim, st_ctim, st_mtim, or st_birthtim
  46    for access, status change, data modification, or birth (creation)
  47    time respectively.
  48 
  49    These macros are private to stat-time.h.  */
  50 #if _GL_WINDOWS_STAT_TIMESPEC || defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
  51 # if _GL_WINDOWS_STAT_TIMESPEC || defined TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC
  52 #  define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim)
  53 # else
  54 #  define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec)
  55 # endif
  56 #elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
  57 # define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec)
  58 #elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC
  59 # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec)
  60 #elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC
  61 # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.st__tim.tv_nsec)
  62 #endif
  63 
  64 /* Return the nanosecond component of *ST's access time.  */
  65 _GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE
  66 get_stat_atime_ns (struct stat const *st)
     /* [previous][next][first][last][top][bottom][index][help] */
  67 {
  68 # if defined STAT_TIMESPEC
  69   return STAT_TIMESPEC (st, st_atim).tv_nsec;
  70 # elif defined STAT_TIMESPEC_NS
  71   return STAT_TIMESPEC_NS (st, st_atim);
  72 # else
  73   return 0;
  74 # endif
  75 }
  76 
  77 /* Return the nanosecond component of *ST's status change time.  */
  78 _GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE
  79 get_stat_ctime_ns (struct stat const *st)
     /* [previous][next][first][last][top][bottom][index][help] */
  80 {
  81 # if defined STAT_TIMESPEC
  82   return STAT_TIMESPEC (st, st_ctim).tv_nsec;
  83 # elif defined STAT_TIMESPEC_NS
  84   return STAT_TIMESPEC_NS (st, st_ctim);
  85 # else
  86   return 0;
  87 # endif
  88 }
  89 
  90 /* Return the nanosecond component of *ST's data modification time.  */
  91 _GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE
  92 get_stat_mtime_ns (struct stat const *st)
     /* [previous][next][first][last][top][bottom][index][help] */
  93 {
  94 # if defined STAT_TIMESPEC
  95   return STAT_TIMESPEC (st, st_mtim).tv_nsec;
  96 # elif defined STAT_TIMESPEC_NS
  97   return STAT_TIMESPEC_NS (st, st_mtim);
  98 # else
  99   return 0;
 100 # endif
 101 }
 102 
 103 /* Return the nanosecond component of *ST's birth time.  */
 104 _GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE
 105 get_stat_birthtime_ns (_GL_UNUSED struct stat const *st)
     /* [previous][next][first][last][top][bottom][index][help] */
 106 {
 107 # if defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
 108   return STAT_TIMESPEC (st, st_birthtim).tv_nsec;
 109 # elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
 110   return STAT_TIMESPEC_NS (st, st_birthtim);
 111 # else
 112   return 0;
 113 # endif
 114 }
 115 
 116 /* Return *ST's access time.  */
 117 _GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE
 118 get_stat_atime (struct stat const *st)
     /* [previous][next][first][last][top][bottom][index][help] */
 119 {
 120 #ifdef STAT_TIMESPEC
 121   return STAT_TIMESPEC (st, st_atim);
 122 #else
 123   struct timespec t;
 124   t.tv_sec = st->st_atime;
 125   t.tv_nsec = get_stat_atime_ns (st);
 126   return t;
 127 #endif
 128 }
 129 
 130 /* Return *ST's status change time.  */
 131 _GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE
 132 get_stat_ctime (struct stat const *st)
     /* [previous][next][first][last][top][bottom][index][help] */
 133 {
 134 #ifdef STAT_TIMESPEC
 135   return STAT_TIMESPEC (st, st_ctim);
 136 #else
 137   struct timespec t;
 138   t.tv_sec = st->st_ctime;
 139   t.tv_nsec = get_stat_ctime_ns (st);
 140   return t;
 141 #endif
 142 }
 143 
 144 /* Return *ST's data modification time.  */
 145 _GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE
 146 get_stat_mtime (struct stat const *st)
     /* [previous][next][first][last][top][bottom][index][help] */
 147 {
 148 #ifdef STAT_TIMESPEC
 149   return STAT_TIMESPEC (st, st_mtim);
 150 #else
 151   struct timespec t;
 152   t.tv_sec = st->st_mtime;
 153   t.tv_nsec = get_stat_mtime_ns (st);
 154   return t;
 155 #endif
 156 }
 157 
 158 /* Return *ST's birth time, if available; otherwise return a value
 159    with tv_sec and tv_nsec both equal to -1.  */
 160 _GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE
 161 get_stat_birthtime (_GL_UNUSED struct stat const *st)
     /* [previous][next][first][last][top][bottom][index][help] */
 162 {
 163   struct timespec t;
 164 
 165 #if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
 166      || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC)
 167   t = STAT_TIMESPEC (st, st_birthtim);
 168 #elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
 169   t.tv_sec = st->st_birthtime;
 170   t.tv_nsec = st->st_birthtimensec;
 171 #elif defined _WIN32 && ! defined __CYGWIN__
 172   /* Native Windows platforms (but not Cygwin) put the "file creation
 173      time" in st_ctime (!).  See
 174      <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/stat-functions>.  */
 175 # if _GL_WINDOWS_STAT_TIMESPEC
 176   t = st->st_ctim;
 177 # else
 178   t.tv_sec = st->st_ctime;
 179   t.tv_nsec = 0;
 180 # endif
 181 #else
 182   /* Birth time is not supported.  */
 183   t.tv_sec = -1;
 184   t.tv_nsec = -1;
 185 #endif
 186 
 187 #if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
 188      || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC \
 189      || defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
 190   /* FreeBSD and NetBSD sometimes signal the absence of knowledge by
 191      using zero.  Attempt to work around this problem.  Alas, this can
 192      report failure even for valid timestamps.  Also, NetBSD
 193      sometimes returns junk in the birth time fields; work around this
 194      bug if it is detected.  */
 195   if (! (t.tv_sec && 0 <= t.tv_nsec && t.tv_nsec < 1000000000))
 196     {
 197       t.tv_sec = -1;
 198       t.tv_nsec = -1;
 199     }
 200 #endif
 201 
 202   return t;
 203 }
 204 
 205 /* If a stat-like function returned RESULT, normalize the timestamps
 206    in *ST, in case this platform suffers from the Solaris 11 bug where
 207    tv_nsec might be negative.  Return the adjusted RESULT, setting
 208    errno to EOVERFLOW if normalization overflowed.  This function
 209    is intended to be private to this .h file.  */
 210 _GL_STAT_TIME_INLINE int
 211 stat_time_normalize (int result, _GL_UNUSED struct stat *st)
     /* [previous][next][first][last][top][bottom][index][help] */
 212 {
 213 #if defined __sun && defined STAT_TIMESPEC
 214   if (result == 0)
 215     {
 216       long int timespec_hz = 1000000000;
 217       short int const ts_off[] = { offsetof (struct stat, st_atim),
 218                                    offsetof (struct stat, st_mtim),
 219                                    offsetof (struct stat, st_ctim) };
 220       int i;
 221       for (i = 0; i < sizeof ts_off / sizeof *ts_off; i++)
 222         {
 223           struct timespec *ts = (struct timespec *) ((char *) st + ts_off[i]);
 224           long int q = ts->tv_nsec / timespec_hz;
 225           long int r = ts->tv_nsec % timespec_hz;
 226           if (r < 0)
 227             {
 228               r += timespec_hz;
 229               q--;
 230             }
 231           ts->tv_nsec = r;
 232           /* Overflow is possible, as Solaris 11 stat can yield
 233              tv_sec == TYPE_MINIMUM (time_t) && tv_nsec == -1000000000.
 234              INT_ADD_WRAPV is OK, since time_t is signed on Solaris.  */
 235           if (INT_ADD_WRAPV (q, ts->tv_sec, &ts->tv_sec))
 236             {
 237               errno = EOVERFLOW;
 238               return -1;
 239             }
 240         }
 241     }
 242 #endif
 243   return result;
 244 }
 245 
 246 #ifdef __cplusplus
 247 }
 248 #endif
 249 
 250 _GL_INLINE_HEADER_END
 251 
 252 #endif

/* [previous][next][first][last][top][bottom][index][help] */