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