summaryrefslogtreecommitdiff
path: root/src/lib/libast/sfio/sfsync.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
committerIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
commit3950ffe2a485479f6561c27364d3d7df5a21d124 (patch)
tree468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libast/sfio/sfsync.c
downloadksh-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.c172
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);
+}