diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5Aint.c | 17 | ||||
-rw-r--r-- | src/H5Dint.c | 25 | ||||
-rw-r--r-- | src/H5Dlayout.c | 19 | ||||
-rw-r--r-- | src/H5F.c | 18 | ||||
-rw-r--r-- | src/H5Fdeprec.c | 62 | ||||
-rw-r--r-- | src/H5Fint.c | 36 | ||||
-rw-r--r-- | src/H5Fprivate.h | 1 | ||||
-rw-r--r-- | src/H5Fpublic.h | 3 | ||||
-rw-r--r-- | src/H5Fquery.c | 11 | ||||
-rw-r--r-- | src/H5Fsuper.c | 87 | ||||
-rw-r--r-- | src/H5Gobj.c | 12 | ||||
-rw-r--r-- | src/H5Oattr.c | 2 | ||||
-rw-r--r-- | src/H5Ocopy.c | 6 | ||||
-rw-r--r-- | src/H5Odtype.c | 2 | ||||
-rw-r--r-- | src/H5Ofill.c | 22 | ||||
-rw-r--r-- | src/H5Oint.c | 22 | ||||
-rw-r--r-- | src/H5Olayout.c | 5 | ||||
-rw-r--r-- | src/H5Opkg.h | 8 | ||||
-rw-r--r-- | src/H5Opline.c | 19 | ||||
-rw-r--r-- | src/H5Oprivate.h | 6 | ||||
-rw-r--r-- | src/H5Osdspace.c | 2 | ||||
-rw-r--r-- | src/H5S.c | 15 | ||||
-rw-r--r-- | src/H5T.c | 5 | ||||
-rw-r--r-- | src/H5trace.c | 3 |
24 files changed, 305 insertions, 103 deletions
diff --git a/src/H5Aint.c b/src/H5Aint.c index 5c32e86..666f11d 100644 --- a/src/H5Aint.c +++ b/src/H5Aint.c @@ -1863,6 +1863,7 @@ herr_t H5A_set_version(const H5F_t *f, H5A_t *attr) { hbool_t type_shared, space_shared; /* Flags to indicate that shared messages are used for this attribute */ + uint8_t version; /* Message version */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -1884,18 +1885,22 @@ H5A_set_version(const H5F_t *f, H5A_t *attr) /* Check which version to encode attribute with */ if(attr->shared->encoding != H5T_CSET_ASCII) - attr->shared->version = H5O_ATTR_VERSION_3; /* Write version which includes the character encoding */ + version = H5O_ATTR_VERSION_3; /* Write version which includes the character encoding */ else if(type_shared || space_shared) - attr->shared->version = H5O_ATTR_VERSION_2; /* Write out version with flag for indicating shared datatype or dataspace */ + version = H5O_ATTR_VERSION_2; /* Write out version with flag for indicating shared datatype or dataspace */ else - attr->shared->version = H5O_ATTR_VERSION_1; /* Write out basic version */ + version = H5O_ATTR_VERSION_1; /* Write out basic version */ /* Upgrade to the version indicated by the file's low bound if higher */ - attr->shared->version = MAX(attr->shared->version, (uint8_t)H5O_attr_ver_bounds[H5F_LOW_BOUND(f)]); + version = MAX(version, (uint8_t)H5O_attr_ver_bounds[H5F_LOW_BOUND(f)]); - /* File bound check */ - if(attr->shared->version > H5O_attr_ver_bounds[H5F_HIGH_BOUND(f)]) + /* Version bounds check */ + if(version > H5O_attr_ver_bounds[H5F_HIGH_BOUND(f)]) HGOTO_ERROR(H5E_ATTR, H5E_BADRANGE, FAIL, "attribute version out of bounds") + + /* Set the message version */ + attr->shared->version = version; + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5A_set_version() */ diff --git a/src/H5Dint.c b/src/H5Dint.c index c1a66ca..89dff1e 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -623,10 +623,10 @@ done: static herr_t H5D__init_type(H5F_t *file, const H5D_t *dset, hid_t type_id, const H5T_t *type) { - htri_t relocatable; /* Flag whether the type is relocatable */ - htri_t immutable; /* Flag whether the type is immutable */ - hbool_t use_v18_latest_format; /* Flag indicating the 'latest datatype version support' is enabled */ - herr_t ret_value = SUCCEED; /* Return value */ + htri_t relocatable; /* Flag whether the type is relocatable */ + htri_t immutable; /* Flag whether the type is immutable */ + hbool_t use_at_least_v18; /* Flag indicating to use at least v18 format versions */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC @@ -643,10 +643,11 @@ H5D__init_type(H5F_t *file, const H5D_t *dset, hid_t type_id, const H5T_t *type) if((immutable = H5T_is_immutable(type)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't check datatype?") - use_v18_latest_format = (H5F_LOW_BOUND(file) >= H5F_LIBVER_V18); + /* To use at least v18 format versions or not */ + use_at_least_v18 = (H5F_LOW_BOUND(file) >= H5F_LIBVER_V18); /* Copy the datatype if it's a custom datatype or if it'll change when it's location is changed */ - if(!immutable || relocatable || use_v18_latest_format) { + if(!immutable || relocatable || use_at_least_v18) { /* Copy datatype for dataset */ if((dset->shared->type = H5T_copy(type, H5T_COPY_ALL)) == NULL) HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "can't copy datatype") @@ -786,6 +787,7 @@ H5D__update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset, hid_t dapl_id) H5D_fill_value_t fill_status; /* Fill value status */ hbool_t fill_changed = FALSE; /* Flag indicating the fill value was changed */ hbool_t layout_init = FALSE; /* Flag to indicate that chunk information was initialized */ + hbool_t use_at_least_v18; /* Flag indicating to use at least v18 format versions */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC @@ -800,6 +802,9 @@ H5D__update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset, hid_t dapl_id) type = dset->shared->type; fill_prop = &dset->shared->dcpl_cache.fill; + /* To use at least v18 format versions or not */ + use_at_least_v18 = (H5F_LOW_BOUND(file) >= H5F_LIBVER_V18); + /* Retrieve "defined" status of fill value */ if(H5P_is_fill_value_defined(fill_prop, &fill_status) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined") @@ -878,8 +883,8 @@ H5D__update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset, hid_t dapl_id) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update new fill value header message") /* If there is valid information for the old fill value struct, add it */ - /* (only if we aren't trying to write the 'latest fill message version support') */ - if(fill_prop->buf && (H5F_LOW_BOUND(file) < H5F_LIBVER_V18)) { + /* (only if we aren't using v18 format versions and above */ + if(fill_prop->buf && !use_at_least_v18) { H5O_fill_t old_fill_prop; /* Copy of fill value property, for writing as "old" fill value */ /* Shallow copy the fill value property */ @@ -931,10 +936,10 @@ H5D__update_oh_info(H5F_t *file, hid_t dxpl_id, H5D_t *dset, hid_t dapl_id) #endif /* H5O_ENABLE_BOGUS */ /* Add a modification time message, if using older format. */ - /* (If using the latest 'no modification time message' version support, the modification time is part of the object + /* (If using v18 format versions and above, the the modification time is part of the object * header and doesn't use a separate message -QAK) */ - if(H5F_LOW_BOUND(file) < H5F_LIBVER_V18) + if(!use_at_least_v18) if(H5O_touch_oh(file, dxpl_id, oh, TRUE) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update modification time message") diff --git a/src/H5Dlayout.c b/src/H5Dlayout.c index 5a4d537..980b810 100644 --- a/src/H5Dlayout.c +++ b/src/H5Dlayout.c @@ -46,9 +46,10 @@ /* Package Variables */ /*********************/ +/* Format version bounds for layout */ const unsigned H5O_layout_ver_bounds[] = { H5O_LAYOUT_VERSION_1, /* H5F_LIBVER_EARLIEST */ - H5O_LAYOUT_VERSION_3, /* H5F_LIBVER_V18 */ + H5O_LAYOUT_VERSION_3, /* H5F_LIBVER_V18 */ /* H5O_LAYOUT_VERSION_DEFAULT */ H5O_LAYOUT_VERSION_LATEST /* H5F_LIBVER_LATEST */ }; @@ -289,16 +290,15 @@ done: * * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * Thursday, January 15, 2009 + * Programmer: Vailin Choi; December 2017 * *------------------------------------------------------------------------- */ herr_t H5D__layout_set_version(H5F_t *f, H5O_layout_t *layout) { - unsigned vers; - herr_t ret_value = SUCCEED; /* Return value */ + unsigned version; /* Message version */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -307,12 +307,15 @@ H5D__layout_set_version(H5F_t *f, H5O_layout_t *layout) HDassert(f); /* Upgrade to the version indicated by the file's low bound if higher */ - layout->version = MAX(layout->version, H5O_layout_ver_bounds[H5F_LOW_BOUND(f)]); + version = MAX(layout->version, H5O_layout_ver_bounds[H5F_LOW_BOUND(f)]); - /* File bound check */ - if(layout->version > H5O_layout_ver_bounds[H5F_HIGH_BOUND(f)]) + /* Version bounds check */ + if(version > H5O_layout_ver_bounds[H5F_HIGH_BOUND(f)]) HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "layout version out of bounds") + /* Set the message version */ + layout->version = version; + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5D__layout_set_version() */ @@ -1478,6 +1478,8 @@ H5Fstart_swmr_write(hid_t file_id) if(file->shared->sblock->super_vers < HDF5_SUPERBLOCK_VERSION_3) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file superblock version should be at least 3") + HDassert((file->shared->low_bound == H5F_LIBVER_V110) && (file->shared->high_bound == H5F_LIBVER_V110)); + /* Should not be marked for SWMR writing mode already */ if(file->shared->sblock->status_flags & H5F_SUPER_SWMR_WRITE_ACCESS) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file already in SWMR writing mode") @@ -1739,9 +1741,12 @@ done: /*------------------------------------------------------------------------- - * Function: H5Fset_libver_bounds (Internal library use) + * Function: H5Fset_libver_bounds * - * Purpose: Set .... the "latest format" flag while a file is open. + * Purpose: Set to a different low and high bounds while a file is open. + * This public routine is introduced in place of + * H5Fset_latest_format() starting release 1.10.2. + * See explanation for H5Fset_latest_format() in H5Fdeprec.c. * * Return: Non-negative on success/Negative on failure *------------------------------------------------------------------------- @@ -1759,12 +1764,9 @@ H5Fset_libver_bounds(hid_t file_id, H5F_libver_t low, H5F_libver_t high) if(NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "not a file ID") - /* Call the flush routine, for this file */ - if(H5F__flush(f, H5AC_ind_read_dxpl_id, H5AC_rawdata_dxpl_id, FALSE) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file's cached information") - - f->shared->low_bound = low; - f->shared->high_bound = high; + /* Call private set_libver_bounds function */ + if(H5F_set_libver_bounds(f, low, high) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "cannot set low/high bounds") done: FUNC_LEAVE_API(ret_value) diff --git a/src/H5Fdeprec.c b/src/H5Fdeprec.c index 03f5df8..a9ffa43 100644 --- a/src/H5Fdeprec.c +++ b/src/H5Fdeprec.c @@ -143,5 +143,67 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Fget_info1() */ + +/*------------------------------------------------------------------------- + * Function: H5Fset_latest_format + * + * Purpose: Enable switching between latest or non-latest format while + * a file is open. + * This is deprecated starting release 1.10.2 and is modified + * to call the private H5F_set_libver_bounds() to set the + * bounds. + * + * Before release 1.10.2, the library supports only two + * combinations of low/high bounds: + * (earliest, latest) + * (latest, latest) + * Thus, this public routine does the job in switching + * between the two combinations listed above. + * + * Starting release 1.10.2, we add v18 to the enumerated + * define H5F_libver_t and the library supports five combinations + * as below: + * (earliest, v18) + * (earliest, v10) + * (v18, v18) + * (v18, v10) + * (v10, v10) + * So we introduce the new public routine H5Fset_libver_bounds() + * in place of H5Fset_latest_format(). + * See also RFC: Setting Bounds for Object Creation in HDF5 1.10.0. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Vailin Choi; December 2017 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Fset_latest_format(hid_t file_id, hbool_t latest_format) +{ + H5F_t *f; /* File */ + H5F_libver_t low = H5F_LIBVER_LATEST; /* Low bound */ + H5F_libver_t high = H5F_LIBVER_LATEST; /* High bound */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ib", file_id, latest_format); + + /* Check args */ + if(NULL == (f = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "not a file ID") + + /* 'low' and 'high' are both initialized to LATEST. + If latest format is not expected, set 'low' to EARLIEST */ + if(!latest_format) + low = H5F_LIBVER_EARLIEST; + + /* Call private set_libver_bounds function to set the bounds */ + if(H5F_set_libver_bounds(f, low, high) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "cannot set low/high bounds") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Fset_latest_format() */ #endif /* H5_NO_DEPRECATED_SYMBOLS */ diff --git a/src/H5Fint.c b/src/H5Fint.c index f223195..79f0d06 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -671,9 +671,9 @@ H5F_new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_t if(H5P_get(plist, H5F_ACS_META_CACHE_INIT_IMAGE_CONFIG_NAME, &(f->shared->mdc_initCacheImageCfg)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial metadata cache resize config") - /* File format version high bound does not allow the generation of metadata cache image */ + /* Format version high bound does not allow the generation of metadata cache image */ if(f->shared->mdc_initCacheImageCfg.generate_image && f->shared->high_bound < H5F_LIBVER_V110) - HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "file format version out of bound for cache image") + HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "format version out of bound for cache image") /* Get the VFD values to cache */ f->shared->maxaddr = H5FD_get_maxaddr(lf); @@ -2313,6 +2313,38 @@ H5F_set_store_msg_crt_idx(H5F_t *f, hbool_t flag) FUNC_LEAVE_NOAPI(SUCCEED) } /* H5F_set_store_msg_crt_idx() */ +/*------------------------------------------------------------------------- + * Function: H5F_set_libver_bounds() + * + * Purpose: Set the file's low and high bound to the input parameters + * 'low' and 'high' respectively. + * This is done only if the existing setting is different + * from the inputs. + * + * Return: SUCCEED on success, and FAIL on failure. + * + * Programmer: Vailin Choi; December 2017 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_set_libver_bounds(H5F_t * f, H5F_libver_t low, H5F_libver_t high) +{ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Sanity checks */ + HDassert(f); + HDassert(f->shared); + + /* Set the bounds only if the existing setting is different from the inputs */ + if(f->shared->low_bound != low || f->shared->high_bound != high) { + f->shared->low_bound = low; + f->shared->high_bound = high; + } + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5F_set_libver_bounds() */ + /*------------------------------------------------------------------------- * Function: H5F_get_file_image diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 50325bb..ec98468 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -769,6 +769,7 @@ H5_DLL unsigned H5F_gc_ref(const H5F_t *f); H5_DLL unsigned H5F_use_latest_flags(const H5F_t *f, unsigned fl); H5_DLL hbool_t H5F_store_msg_crt_idx(const H5F_t *f); H5_DLL herr_t H5F_set_store_msg_crt_idx(H5F_t *f, hbool_t flag); +H5_DLL herr_t H5F_set_libver_bounds(H5F_t * f, H5F_libver_t low, H5F_libver_t high); H5_DLL struct H5UC_t *H5F_grp_btree_shared(const H5F_t *f); H5_DLL herr_t H5F_set_grp_btree_shared(H5F_t *f, struct H5UC_t *rc); H5_DLL hbool_t H5F_use_tmp_space(const H5F_t *f); diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h index 9364ee2..d333fa7 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -173,7 +173,7 @@ typedef struct H5F_sect_info_t { hsize_t size; /* Size of free space section */ } H5F_sect_info_t; -/* Library's file format versions */ +/* Library's format versions */ typedef enum H5F_libver_t { H5F_LIBVER_ERROR = -1, H5F_LIBVER_EARLIEST = 0, /* Use the earliest possible format for storing objects */ @@ -300,6 +300,7 @@ typedef struct H5F_info1_t { /* Function prototypes */ H5_DLL herr_t H5Fget_info1(hid_t obj_id, H5F_info1_t *finfo); +H5_DLL herr_t H5Fset_latest_format(hid_t file_id, hbool_t latest_format); #endif /* H5_NO_DEPRECATED_SYMBOLS */ diff --git a/src/H5Fquery.c b/src/H5Fquery.c index 6b641f1..5d7de9d 100644 --- a/src/H5Fquery.c +++ b/src/H5Fquery.c @@ -716,9 +716,14 @@ H5F_sieve_buf_size(const H5F_t *f) * Purpose: Replaced a macro to retrieve the "garbage collect * references flag" now that the generic properties are being used * to store the values. - e - * is returned. - * Failure: (should not happen) + * + * Return: Success: The "garbage collect references flag" is returned. + * Failure: (should not happen) + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jul 8 2005 + * *------------------------------------------------------------------------- */ unsigned diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c index 4c12cb9..d30434d 100644 --- a/src/H5Fsuper.c +++ b/src/H5Fsuper.c @@ -457,23 +457,46 @@ H5F__super_read(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t initial if(NULL == (sblock = (H5F_super_t *)H5AC_protect(f, meta_dxpl_id, H5AC_SUPERBLOCK, (haddr_t)0, &udata, rw_flags))) HGOTO_ERROR(H5E_FILE, H5E_CANTPROTECT, FAIL, "unable to load superblock") - /* Upgrade low bound to at least V18 when encountering version 2 superblock */ + /* + * When opening a file with SWMR-write access, the library will first + * check to ensure that superblock version 3 is used. Otherwise fail + * file open. + * + * Then the library will upgrade the file's low_bound depending on + * superblock version as follows: + * --version 0 or 1: no change to low_bound + * --version 2: upgrade low_bound to at least V18 + * --version 3: upgrade low_bound to at least V110 + * + * Upgrading low_bound will give the best format versions available for + * that superblock version. Due to the possible upgrade, the fapl returned + * from H5Fget_access_plist() might indicate a low_bound higher than what + * the user originally set. + * + * After upgrading low_bound, the library will check to ensure that the + * superblock version does not exceed the version allowed by high_bound. + * Otherise fail file open. + * + * For details, please see RFC:Setting Bounds for Object Creation in HDF5 1.10.0. + */ + + /* Check to ensure that superblock version 3 is used for SWMR-write access */ + if(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE) { + if(sblock->super_vers < HDF5_SUPERBLOCK_VERSION_3) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "superblock version for SWMR is less than 3") + } + + /* Upgrade low_bound to at least V18 when encountering version 2 superblock */ if(sblock->super_vers == HDF5_SUPERBLOCK_VERSION_2) f->shared->low_bound = MAX(H5F_LIBVER_V18, f->shared->low_bound); - /* Upgrade low bound to at least V110 when encountering version 3 superblock or SWMR_WRITE */ - if((sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_3) || (H5F_INTENT(f) & H5F_ACC_SWMR_WRITE)) + /* Upgrade low_bound to at least V110 when encountering version 3 superblock */ + if(sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_3) f->shared->low_bound = MAX(H5F_LIBVER_V110, f->shared->low_bound); - /* File bound check */ + /* Version bounds check */ if(sblock->super_vers > HDF5_superblock_ver_bounds[f->shared->high_bound]) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "superblock version out of bounds (high bound)") - - /* SWMR requires at least superblock version 3 */ - if(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE) { - if(sblock->super_vers < HDF5_superblock_ver_bounds[f->shared->low_bound]) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "superblock version out of bounds (low bound)") - } + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "superblock version exceeds high bound") /* Pin the superblock in the cache */ if(H5AC_pin_protected_entry(sblock) < 0) @@ -833,9 +856,9 @@ H5F__super_read(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t initial hbool_t rw = ((rw_flags & H5AC__READ_ONLY_FLAG) == 0); H5O_mdci_t mdci_msg; - /* Message exists but file format version high bound does not allow it */ + /* Message exists but version high bound does not allow it */ if(f->shared->high_bound < H5F_LIBVER_V110) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "file format version out of bound for metadata cache image") + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "format version out of bound for metadata cache image") /* if the metadata cache image superblock extension message exists, * read its contents and pass the data on to the metadata cache. @@ -1037,6 +1060,36 @@ H5F__super_init(H5F_t *f, hid_t dxpl_id) f->shared->fs_page_size == H5F_FILE_SPACE_PAGE_SIZE_DEF)) non_default_fs_settings = TRUE; + /* + * When creating a file with write access, the library will: + * -- set superblock version to 0, 1 or 2 based on feature enabled + * -- no change to low_bound + * When creating a file with SWMR-write access, the library will: + * (See explanation (#) below.) + * -- set superblock version to 3 + * -- upgrade low_bound to at least V110 + * + * Then the library will finalize superblock version to that allowed by + * low_bound if that is higher. + * Lastly, the library will check to ensure the superblock version does not + * exceed the version allowed by high_bound. Otherwise fail file open. + * + * For details, please see RFC:Setting Bounds for Object Creation in HDF5 1.10.0. + * + * (#) + * Version 3 superblock is introduced in 1.10 for SWMR due to the problem of + * the status_flags field in the superblock. The problem is discussed in + * jira issue SWMR-79 and also in the RFC: File Format Changes in HDF5 1.10.0. + * The file's low_bound is upgraded for SWMR so that the library will + * use the best format versions available in 1.10. + * Due to the possible upgrade, the fapl returned from H5Fget_access_plist() + * might indicate a low_bound higher than what the user originally set. + */ + + /* + * Creating a file with SWMR-write access will + * upgrade superblock version and low_bound + */ if(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE) { super_vers = HDF5_SUPERBLOCK_VERSION_3; f->shared->low_bound = MAX(H5F_LIBVER_V110, f->shared->low_bound); @@ -1060,10 +1113,10 @@ H5F__super_init(H5F_t *f, hid_t dxpl_id) else if(sblock->btree_k[H5B_CHUNK_ID] != HDF5_BTREE_CHUNK_IK_DEF) super_vers = HDF5_SUPERBLOCK_VERSION_1; - /* Upgrade to the version indicated by the file's low bound if higher */ + /* Finalize superblock version to that allowed by the file's low bound if higher */ super_vers = MAX(super_vers, HDF5_superblock_ver_bounds[f->shared->low_bound]); - /* File bound check */ + /* Version bounds check */ if(super_vers > HDF5_superblock_ver_bounds[f->shared->high_bound]) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "superblock version out of bounds") @@ -1091,8 +1144,8 @@ H5F__super_init(H5F_t *f, hid_t dxpl_id) /* Sanity check the userblock size vs. the file's allocation alignment */ if(userblock_size > 0) { - /* Set up the alignment to use for page or aggr fs */ - hsize_t alignment = H5F_PAGED_AGGR(f) ? f->shared->fs_page_size : f->shared->alignment; + /* Set up the alignment to use for page or aggr fs */ + hsize_t alignment = H5F_PAGED_AGGR(f) ? f->shared->fs_page_size : f->shared->alignment; if(userblock_size < alignment) HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "userblock size must be > file object alignment") diff --git a/src/H5Gobj.c b/src/H5Gobj.c index 832c9a7..5f9bdc8 100644 --- a/src/H5Gobj.c +++ b/src/H5Gobj.c @@ -185,7 +185,7 @@ H5G__obj_create_real(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo, H5G_obj_create_t *gcrt_info, H5O_loc_t *oloc/*out*/) { size_t hdr_size; /* Size of object header to request */ - hbool_t use_v18_latest_format; /* Flag indicating the new group format should be used */ + hbool_t use_at_least_v18; /* Flag indicating the new group format should be used */ hid_t gcpl_id = gcrt_info->gcpl_id; /* Group creation property list ID */ herr_t ret_value = SUCCEED; /* Return value */ @@ -204,12 +204,12 @@ H5G__obj_create_real(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo, if(0 == (H5F_INTENT(f) & H5F_ACC_RDWR)) HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "no write intent on file") - /* Check for using the latest version of the group format */ + /* Check for using the latest version of the group format which is introduced in v18 */ /* (add more checks for creating "new format" groups when needed) */ if((H5F_LOW_BOUND(f) >= H5F_LIBVER_V18) || linfo->track_corder || (pline && pline->nused)) - use_v18_latest_format = TRUE; + use_at_least_v18 = TRUE; else - use_v18_latest_format = FALSE; + use_at_least_v18 = FALSE; /* Make certain that the creation order is being tracked if an index is * going to be built on it. @@ -218,7 +218,7 @@ H5G__obj_create_real(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo, HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "must track creation order to create index for it") /* Check if we should be using the latest version of the group format */ - if(use_v18_latest_format) { + if(use_at_least_v18) { H5O_link_t lnk; /* Temporary link message info for computing message size */ char null_char = '\0'; /* Character for creating null string */ size_t ginfo_size; /* Size of the group info message */ @@ -264,7 +264,7 @@ H5G__obj_create_real(H5F_t *f, hid_t dxpl_id, const H5O_ginfo_t *ginfo, HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create header") /* Check for format of group to create */ - if(use_v18_latest_format) { + if(use_at_least_v18) { /* Insert link info message */ /* (Casting away const OK - QAK) */ if(H5O_msg_create(oloc, H5O_LINFO_ID, 0, H5O_UPDATE_TIME, (void *)linfo, dxpl_id) < 0) diff --git a/src/H5Oattr.c b/src/H5Oattr.c index 5c45e82..773a16b 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -635,6 +635,8 @@ H5O_attr_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *native_src, HDassert(cpy_info); HDassert(cpy_info->file_dst); + /* Check to ensure that the version of the message to be copied does not exceed + the message version allowed by the destination file's high bound */ if(attr_src->shared->version > H5O_attr_ver_bounds[H5F_HIGH_BOUND(cpy_info->file_dst)]) HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "attribute message version out of bounds") diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c index aa26f05..74c02f4 100644 --- a/src/H5Ocopy.c +++ b/src/H5Ocopy.c @@ -416,6 +416,7 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/, /* Initialize header information */ oh_dst->version = oh_src->version; + /* Version bounds check for destination object header */ if(oh_dst->version > H5O_obj_ver_bounds[H5F_HIGH_BOUND(oloc_dst->file)]) HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "destination object header version out of bounds") @@ -494,7 +495,12 @@ H5O_copy_header_real(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out*/, /* Decode the message if necessary. */ H5O_LOAD_NATIVE(oloc_src->file, dxpl_id, 0, oh_src, mesg_src, FAIL) + /* Save destination file pointer in cpy_info so that it can be used + in the pre_copy_file callback to obtain the destination file's + high bound. The high bound is used to index into the corresponding + message's array of versions for doing version bounds check. */ cpy_info->file_dst = oloc_dst->file; + /* Perform "pre copy" operation on message */ if((copy_type->pre_copy_file)(oloc_src->file, mesg_src->native, &(deleted[mesgno]), cpy_info, cpy_udata) < 0) diff --git a/src/H5Odtype.c b/src/H5Odtype.c index f6331df..c51e31d 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -1531,6 +1531,8 @@ H5O_dtype_pre_copy_file(H5F_t *file_src, const void *mesg_src, HDassert(cpy_info); HDassert(cpy_info->file_dst); + /* Check to ensure that the version of the message to be copied does not exceed + the message version as indicated by the destination file's high bound */ if(dt_src->shared->version > H5O_dtype_ver_bounds[H5F_HIGH_BOUND(cpy_info->file_dst)]) HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "datatype message version out of bounds") diff --git a/src/H5Ofill.c b/src/H5Ofill.c index cf64594..6dc3064 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -156,7 +156,7 @@ const H5O_msg_class_t H5O_MSG_FILL_NEW[1] = {{ /* Format version bounds for fill value */ const unsigned H5O_fill_ver_bounds[] = { H5O_FILL_VERSION_1, /* H5F_LIBVER_EARLIEST */ - H5O_FILL_VERSION_3, /* H5F_LIBVER_V18 */ + H5O_FILL_VERSION_2, /* H5F_LIBVER_V18 */ H5O_FILL_VERSION_LATEST /* H5F_LIBVER_LATEST */ }; @@ -809,8 +809,7 @@ H5O_fill_free(void *fill) * Return: Success: Non-negative * Failure: Negative * - * Programmer: Quincey Koziol - * Friday, March 9, 2007 + * Programmer: Vailin Choi; Dec 2017 * *------------------------------------------------------------------------- */ @@ -827,6 +826,8 @@ H5O_fill_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *mesg_src, HDassert(cpy_info); HDassert(cpy_info->file_dst); + /* Check to ensure that the version of the message to be copied does not exceed + the message version allowed by the destination file's high bound */ if(fill_src->version > H5O_fill_ver_bounds[H5F_HIGH_BOUND(cpy_info->file_dst)]) HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "fill value message version out of bounds") @@ -1047,15 +1048,15 @@ done: * * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * Tuesday, July 24, 2007 + * Programmer: Vailin Choi; December 2017 * *------------------------------------------------------------------------- */ herr_t H5O_fill_set_version(H5F_t *f, H5O_fill_t *fill) { - herr_t ret_value = SUCCEED; /* Return value */ + unsigned version; /* Message version */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -1064,12 +1065,15 @@ H5O_fill_set_version(H5F_t *f, H5O_fill_t *fill) HDassert(fill); /* Upgrade to the version indicated by the file's low bound if higher */ - fill->version = MAX(fill->version, H5O_fill_ver_bounds[H5F_LOW_BOUND(f)]); + version = MAX(fill->version, H5O_fill_ver_bounds[H5F_LOW_BOUND(f)]); - /* File bound check */ - if(fill->version > H5O_fill_ver_bounds[H5F_HIGH_BOUND(f)]) + /* Version bounds check */ + if(version > H5O_fill_ver_bounds[H5F_HIGH_BOUND(f)]) HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "Filter pipeline version out of bounds") + /* Set the message version */ + fill->version = version; + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_fill_set_version() */ diff --git a/src/H5Oint.c b/src/H5Oint.c index 0df7467..08eb28d 100644 --- a/src/H5Oint.c +++ b/src/H5Oint.c @@ -216,18 +216,17 @@ H5O__init_package(void) * Chooses the oldest version possible, unless the file's * low bound indicates otherwise. * - * Return: Success: Non-negative - * Failure: Negative + * Return: Success: Non-negative + * Failure: Negative * - * Programmer: Quincey Koziol - * koziol@hdfgroup.org - * Jul 17 2007 + * Programmer: Vailin Choi; December 2017 * *------------------------------------------------------------------------- */ static herr_t H5O_set_version(H5F_t *f, H5O_t *oh, uint8_t oh_flags, hbool_t store_msg_crt_idx) { + uint8_t version; /* Message version */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -238,17 +237,20 @@ H5O_set_version(H5F_t *f, H5O_t *oh, uint8_t oh_flags, hbool_t store_msg_crt_idx /* Set the correct version to encode object header with */ if(store_msg_crt_idx || (oh_flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)) - oh->version = H5O_VERSION_2; + version = H5O_VERSION_LATEST; else - oh->version = H5O_VERSION_1; + version = H5O_VERSION_1; /* Upgrade to the version indicated by the file's low bound if higher */ - oh->version = MAX(oh->version, (uint8_t)H5O_obj_ver_bounds[H5F_LOW_BOUND(f)]); + version = MAX(version, (uint8_t)H5O_obj_ver_bounds[H5F_LOW_BOUND(f)]); - /* File bound check */ - if(oh->version > H5O_obj_ver_bounds[H5F_HIGH_BOUND(f)]) + /* Version bounds check */ + if(version > H5O_obj_ver_bounds[H5F_HIGH_BOUND(f)]) HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "object header version out of bounds") + /* Set the message version */ + oh->version = version; + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_set_version() */ diff --git a/src/H5Olayout.c b/src/H5Olayout.c index 3745f6d..85d7791 100644 --- a/src/H5Olayout.c +++ b/src/H5Olayout.c @@ -1055,8 +1055,7 @@ done: * Return: Success: Non-negative * Failure: Negative * - * Programmer: Quincey Koziol - * Friday, March 9, 2007 + * Programmer: Vailin Choi; Dec 2017 * *------------------------------------------------------------------------- */ @@ -1073,6 +1072,8 @@ H5O__layout_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *mesg_src, HDassert(cpy_info); HDassert(cpy_info->file_dst); + /* Check to ensure that the version of the message to be copied does not exceed + the message version allowed by the destination file's high bound */ if(layout_src->version > H5O_layout_ver_bounds[H5F_HIGH_BOUND(cpy_info->file_dst)]) HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "layout message version out of bounds") diff --git a/src/H5Opkg.h b/src/H5Opkg.h index 13e0e3e..498938a 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -63,8 +63,8 @@ ) #define H5O_ALIGN_OH(O, X) \ H5O_ALIGN_VERS((O)->version, X) -#define H5O_ALIGN_F(F, X) \ - H5O_ALIGN_VERS(((H5F_LOW_BOUND(F) >= H5F_LIBVER_V18) ? H5O_VERSION_LATEST : H5O_VERSION_1), X) +#define H5O_ALIGN_F(F, X) \ + H5O_ALIGN_VERS(MAX(H5O_VERSION_1, (uint8_t)H5O_obj_ver_bounds[H5F_LOW_BOUND(F)]), X) /* Size of checksum (on disk) */ #define H5O_SIZEOF_CHKSUM 4 @@ -136,7 +136,7 @@ #define H5O_SIZEOF_MSGHDR_OH(O) \ H5O_SIZEOF_MSGHDR_VERS((O)->version, (O)->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED) #define H5O_SIZEOF_MSGHDR_F(F, C) \ - H5O_SIZEOF_MSGHDR_VERS(((H5F_LOW_BOUND(F) >= H5F_LIBVER_V18) || H5F_STORE_MSG_CRT_IDX(F)) ? H5O_VERSION_LATEST : H5O_VERSION_1, (C)) + H5O_SIZEOF_MSGHDR_VERS(MAX((H5F_STORE_MSG_CRT_IDX(F) ? H5O_VERSION_LATEST : H5O_VERSION_1), (uint8_t)H5O_obj_ver_bounds[H5F_LOW_BOUND(F)]), (C)) /* * Size of chunk "header" for each chunk @@ -641,6 +641,8 @@ H5_DLL herr_t H5O_attr_link(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, void *_mesg H5_DLL herr_t H5O_attr_count_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, hsize_t *nattrs); +/* Arrays of versions for: + Object header, Layout/Attribute/Datatype/Fill value/Filter pipeline/Dataspace messages */ H5_DLLVAR const unsigned H5O_obj_ver_bounds[H5F_LIBVER_NBOUNDS]; H5_DLLVAR const unsigned H5O_layout_ver_bounds[H5F_LIBVER_NBOUNDS]; H5_DLLVAR const unsigned H5O_attr_ver_bounds[H5F_LIBVER_NBOUNDS]; diff --git a/src/H5Opline.c b/src/H5Opline.c index ea913da..e817f9a 100644 --- a/src/H5Opline.c +++ b/src/H5Opline.c @@ -576,7 +576,7 @@ H5O_pline_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *mesg_src, { const H5O_pline_t *pline_src = (const H5O_pline_t *)mesg_src; /* Source pline */ H5O_copy_file_ud_common_t *udata = (H5O_copy_file_ud_common_t *)_udata; /* Object copying user data */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -585,6 +585,8 @@ H5O_pline_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *mesg_src, HDassert(cpy_info); HDassert(cpy_info->file_dst); + /* Check to ensure that the version of the message to be copied does not exceed + the message version allowed by the destination file's high bound */ if(pline_src->version > H5O_pline_ver_bounds[H5F_HIGH_BOUND(cpy_info->file_dst)]) HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "pline message version out of bounds") @@ -681,15 +683,15 @@ H5O_pline_debug(H5F_t H5_ATTR_UNUSED *f, hid_t H5_ATTR_UNUSED dxpl_id, const voi * * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * Tuesday, July 24, 2007 + * Programmer: Vailin Choi; December 2017 * *------------------------------------------------------------------------- */ herr_t H5O_pline_set_version(H5F_t *f, H5O_pline_t *pline) { - herr_t ret_value = SUCCEED; /* Return value */ + unsigned version; /* Message version */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -698,12 +700,15 @@ H5O_pline_set_version(H5F_t *f, H5O_pline_t *pline) HDassert(pline); /* Upgrade to the version indicated by the file's low bound if higher */ - pline->version = MAX(pline->version, H5O_pline_ver_bounds[H5F_LOW_BOUND(f)]); + version = MAX(pline->version, H5O_pline_ver_bounds[H5F_LOW_BOUND(f)]); - /* File bound check */ - if(pline->version > H5O_pline_ver_bounds[H5F_HIGH_BOUND(f)]) + /* Version bounds check */ + if(version > H5O_pline_ver_bounds[H5F_HIGH_BOUND(f)]) HGOTO_ERROR(H5E_PLINE, H5E_BADRANGE, FAIL, "Filter pipeline version out of bounds") + /* Set the message version */ + pline->version = version; + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_pline_set_version() */ diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 5cf9dce..2253bb2 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -178,7 +178,11 @@ typedef struct H5O_copy_t { hbool_t dst_dt_list_complete; /* Whether the destination datatype list is complete (i.e. not only populated with "suggestions" from H5Padd_merge_committed_dtype_path) */ H5O_t *oh_dst; /* The destination object header */ H5F_t *file_dst; /* The destination file pointer */ - void *shared_fo; /* The shared pointer for the object */ + /* This is used in the pre_copy_file callback to obtain + the destination file's high bound. The high bound + is used to index into the corresponding message's + array of versions for doing version bounds check. */ + void *shared_fo; /* The shared pointer for the src object */ H5O_mcdt_search_cb_t mcdt_cb; /* The callback to invoke before searching the global list of committed datatypes at destination */ void *mcdt_ud; /* User data passed to callback */ } H5O_copy_t; diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c index 9a9d020..12a9bb6 100644 --- a/src/H5Osdspace.c +++ b/src/H5Osdspace.c @@ -455,6 +455,8 @@ H5O_sdspace_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *mesg_src, HDassert(cpy_info); HDassert(cpy_info->file_dst); + /* Check to ensure that the version of the message to be copied does not exceed + the message version allowed by the destination file's high bound */ if(src_space_extent->version > H5O_sdspace_ver_bounds[H5F_HIGH_BOUND(cpy_info->file_dst)]) HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "dataspace message version out of bounds") @@ -2180,15 +2180,15 @@ H5S_extent_nelem(const H5S_extent_t *ext) * * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * Tuesday, July 24, 2007 + * Programmer: Vailin Choi; December 2017 * *------------------------------------------------------------------------- */ herr_t H5S_set_version(H5F_t *f, H5S_t *ds) { - herr_t ret_value = SUCCEED; /* Return value */ + unsigned version; /* Message version */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -2197,12 +2197,15 @@ H5S_set_version(H5F_t *f, H5S_t *ds) HDassert(ds); /* Upgrade to the version indicated by the file's low bound if higher */ - ds->extent.version = MAX(ds->extent.version, H5O_sdspace_ver_bounds[H5F_LOW_BOUND(f)]); + version = MAX(ds->extent.version, H5O_sdspace_ver_bounds[H5F_LOW_BOUND(f)]); - /* File bound check */ - if(ds->extent.version > H5O_sdspace_ver_bounds[H5F_HIGH_BOUND(f)]) + /* Version bounds check */ + if(version > H5O_sdspace_ver_bounds[H5F_HIGH_BOUND(f)]) HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "Dataspace version out of bounds") + /* Set the message version */ + ds->extent.version = version; + done: FUNC_LEAVE_NOAPI(ret_value) @@ -5418,8 +5418,7 @@ done: * * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * Thursday, July 19, 2007 + * Programmer: Vailin Choi; December 2017 * *------------------------------------------------------------------------- */ @@ -5442,7 +5441,7 @@ H5T_set_version(H5F_t *f, H5T_t *dt) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't upgrade datatype encoding") } - /* File bound check */ + /* Version bounds check */ if(dt->shared->version > H5O_dtype_ver_bounds[H5F_HIGH_BOUND(f)]) HGOTO_ERROR(H5E_DATATYPE, H5E_BADRANGE, FAIL, "Datatype version out of bounds") diff --git a/src/H5trace.c b/src/H5trace.c index 5f8ccd1..b1f05ba 100644 --- a/src/H5trace.c +++ b/src/H5trace.c @@ -1021,7 +1021,8 @@ H5_trace(const double *returning, const char *func, const char *type, ...) fprintf(out, "H5F_LIBVER_V18"); break; - case H5F_LIBVER_LATEST: + case H5F_LIBVER_V110: + HDassert(H5F_LIBVER_LATEST == H5F_LIBVER_V110); fprintf(out, "H5F_LIBVER_LATEST"); break; |