1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1992-2011 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                  Common Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*            http://www.opensource.org/licenses/cpl1.0.txt             *
11*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                 Glenn Fowler <gsf@research.att.com>                  *
18*                  David Korn <dgk@research.att.com>                   *
19*                                                                      *
20***********************************************************************/
21#pragma prototyped
22/*
23 * common support for tail and rev
24 */
25
26#include	<cmd.h>
27#include	<rev.h>
28
29#define BUFSIZE			SF_BUFSIZE
30#define rounddown(n,size)	(((n)-1)&~((size)-1))
31
32/*
33 * copy the lines starting at offset <start> from in <in> to <out>
34 * in reverse order
35 */
36int rev_line(Sfio_t *in, Sfio_t *out, off_t start)
37{
38	register char *cp, *cpold;
39	register int n, nleft=0;
40	char buff[BUFSIZE];
41	off_t offset;
42	if(sfseek(in,(off_t)0,SEEK_CUR) < 0)
43	{
44		Sfio_t *tmp = sftmp(4*SF_BUFSIZE);
45		if(!tmp)
46			return(-1);
47		if(start>0 && sfmove(in, (Sfio_t*)0, start, -1) != start)
48			return(-1);
49		if(sfmove(in, tmp, SF_UNBOUND, -1) < 0 || !sfeof(in) || sferror(tmp))
50			return(-1);
51		in = tmp;
52		start=0;
53	}
54	if((offset = sfseek(in,(off_t)0,SEEK_END)) <= start)
55		return(0);
56	offset = rounddown(offset,BUFSIZE);
57	while(1)
58	{
59		n = BUFSIZE;
60		if(offset < start)
61		{
62			n -= (start-offset);
63			offset = start;
64		}
65		sfseek(in, offset, SEEK_SET);
66		if((n=sfread(in, buff, n)) <=0)
67			break;
68		cp = buff+n;
69		n = *buff;
70		*buff = '\n';
71		while(1)
72		{
73			cpold = cp;
74			if(nleft==0)
75				cp--;
76			if(cp==buff)
77			{
78				nleft= 1;
79				break;
80			}
81			while(*--cp != '\n');
82			if(cp==buff && n!='\n')
83			{
84				*cp = n;
85				nleft += cpold-cp;
86				break;
87			}
88			else
89				cp++;
90			if(sfwrite(out,cp,cpold-cp) < 0)
91				return(-1);
92			if(nleft)
93			{
94				if(nleft==1)
95					sfputc(out,'\n');
96				else if(sfmove(in,out,nleft,-1) != nleft)
97					return(-1);
98				nleft = 0;
99			}
100		}
101		if(offset <= start)
102			break;
103		offset -= BUFSIZE;
104	}
105	if(nleft)
106	{
107		sfseek(in, start, SEEK_SET);
108		if(sfmove(in,out,nleft,-1) != nleft)
109			return(-1);
110	}
111	return(0);
112}
113