Subversion Repositories Kolibri OS

Rev

Rev 4921 | 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, oflags2;
  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.   oflags2 = fp->_flags2;
  110.   if (!(oflags2 & __SNLK))
  111.     _flockfile (fp);
  112.  
  113.   if ((flags = __sflags (ptr, mode, &oflags)) == 0)
  114.     {
  115.       if (!(oflags2 & __SNLK))
  116.         _funlockfile (fp);
  117. #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
  118.       pthread_setcancelstate (__oldcancel, &__oldcancel);
  119. #endif
  120.       _fclose_r (ptr, fp);
  121.       return NULL;
  122.     }
  123.  
  124.   /*
  125.    * Remember whether the stream was open to begin with, and
  126.    * which file descriptor (if any) was associated with it.
  127.    * If it was attached to a descriptor, defer closing it,
  128.    * so that, e.g., freopen("/dev/stdin", "r", stdin) works.
  129.    * This is unnecessary if it was not a Unix file.
  130.    */
  131.  
  132.   if (fp->_flags == 0)
  133.     fp->_flags = __SEOF;        /* hold on to it */
  134.   else
  135.     {
  136.       if (fp->_flags & __SWR)
  137.         _fflush_r (ptr, fp);
  138.       /*
  139.        * If close is NULL, closing is a no-op, hence pointless.
  140.        * If file is NULL, the file should not be closed.
  141.        */
  142.       if (fp->_close != NULL && file != NULL)
  143.         fp->_close (ptr, fp->_cookie);
  144.     }
  145.  
  146.   /*
  147.    * Now get a new descriptor to refer to the new file, or reuse the
  148.    * existing file descriptor if file is NULL.
  149.    */
  150.  
  151.   if (file != NULL)
  152.     {
  153.       f = _open_r (ptr, (char *) file, oflags, 0666);
  154.       e = ptr->_errno;
  155.     }
  156.   else
  157.     {
  158. #ifdef HAVE_FCNTL
  159.       int oldflags;
  160.       /*
  161.        * Reuse the file descriptor, but only if the new access mode is
  162.        * equal or less permissive than the old.  F_SETFL correctly
  163.        * ignores creation flags.
  164.        */
  165.       f = fp->_file;
  166.       if ((oldflags = _fcntl_r (ptr, f, F_GETFL, 0)) == -1
  167.           || ! ((oldflags & O_ACCMODE) == O_RDWR
  168.                 || ((oldflags ^ oflags) & O_ACCMODE) == 0)
  169.           || _fcntl_r (ptr, f, F_SETFL, oflags) == -1)
  170.         f = -1;
  171. #else
  172.       /* We cannot modify without fcntl support.  */
  173.       f = -1;
  174. #endif
  175.  
  176. #ifdef __SCLE
  177.       /*
  178.        * F_SETFL doesn't change textmode.  Don't mess with modes of ttys.
  179.        */
  180.       if (0 <= f && ! _isatty_r (ptr, f)
  181.           && setmode (f, oflags & (O_BINARY | O_TEXT)) == -1)
  182.         f = -1;
  183. #endif
  184.  
  185.       if (f < 0)
  186.         {
  187.           e = EBADF;
  188.           if (fp->_close != NULL)
  189.             fp->_close (ptr, fp->_cookie);
  190.         }
  191.     }
  192.  
  193.   /*
  194.    * Finish closing fp.  Even if the open succeeded above,
  195.    * we cannot keep fp->_base: it may be the wrong size.
  196.    * This loses the effect of any setbuffer calls,
  197.    * but stdio has always done this before.
  198.    */
  199.  
  200.   if (fp->_flags & __SMBF)
  201.     _free_r (ptr, (char *) fp->_bf._base);
  202.   fp->_w = 0;
  203.   fp->_r = 0;
  204.   fp->_p = NULL;
  205.   fp->_bf._base = NULL;
  206.   fp->_bf._size = 0;
  207.   fp->_lbfsize = 0;
  208.   if (HASUB (fp))
  209.     FREEUB (ptr, fp);
  210.   fp->_ub._size = 0;
  211.   if (HASLB (fp))
  212.     FREELB (ptr, fp);
  213.   fp->_lb._size = 0;
  214.   fp->_flags &= ~__SORD;
  215.   fp->_flags2 &= ~__SWID;
  216.   memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
  217.  
  218.   if (f < 0)
  219.     {                           /* did not get it after all */
  220.       __sfp_lock_acquire ();
  221.       fp->_flags = 0;           /* set it free */
  222.       ptr->_errno = e;          /* restore in case _close clobbered */
  223.       if (!(oflags2 & __SNLK))
  224.         _funlockfile (fp);
  225. #ifndef __SINGLE_THREAD__
  226.       __lock_close_recursive (fp->_lock);
  227. #endif
  228.       __sfp_lock_release ();
  229. #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
  230.       pthread_setcancelstate (__oldcancel, &__oldcancel);
  231. #endif
  232.       return NULL;
  233.     }
  234.  
  235.   fp->_flags = flags;
  236.   fp->_file = f;
  237.   fp->_cookie = (_PTR) fp;
  238.   fp->_read = __sread;
  239.   fp->_write = __swrite;
  240.   fp->_seek = __sseek;
  241.   fp->_close = __sclose;
  242.  
  243. #ifdef __SCLE
  244.   if (__stextmode (fp->_file))
  245.     fp->_flags |= __SCLE;
  246. #endif
  247.  
  248.   if (!(oflags2 & __SNLK))
  249.     _funlockfile (fp);
  250. #ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
  251.   pthread_setcancelstate (__oldcancel, &__oldcancel);
  252. #endif
  253.   return fp;
  254. }
  255.  
  256. #ifndef _REENT_ONLY
  257.  
  258. FILE *
  259. _DEFUN(freopen, (file, mode, fp),
  260.        _CONST char *__restrict file _AND
  261.        _CONST char *__restrict mode _AND
  262.        register FILE *__restrict fp)
  263. {
  264.   return _freopen_r (_REENT, file, mode, fp);
  265. }
  266.  
  267. #endif /*!_REENT_ONLY */
  268.