1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * Glenn Fowler <gsf@research.att.com> * 18*4887Schin * David Korn <dgk@research.att.com> * 19*4887Schin * Phong Vo <kpv@research.att.com> * 20*4887Schin * * 21*4887Schin ***********************************************************************/ 22*4887Schin #include "sfdchdr.h" 23*4887Schin 24*4887Schin 25*4887Schin /* Make a sequence of streams act like a single stream. 26*4887Schin ** This is for reading only. 27*4887Schin ** 28*4887Schin ** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998. 29*4887Schin */ 30*4887Schin 31*4887Schin #define UNSEEKABLE 1 32*4887Schin 33*4887Schin typedef struct _file_s 34*4887Schin { Sfio_t* f; /* the stream */ 35*4887Schin Sfoff_t lower; /* its lowest end */ 36*4887Schin } File_t; 37*4887Schin 38*4887Schin typedef struct _union_s 39*4887Schin { 40*4887Schin Sfdisc_t disc; /* discipline structure */ 41*4887Schin short type; /* type of streams */ 42*4887Schin short c; /* current stream */ 43*4887Schin short n; /* number of streams */ 44*4887Schin Sfoff_t here; /* current location */ 45*4887Schin File_t f[1]; /* array of streams */ 46*4887Schin } Union_t; 47*4887Schin 48*4887Schin #if __STD_C 49*4887Schin static ssize_t unwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) 50*4887Schin #else 51*4887Schin static ssize_t unwrite(f, buf, n, disc) 52*4887Schin Sfio_t* f; /* stream involved */ 53*4887Schin Void_t* buf; /* buffer to read into */ 54*4887Schin size_t n; /* number of bytes to read */ 55*4887Schin Sfdisc_t* disc; /* discipline */ 56*4887Schin #endif 57*4887Schin { 58*4887Schin return -1; 59*4887Schin } 60*4887Schin 61*4887Schin #if __STD_C 62*4887Schin static ssize_t unread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) 63*4887Schin #else 64*4887Schin static ssize_t unread(f, buf, n, disc) 65*4887Schin Sfio_t* f; /* stream involved */ 66*4887Schin Void_t* buf; /* buffer to read into */ 67*4887Schin size_t n; /* number of bytes to read */ 68*4887Schin Sfdisc_t* disc; /* discipline */ 69*4887Schin #endif 70*4887Schin { 71*4887Schin reg Union_t* un; 72*4887Schin reg ssize_t r, m; 73*4887Schin 74*4887Schin un = (Union_t*)disc; 75*4887Schin m = n; 76*4887Schin f = un->f[un->c].f; 77*4887Schin while(1) 78*4887Schin { if((r = sfread(f,buf,m)) < 0 || (r == 0 && un->c == un->n-1) ) 79*4887Schin break; 80*4887Schin 81*4887Schin m -= r; 82*4887Schin un->here += r; 83*4887Schin 84*4887Schin if(m == 0) 85*4887Schin break; 86*4887Schin 87*4887Schin buf = (char*)buf + r; 88*4887Schin if(sfeof(f) && un->c < un->n-1) 89*4887Schin f = un->f[un->c += 1].f; 90*4887Schin } 91*4887Schin return n-m; 92*4887Schin } 93*4887Schin 94*4887Schin #if __STD_C 95*4887Schin static Sfoff_t unseek(Sfio_t* f, Sfoff_t addr, int type, Sfdisc_t* disc) 96*4887Schin #else 97*4887Schin static Sfoff_t unseek(f, addr, type, disc) 98*4887Schin Sfio_t* f; 99*4887Schin Sfoff_t addr; 100*4887Schin int type; 101*4887Schin Sfdisc_t* disc; 102*4887Schin #endif 103*4887Schin { 104*4887Schin reg Union_t* un; 105*4887Schin reg int i; 106*4887Schin reg Sfoff_t extent, s; 107*4887Schin 108*4887Schin un = (Union_t*)disc; 109*4887Schin if(un->type&UNSEEKABLE) 110*4887Schin return -1L; 111*4887Schin 112*4887Schin if(type == 2) 113*4887Schin { extent = 0; 114*4887Schin for(i = 0; i < un->n; ++i) 115*4887Schin extent += (sfsize(un->f[i].f) - un->f[i].lower); 116*4887Schin addr += extent; 117*4887Schin } 118*4887Schin else if(type == 1) 119*4887Schin addr += un->here; 120*4887Schin 121*4887Schin if(addr < 0) 122*4887Schin return -1; 123*4887Schin 124*4887Schin /* find the stream where the addr could be in */ 125*4887Schin extent = 0; 126*4887Schin for(i = 0; i < un->n-1; ++i) 127*4887Schin { s = sfsize(un->f[i].f) - un->f[i].lower; 128*4887Schin if(addr < extent + s) 129*4887Schin break; 130*4887Schin extent += s; 131*4887Schin } 132*4887Schin 133*4887Schin s = (addr-extent) + un->f[i].lower; 134*4887Schin if(sfseek(un->f[i].f,s,0) != s) 135*4887Schin return -1; 136*4887Schin 137*4887Schin un->c = i; 138*4887Schin un->here = addr; 139*4887Schin 140*4887Schin for(i += 1; i < un->n; ++i) 141*4887Schin sfseek(un->f[i].f,un->f[i].lower,0); 142*4887Schin 143*4887Schin return addr; 144*4887Schin } 145*4887Schin 146*4887Schin /* on close, remove the discipline */ 147*4887Schin #if __STD_C 148*4887Schin static int unexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) 149*4887Schin #else 150*4887Schin static int unexcept(f,type,data,disc) 151*4887Schin Sfio_t* f; 152*4887Schin int type; 153*4887Schin Void_t* data; 154*4887Schin Sfdisc_t* disc; 155*4887Schin #endif 156*4887Schin { 157*4887Schin if(type == SF_FINAL || type == SF_DPOP) 158*4887Schin free(disc); 159*4887Schin 160*4887Schin return 0; 161*4887Schin } 162*4887Schin 163*4887Schin #if __STD_C 164*4887Schin int sfdcunion(Sfio_t* f, Sfio_t** array, int n) 165*4887Schin #else 166*4887Schin int sfdcunion(f, array, n) 167*4887Schin Sfio_t* f; 168*4887Schin Sfio_t** array; 169*4887Schin int n; 170*4887Schin #endif 171*4887Schin { 172*4887Schin reg Union_t* un; 173*4887Schin reg int i; 174*4887Schin 175*4887Schin if(n <= 0) 176*4887Schin return -1; 177*4887Schin 178*4887Schin if(!(un = (Union_t*)malloc(sizeof(Union_t)+(n-1)*sizeof(File_t))) ) 179*4887Schin return -1; 180*4887Schin memset(un, 0, sizeof(*un)); 181*4887Schin 182*4887Schin un->disc.readf = unread; 183*4887Schin un->disc.writef = unwrite; 184*4887Schin un->disc.seekf = unseek; 185*4887Schin un->disc.exceptf = unexcept; 186*4887Schin un->n = n; 187*4887Schin 188*4887Schin for(i = 0; i < n; ++i) 189*4887Schin { un->f[i].f = array[i]; 190*4887Schin if(!(un->type&UNSEEKABLE)) 191*4887Schin { un->f[i].lower = sfseek(array[i],(Sfoff_t)0,1); 192*4887Schin if(un->f[i].lower < 0) 193*4887Schin un->type |= UNSEEKABLE; 194*4887Schin } 195*4887Schin } 196*4887Schin 197*4887Schin if(sfdisc(f,(Sfdisc_t*)un) != (Sfdisc_t*)un) 198*4887Schin { free(un); 199*4887Schin return -1; 200*4887Schin } 201*4887Schin 202*4887Schin return 0; 203*4887Schin } 204