Subversion Repositories shark

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*-
2
 * Copyright (c) 1990, 1993
3
 *      The Regents of the University of California.  All rights reserved.
4
 *
5
 * This code is derived from software contributed to Berkeley by
6
 * Chris Torek.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. All advertising materials mentioning features or use of this software
17
 *    must display the following acknowledgement:
18
 *      This product includes software developed by the University of
19
 *      California, Berkeley and its contributors.
20
 * 4. Neither the name of the University nor the names of its contributors
21
 *    may be used to endorse or promote products derived from this software
22
 *    without specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34
 * SUCH DAMAGE.
35
 */
36
 
37
#if defined(LIBC_SCCS) && !defined(lint)
38
#if 0
39
static char sccsid[] = "@(#)setvbuf.c   8.2 (Berkeley) 11/16/93";
40
#endif
41
static const char rcsid[] =
42
                "$\Id: setvbuf.c,v 1.3 1996/06/22 10:33:53 jraynard Exp $";
43
#endif /* LIBC_SCCS and not lint */
44
 
45
#include <stdio.h>
46
#include <stdlib.h>
47
#include "local.h"
48
#ifdef _THREAD_SAFE
49
#include <pthread.h>
50
#include "pthread_private.h"
51
#endif
52
 
53
/*
54
 * Set one of the three kinds of buffering, optionally including
55
 * a buffer.
56
 */
57
int
58
setvbuf(fp, buf, mode, size)
59
        register FILE *fp;
60
        char *buf;
61
        register int mode;
62
        register size_t size;
63
{
64
        register int ret, flags;
65
        size_t iosize;
66
        int ttyflag;
67
 
68
        /*
69
         * Verify arguments.  The `int' limit on `size' is due to this
70
         * particular implementation.  Note, buf and size are ignored
71
         * when setting _IONBF.
72
         */
73
        if (mode != _IONBF)
74
                if ((mode != _IOFBF && mode != _IOLBF) || (int)size < 0)
75
                        return (EOF);
76
 
77
#ifdef _THREAD_SAFE
78
        _thread_flockfile(fp,__FILE__,__LINE__);
79
#endif
80
        /*
81
         * Write current buffer, if any.  Discard unread input (including
82
         * ungetc data), cancel line buffering, and free old buffer if
83
         * malloc()ed.  We also clear any eof condition, as if this were
84
         * a seek.
85
         */
86
        ret = 0;
87
        (void)__sflush(fp);
88
        if (HASUB(fp))
89
                FREEUB(fp);
90
        fp->_r = fp->_lbfsize = 0;
91
        flags = fp->_flags;
92
        if (flags & __SMBF)
93
                free((void *)fp->_bf._base);
94
        flags &= ~(__SLBF | __SNBF | __SMBF | __SOPT | __SNPT | __SEOF);
95
 
96
        /* If setting unbuffered mode, skip all the hard work. */
97
        if (mode == _IONBF)
98
                goto nbf;
99
 
100
        /*
101
         * Find optimal I/O size for seek optimization.  This also returns
102
         * a `tty flag' to suggest that we check isatty(fd), but we do not
103
         * care since our caller told us how to buffer.
104
         */
105
        flags |= __swhatbuf(fp, &iosize, &ttyflag);
106
        if (size == 0) {
107
                buf = NULL;     /* force local allocation */
108
                size = iosize;
109
        }
110
 
111
        /* Allocate buffer if needed. */
112
        if (buf == NULL) {
113
                if ((buf = malloc(size)) == NULL) {
114
                        /*
115
                         * Unable to honor user's request.  We will return
116
                         * failure, but try again with file system size.
117
                         */
118
                        ret = EOF;
119
                        if (size != iosize) {
120
                                size = iosize;
121
                                buf = malloc(size);
122
                        }
123
                }
124
                if (buf == NULL) {
125
                        /* No luck; switch to unbuffered I/O. */
126
nbf:
127
                        fp->_flags = flags | __SNBF;
128
                        fp->_w = 0;
129
                        fp->_bf._base = fp->_p = fp->_nbuf;
130
                        fp->_bf._size = 1;
131
#ifdef _THREAD_SAFE
132
                        _thread_funlockfile(fp);
133
#endif
134
                        return (ret);
135
                }
136
                flags |= __SMBF;
137
        }
138
 
139
        /*
140
         * Kill any seek optimization if the buffer is not the
141
         * right size.
142
         *
143
         * SHOULD WE ALLOW MULTIPLES HERE (i.e., ok iff (size % iosize) == 0)?
144
         */
145
        if (size != iosize)
146
                flags |= __SNPT;
147
 
148
        /*
149
         * Fix up the FILE fields, and set __cleanup for output flush on
150
         * exit (since we are buffered in some way).
151
         */
152
        if (mode == _IOLBF)
153
                flags |= __SLBF;
154
        fp->_flags = flags;
155
        fp->_bf._base = fp->_p = (unsigned char *)buf;
156
        fp->_bf._size = size;
157
        /* fp->_lbfsize is still 0 */
158
        if (flags & __SWR) {
159
                /*
160
                 * Begin or continue writing: see __swsetup().  Note
161
                 * that __SNBF is impossible (it was handled earlier).
162
                 */
163
                if (flags & __SLBF) {
164
                        fp->_w = 0;
165
                        fp->_lbfsize = -fp->_bf._size;
166
                } else
167
                        fp->_w = size;
168
        } else {
169
                /* begin/continue reading, or stay in intermediate state */
170
                fp->_w = 0;
171
        }
172
        __cleanup = _cleanup;
173
 
174
#ifdef _THREAD_SAFE
175
        _thread_funlockfile(fp);
176
#endif
177
        return (ret);
178
}