opendir.c (241046) | opendir.c (247236) |
---|---|
1/*- 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 17 unchanged lines hidden (view full) --- 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#if defined(LIBC_SCCS) && !defined(lint) 31static char sccsid[] = "@(#)opendir.c 8.8 (Berkeley) 5/1/95"; 32#endif /* LIBC_SCCS and not lint */ 33#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 17 unchanged lines hidden (view full) --- 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#if defined(LIBC_SCCS) && !defined(lint) 31static char sccsid[] = "@(#)opendir.c 8.8 (Berkeley) 5/1/95"; 32#endif /* LIBC_SCCS and not lint */ 33#include <sys/cdefs.h> |
34__FBSDID("$FreeBSD: head/lib/libc/gen/opendir.c 241046 2012-09-29 11:54:34Z jilles $"); | 34__FBSDID("$FreeBSD: head/lib/libc/gen/opendir.c 247236 2013-02-24 20:53:32Z jilles $"); |
35 36#include "namespace.h" 37#include <sys/param.h> 38#include <sys/mount.h> 39#include <sys/stat.h> 40 41#include <dirent.h> 42#include <errno.h> 43#include <fcntl.h> 44#include <stdlib.h> 45#include <string.h> 46#include <unistd.h> 47#include "un-namespace.h" 48 49#include "gen-private.h" 50#include "telldir.h" 51 | 35 36#include "namespace.h" 37#include <sys/param.h> 38#include <sys/mount.h> 39#include <sys/stat.h> 40 41#include <dirent.h> 42#include <errno.h> 43#include <fcntl.h> 44#include <stdlib.h> 45#include <string.h> 46#include <unistd.h> 47#include "un-namespace.h" 48 49#include "gen-private.h" 50#include "telldir.h" 51 |
52static DIR * __opendir_common(int, const char *, int); | 52static DIR * __opendir_common(int, int); |
53 54/* 55 * Open a directory. 56 */ 57DIR * 58opendir(const char *name) 59{ 60 --- 12 unchanged lines hidden (view full) --- 73 if (_fstat(fd, &statb) != 0) 74 return (NULL); 75 if (!S_ISDIR(statb.st_mode)) { 76 errno = ENOTDIR; 77 return (NULL); 78 } 79 if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) 80 return (NULL); | 53 54/* 55 * Open a directory. 56 */ 57DIR * 58opendir(const char *name) 59{ 60 --- 12 unchanged lines hidden (view full) --- 73 if (_fstat(fd, &statb) != 0) 74 return (NULL); 75 if (!S_ISDIR(statb.st_mode)) { 76 errno = ENOTDIR; 77 return (NULL); 78 } 79 if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) 80 return (NULL); |
81 return (__opendir_common(fd, NULL, DTF_HIDEW|DTF_NODUP)); | 81 return (__opendir_common(fd, DTF_HIDEW|DTF_NODUP)); |
82} 83 84DIR * 85__opendir2(const char *name, int flags) 86{ 87 int fd; 88 DIR *dir; 89 int saved_errno; 90 91 if ((fd = _open(name, 92 O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC)) == -1) 93 return (NULL); 94 | 82} 83 84DIR * 85__opendir2(const char *name, int flags) 86{ 87 int fd; 88 DIR *dir; 89 int saved_errno; 90 91 if ((fd = _open(name, 92 O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC)) == -1) 93 return (NULL); 94 |
95 dir = __opendir_common(fd, name, flags); | 95 dir = __opendir_common(fd, flags); |
96 if (dir == NULL) { 97 saved_errno = errno; 98 _close(fd); 99 errno = saved_errno; 100 } 101 return (dir); 102} 103 --- 4 unchanged lines hidden (view full) --- 108 return (strcmp((*(const struct dirent **)p1)->d_name, 109 (*(const struct dirent **)p2)->d_name)); 110} 111 112/* 113 * Common routine for opendir(3), __opendir2(3) and fdopendir(3). 114 */ 115static DIR * | 96 if (dir == NULL) { 97 saved_errno = errno; 98 _close(fd); 99 errno = saved_errno; 100 } 101 return (dir); 102} 103 --- 4 unchanged lines hidden (view full) --- 108 return (strcmp((*(const struct dirent **)p1)->d_name, 109 (*(const struct dirent **)p2)->d_name)); 110} 111 112/* 113 * Common routine for opendir(3), __opendir2(3) and fdopendir(3). 114 */ 115static DIR * |
116__opendir_common(int fd, const char *name, int flags) | 116__opendir_common(int fd, int flags) |
117{ 118 DIR *dirp; 119 int incr; 120 int saved_errno; 121 int unionstack; 122 int fd2; 123 | 117{ 118 DIR *dirp; 119 int incr; 120 int saved_errno; 121 int unionstack; 122 int fd2; 123 |
124 fd2 = -1; 125 |
|
124 if ((dirp = malloc(sizeof(DIR) + sizeof(struct _telldir))) == NULL) 125 return (NULL); 126 127 dirp->dd_td = (struct _telldir *)((char *)dirp + sizeof(DIR)); 128 LIST_INIT(&dirp->dd_td->td_locq); 129 dirp->dd_td->td_loccnt = 0; 130 131 /* --- 28 unchanged lines hidden (view full) --- 160 int n; 161 struct dirent **dpv; 162 163 /* 164 * The strategy here is to read all the directory 165 * entries into a buffer, sort the buffer, and 166 * remove duplicate entries by setting the inode 167 * number to zero. | 126 if ((dirp = malloc(sizeof(DIR) + sizeof(struct _telldir))) == NULL) 127 return (NULL); 128 129 dirp->dd_td = (struct _telldir *)((char *)dirp + sizeof(DIR)); 130 LIST_INIT(&dirp->dd_td->td_locq); 131 dirp->dd_td->td_loccnt = 0; 132 133 /* --- 28 unchanged lines hidden (view full) --- 162 int n; 163 struct dirent **dpv; 164 165 /* 166 * The strategy here is to read all the directory 167 * entries into a buffer, sort the buffer, and 168 * remove duplicate entries by setting the inode 169 * number to zero. |
170 * 171 * We reopen the directory because _getdirentries() 172 * on a MNT_UNION mount modifies the open directory, 173 * making it refer to the lower directory after the 174 * upper directory's entries are exhausted. 175 * This would otherwise break software that uses 176 * the directory descriptor for fchdir or *at 177 * functions, such as fts.c. |
|
168 */ | 178 */ |
179 if ((fd2 = _openat(fd, ".", O_RDONLY | O_CLOEXEC)) == -1) { 180 saved_errno = errno; 181 free(buf); 182 free(dirp); 183 errno = saved_errno; 184 return (NULL); 185 } |
|
169 170 do { 171 /* 172 * Always make at least DIRBLKSIZ bytes 173 * available to _getdirentries 174 */ 175 if (space < DIRBLKSIZ) { 176 space += incr; 177 len += incr; 178 buf = reallocf(buf, len); 179 if (buf == NULL) 180 goto fail; 181 ddptr = buf + (len - space); 182 } 183 | 186 187 do { 188 /* 189 * Always make at least DIRBLKSIZ bytes 190 * available to _getdirentries 191 */ 192 if (space < DIRBLKSIZ) { 193 space += incr; 194 len += incr; 195 buf = reallocf(buf, len); 196 if (buf == NULL) 197 goto fail; 198 ddptr = buf + (len - space); 199 } 200 |
184 n = _getdirentries(fd, ddptr, space, &dirp->dd_seek); | 201 n = _getdirentries(fd2, ddptr, space, &dirp->dd_seek); |
185 if (n > 0) { 186 ddptr += n; 187 space -= n; 188 } 189 } while (n > 0); 190 191 ddeptr = ddptr; 192 flags |= __DTF_READALL; 193 | 202 if (n > 0) { 203 ddptr += n; 204 space -= n; 205 } 206 } while (n > 0); 207 208 ddeptr = ddptr; 209 flags |= __DTF_READALL; 210 |
194 /* 195 * Re-open the directory. 196 * This has the effect of rewinding back to the 197 * top of the union stack and is needed by 198 * programs which plan to fchdir to a descriptor 199 * which has also been read -- see fts.c. 200 */ 201 if (flags & DTF_REWIND) { 202 if ((fd2 = _open(name, O_RDONLY | O_DIRECTORY | 203 O_CLOEXEC)) == -1) { 204 saved_errno = errno; 205 free(buf); 206 free(dirp); 207 errno = saved_errno; 208 return (NULL); 209 } 210 (void)_dup2(fd2, fd); 211 _close(fd2); 212 } | 211 _close(fd2); 212 fd2 = -1; |
213 214 /* 215 * There is now a buffer full of (possibly) duplicate 216 * names. 217 */ 218 dirp->dd_buf = buf; 219 220 /* --- 67 unchanged lines hidden (view full) --- 288 dirp->dd_size = ddptr - dirp->dd_buf; 289 } else { 290 dirp->dd_len = incr; 291 dirp->dd_size = 0; 292 dirp->dd_buf = malloc(dirp->dd_len); 293 if (dirp->dd_buf == NULL) 294 goto fail; 295 dirp->dd_seek = 0; | 213 214 /* 215 * There is now a buffer full of (possibly) duplicate 216 * names. 217 */ 218 dirp->dd_buf = buf; 219 220 /* --- 67 unchanged lines hidden (view full) --- 288 dirp->dd_size = ddptr - dirp->dd_buf; 289 } else { 290 dirp->dd_len = incr; 291 dirp->dd_size = 0; 292 dirp->dd_buf = malloc(dirp->dd_len); 293 if (dirp->dd_buf == NULL) 294 goto fail; 295 dirp->dd_seek = 0; |
296 flags &= ~DTF_REWIND; | |
297 } 298 299 dirp->dd_loc = 0; 300 dirp->dd_fd = fd; 301 dirp->dd_flags = flags; 302 dirp->dd_lock = NULL; 303 304 /* 305 * Set up seek point for rewinddir. 306 */ 307 dirp->dd_rewind = telldir(dirp); 308 309 return (dirp); 310 311fail: 312 saved_errno = errno; | 296 } 297 298 dirp->dd_loc = 0; 299 dirp->dd_fd = fd; 300 dirp->dd_flags = flags; 301 dirp->dd_lock = NULL; 302 303 /* 304 * Set up seek point for rewinddir. 305 */ 306 dirp->dd_rewind = telldir(dirp); 307 308 return (dirp); 309 310fail: 311 saved_errno = errno; |
312 if (fd2 != -1) 313 _close(fd2); |
|
313 free(dirp); 314 errno = saved_errno; 315 return (NULL); 316} | 314 free(dirp); 315 errno = saved_errno; 316 return (NULL); 317} |