diff options
author | Neil Fortner <nfortne2@hdfgroup.org> | 2008-08-11 15:16:34 (GMT) |
---|---|---|
committer | Neil Fortner <nfortne2@hdfgroup.org> | 2008-08-11 15:16:34 (GMT) |
commit | 4f61812180385bb969fee33eece609180cab4866 (patch) | |
tree | bf907a614a6d65c339888097281d1d32409b1011 /src/H5Odtype.c | |
parent | 9474f434a37ee313be94b0388af4322ecdace648 (diff) | |
download | hdf5-4f61812180385bb969fee33eece609180cab4866.zip hdf5-4f61812180385bb969fee33eece609180cab4866.tar.gz hdf5-4f61812180385bb969fee33eece609180cab4866.tar.bz2 |
[svn-r15458] Purpose: Modify the library to take the proper action when files with incorrectinactive/jpeg_converter
datatype versions are encountered.
Description: The library now recognizes some problems with datatype versions in
H5O_decode_helper(), and, if not performing strict format checks, automatically
corrects them. Framework added for other message decode routines to
automatically correct file errors. Datatype version information added to
h5debug.
Tested: kagiso, smirom, linew (h5committest)
Diffstat (limited to 'src/H5Odtype.c')
-rw-r--r-- | src/H5Odtype.c | 95 |
1 files changed, 77 insertions, 18 deletions
diff --git a/src/H5Odtype.c b/src/H5Odtype.c index ba343bc..9c669e0 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -29,7 +29,8 @@ /* PRIVATE PROTOTYPES */ static herr_t H5O_dtype_encode(H5F_t *f, uint8_t *p, const void *mesg); -static void *H5O_dtype_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, const uint8_t *p); +static void *H5O_dtype_decode(H5F_t *f, hid_t dxpl_id, unsigned mesg_flags, + unsigned *ioflags, const uint8_t *p); static void *H5O_dtype_copy(const void *_mesg, void *_dest); static size_t H5O_dtype_size(const H5F_t *f, const void *_mesg); static herr_t H5O_dtype_reset(void *_mesg); @@ -65,6 +66,25 @@ static herr_t H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, #define H5O_SHARED_DEBUG_REAL H5O_dtype_debug #include "H5Oshared.h" /* Shared Object Header Message Callbacks */ +/* Macros to check for the proper version of a datatype */ +#ifdef H5_STRICT_FORMAT_CHECKS +/* If the version is too low, give an error. No error if nochange is set + * because in that case we are either debugging or deleting the object header */ +#define H5O_DTYPE_CHECK_VERSION(DT, VERS, MIN_VERS, IOF, CLASS, ERR) \ + if(((VERS) < (MIN_VERS)) && !(*(IOF) & H5O_DECODEIO_NOCHANGE)) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_VERSION, ERR, "incorrect " CLASS " datatype version") +#else /* H5_STRICT_FORMAT_CHECKS */ +/* If the version is too low and we are allowed to change the message, upgrade + * it and mark the object header as dirty */ +#define H5O_DTYPE_CHECK_VERSION(DT, VERS, MIN_VERS, IOF, CLASS, ERR) \ + if(((VERS) < (MIN_VERS)) && !(*(IOF) & H5O_DECODEIO_NOCHANGE)) { \ + (VERS) = (MIN_VERS); \ + if(H5T_upgrade_version((DT), (VERS)) < 0) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't upgrade " CLASS " encoding version") \ + *(IOF) |= H5O_DECODEIO_DIRTY; \ + } /* end if */ +#endif /* H5_STRICT_FORMAT_CHECKS */ + /* This message derives from H5O message class */ const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{ H5O_DTYPE_ID, /* message id number */ @@ -103,7 +123,7 @@ const H5O_msg_class_t H5O_MSG_DTYPE[1] = {{ *------------------------------------------------------------------------- */ static herr_t -H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt) +H5O_dtype_decode_helper(H5F_t *f, unsigned *ioflags/*in,out*/, const uint8_t **pp, H5T_t *dt) { unsigned flags, version; unsigned i; @@ -233,6 +253,7 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt) { 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 */ unsigned j; /* Compute the # of bytes required to store a member offset */ @@ -297,13 +318,17 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* Decode the field's datatype information */ - if(H5O_dtype_decode_helper(f, pp, temp_type) < 0) { + if(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; + /* Go create the array datatype now, for older versions of the datatype message */ if(version == H5O_DTYPE_VERSION_1) { /* Check if this member is an array field */ @@ -372,6 +397,9 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt) dt->shared->u.compnd.packed = FALSE; } /* end if */ } /* end for */ + /* 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) } break; @@ -402,8 +430,14 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt) dt->shared->u.enumer.nmembs = dt->shared->u.enumer.nalloc = flags & 0xffff; if(NULL == (dt->shared->parent = H5T_alloc())) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - if(H5O_dtype_decode_helper(f, pp, dt->shared->parent) < 0) + if(H5O_dtype_decode_helper(f, ioflags, pp, dt->shared->parent) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode parent datatype") + + /* Check if the parent of this enum has a version greater than the + * enum itself. */ + H5O_DTYPE_CHECK_VERSION(dt, version, dt->shared->parent->shared->version, + ioflags, "enum", FAIL) + if(NULL == (dt->shared->u.enumer.name = (char **)H5MM_calloc(dt->shared->u.enumer.nalloc * sizeof(char*))) || NULL == (dt->shared->u.enumer.value = (uint8_t *)H5MM_calloc(dt->shared->u.enumer.nalloc * dt->shared->parent->shared->size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") @@ -438,9 +472,14 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt) /* Decode base type of VL information */ if(NULL == (dt->shared->parent = H5T_alloc())) HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "memory allocation failed") - if(H5O_dtype_decode_helper(f, pp, dt->shared->parent) < 0) + if(H5O_dtype_decode_helper(f, ioflags, pp, dt->shared->parent) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode VL parent type") + /* Check if the parent of this vlen has a version greater than the + * vlen itself. */ + H5O_DTYPE_CHECK_VERSION(dt, version, dt->shared->parent->shared->version, + ioflags, "vlen", FAIL) + dt->shared->force_conv=TRUE; /* Mark this type as on disk */ if(H5T_set_loc(dt, f, H5T_LOC_DISK) < 0) @@ -471,8 +510,17 @@ H5O_dtype_decode_helper(H5F_t *f, const uint8_t **pp, H5T_t *dt) /* Decode base type of array */ if(NULL == (dt->shared->parent = H5T_alloc())) HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "memory allocation failed") - if(H5O_dtype_decode_helper(f, pp, dt->shared->parent) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode VL parent type") + if(H5O_dtype_decode_helper(f, ioflags, pp, dt->shared->parent) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode array parent type") + + /* Check if the parent of this array has a version greater than the + * array itself. */ + H5O_DTYPE_CHECK_VERSION(dt, version, dt->shared->parent->shared->version, + ioflags, "array", FAIL) + + /* There should be no array datatypes with version < 2. */ + H5O_DTYPE_CHECK_VERSION(dt, version, H5O_DTYPE_VERSION_2, ioflags, + "array", FAIL) /* * Set the "force conversion" flag if a VL base datatype is used or @@ -757,6 +805,9 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) /* Sanity check */ /* (compound datatypes w/array members must be encoded w/version >= 2) */ HDassert(dt->shared->u.compnd.memb[i].type->shared->type != H5T_ARRAY || dt->shared->version >= H5O_DTYPE_VERSION_2); + + /* Check that the version is at least as great as the member */ + HDassert(dt->shared->version >= dt->shared->u.compnd.memb[i].type->shared->version); /* Name */ HDstrcpy((char*)(*pp), dt->shared->u.compnd.memb[i].name); @@ -817,6 +868,9 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) break; case H5T_ENUM: + /* Check that the version is at least as great as the parent */ + HDassert(dt->shared->version >= dt->shared->parent->shared->version); + /* * Enumeration datatypes... */ @@ -849,6 +903,9 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) break; case H5T_VLEN: /* Variable length datatypes... */ + /* Check that the version is at least as great as the parent */ + HDassert(dt->shared->version >= dt->shared->parent->shared->version); + flags |= (dt->shared->u.vlen.type & 0x0f); if(dt->shared->u.vlen.type == H5T_VLEN_STRING) { flags |= (dt->shared->u.vlen.pad & 0x0f) << 4; @@ -864,6 +921,12 @@ H5O_dtype_encode_helper(const H5F_t *f, uint8_t **pp, const H5T_t *dt) /* Double-check the number of dimensions */ HDassert(dt->shared->u.array.ndims <= H5S_MAX_RANK); + /* Check that the version is valid */ + HDassert(dt->shared->version >= H5O_DTYPE_VERSION_2); + + /* Check that the version is at least as great as the parent */ + HDassert(dt->shared->version >= dt->shared->parent->shared->version); + /* Encode the number of dimensions */ *(*pp)++ = dt->shared->u.array.ndims; @@ -927,7 +990,8 @@ done: function using malloc() and is returned to the caller. --------------------------------------------------------------------------*/ static void * -H5O_dtype_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags, const uint8_t *p) +H5O_dtype_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags, + unsigned *ioflags/*in,out*/, const uint8_t *p) { H5T_t *dt = NULL; void *ret_value; /* Return value */ @@ -942,21 +1006,13 @@ H5O_dtype_decode(H5F_t *f, hid_t UNUSED dxpl_id, unsigned UNUSED mesg_flags, con HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Perform actual decode of message */ - if(H5O_dtype_decode_helper(f, &p, dt) < 0) + if(H5O_dtype_decode_helper(f, ioflags, &p, dt) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, NULL, "can't decode type") /* Set return value */ ret_value = dt; done: - if(ret_value == NULL) { - if(dt != NULL) { - if(dt->shared != NULL) - H5FL_FREE(H5T_shared_t, dt->shared); - H5FL_FREE(H5T_t, dt); - } /* end if */ - } /* end if */ - FUNC_LEAVE_NOAPI(ret_value) } /* end H5O_dtype_decode() */ @@ -1522,6 +1578,9 @@ H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *stream, fprintf(stream, "%*s%-*s %lu byte%s\n", indent, "", fwidth, "Size:", (unsigned long)(dt->shared->size), 1 == dt->shared->size ? "" : "s"); + + fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Version:", dt->shared->version); if (H5T_COMPOUND == dt->shared->type) { fprintf(stream, "%*s%-*s %d\n", indent, "", fwidth, @@ -1815,7 +1874,7 @@ H5O_dtype_debug(H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *stream, "Sign scheme:", s); } } - + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O_dtype_debug() */ |