tests: fix license on several tests
[gnulib.git] / tests / test-lutimens.h
1 /* Test of file timestamp modification functions.
2    Copyright (C) 2009 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 #include "test-utimens-common.h"
18
19 /* This file is designed to test both lutimens(a,b) and
20    utimensat(AT_FDCWD,a,b,AT_SYMLINK_NOFOLLOW).  FUNC is the function
21    to test.  Assumes that BASE and ASSERT are already defined.  If
22    PRINT, warn before skipping tests with status 77.  */
23 static int
24 test_lutimens (int (*func) (char const *, struct timespec const *), bool print)
25 {
26   int result;
27   int saved_errno;
28   struct stat st1;
29   struct stat st2;
30   bool atime_supported = true;
31
32   /* Non-symlinks should be handled just like utimens.  */
33   errno = 0;
34   ASSERT (func ("no_such", NULL) == -1);
35   ASSERT (errno == ENOENT);
36   errno = 0;
37   ASSERT (func ("no_such/", NULL) == -1);
38   ASSERT (errno == ENOENT || errno == ENOTDIR);
39   errno = 0;
40   ASSERT (func ("", NULL) == -1);
41   ASSERT (errno == ENOENT);
42   ASSERT (close (creat (BASE "file", 0600)) == 0);
43   ASSERT (stat (BASE "file", &st1) == 0);
44   ASSERT (st1.st_atime != Y2K);
45   ASSERT (st1.st_mtime != Y2K);
46   {
47     struct timespec ts[2] = { { Y2K, 0 }, { Y2K, 0 } };
48     errno = 0;
49     ASSERT (func (BASE "file/", ts) == -1);
50     ASSERT (errno == ENOTDIR);
51     ASSERT (stat (BASE "file", &st2) == 0);
52     ASSERT (st1.st_atime == st2.st_atime);
53     ASSERT (st1.st_mtime == st2.st_mtime);
54   }
55   {
56     struct timespec ts[2] = { { Y2K, 0 }, { Y2K, 0 } };
57     nap ();
58     ASSERT (func (BASE "file", ts) == 0);
59   }
60   ASSERT (stat (BASE "file", &st2) == 0);
61   ASSERT (st2.st_atime == Y2K);
62   ASSERT (st2.st_mtime == Y2K);
63   if (check_ctime)
64     ASSERT (st1.st_ctime < st2.st_ctime
65             || (st1.st_ctime == st2.st_ctime
66                 && get_stat_ctime_ns (&st1) < get_stat_ctime_ns (&st2)));
67
68   /* Play with symlink timestamps.  */
69   if (symlink (BASE "file", BASE "link"))
70     {
71       ASSERT (unlink (BASE "file") == 0);
72       if (print)
73         fputs ("skipping test: symlinks not supported on this file system\n",
74                stderr);
75       return 77;
76     }
77   errno = 0;
78   result = func (BASE "link", NULL);
79   saved_errno = errno;
80   /* Make sure we did not reference through link by accident.  */
81   ASSERT (stat (BASE "file", &st1) == 0);
82   ASSERT (st1.st_atime == Y2K);
83   ASSERT (st1.st_mtime == Y2K);
84   ASSERT (lstat (BASE "link", &st1) == 0);
85   ASSERT (st1.st_atime != Y2K);
86   ASSERT (st1.st_mtime != Y2K);
87   ASSERT (unlink (BASE "file") == 0);
88   if (result == -1 && saved_errno == ENOSYS)
89     {
90       ASSERT (unlink (BASE "link") == 0);
91       if (print)
92         fputs ("skipping test: "
93                "setting symlink time not supported on this file system\n",
94                stderr);
95       return 77;
96     }
97   ASSERT (!result);
98   ASSERT (lstat (BASE "link", &st1) == 0);
99   /* On cygwin, lstat() changes atime of symlinks, so that lutimens
100      can only effectively modify mtime.  */
101   nap ();
102   ASSERT (lstat (BASE "link", &st2) == 0);
103   if (st1.st_atime != st2.st_atime
104       || get_stat_atime_ns (&st1) != get_stat_atime_ns (&st2))
105     atime_supported = false;
106   ASSERT (st1.st_ctime == st2.st_ctime);
107   ASSERT (get_stat_ctime_ns (&st1) == get_stat_ctime_ns (&st2));
108
109   /* Invalid arguments.  */
110   {
111     struct timespec ts[2] = { { Y2K, UTIME_BOGUS_POS }, { Y2K, 0 } };
112     errno = 0;
113     ASSERT (func (BASE "link", ts) == -1);
114     ASSERT (errno == EINVAL);
115   }
116   {
117     struct timespec ts[2] = { { Y2K, 0 }, { Y2K, UTIME_BOGUS_NEG } };
118     errno = 0;
119     ASSERT (func (BASE "link", ts) == -1);
120     ASSERT (errno == EINVAL);
121   }
122   ASSERT (lstat (BASE "link", &st2) == 0);
123   if (atime_supported)
124     {
125       ASSERT (st1.st_atime == st2.st_atime);
126       ASSERT (get_stat_atime_ns (&st1) == get_stat_atime_ns (&st2));
127     }
128   ASSERT (utimecmp (BASE "link", &st1, &st2, 0) == 0);
129
130   /* Set both times.  */
131   {
132     struct timespec ts[2] = { { Y2K, BILLION / 2 - 1 }, { Y2K, BILLION - 1 } };
133     nap ();
134     ASSERT (func (BASE "link", ts) == 0);
135     ASSERT (lstat (BASE "link", &st2) == 0);
136     if (atime_supported)
137       {
138         ASSERT (st2.st_atime == Y2K);
139         ASSERT (0 <= get_stat_atime_ns (&st2));
140         ASSERT (get_stat_atime_ns (&st2) < BILLION / 2);
141       }
142     ASSERT (st2.st_mtime == Y2K);
143     ASSERT (0 <= get_stat_mtime_ns (&st2));
144     ASSERT (get_stat_mtime_ns (&st2) < BILLION);
145     if (check_ctime)
146       ASSERT (st1.st_ctime < st2.st_ctime
147               || (st1.st_ctime == st2.st_ctime
148                   && get_stat_ctime_ns (&st1) < get_stat_ctime_ns (&st2)));
149   }
150
151   /* Play with UTIME_OMIT, UTIME_NOW.  */
152   {
153     struct stat st3;
154     struct timespec ts[2] = { { BILLION, UTIME_OMIT }, { 0, UTIME_NOW } };
155     nap ();
156     ASSERT (func (BASE "link", ts) == 0);
157     ASSERT (lstat (BASE "link", &st3) == 0);
158     if (atime_supported)
159       {
160         ASSERT (st3.st_atime == Y2K);
161         ASSERT (0 <= get_stat_atime_ns (&st3));
162         ASSERT (get_stat_atime_ns (&st3) < BILLION / 2);
163       }
164     ASSERT (utimecmp (BASE "link", &st1, &st3, 0) <= 0);
165     if (check_ctime)
166       ASSERT (st2.st_ctime < st3.st_ctime
167               || (st2.st_ctime == st3.st_ctime
168                   && get_stat_ctime_ns (&st2) < get_stat_ctime_ns (&st3)));
169     nap ();
170     ts[0].tv_nsec = 0;
171     ts[1].tv_nsec = UTIME_OMIT;
172     ASSERT (func (BASE "link", ts) == 0);
173     ASSERT (lstat (BASE "link", &st2) == 0);
174     if (atime_supported)
175       {
176         ASSERT (st2.st_atime == BILLION);
177         ASSERT (get_stat_atime_ns (&st2) == 0);
178       }
179     ASSERT (st3.st_mtime == st2.st_mtime);
180     ASSERT (get_stat_mtime_ns (&st3) == get_stat_mtime_ns (&st2));
181     if (check_ctime)
182       ASSERT (st3.st_ctime < st2.st_ctime
183               || (st3.st_ctime == st2.st_ctime
184                   && get_stat_ctime_ns (&st3) < get_stat_ctime_ns (&st2)));
185   }
186
187   /* Symlink to directory.  */
188   ASSERT (unlink (BASE "link") == 0);
189   ASSERT (symlink (BASE "dir", BASE "link") == 0);
190   ASSERT (mkdir (BASE "dir", 0700) == 0);
191   {
192     struct timespec ts[2] = { { Y2K, 0 }, { Y2K, 0 } };
193     ASSERT (func (BASE "link/", ts) == 0);
194   }
195   /* On cygwin 1.5, stat() changes atime of directories, so only check
196      mtime.  */
197   ASSERT (stat (BASE "dir", &st1) == 0);
198   ASSERT (st1.st_mtime == Y2K);
199   ASSERT (lstat (BASE "link", &st1) == 0);
200   ASSERT (st1.st_atime != Y2K);
201   ASSERT (st1.st_mtime != Y2K);
202   ASSERT (func (BASE "link", NULL) == 0);
203   ASSERT (stat (BASE "dir", &st1) == 0);
204   ASSERT (st1.st_mtime == Y2K);
205   ASSERT (lstat (BASE "link", &st1) == 0);
206   ASSERT (st1.st_atime != Y2K);
207   ASSERT (st1.st_mtime != Y2K);
208
209   /* Cleanup.  */
210   ASSERT (rmdir (BASE "dir") == 0);
211   ASSERT (unlink (BASE "link") == 0);
212   return 0;
213 }