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

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