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 /* Synchronize data in buffers with the file system.
254887Schin ** If f is nil, all streams are sync-ed
264887Schin **
274887Schin ** Written by Kiem-Phong Vo.
284887Schin */
294887Schin
304887Schin #if __STD_C
_sfall(void)314887Schin static int _sfall(void)
324887Schin #else
334887Schin static int _sfall()
344887Schin #endif
354887Schin {
364887Schin reg Sfpool_t *p, *next;
374887Schin reg Sfio_t* f;
384887Schin reg int n, rv;
394887Schin reg int nsync, count, loop;
404887Schin #define MAXLOOP 3
414887Schin
424887Schin for(loop = 0; loop < MAXLOOP; ++loop)
434887Schin { rv = nsync = count = 0;
444887Schin for(p = &_Sfpool; p; p = next)
454887Schin { /* find the next legitimate pool */
464887Schin for(next = p->next; next; next = next->next)
474887Schin if(next->n_sf > 0)
484887Schin break;
494887Schin
504887Schin /* walk the streams for _Sfpool only */
514887Schin for(n = 0; n < ((p == &_Sfpool) ? p->n_sf : 1); ++n)
524887Schin { count += 1;
534887Schin f = p->sf[n];
544887Schin
554887Schin if(f->flags&SF_STRING )
564887Schin goto did_sync;
574887Schin if(SFFROZEN(f))
584887Schin continue;
594887Schin if((f->mode&SF_READ) && (f->mode&SF_SYNCED) )
604887Schin goto did_sync;
614887Schin if((f->mode&SF_READ) && !(f->bits&SF_MMAP) &&
624887Schin f->next == f->endb)
634887Schin goto did_sync;
644887Schin if((f->mode&SF_WRITE) && !(f->bits&SF_HOLE) &&
654887Schin f->next == f->data)
664887Schin goto did_sync;
674887Schin
684887Schin if(sfsync(f) < 0)
694887Schin rv = -1;
704887Schin
714887Schin did_sync:
724887Schin nsync += 1;
734887Schin }
744887Schin }
754887Schin
764887Schin if(nsync == count)
774887Schin break;
784887Schin }
794887Schin return rv;
804887Schin }
814887Schin
824887Schin #if __STD_C
sfsync(reg Sfio_t * f)834887Schin int sfsync(reg Sfio_t* f)
844887Schin #else
854887Schin int sfsync(f)
864887Schin reg Sfio_t* f; /* stream to be synchronized */
874887Schin #endif
884887Schin {
894887Schin int local, rv, mode, lock;
904887Schin Sfio_t* origf;
918462SApril.Chin@Sun.COM SFMTXDECL(f);
924887Schin
934887Schin if(!(origf = f) )
944887Schin return _sfall();
954887Schin
968462SApril.Chin@Sun.COM SFMTXENTER(origf,-1);
974887Schin
984887Schin GETLOCAL(origf,local);
994887Schin
1004887Schin if(origf->disc == _Sfudisc) /* throw away ungetc */
1014887Schin (void)sfclose((*_Sfstack)(origf,NIL(Sfio_t*)));
1024887Schin
1034887Schin rv = 0;
1044887Schin
1054887Schin lock = origf->mode&SF_LOCK;
1064887Schin if(origf->mode == (SF_SYNCED|SF_READ) ) /* already synced */
1074887Schin goto done;
1084887Schin
1094887Schin if((origf->mode&SF_RDWR) != SFMODE(origf,local) && _sfmode(origf,0,local) < 0)
1104887Schin { rv = -1;
1114887Schin goto done;
1124887Schin }
1134887Schin
1144887Schin for(; f; f = f->push)
1154887Schin {
1164887Schin if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf)
1174887Schin (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)1),f->disc);
1184887Schin
1194887Schin SFLOCK(f,local);
1204887Schin
1214887Schin /* pretend that this stream is not on a stack */
1224887Schin mode = f->mode&SF_PUSH;
1234887Schin f->mode &= ~SF_PUSH;
1244887Schin
1254887Schin /* these streams do not need synchronization */
1264887Schin if((f->flags&SF_STRING) || (f->mode&SF_SYNCED))
1274887Schin goto next;
1284887Schin
1294887Schin if((f->mode&SF_WRITE) && (f->next > f->data || (f->bits&SF_HOLE)) )
1304887Schin { /* sync the buffer, make sure pool don't move */
1314887Schin reg int pool = f->mode&SF_POOL;
1324887Schin f->mode &= ~SF_POOL;
1334887Schin if(f->next > f->data && (SFWRALL(f), SFFLSBUF(f,-1)) < 0)
1344887Schin rv = -1;
1354887Schin if(!SFISNULL(f) && (f->bits&SF_HOLE) )
1364887Schin { /* realize a previously created hole of 0's */
1374887Schin if(SFSK(f,(Sfoff_t)(-1),SEEK_CUR,f->disc) >= 0)
1384887Schin (void)SFWR(f,"",1,f->disc);
1394887Schin f->bits &= ~SF_HOLE;
1404887Schin }
1414887Schin f->mode |= pool;
1424887Schin }
1434887Schin
1444887Schin if((f->mode&SF_READ) && f->extent >= 0 &&
1454887Schin ((f->bits&SF_MMAP) || f->next < f->endb) )
1464887Schin { /* make sure the file pointer is at the right place */
1474887Schin f->here -= (f->endb-f->next);
1484887Schin f->endr = f->endw = f->data;
1494887Schin f->mode = SF_READ|SF_SYNCED|lock;
1504887Schin (void)SFSK(f,f->here,SEEK_SET,f->disc);
1514887Schin
1524887Schin if((f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) &&
1534887Schin !(f->bits&SF_MMAP) )
1544887Schin { f->endb = f->next = f->data;
1554887Schin f->mode &= ~SF_SYNCED;
1564887Schin }
1574887Schin }
1584887Schin
1594887Schin next:
1604887Schin f->mode |= mode;
1614887Schin SFOPEN(f,local);
1624887Schin
1634887Schin if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf)
1644887Schin (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)0),f->disc);
1654887Schin }
1664887Schin
1674887Schin done:
1684887Schin if(!local && f && (f->mode&SF_POOL) && f->pool && f != f->pool->sf[0])
1694887Schin SFSYNC(f->pool->sf[0]);
1704887Schin
1714887Schin SFMTXRETURN(origf, rv);
1724887Schin }
173