diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
commit | 3950ffe2a485479f6561c27364d3d7df5a21d124 (patch) | |
tree | 468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libast/sfio/sfsync.c | |
download | ksh-upstream.tar.gz |
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib/libast/sfio/sfsync.c')
-rw-r--r-- | src/lib/libast/sfio/sfsync.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/src/lib/libast/sfio/sfsync.c b/src/lib/libast/sfio/sfsync.c new file mode 100644 index 0000000..4a9d16f --- /dev/null +++ b/src/lib/libast/sfio/sfsync.c @@ -0,0 +1,172 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#include "sfhdr.h" + +/* Synchronize data in buffers with the file system. +** If f is nil, all streams are sync-ed +** +** Written by Kiem-Phong Vo. +*/ + +#if __STD_C +static int _sfall(void) +#else +static int _sfall() +#endif +{ + reg Sfpool_t *p, *next; + reg Sfio_t* f; + reg int n, rv; + reg int nsync, count, loop; +#define MAXLOOP 3 + + for(loop = 0; loop < MAXLOOP; ++loop) + { rv = nsync = count = 0; + for(p = &_Sfpool; p; p = next) + { /* find the next legitimate pool */ + for(next = p->next; next; next = next->next) + if(next->n_sf > 0) + break; + + /* walk the streams for _Sfpool only */ + for(n = 0; n < ((p == &_Sfpool) ? p->n_sf : 1); ++n) + { count += 1; + f = p->sf[n]; + + if(f->flags&SF_STRING ) + goto did_sync; + if(SFFROZEN(f)) + continue; + if((f->mode&SF_READ) && (f->mode&SF_SYNCED) ) + goto did_sync; + if((f->mode&SF_READ) && !(f->bits&SF_MMAP) && + f->next == f->endb) + goto did_sync; + if((f->mode&SF_WRITE) && !(f->bits&SF_HOLE) && + f->next == f->data) + goto did_sync; + + if(sfsync(f) < 0) + rv = -1; + + did_sync: + nsync += 1; + } + } + + if(nsync == count) + break; + } + return rv; +} + +#if __STD_C +int sfsync(reg Sfio_t* f) +#else +int sfsync(f) +reg Sfio_t* f; /* stream to be synchronized */ +#endif +{ + int local, rv, mode, lock; + Sfio_t* origf; + SFMTXDECL(f); + + if(!(origf = f) ) + return _sfall(); + + SFMTXENTER(origf,-1); + + GETLOCAL(origf,local); + + if(origf->disc == _Sfudisc) /* throw away ungetc */ + (void)sfclose((*_Sfstack)(origf,NIL(Sfio_t*))); + + rv = 0; + + lock = origf->mode&SF_LOCK; + if(origf->mode == (SF_SYNCED|SF_READ) ) /* already synced */ + goto done; + + if((origf->mode&SF_RDWR) != SFMODE(origf,local) && _sfmode(origf,0,local) < 0) + { rv = -1; + goto done; + } + + for(; f; f = f->push) + { + if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf) + (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)1),f->disc); + + SFLOCK(f,local); + + /* pretend that this stream is not on a stack */ + mode = f->mode&SF_PUSH; + f->mode &= ~SF_PUSH; + + /* these streams do not need synchronization */ + if((f->flags&SF_STRING) || (f->mode&SF_SYNCED)) + goto next; + + if((f->mode&SF_WRITE) && (f->next > f->data || (f->bits&SF_HOLE)) ) + { /* sync the buffer, make sure pool don't move */ + reg int pool = f->mode&SF_POOL; + f->mode &= ~SF_POOL; + if(f->next > f->data && (SFWRALL(f), SFFLSBUF(f,-1)) < 0) + rv = -1; + if(!SFISNULL(f) && (f->bits&SF_HOLE) ) + { /* realize a previously created hole of 0's */ + if(SFSK(f,(Sfoff_t)(-1),SEEK_CUR,f->disc) >= 0) + (void)SFWR(f,"",1,f->disc); + f->bits &= ~SF_HOLE; + } + f->mode |= pool; + } + + if((f->mode&SF_READ) && f->extent >= 0 && + ((f->bits&SF_MMAP) || f->next < f->endb) ) + { /* make sure the file pointer is at the right place */ + f->here -= (f->endb-f->next); + f->endr = f->endw = f->data; + f->mode = SF_READ|SF_SYNCED|lock; + (void)SFSK(f,f->here,SEEK_SET,f->disc); + + if((f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) && + !(f->bits&SF_MMAP) ) + { f->endb = f->next = f->data; + f->mode &= ~SF_SYNCED; + } + } + + next: + f->mode |= mode; + SFOPEN(f,local); + + if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf) + (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)0),f->disc); + } + +done: + if(!local && f && (f->mode&SF_POOL) && f->pool && f != f->pool->sf[0]) + SFSYNC(f->pool->sf[0]); + + SFMTXRETURN(origf, rv); +} |