Line data Source code
1 : /* stat-related time functions.
2 :
3 : Copyright (C) 2005, 2007 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 <http://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 <sys/stat.h>
24 : #include <time.h>
25 :
26 : /* STAT_TIMESPEC (ST, ST_XTIM) is the ST_XTIM member for *ST of type
27 : struct timespec, if available. If not, then STAT_TIMESPEC_NS (ST,
28 : ST_XTIM) is the nanosecond component of the ST_XTIM member for *ST,
29 : if available. ST_XTIM can be st_atim, st_ctim, st_mtim, or st_birthtim
30 : for access, status change, data modification, or birth (creation)
31 : time respectively.
32 :
33 : These macros are private to stat-time.h. */
34 : #if defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
35 : # ifdef TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC
36 : # define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim)
37 : # else
38 : # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec)
39 : # endif
40 : #elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
41 : # define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec)
42 : #elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC
43 : # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec)
44 : #elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC
45 : # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.st__tim.tv_nsec)
46 : #endif
47 :
48 : /* Return the nanosecond component of *ST's access time. */
49 : static inline long int
50 0 : get_stat_atime_ns (struct stat const *st)
51 : {
52 : # if defined STAT_TIMESPEC
53 0 : return STAT_TIMESPEC (st, st_atim).tv_nsec;
54 : # elif defined STAT_TIMESPEC_NS
55 : return STAT_TIMESPEC_NS (st, st_atim);
56 : # else
57 : return 0;
58 : # endif
59 : }
60 :
61 : /* Return the nanosecond component of *ST's status change time. */
62 : static inline long int
63 0 : get_stat_ctime_ns (struct stat const *st)
64 : {
65 : # if defined STAT_TIMESPEC
66 0 : return STAT_TIMESPEC (st, st_ctim).tv_nsec;
67 : # elif defined STAT_TIMESPEC_NS
68 : return STAT_TIMESPEC_NS (st, st_ctim);
69 : # else
70 : return 0;
71 : # endif
72 : }
73 :
74 : /* Return the nanosecond component of *ST's data modification time. */
75 : static inline long int
76 10 : get_stat_mtime_ns (struct stat const *st)
77 : {
78 : # if defined STAT_TIMESPEC
79 10 : return STAT_TIMESPEC (st, st_mtim).tv_nsec;
80 : # elif defined STAT_TIMESPEC_NS
81 : return STAT_TIMESPEC_NS (st, st_mtim);
82 : # else
83 : return 0;
84 : # endif
85 : }
86 :
87 : /* Return the nanosecond component of *ST's birth time. */
88 : static inline long int
89 : get_stat_birthtime_ns (struct stat const *st)
90 : {
91 : # if defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
92 : return STAT_TIMESPEC (st, st_birthtim).tv_nsec;
93 : # elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
94 : return STAT_TIMESPEC_NS (st, st_birthtim);
95 : # else
96 : /* Avoid a "parameter unused" warning. */
97 : (void) st;
98 : return 0;
99 : # endif
100 : }
101 :
102 : /* Return *ST's access time. */
103 : static inline struct timespec
104 41 : get_stat_atime (struct stat const *st)
105 : {
106 : #ifdef STAT_TIMESPEC
107 41 : return STAT_TIMESPEC (st, st_atim);
108 : #else
109 : struct timespec t;
110 : t.tv_sec = st->st_atime;
111 : t.tv_nsec = get_stat_atime_ns (st);
112 : return t;
113 : #endif
114 : }
115 :
116 : /* Return *ST's status change time. */
117 : static inline struct timespec
118 36 : get_stat_ctime (struct stat const *st)
119 : {
120 : #ifdef STAT_TIMESPEC
121 36 : return STAT_TIMESPEC (st, st_ctim);
122 : #else
123 : struct timespec t;
124 : t.tv_sec = st->st_ctime;
125 : t.tv_nsec = get_stat_ctime_ns (st);
126 : return t;
127 : #endif
128 : }
129 :
130 : /* Return *ST's data modification time. */
131 : static inline struct timespec
132 409736 : get_stat_mtime (struct stat const *st)
133 : {
134 : #ifdef STAT_TIMESPEC
135 409736 : return STAT_TIMESPEC (st, st_mtim);
136 : #else
137 : struct timespec t;
138 : t.tv_sec = st->st_mtime;
139 : t.tv_nsec = get_stat_mtime_ns (st);
140 : return t;
141 : #endif
142 : }
143 :
144 : /* Return *ST's birth time, if available; otherwise return a value
145 : with negative tv_nsec. */
146 : static inline struct timespec
147 : get_stat_birthtime (struct stat const *st)
148 : {
149 : struct timespec t;
150 :
151 : #if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
152 : || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC)
153 : t = STAT_TIMESPEC (st, st_birthtim);
154 : #elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
155 : t.tv_sec = st->st_birthtime;
156 : t.tv_nsec = st->st_birthtimensec;
157 : #elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
158 : /* Woe32 native platforms (but not Cygwin) put the "file creation
159 : time" in st_ctime (!). See
160 : <http://msdn2.microsoft.com/de-de/library/14h5k7ff(VS.80).aspx>. */
161 : t.tv_sec = st->st_ctime;
162 : t.tv_nsec = 0;
163 : #else
164 : /* Birth time is not supported. Set tv_sec to avoid undefined behavior. */
165 : t.tv_sec = -1;
166 : t.tv_nsec = -1;
167 : /* Avoid a "parameter unused" warning. */
168 : (void) st;
169 : #endif
170 :
171 : #if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
172 : || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC \
173 : || defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
174 : /* FreeBSD and NetBSD sometimes signal the absence of knowledge by
175 : using zero. Attempt to work around this problem. Alas, this can
176 : report failure even for valid time stamps. Also, NetBSD
177 : sometimes returns junk in the birth time fields; work around this
178 : bug if it it is detected. There's no need to detect negative
179 : tv_nsec junk as negative tv_nsec already indicates an error. */
180 : if (t.tv_sec == 0 || 1000000000 <= t.tv_nsec)
181 : t.tv_nsec = -1;
182 : #endif
183 :
184 : return t;
185 : }
186 :
187 : #endif
|