cabinet: Store folders in a list in memory instead of in a temp file.

This commit is contained in:
Alexandre Julliard 2011-02-14 20:05:46 +01:00
parent c24cd869cd
commit f6ebe3b8b2
1 changed files with 114 additions and 253 deletions

View File

@ -45,6 +45,7 @@ There is still some work to be done:
#include "winternl.h" #include "winternl.h"
#include "fci.h" #include "fci.h"
#include "cabinet.h" #include "cabinet.h"
#include "wine/list.h"
#include "wine/debug.h" #include "wine/debug.h"
@ -101,6 +102,13 @@ typedef struct {
/* compressed data */ /* compressed data */
} CFDATA; } CFDATA;
struct folder
{
struct list entry;
cab_ULONG data_start;
cab_UWORD data_count;
cab_UWORD compression;
};
typedef struct typedef struct
{ {
@ -144,15 +152,14 @@ typedef struct
int handleCFDATA2; int handleCFDATA2;
char szFileNameCFFILE2[CB_MAX_FILENAME]; char szFileNameCFFILE2[CB_MAX_FILENAME];
int handleCFFILE2; int handleCFFILE2;
char szFileNameCFFOLDER[CB_MAX_FILENAME];
int handleCFFOLDER;
cab_ULONG sizeFileCFDATA1; cab_ULONG sizeFileCFDATA1;
cab_ULONG sizeFileCFFILE1; cab_ULONG sizeFileCFFILE1;
cab_ULONG sizeFileCFDATA2; cab_ULONG sizeFileCFDATA2;
cab_ULONG sizeFileCFFILE2; cab_ULONG sizeFileCFFILE2;
cab_ULONG sizeFileCFFOLDER;
BOOL fNewPrevious; BOOL fNewPrevious;
cab_ULONG estimatedCabinetSize; cab_ULONG estimatedCabinetSize;
struct list folders_list;
cab_ULONG folders_size;
} FCI_Int; } FCI_Int;
#define FCI_INT_MAGIC 0xfcfcfc05 #define FCI_INT_MAGIC 0xfcfcfc05
@ -177,6 +184,64 @@ static FCI_Int *get_fci_ptr( HFCI hfci )
return fci; return fci;
} }
static cab_ULONG get_folder_size( FCI_Int *fci )
{
if (fci->fNextCab || fci->fGetNextCabInVain)
return sizeof(CFFOLDER) + fci->oldCCAB.cbReserveCFFolder;
else
return sizeof(CFFOLDER) + fci->pccab->cbReserveCFFolder;
}
static struct folder *add_folder( FCI_Int *fci )
{
struct folder *folder = fci->alloc( sizeof(*folder) );
if (!folder)
{
set_error( fci, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
return NULL;
}
folder->data_start = fci->sizeFileCFDATA2;
folder->compression = tcompTYPE_NONE; /* FIXME */
list_add_tail( &fci->folders_list, &folder->entry );
fci->folders_size += get_folder_size( fci );
fci->cFolders++;
return folder;
}
/* write all folders to disk and remove them from the list */
static BOOL write_folders( FCI_Int *fci, INT_PTR handle, cab_ULONG header_size )
{
struct folder *folder, *next;
int err;
BOOL ret = TRUE;
CFFOLDER *cffolder;
cab_ULONG folder_size = get_folder_size( fci );
if (!(cffolder = fci->alloc( folder_size )))
{
set_error( fci, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
memset( cffolder, 0, folder_size );
LIST_FOR_EACH_ENTRY_SAFE( folder, next, &fci->folders_list, struct folder, entry )
{
cffolder->coffCabStart = fci_endian_ulong( folder->data_start + header_size );
cffolder->cCFData = fci_endian_uword( folder->data_count );
cffolder->typeCompress = fci_endian_uword( folder->compression );
if (fci->write( handle, cffolder, folder_size, &err, fci->pv ) != folder_size)
{
set_error( fci, FCIERR_CAB_FILE, err );
ret = FALSE;
break;
}
list_remove( &folder->entry );
}
fci->free( cffolder );
return ret;
}
/*********************************************************************** /***********************************************************************
* FCICreate (CABINET.10) * FCICreate (CABINET.10)
* *
@ -293,11 +358,12 @@ HFCI __cdecl FCICreate(
p_fci_internal->sizeFileCFFILE1 = 0; p_fci_internal->sizeFileCFFILE1 = 0;
p_fci_internal->sizeFileCFDATA2 = 0; p_fci_internal->sizeFileCFDATA2 = 0;
p_fci_internal->sizeFileCFFILE2 = 0; p_fci_internal->sizeFileCFFILE2 = 0;
p_fci_internal->sizeFileCFFOLDER = 0;
p_fci_internal->sizeFileCFFOLDER = 0;
p_fci_internal->fNewPrevious = FALSE; p_fci_internal->fNewPrevious = FALSE;
p_fci_internal->estimatedCabinetSize = 0; p_fci_internal->estimatedCabinetSize = 0;
p_fci_internal->statusFolderTotal = 0; p_fci_internal->statusFolderTotal = 0;
p_fci_internal->folders_size = 0;
list_init( &p_fci_internal->folders_list );
memset(&p_fci_internal->oldCCAB, 0, sizeof(CCAB)); memset(&p_fci_internal->oldCCAB, 0, sizeof(CCAB));
memcpy(p_fci_internal->szPrevCab, pccab->szCab, CB_MAX_CABINET_NAME); memcpy(p_fci_internal->szPrevCab, pccab->szCab, CB_MAX_CABINET_NAME);
@ -384,27 +450,7 @@ HFCI __cdecl FCICreate(
} }
/* TODO error checking of err */ /* TODO error checking of err */
/* array of all CFFILE in a folder, ready to be copied into cabinet */
if( !p_fci_internal->gettemp(p_fci_internal->szFileNameCFFOLDER,
CB_MAX_FILENAME, p_fci_internal->pv)) {
set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
return FALSE;
}
/* safety */
if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {
set_error( p_fci_internal, FCIERR_NONE, ERROR_INVALID_DATA );
return FALSE;
}
p_fci_internal->handleCFFOLDER = p_fci_internal->open( p_fci_internal->szFileNameCFFOLDER,
_O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY,
_S_IREAD | _S_IWRITE, &err, pv);
if(p_fci_internal->handleCFFOLDER==0) {
set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_OPEN_FAILED );
return FALSE;
}
/* TODO close and delete new files when return FALSE */ /* TODO close and delete new files when return FALSE */
/* TODO error checking of err */
return (HFCI)p_fci_internal; return (HFCI)p_fci_internal;
} }
@ -579,7 +625,7 @@ static BOOL fci_flushfolder_copy_cfdata(FCI_Int *p_fci_internal, char* buffer, U
if( p_fci_internal->fNextCab && if( p_fci_internal->fNextCab &&
(p_fci_internal->oldCCAB.cb <= sizeof(CFDATA) + cbReserveCFData + (p_fci_internal->oldCCAB.cb <= sizeof(CFDATA) + cbReserveCFData +
p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 + p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER + p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size +
sizeof(CFHEADER) + sizeof(CFHEADER) +
read_result + read_result +
p_fci_internal->oldCCAB.cbReserveCFHeader + p_fci_internal->oldCCAB.cbReserveCFHeader +
@ -642,7 +688,7 @@ static BOOL fci_flushfolder_copy_cfdata(FCI_Int *p_fci_internal, char* buffer, U
(p_fci_internal->oldCCAB.cb < sizeof(CFDATA) + cbReserveCFData + (p_fci_internal->oldCCAB.cb < sizeof(CFDATA) + cbReserveCFData +
pcfdata->cbData + pcfdata->cbData +
p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 + p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER + p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size +
sizeof(CFHEADER) + sizeof(CFHEADER) +
read_result + read_result +
p_fci_internal->oldCCAB.cbReserveCFHeader + p_fci_internal->oldCCAB.cbReserveCFHeader +
@ -664,7 +710,7 @@ static BOOL fci_flushfolder_copy_cfdata(FCI_Int *p_fci_internal, char* buffer, U
pcfdata->cbData = p_fci_internal->oldCCAB.cb - ( pcfdata->cbData = p_fci_internal->oldCCAB.cb - (
sizeof(CFDATA) + cbReserveCFData + sizeof(CFDATA) + cbReserveCFData +
p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 + p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER + p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size +
sizeof(CFHEADER) + sizeof(CFHEADER) +
p_fci_internal->oldCCAB.cbReserveCFHeader + p_fci_internal->oldCCAB.cbReserveCFHeader +
sizeof(CFFOLDER) + /* set size of new CFFolder entry */ sizeof(CFFOLDER) + /* set size of new CFFolder entry */
@ -885,68 +931,6 @@ static BOOL fci_flushfolder_copy_cfdata(FCI_Int *p_fci_internal, char* buffer, U
static BOOL fci_flushfolder_copy_cffolder(FCI_Int *p_fci_internal, int* err, UINT cbReserveCFFolder,
cab_ULONG sizeFileCFDATA2old)
{
CFFOLDER cffolder;
UINT i;
char* reserved;
/* absolute offset cannot be set yet, because the size of cabinet header, */
/* the number of CFFOLDERs and the number of CFFILEs may change. */
/* Instead the size of all previous data blocks will be stored and */
/* the remainder of the offset will be added when the cabinet will be */
/* flushed to disk. */
/* This is exactly the way the original CABINET.DLL works!!! */
cffolder.coffCabStart=sizeFileCFDATA2old;
/* set the number of this folder's CFDATA sections */
cffolder.cCFData=p_fci_internal->cDataBlocks;
/* TODO set compression type */
cffolder.typeCompress = tcompTYPE_NONE;
/* write cffolder to p_fci_internal->handleCFFOLDER */
if( p_fci_internal->write( p_fci_internal->handleCFFOLDER, /* file handle */
&cffolder, /* memory buffer */
sizeof(cffolder), /* number of bytes to copy */
err, p_fci_internal->pv) != sizeof(cffolder) ) {
set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
return FALSE;
}
/* TODO error handling of err */
p_fci_internal->sizeFileCFFOLDER += sizeof(cffolder);
/* add optional reserved area */
if (cbReserveCFFolder!=0) {
if(!(reserved = p_fci_internal->alloc( cbReserveCFFolder))) {
set_error( p_fci_internal, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
for(i=0;i<cbReserveCFFolder;) {
reserved[i++]='\0';
}
if( p_fci_internal->write( p_fci_internal->handleCFFOLDER, /* file handle */
reserved, /* memory buffer */
cbReserveCFFolder, /* number of bytes to copy */
err, p_fci_internal->pv) != cbReserveCFFolder ) {
p_fci_internal->free(reserved);
set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_WRITE_FAULT );
return FALSE;
}
/* TODO error handling of err */
p_fci_internal->sizeFileCFFOLDER += cbReserveCFFolder;
p_fci_internal->free(reserved);
}
return TRUE;
} /* end of fci_flushfolder_copy_cffolder */
static BOOL fci_flushfolder_copy_cffile(FCI_Int *p_fci_internal, int* err, int handleCFFILE1new, static BOOL fci_flushfolder_copy_cffile(FCI_Int *p_fci_internal, int* err, int handleCFFILE1new,
cab_ULONG *psizeFileCFFILE1new, cab_ULONG payload) cab_ULONG *psizeFileCFFILE1new, cab_ULONG payload)
{ {
@ -1195,9 +1179,9 @@ static BOOL fci_flush_folder( FCI_Int *p_fci_internal,
char* reserved; char* reserved;
cab_ULONG sizeFileCFDATA1new=0; cab_ULONG sizeFileCFDATA1new=0;
cab_ULONG sizeFileCFFILE1new=0; cab_ULONG sizeFileCFFILE1new=0;
cab_ULONG sizeFileCFDATA2old;
cab_ULONG payload; cab_ULONG payload;
cab_ULONG read_result; cab_ULONG read_result;
struct folder *folder;
if ((!pfnfcignc) || (!pfnfcis)) { if ((!pfnfcignc) || (!pfnfcis)) {
set_error( p_fci_internal, FCIERR_NONE, ERROR_BAD_ARGUMENTS ); set_error( p_fci_internal, FCIERR_NONE, ERROR_BAD_ARGUMENTS );
@ -1288,7 +1272,7 @@ static BOOL fci_flush_folder( FCI_Int *p_fci_internal,
p_fci_internal->statusFolderTotal = sizeof(CFHEADER)+read_result+ p_fci_internal->statusFolderTotal = sizeof(CFHEADER)+read_result+
sizeof(CFFOLDER) + p_fci_internal->sizeFileCFFILE2+ sizeof(CFFOLDER) + p_fci_internal->sizeFileCFFILE2+
p_fci_internal->sizeFileCFDATA2 + p_fci_internal->sizeFileCFFILE1+ p_fci_internal->sizeFileCFDATA2 + p_fci_internal->sizeFileCFFILE1+
p_fci_internal->sizeFileCFDATA1 + p_fci_internal->sizeFileCFFOLDER; p_fci_internal->sizeFileCFDATA1 + p_fci_internal->folders_size;
p_fci_internal->statusFolderCopied = 0; p_fci_internal->statusFolderCopied = 0;
/* report status with pfnfcis about copied size of folder */ /* report status with pfnfcis about copied size of folder */
@ -1363,7 +1347,7 @@ static BOOL fci_flush_folder( FCI_Int *p_fci_internal,
strlen(p_fci_internal->szPrevDisk)+1; strlen(p_fci_internal->szPrevDisk)+1;
} }
read_result+= sizeof(CFHEADER) + p_fci_internal->sizeFileCFDATA2 + read_result+= sizeof(CFHEADER) + p_fci_internal->sizeFileCFDATA2 +
p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER; p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size;
if(p_fci_internal->sizeFileCFFILE1!=0) { if(p_fci_internal->sizeFileCFFILE1!=0) {
read_result+= sizeof(CFFOLDER)+p_fci_internal->pccab->cbReserveCFFolder; read_result+= sizeof(CFFOLDER)+p_fci_internal->pccab->cbReserveCFFolder;
@ -1475,8 +1459,7 @@ static BOOL fci_flush_folder( FCI_Int *p_fci_internal,
} }
/* TODO error handling of err */ /* TODO error handling of err */
/* save size of file CFDATA2 - required for the folder's offset to data */ if (!(folder = add_folder( p_fci_internal ))) return FALSE;
sizeFileCFDATA2old = p_fci_internal->sizeFileCFDATA2;
if(!(reserved = p_fci_internal->alloc( cbReserveCFData+sizeof(CFDATA)))) { if(!(reserved = p_fci_internal->alloc( cbReserveCFData+sizeof(CFDATA)))) {
set_error( p_fci_internal, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY ); set_error( p_fci_internal, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
@ -1502,16 +1485,7 @@ static BOOL fci_flush_folder( FCI_Int *p_fci_internal,
p_fci_internal->free(reserved); p_fci_internal->free(reserved);
if(!fci_flushfolder_copy_cffolder(p_fci_internal, &err, cbReserveCFFolder, folder->data_count = p_fci_internal->cDataBlocks;
sizeFileCFDATA2old )) {
p_fci_internal->close(handleCFDATA1new,&err,p_fci_internal->pv);
/* TODO error handling of err */
p_fci_internal->delete(szFileNameCFDATA1new,&err,p_fci_internal->pv);
/* TODO error handling of err */
p_fci_internal->close(handleCFFILE1new,&err,p_fci_internal->pv);
/* TODO error handling of err */
return FALSE;
}
if(!fci_flushfolder_copy_cffile(p_fci_internal, &err, handleCFFILE1new, if(!fci_flushfolder_copy_cffile(p_fci_internal, &err, handleCFFILE1new,
&sizeFileCFFILE1new, payload)) { &sizeFileCFFILE1new, payload)) {
@ -1556,8 +1530,6 @@ static BOOL fci_flush_folder( FCI_Int *p_fci_internal,
/* set file size */ /* set file size */
p_fci_internal->sizeFileCFFILE1 = sizeFileCFFILE1new; p_fci_internal->sizeFileCFFILE1 = sizeFileCFFILE1new;
++(p_fci_internal->cFolders);
/* reset CFFolder specific information */ /* reset CFFolder specific information */
p_fci_internal->cDataBlocks=0; p_fci_internal->cDataBlocks=0;
p_fci_internal->cCompressedBytesInFolder=0; p_fci_internal->cCompressedBytesInFolder=0;
@ -1580,7 +1552,7 @@ static BOOL fci_flush_cabinet( FCI_Int *p_fci_internal,
cab_UBYTE cbCFFolder; cab_UBYTE cbCFFolder;
cab_UBYTE cbCFData; cab_UBYTE cbCFData;
} cfreserved; } cfreserved;
CFFOLDER cffolder; cab_ULONG header_size;
cab_ULONG read_result=0; cab_ULONG read_result=0;
int handleCABINET; /* file handle for cabinet */ int handleCABINET; /* file handle for cabinet */
char szFileNameCABINET[CB_MAX_CAB_PATH+CB_MAX_CABINET_NAME];/* name buffer */ char szFileNameCABINET[CB_MAX_CAB_PATH+CB_MAX_CABINET_NAME];/* name buffer */
@ -1603,7 +1575,7 @@ static BOOL fci_flush_cabinet( FCI_Int *p_fci_internal,
if(returntrue) return TRUE; if(returntrue) return TRUE;
if ( (p_fci_internal->fSplitFolder && p_fci_internal->fNextCab==FALSE)|| if ( (p_fci_internal->fSplitFolder && p_fci_internal->fNextCab==FALSE)||
(p_fci_internal->sizeFileCFFOLDER==0 && (p_fci_internal->folders_size==0 &&
(p_fci_internal->sizeFileCFFILE1!=0 || (p_fci_internal->sizeFileCFFILE1!=0 ||
p_fci_internal->sizeFileCFFILE2!=0 ) p_fci_internal->sizeFileCFFILE2!=0 )
) ) ) )
@ -1650,7 +1622,7 @@ static BOOL fci_flush_cabinet( FCI_Int *p_fci_internal,
cfheader.reserved1=0; cfheader.reserved1=0;
cfheader.cbCabinet= /* size of the cabinet file in bytes */ cfheader.cbCabinet= /* size of the cabinet file in bytes */
sizeof(CFHEADER) + sizeof(CFHEADER) +
p_fci_internal->sizeFileCFFOLDER + p_fci_internal->folders_size +
p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFILE2 +
p_fci_internal->sizeFileCFDATA2; p_fci_internal->sizeFileCFDATA2;
@ -1875,127 +1847,41 @@ static BOOL fci_flush_cabinet( FCI_Int *p_fci_internal,
/* TODO error handling of err */ /* TODO error handling of err */
} }
/* set seek of p_fci_internal->handleCFFOLDER to 0 */ /* add size of header size of all CFFOLDERs and size of all CFFILEs */
if( p_fci_internal->seek(p_fci_internal->handleCFFOLDER, header_size = p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size + sizeof(CFHEADER);
0, SEEK_SET, &err, p_fci_internal->pv) != 0 ) { if( p_fci_internal->fNextCab || p_fci_internal->fGetNextCabInVain ) {
/* wrong return value */ header_size+=p_fci_internal->oldCCAB.cbReserveCFHeader;
set_error( p_fci_internal, FCIERR_NONE, ERROR_SEEK ); } else {
return FALSE; header_size+=p_fci_internal->pccab->cbReserveCFHeader;
} }
/* TODO error handling of err */
/* while not all CFFOLDER structures have been copied into the cabinet do */ if (p_fci_internal->fPrevCab) {
while(!FALSE) { header_size += strlen(p_fci_internal->szPrevCab)+1 +
/* use the variable read_result */
/* read cffolder of p_fci_internal->handleCFFOLDER */
read_result = p_fci_internal->read( p_fci_internal->handleCFFOLDER, /* handle */
&cffolder, /* memory buffer */
sizeof(cffolder), /* number of bytes to copy */
&err, p_fci_internal->pv);
if( read_result != sizeof(cffolder) ) {
if( read_result == 0 ) break;/*ALL CFFOLDER structures have been copied*/
/* read error */
set_error( p_fci_internal, FCIERR_NONE, ERROR_READ_FAULT );
return FALSE;
}
/* TODO error handling of err */
/* add size of header size of all CFFOLDERs and size of all CFFILEs */
cffolder.coffCabStart +=
p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
sizeof(CFHEADER);
if( p_fci_internal->fNextCab ||
p_fci_internal->fGetNextCabInVain ) {
cffolder.coffCabStart+=p_fci_internal->oldCCAB.cbReserveCFHeader;
} else {
cffolder.coffCabStart+=p_fci_internal->pccab->cbReserveCFHeader;
}
if (p_fci_internal->fPrevCab) {
cffolder.coffCabStart += strlen(p_fci_internal->szPrevCab)+1 +
strlen(p_fci_internal->szPrevDisk)+1; strlen(p_fci_internal->szPrevDisk)+1;
} }
if (p_fci_internal->fNextCab) { if (p_fci_internal->fNextCab) {
cffolder.coffCabStart += strlen(p_fci_internal->oldCCAB.szCab)+1 + header_size += strlen(p_fci_internal->oldCCAB.szCab)+1 +
strlen(p_fci_internal->oldCCAB.szDisk)+1; strlen(p_fci_internal->oldCCAB.szDisk)+1;
} }
if( p_fci_internal->fNextCab || if( p_fci_internal->fNextCab || p_fci_internal->fGetNextCabInVain ) {
p_fci_internal->fGetNextCabInVain ) { header_size += p_fci_internal->oldCCAB.cbReserveCFHeader;
cffolder.coffCabStart += p_fci_internal->oldCCAB.cbReserveCFHeader;
if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 || if( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
p_fci_internal->oldCCAB.cbReserveCFFolder != 0 || p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
p_fci_internal->oldCCAB.cbReserveCFData != 0 ) { p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
cffolder.coffCabStart += 4; header_size += 4;
} }
} else { } else {
cffolder.coffCabStart += p_fci_internal->pccab->cbReserveCFHeader; header_size += p_fci_internal->pccab->cbReserveCFHeader;
if( p_fci_internal->pccab->cbReserveCFHeader != 0 || if( p_fci_internal->pccab->cbReserveCFHeader != 0 ||
p_fci_internal->pccab->cbReserveCFFolder != 0 || p_fci_internal->pccab->cbReserveCFFolder != 0 ||
p_fci_internal->pccab->cbReserveCFData != 0 ) { p_fci_internal->pccab->cbReserveCFData != 0 ) {
cffolder.coffCabStart += 4; header_size += 4;
} }
} }
/* set little endian */ if (!write_folders( p_fci_internal, handleCABINET, header_size )) return FALSE;
cffolder.coffCabStart=fci_endian_ulong(cffolder.coffCabStart);
cffolder.cCFData=fci_endian_uword(cffolder.cCFData);
cffolder.typeCompress=fci_endian_uword(cffolder.typeCompress);
/* write cffolder to cabinet file */
if( p_fci_internal->write( handleCABINET, /* file handle */
&cffolder, /* memory buffer */
sizeof(cffolder), /* number of bytes to copy */
&err, p_fci_internal->pv) != sizeof(cffolder) ) {
/* write error */
set_error( p_fci_internal, FCIERR_CAB_FILE, ERROR_WRITE_FAULT );
return FALSE;
}
/* TODO error handling of err */
/* reset little endian */
cffolder.coffCabStart=fci_endian_ulong(cffolder.coffCabStart);
cffolder.cCFData=fci_endian_uword(cffolder.cCFData);
cffolder.typeCompress=fci_endian_uword(cffolder.typeCompress);
/* add optional reserved area */
/* This allocation and freeing at each CFFolder block is a bit */
/* inefficient, but it's harder to forget about freeing the buffer :-). */
/* Reserved areas are used seldom besides that... */
if (cbReserveCFFolder!=0) {
if(!(reserved = p_fci_internal->alloc( cbReserveCFFolder))) {
set_error( p_fci_internal, FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
if( p_fci_internal->read( p_fci_internal->handleCFFOLDER, /* file handle */
reserved, /* memory buffer */
cbReserveCFFolder, /* number of bytes to copy */
&err, p_fci_internal->pv) != cbReserveCFFolder ) {
p_fci_internal->free(reserved);
/* read error */
set_error( p_fci_internal, FCIERR_NONE, ERROR_READ_FAULT );
return FALSE;
}
/* TODO error handling of err */
if( p_fci_internal->write( handleCABINET, /* file handle */
reserved, /* memory buffer */
cbReserveCFFolder, /* number of bytes to copy */
&err, p_fci_internal->pv) != cbReserveCFFolder ) {
p_fci_internal->free(reserved);
/* write error */
set_error( p_fci_internal, FCIERR_CAB_FILE, ERROR_WRITE_FAULT );
return FALSE;
}
/* TODO error handling of err */
p_fci_internal->free(reserved);
}
} /* END OF while */
/* set seek of p_fci_internal->handleCFFILE2 to 0 */ /* set seek of p_fci_internal->handleCFFILE2 to 0 */
if( p_fci_internal->seek(p_fci_internal->handleCFFILE2, if( p_fci_internal->seek(p_fci_internal->handleCFFILE2,
@ -2135,21 +2021,16 @@ static BOOL fci_flush_cabinet( FCI_Int *p_fci_internal,
p_fci_internal->delete( p_fci_internal->szFileNameCFFILE2, &err, p_fci_internal->delete( p_fci_internal->szFileNameCFFILE2, &err,
p_fci_internal->pv); p_fci_internal->pv);
/* TODO error handling of err */ /* TODO error handling of err */
p_fci_internal->close( p_fci_internal->handleCFFOLDER,&err,p_fci_internal->pv);
/* TODO error handling of err */
p_fci_internal->delete( p_fci_internal->szFileNameCFFOLDER, &err,
p_fci_internal->pv);
/* TODO error handling of err */
/* END OF copied from FCIDestroy */ /* END OF copied from FCIDestroy */
/* get 3 temporary files and open them */ /* get 3 temporary files and open them */
/* write names and handles to hfci */ /* write names and handles to hfci */
p_fci_internal->folders_size = 0;
p_fci_internal->sizeFileCFDATA2 = 0; p_fci_internal->sizeFileCFDATA2 = 0;
p_fci_internal->sizeFileCFFILE2 = 0; p_fci_internal->sizeFileCFFILE2 = 0;
p_fci_internal->sizeFileCFFOLDER = 0; p_fci_internal->folders_size = 0;
/* COPIED FROM FCICreate */ /* COPIED FROM FCICreate */
@ -2199,28 +2080,6 @@ static BOOL fci_flush_cabinet( FCI_Int *p_fci_internal,
} }
/* TODO error checking of err */ /* TODO error checking of err */
/* array of all CFFILE in a folder, ready to be copied into cabinet */
if (!p_fci_internal->gettemp(p_fci_internal->szFileNameCFFOLDER,CB_MAX_FILENAME, p_fci_internal->pv)) {
/* error handling */
set_error( p_fci_internal, FCIERR_NONE, ERROR_FUNCTION_FAILED );
return FALSE;
}
/* safety */
if ( strlen(p_fci_internal->szFileNameCFFOLDER) >= CB_MAX_FILENAME ) {
/* set error code and abort */
set_error( p_fci_internal, FCIERR_NONE, ERROR_INVALID_DATA );
return FALSE;
}
p_fci_internal->handleCFFOLDER = p_fci_internal->open( p_fci_internal->szFileNameCFFOLDER,
_O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY,
_S_IREAD | _S_IWRITE, &err, p_fci_internal->pv);
/* check handle */
if(p_fci_internal->handleCFFOLDER==0){
set_error( p_fci_internal, FCIERR_TEMP_FILE, ERROR_OPEN_FAILED );
return FALSE;
}
/* TODO error checking of err */
/* END OF copied from FCICreate */ /* END OF copied from FCICreate */
@ -2276,7 +2135,7 @@ static BOOL fci_flush_cabinet( FCI_Int *p_fci_internal,
} }
read_result+= p_fci_internal->sizeFileCFDATA1 + read_result+= p_fci_internal->sizeFileCFDATA1 +
p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 + p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER + p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size +
sizeof(CFHEADER) + sizeof(CFHEADER) +
sizeof(CFFOLDER); /* set size of new CFFolder entry */ sizeof(CFFOLDER); /* set size of new CFFolder entry */
@ -2517,7 +2376,7 @@ BOOL __cdecl FCIAddFile(
read_result+= sizeof(CFFILE) + strlen(pszFileName)+1 + read_result+= sizeof(CFFILE) + strlen(pszFileName)+1 +
p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 + p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER + p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size +
sizeof(CFHEADER) + sizeof(CFHEADER) +
sizeof(CFFOLDER); /* size of new CFFolder entry */ sizeof(CFFOLDER); /* size of new CFFolder entry */
@ -2675,7 +2534,7 @@ BOOL __cdecl FCIAddFile(
} }
read_result+= p_fci_internal->sizeFileCFDATA1 + read_result+= p_fci_internal->sizeFileCFDATA1 +
p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 + p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER + p_fci_internal->sizeFileCFFILE2 + p_fci_internal->folders_size +
sizeof(CFHEADER) + sizeof(CFHEADER) +
sizeof(CFFOLDER); /* set size of new CFFolder entry */ sizeof(CFFOLDER); /* set size of new CFFolder entry */
@ -2876,6 +2735,7 @@ BOOL __cdecl FCIFlushCabinet(
BOOL __cdecl FCIDestroy(HFCI hfci) BOOL __cdecl FCIDestroy(HFCI hfci)
{ {
int err; int err;
struct folder *folder, *folder_next;
FCI_Int *p_fci_internal = get_fci_ptr( hfci ); FCI_Int *p_fci_internal = get_fci_ptr( hfci );
if (!p_fci_internal) return FALSE; if (!p_fci_internal) return FALSE;
@ -2884,6 +2744,12 @@ BOOL __cdecl FCIDestroy(HFCI hfci)
/* and deleted */ /* and deleted */
p_fci_internal->magic = 0; p_fci_internal->magic = 0;
LIST_FOR_EACH_ENTRY_SAFE( folder, folder_next, &p_fci_internal->folders_list, struct folder, entry )
{
list_remove( &folder->entry );
p_fci_internal->free( folder );
}
p_fci_internal->close( p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv); p_fci_internal->close( p_fci_internal->handleCFDATA1,&err,p_fci_internal->pv);
/* TODO error handling of err */ /* TODO error handling of err */
p_fci_internal->delete( p_fci_internal->szFileNameCFDATA1, &err, p_fci_internal->delete( p_fci_internal->szFileNameCFDATA1, &err,
@ -2904,11 +2770,6 @@ BOOL __cdecl FCIDestroy(HFCI hfci)
p_fci_internal->delete( p_fci_internal->szFileNameCFFILE2, &err, p_fci_internal->delete( p_fci_internal->szFileNameCFFILE2, &err,
p_fci_internal->pv); p_fci_internal->pv);
/* TODO error handling of err */ /* TODO error handling of err */
p_fci_internal->close( p_fci_internal->handleCFFOLDER,&err,p_fci_internal->pv);
/* TODO error handling of err */
p_fci_internal->delete( p_fci_internal->szFileNameCFFOLDER, &err,
p_fci_internal->pv);
/* TODO error handling of err */
/* data in and out buffers have to be removed */ /* data in and out buffers have to be removed */
if (p_fci_internal->data_in!=NULL) if (p_fci_internal->data_in!=NULL)