xref: /onnv-gate/usr/src/lib/libast/common/disc/sfdcdos.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.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
addmapping(register Dosdisc_t * dp)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
getmapping(Dosdisc_t * dp,Sfoff_t offset,register int whence)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
dos_read(Sfio_t * iop,void * buff,size_t size,Sfdisc_t * disc)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
cur_offset(Dosdisc_t * dp,Sfoff_t offset,Sfio_t * iop,register int whence)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
dos_seek(Sfio_t * iop,Sfoff_t offset,register int whence,Sfdisc_t * disc)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
dos_except(Sfio_t * iop,int type,void * arg,Sfdisc_t * disc)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
sfdcdos(Sfio_t * f)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