1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
/* $Id: sfsync.c,v 1.1.1.1 2004/12/23 04:04:14 ellson Exp $ $Revision: 1.1.1.1 $ */
/* vim:set shiftwidth=4 ts=8: */
/**********************************************************
* This software is part of the graphviz package *
* http://www.graphviz.org/ *
* *
* Copyright (c) 1994-2004 AT&T Corp. *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Corp. *
* *
* Information and Software Systems Research *
* AT&T Research, Florham Park NJ *
**********************************************************/
#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;
Sfio_t *origf;
if (!(origf = f))
return _sfall();
SFMTXSTART(origf, -1);
GETLOCAL(origf, local);
if (origf->disc == _Sfudisc) /* throw away ungetc */
(void) sfclose((*_Sfstack) (origf, NIL(Sfio_t *)));
rv = 0;
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 | SF_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);
}
|