Initial revision
[kopensolaris-gnu/glibc.git] / sysdeps / unix / opendir.c
1 /* Copyright (C) 1991 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is distributed in the hope that it will be useful, but
5 WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility for
6 the consequences of using it or for whether it serves any particular
7 purpose or works at all, unless he says so in writing.  Refer to the GNU
8 C Library General Public License (in the file COPYING) for full details.
9
10 Everyone is granted permission to copy, modify and redistribute
11 the GNU C Library, but only under the conditions described in the
12 GNU C Library General Public License.  Among other things, this notice
13 must not be changed and a copy of the license must be included.  */
14
15 #include <ansidecl.h>
16 #include <errno.h>
17 #include <limits.h>
18 #include <stddef.h>
19 #include <stdlib.h>
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <bsddir.h>
26
27 /* Open a directory stream on NAME.  */
28 DIR *
29 DEFUN(opendir, (name), CONST char *name)
30 {
31   DIR *dirp;
32   struct stat statbuf;
33   int fd;
34
35   fd = __open(name, O_RDONLY);
36   if (fd < 0)
37     return NULL;
38
39   {
40     int flags = FD_CLOEXEC;
41     if (fcntl(fd, F_SETFD, &flags) < 0)
42       return NULL;
43   }
44
45   dirp = (DIR *) malloc(sizeof(DIR) + NAME_MAX);
46   if (dirp == NULL)
47     {
48       int save = errno;
49       (void) __close(fd);
50       errno = save;
51       return NULL;
52     }
53
54   if (__fstat(fd, &statbuf) < 0 || statbuf.st_blksize < sizeof(struct direct))
55     dirp->__allocation = sizeof(struct direct);
56   else
57     dirp->__allocation = statbuf.st_blksize;
58   dirp->__data = (char *) malloc(dirp->__allocation);
59   if (dirp->__data == NULL)
60     {
61       int save = errno;
62       free((PTR) dirp);
63       (void) __close(fd);
64       errno = save;
65       return NULL;
66     }
67
68   dirp->__fd = fd;
69   dirp->__offset = 0;
70   dirp->__size = 0;
71   return dirp;
72 }