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_SLB |
|
118 #define PHYSFS_SUPPORTS_SLB 0 |
|
119 #endif |
|
120 #ifndef PHYSFS_SUPPORTS_ISO9660 |
|
121 #define PHYSFS_SUPPORTS_ISO9660 0 |
|
122 #endif |
|
123 |
|
124 /* The latest supported PHYSFS_Io::version value. */ |
|
125 #define CURRENT_PHYSFS_IO_API_VERSION 0 |
|
126 |
|
127 /* The latest supported PHYSFS_Archiver::version value. */ |
|
128 #define CURRENT_PHYSFS_ARCHIVER_API_VERSION 0 |
|
129 |
|
130 /* This byteorder stuff was lifted from SDL. https://www.libsdl.org/ */ |
|
131 #define PHYSFS_LIL_ENDIAN 1234 |
|
132 #define PHYSFS_BIG_ENDIAN 4321 |
|
133 |
|
134 #ifdef __linux__ |
|
135 #include <endian.h> |
|
136 #define PHYSFS_BYTEORDER __BYTE_ORDER |
|
137 #else /* __linux__ */ |
|
138 #if defined(__hppa__) || \ |
|
139 defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ |
|
140 (defined(__MIPS__) && defined(__MISPEB__)) || \ |
|
141 defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \ |
|
142 defined(__sparc__) |
|
143 #define PHYSFS_BYTEORDER PHYSFS_BIG_ENDIAN |
|
144 #else |
|
145 #define PHYSFS_BYTEORDER PHYSFS_LIL_ENDIAN |
|
146 #endif |
|
147 #endif /* __linux__ */ |
|
148 |
|
149 |
|
150 /* |
|
151 * When sorting the entries in an archive, we use a modified QuickSort. |
|
152 * When there are less then PHYSFS_QUICKSORT_THRESHOLD entries left to sort, |
|
153 * we switch over to a BubbleSort for the remainder. Tweak to taste. |
|
154 * |
|
155 * You can override this setting by defining PHYSFS_QUICKSORT_THRESHOLD |
|
156 * before #including "physfs_internal.h". |
|
157 */ |
|
158 #ifndef PHYSFS_QUICKSORT_THRESHOLD |
|
159 #define PHYSFS_QUICKSORT_THRESHOLD 4 |
|
160 #endif |
|
161 |
|
162 /* |
|
163 * Sort an array (or whatever) of (max) elements. This uses a mixture of |
|
164 * a QuickSort and BubbleSort internally. |
|
165 * (cmpfn) is used to determine ordering, and (swapfn) does the actual |
|
166 * swapping of elements in the list. |
|
167 */ |
|
168 void __PHYSFS_sort(void *entries, size_t max, |
|
169 int (*cmpfn)(void *, size_t, size_t), |
|
170 void (*swapfn)(void *, size_t, size_t)); |
|
171 |
|
172 /* |
|
173 * This isn't a formal error code, it's just for BAIL_MACRO. |
|
174 * It means: there was an error, but someone else already set it for us. |
|
175 */ |
|
176 #define ERRPASS PHYSFS_ERR_OK |
|
177 |
|
178 /* These get used all over for lessening code clutter. */ |
|
179 #define BAIL_MACRO(e, r) do { if (e) PHYSFS_setErrorCode(e); return r; } while (0) |
|
180 #define BAIL_IF_MACRO(c, e, r) do { if (c) { if (e) PHYSFS_setErrorCode(e); return r; } } while (0) |
|
181 #define BAIL_MACRO_MUTEX(e, m, r) do { if (e) PHYSFS_setErrorCode(e); __PHYSFS_platformReleaseMutex(m); return r; } while (0) |
|
182 #define BAIL_IF_MACRO_MUTEX(c, e, m, r) do { if (c) { if (e) PHYSFS_setErrorCode(e); __PHYSFS_platformReleaseMutex(m); return r; } } while (0) |
|
183 #define GOTO_MACRO(e, g) do { if (e) PHYSFS_setErrorCode(e); goto g; } while (0) |
|
184 #define GOTO_IF_MACRO(c, e, g) do { if (c) { if (e) PHYSFS_setErrorCode(e); goto g; } } while (0) |
|
185 #define GOTO_MACRO_MUTEX(e, m, g) do { if (e) PHYSFS_setErrorCode(e); __PHYSFS_platformReleaseMutex(m); goto g; } while (0) |
|
186 #define GOTO_IF_MACRO_MUTEX(c, e, m, g) do { if (c) { if (e) PHYSFS_setErrorCode(e); __PHYSFS_platformReleaseMutex(m); goto g; } } while (0) |
|
187 |
|
188 #define __PHYSFS_ARRAYLEN(x) ( (sizeof (x)) / (sizeof (x[0])) ) |
|
189 |
|
190 #ifdef PHYSFS_NO_64BIT_SUPPORT |
|
191 #define __PHYSFS_SI64(x) ((PHYSFS_sint64) (x)) |
|
192 #define __PHYSFS_UI64(x) ((PHYSFS_uint64) (x)) |
|
193 #elif (defined __GNUC__) |
|
194 #define __PHYSFS_SI64(x) x##LL |
|
195 #define __PHYSFS_UI64(x) x##ULL |
|
196 #elif (defined _MSC_VER) |
|
197 #define __PHYSFS_SI64(x) x##i64 |
|
198 #define __PHYSFS_UI64(x) x##ui64 |
|
199 #else |
|
200 #define __PHYSFS_SI64(x) ((PHYSFS_sint64) (x)) |
|
201 #define __PHYSFS_UI64(x) ((PHYSFS_uint64) (x)) |
|
202 #endif |
|
203 |
|
204 |
|
205 /* |
|
206 * Check if a ui64 will fit in the platform's address space. |
|
207 * The initial sizeof check will optimize this macro out entirely on |
|
208 * 64-bit (and larger?!) platforms, and the other condition will |
|
209 * return zero or non-zero if the variable will fit in the platform's |
|
210 * size_t, suitable to pass to malloc. This is kinda messy, but effective. |
|
211 */ |
|
212 #define __PHYSFS_ui64FitsAddressSpace(s) ( \ |
|
213 (sizeof (PHYSFS_uint64) <= sizeof (size_t)) || \ |
|
214 ((s) < (__PHYSFS_UI64(0xFFFFFFFFFFFFFFFF) >> (64-(sizeof(size_t)*8)))) \ |
|
215 ) |
|
216 |
|
217 |
|
218 /* |
|
219 * This is a strcasecmp() or stricmp() replacement that expects both strings |
|
220 * to be in UTF-8 encoding. It will do "case folding" to decide if the |
|
221 * Unicode codepoints in the strings match. |
|
222 * |
|
223 * It will report which string is "greater than" the other, but be aware that |
|
224 * this doesn't necessarily mean anything: 'a' may be "less than" 'b', but |
|
225 * a random Kanji codepoint has no meaningful alphabetically relationship to |
|
226 * a Greek Lambda, but being able to assign a reliable "value" makes sorting |
|
227 * algorithms possible, if not entirely sane. Most cases should treat the |
|
228 * return value as "equal" or "not equal". |
|
229 */ |
|
230 int __PHYSFS_utf8stricmp(const char *s1, const char *s2); |
|
231 |
|
232 /* |
|
233 * This works like __PHYSFS_utf8stricmp(), but takes a character (NOT BYTE |
|
234 * COUNT) argument, like strcasencmp(). |
|
235 */ |
|
236 int __PHYSFS_utf8strnicmp(const char *s1, const char *s2, PHYSFS_uint32 l); |
|
237 |
|
238 /* |
|
239 * stricmp() that guarantees to only work with low ASCII. The C runtime |
|
240 * stricmp() might try to apply a locale/codepage/etc, which we don't want. |
|
241 */ |
|
242 int __PHYSFS_stricmpASCII(const char *s1, const char *s2); |
|
243 |
|
244 /* |
|
245 * strnicmp() that guarantees to only work with low ASCII. The C runtime |
|
246 * strnicmp() might try to apply a locale/codepage/etc, which we don't want. |
|
247 */ |
|
248 int __PHYSFS_strnicmpASCII(const char *s1, const char *s2, PHYSFS_uint32 l); |
|
249 |
|
250 /* |
|
251 * Like strdup(), but uses the current PhysicsFS allocator. |
|
252 */ |
|
253 char *__PHYSFS_strdup(const char *str); |
|
254 |
|
255 /* |
|
256 * Give a hash value for a C string (uses djb's xor hashing algorithm). |
|
257 */ |
|
258 PHYSFS_uint32 __PHYSFS_hashString(const char *str, size_t len); |
|
259 |
|
260 |
|
261 /* |
|
262 * The current allocator. Not valid before PHYSFS_init is called! |
|
263 */ |
|
264 extern PHYSFS_Allocator __PHYSFS_AllocatorHooks; |
|
265 |
|
266 /* convenience macro to make this less cumbersome internally... */ |
|
267 #define allocator __PHYSFS_AllocatorHooks |
|
268 |
|
269 /* |
|
270 * Create a PHYSFS_Io for a file in the physical filesystem. |
|
271 * This path is in platform-dependent notation. (mode) must be 'r', 'w', or |
|
272 * 'a' for Read, Write, or Append. |
|
273 */ |
|
274 PHYSFS_Io *__PHYSFS_createNativeIo(const char *path, const int mode); |
|
275 |
|
276 /* |
|
277 * Create a PHYSFS_Io for a buffer of memory (READ-ONLY). If you already |
|
278 * have one of these, just use its duplicate() method, and it'll increment |
|
279 * its refcount without allocating a copy of the buffer. |
|
280 */ |
|
281 PHYSFS_Io *__PHYSFS_createMemoryIo(const void *buf, PHYSFS_uint64 len, |
|
282 void (*destruct)(void *)); |
|
283 |
|
284 |
|
285 /* |
|
286 * Read (len) bytes from (io) into (buf). Returns non-zero on success, |
|
287 * zero on i/o error. Literally: "return (io->read(io, buf, len) == len);" |
|
288 */ |
|
289 int __PHYSFS_readAll(PHYSFS_Io *io, void *buf, const PHYSFS_uint64 len); |
|
290 |
|
291 |
|
292 /* These are shared between some archivers. */ |
|
293 |
|
294 typedef struct |
|
295 { |
|
296 char name[64]; |
|
297 PHYSFS_uint32 startPos; |
|
298 PHYSFS_uint32 size; |
|
299 } UNPKentry; |
|
300 |
|
301 void UNPK_closeArchive(void *opaque); |
|
302 void *UNPK_openArchive(PHYSFS_Io *io,UNPKentry *e,const PHYSFS_uint32 n); |
|
303 void UNPK_enumerateFiles(void *opaque, const char *dname, |
|
304 PHYSFS_EnumFilesCallback cb, |
|
305 const char *origdir, void *callbackdata); |
|
306 PHYSFS_Io *UNPK_openRead(void *opaque, const char *name); |
|
307 PHYSFS_Io *UNPK_openWrite(void *opaque, const char *name); |
|
308 PHYSFS_Io *UNPK_openAppend(void *opaque, const char *name); |
|
309 int UNPK_remove(void *opaque, const char *name); |
|
310 int UNPK_mkdir(void *opaque, const char *name); |
|
311 int UNPK_stat(void *opaque, const char *fn, PHYSFS_Stat *st); |
|
312 |
|
313 |
|
314 /*--------------------------------------------------------------------------*/ |
|
315 /*--------------------------------------------------------------------------*/ |
|
316 /*------------ ----------------*/ |
|
317 /*------------ You MUST implement the following functions ----------------*/ |
|
318 /*------------ if porting to a new platform. ----------------*/ |
|
319 /*------------ (see platform/unix.c for an example) ----------------*/ |
|
320 /*------------ ----------------*/ |
|
321 /*--------------------------------------------------------------------------*/ |
|
322 /*--------------------------------------------------------------------------*/ |
|
323 |
|
324 |
|
325 /* |
|
326 * The dir separator; '/' on unix, '\\' on win32, ":" on MacOS, etc... |
|
327 * Obviously, this isn't a function. If you need more than one char for this, |
|
328 * you'll need to pull some old pieces of PhysicsFS out of revision control. |
|
329 */ |
|
330 #if PHYSFS_PLATFORM_WINDOWS |
|
331 #define __PHYSFS_platformDirSeparator '\\' |
|
332 #else |
|
333 #define __PHYSFS_platformDirSeparator '/' |
|
334 #endif |
|
335 |
|
336 /* |
|
337 * Initialize the platform. This is called when PHYSFS_init() is called from |
|
338 * the application. |
|
339 * |
|
340 * Return zero if there was a catastrophic failure (which prevents you from |
|
341 * functioning at all), and non-zero otherwise. |
|
342 */ |
|
343 int __PHYSFS_platformInit(void); |
|
344 |
|
345 |
|
346 /* |
|
347 * Deinitialize the platform. This is called when PHYSFS_deinit() is called |
|
348 * from the application. You can use this to clean up anything you've |
|
349 * allocated in your platform driver. |
|
350 * |
|
351 * Return zero if there was a catastrophic failure (which prevents you from |
|
352 * functioning at all), and non-zero otherwise. |
|
353 */ |
|
354 int __PHYSFS_platformDeinit(void); |
|
355 |
|
356 |
|
357 /* |
|
358 * Open a file for reading. (filename) is in platform-dependent notation. The |
|
359 * file pointer should be positioned on the first byte of the file. |
|
360 * |
|
361 * The return value will be some platform-specific datatype that is opaque to |
|
362 * the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32. |
|
363 * |
|
364 * The same file can be opened for read multiple times, and each should have |
|
365 * a unique file handle; this is frequently employed to prevent race |
|
366 * conditions in the archivers. |
|
367 * |
|
368 * Call PHYSFS_setErrorCode() and return (NULL) if the file can't be opened. |
|
369 */ |
|
370 void *__PHYSFS_platformOpenRead(const char *filename); |
|
371 |
|
372 |
|
373 /* |
|
374 * Open a file for writing. (filename) is in platform-dependent notation. If |
|
375 * the file exists, it should be truncated to zero bytes, and if it doesn't |
|
376 * exist, it should be created as a zero-byte file. The file pointer should |
|
377 * be positioned on the first byte of the file. |
|
378 * |
|
379 * The return value will be some platform-specific datatype that is opaque to |
|
380 * the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32, |
|
381 * etc. |
|
382 * |
|
383 * Opening a file for write multiple times has undefined results. |
|
384 * |
|
385 * Call PHYSFS_setErrorCode() and return (NULL) if the file can't be opened. |
|
386 */ |
|
387 void *__PHYSFS_platformOpenWrite(const char *filename); |
|
388 |
|
389 |
|
390 /* |
|
391 * Open a file for appending. (filename) is in platform-dependent notation. If |
|
392 * the file exists, the file pointer should be place just past the end of the |
|
393 * file, so that the first write will be one byte after the current end of |
|
394 * the file. If the file doesn't exist, it should be created as a zero-byte |
|
395 * file. The file pointer should be positioned on the first byte of the file. |
|
396 * |
|
397 * The return value will be some platform-specific datatype that is opaque to |
|
398 * the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32, |
|
399 * etc. |
|
400 * |
|
401 * Opening a file for append multiple times has undefined results. |
|
402 * |
|
403 * Call PHYSFS_setErrorCode() and return (NULL) if the file can't be opened. |
|
404 */ |
|
405 void *__PHYSFS_platformOpenAppend(const char *filename); |
|
406 |
|
407 /* |
|
408 * Read more data from a platform-specific file handle. (opaque) should be |
|
409 * cast to whatever data type your platform uses. Read a maximum of (len) |
|
410 * 8-bit bytes to the area pointed to by (buf). If there isn't enough data |
|
411 * available, return the number of bytes read, and position the file pointer |
|
412 * immediately after those bytes. |
|
413 * On success, return (len) and position the file pointer immediately past |
|
414 * the end of the last read byte. Return (-1) if there is a catastrophic |
|
415 * error, and call PHYSFS_setErrorCode() to describe the problem; the file |
|
416 * pointer should not move in such a case. A partial read is success; only |
|
417 * return (-1) on total failure; presumably, the next read call after a |
|
418 * partial read will fail as such. |
|
419 */ |
|
420 PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buf, PHYSFS_uint64 len); |
|
421 |
|
422 /* |
|
423 * Write more data to a platform-specific file handle. (opaque) should be |
|
424 * cast to whatever data type your platform uses. Write a maximum of (len) |
|
425 * 8-bit bytes from the area pointed to by (buffer). If there is a problem, |
|
426 * return the number of bytes written, and position the file pointer |
|
427 * immediately after those bytes. Return (-1) if there is a catastrophic |
|
428 * error, and call PHYSFS_setErrorCode() to describe the problem; the file |
|
429 * pointer should not move in such a case. A partial write is success; only |
|
430 * return (-1) on total failure; presumably, the next write call after a |
|
431 * partial write will fail as such. |
|
432 */ |
|
433 PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer, |
|
434 PHYSFS_uint64 len); |
|
435 |
|
436 /* |
|
437 * Set the file pointer to a new position. (opaque) should be cast to |
|
438 * whatever data type your platform uses. (pos) specifies the number |
|
439 * of 8-bit bytes to seek to from the start of the file. Seeking past the |
|
440 * end of the file is an error condition, and you should check for it. |
|
441 * |
|
442 * Not all file types can seek; this is to be expected by the caller. |
|
443 * |
|
444 * On error, call PHYSFS_setErrorCode() and return zero. On success, return |
|
445 * a non-zero value. |
|
446 */ |
|
447 int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos); |
|
448 |
|
449 |
|
450 /* |
|
451 * Get the file pointer's position, in an 8-bit byte offset from the start of |
|
452 * the file. (opaque) should be cast to whatever data type your platform |
|
453 * uses. |
|
454 * |
|
455 * Not all file types can "tell"; this is to be expected by the caller. |
|
456 * |
|
457 * On error, call PHYSFS_setErrorCode() and return -1. On success, return >= 0. |
|
458 */ |
|
459 PHYSFS_sint64 __PHYSFS_platformTell(void *opaque); |
|
460 |
|
461 |
|
462 /* |
|
463 * Determine the current size of a file, in 8-bit bytes, from an open file. |
|
464 * |
|
465 * The caller expects that this information may not be available for all |
|
466 * file types on all platforms. |
|
467 * |
|
468 * Return -1 if you can't do it, and call PHYSFS_setErrorCode(). Otherwise, |
|
469 * return the file length in 8-bit bytes. |
|
470 */ |
|
471 PHYSFS_sint64 __PHYSFS_platformFileLength(void *handle); |
|
472 |
|
473 |
|
474 /* |
|
475 * !!! FIXME: comment me. |
|
476 */ |
|
477 int __PHYSFS_platformStat(const char *fn, PHYSFS_Stat *stat); |
|
478 |
|
479 /* |
|
480 * Flush any pending writes to disk. (opaque) should be cast to whatever data |
|
481 * type your platform uses. Be sure to check for errors; the caller expects |
|
482 * that this function can fail if there was a flushing error, etc. |
|
483 * |
|
484 * Return zero on failure, non-zero on success. |
|
485 */ |
|
486 int __PHYSFS_platformFlush(void *opaque); |
|
487 |
|
488 /* |
|
489 * Close file and deallocate resources. (opaque) should be cast to whatever |
|
490 * data type your platform uses. This should close the file in any scenario: |
|
491 * flushing is a separate function call, and this function should never fail. |
|
492 * |
|
493 * You should clean up all resources associated with (opaque); the pointer |
|
494 * will be considered invalid after this call. |
|
495 */ |
|
496 void __PHYSFS_platformClose(void *opaque); |
|
497 |
|
498 /* |
|
499 * Platform implementation of PHYSFS_getCdRomDirsCallback()... |
|
500 * CD directories are discovered and reported to the callback one at a time. |
|
501 * Pointers passed to the callback are assumed to be invalid to the |
|
502 * application after the callback returns, so you can free them or whatever. |
|
503 * Callback does not assume results will be sorted in any meaningful way. |
|
504 */ |
|
505 void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data); |
|
506 |
|
507 /* |
|
508 * Calculate the base dir, if your platform needs special consideration. |
|
509 * Just return NULL if the standard routines will suffice. (see |
|
510 * calculateBaseDir() in physfs.c ...) |
|
511 * Your string must end with a dir separator if you don't return NULL. |
|
512 * Caller will allocator.Free() the retval if it's not NULL. |
|
513 */ |
|
514 char *__PHYSFS_platformCalcBaseDir(const char *argv0); |
|
515 |
|
516 /* |
|
517 * Get the platform-specific user dir. |
|
518 * As of PhysicsFS 2.1, returning NULL means fatal error. |
|
519 * Your string must end with a dir separator if you don't return NULL. |
|
520 * Caller will allocator.Free() the retval if it's not NULL. |
|
521 */ |
|
522 char *__PHYSFS_platformCalcUserDir(void); |
|
523 |
|
524 |
|
525 /* This is the cached version from PHYSFS_init(). This is a fast call. */ |
|
526 const char *__PHYSFS_getUserDir(void); /* not deprecated internal version. */ |
|
527 |
|
528 |
|
529 /* |
|
530 * Get the platform-specific pref dir. |
|
531 * Returning NULL means fatal error. |
|
532 * Your string must end with a dir separator if you don't return NULL. |
|
533 * Caller will allocator.Free() the retval if it's not NULL. |
|
534 * Caller will make missing directories if necessary; this just reports |
|
535 * the final path. |
|
536 */ |
|
537 char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app); |
|
538 |
|
539 |
|
540 /* |
|
541 * Return a pointer that uniquely identifies the current thread. |
|
542 * On a platform without threading, (0x1) will suffice. These numbers are |
|
543 * arbitrary; the only requirement is that no two threads have the same |
|
544 * pointer. |
|
545 */ |
|
546 void *__PHYSFS_platformGetThreadID(void); |
|
547 |
|
548 |
|
549 /* |
|
550 * Enumerate a directory of files. This follows the rules for the |
|
551 * PHYSFS_Archiver::enumerateFiles() method, except that the |
|
552 * (dirName) that is passed to this function is converted to |
|
553 * platform-DEPENDENT notation by the caller. The PHYSFS_Archiver version |
|
554 * uses platform-independent notation. Note that ".", "..", and other |
|
555 * meta-entries should always be ignored. |
|
556 */ |
|
557 void __PHYSFS_platformEnumerateFiles(const char *dirname, |
|
558 PHYSFS_EnumFilesCallback callback, |
|
559 const char *origdir, |
|
560 void *callbackdata); |
|
561 |
|
562 /* |
|
563 * Make a directory in the actual filesystem. (path) is specified in |
|
564 * platform-dependent notation. On error, return zero and set the error |
|
565 * message. Return non-zero on success. |
|
566 */ |
|
567 int __PHYSFS_platformMkDir(const char *path); |
|
568 |
|
569 |
|
570 /* |
|
571 * Remove a file or directory entry in the actual filesystem. (path) is |
|
572 * specified in platform-dependent notation. Note that this deletes files |
|
573 * _and_ directories, so you might need to do some determination. |
|
574 * Non-empty directories should report an error and not delete themselves |
|
575 * or their contents. |
|
576 * |
|
577 * Deleting a symlink should remove the link, not what it points to. |
|
578 * |
|
579 * On error, return zero and set the error message. Return non-zero on success. |
|
580 */ |
|
581 int __PHYSFS_platformDelete(const char *path); |
|
582 |
|
583 |
|
584 /* |
|
585 * Create a platform-specific mutex. This can be whatever datatype your |
|
586 * platform uses for mutexes, but it is cast to a (void *) for abstractness. |
|
587 * |
|
588 * Return (NULL) if you couldn't create one. Systems without threads can |
|
589 * return any arbitrary non-NULL value. |
|
590 */ |
|
591 void *__PHYSFS_platformCreateMutex(void); |
|
592 |
|
593 /* |
|
594 * Destroy a platform-specific mutex, and clean up any resources associated |
|
595 * with it. (mutex) is a value previously returned by |
|
596 * __PHYSFS_platformCreateMutex(). This can be a no-op on single-threaded |
|
597 * platforms. |
|
598 */ |
|
599 void __PHYSFS_platformDestroyMutex(void *mutex); |
|
600 |
|
601 /* |
|
602 * Grab possession of a platform-specific mutex. Mutexes should be recursive; |
|
603 * that is, the same thread should be able to call this function multiple |
|
604 * times in a row without causing a deadlock. This function should block |
|
605 * until a thread can gain possession of the mutex. |
|
606 * |
|
607 * Return non-zero if the mutex was grabbed, zero if there was an |
|
608 * unrecoverable problem grabbing it (this should not be a matter of |
|
609 * timing out! We're talking major system errors; block until the mutex |
|
610 * is available otherwise.) |
|
611 * |
|
612 * _DO NOT_ call PHYSFS_setErrorCode() in here! Since setErrorCode calls this |
|
613 * function, you'll cause an infinite recursion. This means you can't |
|
614 * use the BAIL_*MACRO* macros, either. |
|
615 */ |
|
616 int __PHYSFS_platformGrabMutex(void *mutex); |
|
617 |
|
618 /* |
|
619 * Relinquish possession of the mutex when this method has been called |
|
620 * once for each time that platformGrabMutex was called. Once possession has |
|
621 * been released, the next thread in line to grab the mutex (if any) may |
|
622 * proceed. |
|
623 * |
|
624 * _DO NOT_ call PHYSFS_setErrorCode() in here! Since setErrorCode calls this |
|
625 * function, you'll cause an infinite recursion. This means you can't |
|
626 * use the BAIL_*MACRO* macros, either. |
|
627 */ |
|
628 void __PHYSFS_platformReleaseMutex(void *mutex); |
|
629 |
|
630 /* |
|
631 * Called at the start of PHYSFS_init() to prepare the allocator, if the user |
|
632 * hasn't selected their own allocator via PHYSFS_setAllocator(). |
|
633 * If the platform has a custom allocator, it should fill in the fields of |
|
634 * (a) with the proper function pointers and return non-zero. |
|
635 * If the platform just wants to use malloc()/free()/etc, return zero |
|
636 * immediately and the higher level will handle it. The Init and Deinit |
|
637 * fields of (a) are optional...set them to NULL if you don't need them. |
|
638 * Everything else must be implemented. All rules follow those for |
|
639 * PHYSFS_setAllocator(). If Init isn't NULL, it will be called shortly |
|
640 * after this function returns non-zero. |
|
641 */ |
|
642 int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a); |
|
643 |
|
644 #ifdef __cplusplus |
|
645 } |
|
646 #endif |
|
647 |
|
648 #endif |
|
649 |
|
650 /* end of physfs_internal.h ... */ |
|
651 |
|