pyldb: avoid segfault when adding an element with no name
[sfrench/samba-autobuild/.git] / lib / replace / closefrom.c
1 /*
2  * Unix SMB/CIFS implementation.
3  * Samba utility functions
4  * Copyright (C) Volker Lendecke 2016
5  *
6  *   ** NOTE! The following LGPL license applies to the replace
7  *   ** library. This does NOT imply that all of Samba is released
8  *   ** under the LGPL
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 3 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
22  */
23
24 #include "replace.h"
25 #include <dirent.h>
26 #include <unistd.h>
27 #include <limits.h>
28
29 static int closefrom_sysconf(int lower)
30 {
31         long max_files, fd;
32
33         max_files = sysconf(_SC_OPEN_MAX);
34         if (max_files == -1) {
35                 max_files = 65536;
36         }
37
38         for (fd=lower; fd<max_files; fd++) {
39                 close(fd);
40         }
41
42         return 0;
43 }
44
45 static int closefrom_procfs(int lower)
46 {
47         DIR *dirp;
48         int dir_fd;
49         struct dirent *dp;
50         int *fds = NULL;
51         size_t num_fds = 0;
52         size_t fd_array_size = 0;
53         size_t i;
54         int ret = ENOMEM;
55
56         dirp = opendir("/proc/self/fd");
57         if (dirp == 0) {
58                 return errno;
59         }
60
61         dir_fd = dirfd(dirp);
62         if (dir_fd == -1) {
63                 ret = errno;
64                 goto fail;
65         }
66
67         while ((dp = readdir(dirp)) != NULL) {
68                 char *endptr;
69                 unsigned long long fd;
70
71                 errno = 0;
72
73                 fd = strtoull(dp->d_name, &endptr, 10);
74                 if ((fd == 0) && (errno == EINVAL)) {
75                         continue;
76                 }
77                 if ((fd == ULLONG_MAX) && (errno == ERANGE)) {
78                         continue;
79                 }
80                 if (*endptr != '\0') {
81                         continue;
82                 }
83                 if (fd == dir_fd) {
84                         continue;
85                 }
86                 if (fd > INT_MAX) {
87                         continue;
88                 }
89                 if (fd < lower) {
90                         continue;
91                 }
92
93                 if (num_fds >= (fd_array_size / sizeof(int))) {
94                         void *tmp;
95
96                         if (fd_array_size == 0) {
97                                 fd_array_size = 16 * sizeof(int);
98                         } else {
99                                 if (fd_array_size + fd_array_size <
100                                     fd_array_size) {
101                                         /* overflow */
102                                         goto fail;
103                                 }
104                                 fd_array_size = fd_array_size + fd_array_size;
105                         }
106
107                         tmp = realloc(fds, fd_array_size);
108                         if (tmp == NULL) {
109                                 goto fail;
110                         }
111                         fds = tmp;
112                 }
113
114                 fds[num_fds++] = fd;
115         }
116
117         for (i=0; i<num_fds; i++) {
118                 close(fds[i]);
119         }
120
121         ret = 0;
122 fail:
123         closedir(dirp);
124         free(fds);
125         return ret;
126 }
127
128 int rep_closefrom(int lower)
129 {
130         int ret;
131
132         ret = closefrom_procfs(lower);
133         if (ret == 0) {
134                 return 0;
135         }
136
137         return closefrom_sysconf(lower);
138 }