]> git.ipfire.org Git - thirdparty/sarg.git/blame - decomp.c
Make b-tree cache functions static.
[thirdparty/sarg.git] / decomp.c
CommitLineData
25697a35 1/*
94ff9470 2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
110ce984 3 * 1998, 2015
25697a35
GS
4 *
5 * SARG donations:
6 * please look at http://sarg.sourceforge.net/donations.php
1164c474
FM
7 * Support:
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
25697a35
GS
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"
5f3cfd1d 28#include "include/defs.h"
800eafb8
FM
29#ifdef HAVE_ZLIB_H
30#include "zlib.h"
31#endif
32#ifdef HAVE_BZLIB_H
33#include "bzlib.h"
34#endif
35
36#ifdef HAVE_ZLIB_H
37/*!
38 * Read from gzip file.
39 *
40 * \param Data The file object.
41 * \param Buffer The boffer to store the data read.
42 * \param Size How many bytes to read.
43 *
44 * \return The number of bytes read.
45 */
46static int Gzip_Read(void *Data,void *Buffer,int Size)
47{
48 return(gzread((gzFile)Data,Buffer,Size));
49}
50
51/*!
52 * Check if end of file is reached.
53 *
54 * \param Data The file object.
55 *
56 * \return \c True if end of file is reached.
57 */
58static int Gzip_Eof(void *Data)
59{
60 return(gzeof((gzFile)Data));
61}
62
63/*!
64 * Return to the beginnig of the file.
65 *
66 * \param Data The file object.
67 */
68static void Gzip_Rewind(void *Data)
69{
70 gzrewind((gzFile)Data);
71}
72
73/*!
74 * Close the file.
75 *
76 * \param Data File to close.
77 *
78 * \return 0 on success or -1 on error.
79 */
80static int Gzip_Close(void *Data)
81{
82 int RetCode=-1;
83 int Status;
84
85 Status=gzclose((gzFile)Data);
86 switch (Status)
87 {
88 case Z_OK:
89 RetCode=0;
90 break;
91 case Z_STREAM_ERROR:
92 FileObject_SetLastCloseError(_("Invalid gzip file"));
93 break;
94 case Z_ERRNO:
95 FileObject_SetLastCloseError(_("File operation error"));
96 break;
97 case Z_MEM_ERROR:
98 FileObject_SetLastCloseError(_("Not enough memory"));
99 break;
100 case Z_BUF_ERROR:
101 FileObject_SetLastCloseError(_("Truncated gzip stream"));
102 break;
103 default:
104 FileObject_SetLastCloseError(_("Unknown error returned by zlib"));
105 break;
106 }
107 return(RetCode);
108}
109
110/*!
111 * Open a file object to read from a gzip file.
112 *
113 * \return The object to pass to other function in this module.
114 */
115static FileObject *Gzip_Open(int fd)
116{
117 FileObject *File;
118
119 FileObject_SetLastOpenError(NULL);
120 File=calloc(1,sizeof(*File));
121 if (!File)
122 {
123 FileObject_SetLastOpenError(_("Not enough memory"));
124 return(NULL);
125 }
126 File->Data=gzdopen(fd,"rb");
127 if (!File->Data)
128 {
129 free(File);
130 FileObject_SetLastOpenError(_("Error opening gzip file"));
131 return(NULL);
132 }
133 File->Read=Gzip_Read;
134 File->Eof=Gzip_Eof;
135 File->Rewind=Gzip_Rewind;
136 File->Close=Gzip_Close;
137 return(File);
138}
139#endif
140
141#ifdef HAVE_BZLIB_H
142
143struct BzlibInternalFile
144{
145 //! Bzlib object.
146 BZFILE *BzFile;
147 //! \c True if end of file is reached.
148 bool Eof;
a1e4e370
FM
149 //! Original file in case a rewind is necessary.
150 FILE *File;
151};
800eafb8
FM
152
153/*!
154 * Read from bzip file.
155 *
156 * \param Data The file object.
157 * \param Buffer The boffer to store the data read.
158 * \param Size How many bytes to read.
159 *
160 * \return The number of bytes read.
161 */
162static int Bzip_Read(void *Data,void *Buffer,int Size)
163{
164 struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
165 int nread;
a1e4e370 166 int bzerr=BZ_OK;
800eafb8 167
a1e4e370
FM
168 if (BData->Eof) return(0);
169 nread=BZ2_bzRead(&bzerr,BData->BzFile,Buffer,Size);
170 if (bzerr==BZ_STREAM_END)
171 BData->Eof=true;
172 else if (bzerr!=BZ_OK)
173 return(0);
800eafb8
FM
174 return(nread);
175}
176
177/*!
178 * Check if end of file is reached.
179 *
180 * \param Data The file object.
181 *
182 * \return \c True if end of file is reached.
183 */
184static int Bzip_Eof(void *Data)
185{
186 struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
187 return(BData->Eof);
188}
189
190/*!
191 * Return to the beginnig of the file.
192 *
193 * \param Data The file object.
194 */
195static void Bzip_Rewind(void *Data)
196{
197 struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
a1e4e370 198 int bzerr=BZ_OK;
800eafb8 199
a1e4e370
FM
200 BZ2_bzReadClose(&bzerr,BData->BzFile);
201 rewind(BData->File);
202 BData->BzFile=BZ2_bzReadOpen(&bzerr,BData->File,0,0,NULL,0);
800eafb8
FM
203 if (!BData->BzFile)
204 {
205 debuga(__FILE__,__LINE__,_("Cannot rewind bzip file\n"));
206 exit(EXIT_FAILURE);
207 }
a1e4e370 208 BData->Eof=false;
800eafb8
FM
209}
210
211/*!
212 * Close the file.
213 *
214 * \param Data File to close.
215 *
216 * \return 0 on success or -1 on error.
217 */
218static int Bzip_Close(void *Data)
219{
220 struct BzlibInternalFile *BData=(struct BzlibInternalFile *)Data;
a1e4e370 221 int bzerr=BZ_OK;
800eafb8 222
a1e4e370
FM
223 BZ2_bzReadClose(&bzerr,BData->BzFile);
224 fclose(BData->File);
800eafb8
FM
225 free(BData);
226 return(0);
227}
228
229/*!
230 * Open a file object to read from a bzip file.
231 *
232 * \return The object to pass to other function in this module.
233 */
234static FileObject *Bzip_Open(int fd)
235{
236 FileObject *File;
237 struct BzlibInternalFile *BData;
a1e4e370 238 int bzerr=BZ_OK;
800eafb8
FM
239
240 FileObject_SetLastOpenError(NULL);
241 File=calloc(1,sizeof(*File));
242 if (!File)
243 {
244 FileObject_SetLastOpenError(_("Not enough memory"));
245 return(NULL);
246 }
247 BData=calloc(1,sizeof(*BData));
248 if (!BData)
249 {
250 free(File);
251 FileObject_SetLastOpenError(_("Not enough memory"));
252 return(NULL);
253 }
a1e4e370
FM
254 BData->File=fdopen(fd,"rb");
255 if (BData->File==NULL)
800eafb8
FM
256 {
257 free(BData);
258 free(File);
259 FileObject_SetLastOpenError(_("Error duplicating file descriptor"));
260 return(NULL);
261 }
a1e4e370
FM
262 File->Data=BData;
263 BData->BzFile=BZ2_bzReadOpen(&bzerr,BData->File,0,0,NULL,0);
800eafb8
FM
264 if (!BData->BzFile)
265 {
a1e4e370 266 fclose(BData->File);
800eafb8
FM
267 free(BData);
268 free(File);
269 FileObject_SetLastOpenError(_("Error opening bzip file"));
270 return(NULL);
271 }
272 File->Read=Bzip_Read;
273 File->Eof=Bzip_Eof;
274 File->Rewind=Bzip_Rewind;
275 File->Close=Bzip_Close;
276 return(File);
277}
278#endif
279
25697a35 280
d2cd218e
FM
281/*!
282Open the log file. If it is compressed, uncompress it through a pipe.
283
284Log files compressed with gzip, bzip2 or compress are uncompressed with zcat or bzcat.
285
286If the log file does not exist, the process terminates with an error message.
287
288\param arq The log file to process.
289\param pipe A variable set to \c true if the log file is opened through a pipe or set to \c false if the file is open directly.
290
291\date 2009-09-24 - F Marchal\n This function used to uncompress .Z files in
292place using uncompress but that required a write access to the log directory,
293could conflict with logrotate and could leave the log file uncompressed if sarg
294crashed. According to the documentation, zcat is capable of uncompressing .Z
295files so it is now used.
296
297\date 2010-05-10 - F Marchal\n
298The function doesn't use a temporary file any more and read the compressed file through a pipe.
299*/
800eafb8 300FileObject *decomp(const char *arq)
25697a35 301{
800eafb8
FM
302 int fd;
303 FileObject *fi;
304 unsigned char buf[3];
305 ssize_t nread;
306
307 // guess file type
308 fd=open(arq,O_RDONLY | O_LARGEFILE);
309 if (fd==-1) {
310 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),arq,strerror(errno));
311 exit(EXIT_FAILURE);
312 }
313 nread=read(fd,buf,sizeof(buf));
314 if (nread==-1) {
315 debuga(__FILE__,__LINE__,_("Error while reading \"%s\" to guess its type: %s\n"),arq,strerror(errno));
316 exit(EXIT_FAILURE);
317 }
318 if (nread<3) {
319 debuga(__FILE__,__LINE__,_("File \"%s\" is too small to guess its type\n"),arq);
320 exit(EXIT_FAILURE);
321 }
322 if (lseek(fd,0,SEEK_SET)==-1) {
323 debuga(__FILE__,__LINE__,_("Cannot return to the beginning of file \"%s\": %s"),arq,strerror(errno));
324 exit(EXIT_FAILURE);
325 }
326
327 if (buf[0]==0x1F && buf[1]==0x8B && buf[2]==0x08)//gzip file
328 {
329#ifdef HAVE_ZLIB_H
330 fi=Gzip_Open(fd);
331#else
332 debuga(__FILE__,__LINE__,_("Sarg was not compiled with gzip support to read file \"%s\"\n"),arq);
333 exit(EXIT_FAILURE);
334#endif
335 }
336 else if (buf[0]==0x42 && buf[1]==0x5A && buf[2]==0x68)//bzip2 file
337 {
338#ifdef HAVE_BZLIB_H
339 fi=Bzip_Open(fd);
340#else
341 debuga(__FILE__,__LINE__,_("Sarg was not compiled with bzip support to read file \"%s\"\n"),arq);
342 exit(EXIT_FAILURE);
343#endif
344 }
275c8c93
FM
345 else if (buf[0]==0x1F && (buf[1]==0x9D || buf[1]==0xA0))//LZW and LZH compressed file
346 {
347 debuga(__FILE__,__LINE__,_("Support for LZW and LZH compressed files was removed in sarg 2.4.\n"
348 "You can still read such a file with a command like this:\n"
349 " zcat \"%s\" | sarg - [your usual options here]\n"
350 "If you think it is important for sarg to read those files, open a bug ticket at <http://sourceforge.net/p/sarg/bugs/>.\n"),
351 arq);
352 exit(EXIT_FAILURE);
353 }
800eafb8
FM
354 else //normal file
355 {
356 fi=FileObject_FdOpen(fd);
d2cd218e
FM
357 }
358 return(fi);
25697a35 359}