summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2006-02-04 03:24:24 +0000
committerMike Frysinger <vapier@gentoo.org>2006-02-04 03:24:24 +0000
commitad6612eb8e130cf4b43824917809e1fb2f253f42 (patch)
tree83c76a1c5aadb472e511729995aca66c9938c6a5
parente1982ac32aa0edf24703d210861df504409bfa91 (diff)
rfelker reports in Bug 683 that we leak file descriptors if the fcntl() fails ... so fix that. add back in fstat() ofter we open() the directory as we need the blocksize further down in the code. unify the memory error handling to shrink the code there a little.
-rw-r--r--libc/misc/dirent/opendir.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/libc/misc/dirent/opendir.c b/libc/misc/dirent/opendir.c
index 318f4bef2..1b11f65a8 100644
--- a/libc/misc/dirent/opendir.c
+++ b/libc/misc/dirent/opendir.c
@@ -27,7 +27,6 @@ DIR *opendir(const char *name)
{
int fd;
struct stat statbuf;
- char *buf;
DIR *ptr;
#ifndef O_DIRECTORY
@@ -42,21 +41,27 @@ DIR *opendir(const char *name)
#endif
if ((fd = open(name, O_RDONLY|O_NDELAY|O_DIRECTORY)) < 0)
return NULL;
+
/* Note: we should check to make sure that between the stat() and open()
* call, 'name' didnt change on us, but that's only if O_DIRECTORY isnt
* defined and since Linux has supported it for like ever, i'm not going
* to worry about it right now (if ever). */
+ if (fstat(fd, &statbuf) < 0)
+ goto close_and_ret;
/* According to POSIX, directory streams should be closed when
* exec. From "Anna Pluzhnikov" <besp@midway.uchicago.edu>.
*/
- if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
- return NULL;
- if (!(ptr = malloc(sizeof(*ptr)))) {
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
+ int saved_errno;
+close_and_ret:
+ saved_errno = errno;
close(fd);
- __set_errno(ENOMEM);
+ __set_errno(saved_errno);
return NULL;
}
+ if (!(ptr = malloc(sizeof(*ptr))))
+ goto nomem_close_and_ret;
ptr->dd_fd = fd;
ptr->dd_nextloc = ptr->dd_size = ptr->dd_nextoff = 0;
@@ -65,13 +70,13 @@ DIR *opendir(const char *name)
if (ptr->dd_max < 512)
ptr->dd_max = 512;
- if (!(buf = calloc(1, ptr->dd_max))) {
- close(fd);
+ if (!(ptr->dd_buf = calloc(1, ptr->dd_max))) {
free(ptr);
+nomem_close_and_ret:
+ close(fd);
__set_errno(ENOMEM);
return NULL;
}
- ptr->dd_buf = buf;
__pthread_mutex_init(&(ptr->dd_lock), NULL);
return ptr;
}