/
dir.c
344 lines (270 loc) · 9.92 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
16
17
#include <string.h>
#include <errno.h>
#include <fcntl.h>
18
#include "physfs.h"
19
20
21
22
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
23
24
25
26
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);
27
static int DIR_eof(FileHandle *handle);
28
29
30
static PHYSFS_sint64 DIR_tell(FileHandle *handle);
static int DIR_seek(FileHandle *handle, PHYSFS_uint64 offset);
static PHYSFS_sint64 DIR_fileLength(FileHandle *handle);
31
32
33
34
35
36
37
38
39
40
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);
static int DIR_isDirectory(DirHandle *h, const char *name);
static int DIR_isSymLink(DirHandle *h, const char *name);
static FileHandle *DIR_openRead(DirHandle *h, const char *filename);
41
static PHYSFS_sint64 DIR_getLastModTime(DirHandle *h, const char *name);
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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);
static const FileFunctions __PHYSFS_FileFunctions_DIR =
{
DIR_read, /* read() method */
NULL, /* write() method */
DIR_eof, /* eof() method */
DIR_tell, /* tell() method */
DIR_seek, /* seek() method */
DIR_fileLength, /* fileLength() method */
DIR_fileClose /* fileClose() method */
};
static const FileFunctions __PHYSFS_FileFunctions_DIRW =
{
NULL, /* read() method */
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 =
{
DIR_isArchive, /* isArchive() method */
DIR_openArchive, /* openArchive() method */
DIR_enumerateFiles, /* enumerateFiles() method */
DIR_exists, /* exists() method */
DIR_isDirectory, /* isDirectory() method */
DIR_isSymLink, /* isSymLink() method */
81
DIR_getLastModTime, /* getLastModTime() method */
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
DIR_openRead, /* openRead() method */
DIR_openWrite, /* openWrite() method */
DIR_openAppend, /* openAppend() method */
DIR_remove, /* remove() method */
DIR_mkdir, /* mkdir() method */
DIR_dirClose /* dirClose() method */
};
/* This doesn't get listed, since it's technically not an archive... */
#if 0
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_DIR =
{
"DIR",
"non-archive directory I/O",
97
"Ryan C. Gordon <icculus@clutteredmind.org>",
98
99
100
101
"http://www.icculus.org/physfs/",
};
#endif
102
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
121
122
} /* DIR_write */
static int DIR_eof(FileHandle *handle)
{
123
return(__PHYSFS_platformEOF(handle->opaque));
124
125
126
} /* DIR_eof */
127
static PHYSFS_sint64 DIR_tell(FileHandle *handle)
128
{
129
return(__PHYSFS_platformTell(handle->opaque));
130
131
132
} /* DIR_tell */
133
static int DIR_seek(FileHandle *handle, PHYSFS_uint64 offset)
134
{
135
return(__PHYSFS_platformSeek(handle->opaque, offset));
136
137
138
} /* DIR_seek */
139
static PHYSFS_sint64 DIR_fileLength(FileHandle *handle)
140
{
141
return(__PHYSFS_platformFileLength(handle->opaque));
142
143
144
} /* DIR_fileLength */
145
146
147
static int DIR_fileClose(FileHandle *handle)
{
/*
148
* we manually flush the buffer, since that's the place a close will
149
* most likely fail, but that will leave the file handle in an undefined
150
* state if it fails. Flush failures we can recover from.
151
*/
152
153
BAIL_IF_MACRO(!__PHYSFS_platformFlush(handle->opaque), NULL, 0);
BAIL_IF_MACRO(!__PHYSFS_platformClose(handle->opaque), NULL, 0);
154
155
156
157
158
159
160
161
162
163
164
165
166
167
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)
{
168
const char *dirsep = PHYSFS_getDirSeparator();
169
DirHandle *retval = NULL;
170
171
size_t namelen = strlen(name);
size_t seplen = strlen(dirsep);
172
173
174
BAIL_IF_MACRO(!DIR_isArchive(name, forWriting),
ERR_UNSUPPORTED_ARCHIVE, NULL);
175
176
retval = (DirHandle *) malloc(sizeof (DirHandle));
177
178
179
180
181
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
retval->opaque = malloc(namelen + seplen + 1);
if (retval->opaque == NULL)
{
free(retval);
182
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
183
184
185
186
187
188
189
} /* 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);
190
191
retval->funcs = &__PHYSFS_DirFunctions_DIR;
192
193
194
195
return(retval);
} /* DIR_openArchive */
196
197
198
static LinkedStringList *DIR_enumerateFiles(DirHandle *h,
const char *dname,
int omitSymLinks)
199
200
201
202
203
{
char *d = __PHYSFS_platformCvtToDependent((char *)(h->opaque),dname,NULL);
LinkedStringList *retval;
BAIL_IF_MACRO(d == NULL, NULL, NULL);
204
retval = __PHYSFS_platformEnumerateFiles(d, omitSymLinks);
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
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 */
static int DIR_isDirectory(DirHandle *h, const char *name)
{
char *d = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
int retval;
BAIL_IF_MACRO(d == NULL, NULL, 0);
retval = __PHYSFS_platformIsDirectory(d);
free(d);
return(retval);
} /* DIR_isDirectory */
static int DIR_isSymLink(DirHandle *h, const char *name)
{
char *f = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
int retval;
239
BAIL_IF_MACRO(f == NULL, NULL, 0);
240
241
242
243
244
245
retval = __PHYSFS_platformIsSymLink(f);
free(f);
return(retval);
} /* DIR_isSymLink */
246
247
248
249
250
251
static PHYSFS_sint64 DIR_getLastModTime(DirHandle *h, const char *name)
{
char *d = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
PHYSFS_sint64 retval;
BAIL_IF_MACRO(d == NULL, NULL, 0);
252
retval = __PHYSFS_platformGetLastModTime(d);
253
254
255
256
257
free(d);
return(retval);
} /* DIR_getLastModTime */
258
259
260
static FileHandle *doOpen(DirHandle *h, const char *name,
void *(*openFunc)(const char *filename),
const FileFunctions *fileFuncs)
261
262
{
char *f = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
263
void *rc;
264
265
266
267
268
269
270
271
FileHandle *retval;
BAIL_IF_MACRO(f == NULL, NULL, NULL);
retval = (FileHandle *) malloc(sizeof (FileHandle));
if (!retval)
{
free(f);
272
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
273
274
} /* if */
275
rc = openFunc(f);
276
277
278
279
280
free(f);
if (!rc)
{
free(retval);
281
return(NULL);
282
283
284
285
} /* if */
retval->opaque = (void *) rc;
retval->dirHandle = h;
286
287
retval->funcs = fileFuncs;
288
289
290
291
292
293
return(retval);
} /* doOpen */
static FileHandle *DIR_openRead(DirHandle *h, const char *filename)
{
294
295
return(doOpen(h, filename, __PHYSFS_platformOpenRead,
&__PHYSFS_FileFunctions_DIR));
296
297
298
299
300
} /* DIR_openRead */
static FileHandle *DIR_openWrite(DirHandle *h, const char *filename)
{
301
302
return(doOpen(h, filename, __PHYSFS_platformOpenWrite,
&__PHYSFS_FileFunctions_DIRW));
303
304
305
306
307
} /* DIR_openWrite */
static FileHandle *DIR_openAppend(DirHandle *h, const char *filename)
{
308
309
return(doOpen(h, filename, __PHYSFS_platformOpenAppend,
&__PHYSFS_FileFunctions_DIRW));
310
311
312
313
314
315
316
317
318
} /* 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);
319
retval = __PHYSFS_platformDelete(f);
320
321
322
323
324
325
326
327
328
329
330
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);
331
retval = __PHYSFS_platformMkDir(f);
332
333
334
335
336
337
338
339
340
341
342
free(f);
return(retval);
} /* DIR_mkdir */
static void DIR_dirClose(DirHandle *h)
{
free(h->opaque);
free(h);
} /* DIR_dirClose */
343
/* end of dir.c ... */