+#ifdef HAVE_ZLIB_H
+#include "zlib.h"
+#endif
+#ifdef HAVE_BZLIB_H
+#include "bzlib.h"
+#endif
+
+#ifdef HAVE_ZLIB_H
+/*!
+ * Read from gzip 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 Gzip_Read(void *Data,void *Buffer,int Size)
+{
+ return(gzread((gzFile)Data,Buffer,Size));
+}
+
+/*!
+ * Check if end of file is reached.
+ *
+ * \param Data The file object.
+ *
+ * \return \c True if end of file is reached.
+ */
+static int Gzip_Eof(void *Data)
+{
+ return(gzeof((gzFile)Data));
+}
+
+/*!
+ * Return to the beginnig of the file.
+ *
+ * \param Data The file object.
+ */
+static void Gzip_Rewind(void *Data)
+{
+ gzrewind((gzFile)Data);
+}
+
+/*!
+ * Close the file.
+ *
+ * \param Data File to close.
+ *
+ * \return 0 on success or -1 on error.
+ */
+static int Gzip_Close(void *Data)
+{
+ int RetCode=-1;
+ int Status;
+
+ Status=gzclose((gzFile)Data);
+ switch (Status)
+ {
+ case Z_OK:
+ RetCode=0;
+ break;
+ case Z_STREAM_ERROR:
+ FileObject_SetLastCloseError(_("Invalid gzip file"));
+ break;
+ case Z_ERRNO:
+ FileObject_SetLastCloseError(_("File operation error"));
+ break;
+ case Z_MEM_ERROR:
+ FileObject_SetLastCloseError(_("Not enough memory"));
+ break;
+ case Z_BUF_ERROR:
+ FileObject_SetLastCloseError(_("Truncated gzip stream"));
+ break;
+ default:
+ FileObject_SetLastCloseError(_("Unknown error returned by zlib"));
+ break;
+ }
+ return(RetCode);
+}
+
+/*!
+ * Open a file object to read from a gzip file.
+ *
+ * \return The object to pass to other function in this module.
+ */
+static FileObject *Gzip_Open(int fd)
+{
+ FileObject *File;
+
+ FileObject_SetLastOpenError(NULL);
+ File=calloc(1,sizeof(*File));
+ if (!File)
+ {
+ FileObject_SetLastOpenError(_("Not enough memory"));
+ return(NULL);
+ }
+ File->Data=gzdopen(fd,"rb");
+ if (!File->Data)
+ {
+ free(File);
+ FileObject_SetLastOpenError(_("Error opening gzip file"));
+ return(NULL);
+ }
+ File->Read=Gzip_Read;
+ File->Eof=Gzip_Eof;
+ File->Rewind=Gzip_Rewind;
+ File->Close=Gzip_Close;
+ return(File);
+}
+#endif
+
+#ifdef HAVE_BZLIB_H
+
+struct BzlibInternalFile
+{
+ //! Bzlib object.
+ BZFILE *BzFile;
+ //! \c True if end of file is reached.
+ bool Eof;
+ //! Copy of the original file handle.
+ int fd;
+}
+
+/*!
+ * Read from bzip 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 Bzip_Read(void *Data,void *Buffer,int Size)
+{
+ struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
+ int nread;
+
+ nread=BZ2_bzread(BData->BzFile,Buffer,Size);
+ if (nread==0) BData->Eof=true;
+ return(nread);
+}
+
+/*!
+ * Check if end of file is reached.
+ *
+ * \param Data The file object.
+ *
+ * \return \c True if end of file is reached.
+ */
+static int Bzip_Eof(void *Data)
+{
+ struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
+ return(BData->Eof);
+}
+
+/*!
+ * Return to the beginnig of the file.
+ *
+ * \param Data The file object.
+ */
+static void Bzip_Rewind(void *Data)
+{
+ struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
+ int fd;
+
+ BZ2_bzclose(BData->BzFile);
+ fd=dup(BData->fd);
+ if (fd==-1)
+ {
+ debuga(__FILE__,__LINE__,_("Cannot rewind bzip file\n"));
+ exit(EXIT_FAILURE);
+ }
+ BData->BzFile=BZ2_bzdopen(fd,"rb");
+ if (!BData->BzFile)
+ {
+ debuga(__FILE__,__LINE__,_("Cannot rewind bzip file\n"));
+ exit(EXIT_FAILURE);
+ }
+}
+
+/*!
+ * Close the file.
+ *
+ * \param Data File to close.
+ *
+ * \return 0 on success or -1 on error.
+ */
+static int Bzip_Close(void *Data)
+{
+ struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
+
+ BZ2_bzclose(BData->BzFile);
+ close(BData->fd);
+ free(BData);
+ return(0);
+}
+
+/*!
+ * Open a file object to read from a bzip file.
+ *
+ * \return The object to pass to other function in this module.
+ */
+static FileObject *Bzip_Open(int fd)
+{
+ FileObject *File;
+ struct BzlibInternalFile *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->fd=dup(fd);
+ if (BData->fd==-1)
+ {
+ free(BData);
+ free(File);
+ FileObject_SetLastOpenError(_("Error duplicating file descriptor"));
+ return(NULL);
+ }
+ File=Data=BData;
+ BData->BzFile=BZ2_bzdopen(fd,"rb");
+ if (!BData->BzFile)
+ {
+ close(BData->fd);
+ free(BData);
+ free(File);
+ FileObject_SetLastOpenError(_("Error opening bzip file"));
+ return(NULL);
+ }
+ File->Read=Bzip_Read;
+ File->Eof=Bzip_Eof;
+ File->Rewind=Bzip_Rewind;
+ File->Close=Bzip_Close;
+ return(File);
+}
+#endif
+