]>
Commit | Line | Data |
---|---|---|
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 | */ | |
46 | static 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 | */ | |
58 | static 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 | */ | |
68 | static 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 | */ | |
80 | static 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 | */ | |
115 | static 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 | ||
143 | struct 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 | */ | |
162 | static 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 | */ | |
184 | static 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 | */ | |
195 | static 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 | */ | |
218 | static 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 | */ | |
234 | static 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 | 281 | /*! |
6eb9e090 | 282 | Open the log file. If it is compressed, uncompress it with the proper library. |
d2cd218e | 283 | |
6eb9e090 FM |
284 | Log files compressed with gzip, bzip2 can be uncompressed if sarg is compiled with |
285 | the proper library. | |
d2cd218e FM |
286 | |
287 | If the log file does not exist, the process terminates with an error message. | |
288 | ||
289 | \param arq The log file to process. | |
d2cd218e | 290 | */ |
800eafb8 | 291 | FileObject *decomp(const char *arq) |
25697a35 | 292 | { |
800eafb8 FM |
293 | int fd; |
294 | FileObject *fi; | |
295 | unsigned char buf[3]; | |
296 | ssize_t nread; | |
297 | ||
298 | // guess file type | |
299 | fd=open(arq,O_RDONLY | O_LARGEFILE); | |
300 | if (fd==-1) { | |
301 | debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),arq,strerror(errno)); | |
302 | exit(EXIT_FAILURE); | |
303 | } | |
304 | nread=read(fd,buf,sizeof(buf)); | |
305 | if (nread==-1) { | |
306 | debuga(__FILE__,__LINE__,_("Error while reading \"%s\" to guess its type: %s\n"),arq,strerror(errno)); | |
307 | exit(EXIT_FAILURE); | |
308 | } | |
309 | if (nread<3) { | |
310 | debuga(__FILE__,__LINE__,_("File \"%s\" is too small to guess its type\n"),arq); | |
311 | exit(EXIT_FAILURE); | |
312 | } | |
313 | if (lseek(fd,0,SEEK_SET)==-1) { | |
314 | debuga(__FILE__,__LINE__,_("Cannot return to the beginning of file \"%s\": %s"),arq,strerror(errno)); | |
315 | exit(EXIT_FAILURE); | |
316 | } | |
317 | ||
318 | if (buf[0]==0x1F && buf[1]==0x8B && buf[2]==0x08)//gzip file | |
319 | { | |
320 | #ifdef HAVE_ZLIB_H | |
321 | fi=Gzip_Open(fd); | |
322 | #else | |
323 | debuga(__FILE__,__LINE__,_("Sarg was not compiled with gzip support to read file \"%s\"\n"),arq); | |
324 | exit(EXIT_FAILURE); | |
325 | #endif | |
326 | } | |
327 | else if (buf[0]==0x42 && buf[1]==0x5A && buf[2]==0x68)//bzip2 file | |
328 | { | |
329 | #ifdef HAVE_BZLIB_H | |
330 | fi=Bzip_Open(fd); | |
331 | #else | |
332 | debuga(__FILE__,__LINE__,_("Sarg was not compiled with bzip support to read file \"%s\"\n"),arq); | |
333 | exit(EXIT_FAILURE); | |
334 | #endif | |
335 | } | |
275c8c93 FM |
336 | else if (buf[0]==0x1F && (buf[1]==0x9D || buf[1]==0xA0))//LZW and LZH compressed file |
337 | { | |
338 | debuga(__FILE__,__LINE__,_("Support for LZW and LZH compressed files was removed in sarg 2.4.\n" | |
339 | "You can still read such a file with a command like this:\n" | |
340 | " zcat \"%s\" | sarg - [your usual options here]\n" | |
341 | "If you think it is important for sarg to read those files, open a bug ticket at <http://sourceforge.net/p/sarg/bugs/>.\n"), | |
342 | arq); | |
343 | exit(EXIT_FAILURE); | |
344 | } | |
800eafb8 FM |
345 | else //normal file |
346 | { | |
347 | fi=FileObject_FdOpen(fd); | |
d2cd218e FM |
348 | } |
349 | return(fi); | |
25697a35 | 350 | } |