1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #include "sfhdr.h" 23 24 /* Synchronize data in buffers with the file system. 25 ** If f is nil, all streams are sync-ed 26 ** 27 ** Written by Kiem-Phong Vo. 28 */ 29 30 #if __STD_C 31 static int _sfall(void) 32 #else 33 static int _sfall() 34 #endif 35 { 36 reg Sfpool_t *p, *next; 37 reg Sfio_t* f; 38 reg int n, rv; 39 reg int nsync, count, loop; 40 #define MAXLOOP 3 41 42 for(loop = 0; loop < MAXLOOP; ++loop) 43 { rv = nsync = count = 0; 44 for(p = &_Sfpool; p; p = next) 45 { /* find the next legitimate pool */ 46 for(next = p->next; next; next = next->next) 47 if(next->n_sf > 0) 48 break; 49 50 /* walk the streams for _Sfpool only */ 51 for(n = 0; n < ((p == &_Sfpool) ? p->n_sf : 1); ++n) 52 { count += 1; 53 f = p->sf[n]; 54 55 if(f->flags&SF_STRING ) 56 goto did_sync; 57 if(SFFROZEN(f)) 58 continue; 59 if((f->mode&SF_READ) && (f->mode&SF_SYNCED) ) 60 goto did_sync; 61 if((f->mode&SF_READ) && !(f->bits&SF_MMAP) && 62 f->next == f->endb) 63 goto did_sync; 64 if((f->mode&SF_WRITE) && !(f->bits&SF_HOLE) && 65 f->next == f->data) 66 goto did_sync; 67 68 if(sfsync(f) < 0) 69 rv = -1; 70 71 did_sync: 72 nsync += 1; 73 } 74 } 75 76 if(nsync == count) 77 break; 78 } 79 return rv; 80 } 81 82 #if __STD_C 83 int sfsync(reg Sfio_t* f) 84 #else 85 int sfsync(f) 86 reg Sfio_t* f; /* stream to be synchronized */ 87 #endif 88 { 89 int local, rv, mode, lock; 90 Sfio_t* origf; 91 92 if(!(origf = f) ) 93 return _sfall(); 94 95 SFMTXSTART(origf,-1); 96 97 GETLOCAL(origf,local); 98 99 if(origf->disc == _Sfudisc) /* throw away ungetc */ 100 (void)sfclose((*_Sfstack)(origf,NIL(Sfio_t*))); 101 102 rv = 0; 103 104 lock = origf->mode&SF_LOCK; 105 if(origf->mode == (SF_SYNCED|SF_READ) ) /* already synced */ 106 goto done; 107 108 if((origf->mode&SF_RDWR) != SFMODE(origf,local) && _sfmode(origf,0,local) < 0) 109 { rv = -1; 110 goto done; 111 } 112 113 for(; f; f = f->push) 114 { 115 if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf) 116 (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)1),f->disc); 117 118 SFLOCK(f,local); 119 120 /* pretend that this stream is not on a stack */ 121 mode = f->mode&SF_PUSH; 122 f->mode &= ~SF_PUSH; 123 124 /* these streams do not need synchronization */ 125 if((f->flags&SF_STRING) || (f->mode&SF_SYNCED)) 126 goto next; 127 128 if((f->mode&SF_WRITE) && (f->next > f->data || (f->bits&SF_HOLE)) ) 129 { /* sync the buffer, make sure pool don't move */ 130 reg int pool = f->mode&SF_POOL; 131 f->mode &= ~SF_POOL; 132 if(f->next > f->data && (SFWRALL(f), SFFLSBUF(f,-1)) < 0) 133 rv = -1; 134 if(!SFISNULL(f) && (f->bits&SF_HOLE) ) 135 { /* realize a previously created hole of 0's */ 136 if(SFSK(f,(Sfoff_t)(-1),SEEK_CUR,f->disc) >= 0) 137 (void)SFWR(f,"",1,f->disc); 138 f->bits &= ~SF_HOLE; 139 } 140 f->mode |= pool; 141 } 142 143 if((f->mode&SF_READ) && f->extent >= 0 && 144 ((f->bits&SF_MMAP) || f->next < f->endb) ) 145 { /* make sure the file pointer is at the right place */ 146 f->here -= (f->endb-f->next); 147 f->endr = f->endw = f->data; 148 f->mode = SF_READ|SF_SYNCED|lock; 149 (void)SFSK(f,f->here,SEEK_SET,f->disc); 150 151 if((f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) && 152 !(f->bits&SF_MMAP) ) 153 { f->endb = f->next = f->data; 154 f->mode &= ~SF_SYNCED; 155 } 156 } 157 158 next: 159 f->mode |= mode; 160 SFOPEN(f,local); 161 162 if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf) 163 (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)0),f->disc); 164 } 165 166 done: 167 if(!local && f && (f->mode&SF_POOL) && f->pool && f != f->pool->sf[0]) 168 SFSYNC(f->pool->sf[0]); 169 170 SFMTXRETURN(origf, rv); 171 } 172