Blame gnulib/lib/stat-time.h

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