Subversion Repositories Kolibri OS

Rev

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