1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 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
_sfall(void)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
sfsync(reg Sfio_t * f)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