Change copyright notice from GPLv2+ to GPLv3+.
[gnulib.git] / tests / test-stat-time.c
1 /* Test of <stat-time.h>.
2    Copyright (C) 2007 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 /* Written by James Youngman <jay@gnu.org>, 2007.  */
18
19 #include <config.h>
20
21 #include "stat-time.h"
22
23 #include <fcntl.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29
30 #define ASSERT(expr) \
31   do                                                                         \
32     {                                                                        \
33       if (!(expr))                                                           \
34         {                                                                    \
35           fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
36           abort ();                                                          \
37         }                                                                    \
38     }                                                                        \
39   while (0)
40
41 enum { NFILES = 4 };
42
43 static void
44 cleanup (int sig)
45 {
46   /* Remove temporary files.  */
47   unlink ("t-stt-stamp1");
48   unlink ("t-stt-testfile");
49   unlink ("t-stt-stamp2");
50   unlink ("t-stt-renamed");
51   unlink ("t-stt-stamp3");
52
53   if (sig != 0)
54     _exit (1);
55 }
56
57 static int
58 open_file (const char *filename, int flags)
59 {
60   int fd = open (filename, flags | O_WRONLY, 0500);
61   if (fd >= 0)
62     {
63       close (fd);
64       return 1;
65     }
66   else
67     {
68       return 0;
69     }
70 }
71
72 static void
73 create_file (const char *filename)
74 {
75   ASSERT (open_file (filename, O_CREAT | O_EXCL));
76 }
77
78 static void
79 do_stat (const char *filename, struct stat *p)
80 {
81   ASSERT (stat (filename, p) == 0);
82 }
83
84 static void
85 prepare_test (struct stat *statinfo, struct timespec *modtimes)
86 {
87   int i;
88
89   create_file ("t-stt-stamp1");
90   sleep (2);
91   create_file ("t-stt-testfile");
92   sleep (2);
93   create_file ("t-stt-stamp2");
94   sleep (2);
95   ASSERT (chmod ("t-stt-testfile", 0400) == 0);
96   sleep (2);
97   create_file ("t-stt-stamp3");
98
99   do_stat ("t-stt-stamp1",  &statinfo[0]);
100   do_stat ("t-stt-testfile", &statinfo[1]);
101   do_stat ("t-stt-stamp2",  &statinfo[2]);
102   do_stat ("t-stt-stamp3",  &statinfo[3]);
103
104   /* Now use our access functions. */
105   for (i = 0; i < NFILES; ++i)
106     {
107       modtimes[i] = get_stat_mtime (&statinfo[i]);
108     }
109 }
110
111 static void
112 test_mtime (const struct stat *statinfo, struct timespec *modtimes)
113 {
114   int i;
115
116   /* Use the struct stat fields directly. */
117   ASSERT (statinfo[0].st_mtime < statinfo[2].st_mtime); /* mtime(stamp1) < mtime(stamp2) */
118   ASSERT (statinfo[2].st_mtime < statinfo[3].st_mtime); /* mtime(stamp2) < mtime(stamp3) */
119   ASSERT (statinfo[2].st_mtime < statinfo[1].st_ctime); /* mtime(stamp2) < ctime(renamed) */
120
121   /* Now check the result of the access functions. */
122   ASSERT (modtimes[0].tv_sec < modtimes[2].tv_sec); /* mtime(stamp1) < mtime(stamp2) */
123   ASSERT (modtimes[2].tv_sec < modtimes[3].tv_sec); /* mtime(stamp2) < mtime(stamp3) */
124
125   /* verify equivalence */
126   for (i = 0; i < NFILES; ++i)
127     {
128       struct timespec ts;
129       ts = get_stat_mtime (&statinfo[i]);
130       ASSERT (ts.tv_sec == statinfo[i].st_mtime);
131     }
132
133   ASSERT (statinfo[2].st_mtime < statinfo[1].st_ctime); /* mtime(stamp2) < ctime(renamed) */
134 }
135
136 static void
137 test_birthtime (const struct stat *statinfo,
138                 const struct timespec *modtimes,
139                 struct timespec *birthtimes)
140 {
141   int i;
142
143   /* Collect the birth times.. */
144   for (i = 0; i < NFILES; ++i)
145     {
146       birthtimes[i] = get_stat_birthtime (&statinfo[i]);
147       if (birthtimes[i].tv_nsec < 0)
148         return;
149     }
150
151   ASSERT (modtimes[0].tv_sec < birthtimes[1].tv_sec); /* mtime(stamp1) < birthtime(renamed) */
152   ASSERT (birthtimes[1].tv_sec < modtimes[2].tv_sec); /* birthtime(renamed) < mtime(stamp2) */
153 }
154
155 int
156 main ()
157 {
158   struct stat statinfo[NFILES];
159   struct timespec modtimes[NFILES];
160   struct timespec birthtimes[NFILES];
161
162 #ifdef SIGHUP
163   signal (SIGHUP, cleanup);
164 #endif
165 #ifdef SIGINT
166   signal (SIGINT, cleanup);
167 #endif
168 #ifdef SIGQUIT
169   signal (SIGQUIT, cleanup);
170 #endif
171 #ifdef SIGTERM
172   signal (SIGTERM, cleanup);
173 #endif
174
175   cleanup (0);
176   prepare_test (statinfo, modtimes);
177   test_mtime (statinfo, modtimes);
178   test_birthtime (statinfo, modtimes, birthtimes);
179
180   cleanup (0);
181   return 0;
182 }