fis-gtm/sr_port/jnl_get_checksum.c

69 lines
2.6 KiB
C

/****************************************************************
* *
* Copyright 2005, 2009 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#include "mdef.h"
#include "gdsroot.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "jnl_get_checksum.h"
/*
* Input :
* buff : Pointer to the input buffer whose checksum needs to be computed.
* bufflen : Buffer size in bytes
*
* Returns:
* Computed checksum.
*
* Algorithm:
* For every 512 (DISK_BLOCK_SIZE) byte block of the input buffer, the first 16 and last 16 bytes are considered for checksum.
* The way this is implemented is as follows.
* For the 0th 512-byte block, the first 16 bytes are considered.
* For the 1st 512-byte block, the last 16 bytes of the 0th block and the first 16 bytes of the 1st block are considered.
* This is taken as a contiguous sequence of 32-bytes (i.e. CHKSUM_SEGLEN4 uint4s)
* For the 2nd 512-byte block, the last 16 bytes of the 1st block and the first 16 bytes of the 2nd block are considered.
* This is taken as a contiguous sequence of 32-bytes (i.e. CHKSUM_SEGLEN4 uint4s)
* And so on until the input buffer length is exceeded.
* If bufflen is not divisible by 4, it is ROUNDED DOWN to the nearest 4-byte (uint4) multiple.
*/
uint4 jnl_get_checksum(uint4 *buff, sgmnt_addrs *csa, int bufflen)
{
uint4 *top, *blk_base, *blk_top, blen, checksum;
# ifdef GTM_CRYPT
DEBUG_ONLY(
sm_uc_ptr_t orig_buff = NULL;
)
if (NULL != csa && (csa->hdr->is_encrypted))
{
DBG_ENSURE_PTR_IS_VALID_GLOBUFF(csa, csa->hdr, (sm_uc_ptr_t)buff);
DEBUG_ONLY(orig_buff = (unsigned char *)buff;)
buff = (uint4 *)GDS_ANY_ENCRYPTGLOBUF(buff, csa);
DBG_ENSURE_PTR_IS_VALID_ENCTWINGLOBUFF(csa, csa->hdr, (sm_uc_ptr_t)buff);
}
# endif
checksum = INIT_CHECKSUM_SEED;
for (blen = bufflen / SIZEOF(*buff), top = buff + blen, blk_top = buff + CHKSUM_SEGLEN4 / 2; buff < top ;)
{
if (blk_top > top)
blk_top = top;
for ( ; buff < blk_top; buff++)
checksum = ADJUST_CHECKSUM(checksum, *buff);
blk_top = (uint4 *)((sm_uc_ptr_t)buff + DISK_BLOCK_SIZE);
buff = blk_top - CHKSUM_SEGLEN4;
}
/* It is theoretically possible the computed checksum calculates to 0. Since we use a 0 to imply checksum
* was never computed, we need to return a non-zero value so in this case return INIT_CHECKSUM_SEED
*/
if (!checksum)
checksum = INIT_CHECKSUM_SEED;
return checksum;
}