Subversion Repositories Kolibri OS

Rev

Rev 4874 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 1990, 2007 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. /*
  19. FUNCTION
  20. <<freopen>>---open a file using an existing file descriptor
  21.  
  22. INDEX
  23.         freopen
  24. INDEX
  25.         _freopen_r
  26.  
  27. ANSI_SYNOPSIS
  28.         #include <stdio.h>
  29.         FILE *freopen(const char *restrict <[file]>, const char *restrict <[mode]>,
  30.                       FILE *restrict <[fp]>);
  31.         FILE *_freopen_r(struct _reent *<[ptr]>, const char *restrict <[file]>,
  32.                       const char *restrict <[mode]>, FILE *restrict <[fp]>);
  33.  
  34. TRAD_SYNOPSIS
  35.         #include <stdio.h>
  36.         FILE *freopen(<[file]>, <[mode]>, <[fp]>)
  37.         char *<[file]>;
  38.         char *<[mode]>;
  39.         FILE *<[fp]>;
  40.  
  41.         FILE *_freopen_r(<[ptr]>, <[file]>, <[mode]>, <[fp]>)
  42.         struct _reent *<[ptr]>;
  43.         char *<[file]>;
  44.         char *<[mode]>;
  45.         FILE *<[fp]>;
  46.  
  47. DESCRIPTION
  48. Use this variant of <<fopen>> if you wish to specify a particular file
  49. descriptor <[fp]> (notably <<stdin>>, <<stdout>>, or <<stderr>>) for
  50. the file.
  51.  
  52. If <[fp]> was associated with another file or stream, <<freopen>>
  53. closes that other file or stream (but ignores any errors while closing
  54. it).
  55.  
  56. <[file]> and <[mode]> are used just as in <<fopen>>.
  57.  
  58. If <[file]> is <<NULL>>, the underlying stream is modified rather than
  59. closed.  The file cannot be given a more permissive access mode (for
  60. example, a <[mode]> of "w" will fail on a read-only file descriptor),
  61. but can change status such as append or binary mode.  If modification
  62. is not possible, failure occurs.
  63.  
  64. RETURNS
  65. If successful, the result is the same as the argument <[fp]>.  If the
  66. file cannot be opened as specified, the result is <<NULL>>.
  67.  
  68. PORTABILITY
  69. ANSI C requires <<freopen>>.
  70.  
  71. Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
  72. <<lseek>>, <<open>>, <<read>>, <<sbrk>>, <<write>>.
  73. */
  74.  
  75. #include <_ansi.h>
  76. #include <reent.h>
  77. #include <time.h>
  78. #include <stdio.h>
  79. #include <string.h>
  80. #include <errno.h>
  81. #include <fcntl.h>
  82. #include <stdlib.h>
  83. #include <sys/lock.h>
  84. #include "local.h"
  85.  
  86. /*
  87.  * Re-direct an existing, open (probably) file to some other file.
  88.  */
  89.  
  90. FILE *
  91. _DEFUN(_freopen_r, (ptr, file, mode, fp),
  92.        struct _reent *ptr _AND
  93.        const char *__restrict file _AND
  94.        const char *__restrict mode _AND
  95.        register FILE *__restrict fp)
  96. {
  97.   register int f;
  98.   int flags, oflags;
  99.   int e = 0;
  100.  
  101.   CHECK_INIT (ptr, fp);
  102.  
  103.   /* We can't use the _newlib_flockfile_XXX macros here due to the
  104.      interlocked locking with the sfp_lock. */
  105. #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
  106.   int __oldcancel;
  107.   pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldcancel);
  108. #endif
  109.   _flockfile (fp);
  110.  
  111.   if ((flags = __sflags (ptr, mode, &oflags)) == 0)
  112.     {
  113.       _funlockfile (fp);
  114. #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
  115.       pthread_setcancelstate (__oldcancel, &__oldcancel);
  116. #endif
  117.       _fclose_r (ptr, fp);
  118.       return NULL;
  119.     }
  120.  
  121.   /*
  122.    * Remember whether the stream was open to begin with, and
  123.    * which file descriptor (if any) was associated with it.
  124.    * If it was attached to a descriptor, defer closing it,
  125.    * so that, e.g., freopen("/dev/stdin", "r", stdin) works.
  126.    * This is unnecessary if it was not a Unix file.
  127.    */
  128.  
  129.   if (fp->_flags == 0)
  130.     fp->_flags = __SEOF;        /* hold on to it */
  131.   else
  132.     {
  133.       if (fp->_flags & __SWR)
  134.         _fflush_r (ptr, fp);
  135.       /*
  136.        * If close is NULL, closing is a no-op, hence pointless.
  137.        * If file is NULL, the file should not be closed.
  138.        */
  139.       if (fp->_close != NULL && file != NULL)
  140.         fp->_close (ptr, fp->_cookie);
  141.     }
  142.  
  143.   /*
  144.    * Now get a new descriptor to refer to the new file, or reuse the
  145.    * existing file descriptor if file is NULL.
  146.    */
  147.  
  148.   if (file != NULL)
  149.     {
  150.       f = _open_r (ptr, (char *) file, oflags, 0666);
  151.       e = ptr->_errno;
  152.     }
  153.   else
  154.     {
  155. #ifdef HAVE_FCNTL
  156.       int oldflags;
  157.       /*
  158.        * Reuse the file descriptor, but only if the new access mode is
  159.        * equal or less permissive than the old.  F_SETFL correctly
  160.        * ignores creation flags.
  161.        */
  162.       f = fp->_file;
  163.       if ((oldflags = _fcntl_r (ptr, f, F_GETFL, 0)) == -1
  164.           || ! ((oldflags & O_ACCMODE) == O_RDWR
  165.                 || ((oldflags ^ oflags) & O_ACCMODE) == 0)
  166.           || _fcntl_r (ptr, f, F_SETFL, oflags) == -1)
  167.         f = -1;
  168. #else
  169.       /* We cannot modify without fcntl support.  */
  170.       f = -1;
  171. #endif
  172.  
  173. #ifdef __SCLE
  174.       /*
  175.        * F_SETFL doesn't change textmode.  Don't mess with modes of ttys.
  176.        */
  177.       if (0 <= f && ! _isatty_r (ptr, f)
  178.           && setmode (f, oflags & (O_BINARY | O_TEXT)) == -1)
  179.         f = -1;
  180. #endif
  181.  
  182.       if (f < 0)
  183.         {
  184.           e = EBADF;
  185.           if (fp->_close != NULL)
  186.             fp->_close (ptr, fp->_cookie);
  187.         }
  188.     }
  189.  
  190.   /*
  191.    * Finish closing fp.  Even if the open succeeded above,
  192.    * we cannot keep fp->_base: it may be the wrong size.
  193.    * This loses the effect of any setbuffer calls,
  194.    * but stdio has always done this before.
  195.    */
  196.  
  197.   if (fp->_flags & __SMBF)
  198.     _free_r (ptr, (char *) fp->_bf._base);
  199.   fp->_w = 0;
  200.   fp->_r = 0;
  201.   fp->_p = NULL;
  202.   fp->_bf._base = NULL;
  203.   fp->_bf._size = 0;
  204.   fp->_lbfsize = 0;
  205.   if (HASUB (fp))
  206.     FREEUB (ptr, fp);
  207.   fp->_ub._size = 0;
  208.   if (HASLB (fp))
  209.     FREELB (ptr, fp);
  210.   fp->_lb._size = 0;
  211.   fp->_flags &= ~__SORD;
  212.   fp->_flags2 = 0;
  213.   memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
  214.  
  215.   if (f < 0)
  216.     {                           /* did not get it after all */
  217.       __sfp_lock_acquire ();
  218.       fp->_flags = 0;           /* set it free */
  219.       ptr->_errno = e;          /* restore in case _close clobbered */
  220.       _funlockfile (fp);
  221. #ifndef __SINGLE_THREAD__
  222.       __lock_close_recursive (fp->_lock);
  223. #endif
  224.       __sfp_lock_release ();
  225. #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
  226.       pthread_setcancelstate (__oldcancel, &__oldcancel);
  227. #endif
  228.       return NULL;
  229.     }
  230.  
  231.   fp->_flags = flags;
  232.   fp->_file = f;
  233.   fp->_cookie = (_PTR) fp;
  234.   fp->_read = __sread;
  235.   fp->_write = __swrite;
  236.   fp->_seek = __sseek;
  237.   fp->_close = __sclose;
  238.  
  239. #ifdef __SCLE
  240.   if (__stextmode (fp->_file))
  241.     fp->_flags |= __SCLE;
  242. #endif
  243.  
  244.   _funlockfile (fp);
  245. #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
  246.   pthread_setcancelstate (__oldcancel, &__oldcancel);
  247. #endif
  248.   return fp;
  249. }
  250.  
  251. #ifndef _REENT_ONLY
  252.  
  253. FILE *
  254. _DEFUN(freopen, (file, mode, fp),
  255.        _CONST char *__restrict file _AND
  256.        _CONST char *__restrict mode _AND
  257.        register FILE *__restrict fp)
  258. {
  259.   return _freopen_r (_REENT, file, mode, fp);
  260. }
  261.  
  262. #endif /*!_REENT_ONLY */
  263.