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