Annotation of embedaddon/libiconv/srclib/stat-time.h, revision 1.1.1.1

1.1       misho       1: /* stat-related time functions.
                      2: 
                      3:    Copyright (C) 2005, 2007, 2009-2019 Free Software Foundation, Inc.
                      4: 
                      5:    This program is free software: you can redistribute it and/or modify
                      6:    it under the terms of the GNU General Public License as published by
                      7:    the Free Software Foundation; either version 3 of the License, or
                      8:    (at your option) any later version.
                      9: 
                     10:    This program 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 General Public License for more details.
                     14: 
                     15:    You should have received a copy of the GNU 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)
                     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)
                     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)
                     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 (struct stat const *st _GL_UNUSED)
                    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)
                    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)
                    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)
                    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 (struct stat const *st _GL_UNUSED)
                    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, struct stat *st _GL_UNUSED)
                    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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>