(root)/
sed-4.9/
lib/
stat-time.h
       1  /* stat-related time functions.
       2  
       3     Copyright (C) 2005, 2007, 2009-2022 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