Line | Count | Source (jump to first uncovered line) |
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 COPYING 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 | | * |
15 | | * Created: H5Fio.c |
16 | | * |
17 | | * Purpose: File I/O routines. |
18 | | * |
19 | | *------------------------------------------------------------------------- |
20 | | */ |
21 | | |
22 | | /****************/ |
23 | | /* Module Setup */ |
24 | | /****************/ |
25 | | |
26 | | #include "H5Fmodule.h" /* This source code file is part of the H5F module */ |
27 | | |
28 | | /***********/ |
29 | | /* Headers */ |
30 | | /***********/ |
31 | | #include "H5private.h" /* Generic Functions */ |
32 | | #include "H5Eprivate.h" /* Error handling */ |
33 | | #include "H5Fpkg.h" /* File access */ |
34 | | #include "H5FDprivate.h" /* File drivers */ |
35 | | #include "H5PBprivate.h" /* Page Buffer */ |
36 | | |
37 | | /****************/ |
38 | | /* Local Macros */ |
39 | | /****************/ |
40 | | |
41 | | /******************/ |
42 | | /* Local Typedefs */ |
43 | | /******************/ |
44 | | |
45 | | /********************/ |
46 | | /* Package Typedefs */ |
47 | | /********************/ |
48 | | |
49 | | /********************/ |
50 | | /* Local Prototypes */ |
51 | | /********************/ |
52 | | |
53 | | /*********************/ |
54 | | /* Package Variables */ |
55 | | /*********************/ |
56 | | |
57 | | /*****************************/ |
58 | | /* Library Private Variables */ |
59 | | /*****************************/ |
60 | | |
61 | | /*******************/ |
62 | | /* Local Variables */ |
63 | | /*******************/ |
64 | | |
65 | | /*------------------------------------------------------------------------- |
66 | | * Function: H5F_shared_block_read |
67 | | * |
68 | | * Purpose: Reads some data from a file/server/etc into a buffer. |
69 | | * The data is contiguous. The address is relative to the base |
70 | | * address for the file. |
71 | | * |
72 | | * Return: Non-negative on success/Negative on failure |
73 | | * |
74 | | *------------------------------------------------------------------------- |
75 | | */ |
76 | | herr_t |
77 | | H5F_shared_block_read(H5F_shared_t *f_sh, H5FD_mem_t type, haddr_t addr, size_t size, void *buf /*out*/) |
78 | 0 | { |
79 | 0 | H5FD_mem_t map_type; /* Mapped memory type */ |
80 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
81 | |
|
82 | 0 | FUNC_ENTER_NOAPI(FAIL) |
83 | | |
84 | | /* Sanity checks */ |
85 | 0 | assert(f_sh); |
86 | 0 | assert(buf); |
87 | 0 | assert(H5_addr_defined(addr)); |
88 | | |
89 | | /* Check for attempting I/O on 'temporary' file address */ |
90 | 0 | if (H5_addr_le(f_sh->tmp_addr, (addr + size))) |
91 | 0 | HGOTO_ERROR(H5E_IO, H5E_BADRANGE, FAIL, "attempting I/O in temporary file space"); |
92 | | |
93 | | /* Treat global heap as raw data */ |
94 | 0 | map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type; |
95 | | |
96 | | /* Pass through page buffer layer */ |
97 | 0 | if (H5PB_read(f_sh, map_type, addr, size, buf) < 0) |
98 | 0 | HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "read through page buffer failed"); |
99 | | |
100 | 0 | done: |
101 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
102 | 0 | } /* end H5F_shared_block_read() */ |
103 | | |
104 | | /*------------------------------------------------------------------------- |
105 | | * Function: H5F_block_read |
106 | | * |
107 | | * Purpose: Reads some data from a file/server/etc into a buffer. |
108 | | * The data is contiguous. The address is relative to the base |
109 | | * address for the file. |
110 | | * |
111 | | * Return: Non-negative on success/Negative on failure |
112 | | * |
113 | | *------------------------------------------------------------------------- |
114 | | */ |
115 | | herr_t |
116 | | H5F_block_read(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, void *buf /*out*/) |
117 | 170 | { |
118 | 170 | H5FD_mem_t map_type; /* Mapped memory type */ |
119 | 170 | herr_t ret_value = SUCCEED; /* Return value */ |
120 | | |
121 | 170 | FUNC_ENTER_NOAPI(FAIL) |
122 | | |
123 | | /* Sanity checks */ |
124 | 170 | assert(f); |
125 | 170 | assert(f->shared); |
126 | 170 | assert(buf); |
127 | 170 | assert(H5_addr_defined(addr)); |
128 | | |
129 | | /* Check for attempting I/O on 'temporary' file address */ |
130 | 170 | if (H5_addr_le(f->shared->tmp_addr, (addr + size))) |
131 | 0 | HGOTO_ERROR(H5E_IO, H5E_BADRANGE, FAIL, "attempting I/O in temporary file space"); |
132 | | |
133 | | /* Treat global heap as raw data */ |
134 | 170 | map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type; |
135 | | |
136 | | /* Pass through page buffer layer */ |
137 | 170 | if (H5PB_read(f->shared, map_type, addr, size, buf) < 0) |
138 | 0 | HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "read through page buffer failed"); |
139 | | |
140 | 170 | done: |
141 | 170 | FUNC_LEAVE_NOAPI(ret_value) |
142 | 170 | } /* end H5F_block_read() */ |
143 | | |
144 | | /*------------------------------------------------------------------------- |
145 | | * Function: H5F_shared_block_write |
146 | | * |
147 | | * Purpose: Writes some data from memory to a file/server/etc. The |
148 | | * data is contiguous. The address is relative to the base |
149 | | * address. |
150 | | * |
151 | | * Return: Non-negative on success/Negative on failure |
152 | | * |
153 | | *------------------------------------------------------------------------- |
154 | | */ |
155 | | herr_t |
156 | | H5F_shared_block_write(H5F_shared_t *f_sh, H5FD_mem_t type, haddr_t addr, size_t size, const void *buf) |
157 | 0 | { |
158 | 0 | H5FD_mem_t map_type; /* Mapped memory type */ |
159 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
160 | |
|
161 | 0 | FUNC_ENTER_NOAPI(FAIL) |
162 | | |
163 | | /* Sanity checks */ |
164 | 0 | assert(f_sh); |
165 | 0 | assert(H5F_SHARED_INTENT(f_sh) & H5F_ACC_RDWR); |
166 | 0 | assert(buf); |
167 | 0 | assert(H5_addr_defined(addr)); |
168 | | |
169 | | /* Check for attempting I/O on 'temporary' file address */ |
170 | 0 | if (H5_addr_le(f_sh->tmp_addr, (addr + size))) |
171 | 0 | HGOTO_ERROR(H5E_IO, H5E_BADRANGE, FAIL, "attempting I/O in temporary file space"); |
172 | | |
173 | | /* Treat global heap as raw data */ |
174 | 0 | map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type; |
175 | | |
176 | | /* Pass through page buffer layer */ |
177 | 0 | if (H5PB_write(f_sh, map_type, addr, size, buf) < 0) |
178 | 0 | HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write through page buffer failed"); |
179 | | |
180 | 0 | done: |
181 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
182 | 0 | } /* end H5F_shared_block_write() */ |
183 | | |
184 | | /*------------------------------------------------------------------------- |
185 | | * Function: H5F_block_write |
186 | | * |
187 | | * Purpose: Writes some data from memory to a file/server/etc. The |
188 | | * data is contiguous. The address is relative to the base |
189 | | * address. |
190 | | * |
191 | | * Return: Non-negative on success/Negative on failure |
192 | | * |
193 | | *------------------------------------------------------------------------- |
194 | | */ |
195 | | herr_t |
196 | | H5F_block_write(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, const void *buf) |
197 | 0 | { |
198 | 0 | H5FD_mem_t map_type; /* Mapped memory type */ |
199 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
200 | |
|
201 | 0 | FUNC_ENTER_NOAPI(FAIL) |
202 | | |
203 | | /* Sanity checks */ |
204 | 0 | assert(f); |
205 | 0 | assert(f->shared); |
206 | 0 | assert(H5F_INTENT(f) & H5F_ACC_RDWR); |
207 | 0 | assert(buf); |
208 | 0 | assert(H5_addr_defined(addr)); |
209 | | |
210 | | /* Check for attempting I/O on 'temporary' file address */ |
211 | 0 | if (H5_addr_le(f->shared->tmp_addr, (addr + size))) |
212 | 0 | HGOTO_ERROR(H5E_IO, H5E_BADRANGE, FAIL, "attempting I/O in temporary file space"); |
213 | | |
214 | | /* Treat global heap as raw data */ |
215 | 0 | map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type; |
216 | | |
217 | | /* Pass through page buffer layer */ |
218 | 0 | if (H5PB_write(f->shared, map_type, addr, size, buf) < 0) |
219 | 0 | HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write through page buffer failed"); |
220 | 0 | done: |
221 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
222 | 0 | } /* end H5F_block_write() */ |
223 | | |
224 | | /*------------------------------------------------------------------------- |
225 | | * Function: H5F_shared_select_read |
226 | | * |
227 | | * Purpose: Reads some data from a file/server/etc into a buffer. |
228 | | * The location of the data is defined by the mem_spaces and |
229 | | * file_spaces dataspace arrays, along with the offsets |
230 | | * array. The addresses is relative to the base address for |
231 | | * the file. |
232 | | * |
233 | | * Return: Non-negative on success/Negative on failure |
234 | | * |
235 | | *------------------------------------------------------------------------- |
236 | | */ |
237 | | herr_t |
238 | | H5F_shared_select_read(H5F_shared_t *f_sh, H5FD_mem_t type, uint32_t count, H5S_t **mem_spaces, |
239 | | H5S_t **file_spaces, haddr_t offsets[], size_t element_sizes[], void *bufs[] /* out */) |
240 | 0 | { |
241 | 0 | H5FD_mem_t map_type; /* Mapped memory type */ |
242 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
243 | |
|
244 | 0 | FUNC_ENTER_NOAPI(FAIL) |
245 | | |
246 | | /* Sanity checks */ |
247 | 0 | assert(f_sh); |
248 | 0 | assert((mem_spaces) || (count == 0)); |
249 | 0 | assert((file_spaces) || (count == 0)); |
250 | 0 | assert((offsets) || (count == 0)); |
251 | 0 | assert((element_sizes) || (count == 0)); |
252 | 0 | assert((bufs) || (count == 0)); |
253 | | |
254 | | /* Treat global heap as raw data */ |
255 | 0 | map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type; |
256 | | |
257 | | /* Pass down to file driver layer (bypass page buffer for now) */ |
258 | 0 | if (H5FD_read_selection(f_sh->lf, map_type, count, mem_spaces, file_spaces, offsets, element_sizes, |
259 | 0 | bufs) < 0) |
260 | 0 | HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "selection read through file driver failed"); |
261 | | |
262 | 0 | done: |
263 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
264 | 0 | } /* end H5F_shared_select_read() */ |
265 | | |
266 | | /*------------------------------------------------------------------------- |
267 | | * Function: H5F_shared_select_write |
268 | | * |
269 | | * Purpose: Writes some data from a buffer to a file/server/etc. |
270 | | * The location of the data is defined by the mem_spaces and |
271 | | * file_spaces dataspace arrays, along with the offsets |
272 | | * array. The addresses is relative to the base address for |
273 | | * the file. |
274 | | * |
275 | | * Return: Non-negative on success/Negative on failure |
276 | | * |
277 | | *------------------------------------------------------------------------- |
278 | | */ |
279 | | herr_t |
280 | | H5F_shared_select_write(H5F_shared_t *f_sh, H5FD_mem_t type, uint32_t count, H5S_t **mem_spaces, |
281 | | H5S_t **file_spaces, haddr_t offsets[], size_t element_sizes[], const void *bufs[]) |
282 | 0 | { |
283 | 0 | H5FD_mem_t map_type; /* Mapped memory type */ |
284 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
285 | |
|
286 | 0 | FUNC_ENTER_NOAPI(FAIL) |
287 | | |
288 | | /* Sanity checks */ |
289 | 0 | assert(f_sh); |
290 | 0 | assert((mem_spaces) || (count == 0)); |
291 | 0 | assert((file_spaces) || (count == 0)); |
292 | 0 | assert((offsets) || (count == 0)); |
293 | 0 | assert((element_sizes) || (count == 0)); |
294 | 0 | assert((bufs) || (count == 0)); |
295 | | |
296 | | /* Treat global heap as raw data */ |
297 | 0 | map_type = (type == H5FD_MEM_GHEAP) ? H5FD_MEM_DRAW : type; |
298 | | |
299 | | /* Pass down to file driver layer (bypass page buffer for now) */ |
300 | 0 | if (H5FD_write_selection(f_sh->lf, map_type, count, mem_spaces, file_spaces, offsets, element_sizes, |
301 | 0 | bufs) < 0) |
302 | 0 | HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "selection write through file driver failed"); |
303 | | |
304 | 0 | done: |
305 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
306 | 0 | } /* end H5F_shared_select_write() */ |
307 | | |
308 | | herr_t |
309 | | H5F_shared_vector_read(H5F_shared_t *f_sh, uint32_t count, H5FD_mem_t types[], haddr_t addrs[], |
310 | | size_t sizes[], void *bufs[]) |
311 | 0 | { |
312 | 0 | herr_t ret_value = SUCCEED; |
313 | |
|
314 | 0 | FUNC_ENTER_NOAPI(FAIL) |
315 | | |
316 | | /* Sanity checks */ |
317 | 0 | assert(f_sh); |
318 | 0 | assert((types) || (count == 0)); |
319 | 0 | assert((addrs) || (count == 0)); |
320 | 0 | assert((sizes) || (count == 0)); |
321 | 0 | assert((bufs) || (count == 0)); |
322 | | |
323 | | /* |
324 | | * Note that we don't try to map global heap data to raw |
325 | | * data here, as it may become expensive to check for when |
326 | | * I/O vectors are large. This may change in the future, but, |
327 | | * for now, assume the caller has done this already. |
328 | | */ |
329 | | #ifndef NDEBUG |
330 | | for (uint32_t i = 0; i < count; i++) { |
331 | | /* Break early if H5FD_MEM_NOLIST was specified |
332 | | * since a full 'count'-sized array may not |
333 | | * have been passed for 'types' |
334 | | */ |
335 | | if (i > 0 && types[i] == H5FD_MEM_NOLIST) |
336 | | break; |
337 | | |
338 | | assert(types[i] != H5FD_MEM_GHEAP); |
339 | | } |
340 | | #endif |
341 | | |
342 | | /* Pass down to file driver layer (bypass page buffer for now) */ |
343 | 0 | if (H5FD_read_vector(f_sh->lf, count, types, addrs, sizes, bufs) < 0) |
344 | 0 | HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "vector read through file driver failed"); |
345 | | |
346 | 0 | done: |
347 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
348 | 0 | } |
349 | | |
350 | | /*------------------------------------------------------------------------- |
351 | | * Function: H5F_shared_vector_write |
352 | | * |
353 | | * Purpose: Writes data from `count` buffers (from the `bufs` array) to |
354 | | * a file/server/etc. at the offsets provided in the `addrs` |
355 | | * array, with the data sizes specified in the `sizes` array |
356 | | * and data memory types specified in the `types` array. The |
357 | | * addresses are relative to the base address for the file. |
358 | | * |
359 | | *------------------------------------------------------------------------- |
360 | | */ |
361 | | herr_t |
362 | | H5F_shared_vector_write(H5F_shared_t *f_sh, uint32_t count, H5FD_mem_t types[], haddr_t addrs[], |
363 | | size_t sizes[], const void *bufs[]) |
364 | 0 | { |
365 | 0 | herr_t ret_value = SUCCEED; |
366 | |
|
367 | 0 | FUNC_ENTER_NOAPI(FAIL) |
368 | | |
369 | | /* Sanity checks */ |
370 | 0 | assert(f_sh); |
371 | 0 | assert((types) || (count == 0)); |
372 | 0 | assert((addrs) || (count == 0)); |
373 | 0 | assert((sizes) || (count == 0)); |
374 | 0 | assert((bufs) || (count == 0)); |
375 | | |
376 | | /* |
377 | | * Note that we don't try to map global heap data to raw |
378 | | * data here, as it may become expensive to check for when |
379 | | * I/O vectors are large. This may change in the future, but, |
380 | | * for now, assume the caller has done this already. |
381 | | */ |
382 | | #ifndef NDEBUG |
383 | | for (uint32_t i = 0; i < count; i++) { |
384 | | /* Break early if H5FD_MEM_NOLIST was specified |
385 | | * since a full 'count'-sized array may not |
386 | | * have been passed for 'types' |
387 | | */ |
388 | | if (i > 0 && types[i] == H5FD_MEM_NOLIST) |
389 | | break; |
390 | | |
391 | | assert(types[i] != H5FD_MEM_GHEAP); |
392 | | } |
393 | | #endif |
394 | | |
395 | | /* Pass down to file driver layer (bypass page buffer for now) */ |
396 | 0 | if (H5FD_write_vector(f_sh->lf, count, types, addrs, sizes, bufs) < 0) |
397 | 0 | HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write through file driver failed"); |
398 | | |
399 | 0 | done: |
400 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
401 | 0 | } |
402 | | |
403 | | /*------------------------------------------------------------------------- |
404 | | * Function: H5F_flush_tagged_metadata |
405 | | * |
406 | | * Purpose: Flushes metadata with specified tag in the metadata cache |
407 | | * to disk. |
408 | | * |
409 | | * Return: Non-negative on success/Negative on failure |
410 | | * |
411 | | *------------------------------------------------------------------------- |
412 | | */ |
413 | | herr_t |
414 | | H5F_flush_tagged_metadata(H5F_t *f, haddr_t tag) |
415 | 0 | { |
416 | 0 | herr_t ret_value = SUCCEED; |
417 | |
|
418 | 0 | FUNC_ENTER_NOAPI(FAIL) |
419 | | |
420 | | /* Use tag to search for and flush associated metadata */ |
421 | 0 | if (H5AC_flush_tagged_metadata(f, tag) < 0) |
422 | 0 | HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush tagged metadata"); |
423 | | |
424 | | /* Flush and reset the accumulator */ |
425 | 0 | if (H5F__accum_reset(f->shared, true) < 0) |
426 | 0 | HGOTO_ERROR(H5E_IO, H5E_CANTRESET, FAIL, "can't reset accumulator"); |
427 | | |
428 | | /* Flush file buffers to disk. */ |
429 | 0 | if (H5FD_flush(f->shared->lf, false) < 0) |
430 | 0 | HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed"); |
431 | | |
432 | 0 | done: |
433 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
434 | 0 | } /* end H5F_flush_tagged_metadata */ |
435 | | |
436 | | /*------------------------------------------------------------------------- |
437 | | * Function: H5F__evict_cache_entries |
438 | | * |
439 | | * Purpose: To evict all cache entries except the pinned superblock entry |
440 | | * |
441 | | * Return: Non-negative on success/Negative on failure |
442 | | * |
443 | | *------------------------------------------------------------------------- |
444 | | */ |
445 | | herr_t |
446 | | H5F__evict_cache_entries(H5F_t *f) |
447 | 0 | { |
448 | 0 | herr_t ret_value = SUCCEED; |
449 | |
|
450 | 0 | FUNC_ENTER_PACKAGE |
451 | |
|
452 | 0 | assert(f); |
453 | 0 | assert(f->shared); |
454 | | |
455 | | /* Evict all except pinned entries in the cache */ |
456 | 0 | if (H5AC_evict(f) < 0) |
457 | 0 | HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, FAIL, "unable to evict all except pinned entries"); |
458 | | |
459 | | #ifndef NDEBUG |
460 | | { |
461 | | unsigned status = 0; |
462 | | uint32_t cur_num_entries; |
463 | | |
464 | | /* Retrieve status of the superblock */ |
465 | | if (H5AC_get_entry_status(f, (haddr_t)0, &status) < 0) |
466 | | HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to get entry status"); |
467 | | |
468 | | /* Verify status of the superblock entry in the cache */ |
469 | | if (!(status & H5AC_ES__IN_CACHE) || !(status & H5AC_ES__IS_PINNED)) |
470 | | HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to get entry status"); |
471 | | |
472 | | /* Get the number of cache entries */ |
473 | | if (H5AC_get_cache_size(f->shared->cache, NULL, NULL, NULL, &cur_num_entries) < 0) |
474 | | HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_get_cache_size() failed."); |
475 | | |
476 | | /* Should be the only one left in the cache (the superblock) */ |
477 | | if (cur_num_entries != 1) |
478 | | HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "number of cache entries is not correct"); |
479 | | } |
480 | | #endif /* NDEBUG */ |
481 | | |
482 | 0 | done: |
483 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
484 | 0 | } /* end H5F__evict_cache_entries() */ |
485 | | |
486 | | /*------------------------------------------------------------------------- |
487 | | * Function: H5F_get_checksums |
488 | | * |
489 | | * Purpose: Decode checksum stored in the buffer |
490 | | * Calculate checksum for the data in the buffer |
491 | | * |
492 | | * Note: Assumes that the checksum is the last data in the buffer |
493 | | * |
494 | | * Return: Non-negative on success/Negative on failure |
495 | | * |
496 | | *------------------------------------------------------------------------- |
497 | | */ |
498 | | herr_t |
499 | | H5F_get_checksums(const uint8_t *buf, size_t buf_size, uint32_t *s_chksum /*out*/, uint32_t *c_chksum /*out*/) |
500 | 0 | { |
501 | 0 | herr_t ret_value = SUCCEED; |
502 | |
|
503 | 0 | FUNC_ENTER_NOAPI_NOINIT |
504 | | |
505 | | /* Check arguments */ |
506 | 0 | assert(buf); |
507 | 0 | assert(buf_size); |
508 | | |
509 | | /* Check for buffer size smaller than H5_SIZEOF_CHKSUM */ |
510 | 0 | if (buf_size < H5_SIZEOF_CHKSUM) |
511 | 0 | HGOTO_ERROR(H5E_IO, H5E_BADVALUE, FAIL, "checksum buffer is smaller than expected"); |
512 | | |
513 | | /* Return the stored checksum */ |
514 | 0 | if (s_chksum) { |
515 | 0 | const uint8_t *chk_p; /* Pointer into raw data buffer */ |
516 | | |
517 | | /* Offset to the checksum in the buffer */ |
518 | 0 | chk_p = buf + buf_size - H5_SIZEOF_CHKSUM; |
519 | | |
520 | | /* Decode the checksum stored in the buffer */ |
521 | 0 | UINT32DECODE(chk_p, *s_chksum); |
522 | 0 | } /* end if */ |
523 | | |
524 | | /* Return the computed checksum for the buffer */ |
525 | 0 | if (c_chksum) |
526 | 0 | *c_chksum = H5_checksum_metadata(buf, buf_size - H5_SIZEOF_CHKSUM, 0); |
527 | |
|
528 | 0 | done: |
529 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
530 | 0 | } /* end H5F_get_chksums() */ |