os/ossrv/genericopenlibs/cstdlib/LSTDIO/SETVBUF.C
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /* SETVBUF.C
     2  * 
     3  * Portions Copyright (c) 1990-2009 Nokia Corporation and/or its subsidiary(-ies).
     4  * All rights reserved.
     5  */
     6 
     7 /*
     8  * Copyright (c) 1990 The Regents of the University of California.
     9  * All rights reserved.
    10  *
    11  * Redistribution and use in source and binary forms are permitted
    12  * provided that the above copyright notice and this paragraph are
    13  * duplicated in all such forms and that any documentation,
    14  * advertising materials, and other materials related to such
    15  * distribution and use acknowledge that the software was developed
    16  * by the University of California, Berkeley.  The name of the
    17  * University may not be used to endorse or promote products derived
    18  * from this software without specific prior written permission.
    19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
    20  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
    21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
    22  */
    23 
    24 /*
    25 FUNCTION
    26 <<setvbuf>>---specify file or stream buffering
    27 
    28 INDEX
    29 	setvbuf
    30 
    31 ANSI_SYNOPSIS
    32 	#include <stdio.h>
    33 	int setvbuf(FILE *<[fp]>, char *<[buf]>,
    34 	            int <[mode]>, size_t <[size]>);
    35 
    36 TRAD_SYNOPSIS
    37 	#include <stdio.h>
    38 	int setvbuf(<[fp]>, <[buf]>, <[mode]>, <[size]>)
    39 	FILE *<[fp]>;
    40 	char *<[buf]>;
    41 	int <[mode]>;
    42 	size_t <[size]>;
    43 
    44 DESCRIPTION
    45 Use <<setvbuf>> to specify what kind of buffering you want for the
    46 file or stream identified by <[fp]>, by using one of the following
    47 values (from <<stdio.h>>) as the <[mode]> argument:
    48 
    49 o+
    50 o _IONBF
    51 Do not use a buffer: send output directly to the host system for the
    52 file or stream identified by <[fp]>.
    53 
    54 o _IOFBF
    55 Use full output buffering: output will be passed on to the host system
    56 only when the buffer is full, or when an input operation intervenes.
    57 
    58 o _IOLBF
    59 Use line buffering: pass on output to the host system at every
    60 newline, as well as when the buffer is full, or when an input
    61 operation intervenes.
    62 o-
    63 
    64 Use the <[size]> argument to specify how large a buffer you wish.  You
    65 can supply the buffer itself, if you wish, by passing a pointer to a
    66 suitable area of memory as <[buf]>.  Otherwise, you may pass <<NULL>>
    67 as the <[buf]> argument, and <<setvbuf>> will allocate the buffer.
    68 
    69 WARNINGS
    70 You may only use <<setvbuf>> before performing any file operation other
    71 than opening the file.
    72 
    73 If you supply a non-null <[buf]>, you must ensure that the associated
    74 storage continues to be available until you close the stream
    75 identified by <[fp]>.
    76 
    77 RETURNS
    78 A <<0>> result indicates success, <<EOF>> failure (invalid <[mode]> or
    79 <[size]> can cause failure).
    80 
    81 PORTABILITY
    82 Both ANSI C and the System V Interface Definition (Issue 2) require
    83 <<setvbuf>>. However, they differ on the meaning of a <<NULL>> buffer
    84 pointer: the SVID issue 2 specification says that a <<NULL>> buffer
    85 pointer requests unbuffered output.  For maximum portability, avoid
    86 <<NULL>> buffer pointers.
    87 
    88 Both specifications describe the result on failure only as a
    89 nonzero value.
    90 
    91 Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
    92 <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
    93 */
    94 
    95 #include <stdio_r.h>
    96 #include <stdlib_r.h>
    97 #include "LOCAL.H"
    98 
    99 /**
   100 Change stream buffering.
   101 Changes the buffer to be used for I/O operations with the specified stream.
   102 Size and mode for the buffer can be specified.
   103 This function should be called once the file associated with the stream 
   104 has been opened but before any input or output operation has been done.
   105 The size of the buffer is specified by the size parameter,
   106 and can be any value between 2 and 32767 in bytes, 
   107 this value may be rounded down by some system due to specific alignment.
   108 buffer can be NULL.
   109 @return If the buffer is correctly assigned to the file a 0 value is returned.
   110 On error, a non-zero value is returned. This can be because an invalid type or size has been specified or because an error allocating memory (if NULL buffer was specified).
   111 @param fp pointer to an open file. 
   112 @param buf User allocated buffer. Must have at least a size of size bytes. 
   113 @param mode Specifies a mode for file buffering
   114 @param Buffer size in bytes, must be more than 0 and less than 32768, this value may be rounded down by some systems due to specific alignment, in which case the minimum value should be 2.
   115 */
   116 EXPORT_C int
   117 setvbuf (FILE * fp, char *buf, int mode, size_t size)
   118 {
   119   int ret = 0;
   120   CHECK_INIT (fp);
   121 
   122   /*
   123    * Verify arguments.  The `int' limit on `size' is due to this
   124    * particular implementation.
   125    */
   126 
   127   if ((mode != _IOFBF && mode != _IOLBF && mode != _IONBF) || (int) size < 0)
   128     return (EOF);
   129 
   130   /*
   131    * Write current buffer, if any; drop read count, if any.
   132    * Make sure putc() will not think fp is line buffered.
   133    * Free old buffer if it was from malloc().  Clear line and
   134    * non buffer flags, and clear malloc flag.
   135    */
   136 
   137   (void) fflush (fp);
   138   fp->_r = 0;
   139   fp->_lbfsize = 0;
   140   if (fp->_flags & __SMBF)
   141     _free_r (fp->_data, (void *) fp->_bf._base);
   142   fp->_flags &= ~(__SLBF | __SNBF | __SMBF);
   143 
   144   if (mode == _IONBF)
   145     goto nbf;
   146 
   147   /*
   148    * Allocate buffer if needed. */
   149   if (buf == NULL)
   150     {
   151       if ((buf = (char *)malloc (size)) == NULL)
   152 	{
   153 	  ret = EOF;
   154 	  /* Try another size... */
   155 	  buf = (char *)malloc (BUFSIZ);
   156 	}
   157       if (buf == NULL)
   158 	{
   159 	  /* Can't allocate it, let's try another approach */
   160 nbf:
   161 	  fp->_flags |= __SNBF;
   162 	  fp->_w = 0;
   163 	  fp->_bf._base = fp->_p = fp->_nbuf;
   164 	  fp->_bf._size = 1;
   165 	  return (ret);
   166 	}
   167       fp->_flags |= __SMBF;
   168     }
   169   /*
   170    * Now put back whichever flag is needed, and fix _lbfsize
   171    * if line buffered.  Ensure output flush on exit if the
   172    * stream will be buffered at all.
   173    * Force the buffer to be flushed and hence malloced on first use
   174    */
   175 
   176   switch (mode)
   177     {
   178     case _IOLBF:
   179       fp->_flags |= __SLBF;
   180       fp->_lbfsize = -(int)size;
   181       /* FALLTHROUGH */
   182 
   183     case _IOFBF:
   184       /* no flag */
   185       fp->_data->__cleanup = _cleanup_r;
   186       fp->_bf._base = fp->_p = (unsigned char *) buf;
   187       fp->_bf._size = size;
   188       break;
   189     }
   190 
   191   /*
   192    * Patch up write count if necessary.
   193    */
   194 
   195   if (fp->_flags & __SWR)
   196     fp->_w = fp->_flags & (__SLBF | __SNBF) ? 0 : size;
   197 
   198   return 0;
   199 }