| xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame] | 1 | /* Copyright (C) 1993-2016 Free Software Foundation, Inc. | 
 | 2 |    This file is part of the GNU C Library. | 
 | 3 |  | 
 | 4 |    The GNU C Library is free software; you can redistribute it and/or | 
 | 5 |    modify it under the terms of the GNU Lesser General Public | 
 | 6 |    License as published by the Free Software Foundation; either | 
 | 7 |    version 2.1 of the License, or (at your option) any later version. | 
 | 8 |  | 
 | 9 |    The GNU C Library is distributed in the hope that it will be useful, | 
 | 10 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 11 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 | 12 |    Lesser General Public License for more details. | 
 | 13 |  | 
 | 14 |    You should have received a copy of the GNU Lesser General Public | 
 | 15 |    License along with the GNU C Library; if not, see | 
 | 16 |    <http://www.gnu.org/licenses/>. | 
 | 17 |  | 
 | 18 |    As a special exception, if you link the code in this file with | 
 | 19 |    files compiled with a GNU compiler to produce an executable, | 
 | 20 |    that does not cause the resulting executable to be covered by | 
 | 21 |    the GNU Lesser General Public License.  This exception does not | 
 | 22 |    however invalidate any other reasons why the executable file | 
 | 23 |    might be covered by the GNU Lesser General Public License. | 
 | 24 |    This exception applies to code released by its copyright holders | 
 | 25 |    in files containing the exception.  */ | 
 | 26 |  | 
 | 27 | #include <shlib-compat.h> | 
 | 28 | #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1) | 
 | 29 |  | 
 | 30 | #define _IO_USE_OLD_IO_FILE | 
 | 31 | #include <stdlib.h> | 
 | 32 | #include "libioP.h" | 
 | 33 | #include <fcntl.h> | 
 | 34 |  | 
 | 35 | #ifndef _IO_fcntl | 
 | 36 | # define _IO_fcntl __fcntl | 
 | 37 | #endif | 
 | 38 |  | 
 | 39 | _IO_FILE * | 
 | 40 | attribute_compat_text_section | 
 | 41 | _IO_old_fdopen (int fd, const char *mode) | 
 | 42 | { | 
 | 43 |   int read_write; | 
 | 44 |   int posix_mode = 0; | 
 | 45 |   struct locked_FILE | 
 | 46 |   { | 
 | 47 |     struct _IO_FILE_complete_plus fp; | 
 | 48 | #ifdef _IO_MTSAFE_IO | 
 | 49 |     _IO_lock_t lock; | 
 | 50 | #endif | 
 | 51 |   } *new_f; | 
 | 52 |   int fd_flags; | 
 | 53 |  | 
 | 54 |   switch (*mode++) | 
 | 55 |     { | 
 | 56 |     case 'r': | 
 | 57 |       read_write = _IO_NO_WRITES; | 
 | 58 |       break; | 
 | 59 |     case 'w': | 
 | 60 |       read_write = _IO_NO_READS; | 
 | 61 |       break; | 
 | 62 |     case 'a': | 
 | 63 |       posix_mode = O_APPEND; | 
 | 64 |       read_write = _IO_NO_READS|_IO_IS_APPENDING; | 
 | 65 |       break; | 
 | 66 |     default: | 
 | 67 |       MAYBE_SET_EINVAL; | 
 | 68 |       return NULL; | 
 | 69 |   } | 
 | 70 |   if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+')) | 
 | 71 |     read_write &= _IO_IS_APPENDING; | 
 | 72 | #ifdef F_GETFL | 
 | 73 |   fd_flags = _IO_fcntl (fd, F_GETFL); | 
 | 74 | #ifndef O_ACCMODE | 
 | 75 | #define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) | 
 | 76 | #endif | 
 | 77 |   if (fd_flags == -1 | 
 | 78 |       || ((fd_flags & O_ACCMODE) == O_RDONLY && !(read_write & _IO_NO_WRITES)) | 
 | 79 |       || ((fd_flags & O_ACCMODE) == O_WRONLY && !(read_write & _IO_NO_READS))) | 
 | 80 |     return NULL; | 
 | 81 |  | 
 | 82 |   /* The May 93 draft of P1003.4/D14.1 (redesignated as 1003.1b) | 
 | 83 |      [System Application Program Interface (API) Amendment 1: | 
 | 84 |      Realtime Extensions], Rationale B.8.3.3 | 
 | 85 |      Open a Stream on a File Descriptor says: | 
 | 86 |  | 
 | 87 |          Although not explicitly required by POSIX.1, a good | 
 | 88 |          implementation of append ("a") mode would cause the | 
 | 89 |          O_APPEND flag to be set. | 
 | 90 |  | 
 | 91 |      (Historical implementations [such as Solaris2] do a one-time | 
 | 92 |      seek in fdopen.) | 
 | 93 |  | 
 | 94 |      However, we do not turn O_APPEND off if the mode is "w" (even | 
 | 95 |      though that would seem consistent) because that would be more | 
 | 96 |      likely to break historical programs. | 
 | 97 |      */ | 
 | 98 |   if ((posix_mode & O_APPEND) && !(fd_flags & O_APPEND)) | 
 | 99 |     { | 
 | 100 | #ifdef F_SETFL | 
 | 101 |       if (_IO_fcntl (fd, F_SETFL, fd_flags | O_APPEND) == -1) | 
 | 102 | #endif | 
 | 103 | 	return NULL; | 
 | 104 |     } | 
 | 105 | #endif | 
 | 106 |  | 
 | 107 |   new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE)); | 
 | 108 |   if (new_f == NULL) | 
 | 109 |     return NULL; | 
 | 110 | #ifdef _IO_MTSAFE_IO | 
 | 111 |   new_f->fp.file._file._lock = &new_f->lock; | 
 | 112 | #endif | 
 | 113 |   _IO_old_init (&new_f->fp.file._file, 0); | 
 | 114 |   _IO_JUMPS_FILE_plus (&new_f->fp) = &_IO_old_file_jumps; | 
 | 115 |   _IO_old_file_init ((struct _IO_FILE_plus *) &new_f->fp); | 
 | 116 | #if  !_IO_UNIFIED_JUMPTABLES | 
 | 117 |   new_f->fp.vtable = NULL; | 
 | 118 | #endif | 
 | 119 |   if (_IO_old_file_attach (&new_f->fp.file._file, fd) == NULL) | 
 | 120 |     { | 
 | 121 |       _IO_un_link ((struct _IO_FILE_plus *) &new_f->fp); | 
 | 122 |       free (new_f); | 
 | 123 |       return NULL; | 
 | 124 |     } | 
 | 125 |   new_f->fp.file._file._flags &= ~_IO_DELETE_DONT_CLOSE; | 
 | 126 |  | 
 | 127 |   _IO_mask_flags (&new_f->fp.file._file, read_write, | 
 | 128 | 		  _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING); | 
 | 129 |  | 
 | 130 |   return (_IO_FILE *) &new_f->fp; | 
 | 131 | } | 
 | 132 |  | 
 | 133 | strong_alias (_IO_old_fdopen, __old_fdopen) | 
 | 134 | compat_symbol (libc, _IO_old_fdopen, _IO_fdopen, GLIBC_2_0); | 
 | 135 | compat_symbol (libc, __old_fdopen, fdopen, GLIBC_2_0); | 
 | 136 |  | 
 | 137 | #endif |