sl@0: /* SETVBUF.C sl@0: * sl@0: * Portions Copyright (c) 1990-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: */ sl@0: sl@0: /* sl@0: * Copyright (c) 1990 The Regents of the University of California. sl@0: * All rights reserved. sl@0: * sl@0: * Redistribution and use in source and binary forms are permitted sl@0: * provided that the above copyright notice and this paragraph are sl@0: * duplicated in all such forms and that any documentation, sl@0: * advertising materials, and other materials related to such sl@0: * distribution and use acknowledge that the software was developed sl@0: * by the University of California, Berkeley. The name of the sl@0: * University may not be used to endorse or promote products derived sl@0: * from this software without specific prior written permission. sl@0: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR sl@0: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED sl@0: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. sl@0: */ sl@0: sl@0: /* sl@0: FUNCTION sl@0: <>---specify file or stream buffering sl@0: sl@0: INDEX sl@0: setvbuf sl@0: sl@0: ANSI_SYNOPSIS sl@0: #include sl@0: int setvbuf(FILE *<[fp]>, char *<[buf]>, sl@0: int <[mode]>, size_t <[size]>); sl@0: sl@0: TRAD_SYNOPSIS sl@0: #include sl@0: int setvbuf(<[fp]>, <[buf]>, <[mode]>, <[size]>) sl@0: FILE *<[fp]>; sl@0: char *<[buf]>; sl@0: int <[mode]>; sl@0: size_t <[size]>; sl@0: sl@0: DESCRIPTION sl@0: Use <> to specify what kind of buffering you want for the sl@0: file or stream identified by <[fp]>, by using one of the following sl@0: values (from <>) as the <[mode]> argument: sl@0: sl@0: o+ sl@0: o _IONBF sl@0: Do not use a buffer: send output directly to the host system for the sl@0: file or stream identified by <[fp]>. sl@0: sl@0: o _IOFBF sl@0: Use full output buffering: output will be passed on to the host system sl@0: only when the buffer is full, or when an input operation intervenes. sl@0: sl@0: o _IOLBF sl@0: Use line buffering: pass on output to the host system at every sl@0: newline, as well as when the buffer is full, or when an input sl@0: operation intervenes. sl@0: o- sl@0: sl@0: Use the <[size]> argument to specify how large a buffer you wish. You sl@0: can supply the buffer itself, if you wish, by passing a pointer to a sl@0: suitable area of memory as <[buf]>. Otherwise, you may pass <> sl@0: as the <[buf]> argument, and <> will allocate the buffer. sl@0: sl@0: WARNINGS sl@0: You may only use <> before performing any file operation other sl@0: than opening the file. sl@0: sl@0: If you supply a non-null <[buf]>, you must ensure that the associated sl@0: storage continues to be available until you close the stream sl@0: identified by <[fp]>. sl@0: sl@0: RETURNS sl@0: A <<0>> result indicates success, <> failure (invalid <[mode]> or sl@0: <[size]> can cause failure). sl@0: sl@0: PORTABILITY sl@0: Both ANSI C and the System V Interface Definition (Issue 2) require sl@0: <>. However, they differ on the meaning of a <> buffer sl@0: pointer: the SVID issue 2 specification says that a <> buffer sl@0: pointer requests unbuffered output. For maximum portability, avoid sl@0: <> buffer pointers. sl@0: sl@0: Both specifications describe the result on failure only as a sl@0: nonzero value. sl@0: sl@0: Supporting OS subroutines required: <>, <>, <>, sl@0: <>, <>, <>, <>. sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include "LOCAL.H" sl@0: sl@0: /** sl@0: Change stream buffering. sl@0: Changes the buffer to be used for I/O operations with the specified stream. sl@0: Size and mode for the buffer can be specified. sl@0: This function should be called once the file associated with the stream sl@0: has been opened but before any input or output operation has been done. sl@0: The size of the buffer is specified by the size parameter, sl@0: and can be any value between 2 and 32767 in bytes, sl@0: this value may be rounded down by some system due to specific alignment. sl@0: buffer can be NULL. sl@0: @return If the buffer is correctly assigned to the file a 0 value is returned. sl@0: 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). sl@0: @param fp pointer to an open file. sl@0: @param buf User allocated buffer. Must have at least a size of size bytes. sl@0: @param mode Specifies a mode for file buffering sl@0: @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. sl@0: */ sl@0: EXPORT_C int sl@0: setvbuf (FILE * fp, char *buf, int mode, size_t size) sl@0: { sl@0: int ret = 0; sl@0: CHECK_INIT (fp); sl@0: sl@0: /* sl@0: * Verify arguments. The `int' limit on `size' is due to this sl@0: * particular implementation. sl@0: */ sl@0: sl@0: if ((mode != _IOFBF && mode != _IOLBF && mode != _IONBF) || (int) size < 0) sl@0: return (EOF); sl@0: sl@0: /* sl@0: * Write current buffer, if any; drop read count, if any. sl@0: * Make sure putc() will not think fp is line buffered. sl@0: * Free old buffer if it was from malloc(). Clear line and sl@0: * non buffer flags, and clear malloc flag. sl@0: */ sl@0: sl@0: (void) fflush (fp); sl@0: fp->_r = 0; sl@0: fp->_lbfsize = 0; sl@0: if (fp->_flags & __SMBF) sl@0: _free_r (fp->_data, (void *) fp->_bf._base); sl@0: fp->_flags &= ~(__SLBF | __SNBF | __SMBF); sl@0: sl@0: if (mode == _IONBF) sl@0: goto nbf; sl@0: sl@0: /* sl@0: * Allocate buffer if needed. */ sl@0: if (buf == NULL) sl@0: { sl@0: if ((buf = (char *)malloc (size)) == NULL) sl@0: { sl@0: ret = EOF; sl@0: /* Try another size... */ sl@0: buf = (char *)malloc (BUFSIZ); sl@0: } sl@0: if (buf == NULL) sl@0: { sl@0: /* Can't allocate it, let's try another approach */ sl@0: nbf: sl@0: fp->_flags |= __SNBF; sl@0: fp->_w = 0; sl@0: fp->_bf._base = fp->_p = fp->_nbuf; sl@0: fp->_bf._size = 1; sl@0: return (ret); sl@0: } sl@0: fp->_flags |= __SMBF; sl@0: } sl@0: /* sl@0: * Now put back whichever flag is needed, and fix _lbfsize sl@0: * if line buffered. Ensure output flush on exit if the sl@0: * stream will be buffered at all. sl@0: * Force the buffer to be flushed and hence malloced on first use sl@0: */ sl@0: sl@0: switch (mode) sl@0: { sl@0: case _IOLBF: sl@0: fp->_flags |= __SLBF; sl@0: fp->_lbfsize = -(int)size; sl@0: /* FALLTHROUGH */ sl@0: sl@0: case _IOFBF: sl@0: /* no flag */ sl@0: fp->_data->__cleanup = _cleanup_r; sl@0: fp->_bf._base = fp->_p = (unsigned char *) buf; sl@0: fp->_bf._size = size; sl@0: break; sl@0: } sl@0: sl@0: /* sl@0: * Patch up write count if necessary. sl@0: */ sl@0: sl@0: if (fp->_flags & __SWR) sl@0: fp->_w = fp->_flags & (__SLBF | __SNBF) ? 0 : size; sl@0: sl@0: return 0; sl@0: }