~ubuntu-branches/ubuntu/lucid/graphviz/lucid-security

« back to all changes in this revision

Viewing changes to tools/sfio/sfpool.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen M Moraco
  • Date: 2002-02-05 18:52:12 UTC
  • Revision ID: james.westby@ubuntu.com-20020205185212-8i04c70te00rc40y
Tags: upstream-1.7.16
ImportĀ upstreamĀ versionĀ 1.7.16

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include        "sfhdr.h"
 
2
 
 
3
/*      Management of pools of streams.
 
4
**      If pf is not nil, f is pooled with pf and f becomes current;
 
5
**      otherwise, f is isolated from its pool. flag can be one of
 
6
**      0 or SF_SHARE.
 
7
**
 
8
**      Written by Kiem-Phong Vo.
 
9
*/
 
10
 
 
11
/* Note that we do not free the space for a pool once it is allocated.
 
12
** This is to prevent memory faults in calls such as sfsync(NULL) that walk the pool
 
13
** link list and during such walks may free up streams&pools. Free pools will be
 
14
** reused in newpool().
 
15
*/
 
16
#if __STD_C
 
17
static int delpool(reg Sfpool_t* p)
 
18
#else
 
19
static int delpool(p)
 
20
reg Sfpool_t*   p;
 
21
#endif
 
22
{
 
23
        POOLMTXSTART(p);
 
24
 
 
25
        if(p->s_sf && p->sf != p->array)
 
26
                free((Void_t*)p->sf);
 
27
        p->mode = SF_AVAIL;
 
28
 
 
29
        POOLMTXRETURN(p,0);
 
30
}
 
31
 
 
32
#if __STD_C
 
33
static Sfpool_t* newpool(reg int mode)
 
34
#else
 
35
static Sfpool_t* newpool(mode)
 
36
reg int mode;
 
37
#endif
 
38
{
 
39
        reg Sfpool_t    *p, *last = &_Sfpool;
 
40
 
 
41
        /* look to see if there is a free pool */
 
42
        for(last = &_Sfpool, p = last->next; p; last = p, p = p->next)
 
43
        {       if(p->mode == SF_AVAIL )
 
44
                {       p->mode = 0;
 
45
                        break;
 
46
                }
 
47
        }
 
48
 
 
49
        if(!p)
 
50
        {       POOLMTXLOCK(last);
 
51
 
 
52
                if(!(p = (Sfpool_t*) malloc(sizeof(Sfpool_t))) )
 
53
                {       POOLMTXUNLOCK(last);
 
54
                        return NIL(Sfpool_t*);
 
55
                }
 
56
 
 
57
                vtmtxopen(&p->mutex, VT_INIT); /* initialize mutex */
 
58
 
 
59
                p->mode = 0;
 
60
                p->n_sf = 0;
 
61
                p->next = NIL(Sfpool_t*);
 
62
                last->next = p;
 
63
 
 
64
                POOLMTXUNLOCK(last);
 
65
        }
 
66
 
 
67
        POOLMTXSTART(p);
 
68
 
 
69
        p->mode = mode&SF_SHARE;
 
70
        p->s_sf = sizeof(p->array)/sizeof(p->array[0]);
 
71
        p->sf = p->array;
 
72
 
 
73
        POOLMTXRETURN(p,p);
 
74
}
 
75
 
 
76
/* move a stream to head */
 
77
#if __STD_C
 
78
static int _sfphead(Sfpool_t* p, Sfio_t* f, int n)
 
79
#else
 
80
static int _sfphead(p, f, n)
 
81
Sfpool_t*       p;      /* the pool                     */
 
82
Sfio_t*         f;      /* the stream                   */
 
83
int             n;      /* current position in pool     */
 
84
#endif
 
85
{
 
86
        reg Sfio_t*     head;
 
87
        reg ssize_t     k, w, v;
 
88
        reg int         rv;
 
89
 
 
90
        POOLMTXSTART(p);
 
91
 
 
92
        if(n == 0)
 
93
                POOLMTXRETURN(p,0);
 
94
 
 
95
        head = p->sf[0];
 
96
        if(SFFROZEN(head) )
 
97
                POOLMTXRETURN(p,-1);
 
98
 
 
99
        SFLOCK(head,0);
 
100
        rv = -1;
 
101
 
 
102
        if(!(p->mode&SF_SHARE) )
 
103
        {       if(SFSYNC(head) < 0)
 
104
                        goto done;
 
105
        }
 
106
        else    /* shared pool, data can be moved among streams */
 
107
        {       if(SFMODE(head,1) != SF_WRITE && _sfmode(head,SF_WRITE,1) < 0)
 
108
                        goto done;
 
109
                /**/ASSERT((f->mode&(SF_WRITE|SF_POOL)) == (SF_WRITE|SF_POOL) );
 
110
                /**/ASSERT(f->next == f->data);
 
111
 
 
112
                v = head->next - head->data;    /* pending data         */
 
113
                if((k = v - (f->endb-f->data)) <= 0)
 
114
                        k = 0;
 
115
                else    /* try to write out amount exceeding f's capacity */
 
116
                {       if((w = SFWR(head,head->data,k,head->disc)) == k)
 
117
                                v -= k;
 
118
                        else    /* write failed, recover buffer then quit */
 
119
                        {       if(w > 0)
 
120
                                {       v -= w;
 
121
                                        memcpy(head->data,(head->data+w),v);
 
122
                                }
 
123
                                head->next = head->data+v;
 
124
                                goto done;
 
125
                        }
 
126
                }
 
127
 
 
128
                /* move data from head to f */
 
129
                if((head->data+k) != f->data )
 
130
                        memcpy(f->data,(head->data+k),v);
 
131
                f->next = f->data+v;
 
132
        }
 
133
 
 
134
        f->mode &= ~SF_POOL;
 
135
        head->mode |= SF_POOL;
 
136
        head->next = head->endr = head->endw = head->data;
 
137
 
 
138
        p->sf[n] = head;
 
139
        p->sf[0] = f;
 
140
        rv = 0;
 
141
 
 
142
done:
 
143
        head->mode &= ~SF_LOCK; /* partially unlock because it's no longer head */
 
144
 
 
145
        POOLMTXRETURN(p,rv);
 
146
}
 
147
 
 
148
/* delete a stream from its pool */
 
149
#if __STD_C
 
150
static int _sfpdelete(Sfpool_t* p, Sfio_t* f, int n)
 
151
#else
 
152
static int _sfpdelete(p, f, n)
 
153
Sfpool_t*       p;      /* the pool             */
 
154
Sfio_t*         f;      /* the stream           */
 
155
int             n;      /* position in pool     */
 
156
#endif
 
157
{
 
158
        POOLMTXSTART(p);
 
159
 
 
160
        p->n_sf -= 1;
 
161
        for(; n < p->n_sf; ++n)
 
162
                p->sf[n] = p->sf[n+1];
 
163
 
 
164
        f->pool = NIL(Sfpool_t*);
 
165
        f->mode &= ~SF_POOL;
 
166
 
 
167
        if(p->n_sf == 0 || p == &_Sfpool)
 
168
        {       if(p != &_Sfpool)
 
169
                        delpool(p);
 
170
                goto done;
 
171
        }
 
172
 
 
173
        /* !_Sfpool, make sure head stream is an open stream */
 
174
        for(n = 0; n < p->n_sf; ++n)
 
175
                if(!SFFROZEN(p->sf[n]))
 
176
                        break;
 
177
        if(n < p->n_sf && n > 0)
 
178
        {       f = p->sf[n];
 
179
                p->sf[n] = p->sf[0];
 
180
                p->sf[0] = f;
 
181
        }
 
182
 
 
183
        /* head stream has SF_POOL off */
 
184
        f = p->sf[0];
 
185
        f->mode &= ~SF_POOL;
 
186
        if(!SFFROZEN(f))
 
187
                _SFOPEN(f);
 
188
 
 
189
        /* if only one stream left, delete pool */
 
190
        if(p->n_sf == 1 )
 
191
        {       _sfpdelete(p,f,0);
 
192
                _sfsetpool(f);
 
193
        }
 
194
 
 
195
done:
 
196
        POOLMTXRETURN(p,0);
 
197
}
 
198
 
 
199
#if __STD_C
 
200
static int _sfpmove(reg Sfio_t* f, reg int type)
 
201
#else
 
202
static int _sfpmove(f,type)
 
203
reg Sfio_t*     f;
 
204
reg int         type;   /* <0 : deleting, 0: move-to-front, >0: inserting */
 
205
#endif
 
206
{
 
207
        reg Sfpool_t*   p;
 
208
        reg int         n;
 
209
 
 
210
        if(type > 0)
 
211
                return _sfsetpool(f);
 
212
        else
 
213
        {       if(!(p = f->pool) )
 
214
                        return -1;
 
215
                for(n = p->n_sf-1; n >= 0; --n)
 
216
                        if(p->sf[n] == f)
 
217
                                break;
 
218
                if(n < 0)
 
219
                        return -1;
 
220
 
 
221
                return type == 0 ? _sfphead(p,f,n) : _sfpdelete(p,f,n);
 
222
        }
 
223
}
 
224
 
 
225
#if __STD_C
 
226
Sfio_t* sfpool(reg Sfio_t* f, reg Sfio_t* pf, reg int mode)
 
227
#else
 
228
Sfio_t* sfpool(f,pf,mode)
 
229
reg Sfio_t*     f;
 
230
reg Sfio_t*     pf;
 
231
reg int         mode;
 
232
#endif
 
233
{
 
234
        reg Sfpool_t*   p;
 
235
        reg Sfio_t*     rv;
 
236
 
 
237
        _Sfpmove = _sfpmove;
 
238
 
 
239
        if(!f)  /* return head of pool of pf regardless of lock states */
 
240
        {       if(!pf)
 
241
                        return NIL(Sfio_t*);
 
242
                else if(!pf->pool || pf->pool == &_Sfpool)
 
243
                        return pf;
 
244
                else    return pf->pool->sf[0];
 
245
        }
 
246
 
 
247
        if(f)   /* check for permissions */
 
248
        {       SFMTXLOCK(f);
 
249
                if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0)
 
250
                {       SFMTXUNLOCK(f);
 
251
                        return NIL(Sfio_t*);
 
252
                }
 
253
                if(f->disc == _Sfudisc)
 
254
                        (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*)));
 
255
        }
 
256
        if(pf)
 
257
        {       SFMTXLOCK(pf);
 
258
                if((pf->mode&SF_RDWR) != pf->mode && _sfmode(pf,0,0) < 0)
 
259
                {       if(f)
 
260
                                SFMTXUNLOCK(f);
 
261
                        SFMTXUNLOCK(pf);
 
262
                        return NIL(Sfio_t*);
 
263
                }
 
264
                if(pf->disc == _Sfudisc)
 
265
                        (void)sfclose((*_Sfstack)(pf,NIL(Sfio_t*)));
 
266
        }
 
267
 
 
268
        /* f already in the same pool with pf */
 
269
        if(f == pf || (pf && f->pool == pf->pool && f->pool != &_Sfpool) )
 
270
        {       if(f)
 
271
                        SFMTXUNLOCK(f);
 
272
                if(pf)
 
273
                        SFMTXUNLOCK(pf);
 
274
                return pf;
 
275
        }
 
276
 
 
277
        /* lock streams before internal manipulations */
 
278
        rv = NIL(Sfio_t*);
 
279
        SFLOCK(f,0);
 
280
        if(pf)
 
281
                SFLOCK(pf,0);
 
282
 
 
283
        if(!pf) /* deleting f from its current pool */
 
284
        {       if(!(p = f->pool) || p == &_Sfpool ||
 
285
                   _sfpmove(f,-1) < 0 || _sfsetpool(f) < 0)
 
286
                        goto done;
 
287
 
 
288
                if((p = f->pool) == &_Sfpool || p->n_sf <= 0)
 
289
                        rv = f;
 
290
                else    rv = p->sf[0];  /* return head of pool */
 
291
                goto done;
 
292
        }
 
293
 
 
294
        if(pf->pool && pf->pool != &_Sfpool) /* always use current mode */
 
295
                mode = pf->pool->mode;
 
296
 
 
297
        if(mode&SF_SHARE) /* can only have write streams */
 
298
        {       if(SFMODE(f,1) != SF_WRITE && _sfmode(f,SF_WRITE,1) < 0)
 
299
                        goto done;
 
300
                if(SFMODE(pf,1) != SF_WRITE && _sfmode(pf,SF_WRITE,1) < 0)
 
301
                        goto done;
 
302
                if(f->next > f->data && SFSYNC(f) < 0) /* start f clean */
 
303
                        goto done;
 
304
        }
 
305
 
 
306
        if(_sfpmove(f,-1) < 0)  /* isolate f from current pool */
 
307
                goto done;
 
308
 
 
309
        if(!(p = pf->pool) || p == &_Sfpool) /* making a new pool */
 
310
        {       if(!(p = newpool(mode)) )
 
311
                        goto done;
 
312
                if(_sfpmove(pf,-1) < 0) /* isolate pf from its current pool */
 
313
                        goto done;
 
314
                pf->pool = p;
 
315
                p->sf[0] = pf;
 
316
                p->n_sf += 1;
 
317
        }
 
318
 
 
319
        f->pool = p;    /* add f to pf's pool */
 
320
        if(_sfsetpool(f) < 0)
 
321
                goto done;
 
322
 
 
323
        /**/ASSERT(p->sf[0] == pf && p->sf[p->n_sf-1] == f);
 
324
        SFOPEN(pf,0);
 
325
        SFOPEN(f,0);
 
326
        if(_sfpmove(f,0) < 0) /* make f head of pool */
 
327
                goto done;
 
328
        rv = pf;
 
329
 
 
330
done:
 
331
        if(f)
 
332
        {       SFOPEN(f,0);
 
333
                SFMTXUNLOCK(f);
 
334
        }
 
335
        if(pf)
 
336
        {       SFOPEN(pf,0);
 
337
                SFMTXUNLOCK(pf);
 
338
        }
 
339
        return rv;
 
340
}