summaryrefslogtreecommitdiff
path: root/src/H5Zfletcher32.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Zfletcher32.c')
-rw-r--r--src/H5Zfletcher32.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/H5Zfletcher32.c b/src/H5Zfletcher32.c
new file mode 100644
index 0000000..4cd77ef
--- /dev/null
+++ b/src/H5Zfletcher32.c
@@ -0,0 +1,164 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Raymond Lu <slu@ncsa.uiuc.edu>
+ * Jan 3, 2003
+ */
+
+#include "H5Zmodule.h" /* This source code file is part of the H5Z module */
+
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fprivate.h" /* File access */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Zpkg.h" /* Data filters */
+
+/* Local function prototypes */
+static size_t H5Z_filter_fletcher32 (unsigned flags, size_t cd_nelmts,
+ const unsigned cd_values[], size_t nbytes, size_t *buf_size, void **buf);
+
+/* This message derives from H5Z */
+const H5Z_class2_t H5Z_FLETCHER32[1] = {{
+ H5Z_CLASS_T_VERS, /* H5Z_class_t version */
+ H5Z_FILTER_FLETCHER32, /* Filter id number */
+ 1, /* encoder_present flag (set to true) */
+ 1, /* decoder_present flag (set to true) */
+ "fletcher32", /* Filter name for debugging */
+ NULL, /* The "can apply" callback */
+ NULL, /* The "set local" callback */
+ H5Z_filter_fletcher32, /* The actual filter function */
+}};
+
+#define FLETCHER_LEN 4
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_filter_fletcher32
+ *
+ * Purpose: Implement an I/O filter of Fletcher32 Checksum
+ *
+ * Return: Success: Size of buffer filtered
+ * Failure: 0
+ *
+ * Programmer: Raymond Lu
+ * Jan 3, 2003
+ *
+ * Modifications:
+ * Raymond Lu
+ * July 8, 2005
+ * There was a bug in the calculating code of the Fletcher32
+ * checksum in the library before v1.6.3. The checksum
+ * value wasn't consistent between big-endian and little-endian
+ * systems. This bug was fixed in Release 1.6.3. However,
+ * after fixing the bug, the checksum value is no longer the
+ * same as before on little-endian system. We'll check both
+ * the correct checksum and the wrong checksum to be consistent
+ * with Release 1.6.2 and before.
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5Z_filter_fletcher32 (unsigned flags, size_t H5_ATTR_UNUSED cd_nelmts, const unsigned H5_ATTR_UNUSED cd_values[],
+ size_t nbytes, size_t *buf_size, void **buf)
+{
+ void *outbuf = NULL; /* Pointer to new buffer */
+ unsigned char *src = (unsigned char*)(*buf);
+ uint32_t fletcher; /* Checksum value */
+ uint32_t reversed_fletcher; /* Possible wrong checksum value */
+ uint8_t c[4];
+ uint8_t tmp;
+ size_t ret_value = 0; /* Return value */
+
+ FUNC_ENTER_NOAPI(0)
+
+ HDassert(sizeof(uint32_t)>=4);
+
+ if (flags & H5Z_FLAG_REVERSE) { /* Read */
+ /* Do checksum if it's enabled for read; otherwise skip it
+ * to save performance. */
+ if (!(flags & H5Z_FLAG_SKIP_EDC)) {
+ unsigned char *tmp_src; /* Pointer to checksum in buffer */
+ size_t src_nbytes = nbytes; /* Original number of bytes */
+ uint32_t stored_fletcher; /* Stored checksum value */
+
+ /* Get the stored checksum */
+ src_nbytes -= FLETCHER_LEN;
+ tmp_src=src+src_nbytes;
+ UINT32DECODE(tmp_src, stored_fletcher);
+
+ /* Compute checksum (can't fail) */
+ fletcher = H5_checksum_fletcher32(src, src_nbytes);
+
+ /* The reversed checksum. There was a bug in the calculating code of
+ * the Fletcher32 checksum in the library before v1.6.3. The checksum
+ * value wasn't consistent between big-endian and little-endian systems.
+ * This bug was fixed in Release 1.6.3. However, after fixing the bug,
+ * the checksum value is no longer the same as before on little-endian
+ * system. We'll check both the correct checksum and the wrong
+ * checksum to be consistent with Release 1.6.2 and before.
+ */
+ HDmemcpy(c, &fletcher, (size_t)4);
+
+ tmp = c[1];
+ c[1] = c[0];
+ c[0] = tmp;
+
+ tmp = c[3];
+ c[3] = c[2];
+ c[2] = tmp;
+
+ HDmemcpy(&reversed_fletcher, c, (size_t)4);
+
+ /* Verify computed checksum matches stored checksum */
+ if(stored_fletcher != fletcher && stored_fletcher != reversed_fletcher)
+ HGOTO_ERROR(H5E_STORAGE, H5E_READERROR, 0, "data error detected by Fletcher32 checksum")
+ }
+
+ /* Set return values */
+ /* (Re-use the input buffer, just note that the size is smaller by the size of the checksum) */
+ ret_value = nbytes-FLETCHER_LEN;
+ } else { /* Write */
+ unsigned char *dst; /* Temporary pointer to destination buffer */
+
+ /* Compute checksum (can't fail) */
+ fletcher = H5_checksum_fletcher32(src, nbytes);
+
+ if (NULL == (outbuf = H5MM_malloc(nbytes + FLETCHER_LEN)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "unable to allocate Fletcher32 checksum destination buffer")
+
+ dst = (unsigned char *) outbuf;
+
+ /* Copy raw data */
+ HDmemcpy((void*)dst, (void*)(*buf), nbytes);
+
+ /* Append checksum to raw data for storage */
+ dst += nbytes;
+ UINT32ENCODE(dst, fletcher);
+
+ /* Free input buffer */
+ H5MM_xfree(*buf);
+
+ /* Set return values */
+ *buf_size = nbytes + FLETCHER_LEN;
+ *buf = outbuf;
+ outbuf = NULL;
+ ret_value = *buf_size;
+ }
+
+done:
+ if(outbuf)
+ H5MM_xfree(outbuf);
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+