"Fossies" - the Fresh Open Source Software Archive

Member "sarg-2.4.0/decomp.c" (30 Jan 2017, 12632 Bytes) of package /linux/privat/sarg-2.4.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "decomp.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.3.11_vs_2.4.0.

    1 /*
    2  * SARG Squid Analysis Report Generator      http://sarg.sourceforge.net
    3  *                                                            1998, 2015
    4  *
    5  * SARG donations:
    6  *      please look at http://sarg.sourceforge.net/donations.php
    7  * Support:
    8  *     http://sourceforge.net/projects/sarg/forums/forum/363374
    9  * ---------------------------------------------------------------------
   10  *
   11  *  This program is free software; you can redistribute it and/or modify
   12  *  it under the terms of the GNU General Public License as published by
   13  *  the Free Software Foundation; either version 2 of the License, or
   14  *  (at your option) any later version.
   15  *
   16  *  This program is distributed in the hope that it will be useful,
   17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19  *  GNU General Public License for more details.
   20  *
   21  *  You should have received a copy of the GNU General Public License
   22  *  along with this program; if not, write to the Free Software
   23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
   24  *
   25  */
   26 
   27 #include "include/conf.h"
   28 #include "include/defs.h"
   29 #ifdef HAVE_ZLIB_H
   30 #include "zlib.h"
   31 #endif
   32 #ifdef HAVE_BZLIB_H
   33 #include "bzlib.h"
   34 #endif
   35 #ifdef HAVE_LZMA_H
   36 #include "lzma.h"
   37 #endif
   38 
   39 #ifdef HAVE_ZLIB_H
   40 /*!
   41  * Read from gzip file.
   42  *
   43  * \param Data The file object.
   44  * \param Buffer The boffer to store the data read.
   45  * \param Size How many bytes to read.
   46  *
   47  * \return The number of bytes read.
   48  */
   49 static int Gzip_Read(void *Data,void *Buffer,int Size)
   50 {
   51     return(gzread((gzFile)Data,Buffer,Size));
   52 }
   53 
   54 /*!
   55  * Check if end of file is reached.
   56  *
   57  * \param Data The file object.
   58  *
   59  * \return \c True if end of file is reached.
   60  */
   61 static int Gzip_Eof(void *Data)
   62 {
   63     return(gzeof((gzFile)Data));
   64 }
   65 
   66 /*!
   67  * Return to the beginnig of the file.
   68  *
   69  * \param Data The file object.
   70  */
   71 static void Gzip_Rewind(void *Data)
   72 {
   73     gzrewind((gzFile)Data);
   74 }
   75 
   76 /*!
   77  * Close the file.
   78  *
   79  * \param Data File to close.
   80  *
   81  * \return 0 on success or -1 on error.
   82  */
   83 static int Gzip_Close(void *Data)
   84 {
   85     int RetCode=-1;
   86     int Status;
   87 
   88     Status=gzclose((gzFile)Data);
   89     switch (Status)
   90     {
   91     case Z_OK:
   92         RetCode=0;
   93         break;
   94     case Z_STREAM_ERROR:
   95         FileObject_SetLastCloseError(_("Invalid gzip file"));
   96         break;
   97     case Z_ERRNO:
   98         FileObject_SetLastCloseError(_("File operation error"));
   99         break;
  100     case Z_MEM_ERROR:
  101         FileObject_SetLastCloseError(_("Not enough memory"));
  102         break;
  103     case Z_BUF_ERROR:
  104         FileObject_SetLastCloseError(_("Truncated gzip stream"));
  105         break;
  106     default:
  107         FileObject_SetLastCloseError(_("Unknown error returned by zlib"));
  108         break;
  109     }
  110     return(RetCode);
  111 }
  112 
  113 /*!
  114  * Open a file object to read from a gzip file.
  115  *
  116  * \return The object to pass to other function in this module.
  117  */
  118 static FileObject *Gzip_Open(int fd)
  119 {
  120     FileObject *File;
  121 
  122     FileObject_SetLastOpenError(NULL);
  123     File=calloc(1,sizeof(*File));
  124     if (!File)
  125     {
  126         FileObject_SetLastOpenError(_("Not enough memory"));
  127         return(NULL);
  128     }
  129     File->Data=gzdopen(fd,"rb");
  130     if (!File->Data)
  131     {
  132         free(File);
  133         FileObject_SetLastOpenError(_("Error opening gzip file"));
  134         return(NULL);
  135     }
  136     File->Read=Gzip_Read;
  137     File->Eof=Gzip_Eof;
  138     File->Rewind=Gzip_Rewind;
  139     File->Close=Gzip_Close;
  140     return(File);
  141 }
  142 #endif
  143 
  144 #ifdef HAVE_BZLIB_H
  145 
  146 struct BzlibInternalFile
  147 {
  148     //! Bzlib object.
  149     BZFILE *BzFile;
  150     //! \c True if end of file is reached.
  151     bool Eof;
  152     //! Original file in case a rewind is necessary.
  153     FILE *File;
  154 };
  155 
  156 /*!
  157  * Read from bzip file.
  158  *
  159  * \param Data The file object.
  160  * \param Buffer The boffer to store the data read.
  161  * \param Size How many bytes to read.
  162  *
  163  * \return The number of bytes read.
  164  */
  165 static int Bzip_Read(void *Data,void *Buffer,int Size)
  166 {
  167     struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
  168     int nread;
  169     int bzerr=BZ_OK;
  170 
  171     if (BData->Eof) return(0);
  172     nread=BZ2_bzRead(&bzerr,BData->BzFile,Buffer,Size);
  173     if (bzerr==BZ_STREAM_END)
  174         BData->Eof=true;
  175     else if (bzerr!=BZ_OK)
  176         return(0);
  177     return(nread);
  178 }
  179 
  180 /*!
  181  * Check if end of file is reached.
  182  *
  183  * \param Data The file object.
  184  *
  185  * \return \c True if end of file is reached.
  186  */
  187 static int Bzip_Eof(void *Data)
  188 {
  189     struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
  190     return(BData->Eof);
  191 }
  192 
  193 /*!
  194  * Return to the beginnig of the file.
  195  *
  196  * \param Data The file object.
  197  */
  198 static void Bzip_Rewind(void *Data)
  199 {
  200     struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
  201     int bzerr=BZ_OK;
  202 
  203     BZ2_bzReadClose(&bzerr,BData->BzFile);
  204     rewind(BData->File);
  205     BData->BzFile=BZ2_bzReadOpen(&bzerr,BData->File,0,0,NULL,0);
  206     if (!BData->BzFile)
  207     {
  208         debuga(__FILE__,__LINE__,_("Cannot rewind bzip file\n"));
  209         exit(EXIT_FAILURE);
  210     }
  211     BData->Eof=false;
  212 }
  213 
  214 /*!
  215  * Close the file.
  216  *
  217  * \param Data File to close.
  218  *
  219  * \return 0 on success or -1 on error.
  220  */
  221 static int Bzip_Close(void *Data)
  222 {
  223     struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
  224     int bzerr=BZ_OK;
  225 
  226     BZ2_bzReadClose(&bzerr,BData->BzFile);
  227     fclose(BData->File);
  228     free(BData);
  229     return(0);
  230 }
  231 
  232 /*!
  233  * Open a file object to read from a bzip file.
  234  *
  235  * \return The object to pass to other function in this module.
  236  */
  237 static FileObject *Bzip_Open(int fd)
  238 {
  239     FileObject *File;
  240     struct BzlibInternalFile *BData;
  241     int bzerr=BZ_OK;
  242 
  243     FileObject_SetLastOpenError(NULL);
  244     File=calloc(1,sizeof(*File));
  245     if (!File)
  246     {
  247         FileObject_SetLastOpenError(_("Not enough memory"));
  248         return(NULL);
  249     }
  250     BData=calloc(1,sizeof(*BData));
  251     if (!BData)
  252     {
  253         free(File);
  254         FileObject_SetLastOpenError(_("Not enough memory"));
  255         return(NULL);
  256     }
  257     BData->File=fdopen(fd,"rb");
  258     if (BData->File==NULL)
  259     {
  260         free(BData);
  261         free(File);
  262         FileObject_SetLastOpenError(_("Error duplicating file descriptor"));
  263         return(NULL);
  264     }
  265     File->Data=BData;
  266     BData->BzFile=BZ2_bzReadOpen(&bzerr,BData->File,0,0,NULL,0);
  267     if (!BData->BzFile)
  268     {
  269         fclose(BData->File);
  270         free(BData);
  271         free(File);
  272         FileObject_SetLastOpenError(_("Error opening bzip file"));
  273         return(NULL);
  274     }
  275     File->Read=Bzip_Read;
  276     File->Eof=Bzip_Eof;
  277     File->Rewind=Bzip_Rewind;
  278     File->Close=Bzip_Close;
  279     return(File);
  280 }
  281 #endif
  282 
  283 #ifdef HAVE_LZMA_H
  284 
  285 struct LzmaInternalFile
  286 {
  287     //! Lzma stream.
  288     lzma_stream Stream;
  289     //! \c True if end of file is reached.
  290     bool Eof;
  291     //! Original file in case a rewind is necessary.
  292     FILE *File;
  293     //! Input buffer to store data read from the log file.
  294     unsigned char InputBuffer[128*1024];
  295 };
  296 
  297 /*!
  298  * Read from xz file.
  299  *
  300  * \param Data The file object.
  301  * \param Buffer The boffer to store the data read.
  302  * \param Size How many bytes to read.
  303  *
  304  * \return The number of bytes read.
  305  */
  306 static int Lzma_Read(void *Data,void *Buffer,int Size)
  307 {
  308     struct LzmaInternalFile *BData=(struct LzmaInternalFile *)Data;
  309     lzma_ret zerr;
  310 
  311     BData->Stream.next_out=Buffer;
  312     BData->Stream.avail_out=Size;
  313     while (BData->Stream.avail_out>0 && !BData->Eof)
  314     {
  315         if (BData->Stream.avail_in==0 && !BData->Eof)
  316         {
  317             BData->Stream.next_in=BData->InputBuffer;
  318             BData->Stream.avail_in=fread(BData->InputBuffer,1,sizeof(BData->InputBuffer),BData->File);
  319             if (feof(BData->File))
  320                 BData->Eof=true;
  321         }
  322         zerr=lzma_code(&BData->Stream,(BData->Eof) ? LZMA_FINISH : LZMA_RUN);
  323         if (zerr==LZMA_STREAM_END)
  324         {
  325             BData->Eof=true;
  326         }
  327         else if (zerr!=LZMA_OK)
  328         {
  329             debuga(__FILE__,__LINE__,_("Error decompressiong xz file (lzma library returned error %d)"),zerr);
  330             return(0);
  331         }
  332     }
  333     return(Size-BData->Stream.avail_out);
  334 }
  335 
  336 /*!
  337  * Check if end of file is reached.
  338  *
  339  * \param Data The file object.
  340  *
  341  * \return \c True if end of file is reached.
  342  */
  343 static int Lzma_Eof(void *Data)
  344 {
  345     struct LzmaInternalFile *BData=(struct LzmaInternalFile *)Data;
  346     return(BData->Eof);
  347 }
  348 
  349 /*!
  350  * Initialize the lzma decoding stream.
  351  *
  352  * \param Stream Lzma stream to initialize.
  353  *
  354  * \return 0 on success or -1 if the intialization failed. A suitable
  355  * error message is displayed in case of error.
  356  */
  357 static int Lzma_InitDecoder(lzma_stream *Stream)
  358 {
  359     lzma_ret zerr;
  360 
  361     zerr=lzma_stream_decoder(Stream,UINT64_MAX,LZMA_CONCATENATED);
  362     if (zerr!=LZMA_OK)
  363     {
  364         switch (zerr)
  365         {
  366             case LZMA_MEM_ERROR:
  367                 FileObject_SetLastOpenError(_("Not enough memory to initialize LZMA decoder"));
  368                 break;
  369             case LZMA_OPTIONS_ERROR:
  370                 FileObject_SetLastOpenError(_("Failed to initialize LZMA decoder due to invalid option passed to the decoder"));
  371                 break;
  372             default:
  373             {
  374                 char ErrMsg[80];
  375 
  376                 snprintf(ErrMsg,sizeof(ErrMsg),_("Failed to initialize LZMA decoder with unknown error %d"),zerr);
  377                 FileObject_SetLastOpenError(ErrMsg);
  378                 break;
  379             }
  380         }
  381         return(-1);
  382     }
  383     return(0);
  384 }
  385 
  386 /*!
  387  * Return to the beginnig of the file.
  388  *
  389  * \param Data The file object.
  390  */
  391 static void Lzma_Rewind(void *Data)
  392 {
  393     struct LzmaInternalFile *BData=(struct LzmaInternalFile *)Data;
  394 
  395     rewind(BData->File);
  396     BData->Eof=false;
  397     memset(&BData->Stream,0,sizeof(BData->Stream));
  398     if (Lzma_InitDecoder(&BData->Stream)<0)
  399     {
  400         debuga(__FILE__,__LINE__,_("Failed to rewind the xz file (see previous LZMA error)\n"));
  401         exit(EXIT_FAILURE);
  402     }
  403 }
  404 
  405 /*!
  406  * Close the file.
  407  *
  408  * \param Data File to close.
  409  *
  410  * \return 0 on success or -1 on error.
  411  */
  412 static int Lzma_Close(void *Data)
  413 {
  414     struct LzmaInternalFile *BData=(struct LzmaInternalFile *)Data;
  415 
  416     fclose(BData->File);
  417     lzma_end(&BData->Stream);
  418     free(BData);
  419     return(0);
  420 }
  421 
  422 /*!
  423  * Open a file object to read from a xz file.
  424  *
  425  * \return The object to pass to other function in this module.
  426  */
  427 static FileObject *Lzma_Open(int fd)
  428 {
  429     FileObject *File;
  430     struct LzmaInternalFile *BData;
  431 
  432     FileObject_SetLastOpenError(NULL);
  433     File=calloc(1,sizeof(*File));
  434     if (!File)
  435     {
  436         FileObject_SetLastOpenError(_("Not enough memory"));
  437         return(NULL);
  438     }
  439     BData=calloc(1,sizeof(*BData));
  440     if (!BData)
  441     {
  442         free(File);
  443         FileObject_SetLastOpenError(_("Not enough memory"));
  444         return(NULL);
  445     }
  446     BData->File=fdopen(fd,"rb");
  447     if (BData->File==NULL)
  448     {
  449         free(BData);
  450         free(File);
  451         FileObject_SetLastOpenError(_("Error duplicating file descriptor"));
  452         return(NULL);
  453     }
  454     if (Lzma_InitDecoder(&BData->Stream)<0)
  455     {
  456         fclose(BData->File);
  457         free(BData);
  458         free(File);
  459         return(NULL);
  460     }
  461     File->Data=BData;
  462     File->Read=Lzma_Read;
  463     File->Eof=Lzma_Eof;
  464     File->Rewind=Lzma_Rewind;
  465     File->Close=Lzma_Close;
  466     return(File);
  467 }
  468 #endif
  469 
  470 
  471 /*!
  472 Open the log file. If it is compressed, uncompress it with the proper library.
  473 
  474 Log files compressed with gzip, bzip2 can be uncompressed if sarg is compiled with
  475 the proper library.
  476 
  477 If the log file does not exist, the process terminates with an error message.
  478 
  479 \param arq The log file to process.
  480 */
  481 FileObject *decomp(const char *arq)
  482 {
  483     int fd;
  484     FileObject *fi;
  485     unsigned char buf[5];
  486     ssize_t nread;
  487 
  488     // guess file type
  489     fd=open(arq,O_RDONLY | O_LARGEFILE);
  490     if (fd==-1) {
  491         debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),arq,strerror(errno));
  492         exit(EXIT_FAILURE);
  493     }
  494     nread=read(fd,buf,sizeof(buf));
  495     if (nread==-1) {
  496         debuga(__FILE__,__LINE__,_("Error while reading \"%s\" to guess its type: %s\n"),arq,strerror(errno));
  497         exit(EXIT_FAILURE);
  498     }
  499     if (nread<sizeof(buf)) {
  500         debuga(__FILE__,__LINE__,_("File \"%s\" is too small to guess its type\n"),arq);
  501         exit(EXIT_FAILURE);
  502     }
  503     if (lseek(fd,0,SEEK_SET)==-1) {
  504         debuga(__FILE__,__LINE__,_("Cannot return to the beginning of file \"%s\": %s"),arq,strerror(errno));
  505         exit(EXIT_FAILURE);
  506     }
  507 
  508     if (buf[0]==0x1F && buf[1]==0x8B && buf[2]==0x08)//gzip file
  509     {
  510 #ifdef HAVE_ZLIB_H
  511         fi=Gzip_Open(fd);
  512 #else
  513         debuga(__FILE__,__LINE__,_("Sarg was not compiled with gzip support to read file \"%s\"\n"),arq);
  514         exit(EXIT_FAILURE);
  515 #endif
  516     }
  517     else if (buf[0]==0x42 && buf[1]==0x5A && buf[2]==0x68)//bzip2 file
  518     {
  519 #ifdef HAVE_BZLIB_H
  520         fi=Bzip_Open(fd);
  521 #else
  522         debuga(__FILE__,__LINE__,_("Sarg was not compiled with bzip support to read file \"%s\"\n"),arq);
  523         exit(EXIT_FAILURE);
  524 #endif
  525     }
  526     else if (buf[0]==0xFD && buf[1]=='7' && buf[2]=='z' && buf[3]=='X' && buf[4]=='Z')//xz file
  527     {
  528 #ifdef HAVE_LZMA_H
  529         fi=Lzma_Open(fd);
  530 #else
  531         debuga(__FILE__,__LINE__,_("Sarg was not compiled with xz support to read file \"%s\"\n"),arq);
  532         exit(EXIT_FAILURE);
  533 #endif
  534     }
  535     else if (buf[0]==0x1F && (buf[1]==0x9D || buf[1]==0xA0))//LZW and LZH compressed file
  536     {
  537         debuga(__FILE__,__LINE__,_("Support for LZW and LZH compressed files was removed in sarg 2.4.\n"
  538                                    "You can still read such a file with a command like this:\n"
  539                                    "  zcat \"%s\" | sarg - [your usual options here]\n"
  540                                    "If you think it is important for sarg to read those files, open a bug ticket at <http://sourceforge.net/p/sarg/bugs/>.\n"),
  541                arq);
  542         exit(EXIT_FAILURE);
  543     }
  544     else //normal file
  545     {
  546         fi=FileObject_FdOpen(fd);
  547     }
  548     return(fi);
  549 }