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