xref: /titanic_51/usr/src/lib/libast/common/sfio/sfwrite.c (revision 3e14f97f673e8a630f076077de35afdd43dc1587)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*3e14f97fSRoger A. Faulkner *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6da2e3ebdSchin *                  Common Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10da2e3ebdSchin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11da2e3ebdSchin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
19da2e3ebdSchin *                   Phong Vo <kpv@research.att.com>                    *
20da2e3ebdSchin *                                                                      *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #include	"sfhdr.h"
23da2e3ebdSchin 
24da2e3ebdSchin /*	Write data out to the file system
25da2e3ebdSchin **
26da2e3ebdSchin **	Written by Kiem-Phong Vo.
27da2e3ebdSchin */
28da2e3ebdSchin 
29da2e3ebdSchin #if __STD_C
sfwrite(Sfio_t * f,const Void_t * buf,size_t n)307c2fbfb3SApril Chin ssize_t sfwrite(Sfio_t* f, const Void_t* buf, size_t n)
31da2e3ebdSchin #else
32da2e3ebdSchin ssize_t sfwrite(f,buf,n)
337c2fbfb3SApril Chin Sfio_t*		f;	/* write to this stream. 	*/
34da2e3ebdSchin Void_t*		buf;	/* buffer to be written.	*/
357c2fbfb3SApril Chin size_t		n;	/* number of bytes. 		*/
36da2e3ebdSchin #endif
37da2e3ebdSchin {
38da2e3ebdSchin 	reg uchar	*s, *begs, *next;
39da2e3ebdSchin 	reg ssize_t	w;
40da2e3ebdSchin 	reg int		local;
417c2fbfb3SApril Chin 	SFMTXDECL(f);
42da2e3ebdSchin 
437c2fbfb3SApril Chin 	SFMTXENTER(f, (ssize_t)(-1));
44da2e3ebdSchin 
45da2e3ebdSchin 	GETLOCAL(f,local);
46da2e3ebdSchin 
47da2e3ebdSchin 	if(!buf)
48da2e3ebdSchin 		SFMTXRETURN(f, (ssize_t)(n == 0 ? 0 : -1) );
49da2e3ebdSchin 
50da2e3ebdSchin 	/* release peek lock */
51da2e3ebdSchin 	if(f->mode&SF_PEEK)
52da2e3ebdSchin 	{	if(!(f->mode&SF_WRITE) && (f->flags&SF_RDWR) != SF_RDWR)
53da2e3ebdSchin 			SFMTXRETURN(f, (ssize_t)(-1));
54da2e3ebdSchin 
55da2e3ebdSchin 		if((uchar*)buf != f->next &&
56da2e3ebdSchin 		   (!f->rsrv || f->rsrv->data != (uchar*)buf) )
57da2e3ebdSchin 			SFMTXRETURN(f, (ssize_t)(-1));
58da2e3ebdSchin 
59da2e3ebdSchin 		f->mode &= ~SF_PEEK;
60da2e3ebdSchin 
61da2e3ebdSchin 		if(f->mode&SF_PKRD)
62da2e3ebdSchin 		{	/* read past peeked data */
63da2e3ebdSchin 			char		buf[16];
64da2e3ebdSchin 			reg ssize_t	r;
65da2e3ebdSchin 
66da2e3ebdSchin 			for(w = n; w > 0; )
67da2e3ebdSchin 			{	if((r = w) > sizeof(buf))
68da2e3ebdSchin 					r = sizeof(buf);
69da2e3ebdSchin 				if((r = sysreadf(f->file,buf,r)) <= 0)
70da2e3ebdSchin 				{	n -= w;
71da2e3ebdSchin 					break;
72da2e3ebdSchin 				}
73da2e3ebdSchin 				else	w -= r;
74da2e3ebdSchin 			}
75da2e3ebdSchin 
76da2e3ebdSchin 			f->mode &= ~SF_PKRD;
77da2e3ebdSchin 			f->endb = f->data + n;
78da2e3ebdSchin 			f->here += n;
79da2e3ebdSchin 		}
80da2e3ebdSchin 
81da2e3ebdSchin 		if((f->mode&SF_READ) && f->proc)
82da2e3ebdSchin 			f->next += n;
83da2e3ebdSchin 	}
84da2e3ebdSchin 
85da2e3ebdSchin 	s = begs = (uchar*)buf;
86da2e3ebdSchin 	for(;; f->mode &= ~SF_LOCK)
87da2e3ebdSchin 	{	/* check stream mode */
88da2e3ebdSchin 		if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0 )
89da2e3ebdSchin 		{	w = s > begs ? s-begs : -1;
90da2e3ebdSchin 			SFMTXRETURN(f,w);
91da2e3ebdSchin 		}
92da2e3ebdSchin 
93da2e3ebdSchin 		SFLOCK(f,local);
94da2e3ebdSchin 
95da2e3ebdSchin 		w = f->endb - f->next;
96da2e3ebdSchin 
97da2e3ebdSchin 		if(s == f->next) /* after sfreserve */
98da2e3ebdSchin 		{	if(w > (ssize_t)n)
99da2e3ebdSchin 				w = (ssize_t)n;
100da2e3ebdSchin 			f->next = (s += w);
101da2e3ebdSchin 			n -= w;
102da2e3ebdSchin 			break;
103da2e3ebdSchin 		}
104da2e3ebdSchin 
105da2e3ebdSchin 		/* attempt to create space in buffer */
106da2e3ebdSchin 		if(w == 0 || ((f->flags&SF_WHOLE) && w < (ssize_t)n) )
107da2e3ebdSchin 		{	if(f->flags&SF_STRING) /* extend buffer */
108da2e3ebdSchin 			{	(void)SFWR(f, s, n-w, f->disc);
109da2e3ebdSchin 				if((w = f->endb - f->next) < (ssize_t)n)
110da2e3ebdSchin 				{	if(!(f->flags&SF_STRING)) /* maybe sftmp */
111da2e3ebdSchin 					{	if(f->next > f->data)
112da2e3ebdSchin 							goto fls_buf;
113da2e3ebdSchin 					}
114da2e3ebdSchin 					else if(w == 0)
115da2e3ebdSchin 						break;
116da2e3ebdSchin 				}
117da2e3ebdSchin 			}
118da2e3ebdSchin 			else if(f->next > f->data)
119da2e3ebdSchin 			{ fls_buf:
120da2e3ebdSchin 				(void)SFFLSBUF(f, -1);
121da2e3ebdSchin 				if((w = f->endb - f->next) < (ssize_t)n &&
122da2e3ebdSchin 				   (f->flags&SF_WHOLE) && f->next > f->data )
123da2e3ebdSchin 						break;
124da2e3ebdSchin 			}
125da2e3ebdSchin 		}
126da2e3ebdSchin 
127da2e3ebdSchin 		if(!(f->flags&SF_STRING) && f->next == f->data &&
128da2e3ebdSchin 		   (((f->flags&SF_WHOLE) && w <= n) || SFDIRECT(f,n)) )
129da2e3ebdSchin 		{	/* bypass buffering */
130da2e3ebdSchin 			if((w = SFWR(f,s,n,f->disc)) <= 0 )
131da2e3ebdSchin 				break;
132da2e3ebdSchin 		}
133da2e3ebdSchin 		else
134da2e3ebdSchin 		{	if(w > (ssize_t)n)
135da2e3ebdSchin 				w = (ssize_t)n;
136da2e3ebdSchin 			if(w <= 0) /* no forward progress possible */
137da2e3ebdSchin 				break;
138da2e3ebdSchin 			memcpy(f->next, s, w);
139da2e3ebdSchin 			f->next += w;
140da2e3ebdSchin 		}
141da2e3ebdSchin 
142da2e3ebdSchin 		s += w;
143da2e3ebdSchin 		if((n -= w) <= 0)
144da2e3ebdSchin 			break;
145da2e3ebdSchin 	}
146da2e3ebdSchin 
147da2e3ebdSchin 	/* always flush buffer for share streams */
148da2e3ebdSchin 	if(f->extent < 0 && (f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) )
149da2e3ebdSchin 		(void)SFFLSBUF(f,-1);
150da2e3ebdSchin 
151da2e3ebdSchin 	/* check to see if buffer should be flushed */
152da2e3ebdSchin 	else if(n == 0 && (f->flags&SF_LINE) && !(f->flags&SF_STRING))
153da2e3ebdSchin 	{	if((ssize_t)(n = f->next-f->data) > (w = s-begs))
154da2e3ebdSchin 			n = w;
155da2e3ebdSchin 		if(n > 0 && n < HIFORLINE)
156da2e3ebdSchin 		{	for(next = f->next-1; n > 0; --n, --next)
157da2e3ebdSchin 			{	if(*next == '\n')
158da2e3ebdSchin 				{	n = HIFORLINE;
159da2e3ebdSchin 					break;
160da2e3ebdSchin 				}
161da2e3ebdSchin 			}
162da2e3ebdSchin 		}
163da2e3ebdSchin 		if(n >= HIFORLINE)
164da2e3ebdSchin 			(void)SFFLSBUF(f,-1);
165da2e3ebdSchin 	}
166da2e3ebdSchin 
167da2e3ebdSchin 	SFOPEN(f,local);
168da2e3ebdSchin 
169da2e3ebdSchin 	w = s-begs;
170da2e3ebdSchin 	SFMTXRETURN(f,w);
171da2e3ebdSchin }
172