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 /* Discipline to treat a contiguous segment of a stream as a stream 26*4887Schin ** in its own right. The hard part in all this is to allow multiple 27*4887Schin ** segments of the stream to be used as substreams at the same time. 28*4887Schin ** 29*4887Schin ** Written by David G. Korn and Kiem-Phong Vo (03/18/1998) 30*4887Schin */ 31*4887Schin 32*4887Schin typedef struct _subfile_s 33*4887Schin { 34*4887Schin Sfdisc_t disc; /* sfio discipline */ 35*4887Schin Sfio_t* parent; /* parent stream */ 36*4887Schin Sfoff_t offset; /* starting offset */ 37*4887Schin Sfoff_t extent; /* size wanted */ 38*4887Schin Sfoff_t here; /* current seek location */ 39*4887Schin } Subfile_t; 40*4887Schin 41*4887Schin #if __STD_C 42*4887Schin static ssize_t streamio(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc, int type) 43*4887Schin #else 44*4887Schin static ssize_t streamio(f, buf, n, disc, type) 45*4887Schin Sfio_t* f; 46*4887Schin Void_t* buf; 47*4887Schin size_t n; 48*4887Schin Sfdisc_t* disc; 49*4887Schin int type; 50*4887Schin #endif 51*4887Schin { 52*4887Schin reg Subfile_t *su; 53*4887Schin reg Sfoff_t here, parent; 54*4887Schin reg ssize_t io; 55*4887Schin 56*4887Schin su = (Subfile_t*)disc; 57*4887Schin 58*4887Schin /* read just what we need */ 59*4887Schin if(su->extent >= 0 && (ssize_t)n > (io = (ssize_t)(su->extent - su->here)) ) 60*4887Schin n = io; 61*4887Schin if(n <= 0) 62*4887Schin return n; 63*4887Schin 64*4887Schin /* save current location in parent stream */ 65*4887Schin parent = sfsk(f,(Sfoff_t)0,SEEK_CUR,disc); 66*4887Schin 67*4887Schin /* read data */ 68*4887Schin here = su->here + su->offset; 69*4887Schin if(sfsk(f,here,SEEK_SET,disc) != here) 70*4887Schin io = 0; 71*4887Schin else 72*4887Schin { if(type == SF_WRITE) 73*4887Schin io = sfwr(f,buf,n,disc); 74*4887Schin else io = sfrd(f,buf,n,disc); 75*4887Schin if(io > 0) 76*4887Schin su->here += io; 77*4887Schin } 78*4887Schin 79*4887Schin /* restore parent current position */ 80*4887Schin sfsk(f,parent,SEEK_SET,disc); 81*4887Schin 82*4887Schin return io; 83*4887Schin } 84*4887Schin 85*4887Schin #if __STD_C 86*4887Schin static ssize_t streamwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) 87*4887Schin #else 88*4887Schin static ssize_t streamwrite(f, buf, n, disc) 89*4887Schin Sfio_t* f; 90*4887Schin Void_t* buf; 91*4887Schin size_t n; 92*4887Schin Sfdisc_t* disc; 93*4887Schin #endif 94*4887Schin { 95*4887Schin return streamio(f,(Void_t*)buf,n,disc,SF_WRITE); 96*4887Schin } 97*4887Schin 98*4887Schin #if __STD_C 99*4887Schin static ssize_t streamread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) 100*4887Schin #else 101*4887Schin static ssize_t streamread(f, buf, n, disc) 102*4887Schin Sfio_t* f; 103*4887Schin Void_t* buf; 104*4887Schin size_t n; 105*4887Schin Sfdisc_t* disc; 106*4887Schin #endif 107*4887Schin { 108*4887Schin return streamio(f,buf,n,disc,SF_READ); 109*4887Schin } 110*4887Schin 111*4887Schin #if __STD_C 112*4887Schin static Sfoff_t streamseek(Sfio_t* f, Sfoff_t pos, int type, Sfdisc_t* disc) 113*4887Schin #else 114*4887Schin static Sfoff_t streamseek(f, pos, type, disc) 115*4887Schin Sfio_t* f; 116*4887Schin Sfoff_t pos; 117*4887Schin int type; 118*4887Schin Sfdisc_t* disc; 119*4887Schin #endif 120*4887Schin { 121*4887Schin reg Subfile_t* su; 122*4887Schin reg Sfoff_t here, parent; 123*4887Schin 124*4887Schin su = (Subfile_t*)disc; 125*4887Schin 126*4887Schin switch(type) 127*4887Schin { 128*4887Schin case SEEK_SET: 129*4887Schin here = 0; 130*4887Schin break; 131*4887Schin case SEEK_CUR: 132*4887Schin here = su->here; 133*4887Schin break; 134*4887Schin case SEEK_END: 135*4887Schin if(su->extent >= 0) 136*4887Schin here = su->extent; 137*4887Schin else 138*4887Schin { parent = sfsk(f,(Sfoff_t)0,SEEK_CUR,disc); 139*4887Schin if((here = sfsk(f,(Sfoff_t)0,SEEK_END,disc)) < 0) 140*4887Schin return -1; 141*4887Schin else here -= su->offset; 142*4887Schin sfsk(f,parent,SEEK_SET,disc); 143*4887Schin } 144*4887Schin break; 145*4887Schin default: 146*4887Schin return -1; 147*4887Schin } 148*4887Schin 149*4887Schin pos += here; 150*4887Schin if(pos < 0 || (su->extent >= 0 && pos >= su->extent)) 151*4887Schin return -1; 152*4887Schin 153*4887Schin return (su->here = pos); 154*4887Schin } 155*4887Schin 156*4887Schin #if __STD_C 157*4887Schin static int streamexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) 158*4887Schin #else 159*4887Schin static int streamexcept(f, type, data, disc) 160*4887Schin Sfio_t* f; 161*4887Schin int type; 162*4887Schin Void_t* data; 163*4887Schin Sfdisc_t* disc; 164*4887Schin #endif 165*4887Schin { 166*4887Schin if(type == SF_FINAL || type == SF_DPOP) 167*4887Schin free(disc); 168*4887Schin return 0; 169*4887Schin } 170*4887Schin 171*4887Schin #if __STD_C 172*4887Schin Sfio_t* sfdcsubstream(Sfio_t* f, Sfio_t* parent, Sfoff_t offset, Sfoff_t extent) 173*4887Schin #else 174*4887Schin Sfio_t* sfdcsubstream(f, parent, offset, extent) 175*4887Schin Sfio_t* f; /* stream */ 176*4887Schin Sfio_t* parent; /* parent stream */ 177*4887Schin Sfoff_t offset; /* offset in f */ 178*4887Schin Sfoff_t extent; /* desired size */ 179*4887Schin #endif 180*4887Schin { 181*4887Schin reg Sfio_t* sp; 182*4887Schin reg Subfile_t* su; 183*4887Schin reg Sfoff_t here; 184*4887Schin 185*4887Schin /* establish that we can seek to offset */ 186*4887Schin if((here = sfseek(parent,(Sfoff_t)0,SEEK_CUR)) < 0 || sfseek(parent,offset,SEEK_SET) < 0) 187*4887Schin return 0; 188*4887Schin else sfseek(parent,here,SEEK_SET); 189*4887Schin sfpurge(parent); 190*4887Schin 191*4887Schin if (!(sp = f) && !(sp = sfnew(NIL(Sfio_t*), NIL(Void_t*), (size_t)SF_UNBOUND, dup(sffileno(parent)), parent->flags))) 192*4887Schin return 0; 193*4887Schin 194*4887Schin if(!(su = (Subfile_t*)malloc(sizeof(Subfile_t)))) 195*4887Schin { if(sp != f) 196*4887Schin sfclose(sp); 197*4887Schin return 0; 198*4887Schin } 199*4887Schin memset(su, 0, sizeof(*su)); 200*4887Schin 201*4887Schin su->disc.readf = streamread; 202*4887Schin su->disc.writef = streamwrite; 203*4887Schin su->disc.seekf = streamseek; 204*4887Schin su->disc.exceptf = streamexcept; 205*4887Schin su->parent = parent; 206*4887Schin su->offset = offset; 207*4887Schin su->extent = extent; 208*4887Schin 209*4887Schin if(sfdisc(sp, (Sfdisc_t*)su) != (Sfdisc_t*)su) 210*4887Schin { free(su); 211*4887Schin if(sp != f) 212*4887Schin sfclose(sp); 213*4887Schin return 0; 214*4887Schin } 215*4887Schin 216*4887Schin return sp; 217*4887Schin } 218