/
dir.c
330 lines (259 loc) · 9.46 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
41
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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);
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 */
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",
95
"Ryan C. Gordon <icculus@clutteredmind.org>",
96
97
98
99
"http://www.icculus.org/physfs/",
};
#endif
100
101
102
static PHYSFS_sint64 DIR_read(FileHandle *handle, void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
103
{
104
105
106
PHYSFS_sint64 retval;
retval = __PHYSFS_platformRead(handle->opaque, buffer, objSize, objCount);
return(retval);
107
108
109
} /* DIR_read */
110
111
static PHYSFS_sint64 DIR_write(FileHandle *handle, const void *buffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
112
{
113
114
115
PHYSFS_sint64 retval;
retval = __PHYSFS_platformWrite(handle->opaque, buffer, objSize, objCount);
return(retval);
116
117
118
119
120
} /* DIR_write */
static int DIR_eof(FileHandle *handle)
{
121
return(__PHYSFS_platformEOF(handle->opaque));
122
123
124
} /* DIR_eof */
125
static PHYSFS_sint64 DIR_tell(FileHandle *handle)
126
{
127
return(__PHYSFS_platformTell(handle->opaque));
128
129
130
} /* DIR_tell */
131
static int DIR_seek(FileHandle *handle, PHYSFS_uint64 offset)
132
{
133
return(__PHYSFS_platformSeek(handle->opaque, offset));
134
135
136
} /* DIR_seek */
137
static PHYSFS_sint64 DIR_fileLength(FileHandle *handle)
138
{
139
return(__PHYSFS_platformFileLength(handle->opaque));
140
141
142
} /* DIR_fileLength */
143
144
145
static int DIR_fileClose(FileHandle *handle)
{
/*
146
* we manually flush the buffer, since that's the place a close will
147
* most likely fail, but that will leave the file handle in an undefined
148
* state if it fails. Flush failures we can recover from.
149
*/
150
151
BAIL_IF_MACRO(!__PHYSFS_platformFlush(handle->opaque), NULL, 0);
BAIL_IF_MACRO(!__PHYSFS_platformClose(handle->opaque), NULL, 0);
152
153
154
155
156
157
158
159
160
161
162
163
164
165
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)
{
166
const char *dirsep = PHYSFS_getDirSeparator();
167
DirHandle *retval = NULL;
168
169
size_t namelen = strlen(name);
size_t seplen = strlen(dirsep);
170
171
172
BAIL_IF_MACRO(!DIR_isArchive(name, forWriting),
ERR_UNSUPPORTED_ARCHIVE, NULL);
173
174
retval = (DirHandle *) malloc(sizeof (DirHandle));
175
176
177
178
179
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
retval->opaque = malloc(namelen + seplen + 1);
if (retval->opaque == NULL)
{
free(retval);
180
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
181
182
183
184
185
186
187
} /* 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);
188
189
retval->funcs = &__PHYSFS_DirFunctions_DIR;
190
191
192
193
return(retval);
} /* DIR_openArchive */
194
195
196
static LinkedStringList *DIR_enumerateFiles(DirHandle *h,
const char *dname,
int omitSymLinks)
197
198
199
200
201
{
char *d = __PHYSFS_platformCvtToDependent((char *)(h->opaque),dname,NULL);
LinkedStringList *retval;
BAIL_IF_MACRO(d == NULL, NULL, NULL);
202
retval = __PHYSFS_platformEnumerateFiles(d, omitSymLinks);
203
204
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
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;
237
BAIL_IF_MACRO(f == NULL, NULL, 0);
238
239
240
241
242
243
retval = __PHYSFS_platformIsSymLink(f);
free(f);
return(retval);
} /* DIR_isSymLink */
244
245
246
static FileHandle *doOpen(DirHandle *h, const char *name,
void *(*openFunc)(const char *filename),
const FileFunctions *fileFuncs)
247
248
{
char *f = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
249
void *rc;
250
251
252
253
254
255
256
257
FileHandle *retval;
BAIL_IF_MACRO(f == NULL, NULL, NULL);
retval = (FileHandle *) malloc(sizeof (FileHandle));
if (!retval)
{
free(f);
258
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
259
260
} /* if */
261
rc = openFunc(f);
262
263
264
265
266
free(f);
if (!rc)
{
free(retval);
267
return(NULL);
268
269
270
271
} /* if */
retval->opaque = (void *) rc;
retval->dirHandle = h;
272
273
retval->funcs = fileFuncs;
274
275
276
277
278
279
return(retval);
} /* doOpen */
static FileHandle *DIR_openRead(DirHandle *h, const char *filename)
{
280
281
return(doOpen(h, filename, __PHYSFS_platformOpenRead,
&__PHYSFS_FileFunctions_DIR));
282
283
284
285
286
} /* DIR_openRead */
static FileHandle *DIR_openWrite(DirHandle *h, const char *filename)
{
287
288
return(doOpen(h, filename, __PHYSFS_platformOpenWrite,
&__PHYSFS_FileFunctions_DIRW));
289
290
291
292
293
} /* DIR_openWrite */
static FileHandle *DIR_openAppend(DirHandle *h, const char *filename)
{
294
295
return(doOpen(h, filename, __PHYSFS_platformOpenAppend,
&__PHYSFS_FileFunctions_DIRW));
296
297
298
299
300
301
302
303
304
} /* 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);
305
retval = __PHYSFS_platformDelete(f);
306
307
308
309
310
311
312
313
314
315
316
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);
317
retval = __PHYSFS_platformMkDir(f);
318
319
320
321
322
323
324
325
326
327
328
free(f);
return(retval);
} /* DIR_mkdir */
static void DIR_dirClose(DirHandle *h)
{
free(h->opaque);
free(h);
} /* DIR_dirClose */
329
/* end of dir.c ... */