Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 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
/* Turn off MSVC warnings that are aggressively anti-portability. */
18
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
19
#define _CRT_SECURE_NO_WARNINGS 1
20
#endif
21
 
22
#include "physfs.h"
23
 
24
/* The holy trinity. */
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28
 
29
#include "physfs_platforms.h"
30
 
31
#include <assert.h>
32
 
33
#define __PHYSFS_COMPILE_TIME_ASSERT(name, x) \
34
       typedef int __PHYSFS_compile_time_assert_##name[(x) * 2 - 1]
35
 
36
/* !!! FIXME: remove this when revamping stack allocation code... */
37
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__WATCOMC__)
38
#include <malloc.h>
39
#endif
40
 
41
#ifdef PHYSFS_PLATFORM_SOLARIS
42
#include <alloca.h>
43
#endif
44
 
45
#ifdef __cplusplus
46
extern "C" {
47
#endif
48
 
49
#ifdef __GNUC__
50
#define PHYSFS_MINIMUM_GCC_VERSION(major, minor) \
51
    ( ((__GNUC__ << 16) + __GNUC_MINOR__) >= (((major) << 16) + (minor)) )
52
#else
53
#define PHYSFS_MINIMUM_GCC_VERSION(major, minor) (0)
54
#endif
55
 
56
#ifdef __cplusplus
57
    /* C++ always has a real inline keyword. */
58
#elif (defined macintosh) && !(defined __MWERKS__)
59
#   define inline
60
#elif (defined _MSC_VER)
61
#   define inline __inline
62
#endif
63
 
64
#if defined(PHYSFS_PLATFORM_LINUX) && !defined(_FILE_OFFSET_BITS)
65
#define _FILE_OFFSET_BITS 64
66
#endif
67
 
68
/* All public APIs need to be in physfs.h with a PHYSFS_DECL.
69
   All file-private symbols need to be marked "static".
70
   Everything shared between PhysicsFS sources needs to be in this
71
   file between the visibility pragma blocks. */
72
#if PHYSFS_MINIMUM_GCC_VERSION(4,0) || defined(__clang__)
73
#define PHYSFS_HAVE_PRAGMA_VISIBILITY 1
74
#endif
75
 
76
#if PHYSFS_HAVE_PRAGMA_VISIBILITY
77
#pragma GCC visibility push(hidden)
78
#endif
79
 
80
/* These are the build-in archivers. We list them all as "extern" here without
81
   #ifdefs to keep it tidy, but obviously you need to make sure these are
82
   wrapped in PHYSFS_SUPPORTS_* checks before actually referencing them. */
83
extern const PHYSFS_Archiver __PHYSFS_Archiver_DIR;
84
extern const PHYSFS_Archiver __PHYSFS_Archiver_ZIP;
85
extern const PHYSFS_Archiver __PHYSFS_Archiver_7Z;
86
extern const PHYSFS_Archiver __PHYSFS_Archiver_GRP;
87
extern const PHYSFS_Archiver __PHYSFS_Archiver_QPAK;
88
extern const PHYSFS_Archiver __PHYSFS_Archiver_HOG;
89
extern const PHYSFS_Archiver __PHYSFS_Archiver_MVL;
90
extern const PHYSFS_Archiver __PHYSFS_Archiver_WAD;
91
extern const PHYSFS_Archiver __PHYSFS_Archiver_SLB;
92
extern const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660;
93
extern const PHYSFS_Archiver __PHYSFS_Archiver_VDF;
94
 
95
/* a real C99-compliant snprintf() is in Visual Studio 2015,
96
   but just use this everywhere for binary compatibility. */
97
#if defined(_MSC_VER)
98
int __PHYSFS_msvc_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap);
99
int __PHYSFS_msvc_snprintf(char *outBuf, size_t size, const char *format, ...);
100
#define vsnprintf __PHYSFS_msvc_vsnprintf
101
#define snprintf __PHYSFS_msvc_snprintf
102
#endif
103
 
104
/* Some simple wrappers around WinRT C++ interfaces we can call from C. */
105
#ifdef PHYSFS_PLATFORM_WINRT
106
const void *__PHYSFS_winrtCalcBaseDir(void);
107
const void *__PHYSFS_winrtCalcPrefDir(void);
108
#endif
109
 
110
/* atomic operations. */
111
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
112
#include <intrin.h>
113
__PHYSFS_COMPILE_TIME_ASSERT(LongEqualsInt, sizeof (int) == sizeof (long));
114
#define __PHYSFS_ATOMIC_INCR(ptrval) _InterlockedIncrement((long*)(ptrval))
115
#define __PHYSFS_ATOMIC_DECR(ptrval) _InterlockedDecrement((long*)(ptrval))
116
#elif defined(__clang__) || (defined(__GNUC__) && (((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100)) >= 40100))
117
#define __PHYSFS_ATOMIC_INCR(ptrval) __sync_fetch_and_add(ptrval, 1)
118
#define __PHYSFS_ATOMIC_DECR(ptrval) __sync_fetch_and_add(ptrval, -1)
119
#else
120
#define PHYSFS_NEED_ATOMIC_OP_FALLBACK 1
121
int __PHYSFS_ATOMIC_INCR(int *ptrval);
122
int __PHYSFS_ATOMIC_DECR(int *ptrval);
123
#endif
124
 
125
 
126
/*
127
 * Interface for small allocations. If you need a little scratch space for
128
 *  a throwaway buffer or string, use this. It will make small allocations
129
 *  on the stack if possible, and use allocator.Malloc() if they are too
130
 *  large. This helps reduce malloc pressure.
131
 * There are some rules, though:
132
 * NEVER return a pointer from this, as stack-allocated buffers go away
133
 *  when your function returns.
134
 * NEVER allocate in a loop, as stack-allocated pointers will pile up. Call
135
 *  a function that uses smallAlloc from your loop, so the allocation can
136
 *  free each time.
137
 * NEVER call smallAlloc with any complex expression (it's a macro that WILL
138
 *  have side effects...it references the argument multiple times). Use a
139
 *  variable or a literal.
140
 * NEVER free a pointer from this with anything but smallFree. It will not
141
 *  be a valid pointer to the allocator, regardless of where the memory came
142
 *  from.
143
 * NEVER realloc a pointer from this.
144
 * NEVER forget to use smallFree: it may not be a pointer from the stack.
145
 * NEVER forget to check for NULL...allocation can fail here, of course!
146
 */
147
#define __PHYSFS_SMALLALLOCTHRESHOLD 256
148
void *__PHYSFS_initSmallAlloc(void *ptr, const size_t len);
149
 
150
#define __PHYSFS_smallAlloc(bytes) ( \
151
    __PHYSFS_initSmallAlloc( \
152
        (((bytes) < __PHYSFS_SMALLALLOCTHRESHOLD) ? \
153
            alloca((size_t)((bytes)+sizeof(void*))) : NULL), (bytes)) \
154
)
155
 
156
void __PHYSFS_smallFree(void *ptr);
157
 
158
 
159
/* Use the allocation hooks. */
160
#define malloc(x) Do not use malloc() directly.
161
#define realloc(x, y) Do not use realloc() directly.
162
#define free(x) Do not use free() directly.
163
/* !!! FIXME: add alloca check here. */
164
 
165
 
166
/* by default, enable things, so builds can opt out of a few things they
167
   want to avoid. But you can build with this #defined to 0 if you would
168
   like to turn off everything except a handful of things you opt into. */
169
#ifndef PHYSFS_SUPPORTS_DEFAULT
170
#define PHYSFS_SUPPORTS_DEFAULT 1
171
#endif
172
 
173
 
174
#ifndef PHYSFS_SUPPORTS_ZIP
175
#define PHYSFS_SUPPORTS_ZIP PHYSFS_SUPPORTS_DEFAULT
176
#endif
177
#ifndef PHYSFS_SUPPORTS_7Z
178
#define PHYSFS_SUPPORTS_7Z PHYSFS_SUPPORTS_DEFAULT
179
#endif
180
#ifndef PHYSFS_SUPPORTS_GRP
181
#define PHYSFS_SUPPORTS_GRP PHYSFS_SUPPORTS_DEFAULT
182
#endif
183
#ifndef PHYSFS_SUPPORTS_HOG
184
#define PHYSFS_SUPPORTS_HOG PHYSFS_SUPPORTS_DEFAULT
185
#endif
186
#ifndef PHYSFS_SUPPORTS_MVL
187
#define PHYSFS_SUPPORTS_MVL PHYSFS_SUPPORTS_DEFAULT
188
#endif
189
#ifndef PHYSFS_SUPPORTS_WAD
190
#define PHYSFS_SUPPORTS_WAD PHYSFS_SUPPORTS_DEFAULT
191
#endif
192
#ifndef PHYSFS_SUPPORTS_QPAK
193
#define PHYSFS_SUPPORTS_QPAK PHYSFS_SUPPORTS_DEFAULT
194
#endif
195
#ifndef PHYSFS_SUPPORTS_SLB
196
#define PHYSFS_SUPPORTS_SLB PHYSFS_SUPPORTS_DEFAULT
197
#endif
198
#ifndef PHYSFS_SUPPORTS_ISO9660
199
#define PHYSFS_SUPPORTS_ISO9660 PHYSFS_SUPPORTS_DEFAULT
200
#endif
201
#ifndef PHYSFS_SUPPORTS_VDF
202
#define PHYSFS_SUPPORTS_VDF PHYSFS_SUPPORTS_DEFAULT
203
#endif
204
 
205
#if PHYSFS_SUPPORTS_7Z
206
/* 7zip support needs a global init function called at startup (no deinit). */
207
extern void SZIP_global_init(void);
208
#endif
209
 
210
/* The latest supported PHYSFS_Io::version value. */
211
#define CURRENT_PHYSFS_IO_API_VERSION 0
212
 
213
/* The latest supported PHYSFS_Archiver::version value. */
214
#define CURRENT_PHYSFS_ARCHIVER_API_VERSION 0
215
 
216
/* This byteorder stuff was lifted from SDL. https://www.libsdl.org/ */
217
#define PHYSFS_LIL_ENDIAN  1234
218
#define PHYSFS_BIG_ENDIAN  4321
219
 
220
#ifdef __linux__
221
#include <endian.h>
222
#define PHYSFS_BYTEORDER  __BYTE_ORDER
223
#else /* __linux__ */
224
#if defined(__hppa__) || \
225
    defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
226
    (defined(__MIPS__) && defined(__MISPEB__)) || \
227
    defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
228
    defined(__sparc__)
229
#define PHYSFS_BYTEORDER   PHYSFS_BIG_ENDIAN
230
#else
231
#define PHYSFS_BYTEORDER   PHYSFS_LIL_ENDIAN
232
#endif
233
#endif /* __linux__ */
234
 
235
 
236
/*
237
 * When sorting the entries in an archive, we use a modified QuickSort.
238
 *  When there are less then PHYSFS_QUICKSORT_THRESHOLD entries left to sort,
239
 *  we switch over to a BubbleSort for the remainder. Tweak to taste.
240
 *
241
 * You can override this setting by defining PHYSFS_QUICKSORT_THRESHOLD
242
 *  before #including "physfs_internal.h".
243
 */
244
#ifndef PHYSFS_QUICKSORT_THRESHOLD
245
#define PHYSFS_QUICKSORT_THRESHOLD 4
246
#endif
247
 
248
/*
249
 * Sort an array (or whatever) of (max) elements. This uses a mixture of
250
 *  a QuickSort and BubbleSort internally.
251
 * (cmpfn) is used to determine ordering, and (swapfn) does the actual
252
 *  swapping of elements in the list.
253
 */
254
void __PHYSFS_sort(void *entries, size_t max,
255
                   int (*cmpfn)(void *, size_t, size_t),
256
                   void (*swapfn)(void *, size_t, size_t));
257
 
258
/* These get used all over for lessening code clutter. */
259
/* "ERRPASS" means "something else just set the error state for us" and is
260
    just to make it clear where the responsibility for the error state lays. */
261
#define BAIL(e, r) do { if (e) PHYSFS_setErrorCode(e); return r; } while (0)
262
#define BAIL_ERRPASS(r) do { return r; } while (0)
263
#define BAIL_IF(c, e, r) do { if (c) { if (e) PHYSFS_setErrorCode(e); return r; } } while (0)
264
#define BAIL_IF_ERRPASS(c, r) do { if (c) { return r; } } while (0)
265
#define BAIL_MUTEX(e, m, r) do { if (e) PHYSFS_setErrorCode(e); __PHYSFS_platformReleaseMutex(m); return r; } while (0)
266
#define BAIL_MUTEX_ERRPASS(m, r) do { __PHYSFS_platformReleaseMutex(m); return r; } while (0)
267
#define BAIL_IF_MUTEX(c, e, m, r) do { if (c) { if (e) PHYSFS_setErrorCode(e); __PHYSFS_platformReleaseMutex(m); return r; } } while (0)
268
#define BAIL_IF_MUTEX_ERRPASS(c, m, r) do { if (c) { __PHYSFS_platformReleaseMutex(m); return r; } } while (0)
269
#define GOTO(e, g) do { if (e) PHYSFS_setErrorCode(e); goto g; } while (0)
270
#define GOTO_ERRPASS(g) do { goto g; } while (0)
271
#define GOTO_IF(c, e, g) do { if (c) { if (e) PHYSFS_setErrorCode(e); goto g; } } while (0)
272
#define GOTO_IF_ERRPASS(c, g) do { if (c) { goto g; } } while (0)
273
#define GOTO_MUTEX(e, m, g) do { if (e) PHYSFS_setErrorCode(e); __PHYSFS_platformReleaseMutex(m); goto g; } while (0)
274
#define GOTO_MUTEX_ERRPASS(m, g) do { __PHYSFS_platformReleaseMutex(m); goto g; } while (0)
275
#define GOTO_IF_MUTEX(c, e, m, g) do { if (c) { if (e) PHYSFS_setErrorCode(e); __PHYSFS_platformReleaseMutex(m); goto g; } } while (0)
276
#define GOTO_IF_MUTEX_ERRPASS(c, m, g) do { if (c) { __PHYSFS_platformReleaseMutex(m); goto g; } } while (0)
277
 
278
#define __PHYSFS_ARRAYLEN(x) ( (sizeof (x)) / (sizeof (x[0])) )
279
 
280
#ifdef PHYSFS_NO_64BIT_SUPPORT
281
#define __PHYSFS_SI64(x) ((PHYSFS_sint64) (x))
282
#define __PHYSFS_UI64(x) ((PHYSFS_uint64) (x))
283
#elif (defined __GNUC__)
284
#define __PHYSFS_SI64(x) x##LL
285
#define __PHYSFS_UI64(x) x##ULL
286
#elif (defined _MSC_VER)
287
#define __PHYSFS_SI64(x) x##i64
288
#define __PHYSFS_UI64(x) x##ui64
289
#else
290
#define __PHYSFS_SI64(x) ((PHYSFS_sint64) (x))
291
#define __PHYSFS_UI64(x) ((PHYSFS_uint64) (x))
292
#endif
293
 
294
 
295
/*
296
 * Check if a ui64 will fit in the platform's address space.
297
 *  The initial sizeof check will optimize this macro out entirely on
298
 *  64-bit (and larger?!) platforms, and the other condition will
299
 *  return zero or non-zero if the variable will fit in the platform's
300
 *  size_t, suitable to pass to malloc. This is kinda messy, but effective.
301
 */
302
#define __PHYSFS_ui64FitsAddressSpace(s) ( \
303
    (sizeof (PHYSFS_uint64) <= sizeof (size_t)) || \
304
    ((s) < (__PHYSFS_UI64(0xFFFFFFFFFFFFFFFF) >> (64-(sizeof(size_t)*8)))) \
305
)
306
 
307
/*
308
 * Like strdup(), but uses the current PhysicsFS allocator.
309
 */
310
char *__PHYSFS_strdup(const char *str);
311
 
312
/*
313
 * Give a hash value for a C string (uses djb's xor hashing algorithm).
314
 */
315
PHYSFS_uint32 __PHYSFS_hashString(const char *str, size_t len);
316
 
317
 
318
/*
319
 * The current allocator. Not valid before PHYSFS_init is called!
320
 */
321
extern PHYSFS_Allocator __PHYSFS_AllocatorHooks;
322
 
323
/* convenience macro to make this less cumbersome internally... */
324
#define allocator __PHYSFS_AllocatorHooks
325
 
326
/*
327
 * Create a PHYSFS_Io for a file in the physical filesystem.
328
 *  This path is in platform-dependent notation. (mode) must be 'r', 'w', or
329
 *  'a' for Read, Write, or Append.
330
 */
331
PHYSFS_Io *__PHYSFS_createNativeIo(const char *path, const int mode);
332
 
333
/*
334
 * Create a PHYSFS_Io for a buffer of memory (READ-ONLY). If you already
335
 *  have one of these, just use its duplicate() method, and it'll increment
336
 *  its refcount without allocating a copy of the buffer.
337
 */
338
PHYSFS_Io *__PHYSFS_createMemoryIo(const void *buf, PHYSFS_uint64 len,
339
                                   void (*destruct)(void *));
340
 
341
 
342
/*
343
 * Read (len) bytes from (io) into (buf). Returns non-zero on success,
344
 *  zero on i/o error. Literally: "return (io->read(io, buf, len) == len);"
345
 */
346
int __PHYSFS_readAll(PHYSFS_Io *io, void *buf, const size_t len);
347
 
348
 
349
/* These are shared between some archivers. */
350
 
351
void UNPK_abandonArchive(void *opaque);
352
void UNPK_closeArchive(void *opaque);
353
void *UNPK_openArchive(PHYSFS_Io *io);
354
void *UNPK_addEntry(void *opaque, char *name, const int isdir,
355
                    const PHYSFS_sint64 ctime, const PHYSFS_sint64 mtime,
356
                    const PHYSFS_uint64 pos, const PHYSFS_uint64 len);
357
PHYSFS_Io *UNPK_openRead(void *opaque, const char *name);
358
PHYSFS_Io *UNPK_openWrite(void *opaque, const char *name);
359
PHYSFS_Io *UNPK_openAppend(void *opaque, const char *name);
360
int UNPK_remove(void *opaque, const char *name);
361
int UNPK_mkdir(void *opaque, const char *name);
362
int UNPK_stat(void *opaque, const char *fn, PHYSFS_Stat *st);
363
#define UNPK_enumerate __PHYSFS_DirTreeEnumerate
364
 
365
 
366
 
367
/* Optional API many archivers use this to manage their directory tree. */
368
/* !!! FIXME: document this better. */
369
 
370
typedef struct __PHYSFS_DirTreeEntry
371
{
372
    char *name;                              /* Full path in archive.        */
373
    struct __PHYSFS_DirTreeEntry *hashnext;  /* next item in hash bucket.    */
374
    struct __PHYSFS_DirTreeEntry *children;  /* linked list of kids, if dir. */
375
    struct __PHYSFS_DirTreeEntry *sibling;   /* next item in same dir.       */
376
    int isdir;
377
} __PHYSFS_DirTreeEntry;
378
 
379
typedef struct __PHYSFS_DirTree
380
{
381
    __PHYSFS_DirTreeEntry *root;    /* root of directory tree.             */
382
    __PHYSFS_DirTreeEntry **hash;  /* all entries hashed for fast lookup. */
383
    size_t hashBuckets;            /* number of buckets in hash.          */
384
    size_t entrylen;    /* size in bytes of entries (including subclass). */
385
} __PHYSFS_DirTree;
386
 
387
 
388
int __PHYSFS_DirTreeInit(__PHYSFS_DirTree *dt, const size_t entrylen);
389
void *__PHYSFS_DirTreeAdd(__PHYSFS_DirTree *dt, char *name, const int isdir);
390
void *__PHYSFS_DirTreeFind(__PHYSFS_DirTree *dt, const char *path);
391
PHYSFS_EnumerateCallbackResult __PHYSFS_DirTreeEnumerate(void *opaque,
392
                              const char *dname, PHYSFS_EnumerateCallback cb,
393
                              const char *origdir, void *callbackdata);
394
void __PHYSFS_DirTreeDeinit(__PHYSFS_DirTree *dt);
395
 
396
 
397
 
398
/*--------------------------------------------------------------------------*/
399
/*--------------------------------------------------------------------------*/
400
/*------------                                              ----------------*/
401
/*------------  You MUST implement the following functions  ----------------*/
402
/*------------        if porting to a new platform.         ----------------*/
403
/*------------     (see platform/unix.c for an example)     ----------------*/
404
/*------------                                              ----------------*/
405
/*--------------------------------------------------------------------------*/
406
/*--------------------------------------------------------------------------*/
407
 
408
 
409
/*
410
 * The dir separator; '/' on unix, '\\' on win32, ":" on MacOS, etc...
411
 *  Obviously, this isn't a function. If you need more than one char for this,
412
 *  you'll need to pull some old pieces of PhysicsFS out of revision control.
413
 */
414
#if defined(PHYSFS_PLATFORM_WINDOWS) || defined(PHYSFS_PLATFORM_OS2)
415
#define __PHYSFS_platformDirSeparator '\\'
416
#else
417
#define __PHYSFS_STANDARD_DIRSEP 1
418
#define __PHYSFS_platformDirSeparator '/'
419
#endif
420
 
421
/*
422
 * Initialize the platform. This is called when PHYSFS_init() is called from
423
 *  the application.
424
 *
425
 * Return zero if there was a catastrophic failure (which prevents you from
426
 *  functioning at all), and non-zero otherwise.
427
 */
428
int __PHYSFS_platformInit(void);
429
 
430
 
431
/*
432
 * Deinitialize the platform. This is called when PHYSFS_deinit() is called
433
 *  from the application. You can use this to clean up anything you've
434
 *  allocated in your platform driver.
435
 */
436
void __PHYSFS_platformDeinit(void);
437
 
438
 
439
/*
440
 * Open a file for reading. (filename) is in platform-dependent notation. The
441
 *  file pointer should be positioned on the first byte of the file.
442
 *
443
 * The return value will be some platform-specific datatype that is opaque to
444
 *  the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32.
445
 *
446
 * The same file can be opened for read multiple times, and each should have
447
 *  a unique file handle; this is frequently employed to prevent race
448
 *  conditions in the archivers.
449
 *
450
 * Call PHYSFS_setErrorCode() and return (NULL) if the file can't be opened.
451
 */
452
void *__PHYSFS_platformOpenRead(const char *filename);
453
 
454
 
455
/*
456
 * Open a file for writing. (filename) is in platform-dependent notation. If
457
 *  the file exists, it should be truncated to zero bytes, and if it doesn't
458
 *  exist, it should be created as a zero-byte file. The file pointer should
459
 *  be positioned on the first byte of the file.
460
 *
461
 * The return value will be some platform-specific datatype that is opaque to
462
 *  the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32,
463
 *  etc.
464
 *
465
 * Opening a file for write multiple times has undefined results.
466
 *
467
 * Call PHYSFS_setErrorCode() and return (NULL) if the file can't be opened.
468
 */
469
void *__PHYSFS_platformOpenWrite(const char *filename);
470
 
471
 
472
/*
473
 * Open a file for appending. (filename) is in platform-dependent notation. If
474
 *  the file exists, the file pointer should be place just past the end of the
475
 *  file, so that the first write will be one byte after the current end of
476
 *  the file. If the file doesn't exist, it should be created as a zero-byte
477
 *  file. The file pointer should be positioned on the first byte of the file.
478
 *
479
 * The return value will be some platform-specific datatype that is opaque to
480
 *  the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32,
481
 *  etc.
482
 *
483
 * Opening a file for append multiple times has undefined results.
484
 *
485
 * Call PHYSFS_setErrorCode() and return (NULL) if the file can't be opened.
486
 */
487
void *__PHYSFS_platformOpenAppend(const char *filename);
488
 
489
/*
490
 * Read more data from a platform-specific file handle. (opaque) should be
491
 *  cast to whatever data type your platform uses. Read a maximum of (len)
492
 *  8-bit bytes to the area pointed to by (buf). If there isn't enough data
493
 *  available, return the number of bytes read, and position the file pointer
494
 *  immediately after those bytes.
495
 *  On success, return (len) and position the file pointer immediately past
496
 *  the end of the last read byte. Return (-1) if there is a catastrophic
497
 *  error, and call PHYSFS_setErrorCode() to describe the problem; the file
498
 *  pointer should not move in such a case. A partial read is success; only
499
 *  return (-1) on total failure; presumably, the next read call after a
500
 *  partial read will fail as such.
501
 */
502
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buf, PHYSFS_uint64 len);
503
 
504
/*
505
 * Write more data to a platform-specific file handle. (opaque) should be
506
 *  cast to whatever data type your platform uses. Write a maximum of (len)
507
 *  8-bit bytes from the area pointed to by (buffer). If there is a problem,
508
 *  return the number of bytes written, and position the file pointer
509
 *  immediately after those bytes. Return (-1) if there is a catastrophic
510
 *  error, and call PHYSFS_setErrorCode() to describe the problem; the file
511
 *  pointer should not move in such a case. A partial write is success; only
512
 *  return (-1) on total failure; presumably, the next write call after a
513
 *  partial write will fail as such.
514
 */
515
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
516
                                     PHYSFS_uint64 len);
517
 
518
/*
519
 * Set the file pointer to a new position. (opaque) should be cast to
520
 *  whatever data type your platform uses. (pos) specifies the number
521
 *  of 8-bit bytes to seek to from the start of the file. Seeking past the
522
 *  end of the file is an error condition, and you should check for it.
523
 *
524
 * Not all file types can seek; this is to be expected by the caller.
525
 *
526
 * On error, call PHYSFS_setErrorCode() and return zero. On success, return
527
 *  a non-zero value.
528
 */
529
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos);
530
 
531
 
532
/*
533
 * Get the file pointer's position, in an 8-bit byte offset from the start of
534
 *  the file. (opaque) should be cast to whatever data type your platform
535
 *  uses.
536
 *
537
 * Not all file types can "tell"; this is to be expected by the caller.
538
 *
539
 * On error, call PHYSFS_setErrorCode() and return -1. On success, return >= 0.
540
 */
541
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque);
542
 
543
 
544
/*
545
 * Determine the current size of a file, in 8-bit bytes, from an open file.
546
 *
547
 * The caller expects that this information may not be available for all
548
 *  file types on all platforms.
549
 *
550
 * Return -1 if you can't do it, and call PHYSFS_setErrorCode(). Otherwise,
551
 *  return the file length in 8-bit bytes.
552
 */
553
PHYSFS_sint64 __PHYSFS_platformFileLength(void *handle);
554
 
555
 
556
/*
557
 * Read filesystem metadata for a specific path.
558
 *
559
 * This needs to fill in all the fields of (stat). For fields that might not
560
 *  mean anything on a platform (access time, perhaps), choose a reasonable
561
 *  default. if (follow), we want to follow symlinks and stat what they
562
 *  link to and not the link itself.
563
 *
564
 *  Return zero on failure, non-zero on success.
565
 */
566
int __PHYSFS_platformStat(const char *fn, PHYSFS_Stat *stat, const int follow);
567
 
568
/*
569
 * Flush any pending writes to disk. (opaque) should be cast to whatever data
570
 *  type your platform uses. Be sure to check for errors; the caller expects
571
 *  that this function can fail if there was a flushing error, etc.
572
 *
573
 *  Return zero on failure, non-zero on success.
574
 */
575
int __PHYSFS_platformFlush(void *opaque);
576
 
577
/*
578
 * Close file and deallocate resources. (opaque) should be cast to whatever
579
 *  data type your platform uses. This should close the file in any scenario:
580
 *  flushing is a separate function call, and this function should never fail.
581
 *
582
 * You should clean up all resources associated with (opaque); the pointer
583
 *  will be considered invalid after this call.
584
 */
585
void __PHYSFS_platformClose(void *opaque);
586
 
587
/*
588
 * Platform implementation of PHYSFS_getCdRomDirsCallback()...
589
 *  CD directories are discovered and reported to the callback one at a time.
590
 *  Pointers passed to the callback are assumed to be invalid to the
591
 *  application after the callback returns, so you can free them or whatever.
592
 *  Callback does not assume results will be sorted in any meaningful way.
593
 */
594
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data);
595
 
596
/*
597
 * Calculate the base dir, if your platform needs special consideration.
598
 *  Just return NULL if the standard routines will suffice. (see
599
 *  calculateBaseDir() in physfs.c ...)
600
 * Your string must end with a dir separator if you don't return NULL.
601
 *  Caller will allocator.Free() the retval if it's not NULL.
602
 */
603
char *__PHYSFS_platformCalcBaseDir(const char *argv0);
604
 
605
/*
606
 * Get the platform-specific user dir.
607
 * As of PhysicsFS 2.1, returning NULL means fatal error.
608
 * Your string must end with a dir separator if you don't return NULL.
609
 *  Caller will allocator.Free() the retval if it's not NULL.
610
 */
611
char *__PHYSFS_platformCalcUserDir(void);
612
 
613
 
614
/* This is the cached version from PHYSFS_init(). This is a fast call. */
615
const char *__PHYSFS_getUserDir(void);  /* not deprecated internal version. */
616
 
617
 
618
/*
619
 * Get the platform-specific pref dir.
620
 * Returning NULL means fatal error.
621
 * Your string must end with a dir separator if you don't return NULL.
622
 *  Caller will allocator.Free() the retval if it's not NULL.
623
 *  Caller will make missing directories if necessary; this just reports
624
 *   the final path.
625
 */
626
char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app);
627
 
628
 
629
/*
630
 * Return a pointer that uniquely identifies the current thread.
631
 *  On a platform without threading, (0x1) will suffice. These numbers are
632
 *  arbitrary; the only requirement is that no two threads have the same
633
 *  pointer.
634
 */
635
void *__PHYSFS_platformGetThreadID(void);
636
 
637
 
638
/*
639
 * Enumerate a directory of files. This follows the rules for the
640
 *  PHYSFS_Archiver::enumerate() method, except that the (dirName) that is
641
 *  passed to this function is converted to platform-DEPENDENT notation by
642
 *  the caller. The PHYSFS_Archiver version uses platform-independent
643
 *  notation. Note that ".", "..", and other meta-entries should always
644
 *  be ignored.
645
 */
646
PHYSFS_EnumerateCallbackResult __PHYSFS_platformEnumerate(const char *dirname,
647
                               PHYSFS_EnumerateCallback callback,
648
                               const char *origdir, void *callbackdata);
649
 
650
/*
651
 * Make a directory in the actual filesystem. (path) is specified in
652
 *  platform-dependent notation. On error, return zero and set the error
653
 *  message. Return non-zero on success.
654
 */
655
int __PHYSFS_platformMkDir(const char *path);
656
 
657
 
658
/*
659
 * Remove a file or directory entry in the actual filesystem. (path) is
660
 *  specified in platform-dependent notation. Note that this deletes files
661
 *  _and_ directories, so you might need to do some determination.
662
 *  Non-empty directories should report an error and not delete themselves
663
 *  or their contents.
664
 *
665
 * Deleting a symlink should remove the link, not what it points to.
666
 *
667
 * On error, return zero and set the error message. Return non-zero on success.
668
 */
669
int __PHYSFS_platformDelete(const char *path);
670
 
671
 
672
/*
673
 * Create a platform-specific mutex. This can be whatever datatype your
674
 *  platform uses for mutexes, but it is cast to a (void *) for abstractness.
675
 *
676
 * Return (NULL) if you couldn't create one. Systems without threads can
677
 *  return any arbitrary non-NULL value.
678
 */
679
void *__PHYSFS_platformCreateMutex(void);
680
 
681
/*
682
 * Destroy a platform-specific mutex, and clean up any resources associated
683
 *  with it. (mutex) is a value previously returned by
684
 *  __PHYSFS_platformCreateMutex(). This can be a no-op on single-threaded
685
 *  platforms.
686
 */
687
void __PHYSFS_platformDestroyMutex(void *mutex);
688
 
689
/*
690
 * Grab possession of a platform-specific mutex. Mutexes should be recursive;
691
 *  that is, the same thread should be able to call this function multiple
692
 *  times in a row without causing a deadlock. This function should block
693
 *  until a thread can gain possession of the mutex.
694
 *
695
 * Return non-zero if the mutex was grabbed, zero if there was an
696
 *  unrecoverable problem grabbing it (this should not be a matter of
697
 *  timing out! We're talking major system errors; block until the mutex
698
 *  is available otherwise.)
699
 *
700
 * _DO NOT_ call PHYSFS_setErrorCode() in here! Since setErrorCode calls this
701
 *  function, you'll cause an infinite recursion. This means you can't
702
 *  use the BAIL_*MACRO* macros, either.
703
 */
704
int __PHYSFS_platformGrabMutex(void *mutex);
705
 
706
/*
707
 * Relinquish possession of the mutex when this method has been called
708
 *  once for each time that platformGrabMutex was called. Once possession has
709
 *  been released, the next thread in line to grab the mutex (if any) may
710
 *  proceed.
711
 *
712
 * _DO NOT_ call PHYSFS_setErrorCode() in here! Since setErrorCode calls this
713
 *  function, you'll cause an infinite recursion. This means you can't
714
 *  use the BAIL_*MACRO* macros, either.
715
 */
716
void __PHYSFS_platformReleaseMutex(void *mutex);
717
 
718
#if PHYSFS_HAVE_PRAGMA_VISIBILITY
719
#pragma GCC visibility pop
720
#endif
721
 
722
#ifdef __cplusplus
723
}
724
#endif
725
 
726
#endif
727
 
728
/* end of physfs_internal.h ... */
729