Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  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.  
  730.