/
dir.c
312 lines (244 loc) · 9.18 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
static PHYSFS_sint64 DIR_read(fvoid *opaque, void *buffer,
22
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
23
static PHYSFS_sint64 DIR_write(fvoid *opaque, const void *buffer,
24
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
25
26
27
28
29
static int DIR_eof(fvoid *opaque);
static PHYSFS_sint64 DIR_tell(fvoid *opaque);
static int DIR_seek(fvoid *opaque, PHYSFS_uint64 offset);
static PHYSFS_sint64 DIR_fileLength(fvoid *opaque);
static int DIR_fileClose(fvoid *opaque);
30
static int DIR_isArchive(const char *filename, int forWriting);
31
static void *DIR_openArchive(const char *name, int forWriting);
32
static LinkedStringList *DIR_enumerateFiles(dvoid *opaque,
33
34
const char *dname,
int omitSymLinks);
35
36
37
38
39
40
41
42
43
44
static int DIR_exists(dvoid *opaque, const char *name);
static int DIR_isDirectory(dvoid *opaque, const char *name, int *fileExists);
static int DIR_isSymLink(dvoid *opaque, const char *name, int *fileExists);
static fvoid *DIR_openRead(dvoid *opaque, const char *fnm, int *exist);
static PHYSFS_sint64 DIR_getLastModTime(dvoid *opaque, const char *f, int *e);
static fvoid *DIR_openWrite(dvoid *opaque, const char *filename);
static fvoid *DIR_openAppend(dvoid *opaque, const char *filename);
static int DIR_remove(dvoid *opaque, const char *name);
static int DIR_mkdir(dvoid *opaque, const char *name);
static void DIR_dirClose(dvoid *opaque);
45
46
47
48
49
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_DIR =
{
"",
50
DIR_ARCHIVE_DESCRIPTION,
51
52
53
54
55
"Ryan C. Gordon <icculus@clutteredmind.org>",
"http://icculus.org/physfs/",
};
56
57
const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
58
{
59
&__PHYSFS_ArchiveInfo_DIR,
60
61
62
63
64
65
DIR_isArchive, /* isArchive() method */
DIR_openArchive, /* openArchive() method */
DIR_enumerateFiles, /* enumerateFiles() method */
DIR_exists, /* exists() method */
DIR_isDirectory, /* isDirectory() method */
DIR_isSymLink, /* isSymLink() method */
66
DIR_getLastModTime, /* getLastModTime() method */
67
68
69
70
71
DIR_openRead, /* openRead() method */
DIR_openWrite, /* openWrite() method */
DIR_openAppend, /* openAppend() method */
DIR_remove, /* remove() method */
DIR_mkdir, /* mkdir() method */
72
73
74
75
76
77
78
79
DIR_dirClose, /* dirClose() method */
DIR_read, /* 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 */
80
81
82
};
83
static PHYSFS_sint64 DIR_read(fvoid *opaque, void *buffer,
84
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
85
{
86
PHYSFS_sint64 retval;
87
retval = __PHYSFS_platformRead(opaque, buffer, objSize, objCount);
88
return(retval);
89
90
91
} /* DIR_read */
92
static PHYSFS_sint64 DIR_write(fvoid *opaque, const void *buffer,
93
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
94
{
95
PHYSFS_sint64 retval;
96
retval = __PHYSFS_platformWrite(opaque, buffer, objSize, objCount);
97
return(retval);
98
99
100
} /* DIR_write */
101
static int DIR_eof(fvoid *opaque)
102
{
103
return(__PHYSFS_platformEOF(opaque));
104
105
106
} /* DIR_eof */
107
static PHYSFS_sint64 DIR_tell(fvoid *opaque)
108
{
109
return(__PHYSFS_platformTell(opaque));
110
111
112
} /* DIR_tell */
113
static int DIR_seek(fvoid *opaque, PHYSFS_uint64 offset)
114
{
115
return(__PHYSFS_platformSeek(opaque, offset));
116
117
118
} /* DIR_seek */
119
static PHYSFS_sint64 DIR_fileLength(fvoid *opaque)
120
{
121
return(__PHYSFS_platformFileLength(opaque));
122
123
124
} /* DIR_fileLength */
125
static int DIR_fileClose(fvoid *opaque)
126
127
{
/*
128
* we manually flush the buffer, since that's the place a close will
129
* most likely fail, but that will leave the file handle in an undefined
130
* state if it fails. Flush failures we can recover from.
131
*/
132
133
BAIL_IF_MACRO(!__PHYSFS_platformFlush(opaque), NULL, 0);
BAIL_IF_MACRO(!__PHYSFS_platformClose(opaque), NULL, 0);
134
135
136
137
138
139
140
141
142
143
144
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 */
145
static void *DIR_openArchive(const char *name, int forWriting)
146
{
147
const char *dirsep = PHYSFS_getDirSeparator();
148
char *retval = NULL;
149
150
size_t namelen = strlen(name);
size_t seplen = strlen(dirsep);
151
152
/* !!! FIXME: when is this not called right before openArchive? */
153
BAIL_IF_MACRO(!DIR_isArchive(name, forWriting),
154
ERR_UNSUPPORTED_ARCHIVE, 0);
155
156
retval = malloc(namelen + seplen + 1);
157
158
159
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
/* make sure there's a dir separator at the end of the string */
160
strcpy(retval, name);
161
if (strcmp((name + namelen) - seplen, dirsep) != 0)
162
strcat(retval, dirsep);
163
164
165
166
167
return(retval);
} /* DIR_openArchive */
168
static LinkedStringList *DIR_enumerateFiles(dvoid *opaque,
169
170
const char *dname,
int omitSymLinks)
171
{
172
char *d = __PHYSFS_platformCvtToDependent((char *)opaque, dname, NULL);
173
174
175
LinkedStringList *retval;
BAIL_IF_MACRO(d == NULL, NULL, NULL);
176
retval = __PHYSFS_platformEnumerateFiles(d, omitSymLinks);
177
178
179
180
181
free(d);
return(retval);
} /* DIR_enumerateFiles */
182
static int DIR_exists(dvoid *opaque, const char *name)
183
{
184
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
185
186
187
188
189
190
191
192
193
int retval;
BAIL_IF_MACRO(f == NULL, NULL, 0);
retval = __PHYSFS_platformExists(f);
free(f);
return(retval);
} /* DIR_exists */
194
static int DIR_isDirectory(dvoid *opaque, const char *name, int *fileExists)
195
{
196
char *d = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
197
int retval = 0;
198
199
BAIL_IF_MACRO(d == NULL, NULL, 0);
200
201
202
*fileExists = __PHYSFS_platformExists(d);
if (*fileExists)
retval = __PHYSFS_platformIsDirectory(d);
203
204
205
206
207
free(d);
return(retval);
} /* DIR_isDirectory */
208
static int DIR_isSymLink(dvoid *opaque, const char *name, int *fileExists)
209
{
210
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
211
int retval = 0;
212
213
BAIL_IF_MACRO(f == NULL, NULL, 0);
214
215
216
*fileExists = __PHYSFS_platformExists(f);
if (*fileExists)
retval = __PHYSFS_platformIsSymLink(f);
217
218
219
220
221
free(f);
return(retval);
} /* DIR_isSymLink */
222
static PHYSFS_sint64 DIR_getLastModTime(dvoid *opaque,
223
224
const char *name,
int *fileExists)
225
{
226
char *d = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
227
PHYSFS_sint64 retval = -1;
228
229
BAIL_IF_MACRO(d == NULL, NULL, 0);
230
231
232
*fileExists = __PHYSFS_platformExists(d);
if (*fileExists)
retval = __PHYSFS_platformGetLastModTime(d);
233
234
235
236
237
free(d);
return(retval);
} /* DIR_getLastModTime */
238
239
240
static fvoid *doOpen(dvoid *opaque, const char *name,
void *(*openFunc)(const char *filename),
int *fileExists)
241
{
242
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
243
void *rc = NULL;
244
245
246
BAIL_IF_MACRO(f == NULL, NULL, NULL);
247
248
249
250
251
252
253
254
255
256
if (fileExists != NULL)
{
*fileExists = __PHYSFS_platformExists(f);
if (!(*fileExists))
{
free(f);
return(NULL);
} /* if */
} /* if */
257
rc = openFunc(f);
258
259
free(f);
260
return((fvoid *) rc);
261
262
263
} /* doOpen */
264
static fvoid *DIR_openRead(dvoid *opaque, const char *fnm, int *exist)
265
{
266
return(doOpen(opaque, fnm, __PHYSFS_platformOpenRead, exist));
267
268
269
} /* DIR_openRead */
270
static fvoid *DIR_openWrite(dvoid *opaque, const char *filename)
271
{
272
return(doOpen(opaque, filename, __PHYSFS_platformOpenWrite, NULL));
273
274
275
} /* DIR_openWrite */
276
static fvoid *DIR_openAppend(dvoid *opaque, const char *filename)
277
{
278
return(doOpen(opaque, filename, __PHYSFS_platformOpenAppend, NULL));
279
280
281
} /* DIR_openAppend */
282
static int DIR_remove(dvoid *opaque, const char *name)
283
{
284
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
285
286
287
int retval;
BAIL_IF_MACRO(f == NULL, NULL, 0);
288
retval = __PHYSFS_platformDelete(f);
289
290
291
292
293
free(f);
return(retval);
} /* DIR_remove */
294
static int DIR_mkdir(dvoid *opaque, const char *name)
295
{
296
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
297
298
299
int retval;
BAIL_IF_MACRO(f == NULL, NULL, 0);
300
retval = __PHYSFS_platformMkDir(f);
301
302
303
304
305
free(f);
return(retval);
} /* DIR_mkdir */
306
static void DIR_dirClose(dvoid *opaque)
307
{
308
free(opaque);
309
310
} /* DIR_dirClose */
311
/* end of dir.c ... */