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