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 /* Discipline to turn \r\n into \n. 25*4887Schin ** This is useful to deal with DOS text files. 26*4887Schin ** 27*4887Schin ** Written by David Korn (03/18/1998). 28*4887Schin */ 29*4887Schin 30*4887Schin #define MINMAP 8 31*4887Schin #define CHUNK 1024 32*4887Schin 33*4887Schin struct map 34*4887Schin { 35*4887Schin Sfoff_t logical; 36*4887Schin Sfoff_t physical; 37*4887Schin }; 38*4887Schin 39*4887Schin typedef struct _dosdisc 40*4887Schin { 41*4887Schin Sfdisc_t disc; 42*4887Schin struct map *maptable; 43*4887Schin int mapsize; 44*4887Schin int maptop; 45*4887Schin Sfoff_t lhere; 46*4887Schin Sfoff_t llast; 47*4887Schin Sfoff_t lmax; 48*4887Schin Sfoff_t pmax; 49*4887Schin Sfoff_t phere; 50*4887Schin Sfoff_t plast; 51*4887Schin Sfoff_t begin; 52*4887Schin int skip; 53*4887Schin void *buff; 54*4887Schin char last; 55*4887Schin char extra; 56*4887Schin int bsize; 57*4887Schin } Dosdisc_t; 58*4887Schin 59*4887Schin #if __STD_C 60*4887Schin static void addmapping(register Dosdisc_t *dp) 61*4887Schin #else 62*4887Schin static void addmapping(dp) 63*4887Schin register Dosdisc_t *dp; 64*4887Schin #endif 65*4887Schin { 66*4887Schin register int n; 67*4887Schin if((n=dp->maptop++)>=dp->mapsize) 68*4887Schin { 69*4887Schin dp->mapsize *= 2; 70*4887Schin if(!(dp->maptable=(struct map*)realloc((void*)dp->maptable,(dp->mapsize+1)*sizeof(struct map)))) 71*4887Schin { 72*4887Schin dp->maptop--; 73*4887Schin dp->mapsize *= 2; 74*4887Schin return; 75*4887Schin } 76*4887Schin } 77*4887Schin dp->maptable[n].physical = dp->phere; 78*4887Schin dp->maptable[n].logical = dp->lhere; 79*4887Schin dp->maptable[dp->maptop].logical=0; 80*4887Schin } 81*4887Schin 82*4887Schin #if __STD_C 83*4887Schin static struct map *getmapping(Dosdisc_t *dp, Sfoff_t offset, register int whence) 84*4887Schin #else 85*4887Schin static struct map *getmapping(dp, offset, whence) 86*4887Schin Dosdisc_t *dp; 87*4887Schin Sfoff_t offset; 88*4887Schin register int whence; 89*4887Schin #endif 90*4887Schin { 91*4887Schin register struct map *mp; 92*4887Schin static struct map dummy; 93*4887Schin if(offset <= dp->begin) 94*4887Schin { 95*4887Schin dummy.logical = dummy.physical = offset; 96*4887Schin return(&dummy); 97*4887Schin } 98*4887Schin if(!(mp=dp->maptable)) 99*4887Schin { 100*4887Schin dummy.logical = dp->begin; 101*4887Schin dummy.physical = dummy.logical+1; 102*4887Schin return(&dummy); 103*4887Schin } 104*4887Schin while((++mp)->logical && (whence==SEEK_CUR?mp->physical:mp->logical) <= offset); 105*4887Schin return(mp-1); 106*4887Schin } 107*4887Schin 108*4887Schin #if __STD_C 109*4887Schin static ssize_t dos_read(Sfio_t *iop, void *buff, size_t size, Sfdisc_t* disc) 110*4887Schin #else 111*4887Schin static ssize_t dos_read(iop, buff, size, disc) 112*4887Schin Sfio_t *iop; 113*4887Schin void *buff; 114*4887Schin size_t size; 115*4887Schin Sfdisc_t* disc; 116*4887Schin #endif 117*4887Schin { 118*4887Schin register Dosdisc_t *dp = (Dosdisc_t*)disc; 119*4887Schin register char *cp = (char*)buff, *first, *cpmax; 120*4887Schin register int n, count, m; 121*4887Schin if(dp->extra) 122*4887Schin { 123*4887Schin dp->extra=0; 124*4887Schin *cp = dp->last; 125*4887Schin return(1); 126*4887Schin } 127*4887Schin while(1) 128*4887Schin { 129*4887Schin if((n = sfrd(iop,buff,size,disc)) <= 0) 130*4887Schin return(n); 131*4887Schin dp->plast=dp->phere; 132*4887Schin dp->phere +=n; 133*4887Schin dp->llast = dp->lhere; 134*4887Schin cpmax = cp+n-1; 135*4887Schin if(dp->last=='\r' && *cp!='\n') 136*4887Schin { 137*4887Schin /* should insert a '\r' */ ; 138*4887Schin } 139*4887Schin dp->last = *cpmax; 140*4887Schin if(n>1) 141*4887Schin break; 142*4887Schin if(dp->last!='\r') 143*4887Schin { 144*4887Schin dp->lhere++; 145*4887Schin return(1); 146*4887Schin } 147*4887Schin } 148*4887Schin if(dp->last=='\r') 149*4887Schin n--; 150*4887Schin else if(dp->last!='\n' || cpmax[-1]!='\r') 151*4887Schin *cpmax = '\r'; 152*4887Schin dp->lhere += n; 153*4887Schin while(1) 154*4887Schin { 155*4887Schin while(*cp++ != '\r'); 156*4887Schin if(cp > cpmax || *cp=='\n') 157*4887Schin break; 158*4887Schin } 159*4887Schin dp->skip = cp-1 - (char*)buff; 160*4887Schin /* if not \r\n in buffer, just return */ 161*4887Schin if((count = cpmax+1-cp) <=0) 162*4887Schin { 163*4887Schin *cpmax = dp->last; 164*4887Schin if(!dp->maptable) 165*4887Schin dp->begin +=n; 166*4887Schin dp->skip++; 167*4887Schin count=0; 168*4887Schin goto done; 169*4887Schin } 170*4887Schin if(!dp->maptable) 171*4887Schin { 172*4887Schin dp->begin += cp - (char*)buff-1; 173*4887Schin if(dp->maptable=(struct map*)malloc((MINMAP+1)*sizeof(struct map))) 174*4887Schin { 175*4887Schin dp->mapsize = MINMAP; 176*4887Schin dp->maptable[0].logical= dp->begin; 177*4887Schin dp->maptable[0].physical = dp->maptable[0].logical+1; 178*4887Schin dp->maptable[1].logical=0; 179*4887Schin dp->maptop = 1; 180*4887Schin } 181*4887Schin } 182*4887Schin /* save original discipline inside buffer */ 183*4887Schin if(count>dp->bsize) 184*4887Schin { 185*4887Schin if(dp->bsize==0) 186*4887Schin dp->buff = malloc(count); 187*4887Schin else 188*4887Schin dp->buff = realloc(dp->buff,count); 189*4887Schin dp->bsize = count; 190*4887Schin if(!dp->buff) 191*4887Schin return(-1); 192*4887Schin } 193*4887Schin memcpy(dp->buff, cp, count); 194*4887Schin count=1; 195*4887Schin while(1) 196*4887Schin { 197*4887Schin first=cp; 198*4887Schin if(cp==cpmax) 199*4887Schin cp++; 200*4887Schin else 201*4887Schin while(*cp++ != '\r'); 202*4887Schin if(cp<=cpmax && *cp!='\n') 203*4887Schin continue; 204*4887Schin if((m=(cp-first)-1) >0) 205*4887Schin memcpy(first-count, first, m); 206*4887Schin if(cp > cpmax) 207*4887Schin break; 208*4887Schin count++; 209*4887Schin } 210*4887Schin cpmax[-count] = dp->last; 211*4887Schin dp->lhere -= count; 212*4887Schin done: 213*4887Schin if(dp->lhere>dp->lmax) 214*4887Schin { 215*4887Schin dp->lmax = dp->lhere; 216*4887Schin dp->pmax = dp->phere; 217*4887Schin if(dp->maptable && dp->lmax > dp->maptable[dp->maptop-1].logical+CHUNK) 218*4887Schin addmapping(dp); 219*4887Schin } 220*4887Schin return(n-count); 221*4887Schin } 222*4887Schin 223*4887Schin /* 224*4887Schin * returns the current offset 225*4887Schin * <offset> must be in the current buffer 226*4887Schin * if <whence> is SEEK_CUR, physical offset converted to logical offset 227*4887Schin * otherwise, logical offset is converted to physical offset 228*4887Schin */ 229*4887Schin #if __STD_C 230*4887Schin static Sfoff_t cur_offset(Dosdisc_t *dp, Sfoff_t offset,Sfio_t *iop,register int whence) 231*4887Schin #else 232*4887Schin static Sfoff_t cur_offset(dp, offset, iop, whence) 233*4887Schin Dosdisc_t *dp; 234*4887Schin Sfoff_t offset; 235*4887Schin Sfio_t *iop; 236*4887Schin register int whence; 237*4887Schin #endif 238*4887Schin { 239*4887Schin register Sfoff_t n,m=0; 240*4887Schin register char *cp; 241*4887Schin 242*4887Schin if(whence==SEEK_CUR) 243*4887Schin { 244*4887Schin whence= -1; 245*4887Schin n = offset - dp->plast; 246*4887Schin iop->next = iop->data + n; 247*4887Schin offset = dp->llast; 248*4887Schin } 249*4887Schin else 250*4887Schin { 251*4887Schin whence = 1; 252*4887Schin n = offset - dp->llast; 253*4887Schin offset = dp->plast; 254*4887Schin } 255*4887Schin offset +=n; 256*4887Schin if((n -= dp->skip) > 0) 257*4887Schin { 258*4887Schin m=whence; 259*4887Schin cp = (char*)dp->buff; 260*4887Schin while(n--) 261*4887Schin { 262*4887Schin if(*cp++=='\r' && *cp=='\n') 263*4887Schin { 264*4887Schin m += whence; 265*4887Schin if(whence>0) 266*4887Schin n++; 267*4887Schin } 268*4887Schin } 269*4887Schin } 270*4887Schin if(whence<0) 271*4887Schin iop->next += m; 272*4887Schin return(offset+m); 273*4887Schin } 274*4887Schin 275*4887Schin #if __STD_C 276*4887Schin static Sfoff_t dos_seek(Sfio_t *iop, Sfoff_t offset, register int whence, Sfdisc_t* disc) 277*4887Schin #else 278*4887Schin static Sfoff_t dos_seek(iop, offset, whence, disc) 279*4887Schin Sfio_t *iop; 280*4887Schin Sfoff_t offset; 281*4887Schin register int whence; 282*4887Schin Sfdisc_t* disc; 283*4887Schin #endif 284*4887Schin { 285*4887Schin register Dosdisc_t *dp = (Dosdisc_t*)disc; 286*4887Schin struct map dummy, *mp=0; 287*4887Schin Sfoff_t physical; 288*4887Schin register int n,size; 289*4887Schin retry: 290*4887Schin switch(whence) 291*4887Schin { 292*4887Schin case SEEK_CUR: 293*4887Schin offset = sfsk(iop, (Sfoff_t)0,SEEK_CUR,disc); 294*4887Schin if(offset<=dp->begin) 295*4887Schin return(offset); 296*4887Schin /* check for seek outside buffer */ 297*4887Schin if(offset==dp->phere) 298*4887Schin return(dp->lhere); 299*4887Schin else if(offset==dp->plast) 300*4887Schin return(dp->llast); 301*4887Schin else if(offset<dp->plast || offset>dp->phere) 302*4887Schin mp = getmapping(dp,offset,whence); 303*4887Schin break; 304*4887Schin case SEEK_SET: 305*4887Schin /* check for seek outside buffer */ 306*4887Schin if(offset<dp->llast || offset > dp->lhere) 307*4887Schin mp = getmapping(dp,offset,whence); 308*4887Schin break; 309*4887Schin case SEEK_END: 310*4887Schin if(!dp->maptable) 311*4887Schin return(sfsk(iop,offset,SEEK_END,disc)); 312*4887Schin mp = &dummy; 313*4887Schin mp->physical = dp->plast; 314*4887Schin mp->logical = dp->llast; 315*4887Schin break; 316*4887Schin } 317*4887Schin if(sfsetbuf(iop,(char*)iop,0)) 318*4887Schin size = sfvalue(iop); 319*4887Schin else 320*4887Schin size = iop->endb-iop->data; 321*4887Schin if(mp) 322*4887Schin { 323*4887Schin sfsk(iop,mp->physical,SEEK_SET,disc); 324*4887Schin dp->phere = mp->physical; 325*4887Schin dp->lhere = mp->logical; 326*4887Schin if((*disc->readf)(iop,iop->data,size,disc)<0) 327*4887Schin return(-1); 328*4887Schin } 329*4887Schin while(1) 330*4887Schin { 331*4887Schin if(whence==SEEK_CUR && dp->phere>=offset) 332*4887Schin break; 333*4887Schin if(whence==SEEK_SET && dp->lhere>=offset) 334*4887Schin break; 335*4887Schin n=(*disc->readf)(iop,iop->data,size,disc); 336*4887Schin if(n < 0) 337*4887Schin return(-1); 338*4887Schin if(n==0) 339*4887Schin { 340*4887Schin if(whence==SEEK_END && offset<0) 341*4887Schin { 342*4887Schin offset = dp->lhere; 343*4887Schin whence=SEEK_SET; 344*4887Schin goto retry; 345*4887Schin } 346*4887Schin break; 347*4887Schin } 348*4887Schin } 349*4887Schin if(whence==SEEK_END) 350*4887Schin offset += dp->lhere; 351*4887Schin else 352*4887Schin { 353*4887Schin physical = cur_offset(dp,offset,iop,whence); 354*4887Schin if(whence==SEEK_SET) 355*4887Schin { 356*4887Schin sfsk(iop, physical ,SEEK_SET,disc); 357*4887Schin dp->phere = physical; 358*4887Schin dp->lhere = offset; 359*4887Schin } 360*4887Schin else 361*4887Schin offset = physical; 362*4887Schin } 363*4887Schin return(offset); 364*4887Schin } 365*4887Schin 366*4887Schin #if __STD_C 367*4887Schin static int dos_except(Sfio_t *iop, int type, void *arg, Sfdisc_t *disc) 368*4887Schin #else 369*4887Schin static int dos_except(iop, type, arg, disc) 370*4887Schin Sfio_t *iop; 371*4887Schin int type; 372*4887Schin void *arg; 373*4887Schin Sfdisc_t *disc; 374*4887Schin #endif 375*4887Schin { 376*4887Schin register Dosdisc_t *dp = (Dosdisc_t*)disc; 377*4887Schin if(type==SF_DPOP || type==SF_FINAL) 378*4887Schin { 379*4887Schin if(dp->bsize>0) 380*4887Schin free((void*)dp->buff); 381*4887Schin if(dp->mapsize) 382*4887Schin free((void*)dp->maptable); 383*4887Schin free((void*)disc); 384*4887Schin } 385*4887Schin return(0); 386*4887Schin } 387*4887Schin 388*4887Schin #if __STD_C 389*4887Schin int sfdcdos(Sfio_t *f) 390*4887Schin #else 391*4887Schin int sfdcdos(f) 392*4887Schin Sfio_t *f; 393*4887Schin #endif 394*4887Schin { 395*4887Schin Dosdisc_t *dos; 396*4887Schin 397*4887Schin /* this is a readonly discipline */ 398*4887Schin if(sfset(f,0,0)&SF_WRITE) 399*4887Schin return(-1); 400*4887Schin 401*4887Schin if(!(dos = (Dosdisc_t*)malloc(sizeof(Dosdisc_t))) ) 402*4887Schin return -1; 403*4887Schin memset(dos,'\0',sizeof(Dosdisc_t)); 404*4887Schin 405*4887Schin dos->disc.readf = dos_read; 406*4887Schin dos->disc.writef = NIL(Sfwrite_f); 407*4887Schin dos->disc.seekf = dos_seek; 408*4887Schin dos->disc.exceptf = dos_except; 409*4887Schin 410*4887Schin if(sfdisc(f,(Sfdisc_t*)dos) != (Sfdisc_t*)dos) 411*4887Schin { free(dos); 412*4887Schin return -1; 413*4887Schin } 414*4887Schin 415*4887Schin return(0); 416*4887Schin } 417