/
dir.c
376 lines (297 loc) · 11.2 KB
1
2
3
4
5
6
7
8
/*
* Standard directory I/O support routines for PhysicsFS.
*
* Please see the file LICENSE in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
9
10
11
12
#if HAVE_CONFIG_H
# include <config.h>
#endif
13
14
#include <stdio.h>
#include <stdlib.h>
15
#include <string.h>
16
#include "physfs.h"
17
18
19
20
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
21
22
23
24
static PHYSFS_sint64 DIR_read(FileHandle *handle, void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
static PHYSFS_sint64 DIR_write(FileHandle *handle, const void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
25
26
27
28
static PHYSFS_sint64 DIR_dummyRead(FileHandle *handle, void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
static PHYSFS_sint64 DIR_dummyWrite(FileHandle *handle, const void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
29
static int DIR_eof(FileHandle *handle);
30
31
32
static PHYSFS_sint64 DIR_tell(FileHandle *handle);
static int DIR_seek(FileHandle *handle, PHYSFS_uint64 offset);
static PHYSFS_sint64 DIR_fileLength(FileHandle *handle);
33
34
35
36
37
38
39
static int DIR_fileClose(FileHandle *handle);
static int DIR_isArchive(const char *filename, int forWriting);
static DirHandle *DIR_openArchive(const char *name, int forWriting);
static LinkedStringList *DIR_enumerateFiles(DirHandle *h,
const char *dname,
int omitSymLinks);
static int DIR_exists(DirHandle *h, const char *name);
40
41
42
43
static int DIR_isDirectory(DirHandle *h, const char *name, int *fileExists);
static int DIR_isSymLink(DirHandle *h, const char *name, int *fileExists);
static FileHandle *DIR_openRead(DirHandle *h, const char *fnm, int *exist);
static PHYSFS_sint64 DIR_getLastModTime(DirHandle *h, const char *f, int *e);
44
45
46
47
48
49
50
static FileHandle *DIR_openWrite(DirHandle *h, const char *filename);
static FileHandle *DIR_openAppend(DirHandle *h, const char *filename);
static int DIR_remove(DirHandle *h, const char *name);
static int DIR_mkdir(DirHandle *h, const char *name);
static void DIR_dirClose(DirHandle *h);
51
52
53
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_DIR =
{
"",
54
DIR_ARCHIVE_DESCRIPTION,
55
56
57
58
59
"Ryan C. Gordon <icculus@clutteredmind.org>",
"http://icculus.org/physfs/",
};
60
61
static const FileFunctions __PHYSFS_FileFunctions_DIR =
{
62
DIR_read, /* read() method */
63
DIR_dummyWrite, /* write() method */
64
65
66
DIR_eof, /* eof() method */
DIR_tell, /* tell() method */
DIR_seek, /* seek() method */
67
DIR_fileLength, /* fileLength() method */
68
DIR_fileClose /* fileClose() method */
69
70
71
72
73
};
static const FileFunctions __PHYSFS_FileFunctions_DIRW =
{
74
DIR_dummyRead, /* read() method */
75
76
77
78
79
80
81
82
83
84
85
DIR_write, /* write() method */
DIR_eof, /* eof() method */
DIR_tell, /* tell() method */
DIR_seek, /* seek() method */
DIR_fileLength, /* fileLength() method */
DIR_fileClose /* fileClose() method */
};
const DirFunctions __PHYSFS_DirFunctions_DIR =
{
86
&__PHYSFS_ArchiveInfo_DIR,
87
88
89
90
91
92
DIR_isArchive, /* isArchive() method */
DIR_openArchive, /* openArchive() method */
DIR_enumerateFiles, /* enumerateFiles() method */
DIR_exists, /* exists() method */
DIR_isDirectory, /* isDirectory() method */
DIR_isSymLink, /* isSymLink() method */
93
DIR_getLastModTime, /* getLastModTime() method */
94
95
96
97
98
99
100
101
102
DIR_openRead, /* openRead() method */
DIR_openWrite, /* openWrite() method */
DIR_openAppend, /* openAppend() method */
DIR_remove, /* remove() method */
DIR_mkdir, /* mkdir() method */
DIR_dirClose /* dirClose() method */
};
103
104
static PHYSFS_sint64 DIR_read(FileHandle *handle, void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
105
{
106
107
108
PHYSFS_sint64 retval;
retval = __PHYSFS_platformRead(handle->opaque, buffer, objSize, objCount);
return(retval);
109
110
111
} /* DIR_read */
112
113
static PHYSFS_sint64 DIR_write(FileHandle *handle, const void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
114
{
115
116
117
PHYSFS_sint64 retval;
retval = __PHYSFS_platformWrite(handle->opaque, buffer, objSize, objCount);
return(retval);
118
119
120
} /* DIR_write */
121
122
123
124
125
126
127
128
129
130
131
132
133
134
static PHYSFS_sint64 DIR_dummyRead(FileHandle *handle, void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
} /* DIR_dummyRead */
static PHYSFS_sint64 DIR_dummyWrite(FileHandle *handle, const void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
} /* DIR_dummyWrite */
135
136
static int DIR_eof(FileHandle *handle)
{
137
return(__PHYSFS_platformEOF(handle->opaque));
138
139
140
} /* DIR_eof */
141
static PHYSFS_sint64 DIR_tell(FileHandle *handle)
142
{
143
return(__PHYSFS_platformTell(handle->opaque));
144
145
146
} /* DIR_tell */
147
static int DIR_seek(FileHandle *handle, PHYSFS_uint64 offset)
148
{
149
return(__PHYSFS_platformSeek(handle->opaque, offset));
150
151
152
} /* DIR_seek */
153
static PHYSFS_sint64 DIR_fileLength(FileHandle *handle)
154
{
155
return(__PHYSFS_platformFileLength(handle->opaque));
156
157
158
} /* DIR_fileLength */
159
160
161
static int DIR_fileClose(FileHandle *handle)
{
/*
162
* we manually flush the buffer, since that's the place a close will
163
* most likely fail, but that will leave the file handle in an undefined
164
* state if it fails. Flush failures we can recover from.
165
*/
166
167
BAIL_IF_MACRO(!__PHYSFS_platformFlush(handle->opaque), NULL, 0);
BAIL_IF_MACRO(!__PHYSFS_platformClose(handle->opaque), NULL, 0);
168
169
170
171
172
173
174
175
176
177
178
179
180
181
free(handle);
return(1);
} /* DIR_fileClose */
static int DIR_isArchive(const char *filename, int forWriting)
{
/* directories ARE archives in this driver... */
return(__PHYSFS_platformIsDirectory(filename));
} /* DIR_isArchive */
static DirHandle *DIR_openArchive(const char *name, int forWriting)
{
182
const char *dirsep = PHYSFS_getDirSeparator();
183
DirHandle *retval = NULL;
184
185
size_t namelen = strlen(name);
size_t seplen = strlen(dirsep);
186
187
188
BAIL_IF_MACRO(!DIR_isArchive(name, forWriting),
ERR_UNSUPPORTED_ARCHIVE, NULL);
189
190
retval = (DirHandle *) malloc(sizeof (DirHandle));
191
192
193
194
195
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
retval->opaque = malloc(namelen + seplen + 1);
if (retval->opaque == NULL)
{
free(retval);
196
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
197
198
199
200
201
202
203
} /* if */
/* make sure there's a dir separator at the end of the string */
strcpy((char *) (retval->opaque), name);
if (strcmp((name + namelen) - seplen, dirsep) != 0)
strcat((char *) (retval->opaque), dirsep);
204
205
retval->funcs = &__PHYSFS_DirFunctions_DIR;
206
207
208
209
return(retval);
} /* DIR_openArchive */
210
211
212
static LinkedStringList *DIR_enumerateFiles(DirHandle *h,
const char *dname,
int omitSymLinks)
213
214
215
216
217
{
char *d = __PHYSFS_platformCvtToDependent((char *)(h->opaque),dname,NULL);
LinkedStringList *retval;
BAIL_IF_MACRO(d == NULL, NULL, NULL);
218
retval = __PHYSFS_platformEnumerateFiles(d, omitSymLinks);
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
free(d);
return(retval);
} /* DIR_enumerateFiles */
static int DIR_exists(DirHandle *h, const char *name)
{
char *f = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
int retval;
BAIL_IF_MACRO(f == NULL, NULL, 0);
retval = __PHYSFS_platformExists(f);
free(f);
return(retval);
} /* DIR_exists */
236
static int DIR_isDirectory(DirHandle *h, const char *name, int *fileExists)
237
238
{
char *d = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
239
int retval = 0;
240
241
BAIL_IF_MACRO(d == NULL, NULL, 0);
242
243
244
*fileExists = __PHYSFS_platformExists(d);
if (*fileExists)
retval = __PHYSFS_platformIsDirectory(d);
245
246
247
248
249
free(d);
return(retval);
} /* DIR_isDirectory */
250
static int DIR_isSymLink(DirHandle *h, const char *name, int *fileExists)
251
252
{
char *f = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
253
int retval = 0;
254
255
BAIL_IF_MACRO(f == NULL, NULL, 0);
256
257
258
*fileExists = __PHYSFS_platformExists(f);
if (*fileExists)
retval = __PHYSFS_platformIsSymLink(f);
259
260
261
262
263
free(f);
return(retval);
} /* DIR_isSymLink */
264
265
266
static PHYSFS_sint64 DIR_getLastModTime(DirHandle *h,
const char *name,
int *fileExists)
267
268
{
char *d = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
269
PHYSFS_sint64 retval = -1;
270
271
BAIL_IF_MACRO(d == NULL, NULL, 0);
272
273
274
*fileExists = __PHYSFS_platformExists(d);
if (*fileExists)
retval = __PHYSFS_platformGetLastModTime(d);
275
276
277
278
279
free(d);
return(retval);
} /* DIR_getLastModTime */
280
281
static FileHandle *doOpen(DirHandle *h, const char *name,
void *(*openFunc)(const char *filename),
282
int *fileExists, const FileFunctions *fileFuncs)
283
284
{
char *f = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
285
void *rc;
286
287
288
289
FileHandle *retval;
BAIL_IF_MACRO(f == NULL, NULL, NULL);
290
291
292
293
294
295
296
297
298
299
if (fileExists != NULL)
{
*fileExists = __PHYSFS_platformExists(f);
if (!(*fileExists))
{
free(f);
return(NULL);
} /* if */
} /* if */
300
301
302
303
retval = (FileHandle *) malloc(sizeof (FileHandle));
if (!retval)
{
free(f);
304
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
305
306
} /* if */
307
rc = openFunc(f);
308
309
310
311
312
free(f);
if (!rc)
{
free(retval);
313
return(NULL);
314
315
316
317
} /* if */
retval->opaque = (void *) rc;
retval->dirHandle = h;
318
319
retval->funcs = fileFuncs;
320
321
322
323
return(retval);
} /* doOpen */
324
static FileHandle *DIR_openRead(DirHandle *h, const char *fnm, int *exist)
325
{
326
return(doOpen(h, fnm, __PHYSFS_platformOpenRead, exist,
327
&__PHYSFS_FileFunctions_DIR));
328
329
330
331
332
} /* DIR_openRead */
static FileHandle *DIR_openWrite(DirHandle *h, const char *filename)
{
333
return(doOpen(h, filename, __PHYSFS_platformOpenWrite, NULL,
334
&__PHYSFS_FileFunctions_DIRW));
335
336
337
338
339
} /* DIR_openWrite */
static FileHandle *DIR_openAppend(DirHandle *h, const char *filename)
{
340
return(doOpen(h, filename, __PHYSFS_platformOpenAppend, NULL,
341
&__PHYSFS_FileFunctions_DIRW));
342
343
344
345
346
347
348
349
350
} /* DIR_openAppend */
static int DIR_remove(DirHandle *h, const char *name)
{
char *f = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
int retval;
BAIL_IF_MACRO(f == NULL, NULL, 0);
351
retval = __PHYSFS_platformDelete(f);
352
353
354
355
356
357
358
359
360
361
362
free(f);
return(retval);
} /* DIR_remove */
static int DIR_mkdir(DirHandle *h, const char *name)
{
char *f = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
int retval;
BAIL_IF_MACRO(f == NULL, NULL, 0);
363
retval = __PHYSFS_platformMkDir(f);
364
365
366
367
368
369
370
371
372
373
374
free(f);
return(retval);
} /* DIR_mkdir */
static void DIR_dirClose(DirHandle *h)
{
free(h->opaque);
free(h);
} /* DIR_dirClose */
375
/* end of dir.c ... */