archivers/wad.c
changeset 609 3a91332776e0
child 610 1d8057a5d08e
equal deleted inserted replaced
608:2538f5f073ef 609:3a91332776e0
       
     1 /*
       
     2  * WAD support routines for PhysicsFS.
       
     3  *
       
     4  * This driver handles DOOM engine archives ("wads"). 
       
     5  * This format (but not this driver) was designed by id Software for use
       
     6  *  with the DOOM engine.
       
     7  * The specs of the format are from the unofficial doom specs v1.666
       
     8  * found here: http://www.gamers.org/dhs/helpdocs/dmsp1666.html
       
     9  * The format of the archive: (from the specs)
       
    10  *
       
    11  *  A WAD file has three parts:
       
    12  *  (1) a twelve-byte header
       
    13  *  (2) one or more "lumps"
       
    14  *  (3) a directory or "info table" that contains the names, offsets, and
       
    15  *      sizes of all the lumps in the WAD
       
    16  *
       
    17  *  The header consists of three four-byte parts:
       
    18  *    (a) an ASCII string which must be either "IWAD" or "PWAD"
       
    19  *    (b) a 4-byte (long) integer which is the number of lumps in the wad
       
    20  *    (c) a long integer which is the file offset to the start of
       
    21  *    the directory
       
    22  *
       
    23  *  The directory has one 16-byte entry for every lump. Each entry consists
       
    24  *  of three parts:
       
    25  *
       
    26  *    (a) a long integer, the file offset to the start of the lump
       
    27  *    (b) a long integer, the size of the lump in bytes
       
    28  *    (c) an 8-byte ASCII string, the name of the lump, padded with zeros.
       
    29  *        For example, the "DEMO1" entry in hexadecimal would be
       
    30  *        (44 45 4D 4F 31 00 00 00)
       
    31  * 
       
    32  * Note that there is no way to tell if an opened WAD archive is a
       
    33  *  IWAD or PWAD with this archiver.
       
    34  * I couldn't think of a way to provide that information, without being too
       
    35  *  hacky.
       
    36  * I don't think it's really that important though.
       
    37  *
       
    38  *
       
    39  * Please see the file LICENSE in the source's root directory.
       
    40  *
       
    41  * This file written by Travis Wells, based on the GRP archiver by
       
    42  *  Ryan C. Gordon.
       
    43  */
       
    44 
       
    45 #if HAVE_CONFIG_H
       
    46 #  include <config.h>
       
    47 #endif
       
    48 
       
    49 #if (defined PHYSFS_SUPPORTS_WAD)
       
    50 
       
    51 #include <stdio.h>
       
    52 #include <stdlib.h>
       
    53 #include <string.h>
       
    54 #include "physfs.h"
       
    55 
       
    56 #define __PHYSICSFS_INTERNAL__
       
    57 #include "physfs_internal.h"
       
    58 
       
    59 typedef struct
       
    60 {
       
    61     char name[9];
       
    62     PHYSFS_uint32 startPos;
       
    63     PHYSFS_uint32 size;
       
    64 } WADentry;
       
    65 
       
    66 typedef struct
       
    67 {
       
    68     char *filename;
       
    69     PHYSFS_sint64 last_mod_time;
       
    70     PHYSFS_uint32 entryCount;
       
    71     PHYSFS_uint32 entryOffset;
       
    72     WADentry *entries;
       
    73 } WADinfo;
       
    74 
       
    75 typedef struct
       
    76 {
       
    77     void *handle;
       
    78     WADentry *entry;
       
    79     PHYSFS_uint32 curPos;
       
    80 } WADfileinfo;
       
    81 
       
    82 
       
    83 static void WAD_dirClose(DirHandle *h);
       
    84 static PHYSFS_sint64 WAD_read(FileHandle *handle, void *buffer,
       
    85                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
       
    86 static PHYSFS_sint64 WAD_write(FileHandle *handle, const void *buffer,
       
    87                                PHYSFS_uint32 objSize, PHYSFS_uint32 objCount);
       
    88 static int WAD_eof(FileHandle *handle);
       
    89 static PHYSFS_sint64 WAD_tell(FileHandle *handle);
       
    90 static int WAD_seek(FileHandle *handle, PHYSFS_uint64 offset);
       
    91 static PHYSFS_sint64 WAD_fileLength(FileHandle *handle);
       
    92 static int WAD_fileClose(FileHandle *handle);
       
    93 static int WAD_isArchive(const char *filename, int forWriting);
       
    94 static DirHandle *WAD_openArchive(const char *name, int forWriting);
       
    95 static LinkedStringList *WAD_enumerateFiles(DirHandle *h,
       
    96                                             const char *dirname,
       
    97                                             int omitSymLinks);
       
    98 static int WAD_exists(DirHandle *h, const char *name);
       
    99 static int WAD_isDirectory(DirHandle *h, const char *name, int *fileExists);
       
   100 static int WAD_isSymLink(DirHandle *h, const char *name, int *fileExists);
       
   101 static PHYSFS_sint64 WAD_getLastModTime(DirHandle *h, const char *n, int *e);
       
   102 static FileHandle *WAD_openRead(DirHandle *h, const char *name, int *exist);
       
   103 static FileHandle *WAD_openWrite(DirHandle *h, const char *name);
       
   104 static FileHandle *WAD_openAppend(DirHandle *h, const char *name);
       
   105 static int WAD_remove(DirHandle *h, const char *name);
       
   106 static int WAD_mkdir(DirHandle *h, const char *name);
       
   107 
       
   108 const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_WAD =
       
   109 {
       
   110     "WAD",
       
   111     /* !!! FIXME WAD_ARCHIVE_DESCRIPTION, */ "DOOM engine format",
       
   112     "Travis Wells <traviswells@mchsi.com>",
       
   113     "http://www.3dmm2.com/doom/",
       
   114 };
       
   115 
       
   116 
       
   117 static const FileFunctions __PHYSFS_FileFunctions_WAD =
       
   118 {
       
   119     WAD_read,       /* read() method       */
       
   120     WAD_write,      /* write() method      */
       
   121     WAD_eof,        /* eof() method        */
       
   122     WAD_tell,       /* tell() method       */
       
   123     WAD_seek,       /* seek() method       */
       
   124     WAD_fileLength, /* fileLength() method */
       
   125     WAD_fileClose   /* fileClose() method  */
       
   126 };
       
   127 
       
   128 
       
   129 const DirFunctions __PHYSFS_DirFunctions_WAD =
       
   130 {
       
   131     &__PHYSFS_ArchiveInfo_WAD,
       
   132     WAD_isArchive,          /* isArchive() method      */
       
   133     WAD_openArchive,        /* openArchive() method    */
       
   134     WAD_enumerateFiles,     /* enumerateFiles() method */
       
   135     WAD_exists,             /* exists() method         */
       
   136     WAD_isDirectory,        /* isDirectory() method    */
       
   137     WAD_isSymLink,          /* isSymLink() method      */
       
   138     WAD_getLastModTime,     /* getLastModTime() method */
       
   139     WAD_openRead,           /* openRead() method       */
       
   140     WAD_openWrite,          /* openWrite() method      */
       
   141     WAD_openAppend,         /* openAppend() method     */
       
   142     WAD_remove,             /* remove() method         */
       
   143     WAD_mkdir,              /* mkdir() method          */
       
   144     WAD_dirClose            /* dirClose() method       */
       
   145 };
       
   146 
       
   147 
       
   148 
       
   149 static void WAD_dirClose(DirHandle *h)
       
   150 {
       
   151     WADinfo *info = ((WADinfo *) h->opaque);
       
   152     free(info->filename);
       
   153     free(info->entries);
       
   154     free(info);
       
   155     free(h);
       
   156 } /* WAD_dirClose */
       
   157 
       
   158 
       
   159 static PHYSFS_sint64 WAD_read(FileHandle *handle, void *buffer,
       
   160                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
       
   161 {
       
   162     WADfileinfo *finfo = (WADfileinfo *) (handle->opaque);
       
   163     WADentry *entry = finfo->entry;
       
   164     PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
       
   165     PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
       
   166     PHYSFS_sint64 rc;
       
   167 
       
   168     if (objsLeft < objCount)
       
   169         objCount = objsLeft;
       
   170 
       
   171     rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
       
   172     if (rc > 0)
       
   173         finfo->curPos += (PHYSFS_uint32) (rc * objSize);
       
   174 
       
   175     return(rc);
       
   176 } /* WAD_read */
       
   177 
       
   178 
       
   179 static PHYSFS_sint64 WAD_write(FileHandle *handle, const void *buffer,
       
   180                                PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
       
   181 {
       
   182     BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
       
   183 } /* WAD_write */
       
   184 
       
   185 
       
   186 static int WAD_eof(FileHandle *handle)
       
   187 {
       
   188     WADfileinfo *finfo = (WADfileinfo *) (handle->opaque);
       
   189     WADentry *entry = finfo->entry;
       
   190     return(finfo->curPos >= entry->size);
       
   191 } /* WAD_eof */
       
   192 
       
   193 
       
   194 static PHYSFS_sint64 WAD_tell(FileHandle *handle)
       
   195 {
       
   196     return(((WADfileinfo *) (handle->opaque))->curPos);
       
   197 } /* WAD_tell */
       
   198 
       
   199 
       
   200 static int WAD_seek(FileHandle *handle, PHYSFS_uint64 offset)
       
   201 {
       
   202     WADfileinfo *finfo = (WADfileinfo *) (handle->opaque);
       
   203     WADentry *entry = finfo->entry;
       
   204     int rc;
       
   205 
       
   206     BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
       
   207     BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
       
   208     rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
       
   209     if (rc)
       
   210         finfo->curPos = (PHYSFS_uint32) offset;
       
   211 
       
   212     return(rc);
       
   213 } /* WAD_seek */
       
   214 
       
   215 
       
   216 static PHYSFS_sint64 WAD_fileLength(FileHandle *handle)
       
   217 {
       
   218     WADfileinfo *finfo = ((WADfileinfo *) handle->opaque);
       
   219     return((PHYSFS_sint64) finfo->entry->size);
       
   220 } /* WAD_fileLength */
       
   221 
       
   222 
       
   223 static int WAD_fileClose(FileHandle *handle)
       
   224 {
       
   225     WADfileinfo *finfo = ((WADfileinfo *) handle->opaque);
       
   226     BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
       
   227     free(finfo);
       
   228     free(handle);
       
   229     return(1);
       
   230 } /* WAD_fileClose */
       
   231 
       
   232 
       
   233 static int wad_open(const char *filename, int forWriting,
       
   234                     void **fh, PHYSFS_uint32 *count,PHYSFS_uint32 *offset)
       
   235 {
       
   236     PHYSFS_uint8 buf[4];
       
   237 
       
   238     *fh = NULL;
       
   239     BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
       
   240 
       
   241     *fh = __PHYSFS_platformOpenRead(filename);
       
   242     BAIL_IF_MACRO(*fh == NULL, NULL, 0);
       
   243     
       
   244     if (__PHYSFS_platformRead(*fh, buf, 4, 1) != 1)
       
   245         goto openWad_failed;
       
   246 
       
   247     if (memcmp(buf, "IWAD", 4) != 0 && memcmp(buf, "PWAD", 4) != 0)
       
   248     {
       
   249         __PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
       
   250         goto openWad_failed;
       
   251     } /* if */
       
   252 
       
   253     if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
       
   254         goto openWad_failed;
       
   255 
       
   256     *count = PHYSFS_swapULE32(*count);
       
   257 
       
   258     if (__PHYSFS_platformRead(*fh, offset, sizeof (PHYSFS_uint32), 1) != 1)
       
   259         goto openWad_failed;
       
   260 
       
   261     *offset = PHYSFS_swapULE32(*offset);
       
   262 
       
   263     return(1);
       
   264 
       
   265 openWad_failed:
       
   266     if (*fh != NULL)
       
   267         __PHYSFS_platformClose(*fh);
       
   268 
       
   269     *count = -1;
       
   270     *fh = NULL;
       
   271     return(0);
       
   272 } /* wad_open */
       
   273 
       
   274 
       
   275 static int WAD_isArchive(const char *filename, int forWriting)
       
   276 {
       
   277     void *fh;
       
   278     PHYSFS_uint32 fileCount,offset;
       
   279     int retval = wad_open(filename, forWriting, &fh, &fileCount,&offset);
       
   280 
       
   281     if (fh != NULL)
       
   282         __PHYSFS_platformClose(fh);
       
   283 
       
   284     return(retval);
       
   285 } /* WAD_isArchive */
       
   286 
       
   287 
       
   288 static int wad_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
       
   289 {
       
   290     WADentry *a = (WADentry *) _a;
       
   291     return(strcmp(a[one].name, a[two].name));
       
   292 } /* wad_entry_cmp */
       
   293 
       
   294 
       
   295 static void wad_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
       
   296 {
       
   297     WADentry tmp;
       
   298     WADentry *first = &(((WADentry *) _a)[one]);
       
   299     WADentry *second = &(((WADentry *) _a)[two]);
       
   300     memcpy(&tmp, first, sizeof (WADentry));
       
   301     memcpy(first, second, sizeof (WADentry));
       
   302     memcpy(second, &tmp, sizeof (WADentry));
       
   303 } /* wad_entry_swap */
       
   304 
       
   305 
       
   306 static int wad_load_entries(const char *name, int forWriting, WADinfo *info)
       
   307 {
       
   308     void *fh = NULL;
       
   309     PHYSFS_uint32 fileCount;
       
   310     PHYSFS_uint32 directoryOffset;
       
   311     WADentry *entry;
       
   312 
       
   313     BAIL_IF_MACRO(!wad_open(name, forWriting, &fh, &fileCount,&directoryOffset), NULL, 0);
       
   314     info->entryCount = fileCount;
       
   315     info->entries = (WADentry *) malloc(sizeof (WADentry) * fileCount);
       
   316     if (info->entries == NULL)
       
   317     {
       
   318         __PHYSFS_platformClose(fh);
       
   319         BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
       
   320     } /* if */
       
   321 
       
   322     __PHYSFS_platformSeek(fh,directoryOffset);
       
   323 
       
   324     for (entry = info->entries; fileCount > 0; fileCount--, entry++)
       
   325     {
       
   326         if (__PHYSFS_platformRead(fh, &entry->startPos, 4, 1) != 1)
       
   327         {
       
   328             __PHYSFS_platformClose(fh);
       
   329             return(0);
       
   330         } /* if */
       
   331         
       
   332         if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
       
   333         {
       
   334             __PHYSFS_platformClose(fh);
       
   335             return(0);
       
   336         } /* if */
       
   337 
       
   338         if (__PHYSFS_platformRead(fh, &entry->name, 8, 1) != 1)
       
   339         {
       
   340             __PHYSFS_platformClose(fh);
       
   341             return(0);
       
   342         } /* if */
       
   343 
       
   344         entry->name[8] = '\0'; /* name might not be null-terminated in file. */
       
   345         entry->size = PHYSFS_swapULE32(entry->size);
       
   346         entry->startPos = PHYSFS_swapULE32(entry->startPos);
       
   347     } /* for */
       
   348 
       
   349     __PHYSFS_platformClose(fh);
       
   350 
       
   351     __PHYSFS_sort(info->entries, info->entryCount,
       
   352                   wad_entry_cmp, wad_entry_swap);
       
   353     return(1);
       
   354 } /* wad_load_entries */
       
   355 
       
   356 
       
   357 static DirHandle *WAD_openArchive(const char *name, int forWriting)
       
   358 {
       
   359     WADinfo *info;
       
   360     DirHandle *retval = malloc(sizeof (DirHandle));
       
   361     PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
       
   362 
       
   363     BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
       
   364     info = retval->opaque = malloc(sizeof (WADinfo));
       
   365     if (info == NULL)
       
   366     {
       
   367         __PHYSFS_setError(ERR_OUT_OF_MEMORY);
       
   368         goto WAD_openArchive_failed;
       
   369     } /* if */
       
   370 
       
   371     memset(info, '\0', sizeof (WADinfo));
       
   372 
       
   373     info->filename = (char *) malloc(strlen(name) + 1);
       
   374     if (info->filename == NULL)
       
   375     {
       
   376         __PHYSFS_setError(ERR_OUT_OF_MEMORY);
       
   377         goto WAD_openArchive_failed;
       
   378     } /* if */
       
   379 
       
   380     if (!wad_load_entries(name, forWriting, info))
       
   381         goto WAD_openArchive_failed;
       
   382 
       
   383     strcpy(info->filename, name);
       
   384     info->last_mod_time = modtime;
       
   385     retval->funcs = &__PHYSFS_DirFunctions_WAD;
       
   386     return(retval);
       
   387 
       
   388 WAD_openArchive_failed:
       
   389     if (retval != NULL)
       
   390     {
       
   391         if (retval->opaque != NULL)
       
   392         {
       
   393             if (info->filename != NULL)
       
   394                 free(info->filename);
       
   395             if (info->entries != NULL)
       
   396                 free(info->entries);
       
   397             free(info);
       
   398         } /* if */
       
   399         free(retval);
       
   400     } /* if */
       
   401 
       
   402     return(NULL);
       
   403 } /* WAD_openArchive */
       
   404 
       
   405 
       
   406 static LinkedStringList *WAD_enumerateFiles(DirHandle *h,
       
   407                                             const char *dirname,
       
   408                                             int omitSymLinks)
       
   409 {
       
   410     WADinfo *info = ((WADinfo *) h->opaque);
       
   411     WADentry *entry = info->entries;
       
   412     LinkedStringList *retval = NULL, *p = NULL;
       
   413     PHYSFS_uint32 max = info->entryCount;
       
   414     PHYSFS_uint32 i;
       
   415 
       
   416     /* no directories in WAD files. */
       
   417     BAIL_IF_MACRO(*dirname != '\0', ERR_NOT_A_DIR, NULL);
       
   418 
       
   419     for (i = 0; i < max; i++, entry++)
       
   420         retval = __PHYSFS_addToLinkedStringList(retval, &p, entry->name, -1);
       
   421 
       
   422     return(retval);
       
   423 } /* WAD_enumerateFiles */
       
   424 
       
   425 
       
   426 static WADentry *wad_find_entry(WADinfo *info, const char *name)
       
   427 {
       
   428     char *ptr = strchr(name, '.');
       
   429     WADentry *a = info->entries;
       
   430     PHYSFS_sint32 lo = 0;
       
   431     PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
       
   432     PHYSFS_sint32 middle;
       
   433     int rc;
       
   434 
       
   435     /*
       
   436      * Rule out filenames to avoid unneeded processing...no dirs,
       
   437      *   big filenames, or extensions > 3 chars.
       
   438      */
       
   439     BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL);
       
   440     BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL);
       
   441     BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL);
       
   442 
       
   443     while (lo <= hi)
       
   444     {
       
   445         middle = lo + ((hi - lo) / 2);
       
   446         rc = strcmp(name, a[middle].name);
       
   447         if (rc == 0)  /* found it! */
       
   448             return(&a[middle]);
       
   449         else if (rc > 0)
       
   450             lo = middle + 1;
       
   451         else
       
   452             hi = middle - 1;
       
   453     } /* while */
       
   454 
       
   455     BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
       
   456 } /* wad_find_entry */
       
   457 
       
   458 
       
   459 static int WAD_exists(DirHandle *h, const char *name)
       
   460 {
       
   461     return(wad_find_entry(((WADinfo *) h->opaque), name) != NULL);
       
   462 } /* WAD_exists */
       
   463 
       
   464 
       
   465 static int WAD_isDirectory(DirHandle *h, const char *name, int *fileExists)
       
   466 {
       
   467     *fileExists = WAD_exists(h, name);
       
   468     return(0);  /* never directories in a wad. */
       
   469 } /* WAD_isDirectory */
       
   470 
       
   471 
       
   472 static int WAD_isSymLink(DirHandle *h, const char *name, int *fileExists)
       
   473 {
       
   474     *fileExists = WAD_exists(h, name);
       
   475     return(0);  /* never symlinks in a wad. */
       
   476 } /* WAD_isSymLink */
       
   477 
       
   478 
       
   479 static PHYSFS_sint64 WAD_getLastModTime(DirHandle *h,
       
   480                                         const char *name,
       
   481                                         int *fileExists)
       
   482 {
       
   483     WADinfo *info = ((WADinfo *) h->opaque);
       
   484     PHYSFS_sint64 retval = -1;
       
   485 
       
   486     *fileExists = (wad_find_entry(info, name) != NULL);
       
   487     if (*fileExists)  /* use time of WAD itself in the physical filesystem. */
       
   488         retval = ((WADinfo *) h->opaque)->last_mod_time;
       
   489 
       
   490     return(retval);
       
   491 } /* WAD_getLastModTime */
       
   492 
       
   493 
       
   494 static FileHandle *WAD_openRead(DirHandle *h, const char *fnm, int *fileExists)
       
   495 {
       
   496     WADinfo *info = ((WADinfo *) h->opaque);
       
   497     FileHandle *retval;
       
   498     WADfileinfo *finfo;
       
   499     WADentry *entry;
       
   500 
       
   501     entry = wad_find_entry(info, fnm);
       
   502     *fileExists = (entry != NULL);
       
   503     BAIL_IF_MACRO(entry == NULL, NULL, NULL);
       
   504 
       
   505     retval = (FileHandle *) malloc(sizeof (FileHandle));
       
   506     BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
       
   507     finfo = (WADfileinfo *) malloc(sizeof (WADfileinfo));
       
   508     if (finfo == NULL)
       
   509     {
       
   510         free(retval);
       
   511         BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
       
   512     } /* if */
       
   513 
       
   514     finfo->handle = __PHYSFS_platformOpenRead(info->filename);
       
   515     if ( (finfo->handle == NULL) ||
       
   516          (!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
       
   517     {
       
   518         free(finfo);
       
   519         free(retval);
       
   520         return(NULL);
       
   521     } /* if */
       
   522 
       
   523     finfo->curPos = 0;
       
   524     finfo->entry = entry;
       
   525     retval->opaque = (void *) finfo;
       
   526     retval->funcs = &__PHYSFS_FileFunctions_WAD;
       
   527     retval->dirHandle = h;
       
   528     return(retval);
       
   529 } /* WAD_openRead */
       
   530 
       
   531 
       
   532 static FileHandle *WAD_openWrite(DirHandle *h, const char *name)
       
   533 {
       
   534     BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
       
   535 } /* WAD_openWrite */
       
   536 
       
   537 
       
   538 static FileHandle *WAD_openAppend(DirHandle *h, const char *name)
       
   539 {
       
   540     BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
       
   541 } /* WAD_openAppend */
       
   542 
       
   543 
       
   544 static int WAD_remove(DirHandle *h, const char *name)
       
   545 {
       
   546     BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
       
   547 } /* WAD_remove */
       
   548 
       
   549 
       
   550 static int WAD_mkdir(DirHandle *h, const char *name)
       
   551 {
       
   552     BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
       
   553 } /* WAD_mkdir */
       
   554 
       
   555 #endif  /* defined PHYSFS_SUPPORTS_WAD */
       
   556 
       
   557 /* end of wad.c ... */
       
   558