WIP: Vibra support
[neverball] / share / fs_physfs.c
1 /*
2  * Copyright (C) 2003-2010 Neverball authors
3  *
4  * NEVERBALL is  free software; you can redistribute  it and/or modify
5  * it under the  terms of the GNU General  Public License as published
6  * by the Free  Software Foundation; either version 2  of the License,
7  * or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
11  * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
12  * General Public License for more details.
13  */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <assert.h>
18 #include <physfs.h>
19
20 #include "fs.h"
21 #include "dir.h"
22 #include "array.h"
23 #include "common.h"
24
25 /*
26  * This file implements the low-level virtual file system routines
27  * using the PhysicsFS 1.0 API.
28  */
29
30 /*---------------------------------------------------------------------------*/
31
32 struct fs_file
33 {
34     PHYSFS_file *handle;
35 };
36
37 int fs_init(const char *argv0)
38 {
39     if (PHYSFS_init(argv0))
40     {
41         PHYSFS_permitSymbolicLinks(1);
42         return 1;
43     }
44
45     return 0;
46 }
47
48 int fs_quit(void)
49 {
50     return PHYSFS_deinit();
51 }
52
53 const char *fs_error(void)
54 {
55     return PHYSFS_getLastError();
56 }
57
58 /*---------------------------------------------------------------------------*/
59
60 const char *fs_base_dir(void)
61 {
62     return PHYSFS_getBaseDir();
63 }
64
65 int fs_add_path(const char *path)
66 {
67     return PHYSFS_addToSearchPath(path, 0);
68 }
69
70 int fs_set_write_dir(const char *path)
71 {
72     return PHYSFS_setWriteDir(path);
73 }
74
75 const char *fs_get_write_dir(void)
76 {
77     return PHYSFS_getWriteDir();
78 }
79
80 /*---------------------------------------------------------------------------*/
81
82 static List list_files(const char *path)
83 {
84     List list = NULL;
85     char **files, **file;
86
87     if ((files = PHYSFS_enumerateFiles(path)))
88     {
89         for (file = files; *file; file++)
90             list = list_cons(strdup(*file), list);
91
92         PHYSFS_freeList(files);
93     }
94
95     return list;
96 }
97
98 static void free_files(List list)
99 {
100     while (list)
101     {
102         free(list->data);
103         list = list_rest(list);
104     }
105 }
106
107 Array fs_dir_scan(const char *path, int (*filter)(struct dir_item *))
108 {
109     return dir_scan(path, filter, list_files, free_files);
110 }
111
112 void fs_dir_free(Array items)
113 {
114     dir_free(items);
115 }
116
117 /*---------------------------------------------------------------------------*/
118
119 fs_file fs_open(const char *path, const char *mode)
120 {
121     fs_file fh;
122
123     assert((mode[0] == 'r' && !mode[1]) ||
124            (mode[0] == 'w' && (!mode[1] || mode[1] == '+')));
125
126     if ((fh = malloc(sizeof (*fh))))
127     {
128         switch (mode[0])
129         {
130         case 'r':
131             fh->handle = PHYSFS_openRead(path);
132             break;
133
134         case 'w':
135             fh->handle = (mode[1] == '+' ?
136                           PHYSFS_openAppend(path) :
137                           PHYSFS_openWrite(path));
138             break;
139         }
140
141         if (fh->handle)
142         {
143             PHYSFS_setBuffer(fh->handle, 0x2000);
144         }
145         else
146         {
147             free(fh);
148             fh = NULL;
149         }
150     }
151
152     return fh;
153 }
154
155 int fs_close(fs_file fh)
156 {
157     if (PHYSFS_close(fh->handle))
158     {
159         free(fh);
160         return 1;
161     }
162     return 0;
163 }
164
165 /*----------------------------------------------------------------------------*/
166
167 int fs_mkdir(const char *path)
168 {
169     return PHYSFS_mkdir(path);
170 }
171
172 int fs_exists(const char *path)
173 {
174     return PHYSFS_exists(path);
175 }
176
177 int fs_remove(const char *path)
178 {
179     return PHYSFS_delete(path);
180 }
181
182 /*---------------------------------------------------------------------------*/
183
184 int fs_read(void *data, int size, int count, fs_file fh)
185 {
186     return PHYSFS_read(fh->handle, data, size, count);
187 }
188
189 int fs_write(const void *data, int size, int count, fs_file fh)
190 {
191     return PHYSFS_write(fh->handle, data, size, count);
192 }
193
194 int fs_flush(fs_file fh)
195 {
196     return PHYSFS_flush(fh->handle);
197 }
198
199 long fs_tell(fs_file fh)
200 {
201     return PHYSFS_tell(fh->handle);
202 }
203
204 int fs_seek(fs_file fh, long offset, int whence)
205 {
206     PHYSFS_uint64 pos = 0;
207     PHYSFS_sint64 cur = PHYSFS_tell(fh->handle);
208     PHYSFS_sint64 len = PHYSFS_fileLength(fh->handle);
209
210     switch (whence)
211     {
212     case SEEK_SET:
213         pos = offset;
214         break;
215
216     case SEEK_CUR:
217         if (cur < 0)
218             return -1;
219         pos = cur + offset;
220         break;
221
222     case SEEK_END:
223         if (len < 0)
224             return -1;
225         pos = len + offset;
226         break;
227     }
228
229     return PHYSFS_seek(fh->handle, pos);
230 }
231
232 int fs_eof(fs_file fh)
233 {
234     return PHYSFS_eof(fh->handle);
235 }
236
237 int fs_length(fs_file fh)
238 {
239     return PHYSFS_fileLength(fh->handle);
240 }
241
242 /*---------------------------------------------------------------------------*/