misc/libphysfs/archiver_zip.c
author nemo
Sun, 04 Jan 2015 00:44:14 -0500
branch0.9.21
changeset 10743 1d16c5414fee
parent 10017 de822cd3df3a
child 12212 ea891871f481
permissions -rw-r--r--
Intent is to allow filtering by arbitrary flag combinations. This isn't actually working yet. No idea why. It seems it should. Tired though, so will look at it tomorrow.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
7768
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
     1
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
     2
 * ZIP support routines for PhysicsFS.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
     3
 *
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
     4
 * Please see the file LICENSE.txt in the source's root directory.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
     5
 *
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
     6
 *  This file written by Ryan C. Gordon, with some peeking at "unzip.c"
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
     7
 *   by Gilles Vollant.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
     8
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
     9
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    10
#define __PHYSICSFS_INTERNAL__
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    11
#include "physfs_internal.h"
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    12
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    13
#if PHYSFS_SUPPORTS_ZIP
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    14
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    15
#include <errno.h>
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    16
#include <time.h>
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    17
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    18
#define USE_MINIZ 1
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    19
#if USE_MINIZ
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    20
#include "physfs_miniz.h"
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    21
#else
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    22
#include <zlib.h>
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    23
#endif
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    24
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    25
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    26
 * A buffer of ZIP_READBUFSIZE is allocated for each compressed file opened,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    27
 *  and is freed when you close the file; compressed data is read into
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    28
 *  this buffer, and then is decompressed into the buffer passed to
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    29
 *  PHYSFS_read().
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    30
 *
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    31
 * Uncompressed entries in a zipfile do not allocate this buffer; they just
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    32
 *  read data directly into the buffer passed to PHYSFS_read().
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    33
 *
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    34
 * Depending on your speed and memory requirements, you should tweak this
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    35
 *  value.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    36
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    37
#define ZIP_READBUFSIZE   (16 * 1024)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    38
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    39
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    40
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    41
 * Entries are "unresolved" until they are first opened. At that time,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    42
 *  local file headers parsed/validated, data offsets will be updated to look
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    43
 *  at the actual file data instead of the header, and symlinks will be
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    44
 *  followed and optimized. This means that we don't seek and read around the
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    45
 *  archive until forced to do so, and after the first time, we had to do
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    46
 *  less reading and parsing, which is very CD-ROM friendly.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    47
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    48
typedef enum
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    49
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    50
    ZIP_UNRESOLVED_FILE,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    51
    ZIP_UNRESOLVED_SYMLINK,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    52
    ZIP_RESOLVING,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    53
    ZIP_RESOLVED,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    54
    ZIP_BROKEN_FILE,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    55
    ZIP_BROKEN_SYMLINK
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    56
} ZipResolveType;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    57
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    58
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    59
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    60
 * One ZIPentry is kept for each file in an open ZIP archive.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    61
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    62
typedef struct _ZIPentry
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    63
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    64
    char *name;                         /* Name of file in archive        */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    65
    struct _ZIPentry *symlink;          /* NULL or file we symlink to     */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    66
    ZipResolveType resolved;            /* Have we resolved file/symlink? */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    67
    PHYSFS_uint64 offset;               /* offset of data in archive      */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    68
    PHYSFS_uint16 version;              /* version made by                */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    69
    PHYSFS_uint16 version_needed;       /* version needed to extract      */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    70
    PHYSFS_uint16 compression_method;   /* compression method             */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    71
    PHYSFS_uint32 crc;                  /* crc-32                         */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    72
    PHYSFS_uint64 compressed_size;      /* compressed size                */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    73
    PHYSFS_uint64 uncompressed_size;    /* uncompressed size              */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    74
    PHYSFS_sint64 last_mod_time;        /* last file mod time             */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    75
} ZIPentry;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    76
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    77
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    78
 * One ZIPinfo is kept for each open ZIP archive.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    79
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    80
typedef struct
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    81
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    82
    PHYSFS_Io *io;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    83
    int zip64;                /* non-zero if this is a Zip64 archive. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    84
    PHYSFS_uint64 entryCount; /* Number of files in ZIP.              */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    85
    ZIPentry *entries;        /* info on all files in ZIP.            */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    86
} ZIPinfo;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    87
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    88
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    89
 * One ZIPfileinfo is kept for each open file in a ZIP archive.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    90
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    91
typedef struct
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    92
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    93
    ZIPentry *entry;                      /* Info on file.              */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    94
    PHYSFS_Io *io;                        /* physical file handle.      */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    95
    PHYSFS_uint32 compressed_position;    /* offset in compressed data. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    96
    PHYSFS_uint32 uncompressed_position;  /* tell() position.           */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    97
    PHYSFS_uint8 *buffer;                 /* decompression buffer.      */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    98
    z_stream stream;                      /* zlib stream state.         */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
    99
} ZIPfileinfo;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   100
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   101
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   102
/* Magic numbers... */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   103
#define ZIP_LOCAL_FILE_SIG                          0x04034b50
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   104
#define ZIP_CENTRAL_DIR_SIG                         0x02014b50
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   105
#define ZIP_END_OF_CENTRAL_DIR_SIG                  0x06054b50
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   106
#define ZIP64_END_OF_CENTRAL_DIR_SIG                0x06064b50
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   107
#define ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIG  0x07064b50
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   108
#define ZIP64_EXTENDED_INFO_EXTRA_FIELD_SIG         0x0001
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   109
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   110
/* compression methods... */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   111
#define COMPMETH_NONE 0
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   112
/* ...and others... */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   113
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   114
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   115
#define UNIX_FILETYPE_MASK    0170000
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   116
#define UNIX_FILETYPE_SYMLINK 0120000
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   117
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   118
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   119
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   120
 * Bridge physfs allocation functions to zlib's format...
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   121
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   122
static voidpf zlibPhysfsAlloc(voidpf opaque, uInt items, uInt size)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   123
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   124
    return ((PHYSFS_Allocator *) opaque)->Malloc(items * size);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   125
} /* zlibPhysfsAlloc */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   126
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   127
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   128
 * Bridge physfs allocation functions to zlib's format...
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   129
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   130
static void zlibPhysfsFree(voidpf opaque, voidpf address)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   131
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   132
    ((PHYSFS_Allocator *) opaque)->Free(address);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   133
} /* zlibPhysfsFree */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   134
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   135
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   136
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   137
 * Construct a new z_stream to a sane state.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   138
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   139
static void initializeZStream(z_stream *pstr)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   140
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   141
    memset(pstr, '\0', sizeof (z_stream));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   142
    pstr->zalloc = zlibPhysfsAlloc;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   143
    pstr->zfree = zlibPhysfsFree;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   144
    pstr->opaque = &allocator;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   145
} /* initializeZStream */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   146
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   147
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   148
static PHYSFS_ErrorCode zlib_error_code(int rc)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   149
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   150
    switch (rc)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   151
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   152
        case Z_OK: return PHYSFS_ERR_OK;  /* not an error. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   153
        case Z_STREAM_END: return PHYSFS_ERR_OK; /* not an error. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   154
        case Z_ERRNO: return PHYSFS_ERR_IO;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   155
        case Z_MEM_ERROR: return PHYSFS_ERR_OUT_OF_MEMORY;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   156
        default: return PHYSFS_ERR_CORRUPT;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   157
    } /* switch */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   158
} /* zlib_error_string */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   159
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   160
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   161
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   162
 * Wrap all zlib calls in this, so the physfs error state is set appropriately.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   163
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   164
static int zlib_err(const int rc)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   165
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   166
    __PHYSFS_setError(zlib_error_code(rc));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   167
    return rc;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   168
} /* zlib_err */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   169
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   170
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   171
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   172
 * Read an unsigned 64-bit int and swap to native byte order.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   173
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   174
static int readui64(PHYSFS_Io *io, PHYSFS_uint64 *val)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   175
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   176
    PHYSFS_uint64 v;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   177
    BAIL_IF_MACRO(!__PHYSFS_readAll(io, &v, sizeof (v)), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   178
    *val = PHYSFS_swapULE64(v);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   179
    return 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   180
} /* readui64 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   181
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   182
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   183
 * Read an unsigned 32-bit int and swap to native byte order.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   184
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   185
static int readui32(PHYSFS_Io *io, PHYSFS_uint32 *val)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   186
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   187
    PHYSFS_uint32 v;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   188
    BAIL_IF_MACRO(!__PHYSFS_readAll(io, &v, sizeof (v)), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   189
    *val = PHYSFS_swapULE32(v);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   190
    return 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   191
} /* readui32 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   192
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   193
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   194
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   195
 * Read an unsigned 16-bit int and swap to native byte order.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   196
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   197
static int readui16(PHYSFS_Io *io, PHYSFS_uint16 *val)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   198
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   199
    PHYSFS_uint16 v;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   200
    BAIL_IF_MACRO(!__PHYSFS_readAll(io, &v, sizeof (v)), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   201
    *val = PHYSFS_swapULE16(v);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   202
    return 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   203
} /* readui16 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   204
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   205
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   206
static PHYSFS_sint64 ZIP_read(PHYSFS_Io *_io, void *buf, PHYSFS_uint64 len)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   207
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   208
    ZIPfileinfo *finfo = (ZIPfileinfo *) _io->opaque;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   209
    PHYSFS_Io *io = finfo->io;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   210
    ZIPentry *entry = finfo->entry;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   211
    PHYSFS_sint64 retval = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   212
    PHYSFS_sint64 maxread = (PHYSFS_sint64) len;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   213
    PHYSFS_sint64 avail = entry->uncompressed_size -
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   214
                          finfo->uncompressed_position;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   215
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   216
    if (avail < maxread)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   217
        maxread = avail;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   218
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   219
    BAIL_IF_MACRO(maxread == 0, ERRPASS, 0);    /* quick rejection. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   220
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   221
    if (entry->compression_method == COMPMETH_NONE)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   222
        retval = io->read(io, buf, maxread);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   223
    else
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   224
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   225
        finfo->stream.next_out = buf;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   226
        finfo->stream.avail_out = (uInt) maxread;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   227
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   228
        while (retval < maxread)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   229
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   230
            PHYSFS_uint32 before = finfo->stream.total_out;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   231
            int rc;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   232
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   233
            if (finfo->stream.avail_in == 0)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   234
            {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   235
                PHYSFS_sint64 br;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   236
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   237
                br = entry->compressed_size - finfo->compressed_position;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   238
                if (br > 0)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   239
                {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   240
                    if (br > ZIP_READBUFSIZE)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   241
                        br = ZIP_READBUFSIZE;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   242
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   243
                    br = io->read(io, finfo->buffer, (PHYSFS_uint64) br);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   244
                    if (br <= 0)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   245
                        break;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   246
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   247
                    finfo->compressed_position += (PHYSFS_uint32) br;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   248
                    finfo->stream.next_in = finfo->buffer;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   249
                    finfo->stream.avail_in = (PHYSFS_uint32) br;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   250
                } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   251
            } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   252
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   253
            rc = zlib_err(inflate(&finfo->stream, Z_SYNC_FLUSH));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   254
            retval += (finfo->stream.total_out - before);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   255
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   256
            if (rc != Z_OK)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   257
                break;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   258
        } /* while */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   259
    } /* else */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   260
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   261
    if (retval > 0)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   262
        finfo->uncompressed_position += (PHYSFS_uint32) retval;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   263
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   264
    return retval;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   265
} /* ZIP_read */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   266
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   267
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   268
static PHYSFS_sint64 ZIP_write(PHYSFS_Io *io, const void *b, PHYSFS_uint64 len)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   269
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   270
    BAIL_MACRO(PHYSFS_ERR_READ_ONLY, -1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   271
} /* ZIP_write */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   272
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   273
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   274
static PHYSFS_sint64 ZIP_tell(PHYSFS_Io *io)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   275
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   276
    return ((ZIPfileinfo *) io->opaque)->uncompressed_position;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   277
} /* ZIP_tell */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   278
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   279
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   280
static int ZIP_seek(PHYSFS_Io *_io, PHYSFS_uint64 offset)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   281
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   282
    ZIPfileinfo *finfo = (ZIPfileinfo *) _io->opaque;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   283
    ZIPentry *entry = finfo->entry;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   284
    PHYSFS_Io *io = finfo->io;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   285
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   286
    BAIL_IF_MACRO(offset > entry->uncompressed_size, PHYSFS_ERR_PAST_EOF, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   287
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   288
    if (entry->compression_method == COMPMETH_NONE)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   289
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   290
        const PHYSFS_sint64 newpos = offset + entry->offset;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   291
        BAIL_IF_MACRO(!io->seek(io, newpos), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   292
        finfo->uncompressed_position = (PHYSFS_uint32) offset;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   293
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   294
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   295
    else
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   296
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   297
        /*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   298
         * If seeking backwards, we need to redecode the file
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   299
         *  from the start and throw away the compressed bits until we hit
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   300
         *  the offset we need. If seeking forward, we still need to
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   301
         *  decode, but we don't rewind first.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   302
         */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   303
        if (offset < finfo->uncompressed_position)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   304
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   305
            /* we do a copy so state is sane if inflateInit2() fails. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   306
            z_stream str;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   307
            initializeZStream(&str);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   308
            if (zlib_err(inflateInit2(&str, -MAX_WBITS)) != Z_OK)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   309
                return 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   310
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   311
            if (!io->seek(io, entry->offset))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   312
                return 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   313
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   314
            inflateEnd(&finfo->stream);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   315
            memcpy(&finfo->stream, &str, sizeof (z_stream));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   316
            finfo->uncompressed_position = finfo->compressed_position = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   317
        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   318
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   319
        while (finfo->uncompressed_position != offset)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   320
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   321
            PHYSFS_uint8 buf[512];
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   322
            PHYSFS_uint32 maxread;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   323
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   324
            maxread = (PHYSFS_uint32) (offset - finfo->uncompressed_position);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   325
            if (maxread > sizeof (buf))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   326
                maxread = sizeof (buf);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   327
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   328
            if (ZIP_read(_io, buf, maxread) != maxread)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   329
                return 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   330
        } /* while */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   331
    } /* else */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   332
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   333
    return 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   334
} /* ZIP_seek */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   335
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   336
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   337
static PHYSFS_sint64 ZIP_length(PHYSFS_Io *io)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   338
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   339
    const ZIPfileinfo *finfo = (ZIPfileinfo *) io->opaque;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   340
    return (PHYSFS_sint64) finfo->entry->uncompressed_size;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   341
} /* ZIP_length */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   342
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   343
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   344
static PHYSFS_Io *zip_get_io(PHYSFS_Io *io, ZIPinfo *inf, ZIPentry *entry);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   345
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   346
static PHYSFS_Io *ZIP_duplicate(PHYSFS_Io *io)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   347
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   348
    ZIPfileinfo *origfinfo = (ZIPfileinfo *) io->opaque;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   349
    PHYSFS_Io *retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   350
    ZIPfileinfo *finfo = (ZIPfileinfo *) allocator.Malloc(sizeof (ZIPfileinfo));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   351
    GOTO_IF_MACRO(!retval, PHYSFS_ERR_OUT_OF_MEMORY, failed);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   352
    GOTO_IF_MACRO(!finfo, PHYSFS_ERR_OUT_OF_MEMORY, failed);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   353
    memset(finfo, '\0', sizeof (*finfo));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   354
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   355
    finfo->entry = origfinfo->entry;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   356
    finfo->io = zip_get_io(origfinfo->io, NULL, finfo->entry);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   357
    GOTO_IF_MACRO(!finfo->io, ERRPASS, failed);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   358
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   359
    if (finfo->entry->compression_method != COMPMETH_NONE)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   360
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   361
        finfo->buffer = (PHYSFS_uint8 *) allocator.Malloc(ZIP_READBUFSIZE);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   362
        GOTO_IF_MACRO(!finfo->buffer, PHYSFS_ERR_OUT_OF_MEMORY, failed);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   363
        if (zlib_err(inflateInit2(&finfo->stream, -MAX_WBITS)) != Z_OK)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   364
            goto failed;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   365
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   366
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   367
    memcpy(retval, io, sizeof (PHYSFS_Io));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   368
    retval->opaque = finfo;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   369
    return retval;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   370
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   371
failed:
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   372
    if (finfo != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   373
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   374
        if (finfo->io != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   375
            finfo->io->destroy(finfo->io);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   376
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   377
        if (finfo->buffer != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   378
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   379
            allocator.Free(finfo->buffer);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   380
            inflateEnd(&finfo->stream);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   381
        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   382
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   383
        allocator.Free(finfo);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   384
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   385
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   386
    if (retval != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   387
        allocator.Free(retval);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   388
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   389
    return NULL;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   390
} /* ZIP_duplicate */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   391
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   392
static int ZIP_flush(PHYSFS_Io *io) { return 1;  /* no write support. */ }
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   393
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   394
static void ZIP_destroy(PHYSFS_Io *io)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   395
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   396
    ZIPfileinfo *finfo = (ZIPfileinfo *) io->opaque;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   397
    finfo->io->destroy(finfo->io);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   398
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   399
    if (finfo->entry->compression_method != COMPMETH_NONE)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   400
        inflateEnd(&finfo->stream);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   401
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   402
    if (finfo->buffer != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   403
        allocator.Free(finfo->buffer);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   404
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   405
    allocator.Free(finfo);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   406
    allocator.Free(io);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   407
} /* ZIP_destroy */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   408
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   409
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   410
static const PHYSFS_Io ZIP_Io =
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   411
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   412
    CURRENT_PHYSFS_IO_API_VERSION, NULL,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   413
    ZIP_read,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   414
    ZIP_write,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   415
    ZIP_seek,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   416
    ZIP_tell,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   417
    ZIP_length,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   418
    ZIP_duplicate,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   419
    ZIP_flush,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   420
    ZIP_destroy
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   421
};
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   422
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   423
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   424
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   425
static PHYSFS_sint64 zip_find_end_of_central_dir(PHYSFS_Io *io, PHYSFS_sint64 *len)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   426
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   427
    PHYSFS_uint8 buf[256];
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   428
    PHYSFS_uint8 extra[4] = { 0, 0, 0, 0 };
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   429
    PHYSFS_sint32 i = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   430
    PHYSFS_sint64 filelen;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   431
    PHYSFS_sint64 filepos;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   432
    PHYSFS_sint32 maxread;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   433
    PHYSFS_sint32 totalread = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   434
    int found = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   435
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   436
    filelen = io->length(io);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   437
    BAIL_IF_MACRO(filelen == -1, ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   438
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   439
    /*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   440
     * Jump to the end of the file and start reading backwards.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   441
     *  The last thing in the file is the zipfile comment, which is variable
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   442
     *  length, and the field that specifies its size is before it in the
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   443
     *  file (argh!)...this means that we need to scan backwards until we
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   444
     *  hit the end-of-central-dir signature. We can then sanity check that
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   445
     *  the comment was as big as it should be to make sure we're in the
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   446
     *  right place. The comment length field is 16 bits, so we can stop
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   447
     *  searching for that signature after a little more than 64k at most,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   448
     *  and call it a corrupted zipfile.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   449
     */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   450
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   451
    if (sizeof (buf) < filelen)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   452
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   453
        filepos = filelen - sizeof (buf);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   454
        maxread = sizeof (buf);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   455
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   456
    else
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   457
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   458
        filepos = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   459
        maxread = (PHYSFS_uint32) filelen;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   460
    } /* else */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   461
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   462
    while ((totalread < filelen) && (totalread < 65557))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   463
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   464
        BAIL_IF_MACRO(!io->seek(io, filepos), ERRPASS, -1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   465
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   466
        /* make sure we catch a signature between buffers. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   467
        if (totalread != 0)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   468
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   469
            if (!__PHYSFS_readAll(io, buf, maxread - 4))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   470
                return -1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   471
            memcpy(&buf[maxread - 4], &extra, sizeof (extra));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   472
            totalread += maxread - 4;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   473
        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   474
        else
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   475
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   476
            if (!__PHYSFS_readAll(io, buf, maxread))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   477
                return -1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   478
            totalread += maxread;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   479
        } /* else */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   480
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   481
        memcpy(&extra, buf, sizeof (extra));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   482
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   483
        for (i = maxread - 4; i > 0; i--)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   484
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   485
            if ((buf[i + 0] == 0x50) &&
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   486
                (buf[i + 1] == 0x4B) &&
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   487
                (buf[i + 2] == 0x05) &&
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   488
                (buf[i + 3] == 0x06) )
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   489
            {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   490
                found = 1;  /* that's the signature! */
10017
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 8524
diff changeset
   491
                break;
7768
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   492
            } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   493
        } /* for */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   494
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   495
        if (found)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   496
            break;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   497
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   498
        filepos -= (maxread - 4);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   499
        if (filepos < 0)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   500
            filepos = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   501
    } /* while */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   502
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   503
    BAIL_IF_MACRO(!found, PHYSFS_ERR_UNSUPPORTED, -1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   504
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   505
    if (len != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   506
        *len = filelen;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   507
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   508
    return (filepos + i);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   509
} /* zip_find_end_of_central_dir */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   510
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   511
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   512
static int isZip(PHYSFS_Io *io)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   513
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   514
    PHYSFS_uint32 sig = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   515
    int retval = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   516
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   517
    /*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   518
     * The first thing in a zip file might be the signature of the
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   519
     *  first local file record, so it makes for a quick determination.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   520
     */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   521
    if (readui32(io, &sig))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   522
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   523
        retval = (sig == ZIP_LOCAL_FILE_SIG);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   524
        if (!retval)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   525
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   526
            /*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   527
             * No sig...might be a ZIP with data at the start
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   528
             *  (a self-extracting executable, etc), so we'll have to do
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   529
             *  it the hard way...
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   530
             */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   531
            retval = (zip_find_end_of_central_dir(io, NULL) != -1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   532
        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   533
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   534
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   535
    return retval;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   536
} /* isZip */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   537
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   538
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   539
static void zip_free_entries(ZIPentry *entries, PHYSFS_uint64 max)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   540
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   541
    PHYSFS_uint64 i;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   542
    for (i = 0; i < max; i++)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   543
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   544
        ZIPentry *entry = &entries[i];
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   545
        if (entry->name != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   546
            allocator.Free(entry->name);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   547
    } /* for */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   548
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   549
    allocator.Free(entries);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   550
} /* zip_free_entries */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   551
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   552
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   553
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   554
 * This will find the ZIPentry associated with a path in platform-independent
10017
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 8524
diff changeset
   555
 *  notation. Directories don't have ZIPentries associated with them, but
7768
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   556
 *  (*isDir) will be set to non-zero if a dir was hit.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   557
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   558
static ZIPentry *zip_find_entry(const ZIPinfo *info, const char *path,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   559
                                int *isDir)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   560
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   561
    ZIPentry *a = info->entries;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   562
    PHYSFS_sint32 pathlen = (PHYSFS_sint32) strlen(path);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   563
    PHYSFS_sint64 lo = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   564
    PHYSFS_sint64 hi = (PHYSFS_sint64) (info->entryCount - 1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   565
    PHYSFS_sint64 middle;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   566
    const char *thispath = NULL;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   567
    int rc;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   568
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   569
    while (lo <= hi)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   570
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   571
        middle = lo + ((hi - lo) / 2);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   572
        thispath = a[middle].name;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   573
        rc = strncmp(path, thispath, pathlen);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   574
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   575
        if (rc > 0)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   576
            lo = middle + 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   577
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   578
        else if (rc < 0)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   579
            hi = middle - 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   580
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   581
        else /* substring match...might be dir or entry or nothing. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   582
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   583
            if (isDir != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   584
            {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   585
                *isDir = (thispath[pathlen] == '/');
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   586
                if (*isDir)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   587
                    return NULL;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   588
            } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   589
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   590
            if (thispath[pathlen] == '\0') /* found entry? */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   591
                return &a[middle];
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   592
            /* adjust search params, try again. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   593
            else if (thispath[pathlen] > '/')
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   594
                hi = middle - 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   595
            else
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   596
                lo = middle + 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   597
        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   598
    } /* while */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   599
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   600
    if (isDir != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   601
        *isDir = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   602
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   603
    BAIL_MACRO(PHYSFS_ERR_NO_SUCH_PATH, NULL);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   604
} /* zip_find_entry */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   605
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   606
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   607
/* Convert paths from old, buggy DOS zippers... */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   608
static void zip_convert_dos_path(ZIPentry *entry, char *path)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   609
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   610
    PHYSFS_uint8 hosttype = (PHYSFS_uint8) ((entry->version >> 8) & 0xFF);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   611
    if (hosttype == 0)  /* FS_FAT_ */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   612
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   613
        while (*path)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   614
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   615
            if (*path == '\\')
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   616
                *path = '/';
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   617
            path++;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   618
        } /* while */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   619
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   620
} /* zip_convert_dos_path */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   621
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   622
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   623
static void zip_expand_symlink_path(char *path)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   624
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   625
    char *ptr = path;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   626
    char *prevptr = path;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   627
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   628
    while (1)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   629
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   630
        ptr = strchr(ptr, '/');
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   631
        if (ptr == NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   632
            break;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   633
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   634
        if (*(ptr + 1) == '.')
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   635
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   636
            if (*(ptr + 2) == '/')
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   637
            {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   638
                /* current dir in middle of string: ditch it. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   639
                memmove(ptr, ptr + 2, strlen(ptr + 2) + 1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   640
            } /* else if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   641
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   642
            else if (*(ptr + 2) == '\0')
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   643
            {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   644
                /* current dir at end of string: ditch it. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   645
                *ptr = '\0';
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   646
            } /* else if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   647
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   648
            else if (*(ptr + 2) == '.')
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   649
            {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   650
                if (*(ptr + 3) == '/')
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   651
                {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   652
                    /* parent dir in middle: move back one, if possible. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   653
                    memmove(prevptr, ptr + 4, strlen(ptr + 4) + 1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   654
                    ptr = prevptr;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   655
                    while (prevptr != path)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   656
                    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   657
                        prevptr--;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   658
                        if (*prevptr == '/')
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   659
                        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   660
                            prevptr++;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   661
                            break;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   662
                        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   663
                    } /* while */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   664
                } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   665
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   666
                if (*(ptr + 3) == '\0')
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   667
                {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   668
                    /* parent dir at end: move back one, if possible. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   669
                    *prevptr = '\0';
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   670
                } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   671
            } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   672
        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   673
        else
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   674
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   675
            prevptr = ptr;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   676
            ptr++;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   677
        } /* else */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   678
    } /* while */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   679
} /* zip_expand_symlink_path */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   680
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   681
/* (forward reference: zip_follow_symlink and zip_resolve call each other.) */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   682
static int zip_resolve(PHYSFS_Io *io, ZIPinfo *info, ZIPentry *entry);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   683
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   684
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   685
 * Look for the entry named by (path). If it exists, resolve it, and return
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   686
 *  a pointer to that entry. If it's another symlink, keep resolving until you
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   687
 *  hit a real file and then return a pointer to the final non-symlink entry.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   688
 *  If there's a problem, return NULL.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   689
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   690
static ZIPentry *zip_follow_symlink(PHYSFS_Io *io, ZIPinfo *info, char *path)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   691
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   692
    ZIPentry *entry;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   693
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   694
    zip_expand_symlink_path(path);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   695
    entry = zip_find_entry(info, path, NULL);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   696
    if (entry != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   697
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   698
        if (!zip_resolve(io, info, entry))  /* recursive! */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   699
            entry = NULL;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   700
        else
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   701
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   702
            if (entry->symlink != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   703
                entry = entry->symlink;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   704
        } /* else */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   705
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   706
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   707
    return entry;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   708
} /* zip_follow_symlink */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   709
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   710
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   711
static int zip_resolve_symlink(PHYSFS_Io *io, ZIPinfo *info, ZIPentry *entry)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   712
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   713
    const PHYSFS_uint64 size = entry->uncompressed_size;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   714
    char *path = NULL;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   715
    int rc = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   716
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   717
    /*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   718
     * We've already parsed the local file header of the symlink at this
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   719
     *  point. Now we need to read the actual link from the file data and
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   720
     *  follow it.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   721
     */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   722
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   723
    BAIL_IF_MACRO(!io->seek(io, entry->offset), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   724
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   725
    path = (char *) __PHYSFS_smallAlloc(size + 1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   726
    BAIL_IF_MACRO(!path, PHYSFS_ERR_OUT_OF_MEMORY, 0);
10017
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 8524
diff changeset
   727
7768
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   728
    if (entry->compression_method == COMPMETH_NONE)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   729
        rc = __PHYSFS_readAll(io, path, size);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   730
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   731
    else  /* symlink target path is compressed... */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   732
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   733
        z_stream stream;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   734
        const PHYSFS_uint64 complen = entry->compressed_size;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   735
        PHYSFS_uint8 *compressed = (PHYSFS_uint8*) __PHYSFS_smallAlloc(complen);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   736
        if (compressed != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   737
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   738
            if (__PHYSFS_readAll(io, compressed, complen))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   739
            {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   740
                initializeZStream(&stream);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   741
                stream.next_in = compressed;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   742
                stream.avail_in = complen;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   743
                stream.next_out = (unsigned char *) path;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   744
                stream.avail_out = size;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   745
                if (zlib_err(inflateInit2(&stream, -MAX_WBITS)) == Z_OK)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   746
                {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   747
                    rc = zlib_err(inflate(&stream, Z_FINISH));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   748
                    inflateEnd(&stream);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   749
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   750
                    /* both are acceptable outcomes... */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   751
                    rc = ((rc == Z_OK) || (rc == Z_STREAM_END));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   752
                } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   753
            } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   754
            __PHYSFS_smallFree(compressed);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   755
        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   756
    } /* else */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   757
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   758
    if (rc)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   759
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   760
        path[entry->uncompressed_size] = '\0';    /* null-terminate it. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   761
        zip_convert_dos_path(entry, path);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   762
        entry->symlink = zip_follow_symlink(io, info, path);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   763
    } /* else */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   764
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   765
    __PHYSFS_smallFree(path);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   766
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   767
    return (entry->symlink != NULL);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   768
} /* zip_resolve_symlink */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   769
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   770
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   771
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   772
 * Parse the local file header of an entry, and update entry->offset.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   773
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   774
static int zip_parse_local(PHYSFS_Io *io, ZIPentry *entry)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   775
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   776
    PHYSFS_uint32 ui32;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   777
    PHYSFS_uint16 ui16;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   778
    PHYSFS_uint16 fnamelen;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   779
    PHYSFS_uint16 extralen;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   780
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   781
    /*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   782
     * crc and (un)compressed_size are always zero if this is a "JAR"
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   783
     *  archive created with Sun's Java tools, apparently. We only
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   784
     *  consider this archive corrupted if those entries don't match and
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   785
     *  aren't zero. That seems to work well.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   786
     * We also ignore a mismatch if the value is 0xFFFFFFFF here, since it's
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   787
     *  possible that's a Zip64 thing.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   788
     */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   789
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   790
    BAIL_IF_MACRO(!io->seek(io, entry->offset), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   791
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   792
    BAIL_IF_MACRO(ui32 != ZIP_LOCAL_FILE_SIG, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   793
    BAIL_IF_MACRO(!readui16(io, &ui16), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   794
    BAIL_IF_MACRO(ui16 != entry->version_needed, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   795
    BAIL_IF_MACRO(!readui16(io, &ui16), ERRPASS, 0);  /* general bits. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   796
    BAIL_IF_MACRO(!readui16(io, &ui16), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   797
    BAIL_IF_MACRO(ui16 != entry->compression_method, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   798
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);  /* date/time */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   799
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   800
    BAIL_IF_MACRO(ui32 && (ui32 != entry->crc), PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   801
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   802
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   803
    BAIL_IF_MACRO(ui32 && (ui32 != 0xFFFFFFFF) &&
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   804
                  (ui32 != entry->compressed_size), PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   805
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   806
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   807
    BAIL_IF_MACRO(ui32 && (ui32 != 0xFFFFFFFF) &&
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   808
                 (ui32 != entry->uncompressed_size), PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   809
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   810
    BAIL_IF_MACRO(!readui16(io, &fnamelen), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   811
    BAIL_IF_MACRO(!readui16(io, &extralen), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   812
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   813
    entry->offset += fnamelen + extralen + 30;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   814
    return 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   815
} /* zip_parse_local */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   816
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   817
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   818
static int zip_resolve(PHYSFS_Io *io, ZIPinfo *info, ZIPentry *entry)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   819
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   820
    int retval = 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   821
    ZipResolveType resolve_type = entry->resolved;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   822
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   823
    /* Don't bother if we've failed to resolve this entry before. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   824
    BAIL_IF_MACRO(resolve_type == ZIP_BROKEN_FILE, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   825
    BAIL_IF_MACRO(resolve_type == ZIP_BROKEN_SYMLINK, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   826
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   827
    /* uhoh...infinite symlink loop! */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   828
    BAIL_IF_MACRO(resolve_type == ZIP_RESOLVING, PHYSFS_ERR_SYMLINK_LOOP, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   829
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   830
    /*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   831
     * We fix up the offset to point to the actual data on the
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   832
     *  first open, since we don't want to seek across the whole file on
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   833
     *  archive open (can be SLOW on large, CD-stored files), but we
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   834
     *  need to check the local file header...not just for corruption,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   835
     *  but since it stores offset info the central directory does not.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   836
     */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   837
    if (resolve_type != ZIP_RESOLVED)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   838
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   839
        entry->resolved = ZIP_RESOLVING;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   840
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   841
        retval = zip_parse_local(io, entry);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   842
        if (retval)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   843
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   844
            /*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   845
             * If it's a symlink, find the original file. This will cause
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   846
             *  resolution of other entries (other symlinks and, eventually,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   847
             *  the real file) if all goes well.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   848
             */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   849
            if (resolve_type == ZIP_UNRESOLVED_SYMLINK)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   850
                retval = zip_resolve_symlink(io, info, entry);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   851
        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   852
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   853
        if (resolve_type == ZIP_UNRESOLVED_SYMLINK)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   854
            entry->resolved = ((retval) ? ZIP_RESOLVED : ZIP_BROKEN_SYMLINK);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   855
        else if (resolve_type == ZIP_UNRESOLVED_FILE)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   856
            entry->resolved = ((retval) ? ZIP_RESOLVED : ZIP_BROKEN_FILE);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   857
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   858
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   859
    return retval;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   860
} /* zip_resolve */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   861
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   862
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   863
static int zip_version_does_symlinks(PHYSFS_uint32 version)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   864
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   865
    int retval = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   866
    PHYSFS_uint8 hosttype = (PHYSFS_uint8) ((version >> 8) & 0xFF);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   867
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   868
    switch (hosttype)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   869
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   870
            /*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   871
             * These are the platforms that can NOT build an archive with
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   872
             *  symlinks, according to the Info-ZIP project.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   873
             */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   874
        case 0:  /* FS_FAT_  */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   875
        case 1:  /* AMIGA_   */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   876
        case 2:  /* VMS_     */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   877
        case 4:  /* VM_CSM_  */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   878
        case 6:  /* FS_HPFS_ */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   879
        case 11: /* FS_NTFS_ */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   880
        case 14: /* FS_VFAT_ */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   881
        case 13: /* ACORN_   */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   882
        case 15: /* MVS_     */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   883
        case 18: /* THEOS_   */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   884
            break;  /* do nothing. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   885
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   886
        default:  /* assume the rest to be unix-like. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   887
            retval = 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   888
            break;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   889
    } /* switch */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   890
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   891
    return retval;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   892
} /* zip_version_does_symlinks */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   893
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   894
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   895
static int zip_entry_is_symlink(const ZIPentry *entry)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   896
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   897
    return ((entry->resolved == ZIP_UNRESOLVED_SYMLINK) ||
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   898
            (entry->resolved == ZIP_BROKEN_SYMLINK) ||
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   899
            (entry->symlink));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   900
} /* zip_entry_is_symlink */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   901
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   902
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   903
static int zip_has_symlink_attr(ZIPentry *entry, PHYSFS_uint32 extern_attr)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   904
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   905
    PHYSFS_uint16 xattr = ((extern_attr >> 16) & 0xFFFF);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   906
    return ( (zip_version_does_symlinks(entry->version)) &&
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   907
             (entry->uncompressed_size > 0) &&
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   908
             ((xattr & UNIX_FILETYPE_MASK) == UNIX_FILETYPE_SYMLINK) );
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   909
} /* zip_has_symlink_attr */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   910
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   911
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   912
static PHYSFS_sint64 zip_dos_time_to_physfs_time(PHYSFS_uint32 dostime)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   913
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   914
    PHYSFS_uint32 dosdate;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   915
    struct tm unixtime;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   916
    memset(&unixtime, '\0', sizeof (unixtime));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   917
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   918
    dosdate = (PHYSFS_uint32) ((dostime >> 16) & 0xFFFF);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   919
    dostime &= 0xFFFF;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   920
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   921
    /* dissect date */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   922
    unixtime.tm_year = ((dosdate >> 9) & 0x7F) + 80;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   923
    unixtime.tm_mon  = ((dosdate >> 5) & 0x0F) - 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   924
    unixtime.tm_mday = ((dosdate     ) & 0x1F);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   925
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   926
    /* dissect time */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   927
    unixtime.tm_hour = ((dostime >> 11) & 0x1F);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   928
    unixtime.tm_min  = ((dostime >>  5) & 0x3F);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   929
    unixtime.tm_sec  = ((dostime <<  1) & 0x3E);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   930
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   931
    /* let mktime calculate daylight savings time. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   932
    unixtime.tm_isdst = -1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   933
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   934
    return ((PHYSFS_sint64) mktime(&unixtime));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   935
} /* zip_dos_time_to_physfs_time */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   936
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   937
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   938
static int zip_load_entry(PHYSFS_Io *io, const int zip64, ZIPentry *entry,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   939
                          PHYSFS_uint64 ofs_fixup)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   940
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   941
    PHYSFS_uint16 fnamelen, extralen, commentlen;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   942
    PHYSFS_uint32 external_attr;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   943
    PHYSFS_uint32 starting_disk;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   944
    PHYSFS_uint64 offset;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   945
    PHYSFS_uint16 ui16;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   946
    PHYSFS_uint32 ui32;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   947
    PHYSFS_sint64 si64;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   948
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   949
    /* sanity check with central directory signature... */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   950
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   951
    BAIL_IF_MACRO(ui32 != ZIP_CENTRAL_DIR_SIG, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   952
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   953
    /* Get the pertinent parts of the record... */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   954
    BAIL_IF_MACRO(!readui16(io, &entry->version), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   955
    BAIL_IF_MACRO(!readui16(io, &entry->version_needed), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   956
    BAIL_IF_MACRO(!readui16(io, &ui16), ERRPASS, 0);  /* general bits */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   957
    BAIL_IF_MACRO(!readui16(io, &entry->compression_method), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   958
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   959
    entry->last_mod_time = zip_dos_time_to_physfs_time(ui32);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   960
    BAIL_IF_MACRO(!readui32(io, &entry->crc), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   961
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   962
    entry->compressed_size = (PHYSFS_uint64) ui32;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   963
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   964
    entry->uncompressed_size = (PHYSFS_uint64) ui32;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   965
    BAIL_IF_MACRO(!readui16(io, &fnamelen), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   966
    BAIL_IF_MACRO(!readui16(io, &extralen), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   967
    BAIL_IF_MACRO(!readui16(io, &commentlen), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   968
    BAIL_IF_MACRO(!readui16(io, &ui16), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   969
    starting_disk = (PHYSFS_uint32) ui16;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   970
    BAIL_IF_MACRO(!readui16(io, &ui16), ERRPASS, 0);  /* internal file attribs */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   971
    BAIL_IF_MACRO(!readui32(io, &external_attr), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   972
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   973
    offset = (PHYSFS_uint64) ui32;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   974
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   975
    entry->symlink = NULL;  /* will be resolved later, if necessary. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   976
    entry->resolved = (zip_has_symlink_attr(entry, external_attr)) ?
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   977
                            ZIP_UNRESOLVED_SYMLINK : ZIP_UNRESOLVED_FILE;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   978
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   979
    entry->name = (char *) allocator.Malloc(fnamelen + 1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   980
    BAIL_IF_MACRO(entry->name == NULL, PHYSFS_ERR_OUT_OF_MEMORY, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   981
    if (!__PHYSFS_readAll(io, entry->name, fnamelen))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   982
        goto zip_load_entry_puked;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   983
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   984
    entry->name[fnamelen] = '\0';  /* null-terminate the filename. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   985
    zip_convert_dos_path(entry, entry->name);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   986
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   987
    si64 = io->tell(io);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   988
    if (si64 == -1)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   989
        goto zip_load_entry_puked;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   990
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   991
    /*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   992
     * The actual sizes didn't fit in 32-bits; look for the Zip64
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   993
     *  extended information extra field...
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   994
     */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   995
    if ( (zip64) &&
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   996
         ((offset == 0xFFFFFFFF) ||
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   997
          (starting_disk == 0xFFFFFFFF) ||
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   998
          (entry->compressed_size == 0xFFFFFFFF) ||
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
   999
          (entry->uncompressed_size == 0xFFFFFFFF)) )
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1000
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1001
        int found = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1002
        PHYSFS_uint16 sig, len;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1003
        while (extralen > 4)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1004
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1005
            if (!readui16(io, &sig))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1006
                goto zip_load_entry_puked;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1007
            else if (!readui16(io, &len))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1008
                goto zip_load_entry_puked;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1009
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1010
            si64 += 4 + len;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1011
            extralen -= 4 + len;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1012
            if (sig != ZIP64_EXTENDED_INFO_EXTRA_FIELD_SIG)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1013
            {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1014
                if (!io->seek(io, si64))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1015
                    goto zip_load_entry_puked;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1016
                continue;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1017
            } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1018
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1019
            found = 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1020
            break;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1021
        } /* while */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1022
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1023
        GOTO_IF_MACRO(!found, PHYSFS_ERR_CORRUPT, zip_load_entry_puked);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1024
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1025
        if (entry->uncompressed_size == 0xFFFFFFFF)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1026
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1027
            GOTO_IF_MACRO(len < 8, PHYSFS_ERR_CORRUPT, zip_load_entry_puked);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1028
            if (!readui64(io, &entry->uncompressed_size))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1029
                goto zip_load_entry_puked;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1030
            len -= 8;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1031
        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1032
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1033
        if (entry->compressed_size == 0xFFFFFFFF)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1034
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1035
            GOTO_IF_MACRO(len < 8, PHYSFS_ERR_CORRUPT, zip_load_entry_puked);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1036
            if (!readui64(io, &entry->compressed_size))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1037
                goto zip_load_entry_puked;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1038
            len -= 8;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1039
        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1040
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1041
        if (offset == 0xFFFFFFFF)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1042
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1043
            GOTO_IF_MACRO(len < 8, PHYSFS_ERR_CORRUPT, zip_load_entry_puked);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1044
            if (!readui64(io, &offset))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1045
                goto zip_load_entry_puked;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1046
            len -= 8;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1047
        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1048
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1049
        if (starting_disk == 0xFFFFFFFF)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1050
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1051
            GOTO_IF_MACRO(len < 8, PHYSFS_ERR_CORRUPT, zip_load_entry_puked);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1052
            if (!readui32(io, &starting_disk))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1053
                goto zip_load_entry_puked;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1054
            len -= 4;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1055
        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1056
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1057
        GOTO_IF_MACRO(len != 0, PHYSFS_ERR_CORRUPT, zip_load_entry_puked);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1058
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1059
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1060
    GOTO_IF_MACRO(starting_disk != 0, PHYSFS_ERR_CORRUPT, zip_load_entry_puked);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1061
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1062
    entry->offset = offset + ofs_fixup;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1063
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1064
    /* seek to the start of the next entry in the central directory... */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1065
    if (!io->seek(io, si64 + extralen + commentlen))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1066
        goto zip_load_entry_puked;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1067
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1068
    return 1;  /* success. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1069
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1070
zip_load_entry_puked:
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1071
    allocator.Free(entry->name);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1072
    return 0;  /* failure. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1073
} /* zip_load_entry */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1074
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1075
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1076
static int zip_entry_cmp(void *_a, size_t one, size_t two)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1077
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1078
    if (one != two)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1079
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1080
        const ZIPentry *a = (const ZIPentry *) _a;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1081
        return strcmp(a[one].name, a[two].name);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1082
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1083
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1084
    return 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1085
} /* zip_entry_cmp */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1086
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1087
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1088
static void zip_entry_swap(void *_a, size_t one, size_t two)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1089
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1090
    if (one != two)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1091
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1092
        ZIPentry tmp;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1093
        ZIPentry *first = &(((ZIPentry *) _a)[one]);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1094
        ZIPentry *second = &(((ZIPentry *) _a)[two]);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1095
        memcpy(&tmp, first, sizeof (ZIPentry));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1096
        memcpy(first, second, sizeof (ZIPentry));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1097
        memcpy(second, &tmp, sizeof (ZIPentry));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1098
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1099
} /* zip_entry_swap */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1100
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1101
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1102
static int zip_load_entries(PHYSFS_Io *io, ZIPinfo *info,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1103
                            const PHYSFS_uint64 data_ofs,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1104
                            const PHYSFS_uint64 central_ofs)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1105
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1106
    const PHYSFS_uint64 max = info->entryCount;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1107
    const int zip64 = info->zip64;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1108
    PHYSFS_uint64 i;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1109
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1110
    BAIL_IF_MACRO(!io->seek(io, central_ofs), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1111
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1112
    info->entries = (ZIPentry *) allocator.Malloc(sizeof (ZIPentry) * max);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1113
    BAIL_IF_MACRO(!info->entries, PHYSFS_ERR_OUT_OF_MEMORY, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1114
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1115
    for (i = 0; i < max; i++)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1116
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1117
        if (!zip_load_entry(io, zip64, &info->entries[i], data_ofs))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1118
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1119
            zip_free_entries(info->entries, i);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1120
            return 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1121
        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1122
    } /* for */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1123
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1124
    __PHYSFS_sort(info->entries, (size_t) max, zip_entry_cmp, zip_entry_swap);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1125
    return 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1126
} /* zip_load_entries */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1127
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1128
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1129
static PHYSFS_sint64 zip64_find_end_of_central_dir(PHYSFS_Io *io,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1130
                                                   PHYSFS_sint64 _pos,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1131
                                                   PHYSFS_uint64 offset)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1132
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1133
    /*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1134
     * Naturally, the offset is useless to us; it is the offset from the
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1135
     *  start of file, which is meaningless if we've appended this .zip to
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1136
     *  a self-extracting .exe. We need to find this on our own. It should
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1137
     *  be directly before the locator record, but the record in question,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1138
     *  like the original end-of-central-directory record, ends with a
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1139
     *  variable-length field. Unlike the original, which has to store the
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1140
     *  size of that variable-length field in a 16-bit int and thus has to be
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1141
     *  within 64k, the new one gets 64-bits.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1142
     *
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1143
     * Fortunately, the only currently-specified record for that variable
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1144
     *  length block is some weird proprietary thing that deals with EBCDIC
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1145
     *  and tape backups or something. So we don't seek far.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1146
     */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1147
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1148
    PHYSFS_uint32 ui32;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1149
    const PHYSFS_uint64 pos = (PHYSFS_uint64) _pos;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1150
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1151
    assert(_pos > 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1152
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1153
    /* Try offset specified in the Zip64 end of central directory locator. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1154
    /* This works if the entire PHYSFS_Io is the zip file. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1155
    BAIL_IF_MACRO(!io->seek(io, offset), ERRPASS, -1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1156
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, -1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1157
    if (ui32 == ZIP64_END_OF_CENTRAL_DIR_SIG)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1158
        return offset;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1159
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1160
    /* Try 56 bytes before the Zip64 end of central directory locator. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1161
    /* This works if the record isn't variable length and is version 1. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1162
    if (pos > 56)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1163
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1164
        BAIL_IF_MACRO(!io->seek(io, pos-56), ERRPASS, -1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1165
        BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, -1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1166
        if (ui32 == ZIP64_END_OF_CENTRAL_DIR_SIG)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1167
            return pos-56;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1168
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1169
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1170
    /* Try 84 bytes before the Zip64 end of central directory locator. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1171
    /* This works if the record isn't variable length and is version 2. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1172
    if (pos > 84)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1173
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1174
        BAIL_IF_MACRO(!io->seek(io, pos-84), ERRPASS, -1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1175
        BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, -1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1176
        if (ui32 == ZIP64_END_OF_CENTRAL_DIR_SIG)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1177
            return pos-84;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1178
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1179
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1180
    /* Ok, brute force: we know it's between (offset) and (pos) somewhere. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1181
    /*  Just try moving back at most 256k. Oh well. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1182
    if ((offset < pos) && (pos > 4))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1183
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1184
        /* we assume you can eat this stack if you handle Zip64 files. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1185
        PHYSFS_uint8 buf[256 * 1024];
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1186
        PHYSFS_uint64 len = pos - offset;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1187
        PHYSFS_sint32 i;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1188
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1189
        if (len > sizeof (buf))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1190
            len = sizeof (buf);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1191
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1192
        BAIL_IF_MACRO(!io->seek(io, pos - len), ERRPASS, -1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1193
        BAIL_IF_MACRO(!__PHYSFS_readAll(io, buf, len), ERRPASS, -1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1194
        for (i = (PHYSFS_sint32) (len - 4); i >= 0; i--)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1195
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1196
            if (buf[i] != 0x50)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1197
                continue;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1198
            if ( (buf[i+1] == 0x4b) &&
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1199
                 (buf[i+2] == 0x06) &&
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1200
                 (buf[i+3] == 0x06) )
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1201
                return pos - (len - i);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1202
        } /* for */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1203
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1204
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1205
    BAIL_MACRO(PHYSFS_ERR_CORRUPT, -1);  /* didn't find it. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1206
} /* zip64_find_end_of_central_dir */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1207
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1208
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1209
static int zip64_parse_end_of_central_dir(PHYSFS_Io *io, ZIPinfo *info,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1210
                                          PHYSFS_uint64 *data_start,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1211
                                          PHYSFS_uint64 *dir_ofs,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1212
                                          PHYSFS_sint64 pos)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1213
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1214
    PHYSFS_uint64 ui64;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1215
    PHYSFS_uint32 ui32;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1216
    PHYSFS_uint16 ui16;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1217
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1218
    /* We should be positioned right past the locator signature. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1219
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1220
    if ((pos < 0) || (!io->seek(io, pos)))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1221
        return 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1222
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1223
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1224
    if (ui32 != ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIG)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1225
        return -1;  /* it's not a Zip64 archive. Not an error, though! */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1226
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1227
    info->zip64 = 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1228
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1229
    /* number of the disk with the start of the central directory. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1230
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1231
    BAIL_IF_MACRO(ui32 != 0, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1232
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1233
    /* offset of Zip64 end of central directory record. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1234
    BAIL_IF_MACRO(!readui64(io, &ui64), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1235
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1236
    /* total number of disks */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1237
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1238
    BAIL_IF_MACRO(ui32 != 1, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1239
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1240
    pos = zip64_find_end_of_central_dir(io, pos, ui64);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1241
    if (pos < 0)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1242
        return 0;  /* oh well. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1243
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1244
    /*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1245
     * For self-extracting archives, etc, there's crapola in the file
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1246
     *  before the zipfile records; we calculate how much data there is
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1247
     *  prepended by determining how far the zip64-end-of-central-directory
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1248
     *  offset is from where it is supposed to be...the difference in bytes
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1249
     *  is how much arbitrary data is at the start of the physical file.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1250
     */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1251
    assert(((PHYSFS_uint64) pos) >= ui64);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1252
    *data_start = ((PHYSFS_uint64) pos) - ui64;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1253
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1254
    BAIL_IF_MACRO(!io->seek(io, pos), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1255
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1256
    /* check signature again, just in case. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1257
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1258
    BAIL_IF_MACRO(ui32 != ZIP64_END_OF_CENTRAL_DIR_SIG, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1259
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1260
    /* size of Zip64 end of central directory record. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1261
    BAIL_IF_MACRO(!readui64(io, &ui64), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1262
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1263
    /* version made by. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1264
    BAIL_IF_MACRO(!readui16(io, &ui16), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1265
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1266
    /* version needed to extract. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1267
    BAIL_IF_MACRO(!readui16(io, &ui16), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1268
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1269
    /* number of this disk. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1270
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1271
    BAIL_IF_MACRO(ui32 != 0, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1272
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1273
    /* number of disk with start of central directory record. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1274
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1275
    BAIL_IF_MACRO(ui32 != 0, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1276
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1277
    /* total number of entries in the central dir on this disk */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1278
    BAIL_IF_MACRO(!readui64(io, &ui64), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1279
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1280
    /* total number of entries in the central dir */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1281
    BAIL_IF_MACRO(!readui64(io, &info->entryCount), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1282
    BAIL_IF_MACRO(ui64 != info->entryCount, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1283
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1284
    /* size of the central directory */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1285
    BAIL_IF_MACRO(!readui64(io, &ui64), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1286
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1287
    /* offset of central directory */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1288
    BAIL_IF_MACRO(!readui64(io, dir_ofs), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1289
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1290
    /* Since we know the difference, fix up the central dir offset... */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1291
    *dir_ofs += *data_start;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1292
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1293
    /*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1294
     * There are more fields here, for encryption and feature-specific things,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1295
     *  but we don't care about any of them at the moment.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1296
     */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1297
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1298
    return 1;  /* made it. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1299
} /* zip64_parse_end_of_central_dir */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1300
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1301
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1302
static int zip_parse_end_of_central_dir(PHYSFS_Io *io, ZIPinfo *info,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1303
                                        PHYSFS_uint64 *data_start,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1304
                                        PHYSFS_uint64 *dir_ofs)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1305
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1306
    PHYSFS_uint16 entryCount16;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1307
    PHYSFS_uint32 offset32;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1308
    PHYSFS_uint32 ui32;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1309
    PHYSFS_uint16 ui16;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1310
    PHYSFS_sint64 len;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1311
    PHYSFS_sint64 pos;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1312
    int rc;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1313
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1314
    /* find the end-of-central-dir record, and seek to it. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1315
    pos = zip_find_end_of_central_dir(io, &len);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1316
    BAIL_IF_MACRO(pos == -1, ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1317
    BAIL_IF_MACRO(!io->seek(io, pos), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1318
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1319
    /* check signature again, just in case. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1320
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1321
    BAIL_IF_MACRO(ui32 != ZIP_END_OF_CENTRAL_DIR_SIG, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1322
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1323
    /* Seek back to see if "Zip64 end of central directory locator" exists. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1324
    /* this record is 20 bytes before end-of-central-dir */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1325
    rc = zip64_parse_end_of_central_dir(io, info, data_start, dir_ofs, pos-20);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1326
    BAIL_IF_MACRO(rc == 0, ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1327
    if (rc == 1)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1328
        return 1;  /* we're done here. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1329
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1330
    assert(rc == -1);  /* no error, just not a Zip64 archive. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1331
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1332
    /* Not Zip64? Seek back to where we were and keep processing. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1333
    BAIL_IF_MACRO(!io->seek(io, pos + 4), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1334
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1335
    /* number of this disk */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1336
    BAIL_IF_MACRO(!readui16(io, &ui16), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1337
    BAIL_IF_MACRO(ui16 != 0, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1338
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1339
    /* number of the disk with the start of the central directory */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1340
    BAIL_IF_MACRO(!readui16(io, &ui16), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1341
    BAIL_IF_MACRO(ui16 != 0, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1342
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1343
    /* total number of entries in the central dir on this disk */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1344
    BAIL_IF_MACRO(!readui16(io, &ui16), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1345
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1346
    /* total number of entries in the central dir */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1347
    BAIL_IF_MACRO(!readui16(io, &entryCount16), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1348
    BAIL_IF_MACRO(ui16 != entryCount16, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1349
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1350
    info->entryCount = entryCount16;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1351
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1352
    /* size of the central directory */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1353
    BAIL_IF_MACRO(!readui32(io, &ui32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1354
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1355
    /* offset of central directory */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1356
    BAIL_IF_MACRO(!readui32(io, &offset32), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1357
    *dir_ofs = (PHYSFS_uint64) offset32;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1358
    BAIL_IF_MACRO(pos < (*dir_ofs + ui32), PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1359
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1360
    /*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1361
     * For self-extracting archives, etc, there's crapola in the file
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1362
     *  before the zipfile records; we calculate how much data there is
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1363
     *  prepended by determining how far the central directory offset is
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1364
     *  from where it is supposed to be (start of end-of-central-dir minus
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1365
     *  sizeof central dir)...the difference in bytes is how much arbitrary
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1366
     *  data is at the start of the physical file.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1367
     */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1368
    *data_start = (PHYSFS_uint64) (pos - (*dir_ofs + ui32));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1369
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1370
    /* Now that we know the difference, fix up the central dir offset... */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1371
    *dir_ofs += *data_start;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1372
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1373
    /* zipfile comment length */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1374
    BAIL_IF_MACRO(!readui16(io, &ui16), ERRPASS, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1375
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1376
    /*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1377
     * Make sure that the comment length matches to the end of file...
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1378
     *  If it doesn't, we're either in the wrong part of the file, or the
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1379
     *  file is corrupted, but we give up either way.
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1380
     */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1381
    BAIL_IF_MACRO((pos + 22 + ui16) != len, PHYSFS_ERR_CORRUPT, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1382
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1383
    return 1;  /* made it. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1384
} /* zip_parse_end_of_central_dir */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1385
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1386
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1387
static void *ZIP_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1388
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1389
    ZIPinfo *info = NULL;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1390
    PHYSFS_uint64 data_start;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1391
    PHYSFS_uint64 cent_dir_ofs;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1392
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1393
    assert(io != NULL);  /* shouldn't ever happen. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1394
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1395
    BAIL_IF_MACRO(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1396
    BAIL_IF_MACRO(!isZip(io), ERRPASS, NULL);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1397
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1398
    info = (ZIPinfo *) allocator.Malloc(sizeof (ZIPinfo));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1399
    BAIL_IF_MACRO(!info, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1400
    memset(info, '\0', sizeof (ZIPinfo));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1401
    info->io = io;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1402
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1403
    if (!zip_parse_end_of_central_dir(io, info, &data_start, &cent_dir_ofs))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1404
        goto ZIP_openarchive_failed;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1405
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1406
    if (!zip_load_entries(io, info, data_start, cent_dir_ofs))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1407
        goto ZIP_openarchive_failed;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1408
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1409
    return info;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1410
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1411
ZIP_openarchive_failed:
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1412
    if (info != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1413
        allocator.Free(info);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1414
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1415
    return NULL;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1416
} /* ZIP_openArchive */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1417
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1418
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1419
static PHYSFS_sint64 zip_find_start_of_dir(ZIPinfo *info, const char *path,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1420
                                            int stop_on_first_find)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1421
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1422
    PHYSFS_sint64 lo = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1423
    PHYSFS_sint64 hi = (PHYSFS_sint64) (info->entryCount - 1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1424
    PHYSFS_sint64 middle;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1425
    PHYSFS_uint32 dlen = (PHYSFS_uint32) strlen(path);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1426
    PHYSFS_sint64 retval = -1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1427
    const char *name;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1428
    int rc;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1429
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1430
    if (*path == '\0')  /* root dir? */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1431
        return 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1432
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1433
    if ((dlen > 0) && (path[dlen - 1] == '/')) /* ignore trailing slash. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1434
        dlen--;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1435
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1436
    while (lo <= hi)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1437
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1438
        middle = lo + ((hi - lo) / 2);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1439
        name = info->entries[middle].name;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1440
        rc = strncmp(path, name, dlen);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1441
        if (rc == 0)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1442
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1443
            char ch = name[dlen];
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1444
            if ('/' < ch) /* make sure this isn't just a substr match. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1445
                rc = -1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1446
            else if ('/' > ch)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1447
                rc = 1;
10017
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 8524
diff changeset
  1448
            else
7768
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1449
            {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1450
                if (stop_on_first_find) /* Just checking dir's existance? */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1451
                    return middle;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1452
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1453
                if (name[dlen + 1] == '\0') /* Skip initial dir entry. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1454
                    return (middle + 1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1455
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1456
                /* there might be more entries earlier in the list. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1457
                retval = middle;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1458
                hi = middle - 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1459
            } /* else */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1460
        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1461
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1462
        if (rc > 0)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1463
            lo = middle + 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1464
        else
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1465
            hi = middle - 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1466
    } /* while */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1467
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1468
    return retval;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1469
} /* zip_find_start_of_dir */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1470
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1471
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1472
/*
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1473
 * Moved to seperate function so we can use alloca then immediately throw
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1474
 *  away the allocated stack space...
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1475
 */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1476
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1477
                           const char *odir, const char *str, PHYSFS_sint32 ln)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1478
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1479
    char *newstr = __PHYSFS_smallAlloc(ln + 1);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1480
    if (newstr == NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1481
        return;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1482
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1483
    memcpy(newstr, str, ln);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1484
    newstr[ln] = '\0';
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1485
    cb(callbackdata, odir, newstr);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1486
    __PHYSFS_smallFree(newstr);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1487
} /* doEnumCallback */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1488
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1489
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1490
static void ZIP_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1491
                               int omitSymLinks, PHYSFS_EnumFilesCallback cb,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1492
                               const char *origdir, void *callbackdata)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1493
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1494
    ZIPinfo *info = ((ZIPinfo *) opaque);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1495
    PHYSFS_sint32 dlen, dlen_inc;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1496
    PHYSFS_sint64 i, max;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1497
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1498
    i = zip_find_start_of_dir(info, dname, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1499
    if (i == -1)  /* no such directory. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1500
        return;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1501
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1502
    dlen = (PHYSFS_sint32) strlen(dname);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1503
    if ((dlen > 0) && (dname[dlen - 1] == '/')) /* ignore trailing slash. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1504
        dlen--;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1505
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1506
    dlen_inc = ((dlen > 0) ? 1 : 0) + dlen;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1507
    max = (PHYSFS_sint64) info->entryCount;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1508
    while (i < max)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1509
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1510
        char *e = info->entries[i].name;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1511
        if ((dlen) && ((strncmp(e, dname, dlen) != 0) || (e[dlen] != '/')))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1512
            break;  /* past end of this dir; we're done. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1513
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1514
        if ((omitSymLinks) && (zip_entry_is_symlink(&info->entries[i])))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1515
            i++;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1516
        else
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1517
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1518
            char *add = e + dlen_inc;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1519
            char *ptr = strchr(add, '/');
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1520
            PHYSFS_sint32 ln = (PHYSFS_sint32) ((ptr) ? ptr-add : strlen(add));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1521
            doEnumCallback(cb, callbackdata, origdir, add, ln);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1522
            ln += dlen_inc;  /* point past entry to children... */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1523
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1524
            /* increment counter and skip children of subdirs... */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1525
            while ((++i < max) && (ptr != NULL))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1526
            {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1527
                char *e_new = info->entries[i].name;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1528
                if ((strncmp(e, e_new, ln) != 0) || (e_new[ln] != '/'))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1529
                    break;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1530
            } /* while */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1531
        } /* else */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1532
    } /* while */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1533
} /* ZIP_enumerateFiles */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1534
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1535
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1536
static PHYSFS_Io *zip_get_io(PHYSFS_Io *io, ZIPinfo *inf, ZIPentry *entry)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1537
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1538
    int success;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1539
    PHYSFS_Io *retval = io->duplicate(io);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1540
    BAIL_IF_MACRO(!retval, ERRPASS, NULL);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1541
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1542
    /* !!! FIXME: if you open a dir here, it should bail ERR_NOT_A_FILE */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1543
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1544
    /* (inf) can be NULL if we already resolved. */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1545
    success = (inf == NULL) || zip_resolve(retval, inf, entry);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1546
    if (success)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1547
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1548
        PHYSFS_sint64 offset;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1549
        offset = ((entry->symlink) ? entry->symlink->offset : entry->offset);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1550
        success = retval->seek(retval, offset);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1551
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1552
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1553
    if (!success)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1554
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1555
        retval->destroy(retval);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1556
        retval = NULL;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1557
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1558
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1559
    return retval;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1560
} /* zip_get_io */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1561
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1562
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1563
static PHYSFS_Io *ZIP_openRead(PHYSFS_Dir *opaque, const char *fnm,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1564
                               int *fileExists)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1565
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1566
    PHYSFS_Io *retval = NULL;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1567
    ZIPinfo *info = (ZIPinfo *) opaque;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1568
    ZIPentry *entry = zip_find_entry(info, fnm, NULL);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1569
    ZIPfileinfo *finfo = NULL;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1570
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1571
    *fileExists = (entry != NULL);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1572
    BAIL_IF_MACRO(!entry, ERRPASS, NULL);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1573
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1574
    retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1575
    GOTO_IF_MACRO(!retval, PHYSFS_ERR_OUT_OF_MEMORY, ZIP_openRead_failed);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1576
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1577
    finfo = (ZIPfileinfo *) allocator.Malloc(sizeof (ZIPfileinfo));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1578
    GOTO_IF_MACRO(!finfo, PHYSFS_ERR_OUT_OF_MEMORY, ZIP_openRead_failed);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1579
    memset(finfo, '\0', sizeof (ZIPfileinfo));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1580
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1581
    finfo->io = zip_get_io(info->io, info, entry);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1582
    GOTO_IF_MACRO(!finfo->io, ERRPASS, ZIP_openRead_failed);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1583
    finfo->entry = ((entry->symlink != NULL) ? entry->symlink : entry);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1584
    initializeZStream(&finfo->stream);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1585
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1586
    if (finfo->entry->compression_method != COMPMETH_NONE)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1587
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1588
        finfo->buffer = (PHYSFS_uint8 *) allocator.Malloc(ZIP_READBUFSIZE);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1589
        if (!finfo->buffer)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1590
            GOTO_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, ZIP_openRead_failed);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1591
        else if (zlib_err(inflateInit2(&finfo->stream, -MAX_WBITS)) != Z_OK)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1592
            goto ZIP_openRead_failed;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1593
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1594
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1595
    memcpy(retval, &ZIP_Io, sizeof (PHYSFS_Io));
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1596
    retval->opaque = finfo;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1597
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1598
    return retval;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1599
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1600
ZIP_openRead_failed:
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1601
    if (finfo != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1602
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1603
        if (finfo->io != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1604
            finfo->io->destroy(finfo->io);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1605
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1606
        if (finfo->buffer != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1607
        {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1608
            allocator.Free(finfo->buffer);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1609
            inflateEnd(&finfo->stream);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1610
        } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1611
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1612
        allocator.Free(finfo);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1613
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1614
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1615
    if (retval != NULL)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1616
        allocator.Free(retval);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1617
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1618
    return NULL;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1619
} /* ZIP_openRead */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1620
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1621
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1622
static PHYSFS_Io *ZIP_openWrite(PHYSFS_Dir *opaque, const char *filename)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1623
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1624
    BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1625
} /* ZIP_openWrite */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1626
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1627
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1628
static PHYSFS_Io *ZIP_openAppend(PHYSFS_Dir *opaque, const char *filename)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1629
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1630
    BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1631
} /* ZIP_openAppend */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1632
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1633
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1634
static void ZIP_closeArchive(PHYSFS_Dir *opaque)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1635
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1636
    ZIPinfo *zi = (ZIPinfo *) (opaque);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1637
    zi->io->destroy(zi->io);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1638
    zip_free_entries(zi->entries, zi->entryCount);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1639
    allocator.Free(zi);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1640
} /* ZIP_closeArchive */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1641
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1642
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1643
static int ZIP_remove(PHYSFS_Dir *opaque, const char *name)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1644
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1645
    BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1646
} /* ZIP_remove */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1647
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1648
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1649
static int ZIP_mkdir(PHYSFS_Dir *opaque, const char *name)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1650
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1651
    BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1652
} /* ZIP_mkdir */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1653
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1654
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1655
static int ZIP_stat(PHYSFS_Dir *opaque, const char *filename, int *exists,
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1656
                    PHYSFS_Stat *stat)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1657
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1658
    int isDir = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1659
    const ZIPinfo *info = (const ZIPinfo *) opaque;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1660
    const ZIPentry *entry = zip_find_entry(info, filename, &isDir);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1661
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1662
    /* !!! FIXME: does this need to resolve entries here? */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1663
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1664
    *exists = isDir || (entry != 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1665
    if (!*exists)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1666
        return 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1667
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1668
    if (isDir)
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1669
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1670
        stat->filesize = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1671
        stat->filetype = PHYSFS_FILETYPE_DIRECTORY;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1672
    } /* if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1673
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1674
    else if (zip_entry_is_symlink(entry))
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1675
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1676
        stat->filesize = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1677
        stat->filetype = PHYSFS_FILETYPE_SYMLINK;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1678
    } /* else if */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1679
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1680
    else
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1681
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1682
        stat->filesize = (PHYSFS_sint64) entry->uncompressed_size;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1683
        stat->filetype = PHYSFS_FILETYPE_REGULAR;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1684
    } /* else */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1685
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1686
    stat->modtime = ((entry) ? entry->last_mod_time : 0);
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1687
    stat->createtime = stat->modtime;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1688
    stat->accesstime = 0;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1689
    stat->readonly = 1; /* .zip files are always read only */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1690
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1691
    return 1;
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1692
} /* ZIP_stat */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1693
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1694
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1695
const PHYSFS_Archiver __PHYSFS_Archiver_ZIP =
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1696
{
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1697
    {
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1698
        "ZIP",
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1699
        "PkZip/WinZip/Info-Zip compatible",
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1700
        "Ryan C. Gordon <icculus@icculus.org>",
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1701
        "http://icculus.org/physfs/",
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1702
    },
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1703
    ZIP_openArchive,        /* openArchive() method    */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1704
    ZIP_enumerateFiles,     /* enumerateFiles() method */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1705
    ZIP_openRead,           /* openRead() method       */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1706
    ZIP_openWrite,          /* openWrite() method      */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1707
    ZIP_openAppend,         /* openAppend() method     */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1708
    ZIP_remove,             /* remove() method         */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1709
    ZIP_mkdir,              /* mkdir() method          */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1710
    ZIP_closeArchive,       /* closeArchive() method   */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1711
    ZIP_stat                /* stat() method           */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1712
};
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1713
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1714
#endif  /* defined PHYSFS_SUPPORTS_ZIP */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1715
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1716
/* end of zip.c ... */
13e2037ebc79 Try using PhysicsFS.
unc0rr
parents:
diff changeset
  1717