/
archiver_dir.c
289 lines (223 loc) · 7.98 KB
1
2
3
/*
* Standard directory I/O support routines for PhysicsFS.
*
4
* Please see the file LICENSE.txt in the source's root directory.
5
6
7
8
9
10
*
* This file written by Ryan C. Gordon.
*/
#include <stdio.h>
#include <stdlib.h>
11
#include <string.h>
12
#include "physfs.h"
13
14
15
16
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
17
static PHYSFS_sint64 DIR_read(fvoid *opaque, void *buffer, PHYSFS_uint64 len)
18
{
19
return __PHYSFS_platformRead(opaque, buffer, len);
20
21
22
} /* DIR_read */
23
static PHYSFS_sint64 DIR_write(fvoid *f, const void *buf, PHYSFS_uint64 len)
24
{
25
return __PHYSFS_platformWrite(f, buf, len);
26
27
28
} /* DIR_write */
29
static int DIR_eof(fvoid *opaque)
30
{
31
return __PHYSFS_platformEOF(opaque);
32
33
34
} /* DIR_eof */
35
static PHYSFS_sint64 DIR_tell(fvoid *opaque)
36
{
37
return __PHYSFS_platformTell(opaque);
38
39
40
} /* DIR_tell */
41
static int DIR_seek(fvoid *opaque, PHYSFS_uint64 offset)
42
{
43
return __PHYSFS_platformSeek(opaque, offset);
44
45
46
} /* DIR_seek */
47
static PHYSFS_sint64 DIR_fileLength(fvoid *opaque)
48
{
49
return __PHYSFS_platformFileLength(opaque);
50
51
52
} /* DIR_fileLength */
53
static int DIR_fileClose(fvoid *opaque)
54
55
{
/*
56
* we manually flush the buffer, since that's the place a close will
57
* most likely fail, but that will leave the file handle in an undefined
58
* state if it fails. Flush failures we can recover from.
59
*/
60
61
BAIL_IF_MACRO(!__PHYSFS_platformFlush(opaque), NULL, 0);
BAIL_IF_MACRO(!__PHYSFS_platformClose(opaque), NULL, 0);
62
return 1;
63
64
65
66
67
68
} /* DIR_fileClose */
static int DIR_isArchive(const char *filename, int forWriting)
{
/* directories ARE archives in this driver... */
69
return __PHYSFS_platformIsDirectory(filename);
70
71
72
} /* DIR_isArchive */
73
static void *DIR_openArchive(const char *name, int forWriting)
74
{
75
const char *dirsep = PHYSFS_getDirSeparator();
76
char *retval = NULL;
77
78
size_t namelen = strlen(name);
size_t seplen = strlen(dirsep);
79
80
/* !!! FIXME: when is this not called right before openArchive? */
81
BAIL_IF_MACRO(!DIR_isArchive(name, forWriting),
82
ERR_UNSUPPORTED_ARCHIVE, 0);
83
84
retval = allocator.Malloc(namelen + seplen + 1);
85
86
87
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
/* make sure there's a dir separator at the end of the string */
88
strcpy(retval, name);
89
if (strcmp((name + namelen) - seplen, dirsep) != 0)
90
strcat(retval, dirsep);
91
92
return retval;
93
94
95
} /* DIR_openArchive */
96
static void DIR_enumerateFiles(dvoid *opaque, const char *dname,
97
98
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
99
{
100
char *d = __PHYSFS_platformCvtToDependent((char *)opaque, dname, NULL);
101
102
if (d != NULL)
{
103
104
__PHYSFS_platformEnumerateFiles(d, omitSymLinks, cb,
origdir, callbackdata);
105
allocator.Free(d);
106
} /* if */
107
108
109
} /* DIR_enumerateFiles */
110
static int DIR_exists(dvoid *opaque, const char *name)
111
{
112
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
113
114
115
116
int retval;
BAIL_IF_MACRO(f == NULL, NULL, 0);
retval = __PHYSFS_platformExists(f);
117
allocator.Free(f);
118
return retval;
119
120
121
} /* DIR_exists */
122
static int DIR_isDirectory(dvoid *opaque, const char *name, int *fileExists)
123
{
124
char *d = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
125
int retval = 0;
126
127
BAIL_IF_MACRO(d == NULL, NULL, 0);
128
129
130
*fileExists = __PHYSFS_platformExists(d);
if (*fileExists)
retval = __PHYSFS_platformIsDirectory(d);
131
allocator.Free(d);
132
return retval;
133
134
135
} /* DIR_isDirectory */
136
static int DIR_isSymLink(dvoid *opaque, const char *name, int *fileExists)
137
{
138
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
139
int retval = 0;
140
141
BAIL_IF_MACRO(f == NULL, NULL, 0);
142
143
144
*fileExists = __PHYSFS_platformExists(f);
if (*fileExists)
retval = __PHYSFS_platformIsSymLink(f);
145
allocator.Free(f);
146
return retval;
147
148
149
} /* DIR_isSymLink */
150
static PHYSFS_sint64 DIR_getLastModTime(dvoid *opaque,
151
152
const char *name,
int *fileExists)
153
{
154
char *d = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
155
PHYSFS_sint64 retval = -1;
156
157
BAIL_IF_MACRO(d == NULL, NULL, 0);
158
159
160
*fileExists = __PHYSFS_platformExists(d);
if (*fileExists)
retval = __PHYSFS_platformGetLastModTime(d);
161
allocator.Free(d);
162
return retval;
163
164
165
} /* DIR_getLastModTime */
166
167
168
static fvoid *doOpen(dvoid *opaque, const char *name,
void *(*openFunc)(const char *filename),
int *fileExists)
169
{
170
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
171
void *rc = NULL;
172
173
174
BAIL_IF_MACRO(f == NULL, NULL, NULL);
175
176
177
178
179
if (fileExists != NULL)
{
*fileExists = __PHYSFS_platformExists(f);
if (!(*fileExists))
{
180
allocator.Free(f);
181
return NULL;
182
183
184
} /* if */
} /* if */
185
rc = openFunc(f);
186
allocator.Free(f);
187
188
return ((fvoid *) rc);
189
190
191
} /* doOpen */
192
static fvoid *DIR_openRead(dvoid *opaque, const char *fnm, int *exist)
193
{
194
return doOpen(opaque, fnm, __PHYSFS_platformOpenRead, exist);
195
196
197
} /* DIR_openRead */
198
static fvoid *DIR_openWrite(dvoid *opaque, const char *filename)
199
{
200
return doOpen(opaque, filename, __PHYSFS_platformOpenWrite, NULL);
201
202
203
} /* DIR_openWrite */
204
static fvoid *DIR_openAppend(dvoid *opaque, const char *filename)
205
{
206
return doOpen(opaque, filename, __PHYSFS_platformOpenAppend, NULL);
207
208
209
} /* DIR_openAppend */
210
static int DIR_remove(dvoid *opaque, const char *name)
211
{
212
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
213
214
215
int retval;
BAIL_IF_MACRO(f == NULL, NULL, 0);
216
retval = __PHYSFS_platformDelete(f);
217
allocator.Free(f);
218
return retval;
219
220
221
} /* DIR_remove */
222
static int DIR_mkdir(dvoid *opaque, const char *name)
223
{
224
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
225
226
227
int retval;
BAIL_IF_MACRO(f == NULL, NULL, 0);
228
retval = __PHYSFS_platformMkDir(f);
229
allocator.Free(f);
230
return retval;
231
232
233
} /* DIR_mkdir */
234
static void DIR_dirClose(dvoid *opaque)
235
{
236
allocator.Free(opaque);
237
238
} /* DIR_dirClose */
239
240
static int DIR_stat(dvoid *opaque, const char *name, int *exists,
241
242
243
244
245
246
247
248
249
250
251
PHYSFS_Stat *stat)
{
char *d = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
int retval = 0;
BAIL_IF_MACRO(d == NULL, NULL, 0);
retval = __PHYSFS_platformStat(d, exists, stat);
allocator.Free(d);
return retval;
} /* DIR_stat */
252
253
254
255
256
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_DIR =
{
"",
DIR_ARCHIVE_DESCRIPTION,
257
"Ryan C. Gordon <icculus@icculus.org>",
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
"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 */
284
285
DIR_fileClose, /* fileClose() method */
DIR_stat /* stat() method */
286
287
};
288
/* end of dir.c ... */