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 | | #include "H5Omodule.h" /* This source code file is part of the H5O module */ |
14 | | |
15 | | #include "H5private.h" /* Generic Functions */ |
16 | | #include "H5Eprivate.h" /* Error handling */ |
17 | | #include "H5Fprivate.h" /* File access */ |
18 | | #include "H5HLprivate.h" /* Local Heaps */ |
19 | | #include "H5MMprivate.h" /* Memory management */ |
20 | | #include "H5Opkg.h" /* Object headers */ |
21 | | |
22 | | /* PRIVATE PROTOTYPES */ |
23 | | static void *H5O__efl_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags, unsigned *ioflags, size_t p_size, |
24 | | const uint8_t *p); |
25 | | static herr_t H5O__efl_encode(H5F_t *f, bool disable_shared, size_t H5_ATTR_UNUSED p_size, uint8_t *p, |
26 | | const void *_mesg); |
27 | | static void *H5O__efl_copy(const void *_mesg, void *_dest); |
28 | | static size_t H5O__efl_size(const H5F_t *f, bool disable_shared, const void *_mesg); |
29 | | static herr_t H5O__efl_reset(void *_mesg); |
30 | | static void *H5O__efl_copy_file(H5F_t *file_src, void *mesg_src, H5F_t *file_dst, bool *recompute_size, |
31 | | unsigned *mesg_flags, H5O_copy_t *cpy_info, void *udata); |
32 | | static herr_t H5O__efl_debug(H5F_t *f, const void *_mesg, FILE *stream, int indent, int fwidth); |
33 | | |
34 | | /* This message derives from H5O message class */ |
35 | | const H5O_msg_class_t H5O_MSG_EFL[1] = {{ |
36 | | H5O_EFL_ID, /*message id number */ |
37 | | "external file list", /*message name for debugging */ |
38 | | sizeof(H5O_efl_t), /*native message size */ |
39 | | 0, /* messages are shareable? */ |
40 | | H5O__efl_decode, /*decode message */ |
41 | | H5O__efl_encode, /*encode message */ |
42 | | H5O__efl_copy, /*copy native value */ |
43 | | H5O__efl_size, /*size of message on disk */ |
44 | | H5O__efl_reset, /*reset method */ |
45 | | NULL, /* free method */ |
46 | | NULL, /* file delete method */ |
47 | | NULL, /* link method */ |
48 | | NULL, /*set share method */ |
49 | | NULL, /*can share method */ |
50 | | NULL, /* pre copy native value to file */ |
51 | | H5O__efl_copy_file, /* copy native value to file */ |
52 | | NULL, /* post copy native value to file */ |
53 | | NULL, /* get creation index */ |
54 | | NULL, /* set creation index */ |
55 | | H5O__efl_debug /*debug the message */ |
56 | | }}; |
57 | | |
58 | 0 | #define H5O_EFL_VERSION 1 |
59 | | |
60 | | /*------------------------------------------------------------------------- |
61 | | * Function: H5O__efl_decode |
62 | | * |
63 | | * Purpose: Decode an external file list message and return a pointer to |
64 | | * the message (and some other data). |
65 | | * |
66 | | * We allow zero dimension size starting from the 1.8.7 release. |
67 | | * The dataset size of external storage can be zero. |
68 | | * |
69 | | * Return: Success: Pointer to a new message struct |
70 | | * Failure: NULL |
71 | | *------------------------------------------------------------------------- |
72 | | */ |
73 | | static void * |
74 | | H5O__efl_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, |
75 | | unsigned H5_ATTR_UNUSED *ioflags, size_t p_size, const uint8_t *p) |
76 | 0 | { |
77 | 0 | H5O_efl_t *mesg = NULL; |
78 | 0 | int version; |
79 | 0 | const uint8_t *p_end = p + p_size - 1; /* pointer to last byte in p */ |
80 | 0 | const char *s = NULL; |
81 | 0 | H5HL_t *heap = NULL; |
82 | 0 | size_t block_size; /* Size of the heap block */ |
83 | 0 | void *ret_value = NULL; /* Return value */ |
84 | |
|
85 | 0 | FUNC_ENTER_PACKAGE |
86 | | |
87 | | /* Check args */ |
88 | 0 | assert(f); |
89 | 0 | assert(p); |
90 | |
|
91 | 0 | if (NULL == (mesg = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t)))) |
92 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "memory allocation failed"); |
93 | | |
94 | | /* Version (1 byte) */ |
95 | 0 | if (H5_IS_BUFFER_OVERFLOW(p, 1, p_end)) |
96 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding"); |
97 | 0 | version = *p++; |
98 | 0 | if (version != H5O_EFL_VERSION) |
99 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for external file list message"); |
100 | | |
101 | | /* Reserved (3 bytes) */ |
102 | 0 | if (H5_IS_BUFFER_OVERFLOW(p, 3, p_end)) |
103 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding"); |
104 | 0 | p += 3; |
105 | | |
106 | | /* Number of slots (2x 2 bytes) */ |
107 | 0 | if (H5_IS_BUFFER_OVERFLOW(p, 2, p_end)) |
108 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding"); |
109 | 0 | UINT16DECODE(p, mesg->nalloc); |
110 | 0 | if (mesg->nalloc <= 0) |
111 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad number of allocated slots when parsing efl msg"); |
112 | | |
113 | 0 | if (H5_IS_BUFFER_OVERFLOW(p, 2, p_end)) |
114 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding"); |
115 | 0 | UINT16DECODE(p, mesg->nused); |
116 | 0 | if (mesg->nused > mesg->nalloc) |
117 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad number of in-use slots when parsing efl msg"); |
118 | | |
119 | | /* Heap address */ |
120 | 0 | if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_addr(f), p_end)) |
121 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding"); |
122 | 0 | H5F_addr_decode(f, &p, &(mesg->heap_addr)); |
123 | 0 | if (H5_addr_defined(mesg->heap_addr) == false) |
124 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad local heap address when parsing efl msg"); |
125 | | |
126 | | /* Decode the file list */ |
127 | 0 | mesg->slot = (H5O_efl_entry_t *)H5MM_calloc(mesg->nalloc * sizeof(H5O_efl_entry_t)); |
128 | 0 | if (NULL == mesg->slot) |
129 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "memory allocation failed"); |
130 | | |
131 | 0 | if (NULL == (heap = H5HL_protect(f, mesg->heap_addr, H5AC__READ_ONLY_FLAG))) |
132 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to protect local heap"); |
133 | | |
134 | | #ifdef H5O_DEBUG |
135 | | /* Verify that the name at offset 0 in the local heap is the empty string */ |
136 | | s = (const char *)H5HL_offset_into(heap, 0); |
137 | | if (s == NULL) |
138 | | HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "could not obtain pointer into local heap"); |
139 | | if (*s != '\0') |
140 | | HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "entry at offset 0 in local heap not an empty string"); |
141 | | #endif |
142 | | |
143 | | /* Get the size of the heap block */ |
144 | 0 | block_size = H5HL_heap_get_size(heap); |
145 | |
|
146 | 0 | for (size_t u = 0; u < mesg->nused; u++) { |
147 | |
|
148 | 0 | hsize_t offset = 0; |
149 | | |
150 | | /* Name */ |
151 | 0 | if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_size(f), p_end)) |
152 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding"); |
153 | 0 | H5F_DECODE_LENGTH(f, p, mesg->slot[u].name_offset); |
154 | | |
155 | 0 | if ((s = (const char *)H5HL_offset_into(heap, mesg->slot[u].name_offset)) == NULL) |
156 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to get external file name"); |
157 | 0 | if (*s == '\0') |
158 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "invalid external file name"); |
159 | 0 | mesg->slot[u].name = H5MM_strndup(s, (block_size - mesg->slot[u].name_offset)); |
160 | 0 | if (mesg->slot[u].name == NULL) |
161 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "string duplication failed"); |
162 | | |
163 | | /* File offset */ |
164 | 0 | if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_size(f), p_end)) |
165 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding"); |
166 | 0 | H5F_DECODE_LENGTH(f, p, offset); /* Decode into an hsize_t to avoid sign warnings */ |
167 | 0 | mesg->slot[u].offset = (HDoff_t)offset; |
168 | | |
169 | | /* Size */ |
170 | 0 | if (H5_IS_BUFFER_OVERFLOW(p, H5F_sizeof_size(f), p_end)) |
171 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "ran off end of input buffer while decoding"); |
172 | 0 | H5F_DECODE_LENGTH(f, p, mesg->slot[u].size); |
173 | 0 | } |
174 | | |
175 | 0 | if (H5HL_unprotect(heap) < 0) |
176 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to unprotect local heap"); |
177 | | |
178 | | /* Set return value */ |
179 | 0 | ret_value = mesg; |
180 | |
|
181 | 0 | done: |
182 | 0 | if (ret_value == NULL) { |
183 | 0 | if (mesg != NULL) { |
184 | 0 | if (mesg->slot != NULL) { |
185 | 0 | for (size_t u = 0; u < mesg->nused; u++) |
186 | 0 | H5MM_xfree(mesg->slot[u].name); |
187 | 0 | H5MM_xfree(mesg->slot); |
188 | 0 | } |
189 | 0 | H5MM_xfree(mesg); |
190 | 0 | } |
191 | 0 | if (heap != NULL) |
192 | 0 | if (H5HL_unprotect(heap) < 0) |
193 | 0 | HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to unprotect local heap"); |
194 | 0 | } |
195 | |
|
196 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
197 | 0 | } /* end H5O__efl_decode() */ |
198 | | |
199 | | /*------------------------------------------------------------------------- |
200 | | * Function: H5O__efl_encode |
201 | | * |
202 | | * Purpose: Encodes a message. |
203 | | * |
204 | | * Return: Non-negative on success/Negative on failure |
205 | | * |
206 | | *------------------------------------------------------------------------- |
207 | | */ |
208 | | static herr_t |
209 | | H5O__efl_encode(H5F_t *f, bool H5_ATTR_UNUSED disable_shared, size_t H5_ATTR_UNUSED p_size, uint8_t *p, |
210 | | const void *_mesg) |
211 | 0 | { |
212 | 0 | const H5O_efl_t *mesg = (const H5O_efl_t *)_mesg; |
213 | 0 | size_t u; /* Local index variable */ |
214 | |
|
215 | 0 | FUNC_ENTER_PACKAGE_NOERR |
216 | | |
217 | | /* check args */ |
218 | 0 | assert(f); |
219 | 0 | assert(mesg); |
220 | 0 | assert(p); |
221 | | |
222 | | /* Version */ |
223 | 0 | *p++ = H5O_EFL_VERSION; |
224 | | |
225 | | /* Reserved */ |
226 | 0 | *p++ = 0; |
227 | 0 | *p++ = 0; |
228 | 0 | *p++ = 0; |
229 | | |
230 | | /* Number of slots */ |
231 | 0 | assert(mesg->nalloc > 0); |
232 | 0 | UINT16ENCODE(p, mesg->nused); /*yes, twice*/ |
233 | 0 | assert(mesg->nused > 0 && mesg->nused <= mesg->nalloc); |
234 | 0 | UINT16ENCODE(p, mesg->nused); |
235 | | |
236 | | /* Heap address */ |
237 | 0 | assert(H5_addr_defined(mesg->heap_addr)); |
238 | 0 | H5F_addr_encode(f, &p, mesg->heap_addr); |
239 | | |
240 | | /* Encode file list */ |
241 | 0 | for (u = 0; u < mesg->nused; u++) { |
242 | | /* |
243 | | * The name should have been added to the heap when the dataset was |
244 | | * created. |
245 | | */ |
246 | 0 | assert(mesg->slot[u].name_offset); |
247 | 0 | H5F_ENCODE_LENGTH(f, p, mesg->slot[u].name_offset); |
248 | 0 | H5F_ENCODE_LENGTH(f, p, (hsize_t)mesg->slot[u].offset); |
249 | 0 | H5F_ENCODE_LENGTH(f, p, mesg->slot[u].size); |
250 | 0 | } /* end for */ |
251 | | |
252 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
253 | 0 | } /* end H5O__efl_encode() */ |
254 | | |
255 | | /*------------------------------------------------------------------------- |
256 | | * Function: H5O__efl_copy |
257 | | * |
258 | | * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if |
259 | | * necessary. |
260 | | * |
261 | | * Return: Success: Ptr to _DEST |
262 | | * |
263 | | * Failure: NULL |
264 | | * |
265 | | *------------------------------------------------------------------------- |
266 | | */ |
267 | | static void * |
268 | | H5O__efl_copy(const void *_mesg, void *_dest) |
269 | 93 | { |
270 | 93 | const H5O_efl_t *mesg = (const H5O_efl_t *)_mesg; |
271 | 93 | H5O_efl_t *dest = (H5O_efl_t *)_dest; |
272 | 93 | size_t u; /* Local index variable */ |
273 | 93 | bool slot_allocated = false; /* Flag to indicate that dynamic allocation has begun */ |
274 | 93 | void *ret_value = NULL; /* Return value */ |
275 | | |
276 | 93 | FUNC_ENTER_PACKAGE |
277 | | |
278 | | /* check args */ |
279 | 93 | assert(mesg); |
280 | | |
281 | | /* Allocate destination message, if necessary */ |
282 | 93 | if (!dest && NULL == (dest = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t)))) |
283 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "can't allocate efl message"); |
284 | | |
285 | | /* copy */ |
286 | 93 | *dest = *mesg; |
287 | | |
288 | | /* Deep copy allocated information */ |
289 | 93 | if (dest->nalloc > 0) { |
290 | 0 | if (NULL == (dest->slot = (H5O_efl_entry_t *)H5MM_calloc(dest->nalloc * sizeof(H5O_efl_entry_t)))) |
291 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "can't allocate efl message slots"); |
292 | 0 | slot_allocated = true; |
293 | 0 | for (u = 0; u < mesg->nused; u++) { |
294 | 0 | dest->slot[u] = mesg->slot[u]; |
295 | 0 | if (NULL == (dest->slot[u].name = H5MM_xstrdup(mesg->slot[u].name))) |
296 | 0 | HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "can't allocate efl message slot name"); |
297 | 0 | } /* end for */ |
298 | 0 | } /* end if */ |
299 | | |
300 | | /* Set return value */ |
301 | 93 | ret_value = dest; |
302 | | |
303 | 93 | done: |
304 | 93 | if (NULL == ret_value) { |
305 | 0 | if (slot_allocated) { |
306 | 0 | for (u = 0; u < dest->nused; u++) |
307 | 0 | if (dest->slot[u].name != NULL && dest->slot[u].name != mesg->slot[u].name) |
308 | 0 | dest->slot[u].name = (char *)H5MM_xfree(dest->slot[u].name); |
309 | 0 | dest->slot = (H5O_efl_entry_t *)H5MM_xfree(dest->slot); |
310 | 0 | } /* end if */ |
311 | 0 | if (NULL == _dest) |
312 | 0 | dest = (H5O_efl_t *)H5MM_xfree(dest); |
313 | 0 | } /* end if */ |
314 | | |
315 | 93 | FUNC_LEAVE_NOAPI(ret_value) |
316 | 93 | } /* end H5O__efl_copy() */ |
317 | | |
318 | | /*------------------------------------------------------------------------- |
319 | | * Function: H5O__efl_size |
320 | | * |
321 | | * Purpose: Returns the size of the raw message in bytes not counting the |
322 | | * message type or size fields, but only the data fields. This |
323 | | * function doesn't take into account message alignment. This |
324 | | * function doesn't count unused slots. |
325 | | * |
326 | | * Return: Success: Message data size in bytes. |
327 | | * |
328 | | * Failure: 0 |
329 | | * |
330 | | *------------------------------------------------------------------------- |
331 | | */ |
332 | | static size_t |
333 | | H5O__efl_size(const H5F_t *f, bool H5_ATTR_UNUSED disable_shared, const void *_mesg) |
334 | 0 | { |
335 | 0 | const H5O_efl_t *mesg = (const H5O_efl_t *)_mesg; |
336 | 0 | size_t ret_value = 0; |
337 | |
|
338 | 0 | FUNC_ENTER_PACKAGE_NOERR |
339 | | |
340 | | /* check args */ |
341 | 0 | assert(f); |
342 | 0 | assert(mesg); |
343 | |
|
344 | 0 | ret_value = (size_t)H5F_SIZEOF_ADDR(f) + /*heap address */ |
345 | 0 | 2 + /*slots allocated*/ |
346 | 0 | 2 + /*num slots used*/ |
347 | 0 | 4 + /*reserved */ |
348 | 0 | mesg->nused * ((size_t)H5F_SIZEOF_SIZE(f) + /*name offset */ |
349 | 0 | (size_t)H5F_SIZEOF_SIZE(f) + /*file offset */ |
350 | 0 | (size_t)H5F_SIZEOF_SIZE(f)); /*file size */ |
351 | |
|
352 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
353 | 0 | } /* end H5O__efl_size() */ |
354 | | |
355 | | /*------------------------------------------------------------------------- |
356 | | * Function: H5O__efl_reset |
357 | | * |
358 | | * Purpose: Frees internal pointers and resets the message to an |
359 | | * initial state. |
360 | | * |
361 | | * Return: Non-negative on success/Negative on failure |
362 | | * |
363 | | *------------------------------------------------------------------------- |
364 | | */ |
365 | | static herr_t |
366 | | H5O__efl_reset(void *_mesg) |
367 | 145 | { |
368 | 145 | H5O_efl_t *mesg = (H5O_efl_t *)_mesg; |
369 | 145 | size_t u; /* Local index variable */ |
370 | | |
371 | 145 | FUNC_ENTER_PACKAGE_NOERR |
372 | | |
373 | | /* check args */ |
374 | 145 | assert(mesg); |
375 | | |
376 | | /* reset */ |
377 | 145 | if (mesg->slot) { |
378 | 0 | for (u = 0; u < mesg->nused; u++) { |
379 | 0 | mesg->slot[u].name = (char *)H5MM_xfree(mesg->slot[u].name); |
380 | 0 | mesg->slot[u].name_offset = 0; |
381 | 0 | } /* end for */ |
382 | 0 | mesg->slot = (H5O_efl_entry_t *)H5MM_xfree(mesg->slot); |
383 | 0 | } /* end if */ |
384 | 145 | mesg->heap_addr = HADDR_UNDEF; |
385 | 145 | mesg->nused = mesg->nalloc = 0; |
386 | | |
387 | 145 | FUNC_LEAVE_NOAPI(SUCCEED) |
388 | 145 | } /* end H5O__efl_reset() */ |
389 | | |
390 | | /*------------------------------------------------------------------------- |
391 | | * Function: H5O_efl_total_size |
392 | | * |
393 | | * Purpose: Query the total size of the external file list by summing |
394 | | * the sizes of all of the files. |
395 | | * |
396 | | * Return: Non-negative on success/Negative on failure |
397 | | * |
398 | | *------------------------------------------------------------------------- |
399 | | */ |
400 | | herr_t |
401 | | H5O_efl_total_size(const H5O_efl_t *efl, hsize_t *size) |
402 | 0 | { |
403 | 0 | hsize_t total_size = 0, tmp; |
404 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
405 | |
|
406 | 0 | FUNC_ENTER_NOAPI(FAIL) |
407 | |
|
408 | 0 | if (efl->nused > 0 && H5O_EFL_UNLIMITED == efl->slot[efl->nused - 1].size) |
409 | 0 | *size = H5O_EFL_UNLIMITED; |
410 | 0 | else { |
411 | 0 | size_t u; /* Local index variable */ |
412 | |
|
413 | 0 | for (u = 0; u < efl->nused; u++, total_size = tmp) { |
414 | 0 | tmp = total_size + efl->slot[u].size; |
415 | 0 | if (tmp < total_size) |
416 | 0 | HGOTO_ERROR(H5E_EFL, H5E_OVERFLOW, FAIL, "total external storage size overflowed"); |
417 | 0 | } /* end for */ |
418 | | |
419 | | /* Set the size to return */ |
420 | 0 | *size = total_size; |
421 | 0 | } /* end else */ |
422 | | |
423 | 0 | done: |
424 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
425 | 0 | } /* end H5O_efl_total_size() */ |
426 | | |
427 | | /*------------------------------------------------------------------------- |
428 | | * Function: H5O__efl_copy_file |
429 | | * |
430 | | * Purpose: Copies an efl message from _MESG to _DEST in file |
431 | | * |
432 | | * Return: Success: Ptr to _DEST |
433 | | * |
434 | | * Failure: NULL |
435 | | * |
436 | | *------------------------------------------------------------------------- |
437 | | */ |
438 | | static void * |
439 | | H5O__efl_copy_file(H5F_t H5_ATTR_UNUSED *file_src, void *mesg_src, H5F_t *file_dst, |
440 | | bool H5_ATTR_UNUSED *recompute_size, unsigned H5_ATTR_UNUSED *mesg_flags, |
441 | | H5O_copy_t H5_ATTR_UNUSED *cpy_info, void H5_ATTR_UNUSED *_udata) |
442 | 0 | { |
443 | 0 | H5O_efl_t *efl_src = (H5O_efl_t *)mesg_src; |
444 | 0 | H5O_efl_t *efl_dst = NULL; |
445 | 0 | H5HL_t *heap = NULL; /* Pointer to local heap for EFL file names */ |
446 | 0 | size_t idx, size, name_offset, heap_size; |
447 | 0 | void *ret_value = NULL; /* Return value */ |
448 | |
|
449 | 0 | FUNC_ENTER_PACKAGE_TAG(H5AC__COPIED_TAG) |
450 | | |
451 | | /* check args */ |
452 | 0 | assert(efl_src); |
453 | 0 | assert(file_dst); |
454 | | |
455 | | /* Allocate space for the destination efl */ |
456 | 0 | if (NULL == (efl_dst = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t)))) |
457 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
458 | | |
459 | | /* Copy the "top level" information */ |
460 | 0 | H5MM_memcpy(efl_dst, efl_src, sizeof(H5O_efl_t)); |
461 | | |
462 | | /* Determine size needed for destination heap */ |
463 | 0 | heap_size = H5HL_ALIGN(1); /* "empty" name */ |
464 | 0 | for (idx = 0; idx < efl_src->nused; idx++) |
465 | 0 | heap_size += H5HL_ALIGN(strlen(efl_src->slot[idx].name) + 1); |
466 | | |
467 | | /* Create name heap */ |
468 | 0 | if (H5HL_create(file_dst, heap_size, &efl_dst->heap_addr /*out*/) < 0) |
469 | 0 | HGOTO_ERROR(H5E_EFL, H5E_CANTINIT, NULL, "can't create heap"); |
470 | | |
471 | | /* Pin the heap down in memory */ |
472 | 0 | if (NULL == (heap = H5HL_protect(file_dst, efl_dst->heap_addr, H5AC__NO_FLAGS_SET))) |
473 | 0 | HGOTO_ERROR(H5E_EFL, H5E_PROTECT, NULL, "unable to protect EFL file name heap"); |
474 | | |
475 | | /* Insert "empty" name first */ |
476 | 0 | if (H5HL_insert(file_dst, heap, (size_t)1, "", &name_offset) < 0) |
477 | 0 | HGOTO_ERROR(H5E_EFL, H5E_CANTINSERT, NULL, "can't insert file name into heap"); |
478 | 0 | assert(0 == name_offset); |
479 | | |
480 | | /* allocate array of external file entries */ |
481 | 0 | if (efl_src->nalloc > 0) { |
482 | 0 | size = efl_src->nalloc * sizeof(H5O_efl_entry_t); |
483 | 0 | if ((efl_dst->slot = (H5O_efl_entry_t *)H5MM_calloc(size)) == NULL) |
484 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
485 | | |
486 | | /* copy content from the source. Need to update later */ |
487 | 0 | H5MM_memcpy(efl_dst->slot, efl_src->slot, size); |
488 | 0 | } /* end if */ |
489 | | |
490 | | /* copy the name from the source */ |
491 | 0 | for (idx = 0; idx < efl_src->nused; idx++) { |
492 | 0 | efl_dst->slot[idx].name = H5MM_xstrdup(efl_src->slot[idx].name); |
493 | 0 | if (H5HL_insert(file_dst, heap, strlen(efl_dst->slot[idx].name) + 1, efl_dst->slot[idx].name, |
494 | 0 | &(efl_dst->slot[idx].name_offset)) < 0) |
495 | 0 | HGOTO_ERROR(H5E_EFL, H5E_CANTINSERT, NULL, "can't insert file name into heap"); |
496 | 0 | } |
497 | | |
498 | | /* Set return value */ |
499 | 0 | ret_value = efl_dst; |
500 | |
|
501 | 0 | done: |
502 | | /* Release resources */ |
503 | 0 | if (heap && H5HL_unprotect(heap) < 0) |
504 | 0 | HDONE_ERROR(H5E_EFL, H5E_PROTECT, NULL, "unable to unprotect EFL file name heap"); |
505 | 0 | if (!ret_value) |
506 | 0 | if (efl_dst) |
507 | 0 | H5MM_xfree(efl_dst); |
508 | |
|
509 | 0 | FUNC_LEAVE_NOAPI_TAG(ret_value) |
510 | 0 | } /* end H5O__efl_copy_file() */ |
511 | | |
512 | | /*------------------------------------------------------------------------- |
513 | | * Function: H5O__efl_debug |
514 | | * |
515 | | * Purpose: Prints debugging info for a message. |
516 | | * |
517 | | * Return: Non-negative on success/Negative on failure |
518 | | * |
519 | | *------------------------------------------------------------------------- |
520 | | */ |
521 | | static herr_t |
522 | | H5O__efl_debug(H5F_t H5_ATTR_UNUSED *f, const void *_mesg, FILE *stream, int indent, int fwidth) |
523 | 0 | { |
524 | 0 | const H5O_efl_t *mesg = (const H5O_efl_t *)_mesg; |
525 | 0 | size_t u; |
526 | |
|
527 | 0 | FUNC_ENTER_PACKAGE_NOERR |
528 | | |
529 | | /* check args */ |
530 | 0 | assert(f); |
531 | 0 | assert(mesg); |
532 | 0 | assert(stream); |
533 | 0 | assert(indent >= 0); |
534 | 0 | assert(fwidth >= 0); |
535 | |
|
536 | 0 | fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth, "Heap address:", mesg->heap_addr); |
537 | |
|
538 | 0 | fprintf(stream, "%*s%-*s %zu/%zu\n", indent, "", fwidth, "Slots used/allocated:", mesg->nused, |
539 | 0 | mesg->nalloc); |
540 | |
|
541 | 0 | for (u = 0; u < mesg->nused; u++) { |
542 | 0 | char buf[64]; |
543 | |
|
544 | 0 | snprintf(buf, sizeof(buf), "File %zu", u); |
545 | 0 | fprintf(stream, "%*s%s:\n", indent, "", buf); |
546 | |
|
547 | 0 | fprintf(stream, "%*s%-*s \"%s\"\n", indent + 3, "", MAX(fwidth - 3, 0), "Name:", mesg->slot[u].name); |
548 | |
|
549 | 0 | fprintf(stream, "%*s%-*s %zu\n", indent + 3, "", MAX(fwidth - 3, 0), |
550 | 0 | "Name offset:", mesg->slot[u].name_offset); |
551 | |
|
552 | 0 | fprintf(stream, "%*s%-*s %" PRIdMAX "\n", indent + 3, "", MAX(fwidth - 3, 0), |
553 | 0 | "Offset of data in file:", (intmax_t)(mesg->slot[u].offset)); |
554 | |
|
555 | 0 | fprintf(stream, "%*s%-*s %" PRIuHSIZE "\n", indent + 3, "", MAX(fwidth - 3, 0), |
556 | 0 | "Bytes reserved for data:", (mesg->slot[u].size)); |
557 | 0 | } /* end for */ |
558 | |
|
559 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
560 | 0 | } /* end H5O__efl_debug() */ |