stat-time.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /* stat-related time functions.
  2. Copyright (C) 2005, 2007, 2009-2011 Free Software Foundation, Inc.
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  13. /* Written by Paul Eggert. */
  14. #ifndef STAT_TIME_H
  15. #define STAT_TIME_H 1
  16. #include <sys/stat.h>
  17. #include <time.h>
  18. /* STAT_TIMESPEC (ST, ST_XTIM) is the ST_XTIM member for *ST of type
  19. struct timespec, if available. If not, then STAT_TIMESPEC_NS (ST,
  20. ST_XTIM) is the nanosecond component of the ST_XTIM member for *ST,
  21. if available. ST_XTIM can be st_atim, st_ctim, st_mtim, or st_birthtim
  22. for access, status change, data modification, or birth (creation)
  23. time respectively.
  24. These macros are private to stat-time.h. */
  25. #if defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
  26. # ifdef TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC
  27. # define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim)
  28. # else
  29. # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec)
  30. # endif
  31. #elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
  32. # define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec)
  33. #elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC
  34. # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec)
  35. #elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC
  36. # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.st__tim.tv_nsec)
  37. #endif
  38. /* Return the nanosecond component of *ST's access time. */
  39. static inline long int
  40. get_stat_atime_ns (struct stat const *st)
  41. {
  42. # if defined STAT_TIMESPEC
  43. return STAT_TIMESPEC (st, st_atim).tv_nsec;
  44. # elif defined STAT_TIMESPEC_NS
  45. return STAT_TIMESPEC_NS (st, st_atim);
  46. # else
  47. return 0;
  48. # endif
  49. }
  50. /* Return the nanosecond component of *ST's status change time. */
  51. static inline long int
  52. get_stat_ctime_ns (struct stat const *st)
  53. {
  54. # if defined STAT_TIMESPEC
  55. return STAT_TIMESPEC (st, st_ctim).tv_nsec;
  56. # elif defined STAT_TIMESPEC_NS
  57. return STAT_TIMESPEC_NS (st, st_ctim);
  58. # else
  59. return 0;
  60. # endif
  61. }
  62. /* Return the nanosecond component of *ST's data modification time. */
  63. static inline long int
  64. get_stat_mtime_ns (struct stat const *st)
  65. {
  66. # if defined STAT_TIMESPEC
  67. return STAT_TIMESPEC (st, st_mtim).tv_nsec;
  68. # elif defined STAT_TIMESPEC_NS
  69. return STAT_TIMESPEC_NS (st, st_mtim);
  70. # else
  71. return 0;
  72. # endif
  73. }
  74. /* Return the nanosecond component of *ST's birth time. */
  75. static inline long int
  76. get_stat_birthtime_ns (struct stat const *st)
  77. {
  78. # if defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
  79. return STAT_TIMESPEC (st, st_birthtim).tv_nsec;
  80. # elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
  81. return STAT_TIMESPEC_NS (st, st_birthtim);
  82. # else
  83. /* Avoid a "parameter unused" warning. */
  84. (void) st;
  85. return 0;
  86. # endif
  87. }
  88. /* Return *ST's access time. */
  89. static inline struct timespec
  90. get_stat_atime (struct stat const *st)
  91. {
  92. #ifdef STAT_TIMESPEC
  93. return STAT_TIMESPEC (st, st_atim);
  94. #else
  95. struct timespec t;
  96. t.tv_sec = st->st_atime;
  97. t.tv_nsec = get_stat_atime_ns (st);
  98. return t;
  99. #endif
  100. }
  101. /* Return *ST's status change time. */
  102. static inline struct timespec
  103. get_stat_ctime (struct stat const *st)
  104. {
  105. #ifdef STAT_TIMESPEC
  106. return STAT_TIMESPEC (st, st_ctim);
  107. #else
  108. struct timespec t;
  109. t.tv_sec = st->st_ctime;
  110. t.tv_nsec = get_stat_ctime_ns (st);
  111. return t;
  112. #endif
  113. }
  114. /* Return *ST's data modification time. */
  115. static inline struct timespec
  116. get_stat_mtime (struct stat const *st)
  117. {
  118. #ifdef STAT_TIMESPEC
  119. return STAT_TIMESPEC (st, st_mtim);
  120. #else
  121. struct timespec t;
  122. t.tv_sec = st->st_mtime;
  123. t.tv_nsec = get_stat_mtime_ns (st);
  124. return t;
  125. #endif
  126. }
  127. /* Return *ST's birth time, if available; otherwise return a value
  128. with negative tv_nsec. */
  129. static inline struct timespec
  130. get_stat_birthtime (struct stat const *st)
  131. {
  132. struct timespec t;
  133. #if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
  134. || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC)
  135. t = STAT_TIMESPEC (st, st_birthtim);
  136. #elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
  137. t.tv_sec = st->st_birthtime;
  138. t.tv_nsec = st->st_birthtimensec;
  139. #elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
  140. /* Woe32 native platforms (but not Cygwin) put the "file creation
  141. time" in st_ctime (!). See
  142. <http://msdn2.microsoft.com/de-de/library/14h5k7ff(VS.80).aspx>. */
  143. t.tv_sec = st->st_ctime;
  144. t.tv_nsec = 0;
  145. #else
  146. /* Birth time is not supported. Set tv_sec to avoid undefined behavior. */
  147. t.tv_sec = -1;
  148. t.tv_nsec = -1;
  149. /* Avoid a "parameter unused" warning. */
  150. (void) st;
  151. #endif
  152. #if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
  153. || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC \
  154. || defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
  155. /* FreeBSD and NetBSD sometimes signal the absence of knowledge by
  156. using zero. Attempt to work around this problem. Alas, this can
  157. report failure even for valid time stamps. Also, NetBSD
  158. sometimes returns junk in the birth time fields; work around this
  159. bug if it is detected. There's no need to detect negative
  160. tv_nsec junk as negative tv_nsec already indicates an error. */
  161. if (t.tv_sec == 0 || 1000000000 <= t.tv_nsec)
  162. t.tv_nsec = -1;
  163. #endif
  164. return t;
  165. }
  166. #endif