Blame gl/stat-time.h

Packit Service 4684c1
/* stat-related time functions.
Packit Service 4684c1
Packit Service 4684c1
   Copyright (C) 2005, 2007, 2009-2020 Free Software Foundation, Inc.
Packit Service 4684c1
Packit Service 4684c1
   This program is free software: you can redistribute it and/or modify
Packit Service 4684c1
   it under the terms of the GNU Lesser General Public License as published by
Packit Service 4684c1
   the Free Software Foundation; either version 2.1 of the License, or
Packit Service 4684c1
   (at your option) any later version.
Packit Service 4684c1
Packit Service 4684c1
   This program is distributed in the hope that it will be useful,
Packit Service 4684c1
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 4684c1
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 4684c1
   GNU Lesser General Public License for more details.
Packit Service 4684c1
Packit Service 4684c1
   You should have received a copy of the GNU Lesser General Public License
Packit Service 4684c1
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
Packit Service 4684c1
Packit Service 4684c1
/* Written by Paul Eggert.  */
Packit Service 4684c1
Packit Service 4684c1
#ifndef STAT_TIME_H
Packit Service 4684c1
#define STAT_TIME_H 1
Packit Service 4684c1
Packit Service 4684c1
#include "intprops.h"
Packit Service 4684c1
Packit Service 4684c1
#include <errno.h>
Packit Service 4684c1
#include <stddef.h>
Packit Service 4684c1
#include <sys/stat.h>
Packit Service 4684c1
#include <time.h>
Packit Service 4684c1
Packit Service 4684c1
#ifndef _GL_INLINE_HEADER_BEGIN
Packit Service 4684c1
 #error "Please include config.h first."
Packit Service 4684c1
#endif
Packit Service 4684c1
_GL_INLINE_HEADER_BEGIN
Packit Service 4684c1
#ifndef _GL_STAT_TIME_INLINE
Packit Service 4684c1
# define _GL_STAT_TIME_INLINE _GL_INLINE
Packit Service 4684c1
#endif
Packit Service 4684c1
Packit Service 4684c1
#ifdef __cplusplus
Packit Service 4684c1
extern "C" {
Packit Service 4684c1
#endif
Packit Service 4684c1
Packit Service 4684c1
/* STAT_TIMESPEC (ST, ST_XTIM) is the ST_XTIM member for *ST of type
Packit Service 4684c1
   struct timespec, if available.  If not, then STAT_TIMESPEC_NS (ST,
Packit Service 4684c1
   ST_XTIM) is the nanosecond component of the ST_XTIM member for *ST,
Packit Service 4684c1
   if available.  ST_XTIM can be st_atim, st_ctim, st_mtim, or st_birthtim
Packit Service 4684c1
   for access, status change, data modification, or birth (creation)
Packit Service 4684c1
   time respectively.
Packit Service 4684c1
Packit Service 4684c1
   These macros are private to stat-time.h.  */
Packit Service 4684c1
#if _GL_WINDOWS_STAT_TIMESPEC || defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
Packit Service 4684c1
# if _GL_WINDOWS_STAT_TIMESPEC || defined TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC
Packit Service 4684c1
#  define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim)
Packit Service 4684c1
# else
Packit Service 4684c1
#  define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec)
Packit Service 4684c1
# endif
Packit Service 4684c1
#elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
Packit Service 4684c1
# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec)
Packit Service 4684c1
#elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC
Packit Service 4684c1
# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec)
Packit Service 4684c1
#elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC
Packit Service 4684c1
# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.st__tim.tv_nsec)
Packit Service 4684c1
#endif
Packit Service 4684c1
Packit Service 4684c1
/* Return the nanosecond component of *ST's access time.  */
Packit Service 4684c1
_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE
Packit Service 4684c1
get_stat_atime_ns (struct stat const *st)
Packit Service 4684c1
{
Packit Service 4684c1
# if defined STAT_TIMESPEC
Packit Service 4684c1
  return STAT_TIMESPEC (st, st_atim).tv_nsec;
Packit Service 4684c1
# elif defined STAT_TIMESPEC_NS
Packit Service 4684c1
  return STAT_TIMESPEC_NS (st, st_atim);
Packit Service 4684c1
# else
Packit Service 4684c1
  return 0;
Packit Service 4684c1
# endif
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* Return the nanosecond component of *ST's status change time.  */
Packit Service 4684c1
_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE
Packit Service 4684c1
get_stat_ctime_ns (struct stat const *st)
Packit Service 4684c1
{
Packit Service 4684c1
# if defined STAT_TIMESPEC
Packit Service 4684c1
  return STAT_TIMESPEC (st, st_ctim).tv_nsec;
Packit Service 4684c1
# elif defined STAT_TIMESPEC_NS
Packit Service 4684c1
  return STAT_TIMESPEC_NS (st, st_ctim);
Packit Service 4684c1
# else
Packit Service 4684c1
  return 0;
Packit Service 4684c1
# endif
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* Return the nanosecond component of *ST's data modification time.  */
Packit Service 4684c1
_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE
Packit Service 4684c1
get_stat_mtime_ns (struct stat const *st)
Packit Service 4684c1
{
Packit Service 4684c1
# if defined STAT_TIMESPEC
Packit Service 4684c1
  return STAT_TIMESPEC (st, st_mtim).tv_nsec;
Packit Service 4684c1
# elif defined STAT_TIMESPEC_NS
Packit Service 4684c1
  return STAT_TIMESPEC_NS (st, st_mtim);
Packit Service 4684c1
# else
Packit Service 4684c1
  return 0;
Packit Service 4684c1
# endif
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* Return the nanosecond component of *ST's birth time.  */
Packit Service 4684c1
_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE
Packit Service 4684c1
get_stat_birthtime_ns (struct stat const *st _GL_UNUSED)
Packit Service 4684c1
{
Packit Service 4684c1
# if defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
Packit Service 4684c1
  return STAT_TIMESPEC (st, st_birthtim).tv_nsec;
Packit Service 4684c1
# elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
Packit Service 4684c1
  return STAT_TIMESPEC_NS (st, st_birthtim);
Packit Service 4684c1
# else
Packit Service 4684c1
  return 0;
Packit Service 4684c1
# endif
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* Return *ST's access time.  */
Packit Service 4684c1
_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE
Packit Service 4684c1
get_stat_atime (struct stat const *st)
Packit Service 4684c1
{
Packit Service 4684c1
#ifdef STAT_TIMESPEC
Packit Service 4684c1
  return STAT_TIMESPEC (st, st_atim);
Packit Service 4684c1
#else
Packit Service 4684c1
  struct timespec t;
Packit Service 4684c1
  t.tv_sec = st->st_atime;
Packit Service 4684c1
  t.tv_nsec = get_stat_atime_ns (st);
Packit Service 4684c1
  return t;
Packit Service 4684c1
#endif
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* Return *ST's status change time.  */
Packit Service 4684c1
_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE
Packit Service 4684c1
get_stat_ctime (struct stat const *st)
Packit Service 4684c1
{
Packit Service 4684c1
#ifdef STAT_TIMESPEC
Packit Service 4684c1
  return STAT_TIMESPEC (st, st_ctim);
Packit Service 4684c1
#else
Packit Service 4684c1
  struct timespec t;
Packit Service 4684c1
  t.tv_sec = st->st_ctime;
Packit Service 4684c1
  t.tv_nsec = get_stat_ctime_ns (st);
Packit Service 4684c1
  return t;
Packit Service 4684c1
#endif
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* Return *ST's data modification time.  */
Packit Service 4684c1
_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE
Packit Service 4684c1
get_stat_mtime (struct stat const *st)
Packit Service 4684c1
{
Packit Service 4684c1
#ifdef STAT_TIMESPEC
Packit Service 4684c1
  return STAT_TIMESPEC (st, st_mtim);
Packit Service 4684c1
#else
Packit Service 4684c1
  struct timespec t;
Packit Service 4684c1
  t.tv_sec = st->st_mtime;
Packit Service 4684c1
  t.tv_nsec = get_stat_mtime_ns (st);
Packit Service 4684c1
  return t;
Packit Service 4684c1
#endif
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* Return *ST's birth time, if available; otherwise return a value
Packit Service 4684c1
   with tv_sec and tv_nsec both equal to -1.  */
Packit Service 4684c1
_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE
Packit Service 4684c1
get_stat_birthtime (struct stat const *st _GL_UNUSED)
Packit Service 4684c1
{
Packit Service 4684c1
  struct timespec t;
Packit Service 4684c1
Packit Service 4684c1
#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
Packit Service 4684c1
     || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC)
Packit Service 4684c1
  t = STAT_TIMESPEC (st, st_birthtim);
Packit Service 4684c1
#elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
Packit Service 4684c1
  t.tv_sec = st->st_birthtime;
Packit Service 4684c1
  t.tv_nsec = st->st_birthtimensec;
Packit Service 4684c1
#elif defined _WIN32 && ! defined __CYGWIN__
Packit Service 4684c1
  /* Native Windows platforms (but not Cygwin) put the "file creation
Packit Service 4684c1
     time" in st_ctime (!).  See
Packit Service 4684c1
     <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/stat-functions>.  */
Packit Service 4684c1
# if _GL_WINDOWS_STAT_TIMESPEC
Packit Service 4684c1
  t = st->st_ctim;
Packit Service 4684c1
# else
Packit Service 4684c1
  t.tv_sec = st->st_ctime;
Packit Service 4684c1
  t.tv_nsec = 0;
Packit Service 4684c1
# endif
Packit Service 4684c1
#else
Packit Service 4684c1
  /* Birth time is not supported.  */
Packit Service 4684c1
  t.tv_sec = -1;
Packit Service 4684c1
  t.tv_nsec = -1;
Packit Service 4684c1
#endif
Packit Service 4684c1
Packit Service 4684c1
#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
Packit Service 4684c1
     || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC \
Packit Service 4684c1
     || defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
Packit Service 4684c1
  /* FreeBSD and NetBSD sometimes signal the absence of knowledge by
Packit Service 4684c1
     using zero.  Attempt to work around this problem.  Alas, this can
Packit Service 4684c1
     report failure even for valid timestamps.  Also, NetBSD
Packit Service 4684c1
     sometimes returns junk in the birth time fields; work around this
Packit Service 4684c1
     bug if it is detected.  */
Packit Service 4684c1
  if (! (t.tv_sec && 0 <= t.tv_nsec && t.tv_nsec < 1000000000))
Packit Service 4684c1
    {
Packit Service 4684c1
      t.tv_sec = -1;
Packit Service 4684c1
      t.tv_nsec = -1;
Packit Service 4684c1
    }
Packit Service 4684c1
#endif
Packit Service 4684c1
Packit Service 4684c1
  return t;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
/* If a stat-like function returned RESULT, normalize the timestamps
Packit Service 4684c1
   in *ST, in case this platform suffers from the Solaris 11 bug where
Packit Service 4684c1
   tv_nsec might be negative.  Return the adjusted RESULT, setting
Packit Service 4684c1
   errno to EOVERFLOW if normalization overflowed.  This function
Packit Service 4684c1
   is intended to be private to this .h file.  */
Packit Service 4684c1
_GL_STAT_TIME_INLINE int
Packit Service 4684c1
stat_time_normalize (int result, struct stat *st _GL_UNUSED)
Packit Service 4684c1
{
Packit Service 4684c1
#if defined __sun && defined STAT_TIMESPEC
Packit Service 4684c1
  if (result == 0)
Packit Service 4684c1
    {
Packit Service 4684c1
      long int timespec_hz = 1000000000;
Packit Service 4684c1
      short int const ts_off[] = { offsetof (struct stat, st_atim),
Packit Service 4684c1
                                   offsetof (struct stat, st_mtim),
Packit Service 4684c1
                                   offsetof (struct stat, st_ctim) };
Packit Service 4684c1
      int i;
Packit Service 4684c1
      for (i = 0; i < sizeof ts_off / sizeof *ts_off; i++)
Packit Service 4684c1
        {
Packit Service 4684c1
          struct timespec *ts = (struct timespec *) ((char *) st + ts_off[i]);
Packit Service 4684c1
          long int q = ts->tv_nsec / timespec_hz;
Packit Service 4684c1
          long int r = ts->tv_nsec % timespec_hz;
Packit Service 4684c1
          if (r < 0)
Packit Service 4684c1
            {
Packit Service 4684c1
              r += timespec_hz;
Packit Service 4684c1
              q--;
Packit Service 4684c1
            }
Packit Service 4684c1
          ts->tv_nsec = r;
Packit Service 4684c1
          /* Overflow is possible, as Solaris 11 stat can yield
Packit Service 4684c1
             tv_sec == TYPE_MINIMUM (time_t) && tv_nsec == -1000000000.
Packit Service 4684c1
             INT_ADD_WRAPV is OK, since time_t is signed on Solaris.  */
Packit Service 4684c1
          if (INT_ADD_WRAPV (q, ts->tv_sec, &ts->tv_sec))
Packit Service 4684c1
            {
Packit Service 4684c1
              errno = EOVERFLOW;
Packit Service 4684c1
              return -1;
Packit Service 4684c1
            }
Packit Service 4684c1
        }
Packit Service 4684c1
    }
Packit Service 4684c1
#endif
Packit Service 4684c1
  return result;
Packit Service 4684c1
}
Packit Service 4684c1
Packit Service 4684c1
#ifdef __cplusplus
Packit Service 4684c1
}
Packit Service 4684c1
#endif
Packit Service 4684c1
Packit Service 4684c1
_GL_INLINE_HEADER_END
Packit Service 4684c1
Packit Service 4684c1
#endif