/* * zlog.c * * Logs empaquetados y comprimidos * * Historia: * 17/11/2015 Creacion. * 03/12/2015 Primera version completamente funcional [v1.0]. * 04/12/2015 Aniado zlog_vprintf() [v1.1] * 11/12/2014 Corrijo el codificado del segmento 1 [v1.2] * 14/12/2014 Aniado const a los printfs, arreglo modo de apertura [v1.3] * * Autor: Dario Rodriguez dario@softhome.net * (c) 2015 SICOSOFT */ #include #include #include #include #include #include #include #include #include "zlog.h" #define MAXTMPBUF 4096 /*#define LOWLEVELDEBUG */ typedef struct { int fd; } _zlog_data; static int zlog_pack(char *inbuf, int inbufsize, char *outbuf, int outbufsize, int *nprocessed); /* cuerpo funciones exportadas */ zlog_data * zlog_init(char *logfile) { _zlog_data *zlog; if((zlog=malloc(sizeof(_zlog_data)))==NULL) return(NULL); memset(zlog,0,sizeof(zlog)); zlog->fd=open(logfile,O_WRONLY|O_APPEND|O_CREAT,0644); if(zlog->fd==-1) { free(zlog),zlog=NULL; return(NULL); } return((zlog_data *)zlog); } void zlog_fini(zlog_data *zlogparam) { _zlog_data *zlog=(_zlog_data *)zlogparam; if(zlog==NULL) return; if(zlog->fd!=-1) close(zlog->fd),zlog->fd=-1; free(zlog),zlog=NULL; return; } int zlog_printf(zlog_data *zlogparam, const char *format,...) { int res; va_list lista; va_start(lista,format); res=zlog_vprintf(zlogparam,format,lista); va_end(lista); return(res); } int zlog_vprintf(zlog_data *zlogparam, const char *format, va_list lista) { _zlog_data *zlog=(_zlog_data *)zlogparam; char tmpbuf[MAXTMPBUF]; char outbuf[MAXTMPBUF]; int tmpused; int nwritten; int outused; int totalprocessed,nprocessed; int totaloutput; if(zlog==NULL || format==NULL) return(-1); tmpused=vsnprintf(tmpbuf,sizeof(tmpbuf),format,lista); if(tmpused<0) return(-1); tmpused=(tmpused>=sizeof(tmpbuf))?(sizeof(tmpbuf)-1):tmpused; tmpbuf[sizeof(tmpbuf)-1]='\0'; totalprocessed=0; totaloutput=0; while(totalprocessedfd,outbuf,outused))!=outused) { return(-1); /* short write */ } totalprocessed+=nprocessed; totaloutput=outused; } return(totaloutput); } /* local functions */ static int strlist(char *str, char **list, int elemsize) { int i; if(str==NULL || list==NULL || elemsize==0) return(-1); for(i=0;list[i]!=NULL;i++) { if(memcmp(str,list[i],4)==0) return(i); } return(-1); } static int zlog_pack(char *inbuf, int inbufsize, char *outbuf, int outbufsize, int *nprocessed) { static char encoded[]={"0123456789/ :"}; static char *staticstr[]={"Mon ","Tue ","Wed ","Thu ","Fri ","Sat ","Sun ","Jan ","Feb ","Mar ","Apr ","May ","Jun ","Jul ","Aug ","Sep ","Oct ","Nov ","Dec ",NULL}; int ooff,coff,csize; char seg1data[256*2]; char seg2data[256*3]; char seg3data[256]; int seg1size; int seg1origsize; int seg2size; int seg2origsize; int seg3size; int seg3origsize; int i,j,k,m; char *ptr; char c,e; int optimali,optimalk,optimalsize; if(inbuf==NULL || inbufsize<0 || outbuf==NULL || outbufsize<(255+5) || nprocessed==NULL) return(-1); for(ooff=0,coff=0,csize=((inbufsize-coff)>255)?255:(inbufsize-coff);csize>0;coff+=csize,csize=((inbufsize-coff)>255)?255:(inbufsize-coff)) { if((ooff+5+csize)>outbufsize) { *nprocessed=coff; return(ooff); } /* encode segment1 */ for(i=0,seg1size=0;i2) { seg1data[seg1size++]=0xe; seg1data[seg1size++]=j-3; i+=j; } } else if(inbuf[coff+i]!='\0' && (i+4)<=csize && (j=strlist(inbuf+coff+i,staticstr,4))!=-1) { if(j<3) { seg1data[seg1size++]=0xe; seg1data[seg1size++]=16-3+j; } else { seg1data[seg1size++]=0xf; seg1data[seg1size++]=j-3; } i+=4; } else break; } seg1origsize=i; if((seg1size%2)==1) seg1data[seg1size++]=0; /* pack segment1 */ for(j=0;(j<<1)='0' && c<='9') || (c>='A' && c<='Z') || (c>='a' && c<='z'))) { e=(c>='a')?c-'a'+1+10+26:(c>='A')?c-'A'+1+10:(c>='0')?c-'0'+1:0; seg2data[seg2size++]=e; i++; } else { seg2data[seg2size++]=0x3f; seg2data[seg2size++]=((j-1)<<2)|((c>>6)&0x3); seg2data[seg2size++]=c&0x3f; i+=j; } k=((seg2size*3)+3)/4; if((k+(csize-i))<(optimalk+(csize-optimali))) { optimalsize=seg2size; optimalk=k; optimali=i; } } i=optimali; seg2size=optimalsize; seg2origsize=i-seg1origsize; while((seg2size%4)!=0) seg2data[seg2size++]=0; /* pack segment2 */ for(j=0,m=0;j>4); seg2data[m+1]=(seg2data[j+1]<<4)|(seg2data[j+2]>>2); seg2data[m+2]=(seg2data[j+2]<<6)|seg2data[j+3]; } seg2size=m; /* encode segment3 */ for(seg3size=0;i>4)&0xf)); } seg3origsize=seg3size; /* validate encoding */ if((seg1size+seg2size+seg3size)>csize) { #ifdef LOWLEVELDEBUG char buf[256]; memcpy(buf,inbuf+coff,csize); buf[csize]='\0'; for(j=0;j'~')?' ':buf[j]; fprintf(stderr,"INTERNAL ERROR: wrong encoding result (%i(%i)+%i(%i)+%i(%i)=%i(%i) > %i), will not encode this block; off=%i, size=%i \"%s\"\n", seg1size,seg1origsize,seg2size,seg2origsize,seg3size,seg3origsize,(seg1size+seg2size+seg3size),seg1origsize+seg2origsize+seg3origsize,csize,coff,csize,buf); #endif seg1size=0; seg2size=0; seg3size=csize; seg1origsize=0; seg2origsize=0; seg3origsize=csize; for(i=0;i>4)&0xf)); } } /* copy result */ outbuf[ooff++]=seg1size+seg2size+seg3size; outbuf[ooff++]=seg1origsize; outbuf[ooff++]=seg2origsize; outbuf[ooff++]=seg3origsize; memcpy(outbuf+ooff,seg1data,seg1size),ooff+=seg1size; memcpy(outbuf+ooff,seg2data,seg2size),ooff+=seg2size; memcpy(outbuf+ooff,seg3data,seg3size),ooff+=seg3size; outbuf[ooff++]=seg1size+seg2size+seg3size; #ifdef LOWLEVELDEBUG { static int bl=-1; unsigned long sum=0; bl++; for(i=0;i0 || usedinbuf>0) { nread=((nread>0)?nread:0); usedinbuf+=nread; for(lstart=inbuf,len=0;;lstart=lstart+len) { if((lend=memchr(lstart,'\n',usedinbuf-(lstart-inbuf)))!=NULL) { len=lend-lstart+1; } else if((usedinbuf-(lstart-inbuf))>255) { lend=lstart+255; len=255; } else if(lstart==inbuf && usedinbuf>0) { lend=lstart+usedinbuf; len=usedinbuf; } else break; while(len>0) { if((usedoutbuf=zlog_pack(lstart,len,outbuf,sizeof(outbuf),&nprocessed))<=0) { fprintf(stderr,"INTERNAL ERROR: problem codifying stream at byte %li, len %i\n",nbyte,(lend-lstart)+1); break; /* error codifying stream */ } if(write(out,outbuf,usedoutbuf)!=usedoutbuf) { fprintf(stderr,"INTERNAL ERROR: short write at byte %li, len %i\n",nbyte,(lend-lstart)+1); break; /* short write */ } nbyte+=nprocessed; lstart+=nprocessed; len-=nprocessed; } } memmove(inbuf,lstart,usedinbuf-(lstart-inbuf)); usedinbuf-=(lstart-inbuf); } /* finished successfully */ close(out); close(in); return(0); } #endif