1 /***********************************************************************
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 *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
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.
33 typedef struct _file_s
34 { Sfio_t
* f
; /* the stream */
35 Sfoff_t lower
; /* its lowest end */
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 */
49 static ssize_t
unwrite(Sfio_t
* f
, const Void_t
* buf
, size_t n
, Sfdisc_t
* disc
)
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 */
62 static ssize_t
unread(Sfio_t
* f
, Void_t
* buf
, size_t n
, Sfdisc_t
* disc
)
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 */
78 { if((r
= sfread(f
,buf
,m
)) < 0 || (r
== 0 && un
->c
== un
->n
-1) )
88 if(sfeof(f
) && un
->c
< un
->n
-1)
89 f
= un
->f
[un
->c
+= 1].f
;
95 static Sfoff_t
unseek(Sfio_t
* f
, Sfoff_t addr
, int type
, Sfdisc_t
* disc
)
97 static Sfoff_t
unseek(f
, addr
, type
, disc
)
106 reg Sfoff_t extent
, s
;
109 if(un
->type
&UNSEEKABLE
)
114 for(i
= 0; i
< un
->n
; ++i
)
115 extent
+= (sfsize(un
->f
[i
].f
) - un
->f
[i
].lower
);
124 /* find the stream where the addr could be in */
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
)
133 s
= (addr
-extent
) + un
->f
[i
].lower
;
134 if(sfseek(un
->f
[i
].f
,s
,0) != s
)
140 for(i
+= 1; i
< un
->n
; ++i
)
141 sfseek(un
->f
[i
].f
,un
->f
[i
].lower
,0);
146 /* on close, remove the discipline */
148 static int unexcept(Sfio_t
* f
, int type
, Void_t
* data
, Sfdisc_t
* disc
)
150 static int unexcept(f
,type
,data
,disc
)
157 if(type
== SF_FINAL
|| type
== SF_DPOP
)
164 int sfdcunion(Sfio_t
* f
, Sfio_t
** array
, int n
)
166 int sfdcunion(f
, array
, n
)
178 if(!(un
= (Union_t
*)malloc(sizeof(Union_t
)+(n
-1)*sizeof(File_t
))) )
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
;
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
)