1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2009 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 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 SFMTXDECL(f); 92 93 if(!(origf = f) ) 94 return _sfall(); 95 96 SFMTXENTER(origf,-1); 97 98 GETLOCAL(origf,local); 99 100 if(origf->disc == _Sfudisc) /* throw away ungetc */ 101 (void)sfclose((*_Sfstack)(origf,NIL(Sfio_t*))); 102 103 rv = 0; 104 105 lock = origf->mode&SF_LOCK; 106 if(origf->mode == (SF_SYNCED|SF_READ) ) /* already synced */ 107 goto done; 108 109 if((origf->mode&SF_RDWR) != SFMODE(origf,local) && _sfmode(origf,0,local) < 0) 110 { rv = -1; 111 goto done; 112 } 113 114 for(; f; f = f->push) 115 { 116 if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf) 117 (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)1),f->disc); 118 119 SFLOCK(f,local); 120 121 /* pretend that this stream is not on a stack */ 122 mode = f->mode&SF_PUSH; 123 f->mode &= ~SF_PUSH; 124 125 /* these streams do not need synchronization */ 126 if((f->flags&SF_STRING) || (f->mode&SF_SYNCED)) 127 goto next; 128 129 if((f->mode&SF_WRITE) && (f->next > f->data || (f->bits&SF_HOLE)) ) 130 { /* sync the buffer, make sure pool don't move */ 131 reg int pool = f->mode&SF_POOL; 132 f->mode &= ~SF_POOL; 133 if(f->next > f->data && (SFWRALL(f), SFFLSBUF(f,-1)) < 0) 134 rv = -1; 135 if(!SFISNULL(f) && (f->bits&SF_HOLE) ) 136 { /* realize a previously created hole of 0's */ 137 if(SFSK(f,(Sfoff_t)(-1),SEEK_CUR,f->disc) >= 0) 138 (void)SFWR(f,"",1,f->disc); 139 f->bits &= ~SF_HOLE; 140 } 141 f->mode |= pool; 142 } 143 144 if((f->mode&SF_READ) && f->extent >= 0 && 145 ((f->bits&SF_MMAP) || f->next < f->endb) ) 146 { /* make sure the file pointer is at the right place */ 147 f->here -= (f->endb-f->next); 148 f->endr = f->endw = f->data; 149 f->mode = SF_READ|SF_SYNCED|lock; 150 (void)SFSK(f,f->here,SEEK_SET,f->disc); 151 152 if((f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) && 153 !(f->bits&SF_MMAP) ) 154 { f->endb = f->next = f->data; 155 f->mode &= ~SF_SYNCED; 156 } 157 } 158 159 next: 160 f->mode |= mode; 161 SFOPEN(f,local); 162 163 if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf) 164 (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)0),f->disc); 165 } 166 167 done: 168 if(!local && f && (f->mode&SF_POOL) && f->pool && f != f->pool->sf[0]) 169 SFSYNC(f->pool->sf[0]); 170 171 SFMTXRETURN(origf, rv); 172 } 173