da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1985-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "sfhdr.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Synchronize data in buffers with the file system.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** If f is nil, all streams are sync-ed
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin**
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Written by Kiem-Phong Vo.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int _sfall(void)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int _sfall()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Sfpool_t *p, *next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Sfio_t* f;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg int n, rv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg int nsync, count, loop;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define MAXLOOP 3
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(loop = 0; loop < MAXLOOP; ++loop)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { rv = nsync = count = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(p = &_Sfpool; p; p = next)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* find the next legitimate pool */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(next = p->next; next; next = next->next)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(next->n_sf > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* walk the streams for _Sfpool only */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(n = 0; n < ((p == &_Sfpool) ? p->n_sf : 1); ++n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { count += 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f = p->sf[n];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->flags&SF_STRING )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto did_sync;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(SFFROZEN(f))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->mode&SF_READ) && (f->mode&SF_SYNCED) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto did_sync;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->mode&SF_READ) && !(f->bits&SF_MMAP) &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->next == f->endb)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto did_sync;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->mode&SF_WRITE) && !(f->bits&SF_HOLE) &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->next == f->data)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto did_sync;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sfsync(f) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rv = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin did_sync:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nsync += 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(nsync == count)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return rv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint sfsync(reg Sfio_t* f)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint sfsync(f)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinreg Sfio_t* f; /* stream to be synchronized */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int local, rv, mode, lock;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t* origf;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SFMTXDECL(f);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(origf = f) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return _sfall();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin SFMTXENTER(origf,-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin GETLOCAL(origf,local);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(origf->disc == _Sfudisc) /* throw away ungetc */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)sfclose((*_Sfstack)(origf,NIL(Sfio_t*)));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rv = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin lock = origf->mode&SF_LOCK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(origf->mode == (SF_SYNCED|SF_READ) ) /* already synced */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((origf->mode&SF_RDWR) != SFMODE(origf,local) && _sfmode(origf,0,local) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { rv = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(; f; f = f->push)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)1),f->disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFLOCK(f,local);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* pretend that this stream is not on a stack */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mode = f->mode&SF_PUSH;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode &= ~SF_PUSH;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* these streams do not need synchronization */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->flags&SF_STRING) || (f->mode&SF_SYNCED))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->mode&SF_WRITE) && (f->next > f->data || (f->bits&SF_HOLE)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* sync the buffer, make sure pool don't move */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg int pool = f->mode&SF_POOL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode &= ~SF_POOL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(f->next > f->data && (SFWRALL(f), SFFLSBUF(f,-1)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rv = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!SFISNULL(f) && (f->bits&SF_HOLE) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* realize a previously created hole of 0's */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(SFSK(f,(Sfoff_t)(-1),SEEK_CUR,f->disc) >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)SFWR(f,"",1,f->disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->bits &= ~SF_HOLE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode |= pool;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->mode&SF_READ) && f->extent >= 0 &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ((f->bits&SF_MMAP) || f->next < f->endb) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* make sure the file pointer is at the right place */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->here -= (f->endb-f->next);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->endr = f->endw = f->data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode = SF_READ|SF_SYNCED|lock;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)SFSK(f,f->here,SEEK_SET,f->disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin !(f->bits&SF_MMAP) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { f->endb = f->next = f->data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode &= ~SF_SYNCED;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin next:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->mode |= mode;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFOPEN(f,local);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)0),f->disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chindone:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!local && f && (f->mode&SF_POOL) && f->pool && f != f->pool->sf[0])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFSYNC(f->pool->sf[0]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SFMTXRETURN(origf, rv);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}