summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5B.c44
-rw-r--r--src/H5Bprivate.h4
-rw-r--r--src/H5F.c3
-rw-r--r--src/H5Fdbg.c35
-rw-r--r--src/H5Fpkg.h3
-rw-r--r--src/H5Fsuper.c3
-rw-r--r--src/H5G.c18
-rw-r--r--src/H5Gobj.c40
-rw-r--r--src/H5Gpkg.h8
-rw-r--r--src/H5Gprivate.h3
-rw-r--r--src/H5Gstab.c75
-rw-r--r--src/H5Odtype.c51
-rw-r--r--src/H5Omessage.c2
-rw-r--r--src/H5Oprivate.h1
14 files changed, 251 insertions, 39 deletions
diff --git a/src/H5B.c b/src/H5B.c
index 8b2b45c..5d3ce48 100644
--- a/src/H5B.c
+++ b/src/H5B.c
@@ -2057,3 +2057,47 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B_get_info() */
+#ifndef H5_STRICT_FORMAT_CHECKS
+
+/*-------------------------------------------------------------------------
+ * Function: H5B_valid
+ *
+ * Purpose: Attempt to load a b-tree node.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * March 17, 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5B_valid(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr)
+{
+ H5B_t *bt; /* The btree */
+ htri_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5B_valid, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(type);
+
+ if(!H5F_addr_defined(addr))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "address is undefined")
+
+ /* Protect the node */
+ if(NULL == (bt = (H5B_t *)H5AC_protect(f, dxpl_id, H5AC_BT, addr, type, NULL, H5AC_READ)))
+ HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, FAIL, "unable to load B-tree node")
+
+ /* Release the node */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5B_valid() */
+#endif /* H5_STRICT_FORMAT_CHECKS */
+
diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h
index 93c2d80..2ec2c22 100644
--- a/src/H5Bprivate.h
+++ b/src/H5Bprivate.h
@@ -168,5 +168,9 @@ H5_DLL H5B_shared_t *H5B_shared_new(const H5F_t *f, const H5B_class_t *type,
H5_DLL herr_t H5B_shared_free(void *_shared);
H5_DLL herr_t H5B_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream,
int indent, int fwidth, const H5B_class_t *type, void *udata);
+#ifndef H5_STRICT_FORMAT_CHECKS
+H5_DLL htri_t H5B_valid(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type,
+ haddr_t addr);
+#endif /* H5_STRICT_FORMAT_CHECKS */
#endif /* _H5Bprivate_H */
diff --git a/src/H5F.c b/src/H5F.c
index 7b9ce79..e7b4cd3 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -1115,6 +1115,9 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
f->shared->mtab.child = (H5F_mount_t *)H5MM_xfree(f->shared->mtab.child);
f->shared->mtab.nalloc = 0;
+ /* Free root group symbol table entry, if any */
+ f->shared->root_ent = H5MM_xfree(f->shared->root_ent);
+
/* Destroy shared file struct */
f->shared = (H5F_file_t *)H5FL_FREE(H5F_file_t, f->shared);
diff --git a/src/H5Fdbg.c b/src/H5Fdbg.c
index e05c32a..a4577c9 100644
--- a/src/H5Fdbg.c
+++ b/src/H5Fdbg.c
@@ -123,21 +123,26 @@ H5F_debug(H5F_t *f, FILE *stream, int indent, int fwidth)
"Root group symbol table entry:",
f->shared->root_grp ? "" : "(none)");
if(f->shared->root_grp) {
- H5O_loc_t *root_oloc; /* Root object location */
- H5G_entry_t root_ent; /* Constructed root symbol table entry */
-
- /* Reset the root group entry */
- H5G_ent_reset(&root_ent);
-
- /* Build up a simulated root group symbol table entry */
- root_oloc = H5G_oloc(f->shared->root_grp);
- HDassert(root_oloc);
- root_ent.type = H5G_NOTHING_CACHED;
- root_ent.header = root_oloc->addr;
- root_ent.file = f;
-
- /* Display root group symbol table entry info */
- H5G_ent_debug(f, &root_ent, stream, indent + 3, MAX(0, fwidth - 3), NULL);
+ if(f->shared->root_ent) /* Use real root group symbol table entry */
+ H5G_ent_debug(f, f->shared->root_ent, stream, indent + 3,
+ MAX(0, fwidth - 3), NULL);
+ else {
+ H5O_loc_t *root_oloc; /* Root object location */
+ H5G_entry_t root_ent; /* Constructed root symbol table entry */
+
+ /* Reset the root group entry */
+ H5G_ent_reset(&root_ent);
+
+ /* Build up a simulated root group symbol table entry */
+ root_oloc = H5G_oloc(f->shared->root_grp);
+ HDassert(root_oloc);
+ root_ent.type = H5G_NOTHING_CACHED;
+ root_ent.header = root_oloc->addr;
+ root_ent.file = f;
+
+ /* Display root group symbol table entry info */
+ H5G_ent_debug(f, &root_ent, stream, indent + 3, MAX(0, fwidth - 3), NULL);
+ }
} /* end if */
done:
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index cc74a80..4080705 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -158,6 +158,7 @@ typedef struct H5F_file_t {
int ncwfs; /* Num entries on cwfs list */
struct H5HG_heap_t **cwfs; /* Global heap cache */
struct H5G_t *root_grp; /* Open root group */
+ H5G_entry_t *root_ent; /* Root group symbol table entry */
H5FO_t *open_objs; /* Open objects in file */
H5RC_t *grp_btree_shared; /* Ref-counted group B-tree node info */
@@ -193,7 +194,7 @@ struct H5F_t {
H5FO_t *obj_count; /* # of time each object is opened through top file structure */
hid_t file_id; /* ID of this file */
hbool_t closing; /* File is in the process of being closed */
- struct H5F_t *parent; /* Parent file that this file is mounted to */
+ struct H5F_t *parent; /* Parent file that this file is mounted to */
unsigned nmounts; /* Number of children mounted to this file */
};
diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c
index 3c914bd..70e0954 100644
--- a/src/H5Fsuper.c
+++ b/src/H5Fsuper.c
@@ -383,7 +383,8 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
H5F_addr_decode(f, (const uint8_t **)&p, &shared->extension_addr/*out*/);
H5F_addr_decode(f, (const uint8_t **)&p, &stored_eoa/*out*/);
H5F_addr_decode(f, (const uint8_t **)&p, &shared->driver_addr/*out*/);
- if(H5G_obj_ent_decode(f, (const uint8_t **)&p, root_loc->oloc/*out*/) < 0)
+ if(H5G_obj_ent_decode(f, (const uint8_t **)&p, root_loc->oloc/*out*/,
+ &shared->root_ent/*out*/) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read root symbol entry")
/*
diff --git a/src/H5G.c b/src/H5G.c
index 6a7e505..042ce90 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -896,6 +896,24 @@ H5G_mkroot(H5F_t *f, hid_t dxpl_id, H5G_loc_t *loc)
*/
if(H5O_open(loc->oloc) < 0)
HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open root group")
+
+#ifndef H5_STRICT_FORMAT_CHECKS
+ /* If symbol table information is cached, check if we should replace the
+ * symbol table message with the cached symbol table information */
+ if((H5F_INTENT(f) & H5F_ACC_RDWR) && f->shared->root_ent
+ && (f->shared->root_ent->type == H5G_CACHED_STAB)) {
+ H5O_stab_t cached_stab;
+
+ /* Retrieve the cached symbol table information */
+ cached_stab.btree_addr = f->shared->root_ent->cache.stab.btree_addr;
+ cached_stab.heap_addr = f->shared->root_ent->cache.stab.heap_addr;
+
+ /* Check if the symbol table message is valid, and replace with the
+ * cached symbol table if necessary */
+ if(H5G_stab_valid(loc->oloc, dxpl_id, &cached_stab) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to verify symbol table")
+ } /* end if */
+#endif /* H5_STRICT_FORMAT_CHECKS */
} /* end else */
/* Create the path names for the root group's entry */
diff --git a/src/H5Gobj.c b/src/H5Gobj.c
index 3220b67..2eb1924 100644
--- a/src/H5Gobj.c
+++ b/src/H5Gobj.c
@@ -237,31 +237,49 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5G_obj_ent_decode(H5F_t *f, const uint8_t **pp, H5O_loc_t *oloc)
+H5G_obj_ent_decode(H5F_t *f, const uint8_t **pp, H5O_loc_t *oloc, H5G_entry_t **entp)
{
const uint8_t *p_ret = *pp;
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOFUNC(H5G_obj_ent_decode)
+ FUNC_ENTER_NOAPI(H5G_obj_ent_decode, FAIL)
/* check arguments */
HDassert(f);
HDassert(pp);
HDassert(oloc);
- /* Set file pointer for root object location */
- oloc->file = f;
+ if(entp) {
+ /* If entp is not NULL we allocate space for the symbol table entry and
+ * decode the entire entry. */
+ if(!(*entp)) /* Only allocate space if *entp is NULL */
+ if(NULL == (*entp = (H5G_entry_t *) H5MM_calloc(sizeof(H5G_entry_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate space for symbol table entry")
+ if(H5G_ent_decode_vec(f, pp, *entp, 1) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode symbol table entry")
+
+ /* Set oloc to the correct values */
+ oloc->file = (*entp)->file;
+ oloc->addr = (*entp)->header;
+ } else {
+ /* Set file pointer for root object location */
+ oloc->file = f;
+
+ /* decode header */
+ *pp += H5F_SIZEOF_SIZE(f); /* Skip over local heap address */
+ H5F_addr_decode(f, pp, &(oloc->addr));
+ *pp += 4; /* Skip over "cache type" */
+ *pp += 4; /* Reserved */
+ }
+
+ /* Common oloc settings */
oloc->holding_file = FALSE;
- /* decode header */
- *pp += H5F_SIZEOF_SIZE(f); /* Skip over local heap address */
- H5F_addr_decode(f, pp, &(oloc->addr));
- *pp += 4; /* Skip over "cache type" */
- *pp += 4; /* Reserved */
-
/* Set decode pointer */
*pp = p_ret + H5G_SIZEOF_ENTRY(f);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_obj_ent_decode() */
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index 31e5713..38c7628 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -100,14 +100,14 @@ typedef union H5G_cache_t {
* also appears in the object header to which this symbol table entry
* points.
*/
-typedef struct H5G_entry_t {
+struct H5G_entry_t {
hbool_t dirty; /*entry out-of-date? */
H5G_cache_type_t type; /*type of information cached */
H5G_cache_t cache; /*cached data from object header */
size_t name_off; /*offset of name within name heap */
haddr_t header; /*file address of object header */
H5F_t *file; /*file to which this obj hdr belongs */
-} H5G_entry_t;
+};
/*
* A symbol table node is a collection of symbol table entries. It can
@@ -402,6 +402,10 @@ H5_DLL herr_t H5G_stab_lookup(H5O_loc_t *grp_oloc, const char *name,
H5O_link_t *lnk, hid_t dxpl_id);
H5_DLL herr_t H5G_stab_lookup_by_idx(H5O_loc_t *grp_oloc, H5_iter_order_t order,
hsize_t n, H5O_link_t *lnk, hid_t dxpl_id);
+#ifndef H5_STRICT_FORMAT_CHECKS
+H5_DLL herr_t H5G_stab_valid(H5O_loc_t *grp_oloc, hid_t dxpl_id,
+ H5O_stab_t *alt_stab);
+#endif /* H5_STRICT_FORMAT_CHECKS */
#ifndef H5_NO_DEPRECATED_SYMBOLS
H5_DLL H5G_obj_t H5G_stab_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx,
hid_t dxpl_id);
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index 591be6b..b1db96f 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -145,6 +145,7 @@ typedef struct {
typedef struct H5G_t H5G_t;
typedef struct H5G_shared_t H5G_shared_t;
+typedef struct H5G_entry_t H5G_entry_t;
/*
* Library prototypes... These are the ones that other packages routinely
@@ -181,7 +182,7 @@ H5_DLL herr_t H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream
* These functions operate on group object locations.
*/
H5_DLL herr_t H5G_obj_ent_decode(H5F_t *f, const uint8_t **pp,
- struct H5O_loc_t *oloc);
+ struct H5O_loc_t *oloc, H5G_entry_t **entp);
H5_DLL herr_t H5G_obj_ent_encode(const H5F_t *f, uint8_t **pp,
const struct H5O_loc_t *oloc);
diff --git a/src/H5Gstab.c b/src/H5Gstab.c
index f79d78b..c2df8e7 100644
--- a/src/H5Gstab.c
+++ b/src/H5Gstab.c
@@ -982,6 +982,81 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_stab_lookup_by_idx() */
+#ifndef H5_STRICT_FORMAT_CHECKS
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_stab_valid
+ *
+ * Purpose: Verify that a group's symbol table message is valid. If
+ * provided, the addresses in alt_stab will be tried if the
+ * addresses in the group's stab message are invalid, and
+ * the stab message will be updated if necessary.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * nfortne2@hdfgroup.org
+ * Mar 17, 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_stab_valid(H5O_loc_t *grp_oloc, hid_t dxpl_id, H5O_stab_t *alt_stab)
+{
+ H5O_stab_t stab; /* Current symbol table */
+ H5HL_t *heap = NULL; /* Pointer to local heap */
+ hbool_t changed = FALSE; /* Whether stab has been modified */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_stab_valid, FAIL)
+
+ /* Read the symbol table message */
+ H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, dxpl_id);
+
+ /* Check if the symbol table message's b-tree address is valid */
+ if(H5B_valid(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr) < 0) {
+ /* Address is invalid, try the b-tree address in the alternate symbol
+ * table message */
+ if(!alt_stab || H5B_valid(grp_oloc->file, dxpl_id, H5B_SNODE, alt_stab->btree_addr) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to locate b-tree")
+ else {
+ /* The alternate symbol table's b-tree address is valid. Adjust the
+ * symbol table message in the group. */
+ stab.btree_addr = alt_stab->btree_addr;
+ changed = TRUE;
+ } /* end else */
+ } /* end if */
+
+ /* Check if the symbol table message's heap address is valid */
+ if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC_READ))) {
+ /* Address is invalid, try the heap address in the alternate symbol
+ * table message */
+ if(!alt_stab || NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, alt_stab->heap_addr, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "unable to locate heap")
+ else {
+ /* The alternate symbol table's heap address is valid. Adjust the
+ * symbol table message in the group. */
+ stab.heap_addr = alt_stab->heap_addr;
+ changed = TRUE;
+ } /* end else */
+ } /* end if */
+
+ /* Update the symbol table message and clear errors if necessary */
+ if(changed) {
+ H5E_clear_stack(NULL);
+ if(H5O_msg_write(grp_oloc, H5O_STAB_ID, 0, H5O_UPDATE_TIME | H5O_UPDATE_FORCE, &stab, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to correct symbol table message")
+ } /* end if */
+
+done:
+ /* Release resources */
+ if(heap && H5HL_unprotect(grp_oloc->file, dxpl_id, heap, stab.heap_addr) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_stab_valid */
+#endif /* H5_STRICT_FORMAT_CHECKS */
+
#ifndef H5_NO_DEPRECATED_SYMBOLS
/*-------------------------------------------------------------------------
diff --git a/src/H5Odtype.c b/src/H5Odtype.c
index 60f77d9..fe8c627 100644
--- a/src/H5Odtype.c
+++ b/src/H5Odtype.c
@@ -115,20 +115,23 @@ const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{
*
* Purpose: Decodes a datatype
*
- * Return: Non-negative on success/Negative on failure
+ * Return: TRUE if we can upgrade the parent type's version even
+ * with strict format checks
+ * FALSE if we cannot
+ * Negative on failure
*
* Programmer: Robb Matzke
* Monday, December 8, 1997
*
*-------------------------------------------------------------------------
*/
-static herr_t
+static htri_t
H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **pp, H5T_t *dt)
{
unsigned flags, version;
unsigned i;
size_t z;
- herr_t ret_value = SUCCEED; /* Return value */
+ htri_t ret_value = FALSE; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5O_dtype_decode_helper)
@@ -254,6 +257,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
unsigned offset_nbytes; /* Size needed to encode member offsets */
size_t max_memb_pos = 0; /* Maximum member covered, so far */
unsigned max_version = 0; /* Maximum member version */
+ hbool_t upgrade_to = 0; /* Version number we can "soft" upgrade to */
unsigned j;
/* Compute the # of bytes required to store a member offset */
@@ -271,6 +275,7 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
for(i = 0; i < dt->shared->u.compnd.nmembs; i++) {
unsigned ndims = 0; /* Number of dimensions of the array field */
+ htri_t can_upgrade; /* Whether we can upgrade this type's version */
hsize_t dim[H5O_LAYOUT_NDIMS]; /* Dimensions of the array */
H5T_t *array_dt; /* Temporary pointer to the array datatype */
H5T_t *temp_type; /* Temporary pointer to the field's datatype */
@@ -318,16 +323,20 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Decode the field's datatype information */
- if(H5O_dtype_decode_helper(f, ioflags, pp, temp_type) < 0) {
+ if((can_upgrade = H5O_dtype_decode_helper(f, ioflags, pp, temp_type)) < 0) {
for(j = 0; j <= i; j++)
H5MM_xfree(dt->shared->u.compnd.memb[j].name);
H5MM_xfree(dt->shared->u.compnd.memb);
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode member type")
} /* end if */
- /* Keep track of the maximum member version found */
- if(temp_type->shared->version > max_version)
- max_version = temp_type->shared->version;
+ /* Upgrade the version if we can and it is necessary */
+ if(can_upgrade && temp_type->shared->version > version) {
+ upgrade_to = temp_type->shared->version;
+
+ /* Pass "can_upgrade" flag down to parent type */
+ ret_value = TRUE;
+ } /* end if */
/* Go create the array datatype now, for older versions of the datatype message */
if(version == H5O_DTYPE_VERSION_1) {
@@ -346,9 +355,26 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
/* Make the array type the type that is set for the field */
temp_type = array_dt;
+
+ /* Reset array version if NOCHANGE is specified (i.e. h5debug) */
+ if(*ioflags & H5O_DECODEIO_NOCHANGE)
+ temp_type->shared->version = H5O_DTYPE_VERSION_1;
+ else {
+ /* Otherwise upgrade the compound version */
+ if(upgrade_to < temp_type->shared->version)
+ upgrade_to = temp_type->shared->version;
+
+ /* Set the return value to indicate that we should freely
+ * upgrade parent types */
+ ret_value = TRUE;
+ } /* end else */
} /* end if */
} /* end if */
+ /* Keep track of the maximum member version found */
+ if(temp_type->shared->version > max_version)
+ max_version = temp_type->shared->version;
+
/*
* Set the "force conversion" flag if VL datatype fields exist in this
* type or any component types
@@ -397,6 +423,17 @@ H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **p
dt->shared->u.compnd.packed = FALSE;
} /* end if */
} /* end for */
+
+ /* Upgrade the compound if requested */
+ if(version < upgrade_to) {
+ version = upgrade_to;
+ if(H5T_upgrade_version(dt, upgrade_to) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't upgrade compound encoding version")
+ /* We won't mark the message dirty since there were no
+ * errors in the file, simply type versions that we will no
+ * longer encode. */
+ } /* end if */
+
/* Check that no member of this compound has a version greater
* than the compound itself. */
H5O_DTYPE_CHECK_VERSION(dt, version, max_version, ioflags, "compound", FAIL)
diff --git a/src/H5Omessage.c b/src/H5Omessage.c
index 286240c..4a9ecb5 100644
--- a/src/H5Omessage.c
+++ b/src/H5Omessage.c
@@ -393,7 +393,7 @@ H5O_msg_write_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, const H5O_msg_class_t *ty
HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "message type not found")
/* Check for modifying a constant message */
- if(idx_msg->flags & H5O_MSG_FLAG_CONSTANT)
+ if(!(update_flags & H5O_UPDATE_FORCE) && (idx_msg->flags & H5O_MSG_FLAG_CONSTANT))
HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to modify constant message")
/* This message is shared, but it's being modified. */
else if((idx_msg->flags & H5O_MSG_FLAG_SHARED) || (idx_msg->flags & H5O_MSG_FLAG_SHAREABLE)) {
diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h
index c8611b3..82f6b12 100644
--- a/src/H5Oprivate.h
+++ b/src/H5Oprivate.h
@@ -79,6 +79,7 @@ typedef struct H5O_t H5O_t;
/* Flags for updating messages */
#define H5O_UPDATE_TIME 0x01u
+#define H5O_UPDATE_FORCE 0x02u /* Force updating the message */
/* Hash value constants */
#define H5O_HASH_SIZE 32