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