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 closefrom_sysconf(int lower)29static 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 closefrom_procfs(int lower)45static 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 rep_closefrom(int lower)128int 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 } 139