xref: /titanic_50/usr/src/lib/libast/common/sfio/sfflsbuf.c (revision 3c4993fb5a74112f361d71dab20997bdc749a7fb)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                      by AT&T Knowledge Ventures                      *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *            http://www.opensource.org/licenses/cpl1.0.txt             *
11 *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                 Glenn Fowler <gsf@research.att.com>                  *
18 *                  David Korn <dgk@research.att.com>                   *
19 *                   Phong Vo <kpv@research.att.com>                    *
20 *                                                                      *
21 ***********************************************************************/
22 #include	"sfhdr.h"
23 
24 /*	Write a buffer out to a file descriptor or
25 **	extending a buffer for a SF_STRING stream.
26 **
27 **	Written by Kiem-Phong Vo
28 */
29 
30 #if __STD_C
31 int _sfflsbuf(reg Sfio_t* f, reg int c)
32 #else
33 int _sfflsbuf(f,c)
34 reg Sfio_t*	f;	/* write out the buffered content of this stream */
35 reg int		c;	/* if c>=0, c is also written out */
36 #endif
37 {
38 	reg ssize_t	n, w;
39 	reg uchar*	data;
40 	uchar		outc;
41 	reg int		local, isall;
42 	int		inpc = c;
43 
44 	SFMTXSTART(f,-1);
45 
46 	GETLOCAL(f,local);
47 
48 	for(;; f->mode &= ~SF_LOCK)
49 	{	/* check stream mode */
50 		if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0)
51 			SFMTXRETURN(f, -1);
52 		SFLOCK(f,local);
53 
54 		/* current data extent */
55 		n = f->next - (data = f->data);
56 
57 		if(n == (f->endb-data) && (f->flags&SF_STRING))
58 		{	/* extend string stream buffer */
59 			(void)SFWR(f,data,1,f->disc);
60 
61 			/* !(f->flags&SF_STRING) is required because exception
62 			   handlers may turn a string stream to a file stream */
63 			if(f->next < f->endb || !(f->flags&SF_STRING) )
64 				n = f->next - (data = f->data);
65 			else
66 			{	SFOPEN(f,local);
67 				SFMTXRETURN(f, -1);
68 			}
69 		}
70 
71 		if(c >= 0)
72 		{	/* write into buffer */
73 			if(n < (f->endb - (data = f->data)))
74 			{	*f->next++ = c;
75 				if(c == '\n' &&
76 				   (f->flags&SF_LINE) && !(f->flags&SF_STRING))
77 				{	c = -1;
78 					n += 1;
79 				}
80 				else	break;
81 			}
82 			else if(n == 0)
83 			{	/* unbuffered io */
84 				outc = (uchar)c;
85 				data = &outc;
86 				c = -1;
87 				n = 1;
88 			}
89 		}
90 
91 		if(n == 0 || (f->flags&SF_STRING))
92 			break;
93 
94 		isall = SFISALL(f,isall);
95 		if((w = SFWR(f,data,n,f->disc)) > 0)
96 		{	if((n -= w) > 0) /* save unwritten data, then resume */
97 				memcpy((char*)f->data,(char*)data+w,n);
98 			f->next = f->data+n;
99 			if(c < 0 && (!isall || n == 0))
100 				break;
101 		}
102 		else if(w == 0)
103 		{	SFOPEN(f,local);
104 			SFMTXRETURN(f, -1);
105 		}
106 		else if(c < 0)
107 			break;
108 	}
109 
110 	SFOPEN(f,local);
111 
112 	if(inpc < 0)
113 		inpc = f->endb-f->next;
114 
115 	SFMTXRETURN(f,inpc);
116 }
117