xref: /onnv-gate/usr/src/lib/libast/common/sfio/sfwrite.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin #include	"sfhdr.h"
234887Schin 
244887Schin /*	Write data out to the file system
254887Schin **
264887Schin **	Written by Kiem-Phong Vo.
274887Schin */
284887Schin 
294887Schin #if __STD_C
sfwrite(Sfio_t * f,const Void_t * buf,size_t n)308462SApril.Chin@Sun.COM ssize_t sfwrite(Sfio_t* f, const Void_t* buf, size_t n)
314887Schin #else
324887Schin ssize_t sfwrite(f,buf,n)
338462SApril.Chin@Sun.COM Sfio_t*		f;	/* write to this stream. 	*/
344887Schin Void_t*		buf;	/* buffer to be written.	*/
358462SApril.Chin@Sun.COM size_t		n;	/* number of bytes. 		*/
364887Schin #endif
374887Schin {
384887Schin 	reg uchar	*s, *begs, *next;
394887Schin 	reg ssize_t	w;
404887Schin 	reg int		local;
418462SApril.Chin@Sun.COM 	SFMTXDECL(f);
424887Schin 
438462SApril.Chin@Sun.COM 	SFMTXENTER(f, (ssize_t)(-1));
444887Schin 
454887Schin 	GETLOCAL(f,local);
464887Schin 
474887Schin 	if(!buf)
484887Schin 		SFMTXRETURN(f, (ssize_t)(n == 0 ? 0 : -1) );
494887Schin 
504887Schin 	/* release peek lock */
514887Schin 	if(f->mode&SF_PEEK)
524887Schin 	{	if(!(f->mode&SF_WRITE) && (f->flags&SF_RDWR) != SF_RDWR)
534887Schin 			SFMTXRETURN(f, (ssize_t)(-1));
544887Schin 
554887Schin 		if((uchar*)buf != f->next &&
564887Schin 		   (!f->rsrv || f->rsrv->data != (uchar*)buf) )
574887Schin 			SFMTXRETURN(f, (ssize_t)(-1));
584887Schin 
594887Schin 		f->mode &= ~SF_PEEK;
604887Schin 
614887Schin 		if(f->mode&SF_PKRD)
624887Schin 		{	/* read past peeked data */
634887Schin 			char		buf[16];
644887Schin 			reg ssize_t	r;
654887Schin 
664887Schin 			for(w = n; w > 0; )
674887Schin 			{	if((r = w) > sizeof(buf))
684887Schin 					r = sizeof(buf);
694887Schin 				if((r = sysreadf(f->file,buf,r)) <= 0)
704887Schin 				{	n -= w;
714887Schin 					break;
724887Schin 				}
734887Schin 				else	w -= r;
744887Schin 			}
754887Schin 
764887Schin 			f->mode &= ~SF_PKRD;
774887Schin 			f->endb = f->data + n;
784887Schin 			f->here += n;
794887Schin 		}
804887Schin 
814887Schin 		if((f->mode&SF_READ) && f->proc)
824887Schin 			f->next += n;
834887Schin 	}
844887Schin 
854887Schin 	s = begs = (uchar*)buf;
864887Schin 	for(;; f->mode &= ~SF_LOCK)
874887Schin 	{	/* check stream mode */
884887Schin 		if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0 )
894887Schin 		{	w = s > begs ? s-begs : -1;
904887Schin 			SFMTXRETURN(f,w);
914887Schin 		}
924887Schin 
934887Schin 		SFLOCK(f,local);
944887Schin 
954887Schin 		w = f->endb - f->next;
964887Schin 
974887Schin 		if(s == f->next) /* after sfreserve */
984887Schin 		{	if(w > (ssize_t)n)
994887Schin 				w = (ssize_t)n;
1004887Schin 			f->next = (s += w);
1014887Schin 			n -= w;
1024887Schin 			break;
1034887Schin 		}
1044887Schin 
1054887Schin 		/* attempt to create space in buffer */
1064887Schin 		if(w == 0 || ((f->flags&SF_WHOLE) && w < (ssize_t)n) )
1074887Schin 		{	if(f->flags&SF_STRING) /* extend buffer */
1084887Schin 			{	(void)SFWR(f, s, n-w, f->disc);
1094887Schin 				if((w = f->endb - f->next) < (ssize_t)n)
1104887Schin 				{	if(!(f->flags&SF_STRING)) /* maybe sftmp */
1114887Schin 					{	if(f->next > f->data)
1124887Schin 							goto fls_buf;
1134887Schin 					}
1144887Schin 					else if(w == 0)
1154887Schin 						break;
1164887Schin 				}
1174887Schin 			}
1184887Schin 			else if(f->next > f->data)
1194887Schin 			{ fls_buf:
1204887Schin 				(void)SFFLSBUF(f, -1);
1214887Schin 				if((w = f->endb - f->next) < (ssize_t)n &&
1224887Schin 				   (f->flags&SF_WHOLE) && f->next > f->data )
1234887Schin 						break;
1244887Schin 			}
1254887Schin 		}
1264887Schin 
1274887Schin 		if(!(f->flags&SF_STRING) && f->next == f->data &&
1284887Schin 		   (((f->flags&SF_WHOLE) && w <= n) || SFDIRECT(f,n)) )
1294887Schin 		{	/* bypass buffering */
1304887Schin 			if((w = SFWR(f,s,n,f->disc)) <= 0 )
1314887Schin 				break;
1324887Schin 		}
1334887Schin 		else
1344887Schin 		{	if(w > (ssize_t)n)
1354887Schin 				w = (ssize_t)n;
1364887Schin 			if(w <= 0) /* no forward progress possible */
1374887Schin 				break;
1384887Schin 			memcpy(f->next, s, w);
1394887Schin 			f->next += w;
1404887Schin 		}
1414887Schin 
1424887Schin 		s += w;
1434887Schin 		if((n -= w) <= 0)
1444887Schin 			break;
1454887Schin 	}
1464887Schin 
1474887Schin 	/* always flush buffer for share streams */
1484887Schin 	if(f->extent < 0 && (f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) )
1494887Schin 		(void)SFFLSBUF(f,-1);
1504887Schin 
1514887Schin 	/* check to see if buffer should be flushed */
1524887Schin 	else if(n == 0 && (f->flags&SF_LINE) && !(f->flags&SF_STRING))
1534887Schin 	{	if((ssize_t)(n = f->next-f->data) > (w = s-begs))
1544887Schin 			n = w;
1554887Schin 		if(n > 0 && n < HIFORLINE)
1564887Schin 		{	for(next = f->next-1; n > 0; --n, --next)
1574887Schin 			{	if(*next == '\n')
1584887Schin 				{	n = HIFORLINE;
1594887Schin 					break;
1604887Schin 				}
1614887Schin 			}
1624887Schin 		}
1634887Schin 		if(n >= HIFORLINE)
1644887Schin 			(void)SFFLSBUF(f,-1);
1654887Schin 	}
1664887Schin 
1674887Schin 	SFOPEN(f,local);
1684887Schin 
1694887Schin 	w = s-begs;
1704887Schin 	SFMTXRETURN(f,w);
1714887Schin }
172