1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <errno.h>
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <fcntl.h>
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h>
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h>
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/resource.h>
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h>
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "fdleak.h"
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main(int argc, char **argv)
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct rlimit oldrlim;
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct rlimit newrlim;
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int fd;
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLOSE_INHERITED_FDS;
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (getrlimit(RLIMIT_NOFILE, &oldrlim) < 0)
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      perror("getrlimit");
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      exit(1);
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   newrlim.rlim_cur = oldrlim.rlim_max+1;
24663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   newrlim.rlim_max = oldrlim.rlim_max;
25663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (setrlimit(RLIMIT_NOFILE, &newrlim) == -1)
26663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
27663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (errno != EINVAL) {
28663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fprintf(stderr, "setrlimit exceeding hardlimit must set errno=EINVAL\n");
29663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         exit(1);
30663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
31663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
32663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
33663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
34663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        fprintf(stderr, "setrlimit exceeding hardlimit must return -1\n");
35663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        exit(1);
36663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
37663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
38663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   newrlim.rlim_cur = oldrlim.rlim_max;
39663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   newrlim.rlim_max = oldrlim.rlim_max+1;
40663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (setrlimit(RLIMIT_NOFILE, &newrlim) == -1)
41663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
42663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (errno != EPERM) {
43663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fprintf(stderr, "setrlimit changing hardlimit must set errno=EPERM\n");
44663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         exit(1);
45663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
46663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
47663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else
48663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
49663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        fprintf(stderr, "setrlimit changing hardlimit must return -1\n");
50663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        exit(1);
51663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
52663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   newrlim.rlim_cur = oldrlim.rlim_cur / 2;
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   newrlim.rlim_max = oldrlim.rlim_max;
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (setrlimit(RLIMIT_NOFILE, &newrlim) < 0)
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      perror("setrlimit");
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      exit(1);
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (getrlimit(RLIMIT_NOFILE, &newrlim) < 0)
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      perror("getrlimit");
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      exit(1);
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (newrlim.rlim_cur != oldrlim.rlim_cur / 2)
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "rlim_cur is %llu (should be %llu)\n",
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (unsigned long long)newrlim.rlim_cur,
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (unsigned long long)oldrlim.rlim_cur / 2);
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (newrlim.rlim_max != oldrlim.rlim_max)
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "rlim_max is %llu (should be %llu)\n",
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (unsigned long long)newrlim.rlim_max,
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (unsigned long long)oldrlim.rlim_max);
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   newrlim.rlim_cur -= 3; /* allow for stdin, stdout and stderr */
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (newrlim.rlim_cur-- > 0)
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (open("/dev/null", O_RDONLY) < 0)
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         perror("open");
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((fd = open("/dev/null", O_RDONLY)) >= 0)
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "open succeeded with fd %d - it should have failed!\n", fd);
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (errno != EMFILE)
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      perror("open");
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   exit(0);
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
103