1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Copyright by The HDF Group. *
3 * Copyright by the Board of Trustees of the University of Illinois. *
4 * All rights reserved. *
5 * *
6 * This file is part of HDF5. The full HDF5 copyright notice, including *
7 * terms governing use, modification, and redistribution, is contained in *
8 * the COPYING file, which can be found at the root of the source code *
9 * distribution tree, or in https://www.hdfgroup.org/licenses. *
10 * If you do not have access to either file, you may request a copy from *
11 * help@hdfgroup.org. *
12 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13
14 /* Programmer: Robb Matzke
15 * Wednesday, September 30, 1998
16 *
17 * Purpose: The fill message indicates a bit pattern to use for
18 * uninitialized data points of a dataset.
19 */
20
21 #include "H5Omodule.h" /* This source code file is part of the H5O module */
22
23 #include "H5private.h" /* Generic Functions */
24 #include "H5Dprivate.h" /* Datasets */
25 #include "H5Eprivate.h" /* Error handling */
26 #include "H5FLprivate.h" /* Free Lists */
27 #include "H5Iprivate.h" /* IDs */
28 #include "H5MMprivate.h" /* Memory management */
29 #include "H5Opkg.h" /* Object headers */
30 #include "H5Pprivate.h" /* Property lists */
31 #include "H5Sprivate.h" /* Dataspaces */
32
33 static void * H5O__fill_old_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags, unsigned *ioflags,
34 size_t p_size, const uint8_t *p);
35 static herr_t H5O__fill_old_encode(H5F_t *f, uint8_t *p, const void *_mesg);
36 static size_t H5O__fill_old_size(const H5F_t *f, const void *_mesg);
37 static void * H5O__fill_new_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags, unsigned *ioflags,
38 size_t p_size, const uint8_t *p);
39 static herr_t H5O__fill_new_encode(H5F_t *f, uint8_t *p, const void *_mesg);
40 static size_t H5O__fill_new_size(const H5F_t *f, const void *_mesg);
41 static void * H5O__fill_copy(const void *_mesg, void *_dest);
42 static herr_t H5O__fill_reset(void *_mesg);
43 static herr_t H5O__fill_free(void *_mesg);
44 static herr_t H5O__fill_pre_copy_file(H5F_t *file_src, const void *mesg_src, hbool_t *deleted,
45 const H5O_copy_t *cpy_info, void *udata);
46 static herr_t H5O__fill_debug(H5F_t *f, const void *_mesg, FILE *stream, int indent, int fwidth);
47
48 /* Set up & include shared message "interface" info */
49 #define H5O_SHARED_TYPE H5O_MSG_FILL
50 #define H5O_SHARED_DECODE H5O__fill_shared_decode
51 #define H5O_SHARED_DECODE_REAL H5O__fill_old_decode
52 #define H5O_SHARED_ENCODE H5O__fill_shared_encode
53 #define H5O_SHARED_ENCODE_REAL H5O__fill_old_encode
54 #define H5O_SHARED_SIZE H5O__fill_shared_size
55 #define H5O_SHARED_SIZE_REAL H5O__fill_old_size
56 #define H5O_SHARED_DELETE H5O__fill_shared_delete
57 #undef H5O_SHARED_DELETE_REAL
58 #define H5O_SHARED_LINK H5O__fill_shared_link
59 #undef H5O_SHARED_LINK_REAL
60 #define H5O_SHARED_COPY_FILE H5O__fill_shared_copy_file
61 #undef H5O_SHARED_COPY_FILE_REAL
62 #define H5O_SHARED_POST_COPY_FILE H5O__fill_shared_post_copy_file
63 #undef H5O_SHARED_POST_COPY_FILE_REAL
64 #undef H5O_SHARED_POST_COPY_FILE_UPD
65 #define H5O_SHARED_DEBUG H5O__fill_shared_debug
66 #define H5O_SHARED_DEBUG_REAL H5O__fill_debug
67 #include "H5Oshared.h" /* Shared Object Header Message Callbacks */
68
69 /* Set up & include shared message "interface" info */
70 /* (Kludgy 'undef's in order to re-include the H5Oshared.h header) */
71 #undef H5O_SHARED_TYPE
72 #define H5O_SHARED_TYPE H5O_MSG_FILL_NEW
73 #undef H5O_SHARED_DECODE
74 #define H5O_SHARED_DECODE H5O__fill_new_shared_decode
75 #undef H5O_SHARED_DECODE_REAL
76 #define H5O_SHARED_DECODE_REAL H5O__fill_new_decode
77 #undef H5O_SHARED_ENCODE
78 #define H5O_SHARED_ENCODE H5O__fill_new_shared_encode
79 #undef H5O_SHARED_ENCODE_REAL
80 #define H5O_SHARED_ENCODE_REAL H5O__fill_new_encode
81 #undef H5O_SHARED_SIZE
82 #define H5O_SHARED_SIZE H5O__fill_new_shared_size
83 #undef H5O_SHARED_SIZE_REAL
84 #define H5O_SHARED_SIZE_REAL H5O__fill_new_size
85 #undef H5O_SHARED_DELETE
86 #define H5O_SHARED_DELETE H5O__fill_new_shared_delete
87 #undef H5O_SHARED_DELETE_REAL
88 #undef H5O_SHARED_LINK
89 #define H5O_SHARED_LINK H5O__fill_new_shared_link
90 #undef H5O_SHARED_LINK_REAL
91 #undef H5O_SHARED_COPY_FILE
92 #define H5O_SHARED_COPY_FILE H5O__fill_new_shared_copy_file
93 #undef H5O_SHARED_COPY_FILE_REAL
94 #undef H5O_SHARED_POST_COPY_FILE
95 #define H5O_SHARED_POST_COPY_FILE H5O__fill_new_shared_post_copy_file
96 #undef H5O_SHARED_POST_COPY_FILE_REAL
97 #undef H5O_SHARED_POST_COPY_FILE_UPD
98 #undef H5O_SHARED_DEBUG
99 #define H5O_SHARED_DEBUG H5O__fill_new_shared_debug
100 #undef H5O_SHARED_DEBUG_REAL
101 #define H5O_SHARED_DEBUG_REAL H5O__fill_debug
102 #undef H5Oshared_H
103 #include "H5Oshared.h" /* Shared Object Header Message Callbacks */
104
105 /* This message derives from H5O message class, for old fill value before version 1.5 */
106 const H5O_msg_class_t H5O_MSG_FILL[1] = {{
107 H5O_FILL_ID, /*message id number */
108 "fill", /*message name for debugging */
109 sizeof(H5O_fill_t), /*native message size */
110 H5O_SHARE_IS_SHARABLE | H5O_SHARE_IN_OHDR, /* messages are sharable? */
111 H5O__fill_shared_decode, /*decode message */
112 H5O__fill_shared_encode, /*encode message */
113 H5O__fill_copy, /*copy the native value */
114 H5O__fill_shared_size, /*raw message size */
115 H5O__fill_reset, /*free internal memory */
116 H5O__fill_free, /* free method */
117 H5O__fill_shared_delete, /* file delete method */
118 H5O__fill_shared_link, /* link method */
119 NULL, /* set share method */
120 NULL, /*can share method */
121 H5O__fill_pre_copy_file, /* pre copy native value to file */
122 H5O__fill_shared_copy_file, /* copy native value to file */
123 H5O__fill_shared_post_copy_file, /* post copy native value to file */
124 NULL, /* get creation index */
125 NULL, /* set creation index */
126 H5O__fill_shared_debug /*debug the message */
127 }};
128
129 /* This message derives from H5O message class, for new fill value after version 1.4 */
130 const H5O_msg_class_t H5O_MSG_FILL_NEW[1] = {{
131 H5O_FILL_NEW_ID, /*message id number */
132 "fill_new", /*message name for debugging */
133 sizeof(H5O_fill_t), /*native message size */
134 H5O_SHARE_IS_SHARABLE | H5O_SHARE_IN_OHDR, /* messages are sharable? */
135 H5O__fill_new_shared_decode, /*decode message */
136 H5O__fill_new_shared_encode, /*encode message */
137 H5O__fill_copy, /*copy the native value */
138 H5O__fill_new_shared_size, /*raw message size */
139 H5O__fill_reset, /*free internal memory */
140 H5O__fill_free, /* free method */
141 H5O__fill_new_shared_delete, /* file delete method */
142 H5O__fill_new_shared_link, /* link method */
143 NULL, /* set share method */
144 NULL, /*can share method */
145 H5O__fill_pre_copy_file, /* pre copy native value to file */
146 H5O__fill_new_shared_copy_file, /* copy native value to file */
147 H5O__fill_new_shared_post_copy_file, /* post copy native value to file */
148 NULL, /* get creation index */
149 NULL, /* set creation index */
150 H5O__fill_new_shared_debug /*debug the message */
151 }};
152
153 /* Format version bounds for fill value */
154 const unsigned H5O_fill_ver_bounds[] = {
155 H5O_FILL_VERSION_1, /* H5F_LIBVER_EARLIEST */
156 H5O_FILL_VERSION_3, /* H5F_LIBVER_V18 */
157 H5O_FILL_VERSION_3, /* H5F_LIBVER_V110 */
158 H5O_FILL_VERSION_LATEST /* H5F_LIBVER_LATEST */
159 };
160
161 /* Masks, shift values & flags for fill value message */
162 #define H5O_FILL_MASK_ALLOC_TIME 0x03
163 #define H5O_FILL_SHIFT_ALLOC_TIME 0
164 #define H5O_FILL_MASK_FILL_TIME 0x03
165 #define H5O_FILL_SHIFT_FILL_TIME 2
166 #define H5O_FILL_FLAG_UNDEFINED_VALUE 0x10
167 #define H5O_FILL_FLAG_HAVE_VALUE 0x20
168 #define H5O_FILL_FLAGS_ALL \
169 (H5O_FILL_MASK_ALLOC_TIME | (H5O_FILL_MASK_FILL_TIME << H5O_FILL_SHIFT_FILL_TIME) | \
170 H5O_FILL_FLAG_UNDEFINED_VALUE | H5O_FILL_FLAG_HAVE_VALUE)
171
172 /* Declare a free list to manage the H5O_fill_t struct */
173 H5FL_DEFINE(H5O_fill_t);
174
175 /* Declare extern the free list to manage blocks of type conversion data */
176 H5FL_BLK_EXTERN(type_conv);
177
178 /*-------------------------------------------------------------------------
179 * Function: H5O__fill_new_decode
180 *
181 * Purpose: Decode a new fill value message. The new fill value
182 * message is fill value plus space allocation time and
183 * fill value writing time and whether fill value is defined.
184 *
185 * Return: Success: Ptr to new message in native struct.
186 * Failure: NULL
187 *
188 * Programmer: Raymond Lu
189 * Feb 26, 2002
190 *
191 *-------------------------------------------------------------------------
192 */
193 static void *
H5O__fill_new_decode(H5F_t H5_ATTR_UNUSED * f,H5O_t H5_ATTR_UNUSED * open_oh,unsigned H5_ATTR_UNUSED mesg_flags,unsigned H5_ATTR_UNUSED * ioflags,size_t p_size,const uint8_t * p)194 H5O__fill_new_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh,
195 unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, size_t p_size,
196 const uint8_t *p)
197 {
198 H5O_fill_t * fill = NULL;
199 const uint8_t *p_end = p + p_size - 1; /* End of the p buffer */
200 void * ret_value = NULL; /* Return value */
201
202 FUNC_ENTER_STATIC
203
204 HDassert(f);
205 HDassert(p);
206
207 if (NULL == (fill = H5FL_CALLOC(H5O_fill_t)))
208 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value message")
209
210 /* Version */
211 fill->version = *p++;
212 if (fill->version < H5O_FILL_VERSION_1 || fill->version > H5O_FILL_VERSION_LATEST)
213 HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for fill value message")
214
215 /* Decode each version */
216 if (fill->version < H5O_FILL_VERSION_3) {
217 /* Space allocation time */
218 fill->alloc_time = (H5D_alloc_time_t)*p++;
219
220 /* Fill value write time */
221 fill->fill_time = (H5D_fill_time_t)*p++;
222
223 /* Whether fill value is defined */
224 fill->fill_defined = *p++;
225
226 /* Only decode fill value information if one is defined */
227 if (fill->fill_defined) {
228 INT32DECODE(p, fill->size);
229 if (fill->size > 0) {
230 H5_CHECK_OVERFLOW(fill->size, ssize_t, size_t);
231
232 /* Ensure that fill size doesn't exceed buffer size, due to possible data corruption */
233 if (p + fill->size - 1 > p_end)
234 HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "fill size exceeds buffer size")
235
236 if (NULL == (fill->buf = H5MM_malloc((size_t)fill->size)))
237 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value")
238 H5MM_memcpy(fill->buf, p, (size_t)fill->size);
239 } /* end if */
240 } /* end if */
241 else
242 fill->size = (-1);
243 } /* end if */
244 else {
245 unsigned flags; /* Status flags */
246
247 /* Flags */
248 flags = *p++;
249
250 /* Check for unknown flags */
251 if (flags & (unsigned)~H5O_FILL_FLAGS_ALL)
252 HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unknown flag for fill value message")
253
254 /* Space allocation time */
255 fill->alloc_time =
256 (H5D_alloc_time_t)((flags >> H5O_FILL_SHIFT_ALLOC_TIME) & H5O_FILL_MASK_ALLOC_TIME);
257
258 /* Fill value write time */
259 fill->fill_time = (H5D_fill_time_t)((flags >> H5O_FILL_SHIFT_FILL_TIME) & H5O_FILL_MASK_FILL_TIME);
260
261 /* Check for undefined fill value */
262 if (flags & H5O_FILL_FLAG_UNDEFINED_VALUE) {
263 /* Sanity check */
264 HDassert(!(flags & H5O_FILL_FLAG_HAVE_VALUE));
265
266 /* Set value for "undefined" fill value */
267 fill->size = (-1);
268 } /* end if */
269 else if (flags & H5O_FILL_FLAG_HAVE_VALUE) {
270 /* Fill value size */
271 UINT32DECODE(p, fill->size);
272
273 /* Fill value */
274 H5_CHECK_OVERFLOW(fill->size, ssize_t, size_t);
275 if (NULL == (fill->buf = H5MM_malloc((size_t)fill->size)))
276 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value")
277 H5MM_memcpy(fill->buf, p, (size_t)fill->size);
278
279 /* Set the "defined" flag */
280 fill->fill_defined = TRUE;
281 } /* end else */
282 else
283 /* Set the "defined" flag */
284 fill->fill_defined = TRUE;
285 } /* end else */
286
287 /* Set return value */
288 ret_value = (void *)fill;
289
290 done:
291 if (!ret_value && fill) {
292 if (fill->buf)
293 H5MM_xfree(fill->buf);
294 fill = H5FL_FREE(H5O_fill_t, fill);
295 } /* end if */
296
297 FUNC_LEAVE_NOAPI(ret_value)
298 } /* end H5O__fill_new_decode() */
299
300 /*-------------------------------------------------------------------------
301 * Function: H5O__fill_old_decode
302 *
303 * Purpose: Decode an old fill value message.
304 *
305 * Return: Success: Ptr to new message in native struct.
306 * Failure: NULL
307 *
308 * Programmer: Robb Matzke
309 * Wednesday, September 30, 1998
310 *
311 *-------------------------------------------------------------------------
312 */
313 static void *
H5O__fill_old_decode(H5F_t * f,H5O_t * open_oh,unsigned H5_ATTR_UNUSED mesg_flags,unsigned H5_ATTR_UNUSED * ioflags,size_t p_size,const uint8_t * p)314 H5O__fill_old_decode(H5F_t *f, H5O_t *open_oh, unsigned H5_ATTR_UNUSED mesg_flags,
315 unsigned H5_ATTR_UNUSED *ioflags, size_t p_size, const uint8_t *p)
316 {
317 H5O_fill_t * fill = NULL; /* Decoded fill value message */
318 htri_t exists = FALSE;
319 H5T_t * dt = NULL;
320 const uint8_t *p_end = p + p_size - 1; /* End of the p buffer */
321 void * ret_value = NULL; /* Return value */
322
323 FUNC_ENTER_STATIC
324
325 HDassert(f);
326 HDassert(p);
327
328 if (NULL == (fill = H5FL_CALLOC(H5O_fill_t)))
329 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value message")
330
331 /* Set non-zero default fields */
332 fill->version = H5O_FILL_VERSION_2;
333 fill->alloc_time = H5D_ALLOC_TIME_LATE;
334 fill->fill_time = H5D_FILL_TIME_IFSET;
335
336 /* Fill value size */
337 UINT32DECODE(p, fill->size);
338
339 /* Only decode the fill value itself if there is one */
340 if (fill->size > 0) {
341 H5_CHECK_OVERFLOW(fill->size, ssize_t, size_t);
342
343 /* Ensure that fill size doesn't exceed buffer size, due to possible data corruption */
344 if (p + fill->size - 1 > p_end)
345 HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "fill size exceeds buffer size")
346
347 /* Get the datatype message */
348 if ((exists = H5O_msg_exists_oh(open_oh, H5O_DTYPE_ID)) < 0)
349 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read object header")
350 if (exists) {
351 if (NULL == (dt = (H5T_t *)H5O_msg_read_oh(f, open_oh, H5O_DTYPE_ID, NULL)))
352 HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "can't read DTYPE message")
353 /* Verify size */
354 if (fill->size != (ssize_t)H5T_GET_SIZE(dt))
355 HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "inconsistent fill value size")
356 } /* end if */
357
358 if (NULL == (fill->buf = H5MM_malloc((size_t)fill->size)))
359 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value")
360 H5MM_memcpy(fill->buf, p, (size_t)fill->size);
361 fill->fill_defined = TRUE;
362 } /* end if */
363 else
364 fill->size = (-1);
365
366 /* Set return value */
367 ret_value = (void *)fill;
368
369 done:
370 if (dt)
371 H5O_msg_free(H5O_DTYPE_ID, dt);
372
373 if (!ret_value && fill) {
374 if (fill->buf)
375 H5MM_xfree(fill->buf);
376 fill = H5FL_FREE(H5O_fill_t, fill);
377 } /* end if */
378
379 FUNC_LEAVE_NOAPI(ret_value)
380 } /* end H5O__fill_old_decode() */
381
382 /*-------------------------------------------------------------------------
383 * Function: H5O__fill_new_encode
384 *
385 * Purpose: Encode a new fill value message. The new fill value
386 * message is fill value plus space allocation time and
387 * fill value writing time and whether fill value is defined.
388 *
389 * Return: Non-negative on success/Negative on failure
390 *
391 * Programmer: Raymond Lu
392 * Feb 26, 2002
393 *
394 *-------------------------------------------------------------------------
395 */
396 static herr_t
H5O__fill_new_encode(H5F_t H5_ATTR_UNUSED * f,uint8_t * p,const void * _fill)397 H5O__fill_new_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p, const void *_fill)
398 {
399 const H5O_fill_t *fill = (const H5O_fill_t *)_fill;
400
401 FUNC_ENTER_STATIC_NOERR
402
403 HDassert(f);
404 HDassert(p);
405 HDassert(fill && NULL == fill->type);
406
407 /* Version */
408 *p++ = (uint8_t)fill->version;
409
410 if (fill->version < H5O_FILL_VERSION_3) {
411 /* Space allocation time */
412 *p++ = (uint8_t)fill->alloc_time;
413
414 /* Fill value writing time */
415 *p++ = (uint8_t)fill->fill_time;
416
417 /* Whether fill value is defined */
418 *p++ = (uint8_t)fill->fill_defined;
419
420 /* Only write out the size and fill value if it is defined */
421 if (fill->fill_defined) {
422 UINT32ENCODE(p, fill->size);
423 if (fill->size > 0)
424 if (fill->buf) {
425 H5_CHECK_OVERFLOW(fill->size, ssize_t, size_t);
426 H5MM_memcpy(p, fill->buf, (size_t)fill->size);
427 } /* end if */
428 } /* end if */
429 } /* end if */
430 else {
431 uint8_t flags = 0; /* Fill value setting flags */
432
433 /* Encode space allocation time */
434 HDassert(fill->alloc_time == (H5O_FILL_MASK_ALLOC_TIME & fill->alloc_time));
435 flags =
436 (uint8_t)(flags | ((H5O_FILL_MASK_ALLOC_TIME & fill->alloc_time) << H5O_FILL_SHIFT_ALLOC_TIME));
437
438 /* Encode fill value writing time */
439 HDassert(fill->fill_time == (H5O_FILL_MASK_FILL_TIME & fill->fill_time));
440 flags = (uint8_t)(flags | ((H5O_FILL_MASK_FILL_TIME & fill->fill_time) << H5O_FILL_SHIFT_FILL_TIME));
441
442 /* Check if we need to encode a fill value size */
443 if (fill->size < 0) {
444 /* Indicate that the fill value has been "undefined" by the user */
445 flags |= H5O_FILL_FLAG_UNDEFINED_VALUE;
446
447 /* Flags */
448 *p++ = (uint8_t)flags;
449
450 /* Sanity check */
451 HDassert(!fill->buf);
452 } /* end if */
453 else if (fill->size > 0) {
454 /* Indicate that a fill value size is present */
455 flags |= H5O_FILL_FLAG_HAVE_VALUE;
456
457 /* Flags */
458 *p++ = (uint8_t)flags;
459
460 /* Encode the size of fill value */
461 INT32ENCODE(p, fill->size);
462
463 /* Encode the fill value */
464 HDassert(fill->buf);
465 H5_CHECK_OVERFLOW(fill->size, ssize_t, size_t);
466 H5MM_memcpy(p, fill->buf, (size_t)fill->size);
467 } /* end if */
468 else {
469 /* Flags */
470 *p++ = (uint8_t)flags;
471
472 /* Sanity check */
473 HDassert(!fill->buf);
474 } /* end else */
475 } /* end else */
476
477 FUNC_LEAVE_NOAPI(SUCCEED)
478 } /* end H5O__fill_new_encode() */
479
480 /*-------------------------------------------------------------------------
481 * Function: H5O__fill_old_encode
482 *
483 * Purpose: Encode an old fill value message.
484 *
485 * Return: Non-negative on success/Negative on failure
486 *
487 * Programmer: Robb Matzke
488 * Thursday, October 1, 1998
489 *
490 *-------------------------------------------------------------------------
491 */
492 static herr_t
H5O__fill_old_encode(H5F_t H5_ATTR_UNUSED * f,uint8_t * p,const void * _fill)493 H5O__fill_old_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p, const void *_fill)
494 {
495 const H5O_fill_t *fill = (const H5O_fill_t *)_fill;
496
497 FUNC_ENTER_STATIC_NOERR
498
499 HDassert(f);
500 HDassert(p);
501 HDassert(fill && NULL == fill->type);
502
503 UINT32ENCODE(p, fill->size);
504 if (fill->buf)
505 H5MM_memcpy(p, fill->buf, (size_t)fill->size);
506
507 FUNC_LEAVE_NOAPI(SUCCEED)
508 } /* end H5O__fill_old_encode() */
509
510 /*-------------------------------------------------------------------------
511 * Function: H5O__fill_copy
512 *
513 * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if
514 * necessary. The new fill value message is fill value plus
515 * space allocation time and fill value writing time and
516 * whether fill value is defined.
517 *
518 * Return: Success: Ptr to _DEST
519 * Failure: NULL
520 *
521 * Programmer: Raymond Lu
522 * Feb 26, 2002
523 *
524 *-------------------------------------------------------------------------
525 */
526 static void *
H5O__fill_copy(const void * _src,void * _dst)527 H5O__fill_copy(const void *_src, void *_dst)
528 {
529 const H5O_fill_t *src = (const H5O_fill_t *)_src;
530 H5O_fill_t * dst = (H5O_fill_t *)_dst;
531 void * ret_value = NULL; /* Return value */
532
533 FUNC_ENTER_STATIC
534
535 HDassert(src);
536
537 if (!dst && NULL == (dst = H5FL_MALLOC(H5O_fill_t)))
538 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill message")
539
540 /* Shallow copy basic fields */
541 *dst = *src;
542
543 /* Copy data type of fill value */
544 if (src->type) {
545 if (NULL == (dst->type = H5T_copy(src->type, H5T_COPY_TRANSIENT)))
546 HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "can't copy datatype")
547 } /* end if */
548 else
549 dst->type = NULL;
550
551 /* Copy fill value and its size */
552 if (src->buf) {
553 H5_CHECK_OVERFLOW(src->size, ssize_t, size_t);
554 if (NULL == (dst->buf = H5MM_malloc((size_t)src->size)))
555 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value")
556 H5MM_memcpy(dst->buf, src->buf, (size_t)src->size);
557
558 /* Check for needing to convert/copy fill value */
559 if (src->type) {
560 H5T_path_t *tpath; /* Conversion information */
561
562 /* Set up type conversion function */
563 if (NULL == (tpath = H5T_path_find(src->type, dst->type)))
564 HGOTO_ERROR(H5E_OHDR, H5E_UNSUPPORTED, NULL,
565 "unable to convert between src and dst data types")
566
567 /* If necessary, convert fill value datatypes (which copies VL components, etc.) */
568 if (!H5T_path_noop(tpath)) {
569 hid_t dst_id, src_id; /* Source & destination datatypes for type conversion */
570 uint8_t *bkg_buf = NULL; /* Background conversion buffer */
571 size_t bkg_size; /* Size of background buffer */
572
573 /* Wrap copies of types to convert */
574 dst_id = H5I_register(H5I_DATATYPE, H5T_copy(dst->type, H5T_COPY_TRANSIENT), FALSE);
575 if (dst_id < 0)
576 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy/register datatype")
577 src_id = H5I_register(H5I_DATATYPE, H5T_copy(src->type, H5T_COPY_ALL), FALSE);
578 if (src_id < 0) {
579 H5I_dec_ref(dst_id);
580 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy/register datatype")
581 } /* end if */
582
583 /* Allocate a background buffer */
584 bkg_size = MAX(H5T_get_size(dst->type), H5T_get_size(src->type));
585 if (H5T_path_bkg(tpath) && NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size))) {
586 H5I_dec_ref(src_id);
587 H5I_dec_ref(dst_id);
588 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
589 } /* end if */
590
591 /* Convert fill value */
592 if (H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, dst->buf, bkg_buf) <
593 0) {
594 H5I_dec_ref(src_id);
595 H5I_dec_ref(dst_id);
596 if (bkg_buf)
597 bkg_buf = H5FL_BLK_FREE(type_conv, bkg_buf);
598 HGOTO_ERROR(H5E_OHDR, H5E_CANTCONVERT, NULL, "datatype conversion failed")
599 } /* end if */
600
601 /* Release the background buffer */
602 H5I_dec_ref(src_id);
603 H5I_dec_ref(dst_id);
604 if (bkg_buf)
605 bkg_buf = H5FL_BLK_FREE(type_conv, bkg_buf);
606 } /* end if */
607 } /* end if */
608 } /* end if */
609 else
610 dst->buf = NULL;
611
612 /* Set return value */
613 ret_value = dst;
614
615 done:
616 if (!ret_value && dst) {
617 if (dst->buf)
618 H5MM_xfree(dst->buf);
619 if (dst->type)
620 (void)H5T_close_real(dst->type);
621 if (!_dst)
622 dst = H5FL_FREE(H5O_fill_t, dst);
623 } /* end if */
624
625 FUNC_LEAVE_NOAPI(ret_value)
626 } /* end H5O__fill_copy() */
627
628 /*-------------------------------------------------------------------------
629 * Function: H5O__fill_new_size
630 *
631 * Purpose: Returns the size of the raw message in bytes not counting the
632 * message type or size fields, but only the data fields. This
633 * function doesn't take into account alignment. The new fill
634 * value message is fill value plus space allocation time and
635 * fill value writing time and whether fill value is defined.
636 *
637 * Return: Success: Message data size in bytes w/o alignment.
638 * Failure: 0
639 *
640 * Programmer: Raymond Lu
641 * Feb 26, 2002
642 *
643 *-------------------------------------------------------------------------
644 */
645 static size_t
H5O__fill_new_size(const H5F_t H5_ATTR_UNUSED * f,const void * _fill)646 H5O__fill_new_size(const H5F_t H5_ATTR_UNUSED *f, const void *_fill)
647 {
648 const H5O_fill_t *fill = (const H5O_fill_t *)_fill;
649 size_t ret_value = 0; /* Return value */
650
651 FUNC_ENTER_STATIC_NOERR
652
653 HDassert(f);
654 HDassert(fill);
655
656 /* Determine size for different versions */
657 if (fill->version < H5O_FILL_VERSION_3) {
658 ret_value = 1 + /* Version number */
659 1 + /* Space allocation time */
660 1 + /* Fill value write time */
661 1; /* Fill value defined */
662 if (fill->fill_defined)
663 ret_value += 4 + /* Fill value size */
664 (fill->size > 0 ? (size_t)fill->size : 0); /* Size of fill value */
665 } /* end if */
666 else {
667 ret_value = 1 + /* Version number */
668 1; /* Status flags */
669 if (fill->size > 0)
670 ret_value += 4 + /* Fill value size */
671 (size_t)fill->size; /* Size of fill value */
672 } /* end else */
673
674 FUNC_LEAVE_NOAPI(ret_value)
675 } /* end H5O__fill_new_size() */
676
677 /*-------------------------------------------------------------------------
678 * Function: H5O__fill_old_size
679 *
680 * Purpose: Returns the size of the raw message in bytes not counting the
681 * message type or size fields, but only the data fields. This
682 * function doesn't take into account alignment.
683 *
684 * Return: Success: Message data size in bytes w/o alignment.
685 * Failure: 0
686 *
687 * Programmer: Robb Matzke
688 * Thursday, October 1, 1998
689 *
690 *-------------------------------------------------------------------------
691 */
692 static size_t
H5O__fill_old_size(const H5F_t H5_ATTR_UNUSED * f,const void * _fill)693 H5O__fill_old_size(const H5F_t H5_ATTR_UNUSED *f, const void *_fill)
694 {
695 const H5O_fill_t *fill = (const H5O_fill_t *)_fill;
696
697 FUNC_ENTER_STATIC_NOERR
698
699 HDassert(fill);
700
701 FUNC_LEAVE_NOAPI(4 + (size_t)fill->size)
702 } /* end H5O__fill_old_size() */
703
704 /*-------------------------------------------------------------------------
705 * Function: H5O_fill_reset_dyn
706 *
707 * Purpose: Resets dynamic fill value fields
708 *
709 * Return: Non-negative on success/Negative on failure
710 *
711 * Programmer: Quincey Koziol
712 * Monday, January 22, 2007
713 *
714 *-------------------------------------------------------------------------
715 */
716 herr_t
H5O_fill_reset_dyn(H5O_fill_t * fill)717 H5O_fill_reset_dyn(H5O_fill_t *fill)
718 {
719 hid_t fill_type_id = -1; /* Datatype ID for fill value datatype when reclaiming VL fill values */
720 herr_t ret_value = SUCCEED; /* Return value */
721
722 FUNC_ENTER_NOAPI(FAIL)
723
724 HDassert(fill);
725
726 if (fill->buf) {
727 if (fill->type && H5T_detect_class(fill->type, H5T_VLEN, FALSE) > 0) {
728 H5T_t *fill_type; /* Copy of fill value datatype */
729 H5S_t *fill_space; /* Scalar dataspace for fill value element */
730
731 /* Copy the fill value datatype and get an ID for it */
732 if (NULL == (fill_type = H5T_copy(fill->type, H5T_COPY_TRANSIENT)))
733 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy fill value datatype")
734 if ((fill_type_id = H5I_register(H5I_DATATYPE, fill_type, FALSE)) < 0) {
735 (void)H5T_close_real(fill_type);
736 HGOTO_ERROR(H5E_OHDR, H5E_CANTREGISTER, FAIL, "unable to register fill value datatype")
737 } /* end if */
738
739 /* Create a scalar dataspace for the fill value element */
740 if (NULL == (fill_space = H5S_create(H5S_SCALAR)))
741 HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create scalar dataspace")
742
743 /* Reclaim any variable length components of the fill value */
744 if (H5T_reclaim(fill_type_id, fill_space, fill->buf) < 0) {
745 H5S_close(fill_space);
746 HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "unable to reclaim variable-length fill value data")
747 } /* end if */
748
749 /* Release the scalar fill value dataspace */
750 H5S_close(fill_space);
751 } /* end if */
752
753 /* Release the fill value buffer now */
754 fill->buf = H5MM_xfree(fill->buf);
755 } /* end if */
756 fill->size = 0;
757 if (fill->type) {
758 (void)H5T_close_real(fill->type);
759 fill->type = NULL;
760 } /* end if */
761
762 done:
763 if (fill_type_id > 0 && H5I_dec_ref(fill_type_id) < 0)
764 HDONE_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement ref count for temp ID")
765
766 FUNC_LEAVE_NOAPI(ret_value)
767 } /* end H5O_fill_reset_dyn() */
768
769 /*-------------------------------------------------------------------------
770 * Function: H5O__fill_reset
771 *
772 * Purpose: Resets a message to an initial state.
773 *
774 * Return: Non-negative on success/Negative on failure
775 *
776 * Programmer: Robb Matzke
777 * Thursday, October 1, 1998
778 *
779 *-------------------------------------------------------------------------
780 */
781 static herr_t
H5O__fill_reset(void * _fill)782 H5O__fill_reset(void *_fill)
783 {
784 H5O_fill_t *fill = (H5O_fill_t *)_fill;
785
786 FUNC_ENTER_STATIC_NOERR
787
788 HDassert(fill);
789
790 /* Reset dynamic fields */
791 H5O_fill_reset_dyn(fill);
792
793 /* Reset value fields */
794 fill->alloc_time = H5D_ALLOC_TIME_LATE;
795 fill->fill_time = H5D_FILL_TIME_IFSET;
796 fill->fill_defined = FALSE;
797
798 FUNC_LEAVE_NOAPI(SUCCEED)
799 } /* end H5O__fill_reset() */
800
801 /*-------------------------------------------------------------------------
802 * Function: H5O__fill_free
803 *
804 * Purpose: Frees the message
805 *
806 * Return: Non-negative on success/Negative on failure
807 *
808 * Programmer: Quincey Koziol
809 * Thursday, December 5, 2002
810 *
811 *-------------------------------------------------------------------------
812 */
813 static herr_t
H5O__fill_free(void * fill)814 H5O__fill_free(void *fill)
815 {
816 FUNC_ENTER_STATIC_NOERR
817
818 HDassert(fill);
819
820 fill = H5FL_FREE(H5O_fill_t, fill);
821
822 FUNC_LEAVE_NOAPI(SUCCEED)
823 } /* end H5O__fill_free() */
824
825 /*-------------------------------------------------------------------------
826 * Function: H5O__fill_pre_copy_file
827 *
828 * Purpose: Perform any necessary actions before copying message between
829 * files.
830 *
831 * Return: Success: Non-negative
832 * Failure: Negative
833 *
834 * Programmer: Vailin Choi; Dec 2017
835 *
836 *-------------------------------------------------------------------------
837 */
838 static herr_t
H5O__fill_pre_copy_file(H5F_t H5_ATTR_UNUSED * file_src,const void * mesg_src,hbool_t H5_ATTR_UNUSED * deleted,const H5O_copy_t * cpy_info,void H5_ATTR_UNUSED * udata)839 H5O__fill_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *mesg_src, hbool_t H5_ATTR_UNUSED *deleted,
840 const H5O_copy_t *cpy_info, void H5_ATTR_UNUSED *udata)
841 {
842 const H5O_fill_t *fill_src = (const H5O_fill_t *)mesg_src; /* Source fill value */
843 herr_t ret_value = SUCCEED; /* Return value */
844
845 FUNC_ENTER_STATIC
846
847 /* check args */
848 HDassert(cpy_info);
849 HDassert(cpy_info->file_dst);
850
851 /* Check to ensure that the version of the message to be copied does not exceed
852 the message version allowed by the destination file's high bound */
853 if (fill_src->version > H5O_fill_ver_bounds[H5F_HIGH_BOUND(cpy_info->file_dst)])
854 HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "fill value message version out of bounds")
855
856 done:
857 FUNC_LEAVE_NOAPI(ret_value)
858 } /* end H5O__fill_pre_copy_file() */
859
860 /*-------------------------------------------------------------------------
861 * Function: H5O__fill_debug
862 *
863 * Purpose: Prints debugging info for the message.
864 *
865 * Return: Non-negative on success/Negative on failure
866 *
867 * Programmer: Robb Matzke
868 * Thursday, October 1, 1998
869 *
870 *-------------------------------------------------------------------------
871 */
872 static herr_t
H5O__fill_debug(H5F_t H5_ATTR_UNUSED * f,const void * _fill,FILE * stream,int indent,int fwidth)873 H5O__fill_debug(H5F_t H5_ATTR_UNUSED *f, const void *_fill, FILE *stream, int indent, int fwidth)
874 {
875 const H5O_fill_t *fill = (const H5O_fill_t *)_fill;
876 H5D_fill_value_t fill_status; /* Whether the fill value is defined */
877
878 FUNC_ENTER_STATIC_NOERR
879
880 HDassert(f);
881 HDassert(fill);
882 HDassert(stream);
883 HDassert(indent >= 0);
884 HDassert(fwidth >= 0);
885
886 HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Space Allocation Time:");
887 switch (fill->alloc_time) {
888 case H5D_ALLOC_TIME_EARLY:
889 HDfprintf(stream, "Early\n");
890 break;
891
892 case H5D_ALLOC_TIME_LATE:
893 HDfprintf(stream, "Late\n");
894 break;
895
896 case H5D_ALLOC_TIME_INCR:
897 HDfprintf(stream, "Incremental\n");
898 break;
899
900 case H5D_ALLOC_TIME_DEFAULT:
901 case H5D_ALLOC_TIME_ERROR:
902 default:
903 HDfprintf(stream, "Unknown!\n");
904 break;
905 } /* end switch */
906 HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Fill Time:");
907 switch (fill->fill_time) {
908 case H5D_FILL_TIME_ALLOC:
909 HDfprintf(stream, "On Allocation\n");
910 break;
911
912 case H5D_FILL_TIME_NEVER:
913 HDfprintf(stream, "Never\n");
914 break;
915
916 case H5D_FILL_TIME_IFSET:
917 HDfprintf(stream, "If Set\n");
918 break;
919
920 case H5D_FILL_TIME_ERROR:
921 default:
922 HDfprintf(stream, "Unknown!\n");
923 break;
924
925 } /* end switch */
926 HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Fill Value Defined:");
927 H5P_is_fill_value_defined((const H5O_fill_t *)fill, &fill_status);
928 switch (fill_status) {
929 case H5D_FILL_VALUE_UNDEFINED:
930 HDfprintf(stream, "Undefined\n");
931 break;
932
933 case H5D_FILL_VALUE_DEFAULT:
934 HDfprintf(stream, "Default\n");
935 break;
936
937 case H5D_FILL_VALUE_USER_DEFINED:
938 HDfprintf(stream, "User Defined\n");
939 break;
940
941 case H5D_FILL_VALUE_ERROR:
942 default:
943 HDfprintf(stream, "Unknown!\n");
944 break;
945
946 } /* end switch */
947 HDfprintf(stream, "%*s%-*s %zd\n", indent, "", fwidth, "Size:", fill->size);
948 HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Data type:");
949 if (fill->type) {
950 H5T_debug(fill->type, stream);
951 HDfprintf(stream, "\n");
952 } /* end if */
953 else
954 HDfprintf(stream, "<dataset type>\n");
955
956 FUNC_LEAVE_NOAPI(SUCCEED)
957 } /* end H5O__fill_debug() */
958
959 /*-------------------------------------------------------------------------
960 * Function: H5O_fill_convert
961 *
962 * Purpose: Convert a fill value from whatever data type it currently has
963 * to the specified dataset type. The `type' field of the fill
964 * value struct will be set to NULL to indicate that it has the
965 * same type as the dataset.
966 *
967 * Return: Non-negative on success/Negative on failure
968 *
969 * Programmer: Robb Matzke
970 * Thursday, October 1, 1998
971 *
972 *-------------------------------------------------------------------------
973 */
974 herr_t
H5O_fill_convert(H5O_fill_t * fill,H5T_t * dset_type,hbool_t * fill_changed)975 H5O_fill_convert(H5O_fill_t *fill, H5T_t *dset_type, hbool_t *fill_changed)
976 {
977 H5T_path_t *tpath; /* Type conversion info */
978 void * buf = NULL, *bkg = NULL; /* Conversion buffers */
979 hid_t src_id = -1, dst_id = -1; /* Datatype identifiers */
980 herr_t ret_value = SUCCEED; /* Return value */
981
982 FUNC_ENTER_NOAPI(FAIL)
983
984 HDassert(fill);
985 HDassert(dset_type);
986 HDassert(fill_changed);
987
988 /* No-op cases */
989 if (!fill->buf || !fill->type || 0 == H5T_cmp(fill->type, dset_type, FALSE)) {
990 /* Don't need datatype for fill value */
991 if (fill->type)
992 (void)H5T_close_real(fill->type);
993 fill->type = NULL;
994
995 /* Note that the fill value info has changed */
996 *fill_changed = TRUE;
997
998 HGOTO_DONE(SUCCEED);
999 } /* end if */
1000
1001 /*
1002 * Can we convert between source and destination data types?
1003 */
1004 if (NULL == (tpath = H5T_path_find(fill->type, dset_type)))
1005 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to convert between src and dst datatypes")
1006
1007 /* Don't bother doing anything if there will be no actual conversion */
1008 if (!H5T_path_noop(tpath)) {
1009 if ((src_id = H5I_register(H5I_DATATYPE, H5T_copy(fill->type, H5T_COPY_ALL), FALSE)) < 0 ||
1010 (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(dset_type, H5T_COPY_ALL), FALSE)) < 0)
1011 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy/register data type")
1012
1013 /*
1014 * Datatype conversions are always done in place, so we need a buffer
1015 * that is large enough for both source and destination.
1016 */
1017 if (H5T_get_size(fill->type) >= H5T_get_size(dset_type))
1018 buf = fill->buf;
1019 else {
1020 if (NULL == (buf = H5MM_malloc(H5T_get_size(dset_type))))
1021 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
1022 H5MM_memcpy(buf, fill->buf, H5T_get_size(fill->type));
1023 } /* end else */
1024
1025 /* Use CALLOC here to clear the buffer in case later the library thinks there's
1026 * data in the background. */
1027 if (H5T_path_bkg(tpath) && NULL == (bkg = H5MM_calloc(H5T_get_size(dset_type))))
1028 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
1029
1030 /* Do the conversion */
1031 if (H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, buf, bkg) < 0)
1032 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "datatype conversion failed")
1033
1034 /* Update the fill message */
1035 if (buf != fill->buf) {
1036 H5T_vlen_reclaim_elmt(fill->buf, fill->type);
1037 H5MM_xfree(fill->buf);
1038 fill->buf = buf;
1039 } /* end if */
1040 (void)H5T_close_real(fill->type);
1041 fill->type = NULL;
1042 H5_CHECKED_ASSIGN(fill->size, ssize_t, H5T_get_size(dset_type), size_t);
1043
1044 /* Note that the fill value info has changed */
1045 *fill_changed = TRUE;
1046 } /* end if */
1047
1048 done:
1049 if (src_id >= 0 && H5I_dec_ref(src_id) < 0)
1050 HDONE_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement ref count for temp ID")
1051 if (dst_id >= 0 && H5I_dec_ref(dst_id) < 0)
1052 HDONE_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement ref count for temp ID")
1053 if (buf != fill->buf)
1054 H5MM_xfree(buf);
1055 if (bkg)
1056 H5MM_xfree(bkg);
1057
1058 FUNC_LEAVE_NOAPI(ret_value)
1059 } /* end H5O_fill_convert() */
1060
1061 /*-------------------------------------------------------------------------
1062 * Function: H5O_fill_set_version
1063 *
1064 * Purpose: Set the version to encode a fill value with.
1065 *
1066 * Return: Non-negative on success/Negative on failure
1067 *
1068 * Programmer: Vailin Choi; December 2017
1069 *
1070 *-------------------------------------------------------------------------
1071 */
1072 herr_t
H5O_fill_set_version(H5F_t * f,H5O_fill_t * fill)1073 H5O_fill_set_version(H5F_t *f, H5O_fill_t *fill)
1074 {
1075 unsigned version; /* Message version */
1076 herr_t ret_value = SUCCEED; /* Return value */
1077
1078 FUNC_ENTER_NOAPI(FAIL)
1079
1080 /* Sanity check */
1081 HDassert(f);
1082 HDassert(fill);
1083
1084 /* Upgrade to the version indicated by the file's low bound if higher */
1085 version = MAX(fill->version, H5O_fill_ver_bounds[H5F_LOW_BOUND(f)]);
1086
1087 /* Version bounds check */
1088 if (version > H5O_fill_ver_bounds[H5F_HIGH_BOUND(f)])
1089 HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "Filter pipeline version out of bounds")
1090
1091 /* Set the message version */
1092 fill->version = version;
1093
1094 done:
1095 FUNC_LEAVE_NOAPI(ret_value)
1096 } /* end H5O_fill_set_version() */
1097