14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1985-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.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 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 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; 91*8462SApril.Chin@Sun.COM SFMTXDECL(f); 924887Schin 934887Schin if(!(origf = f) ) 944887Schin return _sfall(); 954887Schin 96*8462SApril.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