⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unzip.c

📁 空战游戏flacon源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* ==========================================================================

    Unzip.cpp    

    Interface into the inflation (decompression) of compressed archive files.
    These functions (as the name unzip.cpp implies) provide methods for 
    extracting data from files created with either Phil Katz's PKZIP or 
    Mark Adlers (GCC) unzip.

    Originally, this file was kept as similiar to the original dounzip.c
    that is part of the gcc unzip distribution.  The idea being that anyone
    could diff this file versus that file and see the changes that were
    made.  Unfortunately, the number have changes have become so great that
    there would be far more differences than similarities, making this
    process of little benefit.

    Inflate.cpp, inflate.h and unzip.h are exactly as they are in the
    gcc distribution.  **Touch them if you dare**.

    *06/12/96 - not any more, inflate is now completely thread safe, and 
    therefore, looks nothing like it did before (not that its good - but 
    it is better)*

    NOTE:  MSVC users - don't even bother trying to 'Update Dependencies'.
           Uggh!  06/30/96 - This should work now

	Created     Mark Adler & Jean-loup Gailly (GCC)
    Modified    Roger Fujii (STTNG:AFU)
    Big Purge   Kevin Ray   (RESMGR)


	RESMGR Library component unzip.cpp (ver: 2.05	released 03/26/97)

   ========================================================================== */

#include <ctype.h>
#include <fcntl.h>

#include "lists.h"
#include "unzip.h"                    /* includes, typedefs, macros, etc.        */
#include "resmgr.h"
#include "omni.h"

#include <assert.h>

#ifdef USE_SH_POOLS
#undef MemFree
#undef MemFreePtr
#undef MemMalloc
#include "Smartheap\Include\smrtheap.h"
extern MEM_POOL gResmgrMemPool;
#endif

/* -------------------------------------------------------------------------

    S T A T I C   D A T A 

   ------------------------------------------------------------------------- */

static char seeklocked = FALSE;
int UNZIP_ERROR = 0; /* errno */

                                    /* initialize signatures at runtime so unzip 
                                       executable won't look like a zipfile */

static char near central_hdr_sig[5] = { 0, '\113', '\001', '\002' };
static char near local_hdr_sig[5]   = { 0, '\113', '\003', '\004' };
static char near end_central_sig[5] = { 0, '\113', '\005', '\006' };


/* -------------------------------------------------------------------------

    L O C A L   P R O T O T Y P E S

   ------------------------------------------------------------------------- */

	   int extract_or_test_member( int method, long ucsize, COMPRESSED_FILE * cmp );   /* return PK-type error code */
static int process_cdir_file_hdr( cdir_file_hdr * crec, ARCHIVE * arc );
static int do_string( unsigned int len, int option, char * filename, ARCHIVE * arc );
static int get_cdir_file_hdr( cdir_file_hdr * crec, ARCHIVE * arc );
	   int archive_size( ARCHIVE * arc );

int unzip_seek( LONGINT val, ARCHIVE * arc );
int process_local_file_hdr( local_file_hdr * lrec, char * buffer );

#define CREATE_LOCK(a)      CreateMutex( NULL,  FALSE, a );
#define REQUEST_LOCK(a)     WaitForSingleObject(a, INFINITE);
#define RELEASE_LOCK(a)     ReleaseMutex(a);
#define DESTROY_LOCK(a)     CloseHandle(a);


/* -------------------------------------------------------------------------

    E X T E R N A L   P R O T O T Y P E S   &   D A T A

   ------------------------------------------------------------------------- */

extern HASH_ENTRY * hash_add( struct _finddata_t * data, HASH_TABLE * table );
extern HASH_ENTRY * hash_find( const char * name, HASH_TABLE * hsh );                /* find an entry within a hash table    */
extern HASH_TABLE * hash_create( int size, char * filename );
extern int          hash_resize( HASH_TABLE * table );

extern char       * res_fullpath( char * abs_buffer, const char * rel_buffer, int maxlen );

extern HASH_TABLE * GLOBAL_HASH_TABLE;
extern LIST *       GLOBAL_PATH_LIST;
extern char *       GLOBAL_SEARCH_PATH[];
extern int          GLOBAL_SEARCH_INDEX;
extern int          RES_DEBUG_ERRNO;

#if( RES_DEBUG_VERSION )
void 
    _say_error( int error, const char * msg, int line, const char * filename );

#   define SAY_ERROR(a,b)   _say_error((a),(b), __LINE__, __FILE__ )
#else
#   define SAY_ERROR(a,b)   {RES_DEBUG_ERRNO=(a);}
#endif /* RES_DEBUG_VERSION */




/* -------------------------------------------------------------------------

    C O M P I L E R   D E F I N I T I O N S

   ------------------------------------------------------------------------- */

#define MAKE_WORD(a)            makeword( &byterec[(a)] );
#define MAKE_LONG(a)            makelong( &byterec[(a)] );

#define WriteError(buf, len, strm) memcpy((void *)((int)arc -> out_buffer + arc -> out_count), buf, len); arc -> out_count += len;

#ifdef SFX
#  define UNKN_COMPR \
    (crec.compression_method!=STORED && crec.compression_method!=DEFLATED)
#else
#  define UNKN_COMPR \
    (crec.compression_method>IMPLODED && crec.compression_method!=DEFLATED)
#endif


#define UNZIP_LSEEK(a,b)        unzip_seek(a,b)





/* =======================================================

    FUNCTION:    archive_create

    PURPOSE:     Main interface into the unzip functions.
                 archive_create opens a compressed 
                 archive file and adds the contents into
                 the hash table at the point specified.

    PARAMS:      Ptr to a directory to attach the 
                 archive into, ptr to a complete filename
                 of the archive file, ptr to the hash
                 table for the attach point.

    RETURNS:     Ptr to the create archive structure.

   ======================================================= */

ARCHIVE * archive_create( const char * attach_point, const char * filename, HASH_TABLE * table, int replace_flag )
{
    ARCHIVE     * arc;
    HASH_ENTRY  * entry;
	struct _finddata_t data;     /* for hash_find */
    struct _finddata_t info;
    
    char    sig[5];
    char    vol_was;
    int     dir_was;
    int     error = 0, 
            error_in_archive = 0,
            i, len;

    char    path_was[_MAX_PATH],
            path[_MAX_PATH];
    char *  fname;                  /* used to truncate path from filename */
    int     path_idx;

    ecdir_rec ecrec;                /* used in unzip.c, extract.c */

//    int filnum=(-1);

    ush members_remaining;//, 
//        num_skipped = 0, 
//        num_bad_pwd = 0;

    char curfilename[FILNAMSIZ];
    cdir_file_hdr crec;             /* used in unzip.c, extract.c, misc.c */

	#ifdef USE_SH_POOLS
    arc = (ARCHIVE *)MemAllocPtr( gResmgrMemPool, sizeof(ARCHIVE), 0 );
	#else
    arc = (ARCHIVE *)MemMalloc( sizeof(ARCHIVE), filename );
	#endif

    if( !arc ) {
        UNZIP_ERROR = RES_ERR_NO_MEMORY;
        return( NULL );
    }
  
    strcpy( arc -> name, filename );

    arc -> lock = CREATE_LOCK( "Archive" );

    /*---------------------------------------------------------------------------
       Start by constructing the various PK signature strings.
      ---------------------------------------------------------------------------*/

    local_hdr_sig[0]   = '\120';   /* ASCII 'P', */
    central_hdr_sig[0] = '\120';
    end_central_sig[0] = '\120';   /* not EBCDIC */

    strcpy( path_was, attach_point );
    
	#ifdef USE_SH_POOLS
    arc -> tmp_slide = (uch *)MemAllocPtr( gResmgrMemPool,  UNZIP_SLIDE_SIZE, 0 );
	#else
    arc -> tmp_slide = (uch *)MemMalloc( UNZIP_SLIDE_SIZE, "Slide" );
	#endif

    if( arc -> tmp_slide == NULL ) {
        UNZIP_ERROR = RES_ERR_NO_MEMORY;
        return( NULL );    /* 4 extra for hold[] (below) */
    }

    {
        struct stat statbuf;

        if( SSTAT(filename, &statbuf) || (error = S_ISDIR(statbuf.st_mode)) != 0)
        {
            ResCheckMedia( toupper(filename[0]) - 'A' ); /* see if media has been swapped */

			#ifdef USE_SH_POOLS
            MemFreePtr( arc -> tmp_slide );
            MemFreePtr( arc );
			#else
            MemFree( arc -> tmp_slide );
            MemFree( arc );
			#endif
            UNZIP_ERROR = RES_ERR_UNKNOWN;
            return( NULL );
        }

        arc -> length = statbuf.st_size;
    }

    if(( arc -> os_handle = _open( filename, O_RDONLY | O_BINARY )) < 0 )
    {
        ResCheckMedia( toupper(filename[0]) - 'A' ); /* see if media has been swapped */

		#ifdef USE_SH_POOLS
		MemFreePtr( arc -> tmp_slide );
		MemFreePtr( arc );
		#else
		MemFree( arc -> tmp_slide );
		MemFree( arc );
		#endif
        UNZIP_ERROR = RES_ERR_NO_MEMORY;
        return( NULL );
    }

    res_fullpath( path, filename, _MAX_PATH );
    arc -> volume = (char)(toupper( path[0] ) - 'A');

    arc -> start_buffer = 0;

    // Use 2048 size buffer for now, so we don't break things
    // But Input buffer is set to INPUTBUFSIZE >> 2048 + 4

    arc -> tmp_in_size = UNZIP_BUFFER_SIZE;

	#ifdef USE_SH_POOLS
    if(( arc -> tmp_in_buffer = (uch *)MemAllocPtr( gResmgrMemPool, INPUTBUFSIZE, 0 )) == NULL )
    {
         _close( arc -> os_handle );
        MemFreePtr( arc -> tmp_slide );
        MemFreePtr( arc );
        UNZIP_ERROR = RES_ERR_NO_MEMORY;
        return( NULL );
    }
	#else
    if(( arc -> tmp_in_buffer = (uch *)MemMalloc( INPUTBUFSIZE, "input buffer" )) == NULL )
    {
         _close( arc -> os_handle );
        MemFree( arc -> tmp_slide );
        MemFree( arc );
        UNZIP_ERROR = RES_ERR_NO_MEMORY;
        return( NULL );
    }
	#endif

    arc -> tmp_hold = (uch *)(arc -> tmp_in_buffer + arc -> tmp_in_size);    /* to check for boundary-spanning signatures */

    arc -> tmp_in_ptr = (uch *)(arc -> tmp_in_buffer);

#if( RES_PREDETERMINE_SIZE )
    int sz;

    sz = archive_size( arc );

   /* printf( "archive size: %d\n", sz );*/

    if( ARCHIVE_TABLE_SIZE < (sz>>1)) {
        table -> num_entries = sz;
        if( !hash_resize( table )) {
            _close( arc -> os_handle );
			#ifdef USE_SH_POOLS
            MemFreePtr( arc -> tmp_in_buffer );
			MemFreePtr( arc -> tmp_slide );
			MemFreePtr( arc );
			#else
            MemFree( arc -> tmp_in_buffer );
			MemFree( arc -> tmp_slide );
			MemFree( arc );
			#endif
            UNZIP_ERROR = RES_ERR_NO_MEMORY;
            return( NULL );
        }
    }
#endif /*RES_PREDETERMINE_SIZE */

    //****** (arc -> len) ?  66000L ? *****//
    if(( ((error_in_archive = find_end_central_dir(MIN((arc -> length),66000L), &ecrec, arc)) != 0 ))) 
    {
        _close( arc -> os_handle );
		#ifdef USE_SH_POOLS
		MemFreePtr( arc -> tmp_in_buffer );
		MemFreePtr( arc -> tmp_slide );
		MemFreePtr( arc );
		#else
		MemFree( arc -> tmp_in_buffer );
		MemFree( arc -> tmp_slide );
		MemFree( arc );
		#endif
        UNZIP_ERROR = RES_ERR_NO_MEMORY;
        return( NULL );
    }

    /*-----------------------------------------------------------------------
        Compensate for missing or extra bytes, and seek to where the start
        of central directory should be.  If header not found, uncompensate
        and try again (necessary for at least some Atari archives created
        with STZIP, as well as archives created by J.H. Holm's ZIPSPLIT 1.1).
      ----------------------------------------------------------------------- */

    //LSEEK( ecrec.offset_start_central_directory );

    if( UNZIP_LSEEK( ecrec.offset_start_central_directory, arc )) {
        _close( arc -> os_handle );
		#ifdef USE_SH_POOLS
		MemFreePtr( arc -> tmp_in_buffer );
		MemFreePtr( arc -> tmp_slide );
		MemFreePtr( arc );
		#else
		MemFree( arc -> tmp_in_buffer );
		MemFree( arc -> tmp_slide );
		MemFree( arc );
		#endif
        UNZIP_ERROR = RES_ERR_NO_MEMORY;
        return( NULL );
    }


    /* -----------------------------------------------------------------------
        Seek to the start of the central directory one last time, since we
        have just read the first entry's signature bytes; then list, extract
        or test member files as instructed, and close the zipfile.
       -----------------------------------------------------------------------*/

    /* ---------------------------------------------------------------------------
        The basic idea of this function is as follows.  Since the central di-
        rectory lies at the end of the zipfile and the member files lie at the
        beginning or middle or wherever, it is not very desirable to simply
        read a central directory entry, jump to the member and extract it, and

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -