12a6b7db3Sskrll /* Implement fopen_unlocked and related functions.
2*f22f0ef4Schristos    Copyright (C) 2005-2022 Free Software Foundation, Inc.
32a6b7db3Sskrll    Written by Kaveh R. Ghazi <ghazi@caip.rutgers.edu>.
42a6b7db3Sskrll 
52a6b7db3Sskrll This file is part of the libiberty library.
62a6b7db3Sskrll Libiberty is free software; you can redistribute it and/or
72a6b7db3Sskrll modify it under the terms of the GNU Library General Public
82a6b7db3Sskrll License as published by the Free Software Foundation; either
92a6b7db3Sskrll version 2 of the License, or (at your option) any later version.
102a6b7db3Sskrll 
112a6b7db3Sskrll Libiberty is distributed in the hope that it will be useful,
122a6b7db3Sskrll but WITHOUT ANY WARRANTY; without even the implied warranty of
132a6b7db3Sskrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
142a6b7db3Sskrll Library General Public License for more details.
152a6b7db3Sskrll 
162a6b7db3Sskrll You should have received a copy of the GNU Library General Public
172a6b7db3Sskrll License along with libiberty; see the file COPYING.LIB.  If
182a6b7db3Sskrll not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
192a6b7db3Sskrll Boston, MA 02110-1301, USA.  */
202a6b7db3Sskrll 
212a6b7db3Sskrll /*
222a6b7db3Sskrll 
232a6b7db3Sskrll @deftypefn Extension void unlock_stream (FILE * @var{stream})
242a6b7db3Sskrll 
252a6b7db3Sskrll If the OS supports it, ensure that the supplied stream is setup to
262a6b7db3Sskrll avoid any multi-threaded locking.  Otherwise leave the @code{FILE}
272a6b7db3Sskrll pointer unchanged.  If the @var{stream} is @code{NULL} do nothing.
282a6b7db3Sskrll 
292a6b7db3Sskrll @end deftypefn
302a6b7db3Sskrll 
312a6b7db3Sskrll @deftypefn Extension void unlock_std_streams (void)
322a6b7db3Sskrll 
332a6b7db3Sskrll If the OS supports it, ensure that the standard I/O streams,
342a6b7db3Sskrll @code{stdin}, @code{stdout} and @code{stderr} are setup to avoid any
352a6b7db3Sskrll multi-threaded locking.  Otherwise do nothing.
362a6b7db3Sskrll 
372a6b7db3Sskrll @end deftypefn
382a6b7db3Sskrll 
3905caefcfSchristos @deftypefn Extension {FILE *} fopen_unlocked (const char *@var{path}, @
4005caefcfSchristos   const char * @var{mode})
412a6b7db3Sskrll 
422a6b7db3Sskrll Opens and returns a @code{FILE} pointer via @code{fopen}.  If the
432a6b7db3Sskrll operating system supports it, ensure that the stream is setup to avoid
442a6b7db3Sskrll any multi-threaded locking.  Otherwise return the @code{FILE} pointer
452a6b7db3Sskrll unchanged.
462a6b7db3Sskrll 
472a6b7db3Sskrll @end deftypefn
482a6b7db3Sskrll 
4905caefcfSchristos @deftypefn Extension {FILE *} fdopen_unlocked (int @var{fildes}, @
5005caefcfSchristos   const char * @var{mode})
512a6b7db3Sskrll 
522a6b7db3Sskrll Opens and returns a @code{FILE} pointer via @code{fdopen}.  If the
532a6b7db3Sskrll operating system supports it, ensure that the stream is setup to avoid
542a6b7db3Sskrll any multi-threaded locking.  Otherwise return the @code{FILE} pointer
552a6b7db3Sskrll unchanged.
562a6b7db3Sskrll 
572a6b7db3Sskrll @end deftypefn
582a6b7db3Sskrll 
5905caefcfSchristos @deftypefn Extension {FILE *} freopen_unlocked (const char * @var{path}, @
6005caefcfSchristos   const char * @var{mode}, FILE * @var{stream})
612a6b7db3Sskrll 
622a6b7db3Sskrll Opens and returns a @code{FILE} pointer via @code{freopen}.  If the
632a6b7db3Sskrll operating system supports it, ensure that the stream is setup to avoid
642a6b7db3Sskrll any multi-threaded locking.  Otherwise return the @code{FILE} pointer
652a6b7db3Sskrll unchanged.
662a6b7db3Sskrll 
672a6b7db3Sskrll @end deftypefn
682a6b7db3Sskrll 
692a6b7db3Sskrll */
702a6b7db3Sskrll 
712a6b7db3Sskrll #ifdef HAVE_CONFIG_H
722a6b7db3Sskrll #include "config.h"
732a6b7db3Sskrll #endif
742a6b7db3Sskrll #include <stdio.h>
752a6b7db3Sskrll #ifdef HAVE_STDIO_EXT_H
762a6b7db3Sskrll #include <stdio_ext.h>
772a6b7db3Sskrll #endif
782a6b7db3Sskrll 
792a6b7db3Sskrll #include "libiberty.h"
802a6b7db3Sskrll 
812a6b7db3Sskrll /* This is an inline helper function to consolidate attempts to unlock
822a6b7db3Sskrll    a stream.  */
832a6b7db3Sskrll 
842a6b7db3Sskrll static inline void
unlock_1(FILE * const fp ATTRIBUTE_UNUSED)852a6b7db3Sskrll unlock_1 (FILE *const fp ATTRIBUTE_UNUSED)
862a6b7db3Sskrll {
872a6b7db3Sskrll #if defined(HAVE___FSETLOCKING) && defined(FSETLOCKING_BYCALLER)
882a6b7db3Sskrll   if (fp)
892a6b7db3Sskrll     __fsetlocking (fp, FSETLOCKING_BYCALLER);
902a6b7db3Sskrll #endif
912a6b7db3Sskrll }
922a6b7db3Sskrll 
932a6b7db3Sskrll void
unlock_stream(FILE * fp)942a6b7db3Sskrll unlock_stream (FILE *fp)
952a6b7db3Sskrll {
962a6b7db3Sskrll   unlock_1 (fp);
972a6b7db3Sskrll }
982a6b7db3Sskrll 
992a6b7db3Sskrll void
unlock_std_streams(void)1002a6b7db3Sskrll unlock_std_streams (void)
1012a6b7db3Sskrll {
1022a6b7db3Sskrll   unlock_1 (stdin);
1032a6b7db3Sskrll   unlock_1 (stdout);
1042a6b7db3Sskrll   unlock_1 (stderr);
1052a6b7db3Sskrll }
1062a6b7db3Sskrll 
1072a6b7db3Sskrll FILE *
fopen_unlocked(const char * path,const char * mode)1082a6b7db3Sskrll fopen_unlocked (const char *path, const char *mode)
1092a6b7db3Sskrll {
1102a6b7db3Sskrll   FILE *const fp = fopen (path, mode);
1112a6b7db3Sskrll   unlock_1 (fp);
1122a6b7db3Sskrll   return fp;
1132a6b7db3Sskrll }
1142a6b7db3Sskrll 
1152a6b7db3Sskrll FILE *
fdopen_unlocked(int fildes,const char * mode)1162a6b7db3Sskrll fdopen_unlocked (int fildes, const char *mode)
1172a6b7db3Sskrll {
1182a6b7db3Sskrll   FILE *const fp = fdopen (fildes, mode);
1192a6b7db3Sskrll   unlock_1 (fp);
1202a6b7db3Sskrll   return fp;
1212a6b7db3Sskrll }
1222a6b7db3Sskrll 
1232a6b7db3Sskrll FILE *
freopen_unlocked(const char * path,const char * mode,FILE * stream)1242a6b7db3Sskrll freopen_unlocked (const char *path, const char *mode, FILE *stream)
1252a6b7db3Sskrll {
1262a6b7db3Sskrll   FILE *const fp = freopen (path, mode, stream);
1272a6b7db3Sskrll   unlock_1 (fp);
1282a6b7db3Sskrll   return fp;
1292a6b7db3Sskrll }
130