(root)/
tar-1.35/
gnu/
stat-time.h
       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