/src/hdf5/src/H5FDonion_header.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 | | /* |
14 | | * Onion Virtual File Driver (VFD) |
15 | | * |
16 | | * Purpose: Code for the onion file's header |
17 | | */ |
18 | | |
19 | | #include "H5FDmodule.h" /* This source code file is part of the H5FD module */ |
20 | | |
21 | | #include "H5private.h" /* Generic Functions */ |
22 | | #include "H5Eprivate.h" /* Error handling */ |
23 | | #include "H5FDpkg.h" /* File drivers */ |
24 | | #include "H5FDonion_priv.h" /* Onion file driver internals */ |
25 | | #include "H5MMprivate.h" /* Memory management */ |
26 | | |
27 | | /*----------------------------------------------------------------------------- |
28 | | * Function: H5FD_ingest_header |
29 | | * |
30 | | * Purpose: Read and decode the history header information from `raw_file` |
31 | | * at `addr`, and store the decoded information in the structure |
32 | | * at `hdr_out`. |
33 | | * |
34 | | * Return: SUCCEED/FAIL |
35 | | *----------------------------------------------------------------------------- |
36 | | */ |
37 | | herr_t |
38 | | H5FD__onion_ingest_header(H5FD_onion_header_t *hdr_out, H5FD_t *raw_file, haddr_t addr) |
39 | 0 | { |
40 | 0 | unsigned char *buf = NULL; |
41 | 0 | herr_t ret_value = SUCCEED; |
42 | 0 | haddr_t size = (haddr_t)H5FD_ONION_ENCODED_SIZE_HEADER; |
43 | 0 | uint32_t sum = 0; |
44 | |
|
45 | 0 | FUNC_ENTER_PACKAGE |
46 | |
|
47 | 0 | if (H5FD_get_eof(raw_file, H5FD_MEM_DRAW) < (addr + size)) |
48 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "header indicates history beyond EOF"); |
49 | | |
50 | 0 | if (NULL == (buf = H5MM_malloc(sizeof(char) * size))) |
51 | 0 | HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "can't allocate buffer space"); |
52 | | |
53 | 0 | if (H5FD_set_eoa(raw_file, H5FD_MEM_DRAW, (addr + size)) < 0) |
54 | 0 | HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't modify EOA"); |
55 | | |
56 | 0 | if (H5FD_read(raw_file, H5FD_MEM_DRAW, addr, size, buf) < 0) |
57 | 0 | HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't read history header from file"); |
58 | | |
59 | 0 | if (H5FD__onion_header_decode(buf, hdr_out) == 0) |
60 | 0 | HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "can't decode history header"); |
61 | | |
62 | 0 | sum = H5_checksum_fletcher32(buf, size - 4); |
63 | 0 | if (hdr_out->checksum != sum) |
64 | 0 | HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "checksum mismatch between buffer and stored"); |
65 | | |
66 | 0 | done: |
67 | 0 | H5MM_xfree(buf); |
68 | |
|
69 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
70 | 0 | } /* end H5FD__onion_ingest_header() */ |
71 | | |
72 | | /*------------------------------------------------------------------------- |
73 | | * Function: H5FD__onion_write_header |
74 | | * |
75 | | * Purpose: Write in-memory history header to appropriate backing file. |
76 | | * Overwrites existing header data. |
77 | | * |
78 | | * Return: SUCCEED/FAIL |
79 | | *------------------------------------------------------------------------- |
80 | | */ |
81 | | herr_t |
82 | | H5FD__onion_write_header(H5FD_onion_header_t *header, H5FD_t *file) |
83 | 0 | { |
84 | 0 | uint32_t sum = 0; /* Not used, but required by the encoder */ |
85 | 0 | uint64_t size = 0; |
86 | 0 | unsigned char *buf = NULL; |
87 | 0 | herr_t ret_value = SUCCEED; |
88 | |
|
89 | 0 | FUNC_ENTER_PACKAGE |
90 | |
|
91 | 0 | if (NULL == (buf = H5MM_malloc(H5FD_ONION_ENCODED_SIZE_HEADER))) |
92 | 0 | HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "can't allocate buffer for updated history header"); |
93 | | |
94 | 0 | if (0 == (size = H5FD__onion_header_encode(header, buf, &sum))) |
95 | 0 | HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "problem encoding updated history header"); |
96 | | |
97 | 0 | if (H5FD_write(file, H5FD_MEM_DRAW, 0, (haddr_t)size, buf) < 0) |
98 | 0 | HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "can't write updated history header"); |
99 | | |
100 | 0 | done: |
101 | 0 | H5MM_xfree(buf); |
102 | |
|
103 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
104 | 0 | } /* end H5FD__onion_write_header()*/ |
105 | | |
106 | | /*----------------------------------------------------------------------------- |
107 | | * Function: H5FD__onion_header_decode |
108 | | * |
109 | | * Purpose: Attempt to read a buffer and store it as a history-header |
110 | | * structure. |
111 | | * |
112 | | * Implementation must correspond with |
113 | | * H5FD__onion_header_encode(). |
114 | | * |
115 | | * Return: Success: Number of bytes read from buffer |
116 | | * Failure: 0 |
117 | | *----------------------------------------------------------------------------- |
118 | | */ |
119 | | size_t |
120 | | H5FD__onion_header_decode(unsigned char *buf, H5FD_onion_header_t *header) |
121 | 0 | { |
122 | 0 | uint32_t ui32 = 0; |
123 | 0 | uint32_t sum = 0; |
124 | 0 | uint64_t ui64 = 0; |
125 | 0 | uint8_t *ui8p = NULL; |
126 | 0 | unsigned char *ptr = NULL; |
127 | 0 | size_t ret_value = 0; |
128 | |
|
129 | 0 | FUNC_ENTER_PACKAGE |
130 | |
|
131 | 0 | assert(buf != NULL); |
132 | 0 | assert(header != NULL); |
133 | 0 | assert(H5FD_ONION_HEADER_VERSION_CURR == header->version); |
134 | |
|
135 | 0 | if (strncmp((const char *)buf, H5FD_ONION_HEADER_SIGNATURE, 4)) |
136 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid header signature"); |
137 | | |
138 | 0 | if (buf[4] != H5FD_ONION_HEADER_VERSION_CURR) |
139 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid header version"); |
140 | | |
141 | 0 | ptr = buf + 5; |
142 | 0 | ui32 = 0; |
143 | 0 | H5MM_memcpy(&ui32, ptr, 3); |
144 | 0 | ui8p = (uint8_t *)&ui32; |
145 | 0 | UINT32DECODE(ui8p, header->flags); |
146 | 0 | ptr += 3; |
147 | |
|
148 | 0 | H5MM_memcpy(&ui32, ptr, 4); |
149 | 0 | ui8p = (uint8_t *)&ui32; |
150 | 0 | UINT32DECODE(ui8p, header->page_size); |
151 | 0 | ptr += 4; |
152 | |
|
153 | 0 | H5MM_memcpy(&ui64, ptr, 8); |
154 | 0 | ui8p = (uint8_t *)&ui64; |
155 | 0 | UINT32DECODE(ui8p, header->origin_eof); |
156 | 0 | ptr += 8; |
157 | |
|
158 | 0 | H5MM_memcpy(&ui64, ptr, 8); |
159 | 0 | ui8p = (uint8_t *)&ui64; |
160 | 0 | UINT32DECODE(ui8p, header->history_addr); |
161 | 0 | ptr += 8; |
162 | |
|
163 | 0 | H5MM_memcpy(&ui64, ptr, 8); |
164 | 0 | ui8p = (uint8_t *)&ui64; |
165 | 0 | UINT32DECODE(ui8p, header->history_size); |
166 | 0 | ptr += 8; |
167 | |
|
168 | 0 | sum = H5_checksum_fletcher32(buf, (size_t)(ptr - buf)); |
169 | |
|
170 | 0 | H5MM_memcpy(&ui32, ptr, 4); |
171 | 0 | ui8p = (uint8_t *)&ui32; |
172 | 0 | UINT32DECODE(ui8p, header->checksum); |
173 | 0 | ptr += 4; |
174 | |
|
175 | 0 | if (sum != header->checksum) |
176 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "checksum mismatch"); |
177 | | |
178 | 0 | ret_value = (size_t)(ptr - buf); |
179 | |
|
180 | 0 | done: |
181 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
182 | 0 | } /* end H5FD__onion_header_decode() */ |
183 | | |
184 | | /*----------------------------------------------------------------------------- |
185 | | * Function: H5FD__onion_header_encode |
186 | | * |
187 | | * Purpose: Write history-header structure to the given buffer. |
188 | | * All multi-byte elements are stored in little-endian word order. |
189 | | * |
190 | | * Implementation must correspond with |
191 | | * H5FD__onion_header_decode(). |
192 | | * |
193 | | * The destination buffer must be sufficiently large to hold the |
194 | | * encoded contents (H5FD_ONION_ENCODED_SIZE_HEADER). |
195 | | * |
196 | | * Return: Number of bytes written to buffer. |
197 | | * The checksum of the generated buffer contents (excluding the |
198 | | * checksum itself) is stored in the pointer `checksum`). |
199 | | *----------------------------------------------------------------------------- |
200 | | */ |
201 | | size_t |
202 | | H5FD__onion_header_encode(H5FD_onion_header_t *header, unsigned char *buf, uint32_t *checksum /*out*/) |
203 | 0 | { |
204 | 0 | unsigned char *ptr = buf; |
205 | 0 | size_t ret_value = 0; |
206 | |
|
207 | 0 | FUNC_ENTER_PACKAGE_NOERR |
208 | |
|
209 | 0 | assert(buf != NULL); |
210 | 0 | assert(checksum != NULL); |
211 | 0 | assert(header != NULL); |
212 | 0 | assert(H5FD_ONION_HEADER_VERSION_CURR == header->version); |
213 | 0 | assert(0 == (header->flags & 0xFF000000)); /* max three bits long */ |
214 | |
|
215 | 0 | H5MM_memcpy(ptr, H5FD_ONION_HEADER_SIGNATURE, 4); |
216 | 0 | ptr += 4; |
217 | 0 | H5MM_memcpy(ptr, (unsigned char *)&header->version, 1); |
218 | 0 | ptr += 1; |
219 | 0 | UINT32ENCODE(ptr, header->flags); |
220 | 0 | ptr -= 1; /* truncate to three bytes */ |
221 | 0 | UINT32ENCODE(ptr, header->page_size); |
222 | 0 | UINT64ENCODE(ptr, header->origin_eof); |
223 | 0 | UINT64ENCODE(ptr, header->history_addr); |
224 | 0 | UINT64ENCODE(ptr, header->history_size); |
225 | 0 | *checksum = H5_checksum_fletcher32(buf, (size_t)(ptr - buf)); |
226 | 0 | UINT32ENCODE(ptr, *checksum); |
227 | 0 | ret_value = (size_t)(ptr - buf); |
228 | |
|
229 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
230 | 0 | } /* end H5FD__onion_header_encode() */ |