8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / lib / libast / common / disc / sfdcunion.c
blob310e38ecde4b9b524fd2dd250a328dba249ec37f
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 "sfdchdr.h"
25 /* Make a sequence of streams act like a single stream.
26 ** This is for reading only.
28 ** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998.
31 #define UNSEEKABLE 1
33 typedef struct _file_s
34 { Sfio_t* f; /* the stream */
35 Sfoff_t lower; /* its lowest end */
36 } File_t;
38 typedef struct _union_s
40 Sfdisc_t disc; /* discipline structure */
41 short type; /* type of streams */
42 short c; /* current stream */
43 short n; /* number of streams */
44 Sfoff_t here; /* current location */
45 File_t f[1]; /* array of streams */
46 } Union_t;
48 #if __STD_C
49 static ssize_t unwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
50 #else
51 static ssize_t unwrite(f, buf, n, disc)
52 Sfio_t* f; /* stream involved */
53 Void_t* buf; /* buffer to read into */
54 size_t n; /* number of bytes to read */
55 Sfdisc_t* disc; /* discipline */
56 #endif
58 return -1;
61 #if __STD_C
62 static ssize_t unread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
63 #else
64 static ssize_t unread(f, buf, n, disc)
65 Sfio_t* f; /* stream involved */
66 Void_t* buf; /* buffer to read into */
67 size_t n; /* number of bytes to read */
68 Sfdisc_t* disc; /* discipline */
69 #endif
71 reg Union_t* un;
72 reg ssize_t r, m;
74 un = (Union_t*)disc;
75 m = n;
76 f = un->f[un->c].f;
77 while(1)
78 { if((r = sfread(f,buf,m)) < 0 || (r == 0 && un->c == un->n-1) )
79 break;
81 m -= r;
82 un->here += r;
84 if(m == 0)
85 break;
87 buf = (char*)buf + r;
88 if(sfeof(f) && un->c < un->n-1)
89 f = un->f[un->c += 1].f;
91 return n-m;
94 #if __STD_C
95 static Sfoff_t unseek(Sfio_t* f, Sfoff_t addr, int type, Sfdisc_t* disc)
96 #else
97 static Sfoff_t unseek(f, addr, type, disc)
98 Sfio_t* f;
99 Sfoff_t addr;
100 int type;
101 Sfdisc_t* disc;
102 #endif
104 reg Union_t* un;
105 reg int i;
106 reg Sfoff_t extent, s;
108 un = (Union_t*)disc;
109 if(un->type&UNSEEKABLE)
110 return -1L;
112 if(type == 2)
113 { extent = 0;
114 for(i = 0; i < un->n; ++i)
115 extent += (sfsize(un->f[i].f) - un->f[i].lower);
116 addr += extent;
118 else if(type == 1)
119 addr += un->here;
121 if(addr < 0)
122 return -1;
124 /* find the stream where the addr could be in */
125 extent = 0;
126 for(i = 0; i < un->n-1; ++i)
127 { s = sfsize(un->f[i].f) - un->f[i].lower;
128 if(addr < extent + s)
129 break;
130 extent += s;
133 s = (addr-extent) + un->f[i].lower;
134 if(sfseek(un->f[i].f,s,0) != s)
135 return -1;
137 un->c = i;
138 un->here = addr;
140 for(i += 1; i < un->n; ++i)
141 sfseek(un->f[i].f,un->f[i].lower,0);
143 return addr;
146 /* on close, remove the discipline */
147 #if __STD_C
148 static int unexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
149 #else
150 static int unexcept(f,type,data,disc)
151 Sfio_t* f;
152 int type;
153 Void_t* data;
154 Sfdisc_t* disc;
155 #endif
157 if(type == SF_FINAL || type == SF_DPOP)
158 free(disc);
160 return 0;
163 #if __STD_C
164 int sfdcunion(Sfio_t* f, Sfio_t** array, int n)
165 #else
166 int sfdcunion(f, array, n)
167 Sfio_t* f;
168 Sfio_t** array;
169 int n;
170 #endif
172 reg Union_t* un;
173 reg int i;
175 if(n <= 0)
176 return -1;
178 if(!(un = (Union_t*)malloc(sizeof(Union_t)+(n-1)*sizeof(File_t))) )
179 return -1;
180 memset(un, 0, sizeof(*un));
182 un->disc.readf = unread;
183 un->disc.writef = unwrite;
184 un->disc.seekf = unseek;
185 un->disc.exceptf = unexcept;
186 un->n = n;
188 for(i = 0; i < n; ++i)
189 { un->f[i].f = array[i];
190 if(!(un->type&UNSEEKABLE))
191 { un->f[i].lower = sfseek(array[i],(Sfoff_t)0,1);
192 if(un->f[i].lower < 0)
193 un->type |= UNSEEKABLE;
197 if(sfdisc(f,(Sfdisc_t*)un) != (Sfdisc_t*)un)
198 { free(un);
199 return -1;
202 return 0;