root/lib/stat-time.h

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

/* [<][>][^][v][top][bottom][index][help] */