Blame lib/stat-time.h

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