📄 fci.c
字号:
UINT i;
/* 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 */);
cfdata->csum=0; /* checksum has to be set later */
/* TODO set realsize of compressed data */
cfdata->cbData = p_fci_internal->cdata_in;
cfdata->cbUncomp = p_fci_internal->cdata_in;
/* write cfdata to p_fci_internal->handleCFDATA1 */
if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
cfdata, sizeof(*cfdata), err, p_fci_internal->pv)
!= sizeof(*cfdata) ) {
fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
return FALSE;
}
/* TODO error handling of err */
p_fci_internal->sizeFileCFDATA1 += sizeof(*cfdata);
/* add optional reserved area */
/* This allocation and freeing at each CFData block is a bit */
/* inefficent, but it's harder to forget about freeing the buffer :-). */
/* Reserved areas are used seldom besides that... */
if (cbReserveCFData!=0) {
if(!(reserved = (char*)PFCI_ALLOC(hfci, cbReserveCFData))) {
fci_set_error( FCIERR_ALLOC_FAIL, ERROR_NOT_ENOUGH_MEMORY, TRUE );
return FALSE;
}
for(i=0;i<cbReserveCFData;) {
reserved[i++]='\0';
}
if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
reserved, /* memory buffer */
cbReserveCFData, /* number of bytes to copy */
err, p_fci_internal->pv) != cbReserveCFData ) {
PFCI_FREE(hfci, reserved);
fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
return FALSE;
}
/* TODO error handling of err PFCI_FREE(hfci, reserved)*/
p_fci_internal->sizeFileCFDATA1 += cbReserveCFData;
PFCI_FREE(hfci, reserved);
}
/* write p_fci_internal->data_out to p_fci_internal->handleCFDATA1 */
if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA1, /* file handle */
p_fci_internal->data_out, /* memory buffer */
cfdata->cbData, /* number of bytes to copy */
err, p_fci_internal->pv) != cfdata->cbData) {
fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
return FALSE;
}
/* TODO error handling of err */
p_fci_internal->sizeFileCFDATA1 += cfdata->cbData;
/* reset the offset */
p_fci_internal->cdata_in = 0;
p_fci_internal->cCompressedBytesInFolder += cfdata->cbData;
/* report status with pfnfcis about uncompressed and compressed file data */
if( (*pfnfcis)(statusFile, cfdata->cbData, cfdata->cbUncomp,
p_fci_internal->pv) == -1) {
fci_set_error( FCIERR_USER_ABORT, 0, TRUE );
return FALSE;
}
++(p_fci_internal->cDataBlocks);
return TRUE;
} /* end of fci_flush_data_block */
static cab_ULONG fci_get_checksum(void *pv, UINT cb, CHECKSUM seed)
{
cab_ULONG csum;
cab_ULONG ul;
int cUlong;
BYTE *pb;
csum = seed;
cUlong = cb / 4;
pb = pv;
while (cUlong-- > 0) {
ul = *pb++;
ul |= (((cab_ULONG)(*pb++)) << 8);
ul |= (((cab_ULONG)(*pb++)) << 16);
ul |= (((cab_ULONG)(*pb++)) << 24);
csum ^= ul;
}
ul = 0;
switch (cb % 4) {
case 3:
ul |= (((ULONG)(*pb++)) << 16);
case 2:
ul |= (((ULONG)(*pb++)) << 8);
case 1:
ul |= *pb++;
default:
break;
}
csum ^= ul;
return csum;
} /* end of fci_get_checksum */
static BOOL fci_flushfolder_copy_cfdata(HFCI hfci, char* buffer, UINT cbReserveCFData,
PFNFCISTATUS pfnfcis, int* err, int handleCFDATA1new,
cab_ULONG* psizeFileCFDATA1new, cab_ULONG* payload)
{
cab_ULONG read_result;
CFDATA* pcfdata=(CFDATA*)buffer;
BOOL split_block=FALSE;
cab_UWORD savedUncomp=0;
PFCI_Int p_fci_internal=((PFCI_Int)(hfci));
*payload=0;
/* while not all CFDATAs have been copied do */
while(!FALSE) {
if( p_fci_internal->fNextCab ) {
if( split_block ) {
/* internal error should never happen */
fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
return FALSE;
}
}
/* REUSE the variable read_result */
if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
read_result=4;
} else {
read_result=0;
}
if (p_fci_internal->fPrevCab) {
read_result+=strlen(p_fci_internal->szPrevCab)+1 +
strlen(p_fci_internal->szPrevDisk)+1;
}
/* No more CFDATA fits into the cabinet under construction */
/* So don't try to store more data into it */
if( p_fci_internal->fNextCab &&
(p_fci_internal->oldCCAB.cb <= sizeof(CFDATA) + cbReserveCFData +
p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
sizeof(CFHEADER) +
read_result +
p_fci_internal->oldCCAB.cbReserveCFHeader +
sizeof(CFFOLDER) +
p_fci_internal->oldCCAB.cbReserveCFFolder +
strlen(p_fci_internal->pccab->szCab)+1 +
strlen(p_fci_internal->pccab->szDisk)+1
)) {
/* This may never be run for the first time the while loop is entered.
Pray that the code that calls fci_flushfolder_copy_cfdata handles this.*/
split_block=TRUE; /* In this case split_block is abused to store */
/* the complete data block into the next cabinet and not into the */
/* current one. Originally split_block is the indicator that a */
/* data block has been splitted across different cabinets. */
} else {
/* read CFDATA from p_fci_internal->handleCFDATA1 to cfdata*/
read_result= PFCI_READ(hfci, p_fci_internal->handleCFDATA1,/*file handle*/
buffer, /* memory buffer */
sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
err, p_fci_internal->pv);
if (read_result!=sizeof(CFDATA)+cbReserveCFData) {
if (read_result==0) break; /* ALL DATA has been copied */
/* read error */
fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
return FALSE;
}
/* TODO error handling of err */
/* REUSE buffer p_fci_internal->data_out !!! */
/* read data from p_fci_internal->handleCFDATA1 to */
/* p_fci_internal->data_out */
if( PFCI_READ(hfci, p_fci_internal->handleCFDATA1 /* file handle */,
p_fci_internal->data_out /* memory buffer */,
pcfdata->cbData /* number of bytes to copy */,
err, p_fci_internal->pv) != pcfdata->cbData ) {
/* read error */
fci_set_error( FCIERR_NONE, ERROR_READ_FAULT, TRUE );
return FALSE;
}
/* TODO error handling of err */
/* if cabinet size is too large */
/* REUSE the variable read_result */
if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
read_result=4;
} else {
read_result=0;
}
if (p_fci_internal->fPrevCab) {
read_result+=strlen(p_fci_internal->szPrevCab)+1 +
strlen(p_fci_internal->szPrevDisk)+1;
}
/* Is cabinet with new CFDATA too large? Then data block has to be split */
if( p_fci_internal->fNextCab &&
(p_fci_internal->oldCCAB.cb < sizeof(CFDATA) + cbReserveCFData +
pcfdata->cbData +
p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
sizeof(CFHEADER) +
read_result +
p_fci_internal->oldCCAB.cbReserveCFHeader +
sizeof(CFFOLDER) + /* size of new CFFolder entry */
p_fci_internal->oldCCAB.cbReserveCFFolder +
strlen(p_fci_internal->pccab->szCab)+1 + /* name of next cabinet */
strlen(p_fci_internal->pccab->szDisk)+1 /* name of next disk */
)) {
/* REUSE read_result to save the size of the compressed data */
read_result=pcfdata->cbData;
/* Modify the size of the compressed data to store only a part of the */
/* data block into the current cabinet. This is done to prevent */
/* that the maximum cabinet size will be exceeded. The remainder */
/* will be stored into the next following cabinet. */
/* The cabinet will be of size "p_fci_internal->oldCCAB.cb". */
/* Substract everything except the size of the block of data */
/* to get it's actual size */
pcfdata->cbData = p_fci_internal->oldCCAB.cb - (
sizeof(CFDATA) + cbReserveCFData +
p_fci_internal->sizeFileCFFILE1 + p_fci_internal->sizeFileCFDATA2 +
p_fci_internal->sizeFileCFFILE2 + p_fci_internal->sizeFileCFFOLDER +
sizeof(CFHEADER) +
p_fci_internal->oldCCAB.cbReserveCFHeader +
sizeof(CFFOLDER) + /* set size of new CFFolder entry */
p_fci_internal->oldCCAB.cbReserveCFFolder );
/* substract the size of special header fields */
if ( p_fci_internal->oldCCAB.cbReserveCFHeader != 0 ||
p_fci_internal->oldCCAB.cbReserveCFFolder != 0 ||
p_fci_internal->oldCCAB.cbReserveCFData != 0 ) {
pcfdata->cbData-=4;
}
if (p_fci_internal->fPrevCab) {
pcfdata->cbData-=strlen(p_fci_internal->szPrevCab)+1 +
strlen(p_fci_internal->szPrevDisk)+1;
}
pcfdata->cbData-=strlen(p_fci_internal->pccab->szCab)+1 +
strlen(p_fci_internal->pccab->szDisk)+1;
savedUncomp = pcfdata->cbUncomp;
pcfdata->cbUncomp = 0; /* on splitted blocks of data this is zero */
/* if split_block==TRUE then the above while loop won't */
/* be executed again */
split_block=TRUE; /* split_block is the indicator that */
/* a data block has been splitted across */
/* diffentent cabinets.*/
}
/* This should never happen !!! */
if (pcfdata->cbData==0) {
/* set error */
fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
return FALSE;
}
/* set little endian */
pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
/* get checksum and write to cfdata.csum */
pcfdata->csum = fci_get_checksum( &(pcfdata->cbData),
sizeof(CFDATA)+cbReserveCFData -
sizeof(pcfdata->csum), fci_get_checksum( p_fci_internal->data_out, /*buffer*/
pcfdata->cbData, 0 ) );
/* set little endian */
pcfdata->csum=fci_endian_ulong(pcfdata->csum);
/* write cfdata with checksum to p_fci_internal->handleCFDATA2 */
if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */
buffer, /* memory buffer */
sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
return FALSE;
}
/* TODO error handling of err */
p_fci_internal->sizeFileCFDATA2 += sizeof(CFDATA)+cbReserveCFData;
/* reset little endian */
pcfdata->cbData=fci_endian_uword(pcfdata->cbData);
pcfdata->cbUncomp=fci_endian_uword(pcfdata->cbUncomp);
pcfdata->csum=fci_endian_ulong(pcfdata->csum);
/* write compressed data into p_fci_internal->handleCFDATA2 */
if( PFCI_WRITE(hfci, p_fci_internal->handleCFDATA2, /* file handle */
p_fci_internal->data_out, /* memory buffer */
pcfdata->cbData, /* number of bytes to copy */
err, p_fci_internal->pv) != pcfdata->cbData) {
fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
return FALSE;
}
/* TODO error handling of err */
p_fci_internal->sizeFileCFDATA2 += pcfdata->cbData;
++(p_fci_internal->cDataBlocks);
p_fci_internal->statusFolderCopied += pcfdata->cbData;
(*payload)+=pcfdata->cbUncomp;
/* if cabinet size too large and data has been split */
/* write the remainder of the data block to the new CFDATA1 file */
if( split_block ) { /* This does not include the */
/* abused one (just search for "abused" )*/
/* copy all CFDATA structures from handleCFDATA1 to handleCFDATA1new */
if (p_fci_internal->fNextCab==FALSE ) {
/* internal error */
fci_set_error( FCIERR_NONE, ERROR_GEN_FAILURE, TRUE );
return FALSE;
}
/* set cbData to the size of the remainder of the data block */
pcfdata->cbData = read_result - pcfdata->cbData;
/*recover former value of cfdata.cbData; read_result will be the offset*/
read_result -= pcfdata->cbData;
pcfdata->cbUncomp = savedUncomp;
/* reset checksum, it will be computed later */
pcfdata->csum=0;
/* write cfdata WITHOUT checksum to handleCFDATA1new */
if( PFCI_WRITE(hfci, handleCFDATA1new, /* file handle */
buffer, /* memory buffer */
sizeof(CFDATA)+cbReserveCFData, /* number of bytes to copy */
err, p_fci_internal->pv) != sizeof(CFDATA)+cbReserveCFData ) {
fci_set_error( FCIERR_TEMP_FILE, ERROR_WRITE_FAULT, TRUE );
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -