author | koda |
Tue, 11 Jun 2013 02:46:59 +0200 | |
branch | 0.9.19 |
changeset 9126 | 63bf1f4f40f8 |
parent 9110 | 3883b5dc600c |
child 10017 | de822cd3df3a |
permissions | -rw-r--r-- |
7768 | 1 |
/* |
2 |
* Internal function/structure declaration. Do NOT include in your |
|
3 |
* application. |
|
4 |
* |
|
5 |
* Please see the file LICENSE.txt in the source's root directory. |
|
6 |
* |
|
7 |
* This file written by Ryan C. Gordon. |
|
8 |
*/ |
|
9 |
||
10 |
#ifndef _INCLUDE_PHYSFS_INTERNAL_H_ |
|
11 |
#define _INCLUDE_PHYSFS_INTERNAL_H_ |
|
12 |
||
13 |
#ifndef __PHYSICSFS_INTERNAL__ |
|
14 |
#error Do not include this header from your applications. |
|
15 |
#endif |
|
16 |
||
17 |
#include "physfs.h" |
|
18 |
||
19 |
/* The holy trinity. */ |
|
20 |
#include <stdio.h> |
|
21 |
#include <stdlib.h> |
|
22 |
#include <string.h> |
|
23 |
||
24 |
#include "physfs_platforms.h" |
|
25 |
||
26 |
#include <assert.h> |
|
27 |
||
28 |
/* !!! FIXME: remove this when revamping stack allocation code... */ |
|
29 |
#if defined(_MSC_VER) || defined(__MINGW32__) |
|
30 |
#include <malloc.h> |
|
31 |
#endif |
|
32 |
||
33 |
#if PHYSFS_PLATFORM_SOLARIS |
|
34 |
#include <alloca.h> |
|
35 |
#endif |
|
36 |
||
37 |
#ifdef __cplusplus |
|
38 |
extern "C" { |
|
39 |
#endif |
|
40 |
||
41 |
#ifdef __GNUC__ |
|
42 |
#define PHYSFS_MINIMUM_GCC_VERSION(major, minor) \ |
|
43 |
( ((__GNUC__ << 16) + __GNUC_MINOR__) >= (((major) << 16) + (minor)) ) |
|
44 |
#else |
|
45 |
#define PHYSFS_MINIMUM_GCC_VERSION(major, minor) (0) |
|
46 |
#endif |
|
47 |
||
48 |
#ifdef __cplusplus |
|
49 |
/* C++ always has a real inline keyword. */ |
|
50 |
#elif (defined macintosh) && !(defined __MWERKS__) |
|
51 |
# define inline |
|
52 |
#elif (defined _MSC_VER) |
|
53 |
# define inline __inline |
|
54 |
#endif |
|
55 |
||
56 |
#if PHYSFS_PLATFORM_LINUX && !defined(_FILE_OFFSET_BITS) |
|
57 |
#define _FILE_OFFSET_BITS 64 |
|
58 |
#endif |
|
59 |
||
60 |
/* |
|
61 |
* Interface for small allocations. If you need a little scratch space for |
|
62 |
* a throwaway buffer or string, use this. It will make small allocations |
|
63 |
* on the stack if possible, and use allocator.Malloc() if they are too |
|
64 |
* large. This helps reduce malloc pressure. |
|
65 |
* There are some rules, though: |
|
66 |
* NEVER return a pointer from this, as stack-allocated buffers go away |
|
67 |
* when your function returns. |
|
68 |
* NEVER allocate in a loop, as stack-allocated pointers will pile up. Call |
|
69 |
* a function that uses smallAlloc from your loop, so the allocation can |
|
70 |
* free each time. |
|
71 |
* NEVER call smallAlloc with any complex expression (it's a macro that WILL |
|
72 |
* have side effects...it references the argument multiple times). Use a |
|
73 |
* variable or a literal. |
|
74 |
* NEVER free a pointer from this with anything but smallFree. It will not |
|
75 |
* be a valid pointer to the allocator, regardless of where the memory came |
|
76 |
* from. |
|
77 |
* NEVER realloc a pointer from this. |
|
78 |
* NEVER forget to use smallFree: it may not be a pointer from the stack. |
|
79 |
* NEVER forget to check for NULL...allocation can fail here, of course! |
|
80 |
*/ |
|
81 |
#define __PHYSFS_SMALLALLOCTHRESHOLD 256 |
|
82 |
void *__PHYSFS_initSmallAlloc(void *ptr, PHYSFS_uint64 len); |
|
83 |
||
84 |
#define __PHYSFS_smallAlloc(bytes) ( \ |
|
85 |
__PHYSFS_initSmallAlloc( \ |
|
86 |
(((bytes) < __PHYSFS_SMALLALLOCTHRESHOLD) ? \ |
|
87 |
alloca((size_t)((bytes)+sizeof(void*))) : NULL), (bytes)) \ |
|
88 |
) |
|
89 |
||
90 |
void __PHYSFS_smallFree(void *ptr); |
|
91 |
||
92 |
||
93 |
/* Use the allocation hooks. */ |
|
94 |
#define malloc(x) Do not use malloc() directly. |
|
95 |
#define realloc(x, y) Do not use realloc() directly. |
|
96 |
#define free(x) Do not use free() directly. |
|
97 |
/* !!! FIXME: add alloca check here. */ |
|
98 |
||
99 |
#ifndef PHYSFS_SUPPORTS_ZIP |
|
100 |
#define PHYSFS_SUPPORTS_ZIP 1 |
|
101 |
#endif |
|
102 |
#ifndef PHYSFS_SUPPORTS_7Z |
|
103 |
#define PHYSFS_SUPPORTS_7Z 0 |
|
104 |
#endif |
|
105 |
#ifndef PHYSFS_SUPPORTS_GRP |
|
106 |
#define PHYSFS_SUPPORTS_GRP 0 |
|
107 |
#endif |
|
108 |
#ifndef PHYSFS_SUPPORTS_HOG |
|
109 |
#define PHYSFS_SUPPORTS_HOG 0 |
|
110 |
#endif |
|
111 |
#ifndef PHYSFS_SUPPORTS_MVL |
|
112 |
#define PHYSFS_SUPPORTS_MVL 0 |
|
113 |
#endif |
|
114 |
#ifndef PHYSFS_SUPPORTS_WAD |
|
115 |
#define PHYSFS_SUPPORTS_WAD 0 |
|
116 |
#endif |
|
117 |
#ifndef PHYSFS_SUPPORTS_ISO9660 |
|
118 |
#define PHYSFS_SUPPORTS_ISO9660 0 |
|
119 |
#endif |
|
120 |
||
121 |
/* The latest supported PHYSFS_Io::version value. */ |
|
122 |
#define CURRENT_PHYSFS_IO_API_VERSION 0 |
|
123 |
||
124 |
/* Opaque data for file and dir handlers... */ |
|
125 |
typedef void PHYSFS_Dir; |
|
126 |
||
127 |
typedef struct |
|
128 |
{ |
|
129 |
/* |
|
130 |
* Basic info about this archiver... |
|
131 |
*/ |
|
132 |
const PHYSFS_ArchiveInfo info; |
|
133 |
||
134 |
||
135 |
/* |
|
136 |
* DIRECTORY ROUTINES: |
|
137 |
* These functions are for dir handles. Generate a handle with the |
|
138 |
* openArchive() method, then pass it as the "opaque" PHYSFS_Dir to the |
|
139 |
* others. |
|
140 |
* |
|
141 |
* Symlinks should always be followed (except in stat()); PhysicsFS will |
|
142 |
* use the stat() method to check for symlinks and make a judgement on |
|
143 |
* whether to continue to call other methods based on that. |
|
144 |
*/ |
|
145 |
||
146 |
/* |
|
147 |
* Open a dirhandle for dir/archive data provided by (io). |
|
148 |
* (name) is a filename associated with (io), but doesn't necessarily |
|
149 |
* map to anything, let alone a real filename. This possibly- |
|
150 |
* meaningless name is in platform-dependent notation. |
|
151 |
* (forWrite) is non-zero if this is to be used for |
|
152 |
* the write directory, and zero if this is to be used for an |
|
153 |
* element of the search path. |
|
154 |
* Returns NULL on failure. We ignore any error code you set here. |
|
155 |
* Returns non-NULL on success. The pointer returned will be |
|
156 |
* passed as the "opaque" parameter for later calls. |
|
157 |
*/ |
|
158 |
PHYSFS_Dir *(*openArchive)(PHYSFS_Io *io, const char *name, int forWrite); |
|
159 |
||
160 |
/* |
|
161 |
* List all files in (dirname). Each file is passed to (cb), |
|
162 |
* where a copy is made if appropriate, so you should dispose of |
|
163 |
* it properly upon return from the callback. |
|
164 |
* You should omit symlinks if (omitSymLinks) is non-zero. |
|
165 |
* If you have a failure, report as much as you can. |
|
166 |
* (dirname) is in platform-independent notation. |
|
167 |
*/ |
|
168 |
void (*enumerateFiles)(PHYSFS_Dir *opaque, const char *dirname, |
|
169 |
int omitSymLinks, PHYSFS_EnumFilesCallback cb, |
|
170 |
const char *origdir, void *callbackdata); |
|
171 |
||
172 |
/* |
|
173 |
* Open file for reading. |
|
174 |
* This filename, (fnm), is in platform-independent notation. |
|
175 |
* If you can't handle multiple opens of the same file, |
|
176 |
* you can opt to fail for the second call. |
|
177 |
* Fail if the file does not exist. |
|
178 |
* Returns NULL on failure, and calls __PHYSFS_setError(). |
|
179 |
* Returns non-NULL on success. The pointer returned will be |
|
180 |
* passed as the "opaque" parameter for later file calls. |
|
181 |
* |
|
182 |
* Regardless of success or failure, please set *exists to |
|
183 |
* non-zero if the file existed (even if it's a broken symlink!), |
|
184 |
* zero if it did not. |
|
185 |
*/ |
|
186 |
PHYSFS_Io *(*openRead)(PHYSFS_Dir *opaque, const char *fnm, int *exists); |
|
187 |
||
188 |
/* |
|
189 |
* Open file for writing. |
|
190 |
* If the file does not exist, it should be created. If it exists, |
|
191 |
* it should be truncated to zero bytes. The writing |
|
192 |
* offset should be the start of the file. |
|
193 |
* This filename is in platform-independent notation. |
|
194 |
* If you can't handle multiple opens of the same file, |
|
195 |
* you can opt to fail for the second call. |
|
196 |
* Returns NULL on failure, and calls __PHYSFS_setError(). |
|
197 |
* Returns non-NULL on success. The pointer returned will be |
|
198 |
* passed as the "opaque" parameter for later file calls. |
|
199 |
*/ |
|
200 |
PHYSFS_Io *(*openWrite)(PHYSFS_Dir *opaque, const char *filename); |
|
201 |
||
202 |
/* |
|
203 |
* Open file for appending. |
|
204 |
* If the file does not exist, it should be created. The writing |
|
205 |
* offset should be the end of the file. |
|
206 |
* This filename is in platform-independent notation. |
|
207 |
* If you can't handle multiple opens of the same file, |
|
208 |
* you can opt to fail for the second call. |
|
209 |
* Returns NULL on failure, and calls __PHYSFS_setError(). |
|
210 |
* Returns non-NULL on success. The pointer returned will be |
|
211 |
* passed as the "opaque" parameter for later file calls. |
|
212 |
*/ |
|
213 |
PHYSFS_Io *(*openAppend)(PHYSFS_Dir *opaque, const char *filename); |
|
214 |
||
215 |
/* |
|
216 |
* Delete a file in the archive/directory. |
|
217 |
* Return non-zero on success, zero on failure. |
|
218 |
* This filename is in platform-independent notation. |
|
219 |
* This method may be NULL. |
|
220 |
* On failure, call __PHYSFS_setError(). |
|
221 |
*/ |
|
222 |
int (*remove)(PHYSFS_Dir *opaque, const char *filename); |
|
223 |
||
224 |
/* |
|
225 |
* Create a directory in the archive/directory. |
|
226 |
* If the application is trying to make multiple dirs, PhysicsFS |
|
227 |
* will split them up into multiple calls before passing them to |
|
228 |
* your driver. |
|
229 |
* Return non-zero on success, zero on failure. |
|
230 |
* This filename is in platform-independent notation. |
|
231 |
* This method may be NULL. |
|
232 |
* On failure, call __PHYSFS_setError(). |
|
233 |
*/ |
|
234 |
int (*mkdir)(PHYSFS_Dir *opaque, const char *filename); |
|
235 |
||
236 |
/* |
|
237 |
* Close directories/archives, and free any associated memory, |
|
238 |
* including the original PHYSFS_Io and (opaque) itself, if |
|
239 |
* applicable. Implementation can assume that it won't be called if |
|
240 |
* there are still files open from this archive. |
|
241 |
*/ |
|
242 |
void (*closeArchive)(PHYSFS_Dir *opaque); |
|
243 |
||
244 |
/* |
|
245 |
* Obtain basic file metadata. |
|
246 |
* Returns non-zero on success, zero on failure. |
|
247 |
* On failure, call __PHYSFS_setError(). |
|
248 |
*/ |
|
249 |
int (*stat)(PHYSFS_Dir *opaque, const char *fn, |
|
250 |
int *exists, PHYSFS_Stat *stat); |
|
251 |
} PHYSFS_Archiver; |
|
252 |
||
253 |
||
254 |
/* |
|
255 |
* Call this to set the message returned by PHYSFS_getLastError(). |
|
256 |
* Please only use the ERR_* constants above, or add new constants to the |
|
257 |
* above group, but I want these all in one place. |
|
258 |
* |
|
259 |
* Calling this with a NULL argument is a safe no-op. |
|
260 |
*/ |
|
261 |
void __PHYSFS_setError(const PHYSFS_ErrorCode err); |
|
262 |
||
263 |
||
264 |
/* This byteorder stuff was lifted from SDL. http://www.libsdl.org/ */ |
|
265 |
#define PHYSFS_LIL_ENDIAN 1234 |
|
266 |
#define PHYSFS_BIG_ENDIAN 4321 |
|
267 |
||
268 |
#if defined(__i386__) || defined(__ia64__) || \ |
|
269 |
defined(_M_IX86) || defined(_M_IA64) || defined(_M_X64) || \ |
|
270 |
(defined(__alpha__) || defined(__alpha)) || \ |
|
271 |
defined(__arm__) || defined(ARM) || \ |
|
272 |
(defined(__mips__) && defined(__MIPSEL__)) || \ |
|
273 |
defined(__SYMBIAN32__) || \ |
|
274 |
defined(__x86_64__) || \ |
|
275 |
defined(__LITTLE_ENDIAN__) |
|
276 |
#define PHYSFS_BYTEORDER PHYSFS_LIL_ENDIAN |
|
277 |
#else |
|
278 |
#define PHYSFS_BYTEORDER PHYSFS_BIG_ENDIAN |
|
279 |
#endif |
|
280 |
||
281 |
||
282 |
/* |
|
283 |
* When sorting the entries in an archive, we use a modified QuickSort. |
|
284 |
* When there are less then PHYSFS_QUICKSORT_THRESHOLD entries left to sort, |
|
285 |
* we switch over to a BubbleSort for the remainder. Tweak to taste. |
|
286 |
* |
|
287 |
* You can override this setting by defining PHYSFS_QUICKSORT_THRESHOLD |
|
288 |
* before #including "physfs_internal.h". |
|
289 |
*/ |
|
290 |
#ifndef PHYSFS_QUICKSORT_THRESHOLD |
|
291 |
#define PHYSFS_QUICKSORT_THRESHOLD 4 |
|
292 |
#endif |
|
293 |
||
294 |
/* |
|
295 |
* Sort an array (or whatever) of (max) elements. This uses a mixture of |
|
296 |
* a QuickSort and BubbleSort internally. |
|
297 |
* (cmpfn) is used to determine ordering, and (swapfn) does the actual |
|
298 |
* swapping of elements in the list. |
|
299 |
* |
|
300 |
* See zip.c for an example. |
|
301 |
*/ |
|
302 |
void __PHYSFS_sort(void *entries, size_t max, |
|
303 |
int (*cmpfn)(void *, size_t, size_t), |
|
304 |
void (*swapfn)(void *, size_t, size_t)); |
|
305 |
||
306 |
/* |
|
307 |
* This isn't a formal error code, it's just for BAIL_MACRO. |
|
308 |
* It means: there was an error, but someone else already set it for us. |
|
309 |
*/ |
|
310 |
#define ERRPASS PHYSFS_ERR_OK |
|
311 |
||
312 |
/* These get used all over for lessening code clutter. */ |
|
313 |
#define BAIL_MACRO(e, r) do { if (e) __PHYSFS_setError(e); return r; } while (0) |
|
314 |
#define BAIL_IF_MACRO(c, e, r) do { if (c) { if (e) __PHYSFS_setError(e); return r; } } while (0) |
|
315 |
#define BAIL_MACRO_MUTEX(e, m, r) do { if (e) __PHYSFS_setError(e); __PHYSFS_platformReleaseMutex(m); return r; } while (0) |
|
316 |
#define BAIL_IF_MACRO_MUTEX(c, e, m, r) do { if (c) { if (e) __PHYSFS_setError(e); __PHYSFS_platformReleaseMutex(m); return r; } } while (0) |
|
317 |
#define GOTO_MACRO(e, g) do { if (e) __PHYSFS_setError(e); goto g; } while (0) |
|
318 |
#define GOTO_IF_MACRO(c, e, g) do { if (c) { if (e) __PHYSFS_setError(e); goto g; } } while (0) |
|
319 |
#define GOTO_MACRO_MUTEX(e, m, g) do { if (e) __PHYSFS_setError(e); __PHYSFS_platformReleaseMutex(m); goto g; } while (0) |
|
320 |
#define GOTO_IF_MACRO_MUTEX(c, e, m, g) do { if (c) { if (e) __PHYSFS_setError(e); __PHYSFS_platformReleaseMutex(m); goto g; } } while (0) |
|
321 |
||
322 |
#define __PHYSFS_ARRAYLEN(x) ( (sizeof (x)) / (sizeof (x[0])) ) |
|
323 |
||
324 |
#ifdef PHYSFS_NO_64BIT_SUPPORT |
|
9126
63bf1f4f40f8
backout a few commits that desyncronized translations and broke physfs on 32 bit
koda
parents:
9110
diff
changeset
|
325 |
#define __PHYSFS_SI64(x) ((PHYSFS_sint64) (x)) |
63bf1f4f40f8
backout a few commits that desyncronized translations and broke physfs on 32 bit
koda
parents:
9110
diff
changeset
|
326 |
#define __PHYSFS_UI64(x) ((PHYSFS_uint64) (x)) |
7768 | 327 |
#elif (defined __GNUC__) |
328 |
#define __PHYSFS_SI64(x) x##LL |
|
329 |
#define __PHYSFS_UI64(x) x##ULL |
|
330 |
#elif (defined _MSC_VER) |
|
331 |
#define __PHYSFS_SI64(x) x##i64 |
|
332 |
#define __PHYSFS_UI64(x) x##ui64 |
|
333 |
#else |
|
334 |
#define __PHYSFS_SI64(x) ((PHYSFS_sint64) (x)) |
|
335 |
#define __PHYSFS_UI64(x) ((PHYSFS_uint64) (x)) |
|
336 |
#endif |
|
337 |
||
338 |
||
339 |
/* |
|
340 |
* Check if a ui64 will fit in the platform's address space. |
|
341 |
* The initial sizeof check will optimize this macro out entirely on |
|
342 |
* 64-bit (and larger?!) platforms, and the other condition will |
|
343 |
* return zero or non-zero if the variable will fit in the platform's |
|
344 |
* size_t, suitable to pass to malloc. This is kinda messy, but effective. |
|
345 |
*/ |
|
346 |
#define __PHYSFS_ui64FitsAddressSpace(s) ( \ |
|
347 |
(sizeof (PHYSFS_uint64) <= sizeof (size_t)) || \ |
|
348 |
((s) < (__PHYSFS_UI64(0xFFFFFFFFFFFFFFFF) >> (64-(sizeof(size_t)*8)))) \ |
|
349 |
) |
|
350 |
||
351 |
||
352 |
/* |
|
353 |
* This is a strcasecmp() or stricmp() replacement that expects both strings |
|
354 |
* to be in UTF-8 encoding. It will do "case folding" to decide if the |
|
355 |
* Unicode codepoints in the strings match. |
|
356 |
* |
|
357 |
* It will report which string is "greater than" the other, but be aware that |
|
358 |
* this doesn't necessarily mean anything: 'a' may be "less than" 'b', but |
|
359 |
* a random Kanji codepoint has no meaningful alphabetically relationship to |
|
360 |
* a Greek Lambda, but being able to assign a reliable "value" makes sorting |
|
361 |
* algorithms possible, if not entirely sane. Most cases should treat the |
|
362 |
* return value as "equal" or "not equal". |
|
363 |
*/ |
|
364 |
int __PHYSFS_utf8stricmp(const char *s1, const char *s2); |
|
365 |
||
366 |
/* |
|
367 |
* This works like __PHYSFS_utf8stricmp(), but takes a character (NOT BYTE |
|
368 |
* COUNT) argument, like strcasencmp(). |
|
369 |
*/ |
|
370 |
int __PHYSFS_utf8strnicmp(const char *s1, const char *s2, PHYSFS_uint32 l); |
|
371 |
||
372 |
/* |
|
373 |
* stricmp() that guarantees to only work with low ASCII. The C runtime |
|
374 |
* stricmp() might try to apply a locale/codepage/etc, which we don't want. |
|
375 |
*/ |
|
376 |
int __PHYSFS_stricmpASCII(const char *s1, const char *s2); |
|
377 |
||
378 |
/* |
|
379 |
* strnicmp() that guarantees to only work with low ASCII. The C runtime |
|
380 |
* strnicmp() might try to apply a locale/codepage/etc, which we don't want. |
|
381 |
*/ |
|
382 |
int __PHYSFS_strnicmpASCII(const char *s1, const char *s2, PHYSFS_uint32 l); |
|
383 |
||
384 |
||
385 |
/* |
|
386 |
* The current allocator. Not valid before PHYSFS_init is called! |
|
387 |
*/ |
|
388 |
extern PHYSFS_Allocator __PHYSFS_AllocatorHooks; |
|
389 |
||
390 |
/* convenience macro to make this less cumbersome internally... */ |
|
391 |
#define allocator __PHYSFS_AllocatorHooks |
|
392 |
||
393 |
/* |
|
394 |
* Create a PHYSFS_Io for a file in the physical filesystem. |
|
395 |
* This path is in platform-dependent notation. (mode) must be 'r', 'w', or |
|
396 |
* 'a' for Read, Write, or Append. |
|
397 |
*/ |
|
398 |
PHYSFS_Io *__PHYSFS_createNativeIo(const char *path, const int mode); |
|
399 |
||
400 |
/* |
|
401 |
* Create a PHYSFS_Io for a buffer of memory (READ-ONLY). If you already |
|
402 |
* have one of these, just use its duplicate() method, and it'll increment |
|
403 |
* its refcount without allocating a copy of the buffer. |
|
404 |
*/ |
|
405 |
PHYSFS_Io *__PHYSFS_createMemoryIo(const void *buf, PHYSFS_uint64 len, |
|
406 |
void (*destruct)(void *)); |
|
407 |
||
408 |
||
409 |
/* |
|
410 |
* Read (len) bytes from (io) into (buf). Returns non-zero on success, |
|
411 |
* zero on i/o error. Literally: "return (io->read(io, buf, len) == len);" |
|
412 |
*/ |
|
413 |
int __PHYSFS_readAll(PHYSFS_Io *io, void *buf, const PHYSFS_uint64 len); |
|
414 |
||
415 |
||
416 |
/* These are shared between some archivers. */ |
|
417 |
||
418 |
typedef struct |
|
419 |
{ |
|
420 |
char name[56]; |
|
421 |
PHYSFS_uint32 startPos; |
|
422 |
PHYSFS_uint32 size; |
|
423 |
} UNPKentry; |
|
424 |
||
425 |
void UNPK_closeArchive(PHYSFS_Dir *opaque); |
|
426 |
PHYSFS_Dir *UNPK_openArchive(PHYSFS_Io *io,UNPKentry *e,const PHYSFS_uint32 n); |
|
427 |
void UNPK_enumerateFiles(PHYSFS_Dir *opaque, const char *dname, |
|
428 |
int omitSymLinks, PHYSFS_EnumFilesCallback cb, |
|
429 |
const char *origdir, void *callbackdata); |
|
430 |
PHYSFS_Io *UNPK_openRead(PHYSFS_Dir *opaque, const char *fnm, int *fileExists); |
|
431 |
PHYSFS_Io *UNPK_openWrite(PHYSFS_Dir *opaque, const char *name); |
|
432 |
PHYSFS_Io *UNPK_openAppend(PHYSFS_Dir *opaque, const char *name); |
|
433 |
int UNPK_remove(PHYSFS_Dir *opaque, const char *name); |
|
434 |
int UNPK_mkdir(PHYSFS_Dir *opaque, const char *name); |
|
435 |
int UNPK_stat(PHYSFS_Dir *opaque, const char *fn, int *exist, PHYSFS_Stat *st); |
|
436 |
||
437 |
||
438 |
/*--------------------------------------------------------------------------*/ |
|
439 |
/*--------------------------------------------------------------------------*/ |
|
440 |
/*------------ ----------------*/ |
|
441 |
/*------------ You MUST implement the following functions ----------------*/ |
|
442 |
/*------------ if porting to a new platform. ----------------*/ |
|
443 |
/*------------ (see platform/unix.c for an example) ----------------*/ |
|
444 |
/*------------ ----------------*/ |
|
445 |
/*--------------------------------------------------------------------------*/ |
|
446 |
/*--------------------------------------------------------------------------*/ |
|
447 |
||
448 |
||
449 |
/* |
|
450 |
* The dir separator; '/' on unix, '\\' on win32, ":" on MacOS, etc... |
|
451 |
* Obviously, this isn't a function. If you need more than one char for this, |
|
452 |
* you'll need to pull some old pieces of PhysicsFS out of revision control. |
|
453 |
*/ |
|
454 |
#if PHYSFS_PLATFORM_WINDOWS |
|
455 |
#define __PHYSFS_platformDirSeparator '\\' |
|
456 |
#else |
|
457 |
#define __PHYSFS_platformDirSeparator '/' |
|
458 |
#endif |
|
459 |
||
460 |
/* |
|
461 |
* Initialize the platform. This is called when PHYSFS_init() is called from |
|
462 |
* the application. |
|
463 |
* |
|
464 |
* Return zero if there was a catastrophic failure (which prevents you from |
|
465 |
* functioning at all), and non-zero otherwise. |
|
466 |
*/ |
|
467 |
int __PHYSFS_platformInit(void); |
|
468 |
||
469 |
||
470 |
/* |
|
471 |
* Deinitialize the platform. This is called when PHYSFS_deinit() is called |
|
472 |
* from the application. You can use this to clean up anything you've |
|
473 |
* allocated in your platform driver. |
|
474 |
* |
|
475 |
* Return zero if there was a catastrophic failure (which prevents you from |
|
476 |
* functioning at all), and non-zero otherwise. |
|
477 |
*/ |
|
478 |
int __PHYSFS_platformDeinit(void); |
|
479 |
||
480 |
||
481 |
/* |
|
482 |
* Open a file for reading. (filename) is in platform-dependent notation. The |
|
483 |
* file pointer should be positioned on the first byte of the file. |
|
484 |
* |
|
485 |
* The return value will be some platform-specific datatype that is opaque to |
|
486 |
* the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32. |
|
487 |
* |
|
488 |
* The same file can be opened for read multiple times, and each should have |
|
489 |
* a unique file handle; this is frequently employed to prevent race |
|
490 |
* conditions in the archivers. |
|
491 |
* |
|
492 |
* Call __PHYSFS_setError() and return (NULL) if the file can't be opened. |
|
493 |
*/ |
|
494 |
void *__PHYSFS_platformOpenRead(const char *filename); |
|
495 |
||
496 |
||
497 |
/* |
|
498 |
* Open a file for writing. (filename) is in platform-dependent notation. If |
|
499 |
* the file exists, it should be truncated to zero bytes, and if it doesn't |
|
500 |
* exist, it should be created as a zero-byte file. The file pointer should |
|
501 |
* be positioned on the first byte of the file. |
|
502 |
* |
|
503 |
* The return value will be some platform-specific datatype that is opaque to |
|
504 |
* the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32, |
|
505 |
* etc. |
|
506 |
* |
|
507 |
* Opening a file for write multiple times has undefined results. |
|
508 |
* |
|
509 |
* Call __PHYSFS_setError() and return (NULL) if the file can't be opened. |
|
510 |
*/ |
|
511 |
void *__PHYSFS_platformOpenWrite(const char *filename); |
|
512 |
||
513 |
||
514 |
/* |
|
515 |
* Open a file for appending. (filename) is in platform-dependent notation. If |
|
516 |
* the file exists, the file pointer should be place just past the end of the |
|
517 |
* file, so that the first write will be one byte after the current end of |
|
518 |
* the file. If the file doesn't exist, it should be created as a zero-byte |
|
519 |
* file. The file pointer should be positioned on the first byte of the file. |
|
520 |
* |
|
521 |
* The return value will be some platform-specific datatype that is opaque to |
|
522 |
* the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32, |
|
523 |
* etc. |
|
524 |
* |
|
525 |
* Opening a file for append multiple times has undefined results. |
|
526 |
* |
|
527 |
* Call __PHYSFS_setError() and return (NULL) if the file can't be opened. |
|
528 |
*/ |
|
529 |
void *__PHYSFS_platformOpenAppend(const char *filename); |
|
530 |
||
531 |
/* |
|
532 |
* Read more data from a platform-specific file handle. (opaque) should be |
|
533 |
* cast to whatever data type your platform uses. Read a maximum of (len) |
|
534 |
* 8-bit bytes to the area pointed to by (buf). If there isn't enough data |
|
535 |
* available, return the number of bytes read, and position the file pointer |
|
536 |
* immediately after those bytes. |
|
537 |
* On success, return (len) and position the file pointer immediately past |
|
538 |
* the end of the last read byte. Return (-1) if there is a catastrophic |
|
539 |
* error, and call __PHYSFS_setError() to describe the problem; the file |
|
540 |
* pointer should not move in such a case. A partial read is success; only |
|
541 |
* return (-1) on total failure; presumably, the next read call after a |
|
542 |
* partial read will fail as such. |
|
543 |
*/ |
|
544 |
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buf, PHYSFS_uint64 len); |
|
545 |
||
546 |
/* |
|
547 |
* Write more data to a platform-specific file handle. (opaque) should be |
|
548 |
* cast to whatever data type your platform uses. Write a maximum of (len) |
|
549 |
* 8-bit bytes from the area pointed to by (buffer). If there is a problem, |
|
550 |
* return the number of bytes written, and position the file pointer |
|
551 |
* immediately after those bytes. Return (-1) if there is a catastrophic |
|
552 |
* error, and call __PHYSFS_setError() to describe the problem; the file |
|
553 |
* pointer should not move in such a case. A partial write is success; only |
|
554 |
* return (-1) on total failure; presumably, the next write call after a |
|
555 |
* partial write will fail as such. |
|
556 |
*/ |
|
557 |
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer, |
|
558 |
PHYSFS_uint64 len); |
|
559 |
||
560 |
/* |
|
561 |
* Set the file pointer to a new position. (opaque) should be cast to |
|
562 |
* whatever data type your platform uses. (pos) specifies the number |
|
563 |
* of 8-bit bytes to seek to from the start of the file. Seeking past the |
|
564 |
* end of the file is an error condition, and you should check for it. |
|
565 |
* |
|
566 |
* Not all file types can seek; this is to be expected by the caller. |
|
567 |
* |
|
568 |
* On error, call __PHYSFS_setError() and return zero. On success, return |
|
569 |
* a non-zero value. |
|
570 |
*/ |
|
571 |
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos); |
|
572 |
||
573 |
||
574 |
/* |
|
575 |
* Get the file pointer's position, in an 8-bit byte offset from the start of |
|
576 |
* the file. (opaque) should be cast to whatever data type your platform |
|
577 |
* uses. |
|
578 |
* |
|
579 |
* Not all file types can "tell"; this is to be expected by the caller. |
|
580 |
* |
|
581 |
* On error, call __PHYSFS_setError() and return -1. On success, return >= 0. |
|
582 |
*/ |
|
583 |
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque); |
|
584 |
||
585 |
||
586 |
/* |
|
587 |
* Determine the current size of a file, in 8-bit bytes, from an open file. |
|
588 |
* |
|
589 |
* The caller expects that this information may not be available for all |
|
590 |
* file types on all platforms. |
|
591 |
* |
|
592 |
* Return -1 if you can't do it, and call __PHYSFS_setError(). Otherwise, |
|
593 |
* return the file length in 8-bit bytes. |
|
594 |
*/ |
|
595 |
PHYSFS_sint64 __PHYSFS_platformFileLength(void *handle); |
|
596 |
||
597 |
||
598 |
/* |
|
599 |
* !!! FIXME: comment me. |
|
600 |
*/ |
|
601 |
int __PHYSFS_platformStat(const char *fn, int *exists, PHYSFS_Stat *stat); |
|
602 |
||
603 |
/* |
|
604 |
* Flush any pending writes to disk. (opaque) should be cast to whatever data |
|
605 |
* type your platform uses. Be sure to check for errors; the caller expects |
|
606 |
* that this function can fail if there was a flushing error, etc. |
|
607 |
* |
|
608 |
* Return zero on failure, non-zero on success. |
|
609 |
*/ |
|
610 |
int __PHYSFS_platformFlush(void *opaque); |
|
611 |
||
612 |
/* |
|
613 |
* Close file and deallocate resources. (opaque) should be cast to whatever |
|
614 |
* data type your platform uses. This should close the file in any scenario: |
|
615 |
* flushing is a separate function call, and this function should never fail. |
|
616 |
* |
|
617 |
* You should clean up all resources associated with (opaque); the pointer |
|
618 |
* will be considered invalid after this call. |
|
619 |
*/ |
|
620 |
void __PHYSFS_platformClose(void *opaque); |
|
621 |
||
622 |
/* |
|
623 |
* Platform implementation of PHYSFS_getCdRomDirsCallback()... |
|
624 |
* CD directories are discovered and reported to the callback one at a time. |
|
625 |
* Pointers passed to the callback are assumed to be invalid to the |
|
626 |
* application after the callback returns, so you can free them or whatever. |
|
627 |
* Callback does not assume results will be sorted in any meaningful way. |
|
628 |
*/ |
|
629 |
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data); |
|
630 |
||
631 |
/* |
|
632 |
* Calculate the base dir, if your platform needs special consideration. |
|
633 |
* Just return NULL if the standard routines will suffice. (see |
|
634 |
* calculateBaseDir() in physfs.c ...) |
|
635 |
* Your string must end with a dir separator if you don't return NULL. |
|
636 |
* Caller will allocator.Free() the retval if it's not NULL. |
|
637 |
*/ |
|
638 |
char *__PHYSFS_platformCalcBaseDir(const char *argv0); |
|
639 |
||
640 |
/* |
|
641 |
* Get the platform-specific user dir. |
|
642 |
* As of PhysicsFS 2.1, returning NULL means fatal error. |
|
643 |
* Your string must end with a dir separator if you don't return NULL. |
|
644 |
* Caller will allocator.Free() the retval if it's not NULL. |
|
645 |
*/ |
|
646 |
char *__PHYSFS_platformCalcUserDir(void); |
|
647 |
||
648 |
||
649 |
/* This is the cached version from PHYSFS_init(). This is a fast call. */ |
|
650 |
const char *__PHYSFS_getUserDir(void); /* not deprecated internal version. */ |
|
651 |
||
652 |
||
653 |
/* |
|
654 |
* Get the platform-specific pref dir. |
|
655 |
* Returning NULL means fatal error. |
|
656 |
* Your string must end with a dir separator if you don't return NULL. |
|
657 |
* Caller will allocator.Free() the retval if it's not NULL. |
|
658 |
* Caller will make missing directories if necessary; this just reports |
|
659 |
* the final path. |
|
660 |
*/ |
|
661 |
char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app); |
|
662 |
||
663 |
||
664 |
/* |
|
665 |
* Return a pointer that uniquely identifies the current thread. |
|
666 |
* On a platform without threading, (0x1) will suffice. These numbers are |
|
667 |
* arbitrary; the only requirement is that no two threads have the same |
|
668 |
* pointer. |
|
669 |
*/ |
|
670 |
void *__PHYSFS_platformGetThreadID(void); |
|
671 |
||
672 |
||
673 |
/* |
|
674 |
* Enumerate a directory of files. This follows the rules for the |
|
675 |
* PHYSFS_Archiver->enumerateFiles() method (see above), except that the |
|
676 |
* (dirName) that is passed to this function is converted to |
|
677 |
* platform-DEPENDENT notation by the caller. The PHYSFS_Archiver version |
|
678 |
* uses platform-independent notation. Note that ".", "..", and other |
|
679 |
* metaentries should always be ignored. |
|
680 |
*/ |
|
681 |
void __PHYSFS_platformEnumerateFiles(const char *dirname, |
|
682 |
int omitSymLinks, |
|
683 |
PHYSFS_EnumFilesCallback callback, |
|
684 |
const char *origdir, |
|
685 |
void *callbackdata); |
|
686 |
||
687 |
/* |
|
688 |
* Make a directory in the actual filesystem. (path) is specified in |
|
689 |
* platform-dependent notation. On error, return zero and set the error |
|
690 |
* message. Return non-zero on success. |
|
691 |
*/ |
|
692 |
int __PHYSFS_platformMkDir(const char *path); |
|
693 |
||
694 |
||
695 |
/* |
|
696 |
* Remove a file or directory entry in the actual filesystem. (path) is |
|
697 |
* specified in platform-dependent notation. Note that this deletes files |
|
698 |
* _and_ directories, so you might need to do some determination. |
|
699 |
* Non-empty directories should report an error and not delete themselves |
|
700 |
* or their contents. |
|
701 |
* |
|
702 |
* Deleting a symlink should remove the link, not what it points to. |
|
703 |
* |
|
704 |
* On error, return zero and set the error message. Return non-zero on success. |
|
705 |
*/ |
|
706 |
int __PHYSFS_platformDelete(const char *path); |
|
707 |
||
708 |
||
709 |
/* |
|
710 |
* Create a platform-specific mutex. This can be whatever datatype your |
|
711 |
* platform uses for mutexes, but it is cast to a (void *) for abstractness. |
|
712 |
* |
|
713 |
* Return (NULL) if you couldn't create one. Systems without threads can |
|
714 |
* return any arbitrary non-NULL value. |
|
715 |
*/ |
|
716 |
void *__PHYSFS_platformCreateMutex(void); |
|
717 |
||
718 |
/* |
|
719 |
* Destroy a platform-specific mutex, and clean up any resources associated |
|
720 |
* with it. (mutex) is a value previously returned by |
|
721 |
* __PHYSFS_platformCreateMutex(). This can be a no-op on single-threaded |
|
722 |
* platforms. |
|
723 |
*/ |
|
724 |
void __PHYSFS_platformDestroyMutex(void *mutex); |
|
725 |
||
726 |
/* |
|
727 |
* Grab possession of a platform-specific mutex. Mutexes should be recursive; |
|
728 |
* that is, the same thread should be able to call this function multiple |
|
729 |
* times in a row without causing a deadlock. This function should block |
|
730 |
* until a thread can gain possession of the mutex. |
|
731 |
* |
|
732 |
* Return non-zero if the mutex was grabbed, zero if there was an |
|
733 |
* unrecoverable problem grabbing it (this should not be a matter of |
|
734 |
* timing out! We're talking major system errors; block until the mutex |
|
735 |
* is available otherwise.) |
|
736 |
* |
|
737 |
* _DO NOT_ call __PHYSFS_setError() in here! Since setError calls this |
|
738 |
* function, you'll cause an infinite recursion. This means you can't |
|
739 |
* use the BAIL_*MACRO* macros, either. |
|
740 |
*/ |
|
741 |
int __PHYSFS_platformGrabMutex(void *mutex); |
|
742 |
||
743 |
/* |
|
744 |
* Relinquish possession of the mutex when this method has been called |
|
745 |
* once for each time that platformGrabMutex was called. Once possession has |
|
746 |
* been released, the next thread in line to grab the mutex (if any) may |
|
747 |
* proceed. |
|
748 |
* |
|
749 |
* _DO NOT_ call __PHYSFS_setError() in here! Since setError calls this |
|
750 |
* function, you'll cause an infinite recursion. This means you can't |
|
751 |
* use the BAIL_*MACRO* macros, either. |
|
752 |
*/ |
|
753 |
void __PHYSFS_platformReleaseMutex(void *mutex); |
|
754 |
||
755 |
/* |
|
756 |
* Called at the start of PHYSFS_init() to prepare the allocator, if the user |
|
757 |
* hasn't selected their own allocator via PHYSFS_setAllocator(). |
|
758 |
* If the platform has a custom allocator, it should fill in the fields of |
|
759 |
* (a) with the proper function pointers and return non-zero. |
|
760 |
* If the platform just wants to use malloc()/free()/etc, return zero |
|
761 |
* immediately and the higher level will handle it. The Init and Deinit |
|
762 |
* fields of (a) are optional...set them to NULL if you don't need them. |
|
763 |
* Everything else must be implemented. All rules follow those for |
|
764 |
* PHYSFS_setAllocator(). If Init isn't NULL, it will be called shortly |
|
765 |
* after this function returns non-zero. |
|
766 |
*/ |
|
767 |
int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a); |
|
768 |
||
769 |
#ifdef __cplusplus |
|
770 |
} |
|
771 |
#endif |
|
772 |
||
773 |
#endif |
|
774 |
||
775 |
/* end of physfs_internal.h ... */ |
|
776 |