fdwalk should return 0 on an empty directory
[kopensolaris-gnu/glibc.git] / libio / iofdopen.c
1 /* Copyright (C) 1993,1994,1997,1998,1999,2000,2002,2003
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    As a special exception, if you link the code in this file with
21    files compiled with a GNU compiler to produce an executable,
22    that does not cause the resulting executable to be covered by
23    the GNU Lesser General Public License.  This exception does not
24    however invalidate any other reasons why the executable file
25    might be covered by the GNU Lesser General Public License.
26    This exception applies to code released by its copyright holders
27    in files containing the exception.  */
28
29 #ifdef __STDC__
30 # include <stdlib.h>
31 #endif
32 #include "libioP.h"
33 #include <fcntl.h>
34
35 #ifdef _LIBC
36 # include <shlib-compat.h>
37 #endif
38
39 #ifndef _IO_fcntl
40 #ifdef _LIBC
41 #define _IO_fcntl __fcntl
42 #else
43 #define _IO_fcntl fcntl
44 #endif
45 #endif
46
47 _IO_FILE *
48 _IO_new_fdopen (fd, mode)
49      int fd;
50      const char *mode;
51 {
52   int read_write;
53   int posix_mode = 0;
54   struct locked_FILE
55   {
56     struct _IO_FILE_plus fp;
57 #ifdef _IO_MTSAFE_IO
58     _IO_lock_t lock;
59 #endif
60     struct _IO_wide_data wd;
61   } *new_f;
62   int fd_flags;
63   int i;
64   int use_mmap = 0;
65
66   switch (*mode)
67     {
68     case 'r':
69       read_write = _IO_NO_WRITES;
70       break;
71     case 'w':
72       read_write = _IO_NO_READS;
73       break;
74     case 'a':
75       posix_mode = O_APPEND;
76       read_write = _IO_NO_READS|_IO_IS_APPENDING;
77       break;
78     default:
79       MAYBE_SET_EINVAL;
80       return NULL;
81   }
82   for (i = 1; i < 5; ++i)
83     {
84       switch (*++mode)
85         {
86         case '\0':
87           break;
88         case '+':
89           read_write &= _IO_IS_APPENDING;
90           break;
91         case 'm':
92           use_mmap = 1;
93           continue;
94         case 'x':
95         case 'b':
96         default:
97           /* Ignore */
98           continue;
99         }
100       break;
101     }
102 #ifdef F_GETFL
103   fd_flags = _IO_fcntl (fd, F_GETFL);
104 #ifndef O_ACCMODE
105 #define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
106 #endif
107   if (fd_flags == -1)
108     return NULL;
109
110   if (((fd_flags & O_ACCMODE) == O_RDONLY && !(read_write & _IO_NO_WRITES))
111       || ((fd_flags & O_ACCMODE) == O_WRONLY && !(read_write & _IO_NO_READS)))
112     {
113       MAYBE_SET_EINVAL;
114       return NULL;
115     }
116
117   /* The May 93 draft of P1003.4/D14.1 (redesignated as 1003.1b)
118      [System Application Program Interface (API) Amendment 1:
119      Realtime Extensions], Rationale B.8.3.3
120      Open a Stream on a File Descriptor says:
121
122          Although not explicitly required by POSIX.1, a good
123          implementation of append ("a") mode would cause the
124          O_APPEND flag to be set.
125
126      (Historical implementations [such as Solaris2] do a one-time
127      seek in fdopen.)
128
129      However, we do not turn O_APPEND off if the mode is "w" (even
130      though that would seem consistent) because that would be more
131      likely to break historical programs.
132      */
133   if ((posix_mode & O_APPEND) && !(fd_flags & O_APPEND))
134     {
135 #ifdef F_SETFL
136       if (_IO_fcntl (fd, F_SETFL, fd_flags | O_APPEND) == -1)
137 #endif
138         return NULL;
139     }
140 #endif
141
142   new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
143   if (new_f == NULL)
144     return NULL;
145 #ifdef _IO_MTSAFE_IO
146   new_f->fp.file._lock = &new_f->lock;
147 #endif
148   /* Set up initially to use the `maybe_mmap' jump tables rather than using
149      __fopen_maybe_mmap to do it, because we need them in place before we
150      call _IO_file_attach or else it will allocate a buffer immediately.  */
151   _IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd,
152 #ifdef _G_HAVE_MMAP
153                (use_mmap && (read_write & _IO_NO_WRITES))
154                ? &_IO_wfile_jumps_maybe_mmap :
155 #endif
156                &_IO_wfile_jumps);
157   _IO_JUMPS (&new_f->fp) =
158 #ifdef _G_HAVE_MMAP
159     (use_mmap && (read_write & _IO_NO_WRITES)) ? &_IO_file_jumps_maybe_mmap :
160 #endif
161       &_IO_file_jumps;
162   INTUSE(_IO_file_init) (&new_f->fp);
163 #if  !_IO_UNIFIED_JUMPTABLES
164   new_f->fp.vtable = NULL;
165 #endif
166   if (INTUSE(_IO_file_attach) ((_IO_FILE *) &new_f->fp, fd) == NULL)
167     {
168       INTUSE(_IO_setb) (&new_f->fp.file, NULL, NULL, 0);
169       INTUSE(_IO_un_link) (&new_f->fp);
170       free (new_f);
171       return NULL;
172     }
173   new_f->fp.file._flags &= ~_IO_DELETE_DONT_CLOSE;
174
175   new_f->fp.file._IO_file_flags =
176     _IO_mask_flags (&new_f->fp.file, read_write,
177                     _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
178
179   return &new_f->fp.file;
180 }
181 INTDEF2(_IO_new_fdopen, _IO_fdopen)
182
183 strong_alias (_IO_new_fdopen, __new_fdopen)
184 versioned_symbol (libc, _IO_new_fdopen, _IO_fdopen, GLIBC_2_1);
185 versioned_symbol (libc, __new_fdopen, fdopen, GLIBC_2_1);