Line data Source code
1 : /* Test of lstat() function.
2 : Copyright (C) 2008-2020 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 <https://www.gnu.org/licenses/>. */
16 :
17 : /* Written by Simon Josefsson, 2008; and Eric Blake, 2009. */
18 :
19 : /* This file is designed to test both lstat(n,buf) and
20 : fstatat(AT_FDCWD,n,buf,AT_SYMLINK_NOFOLLOW). FUNC is the function
21 : to test. Assumes that BASE and ASSERT are already defined, and
22 : that appropriate headers are already included. If PRINT, warn
23 : before skipping symlink tests with status 77. */
24 :
25 : static int
26 1 : test_lstat_func (int (*func) (char const *, struct stat *), bool print)
27 : {
28 : struct stat st1;
29 : struct stat st2;
30 :
31 : /* Test for common directories. */
32 1 : ASSERT (func (".", &st1) == 0);
33 1 : ASSERT (func ("./", &st2) == 0);
34 : #if !(defined _WIN32 && !defined __CYGWIN__ && !_GL_WINDOWS_STAT_INODES)
35 1 : ASSERT (SAME_INODE (st1, st2));
36 : #endif
37 1 : ASSERT (S_ISDIR (st1.st_mode));
38 1 : ASSERT (S_ISDIR (st2.st_mode));
39 1 : ASSERT (func ("/", &st1) == 0);
40 1 : ASSERT (func ("///", &st2) == 0);
41 : #if !(defined _WIN32 && !defined __CYGWIN__ && !_GL_WINDOWS_STAT_INODES)
42 1 : ASSERT (SAME_INODE (st1, st2));
43 : #endif
44 1 : ASSERT (S_ISDIR (st1.st_mode));
45 1 : ASSERT (S_ISDIR (st2.st_mode));
46 1 : ASSERT (func ("..", &st1) == 0);
47 1 : ASSERT (S_ISDIR (st1.st_mode));
48 :
49 : /* Test for error conditions. */
50 1 : errno = 0;
51 1 : ASSERT (func ("", &st1) == -1);
52 1 : ASSERT (errno == ENOENT);
53 1 : errno = 0;
54 1 : ASSERT (func ("nosuch", &st1) == -1);
55 1 : ASSERT (errno == ENOENT);
56 1 : errno = 0;
57 1 : ASSERT (func ("nosuch/", &st1) == -1);
58 1 : ASSERT (errno == ENOENT);
59 :
60 1 : ASSERT (close (creat (BASE "file", 0600)) == 0);
61 1 : ASSERT (func (BASE "file", &st1) == 0);
62 1 : ASSERT (S_ISREG (st1.st_mode));
63 1 : errno = 0;
64 1 : ASSERT (func (BASE "file/", &st1) == -1);
65 1 : ASSERT (errno == ENOTDIR);
66 :
67 : /* Now for some symlink tests, where supported. We set up:
68 : link1 -> directory
69 : link2 -> file
70 : link3 -> dangling
71 : link4 -> loop
72 : then test behavior both with and without trailing slash.
73 : */
74 1 : if (symlink (".", BASE "link1") != 0)
75 : {
76 0 : ASSERT (unlink (BASE "file") == 0);
77 0 : if (print)
78 0 : fputs ("skipping test: symlinks not supported on this file system\n",
79 : stderr);
80 0 : return 77;
81 : }
82 1 : ASSERT (symlink (BASE "file", BASE "link2") == 0);
83 1 : ASSERT (symlink (BASE "nosuch", BASE "link3") == 0);
84 1 : ASSERT (symlink (BASE "link4", BASE "link4") == 0);
85 :
86 1 : ASSERT (func (BASE "link1", &st1) == 0);
87 1 : ASSERT (S_ISLNK (st1.st_mode));
88 1 : ASSERT (func (BASE "link1/", &st1) == 0);
89 1 : ASSERT (stat (BASE "link1", &st2) == 0);
90 1 : ASSERT (S_ISDIR (st1.st_mode));
91 1 : ASSERT (S_ISDIR (st2.st_mode));
92 : #if !(defined _WIN32 && !defined __CYGWIN__ && !_GL_WINDOWS_STAT_INODES)
93 1 : ASSERT (SAME_INODE (st1, st2));
94 : #endif
95 :
96 1 : ASSERT (func (BASE "link2", &st1) == 0);
97 1 : ASSERT (S_ISLNK (st1.st_mode));
98 1 : errno = 0;
99 1 : ASSERT (func (BASE "link2/", &st1) == -1);
100 1 : ASSERT (errno == ENOTDIR);
101 :
102 1 : ASSERT (func (BASE "link3", &st1) == 0);
103 1 : ASSERT (S_ISLNK (st1.st_mode));
104 1 : errno = 0;
105 1 : ASSERT (func (BASE "link3/", &st1) == -1);
106 1 : ASSERT (errno == ENOENT);
107 :
108 1 : ASSERT (func (BASE "link4", &st1) == 0);
109 1 : ASSERT (S_ISLNK (st1.st_mode));
110 1 : errno = 0;
111 1 : ASSERT (func (BASE "link4/", &st1) == -1);
112 1 : ASSERT (errno == ELOOP);
113 :
114 : /* Cleanup. */
115 1 : ASSERT (unlink (BASE "file") == 0);
116 1 : ASSERT (unlink (BASE "link1") == 0);
117 1 : ASSERT (unlink (BASE "link2") == 0);
118 1 : ASSERT (unlink (BASE "link3") == 0);
119 1 : ASSERT (unlink (BASE "link4") == 0);
120 :
121 1 : return 0;
122 : }
|