cabinet: Cleanup file loading and add infrastructure for plugging in real compression.
This commit is contained in:
parent
d9d4323137
commit
d651fbe4d1
|
@ -50,6 +50,7 @@ There is still some work to be done:
|
|||
#include "wine/list.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define fci_endian_ulong(x) RtlUlongByteSwap(x)
|
||||
|
@ -119,7 +120,7 @@ struct folder
|
|||
struct temp_file data;
|
||||
cab_ULONG data_start;
|
||||
cab_UWORD data_count;
|
||||
cab_UWORD compression;
|
||||
TCOMP compression;
|
||||
};
|
||||
|
||||
struct file
|
||||
|
@ -141,7 +142,7 @@ struct data_block
|
|||
cab_UWORD uncompressed;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
typedef struct FCI_Int
|
||||
{
|
||||
unsigned int magic;
|
||||
PERF perf;
|
||||
|
@ -185,6 +186,8 @@ typedef struct
|
|||
cab_ULONG files_size;
|
||||
cab_ULONG placed_files_size;
|
||||
cab_ULONG folders_data_size;
|
||||
TCOMP compression;
|
||||
cab_UWORD (*compress)(struct FCI_Int *);
|
||||
} FCI_Int;
|
||||
|
||||
#define FCI_INT_MAGIC 0xfcfcfc05
|
||||
|
@ -282,6 +285,7 @@ static struct file *add_file( FCI_Int *fci, const char *filename )
|
|||
file->attribs = 0;
|
||||
strcpy( file->name, filename );
|
||||
list_add_tail( &fci->files_list, &file->entry );
|
||||
fci->files_size += sizeof(CFFILE) + strlen(filename) + 1;
|
||||
return file;
|
||||
}
|
||||
|
||||
|
@ -305,21 +309,92 @@ static void free_file( FCI_Int *fci, struct file *file )
|
|||
fci->free( file );
|
||||
}
|
||||
|
||||
static struct data_block *add_data_block( FCI_Int *fci, cab_UWORD compressed, cab_UWORD uncompressed )
|
||||
/* create a new data block for the data in fci->data_in */
|
||||
static BOOL add_data_block( FCI_Int *fci, PFNFCISTATUS status_callback )
|
||||
{
|
||||
struct data_block *block = fci->alloc( sizeof(*block) );
|
||||
int err;
|
||||
struct data_block *block;
|
||||
|
||||
if (!block)
|
||||
if (!fci->cdata_in) return TRUE;
|
||||
|
||||
if (!(block = fci->alloc( sizeof(*block) )))
|
||||
{
|
||||
set_error( fci, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
|
||||
return NULL;
|
||||
return FALSE;
|
||||
}
|
||||
block->compressed = compressed;
|
||||
block->uncompressed = uncompressed;
|
||||
list_add_tail( &fci->blocks_list, &block->entry );
|
||||
fci->data.size += sizeof(CFDATA) + fci->ccab.cbReserveCFData + compressed;
|
||||
block->uncompressed = fci->cdata_in;
|
||||
block->compressed = fci->compress( fci );
|
||||
|
||||
if (fci->write( fci->data.handle, fci->data_out,
|
||||
block->compressed, &err, fci->pv ) != block->compressed)
|
||||
{
|
||||
set_error( fci, FCIERR_TEMP_FILE, err );
|
||||
fci->free( block );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fci->cdata_in = 0;
|
||||
fci->data.size += sizeof(CFDATA) + fci->ccab.cbReserveCFData + block->compressed;
|
||||
fci->cCompressedBytesInFolder += block->compressed;
|
||||
fci->cDataBlocks++;
|
||||
return block;
|
||||
list_add_tail( &fci->blocks_list, &block->entry );
|
||||
|
||||
if (status_callback( statusFile, block->compressed, block->uncompressed, fci->pv ) == -1)
|
||||
{
|
||||
set_error( fci, FCIERR_USER_ABORT, 0 );
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* add compressed blocks for all the data that can be read from the file */
|
||||
static BOOL add_file_data( FCI_Int *fci, char *sourcefile, char *filename, BOOL execute,
|
||||
PFNFCIGETOPENINFO get_open_info, PFNFCISTATUS status_callback )
|
||||
{
|
||||
int err, len;
|
||||
INT_PTR handle;
|
||||
struct file *file;
|
||||
|
||||
/* make sure we have buffers */
|
||||
if (!fci->data_in && !(fci->data_in = fci->alloc( CB_MAX_CHUNK )))
|
||||
{
|
||||
set_error( fci, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
|
||||
return FALSE;
|
||||
}
|
||||
if (!fci->data_out && !(fci->data_out = fci->alloc( 2 * CB_MAX_CHUNK )))
|
||||
{
|
||||
set_error( fci, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(file = add_file( fci, filename ))) return FALSE;
|
||||
|
||||
handle = get_open_info( sourcefile, &file->date, &file->time, &file->attribs, &err, fci->pv );
|
||||
if (handle == -1)
|
||||
{
|
||||
free_file( fci, file );
|
||||
set_error( fci, FCIERR_OPEN_SRC, err );
|
||||
return FALSE;
|
||||
}
|
||||
if (execute) file->attribs |= _A_EXEC;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
len = fci->read( handle, fci->data_in + fci->cdata_in,
|
||||
CAB_BLOCKMAX - fci->cdata_in, &err, fci->pv );
|
||||
if (!len) break;
|
||||
|
||||
if (len == -1)
|
||||
{
|
||||
set_error( fci, FCIERR_READ_SRC, err );
|
||||
return FALSE;
|
||||
}
|
||||
file->size += len;
|
||||
fci->cdata_in += len;
|
||||
if (fci->cdata_in == CAB_BLOCKMAX && !add_data_block( fci, status_callback )) return FALSE;
|
||||
}
|
||||
fci->close( handle, &err, fci->pv );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void free_data_block( FCI_Int *fci, struct data_block *block )
|
||||
|
@ -340,7 +415,7 @@ static struct folder *add_folder( FCI_Int *fci )
|
|||
folder->data.handle = -1;
|
||||
folder->data_start = fci->folders_data_size;
|
||||
folder->data_count = 0;
|
||||
folder->compression = tcompTYPE_NONE; /* FIXME */
|
||||
folder->compression = fci->compression;
|
||||
list_init( &folder->files_list );
|
||||
list_init( &folder->blocks_list );
|
||||
list_add_tail( &fci->folders_list, &folder->entry );
|
||||
|
@ -861,6 +936,13 @@ static BOOL add_files_to_folder( FCI_Int *fci, struct folder *folder, cab_ULONG
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static cab_UWORD compress_NONE( FCI_Int *fci )
|
||||
{
|
||||
memcpy( fci->data_out, fci->data_in, fci->cdata_in );
|
||||
return fci->cdata_in;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* FCICreate (CABINET.10)
|
||||
*
|
||||
|
@ -981,6 +1063,8 @@ HFCI __cdecl FCICreate(
|
|||
p_fci_internal->files_size = 0;
|
||||
p_fci_internal->placed_files_size = 0;
|
||||
p_fci_internal->folders_data_size = 0;
|
||||
p_fci_internal->compression = tcompTYPE_NONE;
|
||||
p_fci_internal->compress = compress_NONE;
|
||||
|
||||
list_init( &p_fci_internal->folders_list );
|
||||
list_init( &p_fci_internal->files_list );
|
||||
|
@ -996,48 +1080,6 @@ HFCI __cdecl FCICreate(
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
static BOOL fci_flush_data_block (FCI_Int *p_fci_internal, int* err,
|
||||
PFNFCISTATUS pfnfcis) {
|
||||
|
||||
/* attention no checks if there is data available!!! */
|
||||
struct data_block *block;
|
||||
|
||||
/* TODO compress the data of p_fci_internal->data_in */
|
||||
/* and write it to p_fci_internal->data_out */
|
||||
memcpy(p_fci_internal->data_out, p_fci_internal->data_in,
|
||||
p_fci_internal->cdata_in /* number of bytes to copy */);
|
||||
|
||||
if (!(block = add_data_block( p_fci_internal, p_fci_internal->cdata_in, p_fci_internal->cdata_in )))
|
||||
return FALSE;
|
||||
|
||||
/* write p_fci_internal->data_out to p_fci_internal->data.handle */
|
||||
if( p_fci_internal->write( p_fci_internal->data.handle, /* file handle */
|
||||
p_fci_internal->data_out, /* memory buffer */
|
||||
block->compressed, /* number of bytes to copy */
|
||||
err, p_fci_internal->pv) != block->compressed) {
|
||||
set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
|
||||
return FALSE;
|
||||
}
|
||||
/* TODO error handling of err */
|
||||
|
||||
/* reset the offset */
|
||||
p_fci_internal->cdata_in = 0;
|
||||
p_fci_internal->cCompressedBytesInFolder += block->compressed;
|
||||
|
||||
/* report status with pfnfcis about uncompressed and compressed file data */
|
||||
if( (*pfnfcis)(statusFile, block->compressed, block->uncompressed,
|
||||
p_fci_internal->pv) == -1) {
|
||||
set_error( p_fci_internal, FCIERR_USER_ABORT, 0 );
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
} /* end of fci_flush_data_block */
|
||||
|
||||
|
||||
|
||||
|
||||
static BOOL fci_flush_folder( FCI_Int *p_fci_internal,
|
||||
BOOL fGetNextCab,
|
||||
PFNFCIGETNEXTCABINET pfnfcignc,
|
||||
|
@ -1087,12 +1129,8 @@ static BOOL fci_flush_folder( FCI_Int *p_fci_internal,
|
|||
p_fci_internal->fSplitFolder=FALSE;
|
||||
|
||||
/* START of COPY */
|
||||
/* if there is data in p_fci_internal->data_in */
|
||||
if (p_fci_internal->cdata_in!=0) {
|
||||
if (!add_data_block( p_fci_internal, pfnfcis )) return FALSE;
|
||||
|
||||
if( !fci_flush_data_block(p_fci_internal, &err, pfnfcis) ) return FALSE;
|
||||
|
||||
}
|
||||
/* reset to get the number of data blocks of this folder which are */
|
||||
/* actually in this cabinet ( at least partially ) */
|
||||
p_fci_internal->cDataBlocks=0;
|
||||
|
@ -1395,10 +1433,7 @@ BOOL __cdecl FCIAddFile(
|
|||
PFNFCIGETOPENINFO pfnfcigoi,
|
||||
TCOMP typeCompress)
|
||||
{
|
||||
int err;
|
||||
cab_ULONG read_result;
|
||||
int file_handle;
|
||||
struct file *file;
|
||||
FCI_Int *p_fci_internal = get_fci_ptr( hfci );
|
||||
|
||||
if (!p_fci_internal) return FALSE;
|
||||
|
@ -1409,6 +1444,21 @@ BOOL __cdecl FCIAddFile(
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (typeCompress != p_fci_internal->compression)
|
||||
{
|
||||
if (!FCIFlushFolder( hfci, pfnfcignc, pfnfcis )) return FALSE;
|
||||
switch (typeCompress)
|
||||
{
|
||||
default:
|
||||
FIXME( "compression %x not supported, defaulting to none\n", typeCompress );
|
||||
/* fall through */
|
||||
case tcompTYPE_NONE:
|
||||
p_fci_internal->compression = tcompTYPE_NONE;
|
||||
p_fci_internal->compress = compress_NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO check if pszSourceFile??? */
|
||||
|
||||
if(p_fci_internal->fGetNextCabInVain && p_fci_internal->fNextCab) {
|
||||
|
@ -1423,51 +1473,6 @@ BOOL __cdecl FCIAddFile(
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(file = add_file( p_fci_internal, pszFileName ))) return FALSE;
|
||||
|
||||
/* allocation of memory */
|
||||
if (p_fci_internal->data_in==NULL) {
|
||||
if (p_fci_internal->cdata_in!=0) {
|
||||
/* error handling */
|
||||
set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
|
||||
return FALSE;
|
||||
}
|
||||
if (p_fci_internal->data_out!=NULL) {
|
||||
/* error handling */
|
||||
set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
|
||||
return FALSE;
|
||||
}
|
||||
if(!(p_fci_internal->data_in = p_fci_internal->alloc(CB_MAX_CHUNK))) {
|
||||
set_error( p_fci_internal, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
|
||||
return FALSE;
|
||||
}
|
||||
if (p_fci_internal->data_out==NULL) {
|
||||
if(!(p_fci_internal->data_out = p_fci_internal->alloc( 2 * CB_MAX_CHUNK))){
|
||||
set_error( p_fci_internal, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_fci_internal->data_out==NULL) {
|
||||
p_fci_internal->free(p_fci_internal->data_in);
|
||||
/* error handling */
|
||||
set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* get information about the file */
|
||||
/* set defaults in case callback doesn't set one or more fields */
|
||||
file_handle = pfnfcigoi( pszSourceFile, &file->date, &file->time, &file->attribs,
|
||||
&err, p_fci_internal->pv );
|
||||
/* check file_handle */
|
||||
if(file_handle==0){
|
||||
set_error( p_fci_internal, FCIERR_OPEN_SRC, ERROR_OPEN_FAILED );
|
||||
}
|
||||
/* TODO error handling of err */
|
||||
|
||||
if (fExecute) { file->attribs |= _A_EXEC; }
|
||||
|
||||
/* REUSE the variable read_result */
|
||||
read_result=get_header_size( p_fci_internal ) + p_fci_internal->ccab.cbReserveCFFolder;
|
||||
|
||||
|
@ -1531,45 +1536,8 @@ BOOL __cdecl FCIAddFile(
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* read the contents of the file blockwise */
|
||||
while (!FALSE) {
|
||||
if (p_fci_internal->cdata_in > CAB_BLOCKMAX) {
|
||||
/* internal error */
|
||||
set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
|
||||
if (!add_file_data( p_fci_internal, pszSourceFile, pszFileName, fExecute, pfnfcigoi, pfnfcis ))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
read_result = p_fci_internal->read( file_handle /* file handle */,
|
||||
(p_fci_internal->data_in + p_fci_internal->cdata_in) /* memory buffer */,
|
||||
(CAB_BLOCKMAX - p_fci_internal->cdata_in) /* number of bytes to copy */,
|
||||
&err, p_fci_internal->pv);
|
||||
/* TODO error handling of err */
|
||||
|
||||
if( read_result==0 ) break;
|
||||
|
||||
/* increment the block size */
|
||||
p_fci_internal->cdata_in += read_result;
|
||||
|
||||
/* increment the file size */
|
||||
file->size += read_result;
|
||||
|
||||
if ( p_fci_internal->cdata_in > CAB_BLOCKMAX ) {
|
||||
/* report internal error */
|
||||
set_error( p_fci_internal, FCIERR_NONE, ERROR_GEN_FAILURE );
|
||||
return FALSE;
|
||||
}
|
||||
/* write a whole block */
|
||||
if ( p_fci_internal->cdata_in == CAB_BLOCKMAX ) {
|
||||
|
||||
if( !fci_flush_data_block(p_fci_internal, &err, pfnfcis) ) return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* close the file from FCIAddFile */
|
||||
p_fci_internal->close(file_handle,&err,p_fci_internal->pv);
|
||||
/* TODO error handling of err */
|
||||
|
||||
p_fci_internal->files_size += sizeof(CFFILE) + strlen(pszFileName)+1;
|
||||
|
||||
/* REUSE the variable read_result */
|
||||
read_result = get_header_size( p_fci_internal ) + p_fci_internal->ccab.cbReserveCFFolder;
|
||||
|
|
Loading…
Reference in New Issue