1 /**
2  * @file libcomprex/io.c Input/output functions
3  *
4  * $Id: io.c,v 1.18 2003/01/26 19:54:52 chipx86 Exp $
5  *
6  * @Copyright (C) 2001-2003 The GNUpdate Project.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA  02111-1307, USA.
22  */
23 #include <libcomprex/internal.h>
24 
25 CxFile *
cxMakeFile(const char * filename)26 cxMakeFile(const char *filename)
27 {
28 	CxFile *file;
29 	char   *temp;
30 	struct stat sb;
31 
32 	if (filename == NULL)
33 		return NULL;
34 
35 	if (stat(filename, &sb) != 0)
36 		return NULL;
37 
38 	file = cxNewFile();
39 
40 	temp = cxGetBaseName(filename);
41 	cxSetFileName(file, temp);
42 	free(temp);
43 
44 	cxSetFilePhysicalPath(file, filename);
45 	cxSetFileSize(file, sb.st_size);
46 	cxSetFileMode(file, sb.st_mode);
47 	cxSetFileUid(file,  sb.st_uid);
48 	cxSetFileGid(file,  sb.st_gid);
49 	cxSetFileDate(file, sb.st_mtime);
50 
51 	cxSetFileLocal(file, 1);
52 
53 	return file;
54 }
55 
56 CxFP *
cxOpenFile(const char * path,CxAccessMode mode)57 cxOpenFile(const char *path, CxAccessMode mode)
58 {
59 	CxFP *fp;
60 
61 	if (path == NULL)
62 		return NULL;
63 
64 	cxOpenArchiveOrFile(path, mode, &fp, NULL);
65 
66 	if (fp != NULL)
67 		cxSetFpAccessMode(fp, mode);
68 
69 	return fp;
70 }
71 
72 CxFP *
cxOpenFileHandle(CxFile * file,CxAccessMode mode)73 cxOpenFileHandle(CxFile *file, CxAccessMode mode)
74 {
75 	CxFP *fp;
76 
77 	if (file == NULL)
78 		return NULL;
79 
80 	fp = cxGetFileArchive(file)->module->ops.archive->openFile(file, mode);
81 
82 	if (fp == NULL)
83 		return NULL;
84 
85 	cxSetFpAccessMode(fp, mode);
86 
87 	fp->file = file;
88 	fp->archive = cxGetFileArchive(file);
89 
90 	CX_LINK(file);
91 
92 	return fp;
93 }
94 
95 CxFP *
cxOpenStream(FILE * stream)96 cxOpenStream(FILE *stream)
97 {
98 	CxFP *fp;
99 
100 	if (stream == NULL)
101 		return NULL;
102 
103 	cxInternalOpenStream(stream, CX_MODE_READ_ONLY, &fp, NULL);
104 
105 	if (fp != NULL)
106 		cxSetFpAccessMode(fp, CX_MODE_READ_ONLY);
107 
108 	return fp;
109 }
110 
111 CxFP *
cxOpenBuffer(char * buffer,size_t size)112 cxOpenBuffer(char *buffer, size_t size)
113 {
114 	CxFP *fp;
115 
116 	if (buffer == NULL || size == 0)
117 		return NULL;
118 
119 	cxInternalOpenBuffer(buffer, size, CX_MODE_READ_ONLY, &fp, NULL);
120 
121 	if (fp != NULL)
122 		cxSetFpAccessMode(fp, CX_MODE_READ_ONLY);
123 
124 	return fp;
125 }
126 
127 void
cxClose(CxFP * fp)128 cxClose(CxFP *fp)
129 {
130 	CxFile *file;
131 	CxArchive *archive;
132 
133 	if (fp == NULL || fp->refCount == 0)
134 		return;
135 
136 	CX_UNLINK(fp);
137 
138 	if (fp->refCount > 0)
139 		return;
140 
141 	file = fp->file;
142 	archive = fp->archive;
143 
144 	if (fp->ops.close != NULL)
145 		fp->ops.close(fp);
146 
147 	if (fp->moduleData != NULL)
148 	{
149 		free(fp->moduleData);
150 		fp->moduleData = NULL;
151 	}
152 
153 	free(fp);
154 
155 	if (file != NULL)
156 	{
157 		cxDestroyFile(file);
158 	}
159 }
160 
161 size_t
cxRead(void * ptr,size_t size,size_t nmemb,CxFP * fp)162 cxRead(void *ptr, size_t size, size_t nmemb, CxFP *fp)
163 {
164 	size_t result;
165 
166 	if (fp == NULL || ptr == NULL || (size * nmemb) == 0 ||
167 		fp->ops.read == NULL)
168 	{
169 		return 0;
170 	}
171 
172 	result = fp->ops.read(ptr, size, nmemb, fp);
173 
174 	fp->pos += result * size;
175 
176 #if 0
177 	if (cxTell(fp) == cxGetFileSize(fp->file))
178 	{
179 		fp->eof = 1;
180 	}
181 #endif
182 
183 	return result;
184 }
185 
186 size_t
cxWrite(const void * ptr,size_t size,size_t nmemb,CxFP * fp)187 cxWrite(const void *ptr, size_t size, size_t nmemb, CxFP *fp)
188 {
189 	size_t result;
190 
191 	if (fp == NULL || ptr == NULL || fp->ops.write == NULL ||
192 		(size * nmemb) == 0)
193 	{
194 		return 0;
195 	}
196 
197 	result = fp->ops.write(ptr, size, nmemb, fp);
198 
199 	fp->pos += result * size;
200 
201 	return result;
202 }
203 
204 char *
cxGets(char * buffer,size_t size,CxFP * fp)205 cxGets(char *buffer, size_t size, CxFP *fp)
206 {
207 	size_t result;
208 	char *c;
209 
210 	if (buffer == NULL || fp == NULL || size < 2)
211 		return NULL;
212 
213 	result = cxRead(buffer, 1, size - 1, fp);
214 
215 	if (result == 0)
216 		return NULL;
217 
218 	buffer[size - 1] = '\0';
219 
220 	/* Find either the newline or the NUL */
221 	if ((c = strchr(buffer, '\n')) != NULL)
222 	{
223 		size_t str_len = c - buffer;
224 
225 		*(c + 1) = '\0';
226 
227 		if (str_len < result)
228 		{
229 			/* Skip back to right after the newline. */
230 			cxSeek(fp, str_len - result + 1, SEEK_CUR);
231 		}
232 	}
233 
234 	return buffer;
235 }
236 
237 void
cxSeek(CxFP * fp,long offset,int whence)238 cxSeek(CxFP *fp, long offset, int whence)
239 {
240 	if (fp == NULL || fp->ops.seek == NULL ||
241 		(whence != SEEK_CUR && whence != SEEK_SET && whence != SEEK_END))
242 	{
243 		return;
244 	}
245 
246 	fp->ops.seek(fp, offset, whence);
247 
248 	switch (whence)
249 	{
250 		case SEEK_SET: fp->pos =  offset;                           break;
251 		case SEEK_CUR: fp->pos += offset;                           break;
252 		case SEEK_END: fp->pos =  cxGetFileSize(fp->file) - offset; break;
253 	}
254 
255 	if (cxTell(fp) == cxGetFileSize(fp->file))
256 		fp->eof = 1;
257 	else
258 		fp->eof = 0;
259 }
260 
261 void
cxRewind(CxFP * fp)262 cxRewind(CxFP *fp)
263 {
264 	if (fp == NULL)
265 		return;
266 
267 	cxSeek(fp, 0, SEEK_SET);
268 }
269 
270 long
cxTell(CxFP * fp)271 cxTell(CxFP *fp)
272 {
273 	if (fp == NULL)
274 		return -1;
275 
276 	return fp->pos;
277 }
278 
279 void
cxClearErr(CxFP * fp)280 cxClearErr(CxFP *fp)
281 {
282 	if (fp == NULL)
283 		return;
284 
285 	if (fp->errStr != NULL)
286 		free(fp->errStr);
287 
288 	fp->errStr = NULL;
289 	fp->error  = 0;
290 }
291 
292 int
cxEof(CxFP * fp)293 cxEof(CxFP *fp)
294 {
295 	if (fp == NULL)
296 		return 1;
297 
298 	return (cxTell(fp) >= cxGetFileSize(fp->file));
299 }
300 
301 int
cxError(CxFP * fp)302 cxError(CxFP *fp)
303 {
304 	if (fp == NULL)
305 		return 0;
306 
307 	return fp->error;
308 }
309 
310 const char *
cxStrError(CxFP * fp,int errnum)311 cxStrError(CxFP *fp, int errnum)
312 {
313 	if (fp == NULL)
314 		return NULL;
315 
316 	return fp->errStr;
317 }
318 
319 CxStatus
cxExtractFile(CxFile * file,const char * destPath)320 cxExtractFile(CxFile *file, const char *destPath)
321 {
322 	CxArchive *archive;
323 
324 	archive = cxGetFileArchive(file);
325 
326 	if (archive == NULL)
327 		return CX_ERROR;
328 
329 	/* Let them know we're about to extract this file */
330 	if (archive->ex_callback != NULL)
331 		archive->ex_callback(archive, file, 0, 0);
332 
333 	return cxInternalExtractFile(file, destPath);
334 }
335 
336