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