+#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
+