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

📄 resmgr.c

📁 空战游戏flacon源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    char filename[_MAX_PATH];

    int   retval = 1;
    int   handle;
    int   dir_index;

    struct _finddata_t data; /* used to dummy-up a hash entry */

    char tmp[LREC_SIZE];
    local_file_hdr lrec;
        
    IF_LOG( LOG( "open (%s):\n", name ));


#if( RES_DEBUG_PARAMS )
    if( !name ) {
        SAY_ERROR( RES_ERR_INCORRECT_PARAMETER, "ResOpenFile" );
        return( -1 );
    }
#endif

#if (RES_MULTITHREAD)
	REQUEST_LOCK(GLOCK);
#endif


    /* get the next available file handle */
    handle = get_handle();

    if( handle == -1 ) { /* none left */
        SAY_ERROR( RES_ERR_TOO_MANY_FILES, "ResOpenFile" );
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */ 
#endif

        return( -1 );
    }

    file = &FILE_HANDLES[ handle ];
   

    /* ----------------------------------------------------
       Find the hash entry for the given filename.  If we
       are building a hierarchical model, we need to search
       all of the tables in the order of our search path
       (hash_find_table), otherwise, we just need to search
       our main hash table (hash_find).

       If filename coercion is being used, the filename
       string is scanned for the occurence of a backslash.
       If there is one, the code forces a fullpath name
       conversion on this string in-case it is a relative
       pathname (eg; ..\windows\foo.c).
       ----------------------------------------------------  */

#if( !RES_USE_FLAT_MODEL )
    entry = hash_find_table( name, &table );
#else /* flat model */
    entry = hash_find( name, GLOBAL_HASH_TABLE );
#endif

    if( !entry ) {   /* NOT FOUND */
        /* if the user is trying to create a file on the harddrive,
           this is ok. */

        if( !(mode & _O_CREAT)) {
            SAY_ERROR( RES_ERR_FILE_NOT_FOUND, name );
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif

            return( -1 );
        }
        else {
            /* CREATING A FILE */

            /* In this case, we need to make sure that the directory is already 'added'
               to the resource manager if we are using hierarchical model.  If we are
               using the flat model, we just need to create a dummy hash_entry for the
               file.  The file size member of the hash entry structure will be set 
               in ResFileClose. */

            IF_LOG( LOG( "creating file: %s\n", name ));

#if( !RES_USE_FLAT_MODEL )
            if( strchr( name, ASCII_BACKSLASH )) {
                split_path( name, filename, dirpath );
                entry = hash_find( dirpath, GLOBAL_HASH_TABLE );
            }
            else {/* current directory */
                strcpy( filename, name );
                strcpy( dirpath, GLOBAL_CURRENT_PATH );
                entry = hash_find( GLOBAL_CURRENT_PATH, GLOBAL_HASH_TABLE );
            }

            if( !entry || !entry -> dir ) { /* directory is not already added */
                SAY_ERROR( RES_ERR_UNKNOWN_WRITE_TO, name );
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif

                return( -1 );
            }
            else {
                table = (HASH_TABLE *)entry -> dir;
            }

#else /* flat model */
            if( strchr( name, ASCII_BACKSLASH ))
                split_path( name, filename, dirpath );
            else /* current directory */
                strcpy( filename, name );
        
            table = GLOBAL_HASH_TABLE;
#endif /* !RES_USE_FLAT_MODEL */

            strcpy( data.name, filename );

            data.attrib = (unsigned int)FORCE_BIT;
            data.time_create = 0;
            data.time_access = 0;
            data.size = 0;

            entry = hash_add( &data, table );

            if( !entry ) {
                SAY_ERROR( RES_ERR_UNKNOWN, "ResOpen - create" );
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif

                return( -1 );
            }

            for( dir_index = 0; dir_index <= GLOBAL_SEARCH_INDEX; dir_index++ ) {
                if( !stricmp( dirpath, GLOBAL_SEARCH_PATH[ dir_index ] )) {
                    entry -> directory = dir_index;
                    entry -> volume = (char)(toupper(dirpath[0]) - 'A');
                    break;
                }
            }

            if( dir_index > GLOBAL_SEARCH_INDEX ) {
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif
                return( -1 );
			}

            entry -> archive = -1;
        }
    }


    /* Make sure the user isn't trying to write to an archive file.
       Someday this may be possible, but not for a while. */

    if( entry -> archive != -1 ) {
        int check;

        check = (_O_CREAT | _O_APPEND | _O_RDWR | _O_WRONLY);
        check &= mode;

        if( check ) {/* don't known why had to do it broken out like this - ask MSVC */
            SAY_ERROR( RES_ERR_CANT_WRITE_ARCHIVE, name );
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif
            return( -1 );
        }
    }

    
	/* Initialize some common data */
    file -> current_pos = 0;
    file -> current_filbuf_pos = 0;


    /* Is this a loose file (not in an archive?) */

    if( entry -> archive == -1 ) {
        /* may seem redundant but there are too many pathological cases otherwise */

        if( mode & _O_CREAT )
            res_fullpath( filename, name, _MAX_PATH );  /* regardless of coercion state */
        else
            sprintf( filename, "%s%s", GLOBAL_SEARCH_PATH[ entry -> directory ], entry -> name );

        /* there is actually a third parameter to open() (MSVC just doesn't admit it) 
           octal 666 ensures that stack-crap won't accidently create this file as
           read-only.  Thank to Roger Fujii for this fix! */

        file -> os_handle = _open( filename, mode, 0x1b6 /* choked on O666 and O666L */ );
    
        if( file -> os_handle == -1 ) {

			if( errno == EACCES )
                          {SAY_ERROR( RES_ERR_FILE_SHARING, filename );}
			else
                          {SAY_ERROR( RES_ERR_FILE_NOT_FOUND, filename );}

            ResCheckMedia( entry -> volume );
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif
            return( -1 );
        }

        file -> seek_start  = 0;
        file -> size        = entry -> size;
        file -> csize       = 0;
        file -> attrib      = entry -> attrib;
        file -> mode        = mode;
        file -> location    = -1;
        file -> zip         = NULL;
        file -> filename    = MemStrDup( filename );
        file -> device      = entry -> volume;
    
        SHOULD_I_CALL_WITH( CALLBACK_OPEN_FILE, handle, retval );
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif
        return( handle );
    }
    else {   /* in an archive */
        /* using the handle, search the list for the structure */

        for( list = ARCHIVE_LIST; list; list = list -> next ) {
            archive = (ARCHIVE *)list -> node;

            if( archive -> os_handle == entry -> archive )
               break;
        }

        if( !list ) {
           SAY_ERROR( RES_ERR_UNKNOWN, " " ); /* archive handle in hash entry is incorrect (or archive detached) */
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif
           return( -1 );
        }

        sprintf( filename, "%s%s", GLOBAL_SEARCH_PATH[ entry -> directory ], entry -> name );

        lseek( archive -> os_handle, entry -> file_position + SIGNATURE_SIZE, SEEK_SET );

        _read( archive -> os_handle, tmp, LREC_SIZE );

        process_local_file_hdr( &lrec, tmp );    /* return PK-type error code */

        file -> seek_start = lseek( archive -> os_handle, lrec.filename_length + lrec.extra_field_length, SEEK_CUR );

        switch( entry -> method ) {
            case STORED: {
                file -> os_handle   = archive -> os_handle;
                //file -> seek_start  = entry -> file_position;
                file -> csize       = 0;
                file -> size        = entry -> size;
                file -> filename    = MemStrDup( filename );
                file -> mode        = mode;
                file -> device      = entry -> volume;
                file -> zip         = NULL; /* only used if we need to deflate */

                SHOULD_I_CALL_WITH( CALLBACK_OPEN_FILE, handle, retval );
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif
                return( handle );
                break;
            }

            case DEFLATED: {
                COMPRESSED_FILE * zip;
                                 
				#ifdef USE_SH_POOLS
                zip = (COMPRESSED_FILE *)MemAllocPtr( gResmgrMemPool, sizeof(COMPRESSED_FILE) + (entry -> size), 0 );
				#else
                zip = (COMPRESSED_FILE *)MemMalloc( sizeof(COMPRESSED_FILE) + (entry -> size), "Inflate" );
				#endif

                if( !zip ) {
                    SAY_ERROR( RES_ERR_NO_MEMORY, "Inflate" );
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif
                    return(-1);
                }

                file -> os_handle   = archive -> os_handle;
                //file -> seek_start  = entry -> file_position;
                file -> csize       = entry -> csize;
                file -> size        = entry -> size;
                file -> filename    = MemStrDup( filename );
                file -> mode        = mode;
                file -> device      = entry -> volume;

				#ifdef USE_SH_POOLS
                zip -> slide      = (uch *)MemAllocPtr( gResmgrMemPool, UNZIP_SLIDE_SIZE + INPUTBUFSIZE, 0 ); /* glob temporary allocations */
				#else
                zip -> slide      = (uch *)MemMalloc( UNZIP_SLIDE_SIZE + INPUTBUFSIZE, "deflate" ); /* glob temporary allocations */
				#endif

                zip -> in_buffer  = (uch *)zip -> slide + UNZIP_SLIDE_SIZE;
                zip -> in_ptr     = (uch *)zip -> in_buffer;
                zip -> in_count   = 0;
                zip -> in_size    = file -> csize > INPUTBUFSIZE ? INPUTBUFSIZE : file -> csize;
                zip -> csize      = file -> csize;

                zip -> out_buffer = (char *)zip + sizeof(COMPRESSED_FILE);
                zip -> out_count  = 0;
                zip -> archive    = archive;

                file -> zip       = zip;    /* Future use: I may add incremental deflation */

                inflate( zip );

				#ifdef USE_SH_POOLS
                MemFreePtr( zip -> slide );    /* Free temporary allocations */
				#else
                MemFree( zip -> slide );    /* Free temporary allocations */
				#endif

                SHOULD_I_CALL_WITH( CALLBACK_OPEN_FILE, handle, retval );
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif
                return( handle );
                break;
            }

            default:
                SAY_ERROR( RES_ERR_UNSUPPORTED_COMPRESSION, entry -> name );
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif
                return( -1 );
                break;
        }
    }

#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif
    return( -1 );
}


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

   FUNCTION:   ResSizeFile

   PURPOSE:    Determine the size of a file

   PARAMETERS: File handle.

   RETURNS:    Size of the file in bytes.

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

RES_EXPORT int ResSizeFile( int file )
{
#if( RES_DEBUG_PARAMS )
    if( file < 0 || file >= MAX_FILE_HANDLES ) {
        SAY_ERROR( RES_ERR_INCORRECT_PARAMETER, "ResSizeFile" );
        return( -1 );
    }

    if( FILE_HANDLES[ file ].os_handle == -1 ) {
        SAY_ERROR( RES_ERR_ILLEGAL_FILE_HANDLE, "ResSizeFile" );
        return( -1 );
    }
#endif /* RES_DEBUG_PARAMS */

    return( FILE_HANDLES[ file ].size );
}


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

   FUNCTION:   ResReadFile

   PURPOSE:    Read from a file via the Resource Manager.

   PARAMETERS: File int, ptr to a buffer to place
               data, number of bytes to read.

   RETURNS:    Number of bytes actually read, -1 in case
               of an error.

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

RES_EXPORT int ResReadFile( int handle, void * buffer, size_t count )
{
    FILE_ENTRY * file;
    int len;
    int retval = 1;

#if( RES_DEBUG_PARAMS )
    if( !buffer || handle < 0 || handle > MAX_FILE_HANDLES ) {
        SAY_ERROR( RES_ERR_INCORRECT_PARAMETER, "ResReadFile" );
        return( -1 );
    }
#endif /* RES_DEBUG_PARAMS */
#if (RES_MULTITHREAD)
	REQUEST_LOCK(GLOCK); /* GFG */
#endif
    file = &FILE_HANDLES[ handle ];
    
    if( file -> os_handle == -1 ) {
        SAY_ERROR( RES_ERR_ILLEGAL_FILE_HANDLE, "ResReadFile" );
        return( -1 );  
    }

    IF_LOG( LOG( "read (%s): (%d bytes)\n", file -> filename, count ));

    SHOULD_I_CALL_WITH( CALLBACK_READ_FILE, handle, retval );

    if( file -> current_pos >= file -> size )
	{
#if (RES_MULTITHREAD)
		RELEASE_LOCK(GLOCK); /* GFG */
#endif
        return( 0 );  /* GFG NOV 18   was return (-1) */
	

	}
    if( !file -> zip ) {

⌨️ 快捷键说明

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