1 /*
2  * SARG Squid Analysis Report Generator      http://sarg.sourceforge.net
3  *                                                            1998, 2015
4  *
5  * SARG donations:
6  *      please look at http://sarg.sourceforge.net/donations.php
7  * Support:
8  *     http://sourceforge.net/projects/sarg/forums/forum/363374
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 /*!\file
27 \brief Encapsulate a file object
28 
29 The file can be a standard file of the C library or a gzip file or
30 a bzip file.
31 */
32 
33 #include "include/conf.h"
34 #include "include/stringbuffer.h"
35 #include "include/fileobject.h"
36 
37 //! Message describing the last open error.
38 static char LastOpenErrorString[2048]="";
39 //! Message describing the last close error.
40 static char LastCloseErrorString[2048]="";
41 
42 /*!
43  * Read a file using the standard C api.
44  *
45  * \param Data The file object.
46  * \param Buffer The boffer to store the data read.
47  * \param Size How many bytes to read.
48  *
49  * \return The number of bytes read.
50  */
Standard_Read(void * Data,void * Buffer,int Size)51 static int Standard_Read(void *Data,void *Buffer,int Size)
52 {
53 	return(fread(Buffer,1,Size,(FILE *)Data));
54 }
55 
56 /*!
57  * Check if end of file is reached.
58  *
59  * \param Data The file object.
60  *
61  * \return \c True if end of file is reached.
62  */
Standard_Eof(void * Data)63 static int Standard_Eof(void *Data)
64 {
65 	return(feof((FILE *)Data));
66 }
67 
68 /*!
69  * Return to the beginnig of the file.
70  *
71  * \param Data The file object.
72  */
Standard_Rewind(void * Data)73 static void Standard_Rewind(void *Data)
74 {
75 	rewind((FILE *)Data);
76 }
77 
78 /*!
79  * Close a file using the standard C api.
80  *
81  * \param Data File to close.
82  *
83  * \return EOF on error.
84  */
Standard_Close(void * Data)85 static int Standard_Close(void *Data)
86 {
87 	int RetCode=0;
88 
89 	if (fclose((FILE *)Data)==EOF)
90 	{
91 		FileObject_SetLastCloseError(strerror(errno));
92 		RetCode=-1;
93 	}
94 	return(RetCode);
95 }
96 
97 /*!
98  * Open a file for reading using the standard C api.
99  *
100  * \param FileName The file to open.
101  *
102  * \return The object to pass to other function in this module.
103  */
FileObject_Open(const char * FileName)104 FileObject *FileObject_Open(const char *FileName)
105 {
106 	FileObject *File;
107 
108 	LastOpenErrorString[0]='\0';
109 	File=malloc(sizeof(*File));
110 	if (!File)
111 	{
112 		FileObject_SetLastOpenError(_("Not enough memory"));
113 		return(NULL);
114 	}
115 	File->Data=MY_FOPEN(FileName,"r");
116 	if (!File->Data)
117 	{
118 		free(File);
119 		FileObject_SetLastOpenError(strerror(errno));
120 		return(NULL);
121 	}
122 	File->Read=Standard_Read;
123 	File->Eof=Standard_Eof;
124 	File->Rewind=Standard_Rewind;
125 	File->Close=Standard_Close;
126 	return(File);
127 }
128 
129 /*!
130  * Open a file for reading using the standard C api.
131  *
132  * \param FileName The file to open.
133  *
134  * \return The object to pass to other function in this module.
135  */
FileObject_FdOpen(int fd)136 FileObject *FileObject_FdOpen(int fd)
137 {
138 	FileObject *File;
139 
140 	LastOpenErrorString[0]='\0';
141 	File=malloc(sizeof(*File));
142 	if (!File)
143 	{
144 		FileObject_SetLastOpenError(_("Not enough memory"));
145 		return(NULL);
146 	}
147 	File->Data=fdopen(fd,"r");
148 	if (!File->Data)
149 	{
150 		free(File);
151 		FileObject_SetLastOpenError(strerror(errno));
152 		return(NULL);
153 	}
154 	File->Read=Standard_Read;
155 	File->Eof=Standard_Eof;
156 	File->Rewind=Standard_Rewind;
157 	File->Close=Standard_Close;
158 	return(File);
159 }
160 
161 /*!
162  * Read the content of the file using the function identified
163  * by the file object.
164  *
165  * \param File The file object to read.
166  * \param Buffer The buffer to write the data into.
167  * \param Size The maximum number of bytes to read.
168  *
169  * \return The number of bytes read or -1.
170  */
FileObject_Read(FileObject * File,void * Buffer,int Size)171 int FileObject_Read(FileObject *File,void *Buffer,int Size)
172 {
173 	return(File->Read(File->Data,Buffer,Size));
174 }
175 
176 /*!
177  * Check if the end of file is reached.
178  *
179  * \param File The file object.
180  *
181  * \return \c True if end of file is reached.
182  */
FileObject_Eof(FileObject * File)183 int FileObject_Eof(FileObject *File)
184 {
185 	return(File->Eof(File->Data));
186 }
187 
188 /*!
189  * Return to the beginning of the file.
190  *
191  * \param File The file object.
192  */
FileObject_Rewind(FileObject * File)193 void FileObject_Rewind(FileObject *File)
194 {
195 	File->Rewind(File->Data);
196 }
197 
198 /*!
199  * Close the file opened. The memory is freed. The object
200  * cannot be reused after this function returns.
201  *
202  * \param File The file object to close.
203  *
204  * \return Zero on success or -1 on failure.
205  */
FileObject_Close(FileObject * File)206 int FileObject_Close(FileObject *File)
207 {
208 	LastCloseErrorString[0]='\0';
209 	int RetCode=File->Close(File->Data);
210 	free(File);
211 	return(RetCode);
212 }
213 
214 /*!
215  * Set the message returned by the last open error.
216  *
217  * \param Message The message explaining what error occurred
218  * when the file was opened.
219  */
FileObject_SetLastOpenError(const char * Message)220 void FileObject_SetLastOpenError(const char *Message)
221 {
222 	if (Message)
223 	{
224 		strncpy(LastOpenErrorString,Message,sizeof(LastOpenErrorString)-1);
225 		LastOpenErrorString[sizeof(LastOpenErrorString)-1]='\0';
226 	}
227 	else
228 		LastOpenErrorString[0]='\0';
229 }
230 
231 /*!
232  * Get a message explaining the last open error.
233  *
234  * \return The string to display to the user.
235  */
FileObject_GetLastOpenError(void)236 const char *FileObject_GetLastOpenError(void)
237 {
238 	return(LastOpenErrorString);
239 }
240 
241 /*!
242  * Set the message returned by the last close error.
243  *
244  * \param Message The message explaining what error occurred
245  * when the file was closed.
246  */
FileObject_SetLastCloseError(const char * Message)247 void FileObject_SetLastCloseError(const char *Message)
248 {
249 	if (Message)
250 	{
251 		strncpy(LastCloseErrorString,Message,sizeof(LastCloseErrorString)-1);
252 		LastCloseErrorString[sizeof(LastCloseErrorString)-1]='\0';
253 	}
254 	else
255 		LastCloseErrorString[0]='\0';
256 }
257 
258 /*!
259  * Get a message explaining the last close error.
260  *
261  * \return The string to display to the user.
262  */
FileObject_GetLastCloseError(void)263 const char *FileObject_GetLastCloseError(void)
264 {
265 	return(LastCloseErrorString);
266 }
267