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 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
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  */
rev_line(Sfio_t * in,Sfio_t * out,off_t start)36 int 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