This source file includes following definitions.
- test_lchown
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include "nap.h"
20
21 #if !HAVE_GETEGID
22 # define getegid() ((gid_t) -1)
23 #endif
24
25 #ifndef HAVE_LCHMOD
26 # define HAVE_LCHMOD 0
27 #endif
28
29 #ifndef CHOWN_CHANGE_TIME_BUG
30 # define CHOWN_CHANGE_TIME_BUG 0
31 #endif
32
33
34
35
36
37
38
39 static int
40 test_lchown (int (*func) (char const *, uid_t, gid_t), bool print)
41 {
42 struct stat st1;
43 struct stat st2;
44 gid_t *gids = NULL;
45 int gids_count;
46 int result;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 ASSERT (mkdir (BASE "dir", 0700) == 0);
66 ASSERT (stat (BASE "dir", &st1) == 0);
67
68
69 result = func (BASE "dir", st1.st_uid, getegid ());
70 if (result == -1 && (errno == ENOSYS || errno == EPERM))
71 {
72 ASSERT (rmdir (BASE "dir") == 0);
73 if (print)
74 fputs ("skipping test: no support for ownership\n", stderr);
75 return 77;
76 }
77 ASSERT (result == 0);
78
79 ASSERT (close (creat (BASE "dir/file", 0600)) == 0);
80 ASSERT (stat (BASE "dir/file", &st1) == 0);
81 ASSERT (st1.st_uid != (uid_t) -1);
82 ASSERT (st1.st_gid != (gid_t) -1);
83 ASSERT (st1.st_gid == getegid ());
84
85
86 errno = 0;
87 ASSERT (func ("", -1, -1) == -1);
88 ASSERT (errno == ENOENT);
89 errno = 0;
90 ASSERT (func ("no_such", -1, -1) == -1);
91 ASSERT (errno == ENOENT);
92 errno = 0;
93 ASSERT (func ("no_such/", -1, -1) == -1);
94 ASSERT (errno == ENOENT);
95 errno = 0;
96 ASSERT (func (BASE "dir/file/", -1, -1) == -1);
97 ASSERT (errno == ENOTDIR);
98
99
100 ASSERT (func (BASE "dir/file", -1, st1.st_gid) == 0);
101 ASSERT (func (BASE "dir/file", st1.st_uid, -1) == 0);
102 ASSERT (func (BASE "dir/file", (uid_t) -1, (gid_t) -1) == 0);
103 ASSERT (stat (BASE "dir/file", &st2) == 0);
104 ASSERT (st1.st_uid == st2.st_uid);
105 ASSERT (st1.st_gid == st2.st_gid);
106
107
108
109 nap ();
110 ASSERT (func (BASE "dir/file", st1.st_uid, st1.st_gid) == 0);
111 ASSERT (stat (BASE "dir/file", &st2) == 0);
112 ASSERT (st1.st_ctime < st2.st_ctime
113 || (st1.st_ctime == st2.st_ctime
114 && get_stat_ctime_ns (&st1) < get_stat_ctime_ns (&st2)));
115
116
117 if (symlink ("link", BASE "dir/link2"))
118 {
119 ASSERT (unlink (BASE "dir/file") == 0);
120 ASSERT (rmdir (BASE "dir") == 0);
121 if (print)
122 fputs ("skipping test: symlinks not supported on this file system\n",
123 stderr);
124 return 77;
125 }
126 result = func (BASE "dir/link2", -1, -1);
127 if (result == -1 && (errno == ENOSYS || errno == EOPNOTSUPP))
128 {
129 ASSERT (unlink (BASE "dir/file") == 0);
130 ASSERT (unlink (BASE "dir/link2") == 0);
131 ASSERT (rmdir (BASE "dir") == 0);
132 if (print)
133 fputs ("skipping test: symlink ownership not supported\n", stderr);
134 return 77;
135 }
136 ASSERT (result == 0);
137 errno = 0;
138 ASSERT (func (BASE "dir/link2/", st1.st_uid, st1.st_gid) == -1);
139 ASSERT (errno == ENOENT);
140 ASSERT (symlink ("file", BASE "dir/link") == 0);
141 ASSERT (mkdir (BASE "dir/sub", 0700) == 0);
142 ASSERT (symlink ("sub", BASE "dir/link3") == 0);
143
144
145
146
147
148
149 gids_count = mgetgroups (NULL, st1.st_gid, &gids);
150 if (1 < gids_count)
151 {
152 ASSERT (gids[1] != st1.st_gid);
153 ASSERT (gids[1] != (gid_t) -1);
154 ASSERT (lstat (BASE "dir/link", &st2) == 0);
155 ASSERT (st1.st_uid == st2.st_uid);
156 ASSERT (st1.st_gid == st2.st_gid);
157 ASSERT (lstat (BASE "dir/link2", &st2) == 0);
158 ASSERT (st1.st_uid == st2.st_uid);
159 ASSERT (st1.st_gid == st2.st_gid);
160
161 errno = 0;
162 ASSERT (func (BASE "dir/link2/", -1, gids[1]) == -1);
163 ASSERT (errno == ENOTDIR);
164 ASSERT (stat (BASE "dir/file", &st2) == 0);
165 ASSERT (st1.st_uid == st2.st_uid);
166 ASSERT (st1.st_gid == st2.st_gid);
167 ASSERT (lstat (BASE "dir/link", &st2) == 0);
168 ASSERT (st1.st_uid == st2.st_uid);
169 ASSERT (st1.st_gid == st2.st_gid);
170 ASSERT (lstat (BASE "dir/link2", &st2) == 0);
171 ASSERT (st1.st_uid == st2.st_uid);
172 ASSERT (st1.st_gid == st2.st_gid);
173
174 ASSERT (func (BASE "dir/link2", -1, gids[1]) == 0);
175 ASSERT (stat (BASE "dir/file", &st2) == 0);
176 ASSERT (st1.st_uid == st2.st_uid);
177 ASSERT (st1.st_gid == st2.st_gid);
178 ASSERT (lstat (BASE "dir/link", &st2) == 0);
179 ASSERT (st1.st_uid == st2.st_uid);
180 ASSERT (st1.st_gid == st2.st_gid);
181 ASSERT (lstat (BASE "dir/link2", &st2) == 0);
182 ASSERT (st1.st_uid == st2.st_uid);
183 ASSERT (gids[1] == st2.st_gid);
184
185
186 ASSERT (lstat (BASE "dir/link3", &st2) == 0);
187 ASSERT (st1.st_uid == st2.st_uid);
188 ASSERT (st1.st_gid == st2.st_gid);
189 ASSERT (lstat (BASE "dir/sub", &st2) == 0);
190 ASSERT (st1.st_uid == st2.st_uid);
191 ASSERT (st1.st_gid == st2.st_gid);
192
193 ASSERT (func (BASE "dir/link3/", -1, gids[1]) == 0);
194 ASSERT (lstat (BASE "dir/link3", &st2) == 0);
195 ASSERT (st1.st_uid == st2.st_uid);
196 ASSERT (st1.st_gid == st2.st_gid);
197 ASSERT (lstat (BASE "dir/sub", &st2) == 0);
198 ASSERT (st1.st_uid == st2.st_uid);
199 ASSERT (gids[1] == st2.st_gid);
200 }
201 else if (!CHOWN_CHANGE_TIME_BUG || HAVE_LCHMOD)
202 {
203
204
205 struct stat l1;
206 struct stat l2;
207 ASSERT (stat (BASE "dir/file", &st1) == 0);
208 ASSERT (lstat (BASE "dir/link", &l1) == 0);
209 ASSERT (lstat (BASE "dir/link2", &l2) == 0);
210
211 nap ();
212 errno = 0;
213 ASSERT (func (BASE "dir/link2/", -1, st1.st_gid) == -1);
214 ASSERT (errno == ENOTDIR);
215 ASSERT (stat (BASE "dir/file", &st2) == 0);
216 ASSERT (st1.st_ctime == st2.st_ctime);
217 ASSERT (get_stat_ctime_ns (&st1) == get_stat_ctime_ns (&st2));
218 ASSERT (lstat (BASE "dir/link", &st2) == 0);
219 ASSERT (l1.st_ctime == st2.st_ctime);
220 ASSERT (get_stat_ctime_ns (&l1) == get_stat_ctime_ns (&st2));
221 ASSERT (lstat (BASE "dir/link2", &st2) == 0);
222 ASSERT (l2.st_ctime == st2.st_ctime);
223 ASSERT (get_stat_ctime_ns (&l2) == get_stat_ctime_ns (&st2));
224
225 ASSERT (func (BASE "dir/link2", -1, st1.st_gid) == 0);
226 ASSERT (stat (BASE "dir/file", &st2) == 0);
227 ASSERT (st1.st_ctime == st2.st_ctime);
228 ASSERT (get_stat_ctime_ns (&st1) == get_stat_ctime_ns (&st2));
229 ASSERT (lstat (BASE "dir/link", &st2) == 0);
230 ASSERT (l1.st_ctime == st2.st_ctime);
231 ASSERT (get_stat_ctime_ns (&l1) == get_stat_ctime_ns (&st2));
232 ASSERT (lstat (BASE "dir/link2", &st2) == 0);
233 ASSERT (l2.st_ctime < st2.st_ctime
234 || (l2.st_ctime == st2.st_ctime
235 && get_stat_ctime_ns (&l2) < get_stat_ctime_ns (&st2)));
236
237
238 ASSERT (lstat (BASE "dir/sub", &st1) == 0);
239 ASSERT (lstat (BASE "dir/link3", &l1) == 0);
240 nap ();
241 ASSERT (func (BASE "dir/link3/", -1, st1.st_gid) == 0);
242 ASSERT (lstat (BASE "dir/link3", &st2) == 0);
243 ASSERT (l1.st_ctime == st2.st_ctime);
244 ASSERT (get_stat_ctime_ns (&l1) == get_stat_ctime_ns (&st2));
245 ASSERT (lstat (BASE "dir/sub", &st2) == 0);
246 ASSERT (st1.st_ctime < st2.st_ctime
247 || (st1.st_ctime == st2.st_ctime
248 && get_stat_ctime_ns (&st1) < get_stat_ctime_ns (&st2)));
249 }
250
251
252 free (gids);
253 ASSERT (unlink (BASE "dir/file") == 0);
254 ASSERT (unlink (BASE "dir/link") == 0);
255 ASSERT (unlink (BASE "dir/link2") == 0);
256 ASSERT (unlink (BASE "dir/link3") == 0);
257 ASSERT (rmdir (BASE "dir/sub") == 0);
258 ASSERT (rmdir (BASE "dir") == 0);
259 return 0;
260 }