summaryrefslogtreecommitdiff
path: root/sysdeps/unix/opendir.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/opendir.c')
-rw-r--r--sysdeps/unix/opendir.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/sysdeps/unix/opendir.c b/sysdeps/unix/opendir.c
index 5e03ed9b20..6aa738fb69 100644
--- a/sysdeps/unix/opendir.c
+++ b/sysdeps/unix/opendir.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-1996,98,2000-2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1991-1996,98,2000-2003,2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -78,11 +78,7 @@ tryopen_o_directory (void)
DIR *
__opendir (const char *name)
{
- DIR *dirp;
struct stat64 statbuf;
- int fd;
- size_t allocation;
- int save_errno;
if (__builtin_expect (name[0], '\1') == '\0')
{
@@ -113,7 +109,7 @@ __opendir (const char *name)
}
}
- fd = open_not_cancel_2 (name, O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE);
+ int fd = open_not_cancel_2 (name, O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE);
if (__builtin_expect (fd, 0) < 0)
return NULL;
@@ -129,18 +125,30 @@ __opendir (const char *name)
{
if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0))
{
- save_errno = ENOTDIR;
- goto lose;
+ __set_errno (ENOTDIR);
+ lose:
+ close_not_cancel_no_status (fd);
+ return NULL;
}
}
+ return __alloc_dir (fd, true, &statbuf);
+}
+weak_alias (__opendir, opendir)
+
+
+DIR *
+internal_function
+__alloc_dir (int fd, bool close_fd, const struct stat64 *statp)
+{
if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
goto lose;
+ size_t allocation;
#ifdef _STATBUF_ST_BLKSIZE
- if (__builtin_expect ((size_t) statbuf.st_blksize >= sizeof (struct dirent64),
+ if (__builtin_expect ((size_t) statp->st_blksize >= sizeof (struct dirent64),
1))
- allocation = statbuf.st_blksize;
+ allocation = statp->st_blksize;
else
#endif
allocation = (BUFSIZ < sizeof (struct dirent64)
@@ -148,13 +156,16 @@ __opendir (const char *name)
const int pad = -sizeof (DIR) % __alignof__ (struct dirent64);
- dirp = (DIR *) malloc (sizeof (DIR) + allocation + pad);
+ DIR *dirp = (DIR *) malloc (sizeof (DIR) + allocation + pad);
if (dirp == NULL)
lose:
{
- save_errno = errno;
- close_not_cancel_no_status (fd);
- __set_errno (save_errno);
+ if (close_fd)
+ {
+ int save_errno = errno;
+ close_not_cancel_no_status (fd);
+ __set_errno (save_errno);
+ }
return NULL;
}
memset (dirp, '\0', sizeof (DIR));
@@ -166,4 +177,3 @@ __opendir (const char *name)
return dirp;
}
-weak_alias (__opendir, opendir)