]> git.saurik.com Git - apple/libc.git/blame - tests/stdio.c
Libc-1439.100.3.tar.gz
[apple/libc.git] / tests / stdio.c
CommitLineData
974e3884
A
1#include <stdio.h>
2#include <err.h>
3#include <errno.h>
4#include <unistd.h>
5#include <sys/resource.h>
a9aaacca
A
6#include <stdlib.h>
7#include <sys/sysctl.h>
974e3884
A
8
9#include <darwintest.h>
10
11#define FILE_LIMIT 100
12
a9aaacca
A
13/*
14 * Validate:
15 * (1) the maximum number of fds allowed open per process
16 * implemented by the kernel matches what sysconf expects:
17 * 32 bit: OPEN_MAX
18 * 64 bit: RLIM_INFINITY
19 * (2) fopen does not fail when NOFILE is unlimited.
20 */
21T_DECL(stdio_PR_63187147_SC_STREAM_MAX, "_SC_STREAM_MAX test")
22{
23 struct rlimit rlim;
24 long stream_max, saved_stream_max, open_count, i;
25 int maxfilesperproc, err;
26 size_t maxfilesperproc_size = sizeof(maxfilesperproc);
27 FILE **fp = NULL;
28 const char *filename = "fopen_test";
29
30 T_SETUPBEGIN;
31
32 saved_stream_max = sysconf(_SC_STREAM_MAX);
33 T_LOG("Initial stream_max %ld", saved_stream_max);
34
35 /* Decide the maximum number of fds allowed by the kernel */
36 err = sysctlbyname("kern.maxfilesperproc", &maxfilesperproc, &maxfilesperproc_size, NULL, 0);
37 T_EXPECT_POSIX_SUCCESS(err, "sysctlbyname(\"kern.maxfilesperproc\") returned %d", err);
38 T_LOG("kern.maxfilesperproc %d", maxfilesperproc);
39
40 /*
41 * Raise RLIMIT_NOFILE to RLIM_INFINITY, note that this does NOT update
42 * __stream_max in findfp.c
43 */
44 err = getrlimit(RLIMIT_NOFILE, &rlim);
45 T_EXPECT_POSIX_SUCCESS(err, "getrlimit(RLIMIT_NOFILE)");
46 T_LOG("Initial RLIMIT_NOFILE rlim.cur: 0x%llx", rlim.rlim_cur);
47 rlim.rlim_cur = RLIM_INFINITY;
48 err = setrlimit(RLIMIT_NOFILE, &rlim);
49 T_EXPECT_POSIX_SUCCESS(err, "setrlimit(RLIMIT_NOFILE) to RLIM_INFINITY");
50 err = getrlimit(RLIMIT_NOFILE, &rlim);
51 T_EXPECT_POSIX_SUCCESS(err, "New RLIMIT_NOFILE rlim_cur: 0x%llx", rlim.rlim_cur);
52
53 T_SETUPEND;
54
55 /*
56 * Test 1 (sysconf with _SC_STREAM_MAX): the largest value sysconf
57 * returns for _SC_STREAM_MAX is OPEN_MAX (32 bit) or
58 * RLIM_INFINITY (64 bit)
59 */
60 stream_max = sysconf(_SC_STREAM_MAX);
61 T_EXPECT_NE_LONG((long)-1, stream_max, "stream_max %ld", stream_max);
62#if __LP64__
63 T_EXPECT_EQ((long)RLIM_INFINITY, stream_max, "sysconf returned 0x%lx", stream_max);
64#else
65 T_EXPECT_EQ((long)OPEN_MAX, stream_max, "sysconf returned 0x%lx", stream_max);
66#endif
67
68 /*
69 * Test 2 (__stream_max in findfp.c): exercise __sfp by calling fopen
70 * saved_stream_max + 1 times. Note that we call fopen() up to
71 * maxfilesperproc times in case fopen() goes nuts.
72 */
73 fp = malloc(sizeof(FILE *) * (size_t)maxfilesperproc);
74 T_EXPECT_NOTNULL(fp, "Allocated %d FILE pointers", maxfilesperproc);
75 for (i = 0; i < saved_stream_max + 1 && i < maxfilesperproc; i++) {
76 if (i == saved_stream_max) {
77 T_LOG("The very next fopen should trigger __sfp to update __stream_max and fopen shouldn't fail ");
78 }
79 fp[i] = fopen(filename, "r");
80 T_QUIET; T_EXPECT_NOTNULL(fp, "%ld: fopen(%s, \"r\")", i, filename);
81 }
82 open_count = i;
83
84 for (i = 0; i < open_count; i++) {
85 fclose(fp[i]);
86 }
87 free(fp);
88
89 T_LOG("saved_stream_max %ld stream_max %ld fopen %ld files", saved_stream_max, stream_max, open_count);
90}
91
b061a43b 92T_DECL(stdio_PR_22813396, "STREAM_MAX is affected by changes to RLIMIT_NOFILE")
974e3884
A
93{
94 struct rlimit theLimit;
95 getrlimit( RLIMIT_NOFILE, &theLimit );
96 theLimit.rlim_cur = FILE_LIMIT;
97 setrlimit( RLIMIT_NOFILE, &theLimit );
98
99 long stream_max = sysconf(_SC_STREAM_MAX);
100 T_EXPECT_EQ_LONG(stream_max, (long)FILE_LIMIT, "stream_max = FILE_LIMIT");
101
102 FILE *f;
103 for(int i = 3; i < stream_max; i++) {
104 if((f = fdopen(0, "r")) == NULL) {
105 T_FAIL("Failed after %d streams", i);
106 }
107 }
108
109 f = fdopen(0, "r");
110 T_EXPECT_NULL(f, "fdopen fail after stream_max streams");
111
112 theLimit.rlim_cur = FILE_LIMIT + 1;
113 setrlimit( RLIMIT_NOFILE, &theLimit );
114
115 f = fdopen(0, "r");
116 T_EXPECT_NOTNULL(f, "fdopen succeed after RLIMIT_NOFILE increased");
117}
b061a43b
A
118
119T_DECL(stdio_PR_22813396_close, "STREAM_MAX is enforced properly after fclose")
120{
121 struct rlimit theLimit;
122 getrlimit( RLIMIT_NOFILE, &theLimit );
123 theLimit.rlim_cur = FILE_LIMIT;
124 setrlimit( RLIMIT_NOFILE, &theLimit );
125
126 long stream_max = sysconf(_SC_STREAM_MAX);
127 T_EXPECT_EQ_LONG(stream_max, (long)FILE_LIMIT, "stream_max = FILE_LIMIT");
128
129 FILE *f;
130 for(int i = 3; i < stream_max - 1; i++) {
131 if((f = fdopen(0, "r")) == NULL) {
132 T_FAIL("Failed after %d streams", i);
133 }
134 }
135
136 // the last stream is for dup(0), it needs to be fclose'd
137 FILE *dupf = NULL;
138 T_EXPECT_NOTNULL(dupf = fdopen(dup(0), "r"), NULL);
139
140 T_EXPECT_NULL(f = fdopen(0, "r"), "fdopen fail after stream_max streams");
141
142 T_EXPECT_POSIX_ZERO(fclose(dupf), "fclose succeeds");
143
144 f = fdopen(0, "r");
145 T_WITH_ERRNO; T_EXPECT_NOTNULL(f, "fdopen succeed after fclose");
146}
147