bzlib_status="disabled"
])
+# Build with liblzma
+AC_ARG_WITH([liblzma],
+ AS_HELP_STRING([--with-liblzma],[Compile with support to decompress xz files]),
+ [],[with_liblzma=check])
+AS_IF([test "x$with_liblzma" != "xno" ],
+[
+ AC_CHECK_HEADERS(lzma.h)
+ AS_IF([test "x$ac_cv_header_lzma_h" = "xyes"],
+ [
+ AC_CHECK_LIB([lzma],[lzma_stream_decoder],
+ [
+ LIBS="-llzma ${LIBS}"
+ HAVE_LIBLZMA_LIB="yes"
+ ],[
+ HAVE_LIBLZMA_LIB=""
+ ])
+ AS_IF([test "x$HAVE_LIBLZMA_LIB" != "xyes"],[AC_MSG_ERROR([liblzma was not found])])
+ ],[
+ liblzma_status="not found"
+ ])
+],[
+ liblzma_status="disabled"
+])
+
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_STRUCT_TM
],[test "x$bzlib_status" = "xnot found"],[
AC_MSG_NOTICE([bzlib.h was not found so it won't be possible to process bzipped files])
])
+
+AS_IF([test "x$liblzma_status" = "xdisabled"],[
+ AC_MSG_NOTICE([Not building with liblzma as requested on the configuration command line])
+],[test "x$liblzma_status" = "xnot found"],[
+ AC_MSG_NOTICE([lzma.h was not found so it won't be possible to process xz files])
+])
#ifdef HAVE_BZLIB_H
#include "bzlib.h"
#endif
+#ifdef HAVE_LZMA_H
+#include "lzma.h"
+#endif
#ifdef HAVE_ZLIB_H
/*!
}
#endif
+#ifdef HAVE_LZMA_H
+
+struct LzmaInternalFile
+{
+ //! Lzma stream.
+ lzma_stream Stream;
+ //! \c True if end of file is reached.
+ bool Eof;
+ //! Original file in case a rewind is necessary.
+ FILE *File;
+ //! Input buffer to store data read from the log file.
+ unsigned char InputBuffer[128*1024];
+};
+
+/*!
+ * Read from xz file.
+ *
+ * \param Data The file object.
+ * \param Buffer The boffer to store the data read.
+ * \param Size How many bytes to read.
+ *
+ * \return The number of bytes read.
+ */
+static int Lzma_Read(void *Data,void *Buffer,int Size)
+{
+ struct LzmaInternalFile *BData=(struct LzmaInternalFile *)Data;
+ lzma_ret zerr;
+
+ BData->Stream.next_out=Buffer;
+ BData->Stream.avail_out=Size;
+ while (BData->Stream.avail_out>0 && !BData->Eof)
+ {
+ if (BData->Stream.avail_in==0 && !BData->Eof)
+ {
+ BData->Stream.next_in=BData->InputBuffer;
+ BData->Stream.avail_in=fread(BData->InputBuffer,1,sizeof(BData->InputBuffer),BData->File);
+ if (feof(BData->File))
+ BData->Eof=true;
+ }
+ zerr=lzma_code(&BData->Stream,(BData->Eof) ? LZMA_FINISH : LZMA_RUN);
+ if (zerr==LZMA_STREAM_END)
+ {
+ BData->Eof=true;
+ }
+ else if (zerr!=LZMA_OK)
+ {
+ debuga(__FILE__,__LINE__,_("Error decompressiong xz file (lzma library returned error %d)"),zerr);
+ return(0);
+ }
+ }
+ return(Size-BData->Stream.avail_out);
+}
+
+/*!
+ * Check if end of file is reached.
+ *
+ * \param Data The file object.
+ *
+ * \return \c True if end of file is reached.
+ */
+static int Lzma_Eof(void *Data)
+{
+ struct LzmaInternalFile *BData=(struct LzmaInternalFile *)Data;
+ return(BData->Eof);
+}
+
+/*!
+ * Initialize the lzma decoding stream.
+ *
+ * \param Stream Lzma stream to initialize.
+ *
+ * \return 0 on success or -1 if the intialization failed. A suitable
+ * error message is displayed in case of error.
+ */
+static int Lzma_InitDecoder(lzma_stream *Stream)
+{
+ lzma_ret zerr;
+
+ zerr=lzma_stream_decoder(Stream,UINT64_MAX,LZMA_CONCATENATED);
+ if (zerr!=LZMA_OK)
+ {
+ switch (zerr)
+ {
+ case LZMA_MEM_ERROR:
+ FileObject_SetLastOpenError(_("Not enough memory to initialize LZMA decoder"));
+ break;
+ case LZMA_OPTIONS_ERROR:
+ FileObject_SetLastOpenError(_("Failed to initialize LZMA decoder due to invalid option passed to the decoder"));
+ break;
+ default:
+ {
+ char ErrMsg[80];
+
+ snprintf(ErrMsg,sizeof(ErrMsg),_("Failed to initialize LZMA decoder with unknown error %d"),zerr);
+ FileObject_SetLastOpenError(ErrMsg);
+ break;
+ }
+ }
+ return(-1);
+ }
+ return(0);
+}
+
+/*!
+ * Return to the beginnig of the file.
+ *
+ * \param Data The file object.
+ */
+static void Lzma_Rewind(void *Data)
+{
+ struct LzmaInternalFile *BData=(struct LzmaInternalFile *)Data;
+
+ rewind(BData->File);
+ BData->Eof=false;
+ memset(&BData->Stream,0,sizeof(BData->Stream));
+ if (Lzma_InitDecoder(&BData->Stream)<0)
+ {
+ debuga(__FILE__,__LINE__,_("Failed to rewind the xz file (see previous LZMA error)\n"));
+ exit(EXIT_FAILURE);
+ }
+}
+
+/*!
+ * Close the file.
+ *
+ * \param Data File to close.
+ *
+ * \return 0 on success or -1 on error.
+ */
+static int Lzma_Close(void *Data)
+{
+ struct LzmaInternalFile *BData=(struct LzmaInternalFile *)Data;
+
+ fclose(BData->File);
+ lzma_end(&BData->Stream);
+ free(BData);
+ return(0);
+}
+
+/*!
+ * Open a file object to read from a xz file.
+ *
+ * \return The object to pass to other function in this module.
+ */
+static FileObject *Lzma_Open(int fd)
+{
+ FileObject *File;
+ struct LzmaInternalFile *BData;
+
+ FileObject_SetLastOpenError(NULL);
+ File=calloc(1,sizeof(*File));
+ if (!File)
+ {
+ FileObject_SetLastOpenError(_("Not enough memory"));
+ return(NULL);
+ }
+ BData=calloc(1,sizeof(*BData));
+ if (!BData)
+ {
+ free(File);
+ FileObject_SetLastOpenError(_("Not enough memory"));
+ return(NULL);
+ }
+ BData->File=fdopen(fd,"rb");
+ if (BData->File==NULL)
+ {
+ free(BData);
+ free(File);
+ FileObject_SetLastOpenError(_("Error duplicating file descriptor"));
+ return(NULL);
+ }
+ if (Lzma_InitDecoder(&BData->Stream)<0)
+ {
+ fclose(BData->File);
+ free(BData);
+ free(File);
+ return(NULL);
+ }
+ File->Data=BData;
+ File->Read=Lzma_Read;
+ File->Eof=Lzma_Eof;
+ File->Rewind=Lzma_Rewind;
+ File->Close=Lzma_Close;
+ return(File);
+}
+#endif
+
/*!
Open the log file. If it is compressed, uncompress it with the proper library.
{
int fd;
FileObject *fi;
- unsigned char buf[3];
+ unsigned char buf[5];
ssize_t nread;
// guess file type
debuga(__FILE__,__LINE__,_("Error while reading \"%s\" to guess its type: %s\n"),arq,strerror(errno));
exit(EXIT_FAILURE);
}
- if (nread<3) {
+ if (nread<sizeof(buf)) {
debuga(__FILE__,__LINE__,_("File \"%s\" is too small to guess its type\n"),arq);
exit(EXIT_FAILURE);
}
#else
debuga(__FILE__,__LINE__,_("Sarg was not compiled with bzip support to read file \"%s\"\n"),arq);
exit(EXIT_FAILURE);
+#endif
+ }
+ else if (buf[0]==0xFD && buf[1]=='7' && buf[2]=='z' && buf[3]=='X' && buf[4]=='Z')//xz file
+ {
+#ifdef HAVE_LZMA_H
+ fi=Lzma_Open(fd);
+#else
+ debuga(__FILE__,__LINE__,_("Sarg was not compiled with xz support to read file \"%s\"\n"),arq);
+ exit(EXIT_FAILURE);
#endif
}
else if (buf[0]==0x1F && (buf[1]==0x9D || buf[1]==0xA0))//LZW and LZH compressed file