Annotation of embedaddon/libiconv/srclib/stat-time.h, revision 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>