1#define _LARGEFILE_SOURCE
2#define _LARGEFILE64_SOURCE
3
4#include <errno.h>
5#include <fcntl.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <sys/resource.h>
9#include <unistd.h>
10#include "fdleak.h"
11
12int main(int argc, char **argv)
13{
14   struct rlimit64 oldrlim;
15   struct rlimit64 newrlim;
16   int fd;
17
18   CLOSE_INHERITED_FDS;
19
20   if (getrlimit64(RLIMIT_NOFILE, &oldrlim) < 0)
21   {
22      perror("getrlimit");
23      exit(1);
24   }
25
26   newrlim.rlim_cur = oldrlim.rlim_max+1;
27   newrlim.rlim_max = oldrlim.rlim_max;
28   if (setrlimit64(RLIMIT_NOFILE, &newrlim) == -1)
29   {
30      if (errno != EINVAL) {
31         fprintf(stderr, "setrlimit64 exceeding hardlimit must set errno=EINVAL\n");
32         exit(1);
33      }
34   }
35   else
36   {
37        fprintf(stderr, "setrlimit64 exceeding hardlimit must return -1\n");
38        exit(1);
39   }
40
41   newrlim.rlim_cur = oldrlim.rlim_max;
42   newrlim.rlim_max = oldrlim.rlim_max+1;
43   if (setrlimit64(RLIMIT_NOFILE, &newrlim) == -1)
44   {
45      if (errno != EPERM) {
46         fprintf(stderr, "setrlimit64 changing hardlimit must set errno=EPERM\n");
47         exit(1);
48      }
49   }
50   else
51   {
52        fprintf(stderr, "setrlimit64 changing hardlimit must return -1\n");
53        exit(1);
54   }
55
56   newrlim.rlim_cur = oldrlim.rlim_cur / 2;
57   newrlim.rlim_max = oldrlim.rlim_max;
58
59   if (setrlimit64(RLIMIT_NOFILE, &newrlim) < 0)
60   {
61      perror("setrlimit64");
62      exit(1);
63   }
64
65   if (getrlimit64(RLIMIT_NOFILE, &newrlim) < 0)
66   {
67      perror("getrlimit");
68      exit(1);
69   }
70
71   if (newrlim.rlim_cur != oldrlim.rlim_cur / 2)
72   {
73      fprintf(stderr, "rlim_cur is %llu (should be %llu)\n",
74              (unsigned long long)newrlim.rlim_cur,
75              (unsigned long long)oldrlim.rlim_cur / 2);
76   }
77
78   if (newrlim.rlim_max != oldrlim.rlim_max)
79   {
80      fprintf(stderr, "rlim_max is %llu (should be %llu)\n",
81              (unsigned long long)newrlim.rlim_max,
82              (unsigned long long)oldrlim.rlim_max);
83   }
84
85   newrlim.rlim_cur -= 3; /* allow for stdin, stdout and stderr */
86
87   while (newrlim.rlim_cur-- > 0)
88   {
89      if (open("/dev/null", O_RDONLY) < 0)
90      {
91         perror("open");
92      }
93   }
94
95   if ((fd = open("/dev/null", O_RDONLY)) >= 0)
96   {
97      fprintf(stderr, "open succeeded with fd %d - it should have failed!\n", fd);
98   }
99   else if (errno != EMFILE)
100   {
101      perror("open");
102   }
103
104   exit(0);
105}
106