]> git.saurik.com Git - apple/libc.git/blame - tests/netbsd_stat.c
Libc-1439.100.3.tar.gz
[apple/libc.git] / tests / netbsd_stat.c
CommitLineData
974e3884
A
1/* $NetBSD: t_stat.c,v 1.4 2012/03/17 08:37:08 jruoho Exp $ */
2
3/*-
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jukka Ruohonen.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31#include <sys/cdefs.h>
32__RCSID("$NetBSD: t_stat.c,v 1.4 2012/03/17 08:37:08 jruoho Exp $");
33
34#include <sys/stat.h>
35#include <sys/socket.h>
36#include <sys/types.h>
37
38#include <arpa/inet.h>
39
40#include <errno.h>
41#include <fcntl.h>
42#include <fts.h>
43#include <limits.h>
44#include <string.h>
45#include <unistd.h>
46
47#include <stdio.h>
48
49#include <netinet/in.h>
50
51#include <darwintest.h>
52
53static const char *path = "/tmp/stat";
54
55T_DECL(stat_chflags, "Test chflags(2) with stat(2)")
56{
57 struct stat sa, sb;
58 int fd;
59
60 (void)memset(&sa, 0, sizeof(struct stat));
61 (void)memset(&sb, 0, sizeof(struct stat));
62
63 unlink(path);
64 T_ASSERT_POSIX_SUCCESS((fd = open(path, O_RDONLY | O_CREAT)), NULL);
65
66 T_ASSERT_POSIX_ZERO(stat(path, &sa), NULL);
67 T_ASSERT_POSIX_ZERO(chflags(path, UF_NODUMP), NULL);
68 T_ASSERT_POSIX_ZERO(stat(path, &sb), NULL);
69
70 T_EXPECT_NE(sa.st_flags, sb.st_flags | UF_NODUMP, "stat(2) detects chflags(2)");
71
72 T_ASSERT_POSIX_ZERO(close(fd), NULL);
73 T_ASSERT_POSIX_ZERO(unlink(path), NULL);
74}
75
76T_DECL(stat_dir, "Test stat(2) with directories")
77{
78 const short depth = 2;
79 struct stat sa, sb;
80 char *args[] = {"/System", NULL};
81 FTSENT *ftse;
82 FTS *fts;
83 int ops;
84
85 ops = FTS_NOCHDIR;
86 ops |= FTS_PHYSICAL;
87
88 T_ASSERT_NOTNULL(fts = fts_open(args, ops, NULL), NULL);
89
90 while ((ftse = fts_read(fts)) != NULL) {
91
92 if (ftse->fts_level < 1)
93 continue;
94
95 if (ftse->fts_level > depth) {
96 (void)fts_set(fts, ftse, FTS_SKIP);
97 continue;
98 }
99
100 switch(ftse->fts_info) {
101
102 case FTS_DP:
103
104 (void)memset(&sa, 0, sizeof(struct stat));
105 (void)memset(&sb, 0, sizeof(struct stat));
106
107 T_ASSERT_POSIX_ZERO(stat(ftse->fts_parent->fts_path,&sa), NULL);
108 T_ASSERT_POSIX_ZERO(chdir(ftse->fts_path), NULL);
109 T_ASSERT_POSIX_ZERO(stat(".", &sb), NULL);
110
111 /*
112 * The previous two stat(2) calls
113 * should be for the same directory.
114 */
115 T_EXPECT_EQ(sa.st_dev, sb.st_dev, "stat(2) should return consistent device");
116 T_EXPECT_EQ(sa.st_ino, sb.st_ino, "stat(2) should return consistent inode");
117
118 T_EXPECT_EQ(sb.st_ino, ftse->fts_statp->st_ino, "stat(2) and fts(3) should not differ");
119
120 break;
121
122 default:
123 break;
124 }
125 }
126
127 (void)fts_close(fts);
128}
129
130#if 0 // TODO: port me
131ATF_TC(stat_err);
132ATF_TC_HEAD(stat_err, tc)
133{
134 atf_tc_set_md_var(tc, "descr", "Test errors from the stat(2) family");
135}
136
b061a43b 137T_DECL(stat_err, "")
974e3884
A
138{
139 char buf[NAME_MAX + 1];
140 struct stat st;
141
142 (void)memset(buf, 'x', sizeof(buf));
143
144 errno = 0;
145 ATF_REQUIRE_ERRNO(EBADF, fstat(-1, &st) == -1);
146
147 errno = 0;
148 ATF_REQUIRE_ERRNO(ENAMETOOLONG, stat(buf, &st) == -1);
149
150 errno = 0;
151 ATF_REQUIRE_ERRNO(ENAMETOOLONG, lstat(buf, &st) == -1);
152
153 errno = 0;
154 ATF_REQUIRE_ERRNO(EFAULT, stat((void *)-1, &st) == -1);
155
156 errno = 0;
157 ATF_REQUIRE_ERRNO(EFAULT, lstat((void *)-1, &st) == -1);
158
159 errno = 0;
160 ATF_REQUIRE_ERRNO(EFAULT, stat("/etc/passwd", (void *)-1) == -1);
161
162 errno = 0;
163 ATF_REQUIRE_ERRNO(EFAULT, lstat("/etc/passwd", (void *)-1) == -1);
164
165 errno = 0;
166 ATF_REQUIRE_ERRNO(ENOENT, stat("/a/b/c/d/e/f/g/h/i/j/k", &st) == -1);
167
168 errno = 0;
169 ATF_REQUIRE_ERRNO(ENOENT, lstat("/a/b/c/d/e/f/g/h/i/j/k", &st) == -1);
170}
171
172ATF_TC_WITH_CLEANUP(stat_mtime);
173ATF_TC_HEAD(stat_mtime, tc)
174{
175 atf_tc_set_md_var(tc, "descr", "Test modification times with stat(2)");
176}
177
b061a43b 178T_DECL(stat_mtime, "")
974e3884
A
179{
180 struct stat sa, sb;
181 int fd[3];
182 size_t i;
183
184 for (i = 0; i < __arraycount(fd); i++) {
185
186 (void)memset(&sa, 0, sizeof(struct stat));
187 (void)memset(&sb, 0, sizeof(struct stat));
188
189 fd[i] = open(path, O_WRONLY | O_CREAT);
190
b061a43b
A
191 T_ASSERT_POSIX_SUCCESS(fd[i], NULL);
192 T_ASSERT_EQ(write(fd[i], "X", 1), 1, NULL);
193 T_ASSERT_POSIX_ZERO(stat(path, &sa), NULL);
974e3884
A
194
195 (void)sleep(1);
196
b061a43b
A
197 T_ASSERT_EQ(write(fd[i], "X", 1), 1, NULL);
198 T_ASSERT_POSIX_ZERO(stat(path, &sb), NULL);
974e3884 199
b061a43b
A
200 T_ASSERT_POSIX_ZERO(close(fd[i]), NULL);
201 T_ASSERT_POSIX_ZERO(unlink(path), NULL);
974e3884
A
202
203 if (sa.st_mtime == sb.st_mtime)
204 atf_tc_fail("mtimes did not change");
205 }
206}
207
208ATF_TC_CLEANUP(stat_mtime, tc)
209{
210 (void)unlink(path);
211}
212
213ATF_TC_WITH_CLEANUP(stat_perm);
214ATF_TC_HEAD(stat_perm, tc)
215{
216 atf_tc_set_md_var(tc, "descr", "Test permissions with stat(2)");
217 atf_tc_set_md_var(tc, "require.user", "root");
218}
219
b061a43b 220T_DECL(stat_perm, "")
974e3884
A
221{
222 struct stat sa, sb;
223 gid_t gid;
224 uid_t uid;
225 int fd;
226
227 (void)memset(&sa, 0, sizeof(struct stat));
228 (void)memset(&sb, 0, sizeof(struct stat));
229
230 uid = getuid();
231 gid = getgid();
232
233 fd = open(path, O_RDONLY | O_CREAT);
234
b061a43b
A
235 T_ASSERT_POSIX_SUCCESS(fd, NULL);
236 T_ASSERT_POSIX_ZERO(fstat(fd, &sa), NULL);
237 T_ASSERT_POSIX_ZERO(stat(path, &sb), NULL);
974e3884
A
238
239 if (gid != sa.st_gid || sa.st_gid != sb.st_gid)
240 atf_tc_fail("invalid GID");
241
242 if (uid != sa.st_uid || sa.st_uid != sb.st_uid)
243 atf_tc_fail("invalid UID");
244
b061a43b
A
245 T_ASSERT_POSIX_ZERO(close(fd), NULL);
246 T_ASSERT_POSIX_ZERO(unlink(path), NULL);
974e3884
A
247}
248
249ATF_TC_CLEANUP(stat_perm, tc)
250{
251 (void)unlink(path);
252}
253
254ATF_TC_WITH_CLEANUP(stat_size);
255ATF_TC_HEAD(stat_size, tc)
256{
257 atf_tc_set_md_var(tc, "descr", "Test file sizes with stat(2)");
258}
259
b061a43b 260T_DECL(stat_size, "")
974e3884
A
261{
262 struct stat sa, sb, sc;
263 const size_t n = 10;
264 size_t i;
265 int fd;
266
267 fd = open(path, O_WRONLY | O_CREAT);
268 ATF_REQUIRE(fd >= 0);
269
270 for (i = 0; i < n; i++) {
271
272 (void)memset(&sa, 0, sizeof(struct stat));
273 (void)memset(&sb, 0, sizeof(struct stat));
274 (void)memset(&sc, 0, sizeof(struct stat));
275
b061a43b
A
276 T_ASSERT_POSIX_ZERO(fstat(fd, &sa), NULL);
277 T_ASSERT_EQ(write(fd, "X", 1), 1, NULL);
278 T_ASSERT_POSIX_ZERO(fstat(fd, &sb), NULL);
279 T_ASSERT_POSIX_ZERO(stat(path, &sc), NULL);
974e3884
A
280
281 if (sa.st_size + 1 != sb.st_size)
282 atf_tc_fail("invalid file size");
283
284 if (sb.st_size != sc.st_size)
285 atf_tc_fail("stat(2) and fstat(2) mismatch");
286 }
287
b061a43b
A
288 T_ASSERT_POSIX_ZERO(close(fd), NULL);
289 T_ASSERT_POSIX_ZERO(unlink(path), NULL);
974e3884
A
290}
291
292ATF_TC_CLEANUP(stat_size, tc)
293{
294 (void)unlink(path);
295}
296
297ATF_TC(stat_socket);
298ATF_TC_HEAD(stat_socket, tc)
299{
300 atf_tc_set_md_var(tc, "descr", "Test fstat(2) with "
301 "a socket (PR kern/46077)");
302}
303
b061a43b 304T_DECL(stat_socket, "")
974e3884
A
305{
306 struct sockaddr_in addr;
307 struct stat st;
308 uint32_t iaddr;
309 int fd, flags;
310
311 (void)memset(&st, 0, sizeof(struct stat));
312 (void)memset(&addr, 0, sizeof(struct sockaddr_in));
313
314 fd = socket(AF_INET, SOCK_STREAM, 0);
315 ATF_REQUIRE(fd >= 0);
316
317 flags = fcntl(fd, F_GETFL);
318
b061a43b
A
319 T_ASSERT_POSIX_SUCCESS(flags, NULL);
320 T_ASSERT_POSIX_SUCCESS(fcntl(fd, F_SETFL, flags | O_NONBLOCK), NULL);
321 T_ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &iaddr), 1, NULL);
974e3884
A
322
323 addr.sin_port = htons(42);
324 addr.sin_family = AF_INET;
325 addr.sin_addr.s_addr = iaddr;
326
327 errno = 0;
328
329 ATF_REQUIRE_ERRNO(EINPROGRESS,
330 connect(fd, (struct sockaddr *)&addr,
331 sizeof(struct sockaddr_in)) == -1);
332
333 errno = 0;
334
335 if (fstat(fd, &st) != 0 || errno != 0)
336 atf_tc_fail("fstat(2) failed for a EINPROGRESS socket");
337
338 (void)close(fd);
339}
340
341ATF_TC_WITH_CLEANUP(stat_symlink);
342ATF_TC_HEAD(stat_symlink, tc)
343{
344 atf_tc_set_md_var(tc, "descr", "Test symbolic links with stat(2)");
345}
346
b061a43b 347T_DECL(stat_symlink, "")
974e3884
A
348{
349 const char *pathlink = "pathlink";
350 struct stat sa, sb;
351 int fd;
352
353 (void)memset(&sa, 0, sizeof(struct stat));
354 (void)memset(&sb, 0, sizeof(struct stat));
355
356 fd = open(path, O_WRONLY | O_CREAT);
357
358 ATF_REQUIRE(fd >= 0);
b061a43b
A
359 T_ASSERT_POSIX_ZERO(symlink(path, pathlink), NULL);
360 T_ASSERT_POSIX_ZERO(stat(pathlink, &sa), NULL);
361 T_ASSERT_POSIX_ZERO(lstat(pathlink, &sb), NULL);
974e3884
A
362
363 if (S_ISLNK(sa.st_mode) != 0)
364 atf_tc_fail("stat(2) detected symbolic link");
365
366 if (S_ISLNK(sb.st_mode) == 0)
367 atf_tc_fail("lstat(2) did not detect symbolic link");
368
369 if (sa.st_mode == sb.st_mode)
370 atf_tc_fail("inconsistencies between stat(2) and lstat(2)");
371
b061a43b
A
372 T_ASSERT_POSIX_ZERO(unlink(path), NULL);
373 T_ASSERT_POSIX_ZERO(unlink(pathlink), NULL);
974e3884
A
374}
375
376ATF_TC_CLEANUP(stat_symlink, tc)
377{
378 (void)unlink(path);
379}
380#endif