14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1985-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin #include "sfdchdr.h" 234887Schin 244887Schin /* Discipline to turn \r\n into \n. 254887Schin ** This is useful to deal with DOS text files. 264887Schin ** 274887Schin ** Written by David Korn (03/18/1998). 284887Schin */ 294887Schin 304887Schin #define MINMAP 8 314887Schin #define CHUNK 1024 324887Schin 334887Schin struct map 344887Schin { 354887Schin Sfoff_t logical; 364887Schin Sfoff_t physical; 374887Schin }; 384887Schin 394887Schin typedef struct _dosdisc 404887Schin { 414887Schin Sfdisc_t disc; 424887Schin struct map *maptable; 434887Schin int mapsize; 444887Schin int maptop; 454887Schin Sfoff_t lhere; 464887Schin Sfoff_t llast; 474887Schin Sfoff_t lmax; 484887Schin Sfoff_t pmax; 494887Schin Sfoff_t phere; 504887Schin Sfoff_t plast; 514887Schin Sfoff_t begin; 524887Schin int skip; 534887Schin void *buff; 544887Schin char last; 554887Schin char extra; 564887Schin int bsize; 574887Schin } Dosdisc_t; 584887Schin 594887Schin #if __STD_C 604887Schin static void addmapping(register Dosdisc_t *dp) 614887Schin #else 624887Schin static void addmapping(dp) 634887Schin register Dosdisc_t *dp; 644887Schin #endif 654887Schin { 664887Schin register int n; 674887Schin if((n=dp->maptop++)>=dp->mapsize) 684887Schin { 694887Schin dp->mapsize *= 2; 704887Schin if(!(dp->maptable=(struct map*)realloc((void*)dp->maptable,(dp->mapsize+1)*sizeof(struct map)))) 714887Schin { 724887Schin dp->maptop--; 734887Schin dp->mapsize *= 2; 744887Schin return; 754887Schin } 764887Schin } 774887Schin dp->maptable[n].physical = dp->phere; 784887Schin dp->maptable[n].logical = dp->lhere; 794887Schin dp->maptable[dp->maptop].logical=0; 804887Schin } 814887Schin 824887Schin #if __STD_C 834887Schin static struct map *getmapping(Dosdisc_t *dp, Sfoff_t offset, register int whence) 844887Schin #else 854887Schin static struct map *getmapping(dp, offset, whence) 864887Schin Dosdisc_t *dp; 874887Schin Sfoff_t offset; 884887Schin register int whence; 894887Schin #endif 904887Schin { 914887Schin register struct map *mp; 924887Schin static struct map dummy; 934887Schin if(offset <= dp->begin) 944887Schin { 954887Schin dummy.logical = dummy.physical = offset; 964887Schin return(&dummy); 974887Schin } 984887Schin if(!(mp=dp->maptable)) 994887Schin { 1004887Schin dummy.logical = dp->begin; 1014887Schin dummy.physical = dummy.logical+1; 1024887Schin return(&dummy); 1034887Schin } 1044887Schin while((++mp)->logical && (whence==SEEK_CUR?mp->physical:mp->logical) <= offset); 1054887Schin return(mp-1); 1064887Schin } 1074887Schin 1084887Schin #if __STD_C 1094887Schin static ssize_t dos_read(Sfio_t *iop, void *buff, size_t size, Sfdisc_t* disc) 1104887Schin #else 1114887Schin static ssize_t dos_read(iop, buff, size, disc) 1124887Schin Sfio_t *iop; 1134887Schin void *buff; 1144887Schin size_t size; 1154887Schin Sfdisc_t* disc; 1164887Schin #endif 1174887Schin { 1184887Schin register Dosdisc_t *dp = (Dosdisc_t*)disc; 1194887Schin register char *cp = (char*)buff, *first, *cpmax; 1204887Schin register int n, count, m; 1214887Schin if(dp->extra) 1224887Schin { 1234887Schin dp->extra=0; 1244887Schin *cp = dp->last; 1254887Schin return(1); 1264887Schin } 1274887Schin while(1) 1284887Schin { 1294887Schin if((n = sfrd(iop,buff,size,disc)) <= 0) 1304887Schin return(n); 1314887Schin dp->plast=dp->phere; 1324887Schin dp->phere +=n; 1334887Schin dp->llast = dp->lhere; 1344887Schin cpmax = cp+n-1; 1354887Schin if(dp->last=='\r' && *cp!='\n') 1364887Schin { 1374887Schin /* should insert a '\r' */ ; 1384887Schin } 1394887Schin dp->last = *cpmax; 1404887Schin if(n>1) 1414887Schin break; 1424887Schin if(dp->last!='\r') 1434887Schin { 1444887Schin dp->lhere++; 1454887Schin return(1); 1464887Schin } 1474887Schin } 1484887Schin if(dp->last=='\r') 1494887Schin n--; 1504887Schin else if(dp->last!='\n' || cpmax[-1]!='\r') 1514887Schin *cpmax = '\r'; 1524887Schin dp->lhere += n; 1534887Schin while(1) 1544887Schin { 1554887Schin while(*cp++ != '\r'); 1564887Schin if(cp > cpmax || *cp=='\n') 1574887Schin break; 1584887Schin } 1594887Schin dp->skip = cp-1 - (char*)buff; 1604887Schin /* if not \r\n in buffer, just return */ 1614887Schin if((count = cpmax+1-cp) <=0) 1624887Schin { 1634887Schin *cpmax = dp->last; 1644887Schin if(!dp->maptable) 1654887Schin dp->begin +=n; 1664887Schin dp->skip++; 1674887Schin count=0; 1684887Schin goto done; 1694887Schin } 1704887Schin if(!dp->maptable) 1714887Schin { 1724887Schin dp->begin += cp - (char*)buff-1; 1734887Schin if(dp->maptable=(struct map*)malloc((MINMAP+1)*sizeof(struct map))) 1744887Schin { 1754887Schin dp->mapsize = MINMAP; 1764887Schin dp->maptable[0].logical= dp->begin; 1774887Schin dp->maptable[0].physical = dp->maptable[0].logical+1; 1784887Schin dp->maptable[1].logical=0; 1794887Schin dp->maptop = 1; 1804887Schin } 1814887Schin } 1824887Schin /* save original discipline inside buffer */ 1834887Schin if(count>dp->bsize) 1844887Schin { 1854887Schin if(dp->bsize==0) 1864887Schin dp->buff = malloc(count); 1874887Schin else 1884887Schin dp->buff = realloc(dp->buff,count); 1894887Schin dp->bsize = count; 1904887Schin if(!dp->buff) 1914887Schin return(-1); 1924887Schin } 1934887Schin memcpy(dp->buff, cp, count); 1944887Schin count=1; 1954887Schin while(1) 1964887Schin { 1974887Schin first=cp; 1984887Schin if(cp==cpmax) 1994887Schin cp++; 2004887Schin else 2014887Schin while(*cp++ != '\r'); 2024887Schin if(cp<=cpmax && *cp!='\n') 2034887Schin continue; 2044887Schin if((m=(cp-first)-1) >0) 2054887Schin memcpy(first-count, first, m); 2064887Schin if(cp > cpmax) 2074887Schin break; 2084887Schin count++; 2094887Schin } 2104887Schin cpmax[-count] = dp->last; 2114887Schin dp->lhere -= count; 2124887Schin done: 2134887Schin if(dp->lhere>dp->lmax) 2144887Schin { 2154887Schin dp->lmax = dp->lhere; 2164887Schin dp->pmax = dp->phere; 2174887Schin if(dp->maptable && dp->lmax > dp->maptable[dp->maptop-1].logical+CHUNK) 2184887Schin addmapping(dp); 2194887Schin } 2204887Schin return(n-count); 2214887Schin } 2224887Schin 2234887Schin /* 2244887Schin * returns the current offset 2254887Schin * <offset> must be in the current buffer 2264887Schin * if <whence> is SEEK_CUR, physical offset converted to logical offset 2274887Schin * otherwise, logical offset is converted to physical offset 2284887Schin */ 2294887Schin #if __STD_C 2304887Schin static Sfoff_t cur_offset(Dosdisc_t *dp, Sfoff_t offset,Sfio_t *iop,register int whence) 2314887Schin #else 2324887Schin static Sfoff_t cur_offset(dp, offset, iop, whence) 2334887Schin Dosdisc_t *dp; 2344887Schin Sfoff_t offset; 2354887Schin Sfio_t *iop; 2364887Schin register int whence; 2374887Schin #endif 2384887Schin { 2394887Schin register Sfoff_t n,m=0; 2404887Schin register char *cp; 2414887Schin 2424887Schin if(whence==SEEK_CUR) 2434887Schin { 2444887Schin whence= -1; 2454887Schin n = offset - dp->plast; 2464887Schin iop->next = iop->data + n; 2474887Schin offset = dp->llast; 2484887Schin } 2494887Schin else 2504887Schin { 2514887Schin whence = 1; 2524887Schin n = offset - dp->llast; 2534887Schin offset = dp->plast; 2544887Schin } 2554887Schin offset +=n; 2564887Schin if((n -= dp->skip) > 0) 2574887Schin { 2584887Schin m=whence; 2594887Schin cp = (char*)dp->buff; 2604887Schin while(n--) 2614887Schin { 2624887Schin if(*cp++=='\r' && *cp=='\n') 2634887Schin { 2644887Schin m += whence; 2654887Schin if(whence>0) 2664887Schin n++; 2674887Schin } 2684887Schin } 2694887Schin } 2704887Schin if(whence<0) 2714887Schin iop->next += m; 2724887Schin return(offset+m); 2734887Schin } 2744887Schin 2754887Schin #if __STD_C 2764887Schin static Sfoff_t dos_seek(Sfio_t *iop, Sfoff_t offset, register int whence, Sfdisc_t* disc) 2774887Schin #else 2784887Schin static Sfoff_t dos_seek(iop, offset, whence, disc) 2794887Schin Sfio_t *iop; 2804887Schin Sfoff_t offset; 2814887Schin register int whence; 2824887Schin Sfdisc_t* disc; 2834887Schin #endif 2844887Schin { 2854887Schin register Dosdisc_t *dp = (Dosdisc_t*)disc; 2864887Schin struct map dummy, *mp=0; 2874887Schin Sfoff_t physical; 2884887Schin register int n,size; 2894887Schin retry: 2904887Schin switch(whence) 2914887Schin { 2924887Schin case SEEK_CUR: 2934887Schin offset = sfsk(iop, (Sfoff_t)0,SEEK_CUR,disc); 2944887Schin if(offset<=dp->begin) 2954887Schin return(offset); 2964887Schin /* check for seek outside buffer */ 2974887Schin if(offset==dp->phere) 2984887Schin return(dp->lhere); 2994887Schin else if(offset==dp->plast) 3004887Schin return(dp->llast); 3014887Schin else if(offset<dp->plast || offset>dp->phere) 3024887Schin mp = getmapping(dp,offset,whence); 3034887Schin break; 3044887Schin case SEEK_SET: 3054887Schin /* check for seek outside buffer */ 3064887Schin if(offset<dp->llast || offset > dp->lhere) 3074887Schin mp = getmapping(dp,offset,whence); 3084887Schin break; 3094887Schin case SEEK_END: 3104887Schin if(!dp->maptable) 3114887Schin return(sfsk(iop,offset,SEEK_END,disc)); 3124887Schin mp = &dummy; 3134887Schin mp->physical = dp->plast; 3144887Schin mp->logical = dp->llast; 3154887Schin break; 3164887Schin } 3174887Schin if(sfsetbuf(iop,(char*)iop,0)) 3184887Schin size = sfvalue(iop); 3194887Schin else 3204887Schin size = iop->endb-iop->data; 3214887Schin if(mp) 3224887Schin { 3234887Schin sfsk(iop,mp->physical,SEEK_SET,disc); 3244887Schin dp->phere = mp->physical; 3254887Schin dp->lhere = mp->logical; 3264887Schin if((*disc->readf)(iop,iop->data,size,disc)<0) 3274887Schin return(-1); 3284887Schin } 3294887Schin while(1) 3304887Schin { 3314887Schin if(whence==SEEK_CUR && dp->phere>=offset) 3324887Schin break; 3334887Schin if(whence==SEEK_SET && dp->lhere>=offset) 3344887Schin break; 3354887Schin n=(*disc->readf)(iop,iop->data,size,disc); 3364887Schin if(n < 0) 3374887Schin return(-1); 3384887Schin if(n==0) 3394887Schin { 3404887Schin if(whence==SEEK_END && offset<0) 3414887Schin { 3424887Schin offset = dp->lhere; 3434887Schin whence=SEEK_SET; 3444887Schin goto retry; 3454887Schin } 3464887Schin break; 3474887Schin } 3484887Schin } 3494887Schin if(whence==SEEK_END) 3504887Schin offset += dp->lhere; 3514887Schin else 3524887Schin { 3534887Schin physical = cur_offset(dp,offset,iop,whence); 3544887Schin if(whence==SEEK_SET) 3554887Schin { 3564887Schin sfsk(iop, physical ,SEEK_SET,disc); 3574887Schin dp->phere = physical; 3584887Schin dp->lhere = offset; 3594887Schin } 3604887Schin else 3614887Schin offset = physical; 3624887Schin } 3634887Schin return(offset); 3644887Schin } 3654887Schin 3664887Schin #if __STD_C 3674887Schin static int dos_except(Sfio_t *iop, int type, void *arg, Sfdisc_t *disc) 3684887Schin #else 3694887Schin static int dos_except(iop, type, arg, disc) 3704887Schin Sfio_t *iop; 3714887Schin int type; 3724887Schin void *arg; 3734887Schin Sfdisc_t *disc; 3744887Schin #endif 3754887Schin { 3764887Schin register Dosdisc_t *dp = (Dosdisc_t*)disc; 3774887Schin if(type==SF_DPOP || type==SF_FINAL) 3784887Schin { 3794887Schin if(dp->bsize>0) 3804887Schin free((void*)dp->buff); 3814887Schin if(dp->mapsize) 3824887Schin free((void*)dp->maptable); 3834887Schin free((void*)disc); 3844887Schin } 3854887Schin return(0); 3864887Schin } 3874887Schin 3884887Schin #if __STD_C 3894887Schin int sfdcdos(Sfio_t *f) 3904887Schin #else 3914887Schin int sfdcdos(f) 3924887Schin Sfio_t *f; 3934887Schin #endif 3944887Schin { 3954887Schin Dosdisc_t *dos; 3964887Schin 3974887Schin /* this is a readonly discipline */ 3984887Schin if(sfset(f,0,0)&SF_WRITE) 3994887Schin return(-1); 4004887Schin 4014887Schin if(!(dos = (Dosdisc_t*)malloc(sizeof(Dosdisc_t))) ) 4024887Schin return -1; 4034887Schin memset(dos,'\0',sizeof(Dosdisc_t)); 4044887Schin 4054887Schin dos->disc.readf = dos_read; 4064887Schin dos->disc.writef = NIL(Sfwrite_f); 4074887Schin dos->disc.seekf = dos_seek; 4084887Schin dos->disc.exceptf = dos_except; 4094887Schin 4104887Schin if(sfdisc(f,(Sfdisc_t*)dos) != (Sfdisc_t*)dos) 4114887Schin { free(dos); 4124887Schin return -1; 4134887Schin } 4144887Schin 4154887Schin return(0); 4164887Schin } 417