misc/libphysfs/archiver_unpacked.c
changeset 12213 bb5522e88ab2
parent 10017 de822cd3df3a
equal deleted inserted replaced
12212:ea891871f481 12213:bb5522e88ab2
     5  *  formats that can just hand back a list of files and the offsets of their
     5  *  formats that can just hand back a list of files and the offsets of their
     6  *  uncompressed data. There are an alarming number of formats like this.
     6  *  uncompressed data. There are an alarming number of formats like this.
     7  *
     7  *
     8  * RULES: Archive entries must be uncompressed, must not have separate subdir
     8  * RULES: Archive entries must be uncompressed, must not have separate subdir
     9  *  entries (but can have subdirs), must be case insensitive LOW ASCII
     9  *  entries (but can have subdirs), must be case insensitive LOW ASCII
    10  *  filenames <= 56 bytes. No symlinks, etc. We can relax some of these rules
    10  *  filenames <= 64 bytes. No symlinks, etc. We can relax some of these rules
    11  *  as necessary.
    11  *  as necessary.
    12  *
    12  *
    13  * Please see the file LICENSE.txt in the source's root directory.
    13  * Please see the file LICENSE.txt in the source's root directory.
    14  *
    14  *
    15  *  This file written by Ryan C. Gordon.
    15  *  This file written by Ryan C. Gordon.
    32     UNPKentry *entry;
    32     UNPKentry *entry;
    33     PHYSFS_uint32 curPos;
    33     PHYSFS_uint32 curPos;
    34 } UNPKfileinfo;
    34 } UNPKfileinfo;
    35 
    35 
    36 
    36 
    37 void UNPK_closeArchive(PHYSFS_Dir *opaque)
    37 void UNPK_closeArchive(void *opaque)
    38 {
    38 {
    39     UNPKinfo *info = ((UNPKinfo *) opaque);
    39     UNPKinfo *info = ((UNPKinfo *) opaque);
    40     info->io->destroy(info->io);
    40     info->io->destroy(info->io);
    41     allocator.Free(info->entries);
    41     allocator.Free(info->entries);
    42     allocator.Free(info);
    42     allocator.Free(info);
   198             char ch = name[dlen];
   198             char ch = name[dlen];
   199             if (ch < '/') /* make sure this isn't just a substr match. */
   199             if (ch < '/') /* make sure this isn't just a substr match. */
   200                 rc = -1;
   200                 rc = -1;
   201             else if (ch > '/')
   201             else if (ch > '/')
   202                 rc = 1;
   202                 rc = 1;
   203             else
   203             else 
   204             {
   204             {
   205                 if (stop_on_first_find) /* Just checking dir's existance? */
   205                 if (stop_on_first_find) /* Just checking dir's existance? */
   206                     return middle;
   206                     return middle;
   207 
   207 
   208                 if (name[dlen + 1] == '\0') /* Skip initial dir entry. */
   208                 if (name[dlen + 1] == '\0') /* Skip initial dir entry. */
   240     cb(callbackdata, odir, newstr);
   240     cb(callbackdata, odir, newstr);
   241     __PHYSFS_smallFree(newstr);
   241     __PHYSFS_smallFree(newstr);
   242 } /* doEnumCallback */
   242 } /* doEnumCallback */
   243 
   243 
   244 
   244 
   245 void UNPK_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
   245 void UNPK_enumerateFiles(void *opaque, const char *dname,
   246                          int omitSymLinks, PHYSFS_EnumFilesCallback cb,
   246                          PHYSFS_EnumFilesCallback cb,
   247                          const char *origdir, void *callbackdata)
   247                          const char *origdir, void *callbackdata)
   248 {
   248 {
   249     UNPKinfo *info = ((UNPKinfo *) opaque);
   249     UNPKinfo *info = ((UNPKinfo *) opaque);
   250     PHYSFS_sint32 dlen, dlen_inc, max, i;
   250     PHYSFS_sint32 dlen, dlen_inc, max, i;
   251 
   251 
   291 } /* UNPK_enumerateFiles */
   291 } /* UNPK_enumerateFiles */
   292 
   292 
   293 
   293 
   294 /*
   294 /*
   295  * This will find the UNPKentry associated with a path in platform-independent
   295  * This will find the UNPKentry associated with a path in platform-independent
   296  *  notation. Directories don't have UNPKentries associated with them, but
   296  *  notation. Directories don't have UNPKentries associated with them, but 
   297  *  (*isDir) will be set to non-zero if a dir was hit.
   297  *  (*isDir) will be set to non-zero if a dir was hit.
   298  */
   298  */
   299 static UNPKentry *findEntry(const UNPKinfo *info, const char *path, int *isDir)
   299 static UNPKentry *findEntry(const UNPKinfo *info, const char *path, int *isDir)
   300 {
   300 {
   301     UNPKentry *a = info->entries;
   301     UNPKentry *a = info->entries;
   338     } /* while */
   338     } /* while */
   339 
   339 
   340     if (isDir != NULL)
   340     if (isDir != NULL)
   341         *isDir = 0;
   341         *isDir = 0;
   342 
   342 
   343     BAIL_MACRO(PHYSFS_ERR_NO_SUCH_PATH, NULL);
   343     BAIL_MACRO(PHYSFS_ERR_NOT_FOUND, NULL);
   344 } /* findEntry */
   344 } /* findEntry */
   345 
   345 
   346 
   346 
   347 PHYSFS_Io *UNPK_openRead(PHYSFS_Dir *opaque, const char *fnm, int *fileExists)
   347 PHYSFS_Io *UNPK_openRead(void *opaque, const char *name)
   348 {
   348 {
   349     PHYSFS_Io *retval = NULL;
   349     PHYSFS_Io *retval = NULL;
   350     UNPKinfo *info = (UNPKinfo *) opaque;
   350     UNPKinfo *info = (UNPKinfo *) opaque;
   351     UNPKfileinfo *finfo = NULL;
   351     UNPKfileinfo *finfo = NULL;
   352     int isdir = 0;
   352     int isdir = 0;
   353     UNPKentry *entry = findEntry(info, fnm, &isdir);
   353     UNPKentry *entry = findEntry(info, name, &isdir);
   354 
   354 
   355     *fileExists = (entry != NULL);
       
   356     GOTO_IF_MACRO(isdir, PHYSFS_ERR_NOT_A_FILE, UNPK_openRead_failed);
   355     GOTO_IF_MACRO(isdir, PHYSFS_ERR_NOT_A_FILE, UNPK_openRead_failed);
   357     GOTO_IF_MACRO(!entry, ERRPASS, UNPK_openRead_failed);
   356     GOTO_IF_MACRO(!entry, ERRPASS, UNPK_openRead_failed);
   358 
   357 
   359     retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io));
   358     retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io));
   360     GOTO_IF_MACRO(!retval, PHYSFS_ERR_OUT_OF_MEMORY, UNPK_openRead_failed);
   359     GOTO_IF_MACRO(!retval, PHYSFS_ERR_OUT_OF_MEMORY, UNPK_openRead_failed);
   388 
   387 
   389     return NULL;
   388     return NULL;
   390 } /* UNPK_openRead */
   389 } /* UNPK_openRead */
   391 
   390 
   392 
   391 
   393 PHYSFS_Io *UNPK_openWrite(PHYSFS_Dir *opaque, const char *name)
   392 PHYSFS_Io *UNPK_openWrite(void *opaque, const char *name)
   394 {
   393 {
   395     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
   394     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
   396 } /* UNPK_openWrite */
   395 } /* UNPK_openWrite */
   397 
   396 
   398 
   397 
   399 PHYSFS_Io *UNPK_openAppend(PHYSFS_Dir *opaque, const char *name)
   398 PHYSFS_Io *UNPK_openAppend(void *opaque, const char *name)
   400 {
   399 {
   401     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
   400     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
   402 } /* UNPK_openAppend */
   401 } /* UNPK_openAppend */
   403 
   402 
   404 
   403 
   405 int UNPK_remove(PHYSFS_Dir *opaque, const char *name)
   404 int UNPK_remove(void *opaque, const char *name)
   406 {
   405 {
   407     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
   406     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
   408 } /* UNPK_remove */
   407 } /* UNPK_remove */
   409 
   408 
   410 
   409 
   411 int UNPK_mkdir(PHYSFS_Dir *opaque, const char *name)
   410 int UNPK_mkdir(void *opaque, const char *name)
   412 {
   411 {
   413     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
   412     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
   414 } /* UNPK_mkdir */
   413 } /* UNPK_mkdir */
   415 
   414 
   416 
   415 
   417 int UNPK_stat(PHYSFS_Dir *opaque, const char *filename,
   416 int UNPK_stat(void *opaque, const char *filename, PHYSFS_Stat *stat)
   418               int *exists, PHYSFS_Stat *stat)
       
   419 {
   417 {
   420     int isDir = 0;
   418     int isDir = 0;
   421     const UNPKinfo *info = (const UNPKinfo *) opaque;
   419     const UNPKinfo *info = (const UNPKinfo *) opaque;
   422     const UNPKentry *entry = findEntry(info, filename, &isDir);
   420     const UNPKentry *entry = findEntry(info, filename, &isDir);
   423 
   421 
   424     if (isDir)
   422     if (isDir)
   425     {
   423     {
   426         *exists = 1;
       
   427         stat->filetype = PHYSFS_FILETYPE_DIRECTORY;
   424         stat->filetype = PHYSFS_FILETYPE_DIRECTORY;
   428         stat->filesize = 0;
   425         stat->filesize = 0;
   429     } /* if */
   426     } /* if */
   430     else if (entry != NULL)
   427     else if (entry != NULL)
   431     {
   428     {
   432         *exists = 1;
       
   433         stat->filetype = PHYSFS_FILETYPE_REGULAR;
   429         stat->filetype = PHYSFS_FILETYPE_REGULAR;
   434         stat->filesize = entry->size;
   430         stat->filesize = entry->size;
   435     } /* else if */
   431     } /* else if */
   436     else
   432     else
   437     {
   433     {
   438         *exists = 0;
       
   439         return 0;
   434         return 0;
   440     } /* else */
   435     } /* else */
   441 
   436 
   442     stat->modtime = -1;
   437     stat->modtime = -1;
   443     stat->createtime = -1;
   438     stat->createtime = -1;
   446 
   441 
   447     return 1;
   442     return 1;
   448 } /* UNPK_stat */
   443 } /* UNPK_stat */
   449 
   444 
   450 
   445 
   451 PHYSFS_Dir *UNPK_openArchive(PHYSFS_Io *io, UNPKentry *e,
   446 void *UNPK_openArchive(PHYSFS_Io *io, UNPKentry *e, const PHYSFS_uint32 num)
   452                              const PHYSFS_uint32 num)
       
   453 {
   447 {
   454     UNPKinfo *info = (UNPKinfo *) allocator.Malloc(sizeof (UNPKinfo));
   448     UNPKinfo *info = (UNPKinfo *) allocator.Malloc(sizeof (UNPKinfo));
   455     if (info == NULL)
   449     if (info == NULL)
   456     {
   450     {
   457         allocator.Free(e);
   451         allocator.Free(e);