xref: /haiku/src/system/libroot/posix/glibc/libio/iofdopen.c (revision 5af32e752606778be5dd7379f319fe43cb3f6b8c)
1*5af32e75SAxel Dörfler /* Copyright (C) 1993,1994,1997-1999,2000,2002 Free Software Foundation, Inc.
2*5af32e75SAxel Dörfler    This file is part of the GNU C Library.
3*5af32e75SAxel Dörfler 
4*5af32e75SAxel Dörfler    The GNU C Library is free software; you can redistribute it and/or
5*5af32e75SAxel Dörfler    modify it under the terms of the GNU Lesser General Public
6*5af32e75SAxel Dörfler    License as published by the Free Software Foundation; either
7*5af32e75SAxel Dörfler    version 2.1 of the License, or (at your option) any later version.
8*5af32e75SAxel Dörfler 
9*5af32e75SAxel Dörfler    The GNU C Library is distributed in the hope that it will be useful,
10*5af32e75SAxel Dörfler    but WITHOUT ANY WARRANTY; without even the implied warranty of
11*5af32e75SAxel Dörfler    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12*5af32e75SAxel Dörfler    Lesser General Public License for more details.
13*5af32e75SAxel Dörfler 
14*5af32e75SAxel Dörfler    You should have received a copy of the GNU Lesser General Public
15*5af32e75SAxel Dörfler    License along with the GNU C Library; if not, write to the Free
16*5af32e75SAxel Dörfler    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17*5af32e75SAxel Dörfler    02111-1307 USA.
18*5af32e75SAxel Dörfler 
19*5af32e75SAxel Dörfler    As a special exception, if you link the code in this file with
20*5af32e75SAxel Dörfler    files compiled with a GNU compiler to produce an executable,
21*5af32e75SAxel Dörfler    that does not cause the resulting executable to be covered by
22*5af32e75SAxel Dörfler    the GNU Lesser General Public License.  This exception does not
23*5af32e75SAxel Dörfler    however invalidate any other reasons why the executable file
24*5af32e75SAxel Dörfler    might be covered by the GNU Lesser General Public License.
25*5af32e75SAxel Dörfler    This exception applies to code released by its copyright holders
26*5af32e75SAxel Dörfler    in files containing the exception.
27*5af32e75SAxel Dörfler */
28*5af32e75SAxel Dörfler 
29*5af32e75SAxel Dörfler 
30*5af32e75SAxel Dörfler #include "libioP.h"
31*5af32e75SAxel Dörfler #include <stdlib.h>
32*5af32e75SAxel Dörfler #include <fcntl.h>
33*5af32e75SAxel Dörfler 
34*5af32e75SAxel Dörfler #ifdef _LIBC
35*5af32e75SAxel Dörfler # include <shlib-compat.h>
36*5af32e75SAxel Dörfler #endif
37*5af32e75SAxel Dörfler 
38*5af32e75SAxel Dörfler 
39*5af32e75SAxel Dörfler _IO_FILE *
_IO_new_fdopen(int fd,const char * mode)40*5af32e75SAxel Dörfler _IO_new_fdopen (int fd, const char *mode)
41*5af32e75SAxel Dörfler {
42*5af32e75SAxel Dörfler   int read_write;
43*5af32e75SAxel Dörfler   int posix_mode = 0;
44*5af32e75SAxel Dörfler   struct locked_FILE
45*5af32e75SAxel Dörfler   {
46*5af32e75SAxel Dörfler     struct _IO_FILE_plus fp;
47*5af32e75SAxel Dörfler #ifdef _IO_MTSAFE_IO
48*5af32e75SAxel Dörfler     _IO_lock_t lock;
49*5af32e75SAxel Dörfler #endif
50*5af32e75SAxel Dörfler     struct _IO_wide_data wd;
51*5af32e75SAxel Dörfler   } *new_f;
52*5af32e75SAxel Dörfler   int fd_flags;
53*5af32e75SAxel Dörfler   int i;
54*5af32e75SAxel Dörfler   int use_mmap = 0;
55*5af32e75SAxel Dörfler 
56*5af32e75SAxel Dörfler   switch (*mode)
57*5af32e75SAxel Dörfler     {
58*5af32e75SAxel Dörfler     case 'r':
59*5af32e75SAxel Dörfler       read_write = _IO_NO_WRITES;
60*5af32e75SAxel Dörfler       break;
61*5af32e75SAxel Dörfler     case 'w':
62*5af32e75SAxel Dörfler       read_write = _IO_NO_READS;
63*5af32e75SAxel Dörfler       break;
64*5af32e75SAxel Dörfler     case 'a':
65*5af32e75SAxel Dörfler       posix_mode = O_APPEND;
66*5af32e75SAxel Dörfler       read_write = _IO_NO_READS|_IO_IS_APPENDING;
67*5af32e75SAxel Dörfler       break;
68*5af32e75SAxel Dörfler     default:
69*5af32e75SAxel Dörfler       MAYBE_SET_EINVAL;
70*5af32e75SAxel Dörfler       return NULL;
71*5af32e75SAxel Dörfler   }
72*5af32e75SAxel Dörfler   for (i = 1; i < 5; ++i)
73*5af32e75SAxel Dörfler     {
74*5af32e75SAxel Dörfler       switch (*++mode)
75*5af32e75SAxel Dörfler 	{
76*5af32e75SAxel Dörfler 	case '\0':
77*5af32e75SAxel Dörfler 	  break;
78*5af32e75SAxel Dörfler 	case '+':
79*5af32e75SAxel Dörfler 	  read_write &= _IO_IS_APPENDING;
80*5af32e75SAxel Dörfler 	  break;
81*5af32e75SAxel Dörfler 	case 'm':
82*5af32e75SAxel Dörfler 	  use_mmap = 1;
83*5af32e75SAxel Dörfler 	  continue;
84*5af32e75SAxel Dörfler 	case 'x':
85*5af32e75SAxel Dörfler 	case 'b':
86*5af32e75SAxel Dörfler 	default:
87*5af32e75SAxel Dörfler 	  /* Ignore */
88*5af32e75SAxel Dörfler 	  continue;
89*5af32e75SAxel Dörfler 	}
90*5af32e75SAxel Dörfler       break;
91*5af32e75SAxel Dörfler     }
92*5af32e75SAxel Dörfler #ifdef F_GETFL
93*5af32e75SAxel Dörfler   fd_flags = fcntl(fd, F_GETFL);
94*5af32e75SAxel Dörfler #ifndef O_ACCMODE
95*5af32e75SAxel Dörfler #define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
96*5af32e75SAxel Dörfler #endif
97*5af32e75SAxel Dörfler   if (fd_flags == -1)
98*5af32e75SAxel Dörfler     return NULL;
99*5af32e75SAxel Dörfler 
100*5af32e75SAxel Dörfler   if (((fd_flags & O_ACCMODE) == O_RDONLY && !(read_write & _IO_NO_WRITES))
101*5af32e75SAxel Dörfler       || ((fd_flags & O_ACCMODE) == O_WRONLY && !(read_write & _IO_NO_READS)))
102*5af32e75SAxel Dörfler     {
103*5af32e75SAxel Dörfler       MAYBE_SET_EINVAL;
104*5af32e75SAxel Dörfler       return NULL;
105*5af32e75SAxel Dörfler     }
106*5af32e75SAxel Dörfler 
107*5af32e75SAxel Dörfler   /* The May 93 draft of P1003.4/D14.1 (redesignated as 1003.1b)
108*5af32e75SAxel Dörfler      [System Application Program Interface (API) Amendment 1:
109*5af32e75SAxel Dörfler      Realtime Extensions], Rationale B.8.3.3
110*5af32e75SAxel Dörfler      Open a Stream on a File Descriptor says:
111*5af32e75SAxel Dörfler 
112*5af32e75SAxel Dörfler          Although not explicitly required by POSIX.1, a good
113*5af32e75SAxel Dörfler          implementation of append ("a") mode would cause the
114*5af32e75SAxel Dörfler          O_APPEND flag to be set.
115*5af32e75SAxel Dörfler 
116*5af32e75SAxel Dörfler      (Historical implementations [such as Solaris2] do a one-time
117*5af32e75SAxel Dörfler      seek in fdopen.)
118*5af32e75SAxel Dörfler 
119*5af32e75SAxel Dörfler      However, we do not turn O_APPEND off if the mode is "w" (even
120*5af32e75SAxel Dörfler      though that would seem consistent) because that would be more
121*5af32e75SAxel Dörfler      likely to break historical programs.
122*5af32e75SAxel Dörfler      */
123*5af32e75SAxel Dörfler   if ((posix_mode & O_APPEND) && !(fd_flags & O_APPEND))
124*5af32e75SAxel Dörfler     {
125*5af32e75SAxel Dörfler #ifdef F_SETFL
126*5af32e75SAxel Dörfler       if (fcntl(fd, F_SETFL, fd_flags | O_APPEND) == -1)
127*5af32e75SAxel Dörfler #endif
128*5af32e75SAxel Dörfler 	return NULL;
129*5af32e75SAxel Dörfler     }
130*5af32e75SAxel Dörfler #endif
131*5af32e75SAxel Dörfler 
132*5af32e75SAxel Dörfler   new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
133*5af32e75SAxel Dörfler   if (new_f == NULL)
134*5af32e75SAxel Dörfler     return NULL;
135*5af32e75SAxel Dörfler #ifdef _IO_MTSAFE_IO
136*5af32e75SAxel Dörfler   new_f->fp.file._lock = &new_f->lock;
137*5af32e75SAxel Dörfler #endif
138*5af32e75SAxel Dörfler   /* Set up initially to use the `maybe_mmap' jump tables rather than using
139*5af32e75SAxel Dörfler      __fopen_maybe_mmap to do it, because we need them in place before we
140*5af32e75SAxel Dörfler      call _IO_file_attach or else it will allocate a buffer immediately.  */
141*5af32e75SAxel Dörfler   _IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd,
142*5af32e75SAxel Dörfler #ifdef _G_HAVE_MMAP
143*5af32e75SAxel Dörfler 	       (use_mmap && (read_write & _IO_NO_WRITES))
144*5af32e75SAxel Dörfler 	       ? &_IO_wfile_jumps_maybe_mmap :
145*5af32e75SAxel Dörfler #endif
146*5af32e75SAxel Dörfler 	       &INTUSE(_IO_wfile_jumps));
147*5af32e75SAxel Dörfler   _IO_JUMPS (&new_f->fp) =
148*5af32e75SAxel Dörfler #ifdef _G_HAVE_MMAP
149*5af32e75SAxel Dörfler     (use_mmap && (read_write & _IO_NO_WRITES)) ? &_IO_file_jumps_maybe_mmap :
150*5af32e75SAxel Dörfler #endif
151*5af32e75SAxel Dörfler       &INTUSE(_IO_file_jumps);
152*5af32e75SAxel Dörfler   INTUSE(_IO_file_init) (&new_f->fp);
153*5af32e75SAxel Dörfler #if  !_IO_UNIFIED_JUMPTABLES
154*5af32e75SAxel Dörfler   new_f->fp.vtable = NULL;
155*5af32e75SAxel Dörfler #endif
156*5af32e75SAxel Dörfler   if (INTUSE(_IO_file_attach) ((_IO_FILE *) &new_f->fp, fd) == NULL)
157*5af32e75SAxel Dörfler     {
158*5af32e75SAxel Dörfler       INTUSE(_IO_setb) (&new_f->fp.file, NULL, NULL, 0);
159*5af32e75SAxel Dörfler       INTUSE(_IO_un_link) (&new_f->fp);
160*5af32e75SAxel Dörfler       free (new_f);
161*5af32e75SAxel Dörfler       return NULL;
162*5af32e75SAxel Dörfler     }
163*5af32e75SAxel Dörfler   new_f->fp.file._flags &= ~_IO_DELETE_DONT_CLOSE;
164*5af32e75SAxel Dörfler 
165*5af32e75SAxel Dörfler   new_f->fp.file._IO_file_flags =
166*5af32e75SAxel Dörfler     _IO_mask_flags (&new_f->fp.file, read_write,
167*5af32e75SAxel Dörfler 		    _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
168*5af32e75SAxel Dörfler 
169*5af32e75SAxel Dörfler   return &new_f->fp.file;
170*5af32e75SAxel Dörfler }
171*5af32e75SAxel Dörfler INTDEF2(_IO_new_fdopen, _IO_fdopen)
172*5af32e75SAxel Dörfler 
173*5af32e75SAxel Dörfler strong_alias (_IO_new_fdopen, __new_fdopen)
174*5af32e75SAxel Dörfler versioned_symbol (libc, _IO_new_fdopen, _IO_fdopen, GLIBC_2_1);
175*5af32e75SAxel Dörfler versioned_symbol (libc, __new_fdopen, fdopen, GLIBC_2_1);
176