File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libiconv / srclib / stat-time.h
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 13:38:46 2021 UTC (3 years, 3 months ago) by misho
Branches: libiconv, MAIN
CVS tags: v1_16p0, HEAD
libiconv 1.16

    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>