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