tests: fix license on several tests
[gnulib.git] / tests / test-rename.h
1 /* Test of rename() function.
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 /* This file is designed to test both rename(a,b) and
18    renameat(AT_FDCWD,a,AT_FDCWD,b).  FUNC is the function to test.
19    Assumes that BASE and ASSERT are already defined, and that
20    appropriate headers are already included.  If PRINT, warn before
21    skipping symlink tests with status 77.  */
22
23 static int
24 test_rename (int (*func) (char const *, char const *), bool print)
25 {
26   /* Setup.  */
27   struct stat st;
28   int fd = creat (BASE "file", 0600);
29   ASSERT (0 <= fd);
30   ASSERT (write (fd, "hi", 2) == 2);
31   ASSERT (close (fd) == 0);
32   ASSERT (mkdir (BASE "dir", 0700) == 0);
33
34   /* Obvious errors.  */
35
36   errno = 0; /* Missing source.  */
37   ASSERT (func (BASE "missing", BASE "missing") == -1);
38   ASSERT (errno == ENOENT);
39   errno = 0;
40   ASSERT (func (BASE "missing/", BASE "missing") == -1);
41   ASSERT (errno == ENOENT);
42   errno = 0;
43   ASSERT (func (BASE "missing", BASE "missing/") == -1);
44   ASSERT (errno == ENOENT);
45   errno = 0; /* Empty operand.  */
46   ASSERT (func ("", BASE "missing") == -1);
47   ASSERT (errno == ENOENT);
48   errno = 0;
49   ASSERT (func (BASE "file", "") == -1);
50   ASSERT (errno == ENOENT);
51   errno = 0;
52   ASSERT (func (BASE "", "") == -1);
53   ASSERT (errno == ENOENT);
54
55   /* Files.  */
56   errno = 0; /* Trailing slash.  */
57   ASSERT (func (BASE "file", BASE "file2/") == -1);
58   ASSERT (errno == ENOENT || errno == ENOTDIR);
59   errno = 0;
60   ASSERT (func (BASE "file/", BASE "file2") == -1);
61   ASSERT (errno == ENOTDIR);
62   errno = 0;
63   ASSERT (stat (BASE "file2", &st) == -1);
64   ASSERT (errno == ENOENT);
65   ASSERT (func (BASE "file", BASE "file2") == 0); /* Simple rename.  */
66   errno = 0;
67   ASSERT (stat (BASE "file", &st) == -1);
68   ASSERT (errno == ENOENT);
69   memset (&st, 0, sizeof st);
70   ASSERT (stat (BASE "file2", &st) == 0);
71   ASSERT (st.st_size == 2);
72   ASSERT (close (creat (BASE "file", 0600)) == 0); /* Overwrite.  */
73   errno = 0;
74   ASSERT (func (BASE "file2", BASE "file/") == -1);
75   ASSERT (errno == ENOTDIR);
76   ASSERT (func (BASE "file2", BASE "file") == 0);
77   memset (&st, 0, sizeof st);
78   ASSERT (stat (BASE "file", &st) == 0);
79   ASSERT (st.st_size == 2);
80   errno = 0;
81   ASSERT (stat (BASE "file2", &st) == -1);
82   ASSERT (errno == ENOENT);
83
84   /* Directories.  */
85   ASSERT (func (BASE "dir", BASE "dir2/") == 0); /* Simple rename.  */
86   errno = 0;
87   ASSERT (stat (BASE "dir", &st) == -1);
88   ASSERT (errno == ENOENT);
89   ASSERT (stat (BASE "dir2", &st) == 0);
90   ASSERT (func (BASE "dir2/", BASE "dir") == 0);
91   ASSERT (stat (BASE "dir", &st) == 0);
92   errno = 0;
93   ASSERT (stat (BASE "dir2", &st) == -1);
94   ASSERT (errno == ENOENT);
95   ASSERT (func (BASE "dir", BASE "dir2") == 0);
96   errno = 0;
97   ASSERT (stat (BASE "dir", &st) == -1);
98   ASSERT (errno == ENOENT);
99   ASSERT (stat (BASE "dir2", &st) == 0);
100   ASSERT (mkdir (BASE "dir", 0700) == 0); /* Empty onto empty.  */
101   ASSERT (func (BASE "dir2", BASE "dir") == 0);
102   ASSERT (mkdir (BASE "dir2", 0700) == 0);
103   ASSERT (func (BASE "dir2", BASE "dir/") == 0);
104   ASSERT (mkdir (BASE "dir2", 0700) == 0);
105   ASSERT (func (BASE "dir2/", BASE "dir") == 0);
106   ASSERT (mkdir (BASE "dir2", 0700) == 0);
107   ASSERT (close (creat (BASE "dir/file", 0600)) == 0); /* Empty onto full.  */
108   errno = 0;
109   ASSERT (func (BASE "dir2", BASE "dir") == -1);
110   ASSERT (errno == EEXIST || errno == ENOTEMPTY);
111   errno = 0;
112   ASSERT (func (BASE "dir2/", BASE "dir") == -1);
113   ASSERT (errno == EEXIST || errno == ENOTEMPTY);
114   errno = 0;
115   ASSERT (func (BASE "dir2", BASE "dir/") == -1);
116   ASSERT (errno == EEXIST || errno == ENOTEMPTY);
117   ASSERT (func (BASE "dir", BASE "dir2") == 0); /* Full onto empty.  */
118   errno = 0;
119   ASSERT (stat (BASE "dir", &st) == -1);
120   ASSERT (errno == ENOENT);
121   ASSERT (stat (BASE "dir2/file", &st) == 0);
122   ASSERT (mkdir (BASE "dir", 0700) == 0);
123   ASSERT (func (BASE "dir2/", BASE "dir") == 0);
124   ASSERT (stat (BASE "dir/file", &st) == 0);
125   errno = 0;
126   ASSERT (stat (BASE "dir2", &st) == -1);
127   ASSERT (errno == ENOENT);
128   ASSERT (mkdir (BASE "dir2", 0700) == 0);
129   ASSERT (func (BASE "dir", BASE "dir2/") == 0);
130   errno = 0;
131   ASSERT (stat (BASE "dir", &st) == -1);
132   ASSERT (errno == ENOENT);
133   ASSERT (stat (BASE "dir2/file", &st) == 0);
134   ASSERT (unlink (BASE "dir2/file") == 0);
135   errno = 0; /* Reject trailing dot.  */
136   ASSERT (func (BASE "dir2", BASE "dir/.") == -1);
137   ASSERT (errno == EINVAL || errno == ENOENT);
138   ASSERT (mkdir (BASE "dir", 0700) == 0);
139   errno = 0;
140   ASSERT (func (BASE "dir2", BASE "dir/.") == -1);
141   ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR
142           || errno == ENOTEMPTY);
143   errno = 0;
144   ASSERT (func (BASE "dir2/.", BASE "dir") == -1);
145   ASSERT (errno == EINVAL || errno == EBUSY);
146   ASSERT (rmdir (BASE "dir") == 0);
147   errno = 0;
148   ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
149   ASSERT (errno == EINVAL || errno == ENOENT);
150   ASSERT (mkdir (BASE "dir", 0700) == 0);
151   errno = 0;
152   ASSERT (func (BASE "dir2", BASE "dir/.//") == -1);
153   ASSERT (errno == EINVAL || errno == EBUSY || errno == EISDIR
154           || errno == ENOTEMPTY);
155   errno = 0;
156   ASSERT (func (BASE "dir2/.//", BASE "dir") == -1);
157   ASSERT (errno == EINVAL || errno == EBUSY);
158   ASSERT (rmdir (BASE "dir2") == 0);
159   errno = 0; /* Move into subdir.  */
160   ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
161   ASSERT (errno == EINVAL || errno == EACCES);
162   errno = 0;
163   ASSERT (stat (BASE "dir/sub", &st) == -1);
164   ASSERT (errno == ENOENT);
165   ASSERT (mkdir (BASE "dir/sub", 0700) == 0);
166   errno = 0;
167   ASSERT (func (BASE "dir", BASE "dir/sub") == -1);
168   ASSERT (errno == EINVAL);
169   ASSERT (stat (BASE "dir/sub", &st) == 0);
170   ASSERT (rmdir (BASE "dir/sub") == 0);
171
172   /* Mixing file and directory.  */
173   errno = 0; /* File onto dir.  */
174   ASSERT (func (BASE "file", BASE "dir") == -1);
175   ASSERT (errno == EISDIR || errno == ENOTDIR);
176   errno = 0;
177   ASSERT (func (BASE "file", BASE "dir/") == -1);
178   ASSERT (errno == EISDIR || errno == ENOTDIR);
179   errno = 0; /* Dir onto file.  */
180   ASSERT (func (BASE "dir", BASE "file") == -1);
181   ASSERT (errno == ENOTDIR);
182   errno = 0;
183   ASSERT (func (BASE "dir/", BASE "file") == -1);
184   ASSERT (errno == ENOTDIR);
185
186   /* Hard links.  */
187   ASSERT (func (BASE "file", BASE "file") == 0); /* File onto self.  */
188   memset (&st, 0, sizeof st);
189   ASSERT (stat (BASE "file", &st) == 0);
190   ASSERT (st.st_size == 2);
191   ASSERT (func (BASE "dir", BASE "dir") == 0); /* Empty dir onto self.  */
192   ASSERT (stat (BASE "dir", &st) == 0);
193   ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
194   ASSERT (func (BASE "dir", BASE "dir") == 0); /* Full dir onto self.  */
195   ASSERT (unlink (BASE "dir/file") == 0);
196   {
197     /*  Not all file systems support link.  Mingw doesn't have
198         reliable st_nlink on hard links, but our implementation does
199         fail with EPERM on poor file systems, and we can detect the
200         inferior stat() via st_ino.  Cygwin 1.5.x copies rather than
201         links files on those file systems, but there, st_nlink and
202         st_ino are reliable.  */
203     int ret = link (BASE "file", BASE "file2");
204     if (!ret)
205       {
206         memset (&st, 0, sizeof st);
207         ASSERT (stat (BASE "file2", &st) == 0);
208         if (st.st_ino && st.st_nlink != 2)
209           {
210             ASSERT (unlink (BASE "file2") == 0);
211             errno = EPERM;
212             ret = -1;
213           }
214       }
215     if (ret == -1)
216       {
217         /* If the device does not support hard links, errno is
218            EPERM on Linux, EOPNOTSUPP on FreeBSD.  */
219         switch (errno)
220           {
221           case EPERM:
222           case EOPNOTSUPP:
223             if (print)
224               fputs ("skipping test: "
225                      "hard links not supported on this file system\n",
226                      stderr);
227             ASSERT (unlink (BASE "file") == 0);
228             ASSERT (rmdir (BASE "dir") == 0);
229             return 77;
230           default:
231             perror ("link");
232             return 1;
233           }
234       }
235     ASSERT (ret == 0);
236   }
237   ASSERT (func (BASE "file", BASE "file2") == 0); /* File onto hard link.  */
238   memset (&st, 0, sizeof st);
239   ASSERT (stat (BASE "file", &st) == 0);
240   ASSERT (st.st_size == 2);
241   memset (&st, 0, sizeof st);
242   ASSERT (stat (BASE "file2", &st) == 0);
243   ASSERT (st.st_size == 2);
244   ASSERT (unlink (BASE "file2") == 0);
245
246   /* Symlinks.  */
247   if (symlink (BASE "file", BASE "link1"))
248     {
249       if (print)
250         fputs ("skipping test: symlinks not supported on this file system\n",
251                stderr);
252       ASSERT (unlink (BASE "file") == 0);
253       ASSERT (rmdir (BASE "dir") == 0);
254       return 77;
255     }
256   ASSERT (func (BASE "link1", BASE "link2") == 0); /* Simple rename.  */
257   ASSERT (stat (BASE "file", &st) == 0);
258   errno = 0;
259   ASSERT (lstat (BASE "link1", &st) == -1);
260   ASSERT (errno == ENOENT);
261   memset (&st, 0, sizeof st);
262   ASSERT (lstat (BASE "link2", &st) == 0);
263   ASSERT (S_ISLNK (st.st_mode));
264   ASSERT (symlink (BASE "nowhere", BASE "link1") == 0); /* Overwrite.  */
265   ASSERT (func (BASE "link2", BASE "link1") == 0);
266   memset (&st, 0, sizeof st);
267   ASSERT (stat (BASE "link1", &st) == 0);
268   ASSERT (st.st_size == 2);
269   errno = 0;
270   ASSERT (lstat (BASE "link2", &st) == -1);
271   ASSERT (errno == ENOENT);
272   ASSERT (symlink (BASE "link2", BASE "link2") == 0); /* Symlink loop.  */
273   ASSERT (func (BASE "link2", BASE "link2") == 0);
274   errno = 0;
275   ASSERT (func (BASE "link2/", BASE "link2") == -1);
276   ASSERT (errno == ELOOP || errno == ENOTDIR);
277   ASSERT (func (BASE "link2", BASE "link3") == 0);
278   ASSERT (unlink (BASE "link3") == 0);
279   ASSERT (symlink (BASE "nowhere", BASE "link2") == 0); /* Dangling link.  */
280   ASSERT (func (BASE "link2", BASE "link3") == 0);
281   errno = 0;
282   ASSERT (lstat (BASE "link2", &st) == -1);
283   ASSERT (errno == ENOENT);
284   memset (&st, 0, sizeof st);
285   ASSERT (lstat (BASE "link3", &st) == 0);
286   errno = 0; /* Trailing slash on dangling.  */
287   ASSERT (func (BASE "link3/", BASE "link2") == -1);
288   ASSERT (errno == ENOENT || errno == ENOTDIR);
289   errno = 0;
290   ASSERT (func (BASE "link3", BASE "link2/") == -1);
291   ASSERT (errno == ENOENT || errno == ENOTDIR);
292   errno = 0;
293   ASSERT (lstat (BASE "link2", &st) == -1);
294   ASSERT (errno == ENOENT);
295   memset (&st, 0, sizeof st);
296   ASSERT (lstat (BASE "link3", &st) == 0);
297   errno = 0; /* Trailing slash on link to file.  */
298   ASSERT (func (BASE "link1/", BASE "link2") == -1);
299   ASSERT (errno == ENOTDIR);
300   errno = 0;
301   ASSERT (func (BASE "link1", BASE "link3/") == -1);
302   ASSERT (errno == ENOENT || errno == ENOTDIR);
303
304   /* Mixing symlink and file.  */
305   ASSERT (close (creat (BASE "file2", 0600)) == 0); /* File onto link.  */
306   ASSERT (func (BASE "file2", BASE "link3") == 0);
307   errno = 0;
308   ASSERT (stat (BASE "file2", &st) == -1);
309   ASSERT (errno == ENOENT);
310   memset (&st, 0, sizeof st);
311   ASSERT (lstat (BASE "link3", &st) == 0);
312   ASSERT (S_ISREG (st.st_mode));
313   ASSERT (unlink (BASE "link3") == 0);
314   ASSERT (symlink (BASE "nowhere", BASE "link2") == 0); /* Link onto file.  */
315   ASSERT (close (creat (BASE "file2", 0600)) == 0);
316   ASSERT (func (BASE "link2", BASE "file2") == 0);
317   errno = 0;
318   ASSERT (lstat (BASE "link2", &st) == -1);
319   ASSERT (errno == ENOENT);
320   memset (&st, 0, sizeof st);
321   ASSERT (lstat (BASE "file2", &st) == 0);
322   ASSERT (S_ISLNK (st.st_mode));
323   ASSERT (unlink (BASE "file2") == 0);
324   errno = 0; /* Trailing slash.  */
325   ASSERT (func (BASE "file/", BASE "link1") == -1);
326   ASSERT (errno == ENOTDIR);
327   errno = 0;
328   ASSERT (func (BASE "file", BASE "link1/") == -1);
329   ASSERT (errno == ENOTDIR || errno == ENOENT);
330   errno = 0;
331   ASSERT (func (BASE "link1/", BASE "file") == -1);
332   ASSERT (errno == ENOTDIR);
333   errno = 0;
334   ASSERT (func (BASE "link1", BASE "file/") == -1);
335   ASSERT (errno == ENOTDIR || errno == ENOENT);
336   memset (&st, 0, sizeof st);
337   ASSERT (lstat (BASE "file", &st) == 0);
338   ASSERT (S_ISREG (st.st_mode));
339   memset (&st, 0, sizeof st);
340   ASSERT (lstat (BASE "link1", &st) == 0);
341   ASSERT (S_ISLNK (st.st_mode));
342
343   /* Mixing symlink and directory.  */
344   errno = 0; /* Directory onto link.  */
345   ASSERT (func (BASE "dir", BASE "link1") == -1);
346   ASSERT (errno == ENOTDIR);
347   errno = 0;
348   ASSERT (func (BASE "dir/", BASE "link1") == -1);
349   ASSERT (errno == ENOTDIR);
350   errno = 0;
351   ASSERT (func (BASE "dir", BASE "link1/") == -1);
352   ASSERT (errno == ENOTDIR);
353   errno = 0; /* Link onto directory.  */
354   ASSERT (func (BASE "link1", BASE "dir") == -1);
355   ASSERT (errno == EISDIR || errno == ENOTDIR);
356   errno = 0;
357   ASSERT (func (BASE "link1", BASE "dir/") == -1);
358   ASSERT (errno == EISDIR || errno == ENOTDIR);
359   errno = 0;
360   ASSERT (func (BASE "link1/", BASE "dir") == -1);
361   ASSERT (errno == ENOTDIR);
362   memset (&st, 0, sizeof st);
363   ASSERT (lstat (BASE "link1", &st) == 0);
364   ASSERT (S_ISLNK (st.st_mode));
365   memset (&st, 0, sizeof st);
366   ASSERT (lstat (BASE "dir", &st) == 0);
367   ASSERT (S_ISDIR (st.st_mode));
368
369   /* POSIX requires rename("link-to-dir/","other") to rename "dir" and
370      leave "link-to-dir" dangling, but GNU rejects this.  POSIX
371      requires rename("dir","dangling/") to create the directory so
372      that "dangling/" now resolves, but GNU rejects this.  While we
373      prefer GNU behavior, we don't enforce it.  However, we do test
374      that the system either follows POSIX in both cases, or follows
375      GNU.  */
376   {
377     int result;
378     ASSERT (symlink (BASE "dir2", BASE "link2") == 0);
379     errno = 0;
380     result = func (BASE "dir", BASE "link2/");
381     if (result == 0)
382       {
383         /* POSIX.  */
384         errno = 0;
385         ASSERT (lstat (BASE "dir", &st) == -1);
386         ASSERT (errno == ENOENT);
387         memset (&st, 0, sizeof st);
388         ASSERT (lstat (BASE "dir2", &st) == 0);
389         ASSERT (S_ISDIR (st.st_mode));
390         memset (&st, 0, sizeof st);
391         ASSERT (lstat (BASE "link2", &st) == 0);
392         ASSERT (S_ISLNK (st.st_mode));
393         ASSERT (func (BASE "link2/", BASE "dir") == 0);
394         memset (&st, 0, sizeof st);
395         ASSERT (lstat (BASE "dir", &st) == 0);
396         ASSERT (S_ISDIR (st.st_mode));
397         errno = 0;
398         ASSERT (lstat (BASE "dir2", &st) == -1);
399         ASSERT (errno == ENOENT);
400         memset (&st, 0, sizeof st);
401         ASSERT (lstat (BASE "link2", &st) == 0);
402         ASSERT (S_ISLNK (st.st_mode));
403       }
404     else
405       {
406         /* GNU.  */
407         ASSERT (result == -1);
408         ASSERT (errno == ENOTDIR);
409         memset (&st, 0, sizeof st);
410         ASSERT (lstat (BASE "dir", &st) == 0);
411         ASSERT (S_ISDIR (st.st_mode));
412         errno = 0;
413         ASSERT (lstat (BASE "dir2", &st) == -1);
414         ASSERT (errno == ENOENT);
415         memset (&st, 0, sizeof st);
416         ASSERT (lstat (BASE "link2", &st) == 0);
417         ASSERT (S_ISLNK (st.st_mode));
418         ASSERT (unlink (BASE "link2") == 0);
419         ASSERT (symlink (BASE "dir", BASE "link2") == 0);
420         errno = 0; /* OpenBSD notices that link2/ and dir are the same.  */
421         result = func (BASE "link2/", BASE "dir");
422         if (result) /* GNU/Linux rejects attempts to use link2/.  */
423           {
424             ASSERT (result == -1);
425             ASSERT (errno == ENOTDIR);
426           }
427         memset (&st, 0, sizeof st);
428         ASSERT (lstat (BASE "dir", &st) == 0);
429         ASSERT (S_ISDIR (st.st_mode));
430         errno = 0;
431         ASSERT (lstat (BASE "dir2", &st) == -1);
432         ASSERT (errno == ENOENT);
433         memset (&st, 0, sizeof st);
434         ASSERT (lstat (BASE "link2", &st) == 0);
435         ASSERT (S_ISLNK (st.st_mode));
436       }
437   }
438
439   /* Clean up.  */
440   ASSERT (unlink (BASE "file") == 0);
441   ASSERT (rmdir (BASE "dir") == 0);
442   ASSERT (unlink (BASE "link1") == 0);
443   ASSERT (unlink (BASE "link2") == 0);
444
445   return 0;
446 }