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