Back to index

glibc  2.9
iofdopen.c
Go to the documentation of this file.
00001 /* Copyright (C) 1993,1994,1997,1998,1999,2000,2002,2003
00002        Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.
00019 
00020    As a special exception, if you link the code in this file with
00021    files compiled with a GNU compiler to produce an executable,
00022    that does not cause the resulting executable to be covered by
00023    the GNU Lesser General Public License.  This exception does not
00024    however invalidate any other reasons why the executable file
00025    might be covered by the GNU Lesser General Public License.
00026    This exception applies to code released by its copyright holders
00027    in files containing the exception.  */
00028 
00029 #ifdef __STDC__
00030 # include <stdlib.h>
00031 #endif
00032 #include "libioP.h"
00033 #include <fcntl.h>
00034 
00035 #ifdef _LIBC
00036 # include <shlib-compat.h>
00037 #endif
00038 
00039 #ifndef _IO_fcntl
00040 #ifdef _LIBC
00041 #define _IO_fcntl __fcntl
00042 #else
00043 #define _IO_fcntl fcntl
00044 #endif
00045 #endif
00046 
00047 _IO_FILE *
00048 _IO_new_fdopen (fd, mode)
00049      int fd;
00050      const char *mode;
00051 {
00052   int read_write;
00053   int posix_mode = 0;
00054   struct locked_FILE
00055   {
00056     struct _IO_FILE_plus fp;
00057 #ifdef _IO_MTSAFE_IO
00058     _IO_lock_t lock;
00059 #endif
00060     struct _IO_wide_data wd;
00061   } *new_f;
00062   int fd_flags;
00063   int i;
00064   int use_mmap = 0;
00065 
00066   switch (*mode)
00067     {
00068     case 'r':
00069       read_write = _IO_NO_WRITES;
00070       break;
00071     case 'w':
00072       read_write = _IO_NO_READS;
00073       break;
00074     case 'a':
00075       posix_mode = O_APPEND;
00076       read_write = _IO_NO_READS|_IO_IS_APPENDING;
00077       break;
00078     default:
00079       MAYBE_SET_EINVAL;
00080       return NULL;
00081   }
00082   for (i = 1; i < 5; ++i)
00083     {
00084       switch (*++mode)
00085        {
00086        case '\0':
00087          break;
00088        case '+':
00089          read_write &= _IO_IS_APPENDING;
00090          break;
00091        case 'm':
00092          use_mmap = 1;
00093          continue;
00094        case 'x':
00095        case 'b':
00096        default:
00097          /* Ignore */
00098          continue;
00099        }
00100       break;
00101     }
00102 #ifdef F_GETFL
00103   fd_flags = _IO_fcntl (fd, F_GETFL);
00104 #ifndef O_ACCMODE
00105 #define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
00106 #endif
00107   if (fd_flags == -1)
00108     return NULL;
00109 
00110   if (((fd_flags & O_ACCMODE) == O_RDONLY && !(read_write & _IO_NO_WRITES))
00111       || ((fd_flags & O_ACCMODE) == O_WRONLY && !(read_write & _IO_NO_READS)))
00112     {
00113       MAYBE_SET_EINVAL;
00114       return NULL;
00115     }
00116 
00117   /* The May 93 draft of P1003.4/D14.1 (redesignated as 1003.1b)
00118      [System Application Program Interface (API) Amendment 1:
00119      Realtime Extensions], Rationale B.8.3.3
00120      Open a Stream on a File Descriptor says:
00121 
00122          Although not explicitly required by POSIX.1, a good
00123          implementation of append ("a") mode would cause the
00124          O_APPEND flag to be set.
00125 
00126      (Historical implementations [such as Solaris2] do a one-time
00127      seek in fdopen.)
00128 
00129      However, we do not turn O_APPEND off if the mode is "w" (even
00130      though that would seem consistent) because that would be more
00131      likely to break historical programs.
00132      */
00133   if ((posix_mode & O_APPEND) && !(fd_flags & O_APPEND))
00134     {
00135 #ifdef F_SETFL
00136       if (_IO_fcntl (fd, F_SETFL, fd_flags | O_APPEND) == -1)
00137 #endif
00138        return NULL;
00139     }
00140 #endif
00141 
00142   new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
00143   if (new_f == NULL)
00144     return NULL;
00145 #ifdef _IO_MTSAFE_IO
00146   new_f->fp.file._lock = &new_f->lock;
00147 #endif
00148   /* Set up initially to use the `maybe_mmap' jump tables rather than using
00149      __fopen_maybe_mmap to do it, because we need them in place before we
00150      call _IO_file_attach or else it will allocate a buffer immediately.  */
00151   _IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd,
00152 #ifdef _G_HAVE_MMAP
00153               (use_mmap && (read_write & _IO_NO_WRITES))
00154               ? &_IO_wfile_jumps_maybe_mmap :
00155 #endif
00156               &_IO_wfile_jumps);
00157   _IO_JUMPS (&new_f->fp) =
00158 #ifdef _G_HAVE_MMAP
00159     (use_mmap && (read_write & _IO_NO_WRITES)) ? &_IO_file_jumps_maybe_mmap :
00160 #endif
00161       &_IO_file_jumps;
00162   INTUSE(_IO_file_init) (&new_f->fp);
00163 #if  !_IO_UNIFIED_JUMPTABLES
00164   new_f->fp.vtable = NULL;
00165 #endif
00166   if (INTUSE(_IO_file_attach) ((_IO_FILE *) &new_f->fp, fd) == NULL)
00167     {
00168       INTUSE(_IO_setb) (&new_f->fp.file, NULL, NULL, 0);
00169       INTUSE(_IO_un_link) (&new_f->fp);
00170       free (new_f);
00171       return NULL;
00172     }
00173   new_f->fp.file._flags &= ~_IO_DELETE_DONT_CLOSE;
00174 
00175   new_f->fp.file._IO_file_flags =
00176     _IO_mask_flags (&new_f->fp.file, read_write,
00177                   _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
00178 
00179   return &new_f->fp.file;
00180 }
00181 INTDEF2(_IO_new_fdopen, _IO_fdopen)
00182 
00183 strong_alias (_IO_new_fdopen, __new_fdopen)
00184 versioned_symbol (libc, _IO_new_fdopen, _IO_fdopen, GLIBC_2_1);
00185 versioned_symbol (libc, __new_fdopen, fdopen, GLIBC_2_1);