/src/hdf5/src/H5Zfletcher32.c
Line | Count | Source |
1 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | | * Copyright by The HDF Group. * |
3 | | * All rights reserved. * |
4 | | * * |
5 | | * This file is part of HDF5. The full HDF5 copyright notice, including * |
6 | | * terms governing use, modification, and redistribution, is contained in * |
7 | | * the LICENSE file, which can be found at the root of the source code * |
8 | | * distribution tree, or in https://www.hdfgroup.org/licenses. * |
9 | | * If you do not have access to either file, you may request a copy from * |
10 | | * help@hdfgroup.org. * |
11 | | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
12 | | |
13 | | #include "H5Zmodule.h" /* This source code file is part of the H5Z module */ |
14 | | |
15 | | #include "H5private.h" /* Generic Functions */ |
16 | | #include "H5Eprivate.h" /* Error handling */ |
17 | | #include "H5MMprivate.h" /* Memory management */ |
18 | | #include "H5Zpkg.h" /* Data filters */ |
19 | | |
20 | | /* Local function prototypes */ |
21 | | static size_t H5Z__filter_fletcher32(unsigned flags, size_t cd_nelmts, const unsigned cd_values[], |
22 | | size_t nbytes, size_t *buf_size, void **buf); |
23 | | |
24 | | /* This message derives from H5Z */ |
25 | | const H5Z_class2_t H5Z_FLETCHER32[1] = {{ |
26 | | H5Z_CLASS_T_VERS, /* H5Z_class_t version */ |
27 | | H5Z_FILTER_FLETCHER32, /* Filter id number */ |
28 | | 1, /* encoder_present flag (set to true) */ |
29 | | 1, /* decoder_present flag (set to true) */ |
30 | | "fletcher32", /* Filter name for debugging */ |
31 | | NULL, /* The "can apply" callback */ |
32 | | NULL, /* The "set local" callback */ |
33 | | H5Z__filter_fletcher32, /* The actual filter function */ |
34 | | }}; |
35 | | |
36 | 0 | #define FLETCHER_LEN 4 |
37 | | |
38 | | /*------------------------------------------------------------------------- |
39 | | * Function: H5Z__filter_fletcher32 |
40 | | * |
41 | | * Purpose: Implement an I/O filter of Fletcher32 Checksum |
42 | | * |
43 | | * Return: Success: Size of buffer filtered |
44 | | * Failure: 0 |
45 | | * |
46 | | *------------------------------------------------------------------------- |
47 | | */ |
48 | | static size_t |
49 | | H5Z__filter_fletcher32(unsigned flags, size_t H5_ATTR_UNUSED cd_nelmts, |
50 | | const unsigned H5_ATTR_UNUSED cd_values[], size_t nbytes, size_t *buf_size, void **buf) |
51 | 0 | { |
52 | 0 | void *outbuf = NULL; /* Pointer to new buffer */ |
53 | 0 | unsigned char *src = (unsigned char *)(*buf); |
54 | 0 | uint32_t fletcher; /* Checksum value */ |
55 | 0 | uint32_t reversed_fletcher; /* Possible wrong checksum value */ |
56 | 0 | uint8_t c[4]; |
57 | 0 | uint8_t tmp; |
58 | 0 | size_t ret_value = 0; /* Return value */ |
59 | |
|
60 | 0 | FUNC_ENTER_PACKAGE |
61 | |
|
62 | 0 | assert(sizeof(uint32_t) >= 4); |
63 | |
|
64 | 0 | if (flags & H5Z_FLAG_REVERSE) { /* Read */ |
65 | | /* Do checksum if it's enabled for read; otherwise skip it |
66 | | * to save performance. */ |
67 | 0 | if (!(flags & H5Z_FLAG_SKIP_EDC)) { |
68 | 0 | unsigned char *tmp_src; /* Pointer to checksum in buffer */ |
69 | 0 | size_t src_nbytes = nbytes; /* Original number of bytes */ |
70 | 0 | uint32_t stored_fletcher; /* Stored checksum value */ |
71 | | |
72 | | /* Get the stored checksum */ |
73 | 0 | src_nbytes -= FLETCHER_LEN; |
74 | 0 | tmp_src = src + src_nbytes; |
75 | 0 | UINT32DECODE(tmp_src, stored_fletcher); |
76 | | |
77 | | /* Compute checksum (can't fail) */ |
78 | 0 | fletcher = H5_checksum_fletcher32(src, src_nbytes); |
79 | | |
80 | | /* The reversed checksum. There was a bug in the calculating code of |
81 | | * the Fletcher32 checksum in the library before v1.6.3. The checksum |
82 | | * value wasn't consistent between big-endian and little-endian systems. |
83 | | * This bug was fixed in Release 1.6.3. However, after fixing the bug, |
84 | | * the checksum value is no longer the same as before on little-endian |
85 | | * system. We'll check both the correct checksum and the wrong |
86 | | * checksum to be consistent with Release 1.6.2 and before. |
87 | | */ |
88 | 0 | H5MM_memcpy(c, &fletcher, (size_t)4); |
89 | |
|
90 | 0 | tmp = c[1]; |
91 | 0 | c[1] = c[0]; |
92 | 0 | c[0] = tmp; |
93 | |
|
94 | 0 | tmp = c[3]; |
95 | 0 | c[3] = c[2]; |
96 | 0 | c[2] = tmp; |
97 | |
|
98 | 0 | H5MM_memcpy(&reversed_fletcher, c, (size_t)4); |
99 | | |
100 | | /* Verify computed checksum matches stored checksum */ |
101 | 0 | if (stored_fletcher != fletcher && stored_fletcher != reversed_fletcher) |
102 | 0 | HGOTO_ERROR(H5E_STORAGE, H5E_READERROR, 0, "data error detected by Fletcher32 checksum"); |
103 | 0 | } |
104 | | |
105 | | /* Set return values */ |
106 | | /* (Reuse the input buffer, just note that the size is smaller by the size of the checksum) */ |
107 | 0 | ret_value = nbytes - FLETCHER_LEN; |
108 | 0 | } |
109 | 0 | else { /* Write */ |
110 | 0 | unsigned char *dst; /* Temporary pointer to destination buffer */ |
111 | | |
112 | | /* Compute checksum (can't fail) */ |
113 | 0 | fletcher = H5_checksum_fletcher32(src, nbytes); |
114 | |
|
115 | 0 | if (NULL == (outbuf = H5MM_malloc(nbytes + FLETCHER_LEN))) |
116 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, |
117 | 0 | "unable to allocate Fletcher32 checksum destination buffer"); |
118 | | |
119 | 0 | dst = (unsigned char *)outbuf; |
120 | | |
121 | | /* Copy raw data */ |
122 | 0 | H5MM_memcpy((void *)dst, (void *)(*buf), nbytes); |
123 | | |
124 | | /* Append checksum to raw data for storage */ |
125 | 0 | dst += nbytes; |
126 | 0 | UINT32ENCODE(dst, fletcher); |
127 | | |
128 | | /* Free input buffer */ |
129 | 0 | H5MM_xfree(*buf); |
130 | | |
131 | | /* Set return values */ |
132 | 0 | *buf_size = nbytes + FLETCHER_LEN; |
133 | 0 | *buf = outbuf; |
134 | 0 | outbuf = NULL; |
135 | 0 | ret_value = *buf_size; |
136 | 0 | } |
137 | | |
138 | 0 | done: |
139 | 0 | if (outbuf) |
140 | 0 | H5MM_xfree(outbuf); |
141 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
142 | 0 | } |