misc/libphysfs/physfs_internal.h
branchui-scaling
changeset 15283 c4fd2813b127
parent 13390 0135e64c6c66
parent 15279 7ab5cf405686
child 15663 d92eeb468dad
equal deleted inserted replaced
13390:0135e64c6c66 15283:c4fd2813b127
     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