1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1992-2010 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 */
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