Upgrade to gcc-4.9.2
[akaros.git] / tools / compilers / gcc-glibc / glibc-2.14.1-ros / sysdeps / unix / opendir.c
1 /* Copyright (C) 1991-1996,98,2000-2003,2005,2007,2009,2011
2    Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <errno.h>
21 #include <limits.h>
22 #include <stddef.h>
23 #include <stdlib.h>
24 #include <dirent.h>
25 #include <fcntl.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #include <dirstream.h>
33 #include <not-cancel.h>
34 #include <kernel-features.h>
35
36
37 /* opendir() must not accidentally open something other than a directory.
38    Some OS's have kernel support for that, some don't.  In the worst
39    case we have to stat() before the open() AND fstat() after.
40
41    We have to test at runtime for kernel support since libc may have
42    been compiled with different headers to the kernel it's running on.
43    This test can't be done reliably in the general case.  We'll use
44    /dev/null, which if it's not a device lots of stuff will break, as
45    a guinea pig.  It may be missing in chroot environments, so we
46    make sure to fail safe. */
47 #ifdef O_DIRECTORY
48 # ifdef O_DIRECTORY_WORKS
49 #  define o_directory_works 1
50 #  define tryopen_o_directory() while (1) /* This must not be called.  */
51 # else
52 static int o_directory_works;
53
54 static void
55 tryopen_o_directory (void)
56 {
57   int serrno = errno;
58   int x = open_not_cancel_2 ("/dev/null", O_RDONLY|O_NDELAY|O_DIRECTORY);
59
60   if (x >= 0)
61     {
62       close_not_cancel_no_status (x);
63       o_directory_works = -1;
64     }
65   else if (errno != ENOTDIR)
66     o_directory_works = -1;
67   else
68     o_directory_works = 1;
69
70   __set_errno (serrno);
71 }
72 # endif
73 # define EXTRA_FLAGS O_DIRECTORY
74 #else
75 # define EXTRA_FLAGS 0
76 #endif
77
78
79 /* Open a directory stream on NAME.  */
80 DIR *
81 __opendir (const char *name)
82 {
83   struct stat64 statbuf;
84   struct stat64 *statp = NULL;
85
86   if (__builtin_expect (name[0], '\1') == '\0')
87     {
88       /* POSIX.1-1990 says an empty name gets ENOENT;
89          but `open' might like it fine.  */
90       __set_errno (ENOENT);
91       return NULL;
92     }
93
94 #ifdef O_DIRECTORY
95   /* Test whether O_DIRECTORY works.  */
96   if (o_directory_works == 0)
97     tryopen_o_directory ();
98
99   /* We can skip the expensive `stat' call if O_DIRECTORY works.  */
100   if (o_directory_works < 0)
101 #endif
102     {
103       /* We first have to check whether the name is for a directory.  We
104          cannot do this after the open() call since the open/close operation
105          performed on, say, a tape device might have undesirable effects.  */
106       if (__builtin_expect (__xstat64 (_STAT_VER, name, &statbuf), 0) < 0)
107         return NULL;
108       if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0))
109         {
110           __set_errno (ENOTDIR);
111           return NULL;
112          }
113     }
114
115   int flags = O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE;
116 #ifdef O_CLOEXEC
117   flags |= O_CLOEXEC;
118 #endif
119   int fd = open_not_cancel_2 (name, flags);
120   if (__builtin_expect (fd, 0) < 0)
121     return NULL;
122
123 #ifdef O_DIRECTORY
124   if (o_directory_works <= 0)
125 #endif
126     {
127       /* Now make sure this really is a directory and nothing changed since
128          the `stat' call.  */
129       if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &statbuf), 0) < 0)
130         goto lose;
131       if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0))
132         {
133           __set_errno (ENOTDIR);
134         lose:
135           close_not_cancel_no_status (fd);
136           return NULL;
137         }
138       statp = &statbuf;
139     }
140
141   return __alloc_dir (fd, true, 0, statp);
142 }
143 weak_alias (__opendir, opendir)
144
145
146 #ifdef __ASSUME_O_CLOEXEC
147 # define check_have_o_cloexec(fd) 1
148 #elif defined O_CLOEXEC
149 static int
150 check_have_o_cloexec (int fd)
151 {
152   if (__have_o_cloexec == 0)
153     __have_o_cloexec = (__fcntl (fd, F_GETFD, 0) & FD_CLOEXEC) == 0 ? -1 : 1;
154   return __have_o_cloexec > 0;
155 }
156 #endif
157
158
159 DIR *
160 internal_function
161 __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
162 {
163   /* We always have to set the close-on-exit flag if the user provided
164      the file descriptor.  Otherwise only if we have no working
165      O_CLOEXEC support.  */
166 #ifdef O_CLOEXEC
167   if ((! close_fd && (flags & O_CLOEXEC) == 0)
168       || ! check_have_o_cloexec (fd))
169 #endif
170     {
171       if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
172         goto lose;
173     }
174
175   const size_t default_allocation = (4 * BUFSIZ < sizeof (struct dirent64)
176                                      ? sizeof (struct dirent64) : 4 * BUFSIZ);
177   const size_t small_allocation = (BUFSIZ < sizeof (struct dirent64)
178                                    ? sizeof (struct dirent64) : BUFSIZ);
179   size_t allocation = default_allocation;
180 #ifdef _STATBUF_ST_BLKSIZE
181   if (statp != NULL && default_allocation < statp->st_blksize)
182     allocation = statp->st_blksize;
183 #endif
184
185   DIR *dirp = (DIR *) malloc (sizeof (DIR) + allocation);
186   if (dirp == NULL)
187     {
188       allocation = small_allocation;
189       dirp = (DIR *) malloc (sizeof (DIR) + allocation);
190
191       if (dirp == NULL)
192       lose:
193         {
194           if (close_fd)
195             {
196               int save_errno = errno;
197               close_not_cancel_no_status (fd);
198               __set_errno (save_errno);
199             }
200           return NULL;
201         }
202     }
203
204   dirp->fd = fd;
205 #ifndef NOT_IN_libc
206   __libc_lock_init (dirp->lock);
207 #endif
208   dirp->allocation = allocation;
209   dirp->size = 0;
210   dirp->offset = 0;
211   dirp->filepos = 0;
212
213   return dirp;
214 }