summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST1
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/H5A.c1074
-rw-r--r--src/H5Adeprec.c7
-rw-r--r--src/H5Aint.c1152
-rw-r--r--src/H5Apkg.h14
-rw-r--r--src/H5D.c193
-rw-r--r--src/H5Dint.c269
-rw-r--r--src/H5Dio.c111
-rw-r--r--src/H5Dprivate.h3
-rw-r--r--src/H5F.c1963
-rw-r--r--src/H5Fint.c2051
-rw-r--r--src/H5Fpkg.h6
-rw-r--r--src/H5Fprivate.h1
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.in29
-rw-r--r--test/testfiles/err_compat_15
17 files changed, 3660 insertions, 3222 deletions
diff --git a/MANIFEST b/MANIFEST
index a02497f..685022f 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -673,6 +673,7 @@
./src/H5Fdeprec.c
./src/H5Fefc.c
./src/H5Ffake.c
+./src/H5Fint.c
./src/H5Fio.c
./src/H5Fmount.c
./src/H5Fmpi.c
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8fd232b..d5d57d4 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -162,6 +162,7 @@ IDE_GENERATED_PROPERTIES ("H5EA" "${H5EA_HDRS}" "${H5EA_SRCS}" )
set (H5F_SRCS
${HDF5_SRC_DIR}/H5F.c
+ ${HDF5_SRC_DIR}/H5Fint.c
${HDF5_SRC_DIR}/H5Faccum.c
${HDF5_SRC_DIR}/H5Fcwfs.c
${HDF5_SRC_DIR}/H5Fdbg.c
diff --git a/src/H5A.c b/src/H5A.c
index 9a51214..a414689 100644
--- a/src/H5A.c
+++ b/src/H5A.c
@@ -63,10 +63,6 @@ typedef struct H5A_iter_cb1 {
/* Local Prototypes */
/********************/
-static herr_t H5A_open_common(const H5G_loc_t *loc, H5A_t *attr);
-static herr_t H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id);
-static herr_t H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id);
-
/*********************/
/* Package Variables */
@@ -229,6 +225,7 @@ hid_t
H5Acreate2(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id,
hid_t acpl_id, hid_t UNUSED aapl_id)
{
+ H5A_t *attr = NULL; /* Attribute created */
H5G_loc_t loc; /* Object location */
H5T_t *type; /* Datatype to use for attribute */
H5S_t *space; /* Dataspace to use for attribute */
@@ -252,10 +249,18 @@ H5Acreate2(hid_t loc_id, const char *attr_name, hid_t type_id, hid_t space_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
/* Go do the real work for attaching the attribute to the dataset */
- if((ret_value = H5A_create(&loc, attr_name, type, space, acpl_id, H5AC_dxpl_id)) < 0)
+ if(NULL == (attr = H5A_create(&loc, attr_name, type, space, acpl_id, H5AC_dxpl_id)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create attribute")
+ /* Register the new attribute and get an ID for it */
+ if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID")
+
done:
+ /* Cleanup on failure */
+ if(ret_value < 0 && attr && H5A_close(attr) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't close attribute")
+
FUNC_LEAVE_API(ret_value)
} /* H5Acreate2() */
@@ -296,6 +301,7 @@ H5Acreate_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
hid_t type_id, hid_t space_id, hid_t acpl_id, hid_t UNUSED aapl_id,
hid_t lapl_id)
{
+ H5A_t *attr = NULL; /* Attribute created */
H5G_loc_t loc; /* Object location */
H5G_loc_t obj_loc; /* Location used to open group */
H5G_name_t obj_path; /* Opened object group hier. path */
@@ -336,185 +342,21 @@ H5Acreate_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
loc_found = TRUE;
/* Go do the real work for attaching the attribute to the dataset */
- if((ret_value = H5A_create(&obj_loc, attr_name, type, space, acpl_id, H5AC_dxpl_id)) < 0)
+ if(NULL == (attr = H5A_create(&obj_loc, attr_name, type, space, acpl_id, H5AC_dxpl_id)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create attribute")
-done:
- /* Release resources */
- if(loc_found && H5G_loc_free(&obj_loc) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location")
-
- FUNC_LEAVE_API(ret_value)
-} /* H5Acreate_by_name() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5A_create
- *
- * Purpose:
- * This is the guts of creating an attribute.
- * Usage:
- * hid_t H5A_create(ent, name, type, space)
- * const H5G_entry_t *ent; IN: Pointer to symbol table entry for object to attribute
- * const char *name; IN: Name of attribute
- * H5T_t *type; IN: Datatype of attribute
- * H5S_t *space; IN: Dataspace of attribute
- * hid_t acpl_id IN: Attribute creation property list
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * April 2, 1998
- *
- *-------------------------------------------------------------------------
- */
-hid_t
-H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type,
- const H5S_t *space, hid_t acpl_id, hid_t dxpl_id)
-{
- H5A_t *attr = NULL; /* Attribute created */
- hssize_t snelmts; /* elements in attribute */
- size_t nelmts; /* elements in attribute */
- htri_t tri_ret; /* htri_t return value */
- hid_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT_TAG(dxpl_id, loc->oloc->addr, FAIL)
-
- /* check args */
- HDassert(loc);
- HDassert(name);
- HDassert(type);
- HDassert(space);
-
- /* Check for existing attribute with same name */
- /* (technically, the "attribute create" operation will fail for a duplicated
- * name, but it's going to be hard to unwind all the special cases on
- * failure, so just check first, for now - QAK)
- */
- if((tri_ret = H5O_attr_exists(loc->oloc, name, H5AC_ind_dxpl_id)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "error checking attributes")
- else if(tri_ret > 0)
- HGOTO_ERROR(H5E_ATTR, H5E_ALREADYEXISTS, FAIL, "attribute already exists")
-
- /* Check if the dataspace has an extent set (or is NULL) */
- if(!(H5S_has_extent(space)))
- HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "dataspace extent has not been set")
-
- /* Check if the datatype is "sensible" for use in a dataset */
- if(H5T_is_sensible(type) != TRUE)
- HGOTO_ERROR(H5E_ATTR, H5E_BADTYPE, FAIL, "datatype is not sensible")
-
- /* Build the attribute information */
- if(NULL == (attr = H5FL_CALLOC(H5A_t)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed for attribute info")
-
- if(NULL == (attr->shared = H5FL_CALLOC(H5A_shared_t)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "can't allocate shared attr structure")
-
- /* If the creation property list is H5P_DEFAULT, use the default character encoding */
- if(acpl_id == H5P_DEFAULT)
- attr->shared->encoding = H5F_DEFAULT_CSET;
- else {
- H5P_genplist_t *ac_plist; /* ACPL Property list */
-
- /* Get a local copy of the attribute creation property list */
- if(NULL == (ac_plist = (H5P_genplist_t *)H5I_object(acpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
-
- if(H5P_get(ac_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get character encoding flag")
- } /* end else */
-
- /* Copy the attribute name */
- attr->shared->name = H5MM_xstrdup(name);
-
- /* Copy datatype */
- if(NULL == (attr->shared->dt = H5T_copy(type, H5T_COPY_ALL)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get shared datatype info")
-
- /* Mark datatype as being on disk now */
- if(H5T_set_loc(attr->shared->dt, loc->oloc->file, H5T_LOC_DISK) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
-
- /* Set the latest format for datatype, if requested */
- if(H5F_USE_LATEST_FORMAT(loc->oloc->file))
- if(H5T_set_latest_version(attr->shared->dt) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set latest version of datatype")
-
- /* Copy the dataspace for the attribute */
- attr->shared->ds = H5S_copy(space, FALSE, TRUE);
-
- /* Set the latest format for dataspace, if requested */
- if(H5F_USE_LATEST_FORMAT(loc->oloc->file))
- if(H5S_set_latest_version(attr->shared->ds) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set latest version of dataspace")
-
- /* Copy the object header information */
- if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry")
-
- /* Deep copy of the group hierarchy path */
- if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy path")
-
- /* Check if any of the pieces should be (or are already) shared in the
- * SOHM table
- */
- if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, 0, H5O_DTYPE_ID, attr->shared->dt, NULL) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share datatype failed")
- if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, 0, H5O_SDSPACE_ID, attr->shared->ds, NULL) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "trying to share dataspace failed")
-
- /* Check whether datatype is committed & increment ref count
- * (to maintain ref. count incr/decr similarity with "shared message"
- * type of datatype sharing)
- */
- if(H5T_committed(attr->shared->dt)) {
- /* Increment the reference count on the shared datatype */
- if(H5T_link(attr->shared->dt, 1, dxpl_id) < 0)
- HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared datatype link count")
- } /* end if */
-
- /* Compute the size of pieces on disk. This is either the size of the
- * datatype and dataspace messages themselves, or the size of the "shared"
- * messages if either or both of them are shared.
- */
- attr->shared->dt_size = H5O_msg_raw_size(attr->oloc.file, H5O_DTYPE_ID, FALSE, attr->shared->dt);
- attr->shared->ds_size = H5O_msg_raw_size(attr->oloc.file, H5O_SDSPACE_ID, FALSE, attr->shared->ds);
-
- /* Get # of elements for attribute's dataspace */
- if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
- H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t);
-
- HDassert(attr->shared->dt_size > 0);
- HDassert(attr->shared->ds_size > 0);
- attr->shared->data_size = nelmts * H5T_GET_SIZE(attr->shared->dt);
-
- /* Hold the symbol table entry (and file) open */
- if(H5O_open(&(attr->oloc)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open")
- attr->obj_opened = TRUE;
-
- /* Set the version to encode the attribute with */
- if(H5A_set_version(attr->oloc.file, attr) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "unable to update attribute version")
-
- /* Insert the attribute into the object header */
- if(H5O_attr_create(&(attr->oloc), dxpl_id, attr) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create attribute in object header")
-
/* Register the new attribute and get an ID for it */
if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID")
-
done:
- /* Cleanup on failure */
+ /* Release resources */
+ if(loc_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location")
if(ret_value < 0 && attr && H5A_close(attr) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "can't close attribute")
- FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
-} /* H5A_create() */
+ FUNC_LEAVE_API(ret_value)
+} /* H5Acreate_by_name() */
/*--------------------------------------------------------------------------
@@ -712,192 +554,6 @@ done:
} /* H5Aopen_by_idx() */
-/*-------------------------------------------------------------------------
- * Function: H5A_open_common
- *
- * Purpose:
- * Finishes initializing an attributes the open
- *
- * Usage:
- * herr_t H5A_open_common(loc, name, dxpl_id)
- * const H5G_loc_t *loc; IN: Pointer to group location for object
- * H5A_t *attr; IN/OUT: Pointer to attribute to initialize
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * December 18, 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5A_open_common(const H5G_loc_t *loc, H5A_t *attr)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* check args */
- HDassert(loc);
- HDassert(attr);
-
-#if defined(H5_USING_MEMCHECKER) || !defined(NDEBUG)
- /* Clear object location */
- if(H5O_loc_reset(&(attr->oloc)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to reset location")
-#endif /* H5_USING_MEMCHECKER */
-
- /* Free any previous group hier. path */
- if(H5G_name_free(&(attr->path)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path")
-
- /* Deep copy of the symbol table entry */
- if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry")
-
- /* Deep copy of the group hier. path */
- if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy entry")
-
- /* Hold the symbol table entry (and file) open */
- if(H5O_open(&(attr->oloc)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open")
- attr->obj_opened = TRUE;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5A_open_common() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5A_open_by_idx
- *
- * Purpose: Open an attribute according to its index order
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * April 2, 1998
- *
- *-------------------------------------------------------------------------
- */
-H5A_t *
-H5A_open_by_idx(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type,
- H5_iter_order_t order, hsize_t n, hid_t lapl_id, hid_t dxpl_id)
-{
- H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
- hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
- H5A_t *attr = NULL; /* Attribute from object header */
- H5A_t *ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* check args */
- HDassert(loc);
- HDassert(obj_name);
-
- /* Set up opened group location to fill in */
- obj_loc.oloc = &obj_oloc;
- obj_loc.path = &obj_path;
- H5G_loc_reset(&obj_loc);
-
- /* Find the object's location */
- if(H5G_loc_find(loc, obj_name, &obj_loc/*out*/, lapl_id, dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "object not found")
- loc_found = TRUE;
-
- /* Read in attribute from object header */
- if(NULL == (attr = H5O_attr_open_by_idx(obj_loc.oloc, idx_type, order, n, dxpl_id)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to load attribute info from object header")
-
- /* Finish initializing attribute */
- if(H5A_open_common(&obj_loc, attr) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute")
-
- /* Set return value */
- ret_value = attr;
-
-done:
- /* Release resources */
- if(loc_found && H5G_loc_free(&obj_loc) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't free location")
-
- /* Cleanup on failure */
- if(ret_value == NULL)
- if(attr && H5A_close(attr) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5A_open_by_idx() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5A_open_by_name
- *
- * Purpose: Open an attribute in an object header, according to it's name
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * December 11, 2006
- *
- *-------------------------------------------------------------------------
- */
-H5A_t *
-H5A_open_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_name,
- hid_t lapl_id, hid_t dxpl_id)
-{
- H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
- hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
- H5A_t *attr = NULL; /* Attribute from object header */
- H5A_t *ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(NULL)
-
- /* check args */
- HDassert(loc);
- HDassert(obj_name);
- HDassert(attr_name);
-
- /* Set up opened group location to fill in */
- obj_loc.oloc = &obj_oloc;
- obj_loc.path = &obj_path;
- H5G_loc_reset(&obj_loc);
-
- /* Find the object's location */
- if(H5G_loc_find(loc, obj_name, &obj_loc/*out*/, lapl_id, dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "object not found")
- loc_found = TRUE;
-
- /* Read in attribute from object header */
- if(NULL == (attr = H5O_attr_open_by_name(obj_loc.oloc, attr_name, dxpl_id)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to load attribute info from object header")
-
- /* Finish initializing attribute */
- if(H5A_open_common(loc, attr) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute")
-
- /* Set return value */
- ret_value = attr;
-
-done:
- /* Release resources */
- if(loc_found && H5G_loc_free(&obj_loc) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't free location")
-
- /* Cleanup on failure */
- if(ret_value == NULL)
- if(attr && H5A_close(attr) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5A_open_by_name() */
-
-
/*--------------------------------------------------------------------------
NAME
H5Awrite
@@ -943,120 +599,6 @@ done:
/*--------------------------------------------------------------------------
NAME
- H5A_write
- PURPOSE
- Actually write out data to an attribute
- USAGE
- herr_t H5A_write (attr, mem_type, buf)
- H5A_t *attr; IN: Attribute to write
- const H5T_t *mem_type; IN: Memory datatype of buffer
- const void *buf; IN: Buffer of data to write
- RETURNS
- Non-negative on success/Negative on failure
-
- DESCRIPTION
- This function writes a complete attribute to disk.
---------------------------------------------------------------------------*/
-static herr_t
-H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id)
-{
- uint8_t *tconv_buf = NULL; /* datatype conv buffer */
- hbool_t tconv_owned = FALSE; /* Whether the datatype conv buffer is owned by attribute */
- uint8_t *bkg_buf = NULL; /* temp conversion buffer */
- hssize_t snelmts; /* elements in attribute */
- size_t nelmts; /* elements in attribute */
- H5T_path_t *tpath = NULL; /* conversion information*/
- hid_t src_id = -1, dst_id = -1;/* temporary type atoms */
- size_t src_type_size; /* size of source type */
- size_t dst_type_size; /* size of destination type*/
- size_t buf_size; /* desired buffer size */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT_TAG(dxpl_id, attr->oloc.addr, FAIL)
-
- HDassert(attr);
- HDassert(mem_type);
- HDassert(buf);
-
- /* Get # of elements for attribute's dataspace */
- if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
- H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t);
-
- /* If there's actually data elements for the attribute, make a copy of the data passed in */
- if(nelmts > 0) {
- /* Get the memory and file datatype sizes */
- src_type_size = H5T_GET_SIZE(mem_type);
- dst_type_size = H5T_GET_SIZE(attr->shared->dt);
-
- /* Convert memory buffer into disk buffer */
- /* Set up type conversion function */
- if(NULL == (tpath = H5T_path_find(mem_type, attr->shared->dt, NULL, NULL, dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes")
-
- /* Check for type conversion required */
- if(!H5T_path_noop(tpath)) {
- if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL), FALSE)) < 0 ||
- (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL), FALSE)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
-
- /* Get the maximum buffer size needed and allocate it */
- buf_size = nelmts * MAX(src_type_size, dst_type_size);
- if(NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed")
- if(NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed")
-
- /* Copy the user's data into the buffer for conversion */
- HDmemcpy(tconv_buf, buf, (src_type_size * nelmts));
-
- /* Perform datatype conversion */
- if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed")
-
- /* Free the previous attribute data buffer, if there is one */
- if(attr->shared->data)
- attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data);
-
- /* Set the pointer to the attribute data to the converted information */
- attr->shared->data = tconv_buf;
- tconv_owned = TRUE;
- } /* end if */
- /* No type conversion necessary */
- else {
- HDassert(dst_type_size == src_type_size);
-
- /* Allocate the attribute buffer, if there isn't one */
- if(attr->shared->data == NULL)
- if(NULL == (attr->shared->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size * nelmts)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
-
- /* Copy the attribute data into the user's buffer */
- HDmemcpy(attr->shared->data, buf, (dst_type_size * nelmts));
- } /* end else */
-
- /* Modify the attribute in the object header */
- if(H5O_attr_write(&(attr->oloc), dxpl_id, attr) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to modify attribute")
- } /* end if */
-
-done:
- /* Release resources */
- if(src_id >= 0 && H5I_dec_ref(src_id) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object")
- if(dst_id >= 0 && H5I_dec_ref(dst_id) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object")
- if(tconv_buf && !tconv_owned)
- tconv_buf = H5FL_BLK_FREE(attr_buf, tconv_buf);
- if(bkg_buf)
- bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf);
-
- FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
-} /* H5A_write() */
-
-
-/*--------------------------------------------------------------------------
- NAME
H5Aread
PURPOSE
Read in data from an attribute
@@ -1100,109 +642,6 @@ done:
/*--------------------------------------------------------------------------
NAME
- H5A_read
- PURPOSE
- Actually read in data from an attribute
- USAGE
- herr_t H5A_read (attr, mem_type, buf)
- H5A_t *attr; IN: Attribute to read
- const H5T_t *mem_type; IN: Memory datatype of buffer
- void *buf; IN: Buffer for data to read
- RETURNS
- Non-negative on success/Negative on failure
-
- DESCRIPTION
- This function reads a complete attribute from disk.
---------------------------------------------------------------------------*/
-static herr_t
-H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id)
-{
- uint8_t *tconv_buf = NULL; /* datatype conv buffer*/
- uint8_t *bkg_buf = NULL; /* background buffer */
- hssize_t snelmts; /* elements in attribute */
- size_t nelmts; /* elements in attribute*/
- H5T_path_t *tpath = NULL; /* type conversion info */
- hid_t src_id = -1, dst_id = -1;/* temporary type atoms*/
- size_t src_type_size; /* size of source type */
- size_t dst_type_size; /* size of destination type */
- size_t buf_size; /* desired buffer size */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT
-
- HDassert(attr);
- HDassert(mem_type);
- HDassert(buf);
-
- /* Create buffer for data to store on disk */
- if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
- H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t);
-
- if(nelmts > 0) {
- /* Get the memory and file datatype sizes */
- src_type_size = H5T_GET_SIZE(attr->shared->dt);
- dst_type_size = H5T_GET_SIZE(mem_type);
-
- /* Check if the attribute has any data yet, if not, fill with zeroes */
- if(attr->obj_opened && !attr->shared->data)
- HDmemset(buf, 0, (dst_type_size * nelmts));
- else { /* Attribute exists and has a value */
- /* Convert memory buffer into disk buffer */
- /* Set up type conversion function */
- if(NULL == (tpath = H5T_path_find(attr->shared->dt, mem_type, NULL, NULL, dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes")
-
- /* Check for type conversion required */
- if(!H5T_path_noop(tpath)) {
- if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL), FALSE)) < 0 ||
- (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL), FALSE)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
-
- /* Get the maximum buffer size needed and allocate it */
- buf_size = nelmts * MAX(src_type_size, dst_type_size);
- if(NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
- HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed")
- if(NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
- HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed")
-
- /* Copy the attribute data into the buffer for conversion */
- HDmemcpy(tconv_buf, attr->shared->data, (src_type_size * nelmts));
-
- /* Perform datatype conversion. */
- if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed")
-
- /* Copy the converted data into the user's buffer */
- HDmemcpy(buf, tconv_buf, (dst_type_size * nelmts));
- } /* end if */
- /* No type conversion necessary */
- else {
- HDassert(dst_type_size == src_type_size);
-
- /* Copy the attribute data into the user's buffer */
- HDmemcpy(buf, attr->shared->data, (dst_type_size * nelmts));
- } /* end else */
- } /* end else */
- } /* end if */
-
-done:
- /* Release resources */
- if(src_id >= 0 && H5I_dec_ref(src_id) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object")
- if(dst_id >= 0 && H5I_dec_ref(dst_id) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object")
- if(tconv_buf)
- tconv_buf = H5FL_BLK_FREE(attr_buf, tconv_buf);
- if(bkg_buf)
- bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf);
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5A_read() */
-
-
-/*--------------------------------------------------------------------------
- NAME
H5Aget_space
PURPOSE
Gets a copy of the dataspace for an attribute
@@ -1221,7 +660,6 @@ hid_t
H5Aget_space(hid_t attr_id)
{
H5A_t *attr; /* Attribute object for ID */
- H5S_t *ds = NULL; /* Copy of dataspace for attribute */
hid_t ret_value;
FUNC_ENTER_API(FAIL)
@@ -1231,18 +669,10 @@ H5Aget_space(hid_t attr_id)
if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute")
- /* Copy the attribute's dataspace */
- if(NULL == (ds = H5S_copy(attr->shared->ds, FALSE, TRUE)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy dataspace")
-
- /* Atomize */
- if((ret_value = H5I_register(H5I_DATASPACE, ds, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom")
+ if((ret_value = H5A_get_space(attr)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get space ID of attribute")
done:
- if(ret_value < 0 && ds)
- (void)H5S_close(ds);
-
FUNC_LEAVE_API(ret_value)
} /* H5Aget_space() */
@@ -1267,7 +697,6 @@ hid_t
H5Aget_type(hid_t attr_id)
{
H5A_t *attr; /* Attribute object for ID */
- H5T_t *dt = NULL; /* Copy of attribute's datatype */
hid_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1277,36 +706,10 @@ H5Aget_type(hid_t attr_id)
if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute")
- /* Patch the datatype's "top level" file pointer */
- if(H5T_patch_file(attr->shared->dt, attr->oloc.file) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to patch datatype's file pointer")
-
- /*
- * Copy the attribute's datatype. If the type is a named type then
- * reopen the type before returning it to the user. Make the type
- * read-only.
- */
- if(NULL == (dt = H5T_copy(attr->shared->dt, H5T_COPY_REOPEN)))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy datatype")
-
- /* Mark any datatypes as being in memory now */
- if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
-
- /* Lock copied type */
- if(H5T_lock(dt, FALSE) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to lock transient datatype")
-
- /* Atomize */
- if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype ID")
+ if((ret_value = H5A_get_type(attr)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get space ID of attribute")
done:
- if(ret_value < 0) {
- if(dt && H5T_close(dt) < 0)
- HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to release datatype")
- } /* end if */
-
FUNC_LEAVE_API(ret_value)
} /* H5Aget_type() */
@@ -1334,9 +737,6 @@ hid_t
H5Aget_create_plist(hid_t attr_id)
{
H5A_t *attr; /* Attribute object for ID */
- H5P_genplist_t *plist; /* Default property list */
- hid_t new_plist_id; /* ID of ACPL to return */
- H5P_genplist_t *new_plist; /* ACPL to return */
hid_t ret_value;
FUNC_ENTER_API(FAIL)
@@ -1347,20 +747,9 @@ H5Aget_create_plist(hid_t attr_id)
/* Get attribute and default attribute creation property list*/
if(NULL == (attr = (H5A_t *)H5I_object_verify(attr_id, H5I_ATTR)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute")
- if(NULL == (plist = (H5P_genplist_t *)H5I_object(H5P_LST_ATTRIBUTE_CREATE_ID_g)))
- HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get default ACPL")
-
- /* Create the property list object to return */
- if((new_plist_id = H5P_copy_plist(plist, TRUE)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy attribute creation properties")
- if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_plist_id)))
- HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get property list")
-
- /* Set the character encoding on the new property list */
- if(H5P_set(new_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set character encoding")
- ret_value = new_plist_id;
+ if((ret_value = H5A_get_create_plist(attr)) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_CANTGET, FAIL, "can't get creation property list for attr")
done:
FUNC_LEAVE_API(ret_value)
@@ -1412,53 +801,6 @@ done:
} /* H5Aget_name() */
-/*--------------------------------------------------------------------------
- NAME
- H5A_get_name
- PURPOSE
- Private function for H5Aget_name. Gets a copy of the name for an
- attribute
- RETURNS
- This function returns the length of the attribute's name (which may be
- longer than 'buf_size') on success or negative for failure.
- DESCRIPTION
- This function retrieves the name of an attribute for an attribute ID.
- Up to 'buf_size' characters are stored in 'buf' followed by a '\0' string
- terminator. If the name of the attribute is longer than 'buf_size'-1,
- the string terminator is stored in the last position of the buffer to
- properly terminate the string.
---------------------------------------------------------------------------*/
-ssize_t
-H5A_get_name(H5A_t *attr, size_t buf_size, char *buf)
-{
- size_t copy_len, nbytes;
- ssize_t ret_value;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* get the real attribute length */
- nbytes = HDstrlen(attr->shared->name);
- HDassert((ssize_t)nbytes >= 0); /*overflow, pretty unlikely --rpm*/
-
- /* compute the string length which will fit into the user's buffer */
- copy_len = MIN(buf_size - 1, nbytes);
-
- /* Copy all/some of the name */
- if(buf && copy_len > 0) {
- HDmemcpy(buf, attr->shared->name, copy_len);
-
- /* Terminate the string */
- buf[copy_len]='\0';
- } /* end if */
-
- /* Set return value */
- ret_value = (ssize_t)nbytes;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5A_get_name() */
-
-
/*-------------------------------------------------------------------------
* Function: H5Aget_name_by_idx
*
@@ -1723,47 +1065,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5A_get_info
- *
- * Purpose: Retrieve information about an attribute.
- *
- * Return: Success: Non-negative
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * February 6, 2007
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5A_get_info(const H5A_t *attr, H5A_info_t *ainfo)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Check args */
- HDassert(attr);
- HDassert(ainfo);
-
- /* Set info for attribute */
- ainfo->cset = attr->shared->encoding;
- ainfo->data_size = attr->shared->data_size;
- if(attr->shared->crt_idx == H5O_MAX_CRT_ORDER_IDX) {
- ainfo->corder_valid = FALSE;
- ainfo->corder = 0;
- } /* end if */
- else {
- ainfo->corder_valid = TRUE;
- ainfo->corder = attr->shared->crt_idx;
- } /* end else */
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5A_get_info() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5Arename
*
* Purpose: Rename an attribute
@@ -1779,7 +1080,6 @@ done:
herr_t
H5Arename(hid_t loc_id, const char *old_name, const char *new_name)
{
- H5G_loc_t loc; /* Object location */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1790,14 +1090,18 @@ H5Arename(hid_t loc_id, const char *old_name, const char *new_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "name is nil")
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
- if(H5G_loc(loc_id, & loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
/* Avoid thrashing things if the names are the same */
- if(HDstrcmp(old_name, new_name))
- /* Call attribute rename routine */
+ if(HDstrcmp(old_name, new_name)) {
+ H5G_loc_t loc; /* Object location */
+
+ if(H5G_loc(loc_id, & loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+
+ /* Call private attribute rename routine */
if(H5O_attr_rename(loc.oloc, H5AC_dxpl_id, old_name, new_name) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute")
+ } /* end if */
done:
FUNC_LEAVE_API(ret_value)
@@ -1821,11 +1125,6 @@ herr_t
H5Arename_by_name(hid_t loc_id, const char *obj_name, const char *old_attr_name,
const char *new_attr_name, hid_t lapl_id)
{
- H5G_loc_t loc; /* Object location */
- H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
- hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -1835,8 +1134,6 @@ H5Arename_by_name(hid_t loc_id, const char *obj_name, const char *old_attr_name,
/* check arguments */
if(H5I_ATTR == H5I_get_type(loc_id))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute")
- if(H5G_loc(loc_id, &loc) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!obj_name || !*obj_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name")
if(!old_attr_name || !*old_attr_name)
@@ -1851,26 +1148,17 @@ H5Arename_by_name(hid_t loc_id, const char *obj_name, const char *old_attr_name,
/* Avoid thrashing things if the names are the same */
if(HDstrcmp(old_attr_name, new_attr_name)) {
- /* Set up opened group location to fill in */
- obj_loc.oloc = &obj_oloc;
- obj_loc.path = &obj_path;
- H5G_loc_reset(&obj_loc);
-
- /* Find the object's location */
- if(H5G_loc_find(&loc, obj_name, &obj_loc/*out*/, lapl_id, H5AC_ind_dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found")
- loc_found = TRUE;
-
- /* Call attribute rename routine */
- if(H5O_attr_rename(obj_loc.oloc, H5AC_dxpl_id, old_attr_name, new_attr_name) < 0)
+ H5G_loc_t loc; /* Object location */
+
+ if(H5G_loc(loc_id, & loc) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
+
+ /* Call private attribute rename routine */
+ if(H5A_rename_by_name(loc, obj_name, old_attr_name, new_attr_name, lapl_id) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute")
} /* end if */
done:
- /* Release resources */
- if(loc_found && H5G_loc_free(&obj_loc) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location")
-
FUNC_LEAVE_API(ret_value)
} /* H5Arename_by_name() */
@@ -2297,271 +1585,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5A_copy
- *
- * Purpose: Copies attribute OLD_ATTR.
- *
- * Return: Success: Pointer to a new copy of the OLD_ATTR argument.
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * Thursday, December 4, 1997
- *
- * Modification:Raymond Lu
- * 4 June 2008
- * Changed some attribute information to be shared.
- *
- *-------------------------------------------------------------------------
- */
-H5A_t *
-H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr)
-{
- H5A_t *new_attr = NULL;
- hbool_t allocated_attr = FALSE; /* Whether the attribute was allocated */
- H5A_t *ret_value = NULL; /* Return value */
-
- FUNC_ENTER_NOAPI(NULL)
-
- /* check args */
- HDassert(old_attr);
-
- /* Allocate attribute structure */
- if(_new_attr == NULL) {
- if(NULL == (new_attr = H5FL_CALLOC(H5A_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
- allocated_attr = TRUE;
- } /* end if */
- else
- new_attr = _new_attr;
-
- /* Copy the top level of the attribute */
- new_attr->sh_loc = old_attr->sh_loc;
-
- /* Deep copy of the group hierarchy path */
- if(H5G_name_copy(&(new_attr->path), &(old_attr->path), H5_COPY_DEEP) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy path")
-
- /* Share some attribute information */
- new_attr->shared = old_attr->shared;
-
- /* Increment reference count for shared object */
- new_attr->shared->nrefs++;
-
- /* Don't open the object header for a copy */
- new_attr->obj_opened = FALSE;
-
- /* Set the return value */
- ret_value = new_attr;
-
-done:
- if(ret_value == NULL)
- if(allocated_attr && new_attr && H5A_close(new_attr) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5A_copy() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5A_free
- *
- * Purpose: Frees all memory associated with an attribute, but does not
- * free the H5A_t structure (which should be done in H5T_close).
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Monday, November 15, 2004
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5A_free(H5A_t *attr)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- HDassert(attr);
-
- /* Free dynamicly allocated items */
- if(attr->shared->name) {
- H5MM_xfree(attr->shared->name);
- attr->shared->name = NULL;
- }
- if(attr->shared->dt) {
- if(H5T_close(attr->shared->dt) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release datatype info")
- attr->shared->dt = NULL;
- }
- if(attr->shared->ds) {
- if(H5S_close(attr->shared->ds) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release dataspace info")
- attr->shared->ds = NULL;
- }
- if(attr->shared->data)
- attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5A_free() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5A_close
- *
- * Purpose: Frees an attribute and all associated memory.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Monday, December 8, 1997
- *
- * Modifications:
- * Raymond Lu
- * 4 June 2008
- * Changed some attribute object information to be shared.
- *-------------------------------------------------------------------------
- */
-herr_t
-H5A_close(H5A_t *attr)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- HDassert(attr);
- HDassert(attr->shared);
-
- /* Close the object's symbol-table entry */
- if(attr->obj_opened && (H5O_close(&(attr->oloc)) < 0))
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release object header info")
-
- /* Reference count can be 0. It only happens when H5A_create fails. */
- if(attr->shared->nrefs <= 1) {
- /* Free dynamicly allocated items */
- if(H5A_free(attr) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info")
-
- /* Destroy shared attribute struct */
- attr->shared = H5FL_FREE(H5A_shared_t, attr->shared);
- } /* end if */
- else {
- /* There are other references to the shared part of the attribute.
- * Only decrement the reference count. */
- --attr->shared->nrefs;
- } /* end else */
-
- /* Free group hierarchy path */
- if(H5G_name_free(&(attr->path)) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path")
-
- attr->shared = NULL;
- attr = H5FL_FREE(H5A_t, attr);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5A_close() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5A_oloc
- *
- * Purpose: Return the object location for an attribute. It's the
- * object location for the object to which the attribute
- * belongs, not the attribute itself.
- *
- * Return: Success: Ptr to entry
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * Thursday, August 6, 1998
- *
- *-------------------------------------------------------------------------
- */
-H5O_loc_t *
-H5A_oloc(H5A_t *attr)
-{
- H5O_loc_t *ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(NULL)
-
- HDassert(attr);
-
- /* Set return value */
- ret_value = &(attr->oloc);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5A_oloc() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5A_nameof
- *
- * Purpose: Return the group hier. path for an attribute. It's the
- * group hier. path for the object to which the attribute
- * belongs, not the attribute itself.
- *
- * Return: Success: Ptr to entry
- * Failure: NULL
- *
- * Programmer: Quincey Koziol
- * Monday, September 12, 2005
- *
- *-------------------------------------------------------------------------
- */
-H5G_name_t *
-H5A_nameof(H5A_t *attr)
-{
- H5G_name_t *ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(NULL)
-
- HDassert(attr);
-
- /* Set return value */
- ret_value=&(attr->path);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5A_nameof() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5A_type
- *
- * Purpose: Return the datatype for an attribute.
- *
- * Return: Success: Ptr to entry
- * Failure: NULL
- *
- * Programmer: Neil Fortner
- * Friday, November 11, 2011
- *
- *-------------------------------------------------------------------------
- */
-H5T_t *
-H5A_type(const H5A_t *attr)
-{
- H5T_t *ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(NULL)
-
- HDassert(attr);
-
- /* Set return value */
- ret_value = attr->shared->dt;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5A_type() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5Aexists
*
* Purpose: Checks if an attribute with a given name exists on an opened
@@ -2619,10 +1642,6 @@ H5Aexists_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
hid_t lapl_id)
{
H5G_loc_t loc; /* Object location */
- H5G_loc_t obj_loc; /* Location used to open group */
- H5G_name_t obj_path; /* Opened object group hier. path */
- H5O_loc_t obj_oloc; /* Opened object object location */
- hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
htri_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -2643,25 +1662,10 @@ H5Aexists_by_name(hid_t loc_id, const char *obj_name, const char *attr_name,
if(TRUE != H5P_isa_class(lapl_id, H5P_LINK_ACCESS))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link access property list ID")
- /* Set up opened group location to fill in */
- obj_loc.oloc = &obj_oloc;
- obj_loc.path = &obj_path;
- H5G_loc_reset(&obj_loc);
-
- /* Find the object's location */
- if(H5G_loc_find(&loc, obj_name, &obj_loc/*out*/, lapl_id, H5AC_ind_dxpl_id) < 0)
- HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found")
- loc_found = TRUE;
-
- /* Check if the attribute exists */
- if((ret_value = H5O_attr_exists(obj_loc.oloc, attr_name, H5AC_ind_dxpl_id)) < 0)
+ if((ret_value = H5A_exists_by_name(loc, obj_name, attr_name, lapl_id)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists")
done:
- /* Release resources */
- if(loc_found && H5G_loc_free(&obj_loc) < 0)
- HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location")
-
FUNC_LEAVE_API(ret_value)
} /* H5Aexists_by_name() */
diff --git a/src/H5Adeprec.c b/src/H5Adeprec.c
index 6194150..6342e18 100644
--- a/src/H5Adeprec.c
+++ b/src/H5Adeprec.c
@@ -162,6 +162,7 @@ hid_t
H5Acreate1(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id,
hid_t plist_id)
{
+ H5A_t *attr = NULL; /* Attribute created */
H5G_loc_t loc; /* Object location */
H5T_t *type; /* Datatype to use for attribute */
H5S_t *space; /* Dataspace to use for attribute */
@@ -185,9 +186,13 @@ H5Acreate1(hid_t loc_id, const char *name, hid_t type_id, hid_t space_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
/* Go do the real work for attaching the attribute to the dataset */
- if((ret_value = H5A_create(&loc, name, type, space, plist_id, H5AC_dxpl_id)) < 0)
+ if((attr = H5A_create(&loc, name, type, space, plist_id, H5AC_dxpl_id)) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create attribute")
+ /* Register the new attribute and get an ID for it */
+ if((ret_value = H5I_register(H5I_ATTR, attr, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register attribute for ID")
+
done:
FUNC_LEAVE_API(ret_value)
} /* H5Acreate1() */
diff --git a/src/H5Aint.c b/src/H5Aint.c
index ab9bece..625bfa9 100644
--- a/src/H5Aint.c
+++ b/src/H5Aint.c
@@ -119,6 +119,1108 @@ H5FL_SEQ_DEFINE(H5A_t_ptr);
/*-------------------------------------------------------------------------
+ * Function: H5A_create
+ *
+ * Purpose:
+ * This is the guts of creating an attribute.
+ * Usage:
+ * hid_t H5A_create(ent, name, type, space)
+ * const H5G_entry_t *ent; IN: Pointer to symbol table entry for object to attribute
+ * const char *name; IN: Name of attribute
+ * H5T_t *type; IN: Datatype of attribute
+ * H5S_t *space; IN: Dataspace of attribute
+ * hid_t acpl_id IN: Attribute creation property list
+ *
+ * Return: attribute structure on success, NULL on Failure.
+ *
+ * Programmer: Quincey Koziol
+ * April 2, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+H5A_t *
+H5A_create(const H5G_loc_t *loc, const char *name, const H5T_t *type,
+ const H5S_t *space, hid_t acpl_id, hid_t dxpl_id)
+{
+ H5A_t *attr = NULL; /* Attribute created */
+ hssize_t snelmts; /* elements in attribute */
+ size_t nelmts; /* elements in attribute */
+ htri_t tri_ret; /* htri_t return value */
+ H5A_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_TAG(dxpl_id, loc->oloc->addr, NULL)
+
+ /* check args */
+ HDassert(loc);
+ HDassert(name);
+ HDassert(type);
+ HDassert(space);
+
+ /* Check for existing attribute with same name */
+ /* (technically, the "attribute create" operation will fail for a duplicated
+ * name, but it's going to be hard to unwind all the special cases on
+ * failure, so just check first, for now - QAK)
+ */
+ if((tri_ret = H5O_attr_exists(loc->oloc, name, H5AC_ind_dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "error checking attributes")
+ else if(tri_ret > 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_ALREADYEXISTS, NULL, "attribute already exists")
+
+ /* Check if the dataspace has an extent set (or is NULL) */
+ if(!(H5S_has_extent(space)))
+ HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, NULL, "dataspace extent has not been set")
+
+ /* Check if the datatype is "sensible" for use in a dataset */
+ if(H5T_is_sensible(type) != TRUE)
+ HGOTO_ERROR(H5E_ATTR, H5E_BADTYPE, NULL, "datatype is not sensible")
+
+ /* Build the attribute information */
+ if(NULL == (attr = H5FL_CALLOC(H5A_t)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "memory allocation failed for attribute info")
+
+ if(NULL == (attr->shared = H5FL_CALLOC(H5A_shared_t)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "can't allocate shared attr structure")
+
+ /* If the creation property list is H5P_DEFAULT, use the default character encoding */
+ if(acpl_id == H5P_DEFAULT)
+ attr->shared->encoding = H5F_DEFAULT_CSET;
+ else {
+ H5P_genplist_t *ac_plist; /* ACPL Property list */
+
+ /* Get a local copy of the attribute creation property list */
+ if(NULL == (ac_plist = (H5P_genplist_t *)H5I_object(acpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a property list")
+
+ if(H5P_get(ac_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get character encoding flag")
+ } /* end else */
+
+ /* Copy the attribute name */
+ attr->shared->name = H5MM_xstrdup(name);
+
+ /* Copy datatype */
+ if(NULL == (attr->shared->dt = H5T_copy(type, H5T_COPY_ALL)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "can't get shared datatype info")
+
+ /* Mark datatype as being on disk now */
+ if(H5T_set_loc(attr->shared->dt, loc->oloc->file, H5T_LOC_DISK) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location")
+
+ /* Set the latest format for datatype, if requested */
+ if(H5F_USE_LATEST_FORMAT(loc->oloc->file))
+ if(H5T_set_latest_version(attr->shared->dt) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set latest version of datatype")
+
+ /* Copy the dataspace for the attribute */
+ attr->shared->ds = H5S_copy(space, FALSE, TRUE);
+
+ /* Set the latest format for dataspace, if requested */
+ if(H5F_USE_LATEST_FORMAT(loc->oloc->file))
+ if(H5S_set_latest_version(attr->shared->ds) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set latest version of dataspace")
+
+ /* Copy the object header information */
+ if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to copy entry")
+
+ /* Deep copy of the group hierarchy path */
+ if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy path")
+
+ /* Check if any of the pieces should be (or are already) shared in the
+ * SOHM table
+ */
+ if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, 0, H5O_DTYPE_ID, attr->shared->dt, NULL) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, NULL, "trying to share datatype failed")
+ if(H5SM_try_share(attr->oloc.file, dxpl_id, NULL, 0, H5O_SDSPACE_ID, attr->shared->ds, NULL) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, NULL, "trying to share dataspace failed")
+
+ /* Check whether datatype is committed & increment ref count
+ * (to maintain ref. count incr/decr similarity with "shared message"
+ * type of datatype sharing)
+ */
+ if(H5T_committed(attr->shared->dt)) {
+ /* Increment the reference count on the shared datatype */
+ if(H5T_link(attr->shared->dt, 1, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, NULL, "unable to adjust shared datatype link count")
+ } /* end if */
+
+ /* Compute the size of pieces on disk. This is either the size of the
+ * datatype and dataspace messages themselves, or the size of the "shared"
+ * messages if either or both of them are shared.
+ */
+ attr->shared->dt_size = H5O_msg_raw_size(attr->oloc.file, H5O_DTYPE_ID, FALSE, attr->shared->dt);
+ attr->shared->ds_size = H5O_msg_raw_size(attr->oloc.file, H5O_SDSPACE_ID, FALSE, attr->shared->ds);
+
+ /* Get # of elements for attribute's dataspace */
+ if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, NULL, "dataspace is invalid")
+ H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t);
+
+ HDassert(attr->shared->dt_size > 0);
+ HDassert(attr->shared->ds_size > 0);
+ attr->shared->data_size = nelmts * H5T_GET_SIZE(attr->shared->dt);
+
+ /* Hold the symbol table entry (and file) open */
+ if(H5O_open(&(attr->oloc)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open")
+ attr->obj_opened = TRUE;
+
+ /* Set the version to encode the attribute with */
+ if(H5A_set_version(attr->oloc.file, attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "unable to update attribute version")
+
+ /* Insert the attribute into the object header */
+ if(H5O_attr_create(&(attr->oloc), dxpl_id, attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, NULL, "unable to create attribute in object header")
+
+ ret_value = attr;
+done:
+ if(NULL == ret_value && attr && H5A_close(attr))
+ HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
+ FUNC_LEAVE_NOAPI_TAG(ret_value, NULL)
+} /* H5A_create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_open_common
+ *
+ * Purpose:
+ * Finishes initializing an attributes the open
+ *
+ * Usage:
+ * herr_t H5A_open_common(loc, name, dxpl_id)
+ * const H5G_loc_t *loc; IN: Pointer to group location for object
+ * H5A_t *attr; IN/OUT: Pointer to attribute to initialize
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * December 18, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_open_common(const H5G_loc_t *loc, H5A_t *attr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* check args */
+ HDassert(loc);
+ HDassert(attr);
+
+#if defined(H5_USING_MEMCHECKER) || !defined(NDEBUG)
+ /* Clear object location */
+ if(H5O_loc_reset(&(attr->oloc)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to reset location")
+#endif /* H5_USING_MEMCHECKER */
+
+ /* Free any previous group hier. path */
+ if(H5G_name_free(&(attr->path)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path")
+
+ /* Deep copy of the symbol table entry */
+ if(H5O_loc_copy(&(attr->oloc), loc->oloc, H5_COPY_DEEP) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to copy entry")
+
+ /* Deep copy of the group hier. path */
+ if(H5G_name_copy(&(attr->path), loc->path, H5_COPY_DEEP) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "unable to copy entry")
+
+ /* Hold the symbol table entry (and file) open */
+ if(H5O_open(&(attr->oloc)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open")
+ attr->obj_opened = TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5A_open_common() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_open_by_idx
+ *
+ * Purpose: Open an attribute according to its index order
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * April 2, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+H5A_t *
+H5A_open_by_idx(const H5G_loc_t *loc, const char *obj_name, H5_index_t idx_type,
+ H5_iter_order_t order, hsize_t n, hid_t lapl_id, hid_t dxpl_id)
+{
+ H5G_loc_t obj_loc; /* Location used to open group */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
+ hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
+ H5A_t *attr = NULL; /* Attribute from object header */
+ H5A_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* check args */
+ HDassert(loc);
+ HDassert(obj_name);
+
+ /* Set up opened group location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
+
+ /* Find the object's location */
+ if(H5G_loc_find(loc, obj_name, &obj_loc/*out*/, lapl_id, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "object not found")
+ loc_found = TRUE;
+
+ /* Read in attribute from object header */
+ if(NULL == (attr = H5O_attr_open_by_idx(obj_loc.oloc, idx_type, order, n, dxpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to load attribute info from object header")
+
+ /* Finish initializing attribute */
+ if(H5A_open_common(&obj_loc, attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute")
+
+ /* Set return value */
+ ret_value = attr;
+
+done:
+ /* Release resources */
+ if(loc_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't free location")
+
+ /* Cleanup on failure */
+ if(ret_value == NULL)
+ if(attr && H5A_close(attr) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5A_open_by_idx() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_open_by_name
+ *
+ * Purpose: Open an attribute in an object header, according to it's name
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * December 11, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+H5A_t *
+H5A_open_by_name(const H5G_loc_t *loc, const char *obj_name, const char *attr_name,
+ hid_t lapl_id, hid_t dxpl_id)
+{
+ H5G_loc_t obj_loc; /* Location used to open group */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
+ hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
+ H5A_t *attr = NULL; /* Attribute from object header */
+ H5A_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* check args */
+ HDassert(loc);
+ HDassert(obj_name);
+ HDassert(attr_name);
+
+ /* Set up opened group location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
+
+ /* Find the object's location */
+ if(H5G_loc_find(loc, obj_name, &obj_loc/*out*/, lapl_id, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "object not found")
+ loc_found = TRUE;
+
+ /* Read in attribute from object header */
+ if(NULL == (attr = H5O_attr_open_by_name(obj_loc.oloc, attr_name, dxpl_id)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to load attribute info from object header")
+
+ /* Finish initializing attribute */
+ if(H5A_open_common(loc, attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "unable to initialize attribute")
+
+ /* Set return value */
+ ret_value = attr;
+
+done:
+ /* Release resources */
+ if(loc_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, NULL, "can't free location")
+
+ /* Cleanup on failure */
+ if(ret_value == NULL)
+ if(attr && H5A_close(attr) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5A_open_by_name() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5A_write
+ PURPOSE
+ Actually write out data to an attribute
+ USAGE
+ herr_t H5A_write (attr, mem_type, buf)
+ H5A_t *attr; IN: Attribute to write
+ const H5T_t *mem_type; IN: Memory datatype of buffer
+ const void *buf; IN: Buffer of data to write
+ RETURNS
+ Non-negative on success/Negative on failure
+
+ DESCRIPTION
+ This function writes a complete attribute to disk.
+--------------------------------------------------------------------------*/
+herr_t
+H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id)
+{
+ uint8_t *tconv_buf = NULL; /* datatype conv buffer */
+ hbool_t tconv_owned = FALSE; /* Whether the datatype conv buffer is owned by attribute */
+ uint8_t *bkg_buf = NULL; /* temp conversion buffer */
+ hssize_t snelmts; /* elements in attribute */
+ size_t nelmts; /* elements in attribute */
+ H5T_path_t *tpath = NULL; /* conversion information*/
+ hid_t src_id = -1, dst_id = -1;/* temporary type atoms */
+ size_t src_type_size; /* size of source type */
+ size_t dst_type_size; /* size of destination type*/
+ size_t buf_size; /* desired buffer size */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT_TAG(dxpl_id, attr->oloc.addr, FAIL)
+
+ HDassert(attr);
+ HDassert(mem_type);
+ HDassert(buf);
+
+ /* Get # of elements for attribute's dataspace */
+ if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
+ H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t);
+
+ /* If there's actually data elements for the attribute, make a copy of the data passed in */
+ if(nelmts > 0) {
+ /* Get the memory and file datatype sizes */
+ src_type_size = H5T_GET_SIZE(mem_type);
+ dst_type_size = H5T_GET_SIZE(attr->shared->dt);
+
+ /* Convert memory buffer into disk buffer */
+ /* Set up type conversion function */
+ if(NULL == (tpath = H5T_path_find(mem_type, attr->shared->dt, NULL, NULL, dxpl_id, FALSE)))
+ HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes")
+
+ /* Check for type conversion required */
+ if(!H5T_path_noop(tpath)) {
+ if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL), FALSE)) < 0 ||
+ (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL), FALSE)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
+
+ /* Get the maximum buffer size needed and allocate it */
+ buf_size = nelmts * MAX(src_type_size, dst_type_size);
+ if(NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed")
+ if(NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed")
+
+ /* Copy the user's data into the buffer for conversion */
+ HDmemcpy(tconv_buf, buf, (src_type_size * nelmts));
+
+ /* Perform datatype conversion */
+ if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed")
+
+ /* Free the previous attribute data buffer, if there is one */
+ if(attr->shared->data)
+ attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data);
+
+ /* Set the pointer to the attribute data to the converted information */
+ attr->shared->data = tconv_buf;
+ tconv_owned = TRUE;
+ } /* end if */
+ /* No type conversion necessary */
+ else {
+ HDassert(dst_type_size == src_type_size);
+
+ /* Allocate the attribute buffer, if there isn't one */
+ if(attr->shared->data == NULL)
+ if(NULL == (attr->shared->data = H5FL_BLK_MALLOC(attr_buf, dst_type_size * nelmts)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Copy the attribute data into the user's buffer */
+ HDmemcpy(attr->shared->data, buf, (dst_type_size * nelmts));
+ } /* end else */
+
+ /* Modify the attribute in the object header */
+ if(H5O_attr_write(&(attr->oloc), dxpl_id, attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to modify attribute")
+ } /* end if */
+
+done:
+ /* Release resources */
+ if(src_id >= 0 && H5I_dec_ref(src_id) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object")
+ if(dst_id >= 0 && H5I_dec_ref(dst_id) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object")
+ if(tconv_buf && !tconv_owned)
+ tconv_buf = H5FL_BLK_FREE(attr_buf, tconv_buf);
+ if(bkg_buf)
+ bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf);
+
+ FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
+} /* H5A_write() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5A_read
+ PURPOSE
+ Actually read in data from an attribute
+ USAGE
+ herr_t H5A_read (attr, mem_type, buf)
+ H5A_t *attr; IN: Attribute to read
+ const H5T_t *mem_type; IN: Memory datatype of buffer
+ void *buf; IN: Buffer for data to read
+ RETURNS
+ Non-negative on success/Negative on failure
+
+ DESCRIPTION
+ This function reads a complete attribute from disk.
+--------------------------------------------------------------------------*/
+herr_t
+H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id)
+{
+ uint8_t *tconv_buf = NULL; /* datatype conv buffer*/
+ uint8_t *bkg_buf = NULL; /* background buffer */
+ hssize_t snelmts; /* elements in attribute */
+ size_t nelmts; /* elements in attribute*/
+ H5T_path_t *tpath = NULL; /* type conversion info */
+ hid_t src_id = -1, dst_id = -1;/* temporary type atoms*/
+ size_t src_type_size; /* size of source type */
+ size_t dst_type_size; /* size of destination type */
+ size_t buf_size; /* desired buffer size */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(attr);
+ HDassert(mem_type);
+ HDassert(buf);
+
+ /* Create buffer for data to store on disk */
+ if((snelmts = H5S_GET_EXTENT_NPOINTS(attr->shared->ds)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOUNT, FAIL, "dataspace is invalid")
+ H5_ASSIGN_OVERFLOW(nelmts, snelmts, hssize_t, size_t);
+
+ if(nelmts > 0) {
+ /* Get the memory and file datatype sizes */
+ src_type_size = H5T_GET_SIZE(attr->shared->dt);
+ dst_type_size = H5T_GET_SIZE(mem_type);
+
+ /* Check if the attribute has any data yet, if not, fill with zeroes */
+ if(attr->obj_opened && !attr->shared->data)
+ HDmemset(buf, 0, (dst_type_size * nelmts));
+ else { /* Attribute exists and has a value */
+ /* Convert memory buffer into disk buffer */
+ /* Set up type conversion function */
+ if(NULL == (tpath = H5T_path_find(attr->shared->dt, mem_type, NULL, NULL, dxpl_id, FALSE)))
+ HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dst datatypes")
+
+ /* Check for type conversion required */
+ if(!H5T_path_noop(tpath)) {
+ if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(attr->shared->dt, H5T_COPY_ALL), FALSE)) < 0 ||
+ (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL), FALSE)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTREGISTER, FAIL, "unable to register types for conversion")
+
+ /* Get the maximum buffer size needed and allocate it */
+ buf_size = nelmts * MAX(src_type_size, dst_type_size);
+ if(NULL == (tconv_buf = H5FL_BLK_MALLOC(attr_buf, buf_size)))
+ HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if(NULL == (bkg_buf = H5FL_BLK_CALLOC(attr_buf, buf_size)))
+ HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Copy the attribute data into the buffer for conversion */
+ HDmemcpy(tconv_buf, attr->shared->data, (src_type_size * nelmts));
+
+ /* Perform datatype conversion. */
+ if(H5T_convert(tpath, src_id, dst_id, nelmts, (size_t)0, (size_t)0, tconv_buf, bkg_buf, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "datatype conversion failed")
+
+ /* Copy the converted data into the user's buffer */
+ HDmemcpy(buf, tconv_buf, (dst_type_size * nelmts));
+ } /* end if */
+ /* No type conversion necessary */
+ else {
+ HDassert(dst_type_size == src_type_size);
+
+ /* Copy the attribute data into the user's buffer */
+ HDmemcpy(buf, attr->shared->data, (dst_type_size * nelmts));
+ } /* end else */
+ } /* end else */
+ } /* end if */
+
+done:
+ /* Release resources */
+ if(src_id >= 0 && H5I_dec_ref(src_id) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object")
+ if(dst_id >= 0 && H5I_dec_ref(dst_id) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTDEC, FAIL, "unable to close temporary object")
+ if(tconv_buf)
+ tconv_buf = H5FL_BLK_FREE(attr_buf, tconv_buf);
+ if(bkg_buf)
+ bkg_buf = H5FL_BLK_FREE(attr_buf, bkg_buf);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5A_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_get_space
+ *
+ * Purpose: Returns and ID for the dataspace of the attribute.
+ *
+ * Return: Success: ID for dataspace
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Mohamad Chaarawi
+ * March, 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5A_get_space(H5A_t *attr)
+{
+ H5S_t *ds = NULL;
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Copy the attribute's dataspace */
+ if(NULL == (ds = H5S_copy(attr->shared->ds, FALSE, TRUE)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy dataspace")
+
+ /* Atomize */
+ if((ret_value = H5I_register(H5I_DATASPACE, ds, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom")
+
+done:
+ if(ret_value < 0 && ds) {
+ if(H5S_close(ds) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_get_space() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_get_type
+ *
+ * Purpose: Returns and ID for the datatype of the dataset.
+ *
+ * Return: Success: ID for datatype
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Mohamad Chaarawi
+ * March, 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5A_get_type(H5A_t *attr)
+{
+ H5T_t *dt = NULL;
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Patch the datatype's "top level" file pointer */
+ if(H5T_patch_file(attr->shared->dt, attr->oloc.file) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to patch datatype's file pointer")
+
+ /*
+ * Copy the attribute's datatype. If the type is a named type then
+ * reopen the type before returning it to the user. Make the type
+ * read-only.
+ */
+ if(NULL == (dt = H5T_copy(attr->shared->dt, H5T_COPY_REOPEN)))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to copy datatype")
+
+ /* Mark any datatypes as being in memory now */
+ if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
+
+ /* Lock copied type */
+ if(H5T_lock(dt, FALSE) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to lock transient datatype")
+
+ /* Create an atom */
+ if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype")
+
+done:
+ if(ret_value < 0) {
+ if(dt && H5T_close(dt) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release datatype")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_get_type() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5A_get_create_plist
+ PURPOSE
+ private version of H5Aget_create_plist
+ RETURNS
+ This function returns the ID of a copy of the attribute's creation
+ property list, or negative on failure.
+
+ ERRORS
+
+ DESCRIPTION
+ This function returns a copy of the creation property list for
+ an attribute. The resulting ID must be closed with H5Pclose() or
+ resource leaks will occur.
+--------------------------------------------------------------------------*/
+hid_t
+H5A_get_create_plist(H5A_t* attr)
+{
+ H5P_genplist_t *plist; /* Default property list */
+ hid_t new_plist_id; /* ID of ACPL to return */
+ H5P_genplist_t *new_plist; /* ACPL to return */
+ hid_t ret_value;
+ FUNC_ENTER_NOAPI_NOINIT
+
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(H5P_LST_ATTRIBUTE_CREATE_ID_g)))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get default ACPL")
+
+ /* Create the property list object to return */
+ if((new_plist_id = H5P_copy_plist(plist, TRUE)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy attribute creation properties")
+ if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_plist_id)))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "can't get property list")
+
+ /* Set the character encoding on the new property list */
+ if(H5P_set(new_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &(attr->shared->encoding)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set character encoding")
+
+ ret_value = new_plist_id;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5Aget_create_plist() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5A_get_name
+ PURPOSE
+ Private function for H5Aget_name. Gets a copy of the name for an
+ attribute
+ RETURNS
+ This function returns the length of the attribute's name (which may be
+ longer than 'buf_size') on success or negative for failure.
+ DESCRIPTION
+ This function retrieves the name of an attribute for an attribute ID.
+ Up to 'buf_size' characters are stored in 'buf' followed by a '\0' string
+ terminator. If the name of the attribute is longer than 'buf_size'-1,
+ the string terminator is stored in the last position of the buffer to
+ properly terminate the string.
+--------------------------------------------------------------------------*/
+ssize_t
+H5A_get_name(H5A_t *attr, size_t buf_size, char *buf)
+{
+ size_t copy_len, nbytes;
+ ssize_t ret_value;
+
+ FUNC_ENTER_NOAPI_NOERR
+
+ /* get the real attribute length */
+ nbytes = HDstrlen(attr->shared->name);
+ HDassert((ssize_t)nbytes >= 0); /*overflow, pretty unlikely --rpm*/
+
+ /* compute the string length which will fit into the user's buffer */
+ copy_len = MIN(buf_size - 1, nbytes);
+
+ /* Copy all/some of the name */
+ if(buf && copy_len > 0) {
+ HDmemcpy(buf, attr->shared->name, copy_len);
+
+ /* Terminate the string */
+ buf[copy_len]='\0';
+ } /* end if */
+
+ /* Set return value */
+ ret_value = (ssize_t)nbytes;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5A_get_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_get_info
+ *
+ * Purpose: Retrieve information about an attribute.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * February 6, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_get_info(const H5A_t *attr, H5A_info_t *ainfo)
+{
+ FUNC_ENTER_NOAPI_NOERR
+
+ /* Check args */
+ HDassert(attr);
+ HDassert(ainfo);
+
+ /* Set info for attribute */
+ ainfo->cset = attr->shared->encoding;
+ ainfo->data_size = attr->shared->data_size;
+ if(attr->shared->crt_idx == H5O_MAX_CRT_ORDER_IDX) {
+ ainfo->corder_valid = FALSE;
+ ainfo->corder = 0;
+ } /* end if */
+ else {
+ ainfo->corder_valid = TRUE;
+ ainfo->corder = attr->shared->crt_idx;
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5A_get_info() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_copy
+ *
+ * Purpose: Copies attribute OLD_ATTR.
+ *
+ * Return: Success: Pointer to a new copy of the OLD_ATTR argument.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, December 4, 1997
+ *
+ * Modification:Raymond Lu
+ * 4 June 2008
+ * Changed some attribute information to be shared.
+ *
+ *-------------------------------------------------------------------------
+ */
+H5A_t *
+H5A_copy(H5A_t *_new_attr, const H5A_t *old_attr)
+{
+ H5A_t *new_attr = NULL;
+ hbool_t allocated_attr = FALSE; /* Whether the attribute was allocated */
+ H5A_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* check args */
+ HDassert(old_attr);
+
+ /* Allocate attribute structure */
+ if(_new_attr == NULL) {
+ if(NULL == (new_attr = H5FL_CALLOC(H5A_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+ allocated_attr = TRUE;
+ } /* end if */
+ else
+ new_attr = _new_attr;
+
+ /* Copy the top level of the attribute */
+ new_attr->sh_loc = old_attr->sh_loc;
+
+ /* Deep copy of the group hierarchy path */
+ if(H5G_name_copy(&(new_attr->path), &(old_attr->path), H5_COPY_DEEP) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "unable to copy path")
+
+ /* Share some attribute information */
+ new_attr->shared = old_attr->shared;
+
+ /* Increment reference count for shared object */
+ new_attr->shared->nrefs++;
+
+ /* Don't open the object header for a copy */
+ new_attr->obj_opened = FALSE;
+
+ /* Set the return value */
+ ret_value = new_attr;
+
+done:
+ if(ret_value == NULL)
+ if(allocated_attr && new_attr && H5A_close(new_attr) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, NULL, "can't close attribute")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_free
+ *
+ * Purpose: Frees all memory associated with an attribute, but does not
+ * free the H5A_t structure (which should be done in H5T_close).
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, November 15, 2004
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_free(H5A_t *attr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ HDassert(attr);
+
+ /* Free dynamicly allocated items */
+ if(attr->shared->name) {
+ H5MM_xfree(attr->shared->name);
+ attr->shared->name = NULL;
+ }
+ if(attr->shared->dt) {
+ if(H5T_close(attr->shared->dt) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release datatype info")
+ attr->shared->dt = NULL;
+ }
+ if(attr->shared->ds) {
+ if(H5S_close(attr->shared->ds) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release dataspace info")
+ attr->shared->ds = NULL;
+ }
+ if(attr->shared->data)
+ attr->shared->data = H5FL_BLK_FREE(attr_buf, attr->shared->data);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_close
+ *
+ * Purpose: Frees an attribute and all associated memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Monday, December 8, 1997
+ *
+ * Modifications:
+ * Raymond Lu
+ * 4 June 2008
+ * Changed some attribute object information to be shared.
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_close(H5A_t *attr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ HDassert(attr);
+ HDassert(attr->shared);
+
+ /* Close the object's symbol-table entry */
+ if(attr->obj_opened && (H5O_close(&(attr->oloc)) < 0))
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release object header info")
+
+ /* Reference count can be 0. It only happens when H5A_create fails. */
+ if(attr->shared->nrefs <= 1) {
+ /* Free dynamicly allocated items */
+ if(H5A_free(attr) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info")
+
+ /* Destroy shared attribute struct */
+ attr->shared = H5FL_FREE(H5A_shared_t, attr->shared);
+ } /* end if */
+ else {
+ /* There are other references to the shared part of the attribute.
+ * Only decrement the reference count. */
+ --attr->shared->nrefs;
+ } /* end else */
+
+ /* Free group hierarchy path */
+ if(H5G_name_free(&(attr->path)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release group hier. path")
+
+ attr->shared = NULL;
+ attr = H5FL_FREE(H5A_t, attr);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_oloc
+ *
+ * Purpose: Return the object location for an attribute. It's the
+ * object location for the object to which the attribute
+ * belongs, not the attribute itself.
+ *
+ * Return: Success: Ptr to entry
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, August 6, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+H5O_loc_t *
+H5A_oloc(H5A_t *attr)
+{
+ H5O_loc_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOERR
+
+ HDassert(attr);
+
+ /* Set return value */
+ ret_value = &(attr->oloc);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_oloc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_nameof
+ *
+ * Purpose: Return the group hier. path for an attribute. It's the
+ * group hier. path for the object to which the attribute
+ * belongs, not the attribute itself.
+ *
+ * Return: Success: Ptr to entry
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol
+ * Monday, September 12, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+H5G_name_t *
+H5A_nameof(H5A_t *attr)
+{
+ H5G_name_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOERR
+
+ HDassert(attr);
+
+ /* Set return value */
+ ret_value=&(attr->path);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_nameof() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_type
+ *
+ * Purpose: Return the datatype for an attribute.
+ *
+ * Return: Success: Ptr to entry
+ * Failure: NULL
+ *
+ * Programmer: Neil Fortner
+ * Friday, November 11, 2011
+ *
+ *-------------------------------------------------------------------------
+ */
+H5T_t *
+H5A_type(const H5A_t *attr)
+{
+ H5T_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOERR
+
+ HDassert(attr);
+
+ /* Set return value */
+ ret_value = attr->shared->dt;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5A_type() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_exists_by_name
+ *
+ * Purpose: Private version of H5Aexists_by_name
+ *
+ * Return: Success: TRUE/FALSE
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, November 1, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5A_exists_by_name(H5G_loc_t loc, const char *obj_name, const char *attr_name,
+ hid_t lapl_id)
+{
+ H5G_loc_t obj_loc; /* Location used to open group */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
+ hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
+ htri_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Set up opened group location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
+
+ /* Find the object's location */
+ if(H5G_loc_find(&loc, obj_name, &obj_loc/*out*/, lapl_id, H5AC_ind_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found")
+ loc_found = TRUE;
+
+ /* Check if the attribute exists */
+ if((ret_value = H5O_attr_exists(obj_loc.oloc, attr_name, H5AC_ind_dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "unable to determine if attribute exists")
+
+done:
+ /* Release resources */
+ if(loc_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5A_exists_by_name() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5A__compact_build_table_cb
*
* Purpose: Object header iterator callback routine to copy attribute
@@ -1259,3 +2361,53 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A_dense_post_copy_file_all */
+
+/*-------------------------------------------------------------------------
+ * Function: H5A_rename_by_name
+ *
+ * Purpose: Private version of H5Arename_by_name
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * February 20, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5A_rename_by_name(H5G_loc_t loc, const char *obj_name, const char *old_attr_name,
+ const char *new_attr_name, hid_t lapl_id)
+{
+ H5G_loc_t obj_loc; /* Location used to open group */
+ H5G_name_t obj_path; /* Opened object group hier. path */
+ H5O_loc_t obj_oloc; /* Opened object object location */
+ hbool_t loc_found = FALSE; /* Entry at 'obj_name' found */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Avoid thrashing things if the names are the same */
+ if(HDstrcmp(old_attr_name, new_attr_name)) {
+ /* Set up opened group location to fill in */
+ obj_loc.oloc = &obj_oloc;
+ obj_loc.path = &obj_path;
+ H5G_loc_reset(&obj_loc);
+
+ /* Find the object's location */
+ if(H5G_loc_find(&loc, obj_name, &obj_loc/*out*/, lapl_id, H5AC_ind_dxpl_id) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "object not found")
+ loc_found = TRUE;
+
+ /* Call attribute rename routine */
+ if(H5O_attr_rename(obj_loc.oloc, H5AC_dxpl_id, old_attr_name, new_attr_name) < 0)
+ HGOTO_ERROR(H5E_ATTR, H5E_CANTRENAME, FAIL, "can't rename attribute")
+ } /* end if */
+
+done:
+ /* Release resources */
+ if(loc_found && H5G_loc_free(&obj_loc) < 0)
+ HDONE_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't free location")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5A_rename_by_name() */
diff --git a/src/H5Apkg.h b/src/H5Apkg.h
index fa26a9a..efa2b74 100644
--- a/src/H5Apkg.h
+++ b/src/H5Apkg.h
@@ -186,19 +186,29 @@ H5_DLLVAR const H5B2_class_t H5A_BT2_CORDER[1];
/* Function prototypes for H5A package scope */
H5_DLL herr_t H5A_init(void);
H5_DLL herr_t H5A__term_deprec_interface(void);
-H5_DLL hid_t H5A_create(const H5G_loc_t *loc, const char *name,
+H5_DLL H5A_t *H5A_create(const H5G_loc_t *loc, const char *name,
const H5T_t *type, const H5S_t *space, hid_t acpl_id, hid_t dxpl_id);
-H5_DLL H5A_t * H5A_open_by_name(const H5G_loc_t *loc, const char *obj_name,
+H5_DLL H5A_t *H5A_open_by_name(const H5G_loc_t *loc, const char *obj_name,
const char *attr_name, hid_t lapl_id, hid_t dxpl_id);
H5_DLL H5A_t *H5A_open_by_idx(const H5G_loc_t *loc, const char *obj_name,
H5_index_t idx_type, H5_iter_order_t order, hsize_t n, hid_t lapl_id, hid_t dxpl_id);
+H5_DLL herr_t H5A_open_common(const H5G_loc_t *loc, H5A_t *attr);
+H5_DLL herr_t H5A_write(H5A_t *attr, const H5T_t *mem_type, const void *buf, hid_t dxpl_id);
+H5_DLL herr_t H5A_read(const H5A_t *attr, const H5T_t *mem_type, void *buf, hid_t dxpl_id);
H5_DLL ssize_t H5A_get_name(H5A_t *attr, size_t buf_size, char *buf);
H5_DLL H5A_t *H5A_copy(H5A_t *new_attr, const H5A_t *old_attr);
H5_DLL herr_t H5A_get_info(const H5A_t *attr, H5A_info_t *ainfo);
+H5_DLL hid_t H5A_get_type(H5A_t *attr);
+H5_DLL hid_t H5A_get_space(H5A_t *attr);
+H5_DLL hid_t H5A_get_create_plist(H5A_t* attr);
H5_DLL herr_t H5A_free(H5A_t *attr);
H5_DLL herr_t H5A_close(H5A_t *attr);
H5_DLL htri_t H5A_get_ainfo(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5O_ainfo_t *ainfo);
H5_DLL herr_t H5A_set_version(const H5F_t *f, H5A_t *attr);
+H5_DLL herr_t H5A_rename_by_name(H5G_loc_t loc, const char *obj_name, const char *old_attr_name,
+ const char *new_attr_name, hid_t lapl_id);
+H5_DLL htri_t H5A_exists_by_name(H5G_loc_t loc, const char *obj_name, const char *attr_name,
+ hid_t lapl_id);
/* Attribute "dense" storage routines */
H5_DLL herr_t H5A_dense_create(H5F_t *f, hid_t dxpl_id, H5O_ainfo_t *ainfo);
diff --git a/src/H5D.c b/src/H5D.c
index 11d8d40..a81fb8b 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -450,7 +450,6 @@ hid_t
H5Dget_space(hid_t dset_id)
{
H5D_t *dset = NULL;
- H5S_t *space = NULL;
hid_t ret_value;
FUNC_ENTER_API(FAIL)
@@ -460,22 +459,10 @@ H5Dget_space(hid_t dset_id)
if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
- /* Read the dataspace message and return a dataspace object */
- if(NULL == (space = H5S_copy(dset->shared->space, FALSE, TRUE)))
+ if((ret_value = H5D_get_space(dset)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get dataspace")
- /* Create an atom */
- if((ret_value = H5I_register (H5I_DATASPACE, space, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace")
-
done:
- if(ret_value < 0) {
- if(space!=NULL) {
- if(H5S_close(space) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace")
- } /* end if */
- } /* end if */
-
FUNC_LEAVE_API(ret_value)
}
@@ -504,7 +491,7 @@ H5Dget_space_status(hid_t dset_id, H5D_space_status_t *allocation)
H5TRACE2("e", "i*Ds", dset_id, allocation);
/* Check arguments */
- if(NULL==(dset=(H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
+ if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
/* Read dataspace address and return */
@@ -537,7 +524,6 @@ H5Dget_type(hid_t dset_id)
{
H5D_t *dset; /* Dataset */
- H5T_t *dt = NULL; /* Datatype to return */
hid_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -547,32 +533,10 @@ H5Dget_type(hid_t dset_id)
if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
- /* Patch the datatype's "top level" file pointer */
- if(H5T_patch_file(dset->shared->type, dset->oloc.file) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to patch datatype's file pointer")
-
- /* Copy the dataset's datatype */
- if(NULL == (dt = H5T_copy(dset->shared->type, H5T_COPY_REOPEN)))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy datatype")
-
- /* Mark any datatypes as being in memory now */
- if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
-
- /* Lock copied type */
- if(H5T_lock(dt, FALSE) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to lock transient datatype")
-
- /* Create an atom */
- if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype")
+ if((ret_value = H5D_get_type(dset)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get dataspace")
done:
- if(ret_value < 0) {
- if(dt && H5T_close(dt) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release datatype")
- } /* end if */
-
FUNC_LEAVE_API(ret_value)
} /* end H5Dget_type() */
@@ -607,7 +571,7 @@ H5Dget_create_plist(hid_t dset_id)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
if((ret_value = H5D_get_create_plist(dataset)) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "Can't get creation plist")
done:
FUNC_LEAVE_API(ret_value)
@@ -615,123 +579,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5D_get_create_plist
- *
- * Purpose: Private function for H5Dget_create_plist
- *
- * Return: Success: ID for a copy of the dataset creation
- * property list. The template should be
- * released by calling H5P_close().
- *
- * Failure: FAIL
- *
- * Programmer: Robb Matzke
- * Tuesday, February 3, 1998
- *
- *-------------------------------------------------------------------------
- */
-hid_t
-H5D_get_create_plist(H5D_t *dset)
-{
- H5P_genplist_t *dcpl_plist; /* Dataset's DCPL */
- H5P_genplist_t *new_plist; /* Copy of dataset's DCPL */
- H5O_fill_t copied_fill; /* Fill value to tweak */
- hid_t new_dcpl_id = FAIL;
- hid_t ret_value; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Check args */
- if(NULL == (dcpl_plist = (H5P_genplist_t *)H5I_object(dset->shared->dcpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
-
- /* Copy the creation property list */
- if((new_dcpl_id = H5P_copy_plist(dcpl_plist, TRUE)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to copy the creation property list")
- if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_dcpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
-
- /* Retrieve any object creation properties */
- if(H5O_get_create_plist(&dset->oloc, H5AC_ind_dxpl_id, new_plist) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get object creation info")
-
- /* Get the fill value property */
- if(H5P_get(new_plist, H5D_CRT_FILL_VALUE_NAME, &copied_fill) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fill value")
-
- /* Check if there is a fill value, but no type yet */
- if(copied_fill.buf != NULL && copied_fill.type == NULL) {
- H5T_path_t *tpath; /* Conversion information*/
-
- /* Copy the dataset type into the fill value message */
- if(NULL == (copied_fill.type = H5T_copy(dset->shared->type, H5T_COPY_TRANSIENT)))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy dataset datatype for fill value")
-
- /* Set up type conversion function */
- if(NULL == (tpath = H5T_path_find(dset->shared->type, copied_fill.type, NULL, NULL, H5AC_ind_dxpl_id, FALSE)))
- HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types")
-
- /* Convert disk form of fill value into memory form */
- if(!H5T_path_noop(tpath)) {
- hid_t dst_id, src_id; /* Source & destination datatypes for type conversion */
- uint8_t *bkg_buf = NULL; /* Background conversion buffer */
- size_t bkg_size; /* Size of background buffer */
-
- /* Wrap copies of types to convert */
- dst_id = H5I_register(H5I_DATATYPE, H5T_copy(copied_fill.type, H5T_COPY_TRANSIENT), FALSE);
- if(dst_id < 0)
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype")
- src_id = H5I_register(H5I_DATATYPE, H5T_copy(dset->shared->type, H5T_COPY_ALL), FALSE);
- if(src_id < 0) {
- H5I_dec_ref(dst_id);
- HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype")
- } /* end if */
-
- /* Allocate a background buffer */
- bkg_size = MAX(H5T_GET_SIZE(copied_fill.type), H5T_GET_SIZE(dset->shared->type));
- if(H5T_path_bkg(tpath) && NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size))) {
- H5I_dec_ref(src_id);
- H5I_dec_ref(dst_id);
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- } /* end if */
-
- /* Convert fill value */
- if(H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, copied_fill.buf, bkg_buf, H5AC_ind_dxpl_id) < 0) {
- H5I_dec_ref(src_id);
- H5I_dec_ref(dst_id);
- if(bkg_buf)
- bkg_buf = H5FL_BLK_FREE(type_conv, bkg_buf);
- HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
- } /* end if */
-
- /* Release local resources */
- if(H5I_dec_ref(src_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object")
- if(H5I_dec_ref(dst_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object")
- if(bkg_buf)
- bkg_buf = H5FL_BLK_FREE(type_conv, bkg_buf);
- } /* end if */
- } /* end if */
-
- /* Set back the fill value property to property list */
- if(H5P_set(new_plist, H5D_CRT_FILL_VALUE_NAME, &copied_fill) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set property list fill value")
-
- /* Set the return value */
- ret_value = new_dcpl_id;
-
-done:
- if(ret_value < 0)
- if(new_dcpl_id > 0)
- if(H5I_dec_app_ref(new_dcpl_id) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5D_get_create_plist() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5Dget_access_plist
*
* Purpose: Returns a copy of the dataset creation property list.
@@ -768,9 +615,6 @@ hid_t
H5Dget_access_plist(hid_t dset_id)
{
H5D_t *dset; /* Dataset structure */
- H5P_genplist_t *old_plist; /* Default DAPL */
- H5P_genplist_t *new_plist; /* New DAPL */
- hid_t new_dapl_id = FAIL;
hid_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -780,33 +624,10 @@ H5Dget_access_plist(hid_t dset_id)
if (NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
- /* Make a copy of the default dataset access property list */
- if (NULL == (old_plist = (H5P_genplist_t *)H5I_object(H5P_LST_DATASET_ACCESS_ID_g)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
- if ((new_dapl_id = H5P_copy_plist(old_plist, TRUE)) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "can't copy dataset access property list")
- if (NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_dapl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
-
- /* If the dataset is chunked then copy the rdcc parameters */
- if (dset->shared->layout.type == H5D_CHUNKED) {
- if (H5P_set(new_plist, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(dset->shared->cache.chunk.nslots)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache number of slots")
- if (H5P_set(new_plist, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(dset->shared->cache.chunk.nbytes_max)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache byte size")
- if (H5P_set(new_plist, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, &(dset->shared->cache.chunk.w0)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set preempt read chunks")
- } /* end if */
-
- /* Set the return value */
- ret_value = new_dapl_id;
+ if((ret_value = H5D_get_access_plist(dset)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "Can't get access plist")
done:
- if(ret_value < 0)
- if(new_dapl_id >= 0)
- if(H5I_dec_app_ref(new_dapl_id) < 0)
- HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object")
-
FUNC_LEAVE_API(ret_value)
} /* end H5Dget_access_plist() */
diff --git a/src/H5Dint.c b/src/H5Dint.c
index 88367d6..6c61d28 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -103,6 +103,9 @@ H5FL_BLK_EXTERN(sieve_buf);
/* Declare the external free list to manage the H5D_chunk_info_t struct */
H5FL_EXTERN(H5D_chunk_info_t);
+/* Declare extern the free list to manage blocks of type conversion data */
+H5FL_BLK_EXTERN(type_conv);
+
/* Define a static "default" dataset structure to use to initialize new datasets */
static H5D_shared_t H5D_def_dset;
@@ -2456,3 +2459,269 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_flush() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_get_create_plist
+ *
+ * Purpose: Private function for H5Dget_create_plist
+ *
+ * Return: Success: ID for a copy of the dataset creation
+ * property list. The template should be
+ * released by calling H5P_close().
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, February 3, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5D_get_create_plist(H5D_t *dset)
+{
+ H5P_genplist_t *dcpl_plist; /* Dataset's DCPL */
+ H5P_genplist_t *new_plist; /* Copy of dataset's DCPL */
+ H5O_fill_t copied_fill; /* Fill value to tweak */
+ hid_t new_dcpl_id = FAIL;
+ hid_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check args */
+ if(NULL == (dcpl_plist = (H5P_genplist_t *)H5I_object(dset->shared->dcpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
+
+ /* Copy the creation property list */
+ if((new_dcpl_id = H5P_copy_plist(dcpl_plist, TRUE)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to copy the creation property list")
+ if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_dcpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
+
+ /* Retrieve any object creation properties */
+ if(H5O_get_create_plist(&dset->oloc, H5AC_ind_dxpl_id, new_plist) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get object creation info")
+
+ /* Get the fill value property */
+ if(H5P_get(new_plist, H5D_CRT_FILL_VALUE_NAME, &copied_fill) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fill value")
+
+ /* Check if there is a fill value, but no type yet */
+ if(copied_fill.buf != NULL && copied_fill.type == NULL) {
+ H5T_path_t *tpath; /* Conversion information*/
+
+ /* Copy the dataset type into the fill value message */
+ if(NULL == (copied_fill.type = H5T_copy(dset->shared->type, H5T_COPY_TRANSIENT)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy dataset datatype for fill value")
+
+ /* Set up type conversion function */
+ if(NULL == (tpath = H5T_path_find(dset->shared->type, copied_fill.type, NULL, NULL, H5AC_ind_dxpl_id, FALSE)))
+ HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types")
+
+ /* Convert disk form of fill value into memory form */
+ if(!H5T_path_noop(tpath)) {
+ hid_t dst_id, src_id; /* Source & destination datatypes for type conversion */
+ uint8_t *bkg_buf = NULL; /* Background conversion buffer */
+ size_t bkg_size; /* Size of background buffer */
+
+ /* Wrap copies of types to convert */
+ dst_id = H5I_register(H5I_DATATYPE, H5T_copy(copied_fill.type, H5T_COPY_TRANSIENT), FALSE);
+ if(dst_id < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype")
+ src_id = H5I_register(H5I_DATATYPE, H5T_copy(dset->shared->type, H5T_COPY_ALL), FALSE);
+ if(src_id < 0) {
+ H5I_dec_ref(dst_id);
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy/register datatype")
+ } /* end if */
+
+ /* Allocate a background buffer */
+ bkg_size = MAX(H5T_GET_SIZE(copied_fill.type), H5T_GET_SIZE(dset->shared->type));
+ if(H5T_path_bkg(tpath) && NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size))) {
+ H5I_dec_ref(src_id);
+ H5I_dec_ref(dst_id);
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ } /* end if */
+
+ /* Convert fill value */
+ if(H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, copied_fill.buf, bkg_buf, H5AC_ind_dxpl_id) < 0) {
+ H5I_dec_ref(src_id);
+ H5I_dec_ref(dst_id);
+ if(bkg_buf)
+ bkg_buf = H5FL_BLK_FREE(type_conv, bkg_buf);
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
+ } /* end if */
+
+ /* Release local resources */
+ if(H5I_dec_ref(src_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object")
+ if(H5I_dec_ref(dst_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object")
+ if(bkg_buf)
+ bkg_buf = H5FL_BLK_FREE(type_conv, bkg_buf);
+ } /* end if */
+ } /* end if */
+
+ /* Set back the fill value property to property list */
+ if(H5P_set(new_plist, H5D_CRT_FILL_VALUE_NAME, &copied_fill) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to set property list fill value")
+
+ /* Set the return value */
+ ret_value = new_dcpl_id;
+
+done:
+ if(ret_value < 0)
+ if(new_dcpl_id > 0)
+ if(H5I_dec_app_ref(new_dcpl_id) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTDEC, FAIL, "unable to close temporary object")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_get_create_plist() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_get_access_plist
+ *
+ * Purpose: Returns a copy of the dataset access property list.
+ *
+ * Return: Success: ID for a copy of the dataset access
+ * property list.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Mohamad Chaarawi
+ * March, 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5D_get_access_plist(H5D_t *dset)
+{
+ H5P_genplist_t *old_plist; /* Default DAPL */
+ H5P_genplist_t *new_plist; /* New DAPL */
+ hid_t new_dapl_id = FAIL;
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Make a copy of the default dataset access property list */
+ if (NULL == (old_plist = (H5P_genplist_t *)H5I_object(H5P_LST_DATASET_ACCESS_ID_g)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+ if ((new_dapl_id = H5P_copy_plist(old_plist, TRUE)) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "can't copy dataset access property list")
+ if (NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_dapl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+
+ /* If the dataset is chunked then copy the rdcc parameters */
+ if (dset->shared->layout.type == H5D_CHUNKED) {
+ if (H5P_set(new_plist, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(dset->shared->cache.chunk.nslots)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache number of slots")
+ if (H5P_set(new_plist, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(dset->shared->cache.chunk.nbytes_max)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache byte size")
+ if (H5P_set(new_plist, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, &(dset->shared->cache.chunk.w0)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set preempt read chunks")
+ } /* end if */
+
+ /* Set the return value */
+ ret_value = new_dapl_id;
+
+done:
+ if(ret_value < 0) {
+ if(new_dapl_id > 0)
+ if(H5I_dec_app_ref(new_dapl_id) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "can't free")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_get_access_plist() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_get_space
+ *
+ * Purpose: Returns and ID for the dataspace of the dataset.
+ *
+ * Return: Success: ID for dataspace
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Mohamad Chaarawi
+ * March, 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5D_get_space(H5D_t *dset)
+{
+ H5S_t *space = NULL;
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Read the data space message and return a data space object */
+ if(NULL == (space = H5S_copy(dset->shared->space, FALSE, TRUE)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get data space")
+
+ /* Create an atom */
+ if((ret_value = H5I_register (H5I_DATASPACE, space, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register data space")
+
+done:
+ if(ret_value < 0) {
+ if(space!=NULL) {
+ if(H5S_close(space) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataspace")
+ } /* end if */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_get_space() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_get_type
+ *
+ * Purpose: Returns and ID for the datatype of the dataset.
+ *
+ * Return: Success: ID for datatype
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Mohamad Chaarawi
+ * March, 2012
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5D_get_type(H5D_t *dset)
+{
+ H5T_t *dt = NULL;
+ hid_t ret_value = FAIL;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Patch the datatype's "top level" file pointer */
+ if(H5T_patch_file(dset->shared->type, dset->oloc.file) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to patch datatype's file pointer")
+
+ /* Copy the dataset's datatype */
+ if(NULL == (dt = H5T_copy(dset->shared->type, H5T_COPY_REOPEN)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy datatype")
+
+ /* Mark any datatypes as being in memory now */
+ if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location")
+
+ /* Lock copied type */
+ if(H5T_lock(dt, FALSE) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to lock transient datatype")
+
+ if((ret_value = H5I_register(H5I_DATATYPE, dt, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register datatype")
+
+done:
+ if(ret_value < 0) {
+ if(dt && H5T_close(dt) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release datatype")
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_get_type() */
diff --git a/src/H5Dio.c b/src/H5Dio.c
index 90e4983..b91d7f8 100644
--- a/src/H5Dio.c
+++ b/src/H5Dio.c
@@ -55,8 +55,8 @@
static herr_t H5D__write(H5D_t *dataset, hid_t mem_type_id,
const H5S_t *mem_space, const H5S_t *file_space, hid_t dset_xfer_plist,
const void *buf);
-static herr_t H5D__pre_write(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
- hid_t file_space_id, hid_t dxpl_id, const void *buf);
+static herr_t H5D__pre_write(H5D_t *dset, hbool_t direct_write, hid_t mem_type_id,
+ const H5S_t *mem_space, const H5S_t *file_space, hid_t dxpl_id, const void *buf);
/* Setup/teardown routines */
static herr_t H5D__ioinfo_init(H5D_t *dset,
@@ -212,16 +212,62 @@ herr_t
H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
hid_t file_space_id, hid_t dxpl_id, const void *buf)
{
+ H5D_t *dset = NULL;
+ H5P_genplist_t *plist; /* Property list pointer */
+ const H5S_t *mem_space = NULL;
+ const H5S_t *file_space = NULL;
+ hbool_t direct_write = FALSE;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_API(FAIL)
H5TRACE6("e", "iiiii*x", dset_id, mem_type_id, mem_space_id, file_space_id,
dxpl_id, buf);
- if(!dset_id)
+ /* check arguments */
+ if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
+ if(NULL == dset->oloc.file)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
+
+ /* Get the default dataset transfer property list if the user didn't provide one */
+ if(H5P_DEFAULT == dxpl_id)
+ dxpl_id= H5P_DATASET_XFER_DEFAULT;
+ else
+ if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
+
+ /* Get the dataset transfer property list */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
+
+ /* Retrieve the 'direct write' flag */
+ if(H5P_get(plist, H5D_XFER_DIRECT_CHUNK_WRITE_FLAG_NAME, &direct_write) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "error getting flag for direct chunk write")
+
+ /* Check dataspace selections if this is not a direct write */
+ if(!direct_write) {
+ if(mem_space_id < 0 || file_space_id < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+
+ if(H5S_ALL != mem_space_id) {
+ if(NULL == (mem_space = (const H5S_t *)H5I_object_verify(mem_space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+
+ /* Check for valid selection */
+ if(H5S_SELECT_VALID(mem_space) != TRUE)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "memory selection+offset not within extent")
+ } /* end if */
+ if(H5S_ALL != file_space_id) {
+ if(NULL == (file_space = (const H5S_t *)H5I_object_verify(file_space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
- if(H5D__pre_write(dset_id, mem_type_id, mem_space_id, file_space_id, dxpl_id, buf) < 0)
+ /* Check for valid selection */
+ if(H5S_SELECT_VALID(file_space) != TRUE)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "file selection+offset not within extent")
+ } /* end if */
+ }
+
+ if(H5D__pre_write(dset, direct_write, mem_type_id, mem_space, file_space, dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't prepare for writing data")
done:
@@ -242,39 +288,17 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5D__pre_write(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
- hid_t file_space_id, hid_t dxpl_id, const void *buf)
+H5D__pre_write(H5D_t *dset, hbool_t direct_write, hid_t mem_type_id,
+ const H5S_t *mem_space, const H5S_t *file_space,
+ hid_t dxpl_id, const void *buf)
{
- H5D_t *dset = NULL;
- H5P_genplist_t *plist; /* Property list pointer */
- hbool_t direct_write = FALSE;
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
- /* check arguments */
- if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset")
- if(NULL == dset->oloc.file)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
-
- /* Get the default dataset transfer property list if the user didn't provide one */
- if(H5P_DEFAULT == dxpl_id)
- dxpl_id= H5P_DATASET_XFER_DEFAULT;
- else
- if(TRUE != H5P_isa_class(dxpl_id, H5P_DATASET_XFER))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms")
-
- /* Get the dataset transfer property list */
- if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
-
- /* Retrieve the 'direct write' flag */
- if(H5P_get(plist, H5D_XFER_DIRECT_CHUNK_WRITE_FLAG_NAME, &direct_write) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "error getting flag for direct chunk write")
-
/* Direct chunk write */
if(direct_write) {
+ H5P_genplist_t *plist; /* Property list pointer */
uint32_t direct_filters;
hsize_t *direct_offset;
uint32_t direct_datasize;
@@ -283,6 +307,10 @@ H5D__pre_write(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
hsize_t internal_offset[H5O_LAYOUT_NDIMS];
int i;
+ /* Get the dataset transfer property list */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(dxpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
+
if(H5D_CHUNKED != dset->shared->layout.type)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a chunked dataset")
@@ -319,29 +347,6 @@ H5D__pre_write(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id,
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write chunk directly")
} /* end if */
else { /* Normal write */
- const H5S_t *mem_space = NULL;
- const H5S_t *file_space = NULL;
-
- if(mem_space_id < 0 || file_space_id < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
-
- if(H5S_ALL != mem_space_id) {
- if(NULL == (mem_space = (const H5S_t *)H5I_object_verify(mem_space_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
-
- /* Check for valid selection */
- if(H5S_SELECT_VALID(mem_space) != TRUE)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "memory selection+offset not within extent")
- } /* end if */
- if(H5S_ALL != file_space_id) {
- if(NULL == (file_space = (const H5S_t *)H5I_object_verify(file_space_id, H5I_DATASPACE)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
-
- /* Check for valid selection */
- if(H5S_SELECT_VALID(file_space) != TRUE)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "file selection+offset not within extent")
- } /* end if */
-
/* write raw data */
if(H5D__write(dset, mem_type_id, mem_space, file_space, dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data")
diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h
index d4ecedc..0b8b76f 100644
--- a/src/H5Dprivate.h
+++ b/src/H5Dprivate.h
@@ -163,6 +163,9 @@ H5_DLL H5G_name_t *H5D_nameof(H5D_t *dataset);
H5_DLL H5T_t *H5D_typeof(const H5D_t *dset);
H5_DLL herr_t H5D_flush(const H5F_t *f, hid_t dxpl_id);
H5_DLL hid_t H5D_get_create_plist(H5D_t *dset);
+H5_DLL hid_t H5D_get_access_plist(H5D_t *dset);
+H5_DLL hid_t H5D_get_space(H5D_t *dset);
+H5_DLL hid_t H5D_get_type(H5D_t *dset);
/* Functions that operate on vlen data */
H5_DLL herr_t H5D_vlen_reclaim(hid_t type_id, H5S_t *space, hid_t plist_id,
diff --git a/src/H5F.c b/src/H5F.c
index ed95322..f25f00f 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -20,7 +20,7 @@
#define H5F_PACKAGE /*suppress error about including H5Fpkg */
/* Interface initialization */
-#define H5_INTERFACE_INIT_FUNC H5F_init_interface
+#define H5_INTERFACE_INIT_FUNC H5F__init_pub_interface
/***********/
@@ -50,22 +50,6 @@
/* Local Typedefs */
/******************/
-/* Struct only used by functions H5F_get_objects and H5F_get_objects_cb */
-typedef struct H5F_olist_t {
- H5I_type_t obj_type; /* Type of object to look for */
- hid_t *obj_id_list; /* Pointer to the list of open IDs to return */
- size_t *obj_id_count; /* Number of open IDs */
- struct {
- hbool_t local; /* Set flag for "local" file searches */
- union {
- H5F_file_t *shared; /* Pointer to shared file to look inside */
- const H5F_t *file; /* Pointer to file to look inside */
- } ptr;
- } file_info;
- size_t list_index; /* Current index in open ID array */
- size_t max_nobjs; /* Maximum # of IDs to put into array */
-} H5F_olist_t;
-
/********************/
/* Package Typedefs */
@@ -75,14 +59,7 @@ typedef struct H5F_olist_t {
/********************/
/* Local Prototypes */
/********************/
-static herr_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr);
-static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key);
-static H5F_t *H5F_new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id,
- hid_t fapl_id, H5FD_t *lf);
-static herr_t H5F_build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl,
- const char *name, char ** /*out*/ actual_name);
-static herr_t H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush);
-static herr_t H5F_close(H5F_t *f);
+
/*********************/
@@ -99,11 +76,6 @@ static herr_t H5F_close(H5F_t *f);
/* Local Variables */
/*******************/
-/* Declare a free list to manage the H5F_t struct */
-H5FL_DEFINE(H5F_t);
-
-/* Declare a free list to manage the H5F_file_t struct */
-H5FL_DEFINE(H5F_file_t);
/* File ID class */
static const H5I_class_t H5I_FILE_CLS[1] = {{
@@ -113,6 +85,35 @@ static const H5I_class_t H5I_FILE_CLS[1] = {{
(H5I_free_t)H5F_close /* Callback routine for closing objects of this class */
}};
+
+/*--------------------------------------------------------------------------
+NAME
+ H5F__init_pub_interface -- Initialize interface-specific information
+USAGE
+ herr_t H5F__init_pub_interface()
+RETURNS
+ Non-negative on success/Negative on failure
+DESCRIPTION
+ Initializes any interface-specific data or routines. (Just calls
+ H5F_init() currently).
+
+--------------------------------------------------------------------------*/
+static herr_t
+H5F__init_pub_interface(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+ FUNC_ENTER_STATIC
+
+ /*
+ * Initialize the atom group for the file IDs.
+ */
+ if(H5I_register_type(H5I_FILE_CLS) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to initialize interface")
+
+ ret_value = H5F_init();
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F__init_pub_interface() */
/*-------------------------------------------------------------------------
@@ -142,37 +143,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_init_interface
- *
- * Purpose: Initialize interface-specific information.
- *
- * Return: Success: non-negative
- * Failure: negative
- *
- * Programmer: Robb Matzke
- * Friday, November 20, 1998
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5F_init_interface(void)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /*
- * Initialize the atom group for the file IDs.
- */
- if(H5I_register_type(H5I_FILE_CLS) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to initialize interface")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_init_interface() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5F_term_interface
*
* Purpose: Terminate this interface: free all memory and reset global
@@ -301,109 +271,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_get_access_plist
- *
- * Purpose: Returns a copy of the file access property list of the
- * specified file.
- *
- * NOTE: Make sure that, if you are going to overwrite
- * information in the copied property list that was
- * previously opened and assigned to the property list, then
- * you must close it before overwriting the values.
- *
- * Return: Success: Object ID for a copy of the file access
- * property list.
- *
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- * Wednesday, May 25, 2005
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-hid_t
-H5F_get_access_plist(H5F_t *f, hbool_t app_ref)
-{
- H5P_genplist_t *new_plist; /* New property list */
- H5P_genplist_t *old_plist; /* Old property list */
- void *driver_info=NULL;
- unsigned efc_size = 0;
- hid_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Check args */
- HDassert(f);
-
- /* Make a copy of the default file access property list */
- if(NULL == (old_plist = (H5P_genplist_t *)H5I_object(H5P_LST_FILE_ACCESS_ID_g)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
- if((ret_value = H5P_copy_plist(old_plist, app_ref)) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "can't copy file access property list")
- if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(ret_value)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
-
- /* Copy properties of the file access property list */
- if(H5P_set(new_plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set initial metadata cache resize config.")
- if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(f->shared->rdcc_nslots)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache number of slots")
- if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache byte size")
- if(H5P_set(new_plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &(f->shared->rdcc_w0)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set preempt read chunks")
- if(H5P_set(new_plist, H5F_ACS_ALIGN_THRHD_NAME, &(f->shared->threshold)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set alignment threshold")
- if(H5P_set(new_plist, H5F_ACS_ALIGN_NAME, &(f->shared->alignment)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set alignment")
- if(H5P_set(new_plist, H5F_ACS_GARBG_COLCT_REF_NAME, &(f->shared->gc_ref)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set garbage collect reference")
- if(H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set metadata cache size")
- if(H5P_set(new_plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't sieve buffer size")
- if(H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'small data' cache size")
- if(H5P_set(new_plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'latest format' flag")
- if(f->shared->efc)
- efc_size = H5F_efc_max_nfiles(f->shared->efc);
- if(H5P_set(new_plist, H5F_ACS_EFC_SIZE_NAME, &efc_size) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set elink file cache size")
-
- /*
- * Since we're resetting the driver ID and info, close them if they
- * exist in this new property list.
- */
- if(H5P_facc_close(ret_value, NULL) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "can't free the old driver information")
-
- /* Increment the reference count on the driver ID and insert it into the property list */
- if(H5I_inc_ref(f->shared->lf->driver_id, FALSE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINC, FAIL, "unable to increment ref count on VFL driver")
- if(H5P_set(new_plist, H5F_ACS_FILE_DRV_ID_NAME, &(f->shared->lf->driver_id)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file driver ID")
-
- /* Set the driver "info" in the property list */
- driver_info = H5FD_fapl_get(f->shared->lf);
- if(driver_info != NULL && H5P_set(new_plist, H5F_ACS_FILE_DRV_INFO_NAME, &driver_info) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file driver info")
-
- /* Set the file close degree appropriately */
- if(f->shared->fc_degree == H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_ACS_CLOSE_DEGREE_NAME, &(f->shared->lf->cls->fc_degree)) < 0) {
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree")
- } else if(f->shared->fc_degree != H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_ACS_CLOSE_DEGREE_NAME, &(f->shared->fc_degree)) < 0) {
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree")
- }
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_get_access_plist() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5Fget_obj_count
*
* Purpose: Public function returning the number of opened object IDs
@@ -445,38 +312,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_get_obj_count
- *
- * Purpose: Private function return the number of opened object IDs
- * (files, datasets, groups, datatypes) in the same file.
- *
- * Return: SUCCEED on success, FAIL on failure.
- *
- * Programmer: Raymond Lu
- * Wednesday, Dec 5, 2001
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr)
-{
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity check */
- HDassert(obj_id_count_ptr);
-
- /* Perform the query */
- if((ret_value = H5F_get_objects(f, types, 0, NULL, app_ref, obj_id_count_ptr)) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_get_obj_count() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5Fget_object_ids
*
* Purpose: Public function to return a list of opened object IDs.
@@ -525,253 +360,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_get_obj_ids
- *
- * Purpose: Private function to return a list of opened object IDs.
- *
- * Return: Non-negative on success; can't fail.
- *
- * Programmer: Raymond Lu
- * Wednesday, Dec 5, 2001
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref, size_t *obj_id_count_ptr)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity check */
- HDassert(obj_id_count_ptr);
-
- /* Perform the query */
- if((ret_value = H5F_get_objects(f, types, max_objs, oid_list, app_ref, obj_id_count_ptr)) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_get_obj_ids() */
-
-
-/*---------------------------------------------------------------------------
- * Function: H5F_get_objects
- *
- * Purpose: This function is called by H5F_get_obj_count or
- * H5F_get_obj_ids to get number of object IDs and/or a
- * list of opened object IDs (in return value).
- * Return: Non-negative on success; Can't fail.
- *
- * Programmer: Raymond Lu
- * Wednesday, Dec 5, 2001
- *
- *---------------------------------------------------------------------------
- */
-static herr_t
-H5F_get_objects(const H5F_t *f, unsigned types, size_t max_nobjs, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr)
-{
- size_t obj_id_count=0; /* Number of open IDs */
- H5F_olist_t olist; /* Structure to hold search results */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Sanity check */
- HDassert(obj_id_count_ptr);
-
- /* Set up search information */
- olist.obj_id_list = (max_nobjs==0 ? NULL : obj_id_list);
- olist.obj_id_count = &obj_id_count;
- olist.list_index = 0;
- olist.max_nobjs = max_nobjs;
-
- /* Determine if we are searching for local or global objects */
- if(types & H5F_OBJ_LOCAL) {
- olist.file_info.local = TRUE;
- olist.file_info.ptr.file = f;
- } /* end if */
- else {
- olist.file_info.local = FALSE;
- olist.file_info.ptr.shared = f ? f->shared : NULL;
- } /* end else */
-
- /* Iterate through file IDs to count the number, and put their
- * IDs on the object list. */
- if(types & H5F_OBJ_FILE) {
- olist.obj_type = H5I_FILE;
- if(H5I_iterate(H5I_FILE, H5F_get_objects_cb, &olist, app_ref) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(1)")
- } /* end if */
-
- /* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
- * or the caller wants to get the list of IDs and the list isn't full,
- * search through dataset IDs to count number of datasets, and put their
- * IDs on the object list */
- if(!olist.max_nobjs || (olist.max_nobjs && olist.list_index<olist.max_nobjs)) {
- if (types & H5F_OBJ_DATASET) {
- olist.obj_type = H5I_DATASET;
- if(H5I_iterate(H5I_DATASET, H5F_get_objects_cb, &olist, app_ref) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(2)")
- } /* end if */
- }
-
- /* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
- * or the caller wants to get the list of IDs and the list isn't full,
- * search through group IDs to count number of groups, and put their
- * IDs on the object list */
- if(!olist.max_nobjs || (olist.max_nobjs && olist.list_index<olist.max_nobjs)) {
- if(types & H5F_OBJ_GROUP) {
- olist.obj_type = H5I_GROUP;
- if(H5I_iterate(H5I_GROUP, H5F_get_objects_cb, &olist, app_ref) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(3)")
- } /* end if */
- }
-
- /* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
- * or the caller wants to get the list of IDs and the list isn't full,
- * search through datatype IDs to count number of named datatypes, and put their
- * IDs on the object list */
- if(!olist.max_nobjs || (olist.max_nobjs && olist.list_index<olist.max_nobjs)) {
- if(types & H5F_OBJ_DATATYPE) {
- olist.obj_type = H5I_DATATYPE;
- if(H5I_iterate(H5I_DATATYPE, H5F_get_objects_cb, &olist, app_ref) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(4)")
- } /* end if */
- }
-
- /* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
- * or the caller wants to get the list of IDs and the list isn't full,
- * search through attribute IDs to count number of attributes, and put their
- * IDs on the object list */
- if(!olist.max_nobjs || (olist.max_nobjs && olist.list_index<olist.max_nobjs)) {
- if(types & H5F_OBJ_ATTR) {
- olist.obj_type = H5I_ATTR;
- if(H5I_iterate(H5I_ATTR, H5F_get_objects_cb, &olist, app_ref) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(5)")
- } /* end if */
- }
-
- /* Set the number of objects currently open */
- *obj_id_count_ptr = obj_id_count;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_get_objects() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_get_objects_cb
- *
- * Purpose: H5F_get_objects' callback function. It verifies if an
- * object is in the file, and either count it or put its ID
- * on the list.
- *
- * Return: H5_ITER_STOP if the array of object IDs is filled up.
- * H5_ITER_CONT otherwise.
- *
- * Programmer: Raymond Lu
- * Wednesday, Dec 5, 2001
- *
- *-------------------------------------------------------------------------
- */
-static int
-H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
-{
- H5F_olist_t *olist = (H5F_olist_t *)key; /* Alias for search info */
- int ret_value = H5_ITER_CONT; /* Return value */
- hbool_t add_obj = FALSE;
-
- FUNC_ENTER_NOAPI_NOINIT
-
- HDassert(obj_ptr);
- HDassert(olist);
-
- /* Count file IDs */
- if(olist->obj_type == H5I_FILE) {
- if((olist->file_info.local &&
- (!olist->file_info.ptr.file || (olist->file_info.ptr.file && (H5F_t*)obj_ptr == olist->file_info.ptr.file) ))
- || (!olist->file_info.local &&
- ( !olist->file_info.ptr.shared || (olist->file_info.ptr.shared && ((H5F_t*)obj_ptr)->shared == olist->file_info.ptr.shared) ))) {
- add_obj = TRUE;
- }
- } /* end if */
- else { /* either count opened object IDs or put the IDs on the list */
- H5O_loc_t *oloc; /* Group entry info for object */
-
- switch(olist->obj_type) {
- case H5I_ATTR:
- oloc = H5A_oloc((H5A_t *)obj_ptr);
- break;
-
- case H5I_GROUP:
- oloc = H5G_oloc((H5G_t *)obj_ptr);
- break;
-
- case H5I_DATASET:
- oloc = H5D_oloc((H5D_t *)obj_ptr);
- break;
-
- case H5I_DATATYPE:
- if(H5T_is_named((H5T_t*)obj_ptr)==TRUE)
- oloc = H5T_oloc((H5T_t*)obj_ptr);
- else
- oloc = NULL;
- break;
-
- case H5I_UNINIT:
- case H5I_BADID:
- case H5I_FILE:
- case H5I_DATASPACE:
- case H5I_REFERENCE:
- case H5I_VFL:
- case H5I_GENPROP_CLS:
- case H5I_GENPROP_LST:
- case H5I_ERROR_CLASS:
- case H5I_ERROR_MSG:
- case H5I_ERROR_STACK:
- case H5I_NTYPES:
- default:
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "unknown data object")
- } /* end switch */
-
- if((olist->file_info.local &&
- ( (!olist->file_info.ptr.file && olist->obj_type == H5I_DATATYPE && H5T_is_immutable((H5T_t *)obj_ptr) == FALSE)
- || (!olist->file_info.ptr.file && olist->obj_type != H5I_DATATYPE)
- || (oloc && oloc->file == olist->file_info.ptr.file)))
- || (!olist->file_info.local &&
- ((!olist->file_info.ptr.shared && olist->obj_type == H5I_DATATYPE && H5T_is_immutable((H5T_t *)obj_ptr) == FALSE)
- || (!olist->file_info.ptr.shared && olist->obj_type != H5I_DATATYPE)
- || (oloc && oloc->file && oloc->file->shared == olist->file_info.ptr.shared)))) {
- add_obj = TRUE;
- } /* end if */
- } /* end else */
-
- if(TRUE==add_obj) {
- /* Add the object's ID to the ID list, if appropriate */
- if(olist->obj_id_list) {
- olist->obj_id_list[olist->list_index] = obj_id;
- olist->list_index++;
- } /* end if */
-
- /* Increment the number of open objects */
- if(olist->obj_id_count)
- (*olist->obj_id_count)++;
-
- /* Check if we've filled up the array. Return H5_ITER_STOP only if
- * we have filled up the array. Otherwise return H5_ITER_CONT(RET_VALUE is
- * preset to H5_ITER_CONT) because H5I_iterate needs the return value of
- * H5_ITER_CONT to continue the iteration. */
- if(olist->max_nobjs>0 && olist->list_index>=olist->max_nobjs)
- HGOTO_DONE(H5_ITER_STOP) /* Indicate that the iterator should stop */
- }
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_get_objects_cb() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5Fget_vfd_handle
*
* Purpose: Returns a pointer to the file handle of the low-level file
@@ -834,8 +422,6 @@ done:
htri_t
H5Fis_hdf5(const char *name)
{
- H5FD_t *file = NULL; /* Low-level file struct */
- haddr_t sig_addr; /* Address of hdf5 file signature */
htri_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -845,608 +431,17 @@ H5Fis_hdf5(const char *name)
if(!name || !*name)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "no file name specified")
- /* Open the file at the virtual file layer */
- if(NULL == (file = H5FD_open(name, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT, HADDR_UNDEF)))
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to open file")
-
- /* The file is an hdf5 file if the hdf5 file signature can be found */
- if(H5FD_locate_signature(file, H5AC_ind_dxpl_g, &sig_addr) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to locate file signature")
- ret_value = (HADDR_UNDEF != sig_addr);
+ /* call the private is_HDF5 function */
+ if((ret_value = H5F_is_hdf5(name)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable open file")
done:
- /* Close the file */
- if(file)
- if(H5FD_close(file) < 0 && ret_value >= 0)
- HDONE_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
FUNC_LEAVE_API(ret_value)
} /* end H5Fis_hdf5() */
/*-------------------------------------------------------------------------
- * Function: H5F_new
- *
- * Purpose: Creates a new file object and initializes it. The
- * H5Fopen and H5Fcreate functions then fill in various
- * fields. If SHARED is a non-null pointer then the shared info
- * to which it points has the reference count incremented.
- * Otherwise a new, empty shared info struct is created and
- * initialized with the specified file access property list.
- *
- * Errors:
- *
- * Return: Success: Ptr to a new file struct.
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 18 1997
- *
- *-------------------------------------------------------------------------
- */
-static H5F_t *
-H5F_new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
-{
- H5F_t *f = NULL, *ret_value;
-
- FUNC_ENTER_NOAPI_NOINIT
-
- if(NULL == (f = H5FL_CALLOC(H5F_t)))
- HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate top file structure")
- f->file_id = -1;
-
- if(shared) {
- HDassert(lf == NULL);
- f->shared = shared;
- } /* end if */
- else {
- H5P_genplist_t *plist; /* Property list */
- unsigned efc_size; /* External file cache size */
- size_t u; /* Local index variable */
-
- HDassert(lf != NULL);
- if(NULL == (f->shared = H5FL_CALLOC(H5F_file_t)))
- HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared file structure")
-
- f->shared->flags = flags;
- f->shared->sohm_addr = HADDR_UNDEF;
- f->shared->sohm_vers = HDF5_SHAREDHEADER_VERSION;
- for(u = 0; u < NELMTS(f->shared->fs_addr); u++)
- f->shared->fs_addr[u] = HADDR_UNDEF;
- f->shared->accum.loc = HADDR_UNDEF;
- f->shared->lf = lf;
-
- /*
- * Copy the file creation and file access property lists into the
- * new file handle. We do this early because some values might need
- * to change as the file is being opened.
- */
- if(NULL == (plist = (H5P_genplist_t *)H5I_object(fcpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not property list")
- f->shared->fcpl_id = H5P_copy_plist(plist, FALSE);
-
- /* Get the FCPL values to cache */
- if(H5P_get(plist, H5F_CRT_ADDR_BYTE_NUM_NAME, &f->shared->sizeof_addr) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for address")
- if(H5P_get(plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &f->shared->sizeof_size) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for object size")
- if(H5P_get(plist, H5F_CRT_SHMSG_NINDEXES_NAME, &f->shared->sohm_nindexes) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get number of SOHM indexes")
- HDassert(f->shared->sohm_nindexes < 255);
- if(H5P_get(plist, H5F_CRT_FILE_SPACE_STRATEGY_NAME, &f->shared->fs_strategy) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file space strategy")
- if(H5P_get(plist, H5F_CRT_FREE_SPACE_THRESHOLD_NAME, &f->shared->fs_threshold) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get free-space section threshold")
-
- /* Get the FAPL values to cache */
- if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list")
- if(H5P_get(plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial metadata cache resize config")
- if(H5P_get(plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(f->shared->rdcc_nslots)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache number of slots")
- if(H5P_get(plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache byte size")
- if(H5P_get(plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &(f->shared->rdcc_w0)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get preempt read chunk")
- if(H5P_get(plist, H5F_ACS_ALIGN_THRHD_NAME, &(f->shared->threshold)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment threshold")
- if(H5P_get(plist, H5F_ACS_ALIGN_NAME, &(f->shared->alignment)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment")
- if(H5P_get(plist, H5F_ACS_GARBG_COLCT_REF_NAME,&(f->shared->gc_ref)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get garbage collect reference")
- if(H5P_get(plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get sieve buffer size")
- if(H5P_get(plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'latest format' flag")
- if(H5P_get(plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get metadata cache size")
- f->shared->meta_aggr.feature_flag = H5FD_FEAT_AGGREGATE_METADATA;
- if(H5P_get(plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'small data' cache size")
- f->shared->sdata_aggr.feature_flag = H5FD_FEAT_AGGREGATE_SMALLDATA;
- if(H5P_get(plist, H5F_ACS_EFC_SIZE_NAME, &efc_size) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get elink file cache size")
- if(efc_size > 0)
- if(NULL == (f->shared->efc = H5F_efc_create(efc_size)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't create external file cache")
-
- /* Get the VFD values to cache */
- f->shared->maxaddr = H5FD_get_maxaddr(lf);
- if(!H5F_addr_defined(f->shared->maxaddr))
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad maximum address from VFD")
- if(H5FD_get_feature_flags(lf, &f->shared->feature_flags) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get feature flags from VFD")
- if(H5FD_get_fs_type_map(lf, f->shared->fs_type_map) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get free space type mapping from VFD")
- if(H5MF_init_merge_flags(f) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "problem initializing free space merge flags")
- f->shared->tmp_addr = f->shared->maxaddr;
- /* Disable temp. space allocation for parallel I/O (for now) */
- /* (When we've arranged to have the relocated metadata addresses (and
- * sizes) broadcast during the "end of epoch" metadata operations,
- * this can be enabled - QAK)
- */
- /* (This should be disabled when the metadata journaling branch is
- * merged into the trunk and journaling is enabled, at least until
- * we make it work. - QAK)
- */
- f->shared->use_tmp_space = !H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI);
-
- /*
- * Create a metadata cache with the specified number of elements.
- * The cache might be created with a different number of elements and
- * the access property list should be updated to reflect that.
- */
- if(H5AC_create(f, &(f->shared->mdc_initCacheCfg)) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create metadata cache")
-
- /* Create the file's "open object" information */
- if(H5FO_create(f) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure")
-
- /* Add new "shared" struct to list of open files */
- if(H5F_sfile_add(f->shared) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to append to list of open files")
- } /* end else */
-
- f->shared->nrefs++;
-
- /* Create the file's "top open object" information */
- if(H5FO_top_create(f) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure")
-
- /* Set return value */
- ret_value = f;
-
-done:
- if(!ret_value && f) {
- if(!shared) {
- /* Attempt to clean up some of the shared file structures */
- if(f->shared->efc)
- if(H5F_efc_destroy(f->shared->efc) < 0)
- HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, NULL, "can't destroy external file cache")
- if(f->shared->fcpl_id > 0)
- if(H5I_dec_ref(f->shared->fcpl_id) < 0)
- HDONE_ERROR(H5E_FILE, H5E_CANTDEC, NULL, "can't close property list")
-
- f->shared = H5FL_FREE(H5F_file_t, f->shared);
- } /* end if */
- f = H5FL_FREE(H5F_t, f);
- } /* end if */
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_new() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_dest
- *
- * Purpose: Destroys a file structure. This function flushes the cache
- * but doesn't do any other cleanup other than freeing memory
- * for the file struct. The shared info for the file is freed
- * only when its reference count reaches zero.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Jul 18 1997
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Sanity check */
- HDassert(f);
- HDassert(f->shared);
-
- if(1 == f->shared->nrefs) {
- H5F_io_info_t fio_info; /* I/O info for operation */
-
- /* Flush at this point since the file will be closed.
- * Only try to flush the file if it was opened with write access, and if
- * the caller requested a flush.
- */
- if((H5F_ACC_RDWR & H5F_INTENT(f)) && flush)
- if(H5F_flush(f, dxpl_id, TRUE) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
-
- /* Release the external file cache */
- if(f->shared->efc) {
- if(H5F_efc_destroy(f->shared->efc) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't destroy external file cache")
- f->shared->efc = NULL;
- } /* end if */
-
- /* Release objects that depend on the superblock being initialized */
- if(f->shared->sblock) {
- /* Shutdown file free space manager(s) */
- /* (We should release the free space information now (before truncating
- * the file and before the metadata cache is shut down) since the
- * free space manager is holding some data structures in memory
- * and also because releasing free space can shrink the file's
- * 'eoa' value)
- */
- if(H5F_ACC_RDWR & H5F_INTENT(f)) {
- if(H5MF_close(f, dxpl_id) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file free space info")
-
- /* Flush the file again (if requested), as shutting down the
- * free space manager may dirty some data structures again.
- */
- if(flush)
- if(H5F_flush(f, dxpl_id, TRUE) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
- } /* end if */
-
- /* Unpin the superblock, since we're about to destroy the cache */
- if(H5AC_unpin_entry(f->shared->sblock) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin superblock")
- f->shared->sblock = NULL;
- } /* end if */
-
- /* Remove shared file struct from list of open files */
- if(H5F_sfile_remove(f->shared) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
-
- /* Shutdown the metadata cache */
- if(H5AC_dest(f, dxpl_id))
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
-
- /*
- * Do not close the root group since we didn't count it, but free
- * the memory associated with it.
- */
- if(f->shared->root_grp) {
- /* Free the root group */
- if(H5G_root_free(f->shared->root_grp) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
- f->shared->root_grp = NULL;
- } /* end if */
-
- /* Set up I/O info for operation */
- fio_info.f = f;
- if(NULL == (fio_info.dxpl = (H5P_genplist_t *)H5I_object(dxpl_id)))
- HDONE_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
-
- /* Destroy other components of the file */
- if(H5F__accum_reset(&fio_info, TRUE) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
- if(H5FO_dest(f) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
- f->shared->cwfs = (struct H5HG_heap_t **)H5MM_xfree(f->shared->cwfs);
- if(H5G_node_close(f) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
-
- /* Destroy file creation properties */
- if(H5I_GENPROP_LST != H5I_get_type(f->shared->fcpl_id))
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "not a property list")
- if(H5I_dec_ref(f->shared->fcpl_id) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't close property list")
-
- /* Only truncate the file on an orderly close, with write-access */
- if(f->closing && (H5F_ACC_RDWR & H5F_INTENT(f))) {
- /* Truncate the file to the current allocated size */
- if(H5FD_truncate(f->shared->lf, dxpl_id, (unsigned)TRUE) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "low level truncate failed")
- } /* end if */
-
- /* Close the file */
- if(H5FD_close(f->shared->lf) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
-
- /* Free mount table */
- f->shared->mtab.child = (H5F_mount_t *)H5MM_xfree(f->shared->mtab.child);
- f->shared->mtab.nalloc = 0;
-
- /* Destroy shared file struct */
- f->shared = (H5F_file_t *)H5FL_FREE(H5F_file_t, f->shared);
-
- } else if(f->shared->nrefs > 0) {
- /*
- * There are other references to the shared part of the file.
- * Only decrement the reference count.
- */
- --f->shared->nrefs;
- }
-
- /* Free the non-shared part of the file */
- f->open_name = (char *)H5MM_xfree(f->open_name);
- f->actual_name = (char *)H5MM_xfree(f->actual_name);
- f->extpath = (char *)H5MM_xfree(f->extpath);
- if(H5FO_top_dest(f) < 0)
- HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "problems closing file")
- f->shared = NULL;
- f = H5FL_FREE(H5F_t, f);
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_dest() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_open
- *
- * Purpose: Opens (or creates) a file. This function understands the
- * following flags which are similar in nature to the Posix
- * open(2) flags.
- *
- * H5F_ACC_RDWR: Open with read/write access. If the file is
- * currently open for read-only access then it
- * will be reopened. Absence of this flag
- * implies read-only access.
- *
- * H5F_ACC_CREAT: Create a new file if it doesn't exist yet.
- * The permissions are 0666 bit-wise AND with
- * the current umask. H5F_ACC_WRITE must also
- * be specified.
- *
- * H5F_ACC_EXCL: This flag causes H5F_open() to fail if the
- * file already exists.
- *
- * H5F_ACC_TRUNC: The file is truncated and a new HDF5 superblock
- * is written. This operation will fail if the
- * file is already open.
- *
- * Unlinking the file name from the group directed graph while
- * the file is opened causes the file to continue to exist but
- * one will not be able to upgrade the file from read-only
- * access to read-write access by reopening it. Disk resources
- * for the file are released when all handles to the file are
- * closed. NOTE: This paragraph probably only applies to Unix;
- * deleting the file name in other OS's has undefined results.
- *
- * The CREATE_PARMS argument is optional. A null pointer will
- * cause the default file creation parameters to be used.
- *
- * The ACCESS_PARMS argument is optional. A null pointer will
- * cause the default file access parameters to be used.
- *
- * Return: Success: A new file pointer.
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * Tuesday, September 23, 1997
- *
- *-------------------------------------------------------------------------
- */
-H5F_t *
-H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id,
- hid_t dxpl_id)
-{
- H5F_t *file = NULL; /*the success return value */
- H5F_file_t *shared = NULL; /*shared part of `file' */
- H5FD_t *lf = NULL; /*file driver part of `shared' */
- unsigned tent_flags; /*tentative flags */
- H5FD_class_t *drvr; /*file driver class info */
- H5P_genplist_t *a_plist; /*file access property list */
- H5F_close_degree_t fc_degree; /*file close degree */
- H5F_t *ret_value; /*actual return value */
-
- FUNC_ENTER_NOAPI(NULL)
-
- /*
- * If the driver has a `cmp' method then the driver is capable of
- * determining when two file handles refer to the same file and the
- * library can insure that when the application opens a file twice
- * that the two handles coordinate their operations appropriately.
- * Otherwise it is the application's responsibility to never open the
- * same file more than once at a time.
- */
- if(NULL == (drvr = H5FD_get_class(fapl_id)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to retrieve VFL class")
-
- /*
- * Opening a file is a two step process. First we try to open the
- * file in a way which doesn't affect its state (like not truncating
- * or creating it) so we can compare it with files that are already
- * open. If that fails then we try again with the full set of flags
- * (only if they're different than the original failed attempt).
- * However, if the file driver can't distinquish between files then
- * there's no reason to open the file tentatively because it's the
- * application's responsibility to prevent this situation (there's no
- * way for us to detect it here anyway).
- */
- if(drvr->cmp)
- tent_flags = flags & ~(H5F_ACC_CREAT|H5F_ACC_TRUNC|H5F_ACC_EXCL);
- else
- tent_flags = flags;
-
- if(NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) {
- if(tent_flags == flags) {
-#ifndef H5_USING_MEMCHECKER
- time_t mytime = HDtime(NULL);
-
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: time = %s, name = '%s', tent_flags = %x", HDctime(&mytime), name, tent_flags)
-#else /* H5_USING_MEMCHECKER */
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', tent_flags = %x", name, tent_flags)
-#endif /* H5_USING_MEMCHECKER */
- } /* end if */
- H5E_clear_stack(NULL);
- tent_flags = flags;
- if(NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) {
-#ifndef H5_USING_MEMCHECKER
- time_t mytime = HDtime(NULL);
-
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: time = %s, name = '%s', tent_flags = %x", HDctime(&mytime), name, tent_flags)
-#else /* H5_USING_MEMCHECKER */
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', tent_flags = %x", name, tent_flags)
-#endif /* H5_USING_MEMCHECKER */
- } /* end if */
- } /* end if */
-
- /* Is the file already open? */
- if((shared = H5F_sfile_search(lf)) != NULL) {
- /*
- * The file is already open, so use that one instead of the one we
- * just opened. We only one one H5FD_t* per file so one doesn't
- * confuse the other. But fail if this request was to truncate the
- * file (since we can't do that while the file is open), or if the
- * request was to create a non-existent file (since the file already
- * exists), or if the new request adds write access (since the
- * readers don't expect the file to change under them).
- */
- if(H5FD_close(lf) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info")
- if(flags & H5F_ACC_TRUNC)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to truncate a file which is already open")
- if(flags & H5F_ACC_EXCL)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file exists")
- if((flags & H5F_ACC_RDWR) && 0 == (shared->flags & H5F_ACC_RDWR))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file is already open for read-only")
-
- /* Allocate new "high-level" file struct */
- if((file = H5F_new(shared, flags, fcpl_id, fapl_id, NULL)) == NULL)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object")
- } /* end if */
- else {
- /* Check if tentative open was good enough */
- if(flags != tent_flags) {
- /*
- * This file is not yet open by the library and the flags we used to
- * open it are different than the desired flags. Close the tentative
- * file and open it for real.
- */
- if(H5FD_close(lf) < 0) {
- file = NULL; /*to prevent destruction of wrong file*/
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info")
- } /* end if */
- if(NULL == (lf = H5FD_open(name, flags, fapl_id, HADDR_UNDEF))) {
- file = NULL; /*to prevent destruction of wrong file*/
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file")
- } /* end if */
- } /* end if */
-
- if(NULL == (file = H5F_new(NULL, flags, fcpl_id, fapl_id, lf)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object")
- } /* end else */
-
- /* Retain the name the file was opened with */
- file->open_name = H5MM_xstrdup(name);
-
- /* Short cuts */
- shared = file->shared;
- lf = shared->lf;
-
- /*
- * Read or write the file superblock, depending on whether the file is
- * empty or not.
- */
- if(0 == H5FD_get_eof(lf) && (flags & H5F_ACC_RDWR)) {
- /*
- * We've just opened a fresh new file (or truncated one). We need
- * to create & write the superblock.
- */
-
- /* Initialize information about the superblock and allocate space for it */
- /* (Writes superblock extension messages, if there are any) */
- if(H5F_super_init(file, dxpl_id) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to allocate file superblock")
-
- /* Create and open the root group */
- /* (This must be after the space for the superblock is allocated in
- * the file, since the superblock must be at offset 0)
- */
- if(H5G_mkroot(file, dxpl_id, TRUE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create/open root group")
- } else if (1 == shared->nrefs) {
- /* Read the superblock if it hasn't been read before. */
- if(H5F_super_read(file, dxpl_id) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock")
-
- /* Open the root group */
- if(H5G_mkroot(file, dxpl_id, FALSE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read root group")
- } /* end if */
-
- /* Get the file access property list, for future queries */
- if(NULL == (a_plist = (H5P_genplist_t *)H5I_object(fapl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list")
-
- /*
- * Decide the file close degree. If it's the first time to open the
- * file, set the degree to access property list value; if it's the
- * second time or later, verify the access property list value matches
- * the degree in shared file structure.
- */
- if(H5P_get(a_plist, H5F_ACS_CLOSE_DEGREE_NAME, &fc_degree) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file close degree")
-
- if(shared->nrefs == 1) {
- if(fc_degree == H5F_CLOSE_DEFAULT)
- shared->fc_degree = lf->cls->fc_degree;
- else
- shared->fc_degree = fc_degree;
- } else if(shared->nrefs > 1) {
- if(fc_degree == H5F_CLOSE_DEFAULT && shared->fc_degree != lf->cls->fc_degree)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match")
- if(fc_degree != H5F_CLOSE_DEFAULT && fc_degree != shared->fc_degree)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match")
- } /* end if */
-
- /* Formulate the absolute path for later search of target file for external links */
- if(H5_build_extpath(name, &file->extpath) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build extpath")
-
- /* Formulate the actual file name, after following symlinks, etc. */
- if(H5F_build_actual_name(file, a_plist, name, &file->actual_name) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build actual name")
-
- /* Success */
- ret_value = file;
-
-done:
- if(!ret_value && file)
- if(H5F_dest(file, dxpl_id, FALSE) < 0)
- HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_open() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5Fcreate
*
* Purpose: This is the primary function for creating HDF5 files . The
@@ -1741,297 +736,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_flush
- *
- * Purpose: Flushes cached data.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 29 1997
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_flush(H5F_t *f, hid_t dxpl_id, hbool_t closing)
-{
- H5F_io_info_t fio_info; /* I/O info for operation */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(FAIL)
-
- /* Sanity check arguments */
- HDassert(f);
-
- /* Flush any cached dataset storage raw data */
- if(H5D_flush(f, dxpl_id) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush dataset cache")
-
- /* Release any space allocated to space aggregators, so that the eoa value
- * corresponds to the end of the space written to in the file.
- */
- /* (needs to happen before cache flush, with superblock write, since the
- * 'eoa' value is written in superblock -QAK)
- */
- if(H5MF_free_aggrs(f, dxpl_id) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file space")
-
- /* Flush the entire metadata cache */
- if(H5AC_flush(f, dxpl_id) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush metadata cache")
-
- /* Set up I/O info for operation */
- fio_info.f = f;
- if(NULL == (fio_info.dxpl = (H5P_genplist_t *)H5I_object(dxpl_id)))
- HDONE_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
-
- /* Flush out the metadata accumulator */
- if(H5F__accum_flush(&fio_info) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush metadata accumulator")
-
- /* Flush file buffers to disk. */
- if(H5FD_flush(f->shared->lf, dxpl_id, closing) < 0)
- /* Push error, but keep going*/
- HDONE_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_flush() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_close
- *
- * Purpose: Closes a file or causes the close operation to be pended.
- * This function is called two ways: from the API it gets called
- * by H5Fclose->H5I_dec_ref->H5F_close when H5I_dec_ref()
- * decrements the file ID reference count to zero. The file ID
- * is removed from the H5I_FILE group by H5I_dec_ref() just
- * before H5F_close() is called. If there are open object
- * headers then the close is pended by moving the file to the
- * H5I_FILE_CLOSING ID group (the f->closing contains the ID
- * assigned to file).
- *
- * This function is also called directly from H5O_close() when
- * the last object header is closed for the file and the file
- * has a pending close.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Tuesday, September 23, 1997
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5F_close(H5F_t *f)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Sanity check */
- HDassert(f);
- HDassert(f->file_id > 0); /* This routine should only be called when a file ID's ref count drops to zero */
-
- /* Perform checks for "semi" file close degree here, since closing the
- * file is not allowed if there are objects still open */
- if(f->shared->fc_degree == H5F_CLOSE_SEMI) {
- unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */
- unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */
-
- /* Get the number of open objects and open files on this file/mount hierarchy */
- if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy")
-
- /* If there are no other file IDs open on this file/mount hier., but
- * there are still open objects, issue an error and bail out now,
- * without decrementing the file ID's reference count and triggering
- * a "real" attempt at closing the file */
- if(nopen_files == 1 && nopen_objs > 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open")
- } /* end if */
-
- /* Reset the file ID for this file */
- f->file_id = -1;
-
- /* Attempt to close the file/mount hierarchy */
- if(H5F_try_close(f) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_close() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_try_close
- *
- * Purpose: Attempts to close a file due to one of several actions:
- * - The reference count on the file ID dropped to zero
- * - The last open object was closed in the file
- * - The file was unmounted
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Tuesday, July 19, 2005
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_try_close(H5F_t *f)
-{
- unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */
- unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Sanity check */
- HDassert(f);
- HDassert(f->shared);
-
- /* Check if this file is already in the process of closing */
- if(f->closing)
- HGOTO_DONE(SUCCEED)
-
- /* Get the number of open objects and open files on this file/mount hierarchy */
- if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy")
-
- /*
- * Close file according to close degree:
- *
- * H5F_CLOSE_WEAK: if there are still objects open, wait until
- * they are all closed.
- * H5F_CLOSE_SEMI: if there are still objects open, return fail;
- * otherwise, close file.
- * H5F_CLOSE_STRONG: if there are still objects open, close them
- * first, then close file.
- */
- switch(f->shared->fc_degree) {
- case H5F_CLOSE_WEAK:
- /*
- * If file or object IDS are still open then delay deletion of
- * resources until they have all been closed. Flush all
- * caches and update the object header anyway so that failing to
- * close all objects isn't a major problem.
- */
- if((nopen_files + nopen_objs) > 0)
- HGOTO_DONE(SUCCEED)
- break;
-
- case H5F_CLOSE_SEMI:
- /* Can leave safely if file IDs are still open on this file */
- if(nopen_files > 0)
- HGOTO_DONE(SUCCEED)
-
- /* Sanity check: If close degree if "semi" and we have gotten this
- * far and there are objects left open, bail out now */
- HDassert(nopen_files == 0 && nopen_objs == 0);
-
- /* If we've gotten this far (ie. there are no open objects in the file), fall through to flush & close */
- break;
-
- case H5F_CLOSE_STRONG:
- /* If there are other open files in the hierarchy, we can leave now */
- if(nopen_files > 0)
- HGOTO_DONE(SUCCEED)
-
- /* If we've gotten this far (ie. there are no open file IDs in the file/mount hierarchy), fall through to flush & close */
- break;
-
- case H5F_CLOSE_DEFAULT:
- default:
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, unknown file close degree")
- } /* end switch */
-
- /* Mark this file as closing (prevents re-entering file shutdown code below) */
- f->closing = TRUE;
-
- /* If the file close degree is "strong", close all the open objects in this file */
- if(f->shared->fc_degree == H5F_CLOSE_STRONG) {
- HDassert(nopen_files == 0);
-
- /* Forced close of all opened objects in this file */
- if(f->nopen_objs > 0) {
- size_t obj_count; /* # of open objects */
- hid_t objs[128]; /* Array of objects to close */
- herr_t result; /* Local result from obj ID query */
- size_t u; /* Local index variable */
-
- /* Get the list of IDs of open dataset, group, & attribute objects */
- while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATASET | H5F_OBJ_GROUP | H5F_OBJ_ATTR, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0
- && obj_count != 0 ) {
-
- /* Try to close all the open objects in this file */
- for(u = 0; u < obj_count; u++)
- if(H5I_dec_ref(objs[u]) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
- } /* end while */
- if(result < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(1)")
-
- /* Get the list of IDs of open named datatype objects */
- /* (Do this separately from the dataset & attribute IDs, because
- * they could be using one of the named datatypes and then the
- * open named datatype ID will get closed twice)
- */
- while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATATYPE, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0
- && obj_count != 0) {
-
- /* Try to close all the open objects in this file */
- for(u = 0; u < obj_count; u++)
- if(H5I_dec_ref(objs[u]) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
- } /* end while */
- if(result < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(2)")
- } /* end if */
- } /* end if */
-
- /* Check if this is a child file in a mounting hierarchy & proceed up the
- * hierarchy if so.
- */
- if(f->parent)
- if(H5F_try_close(f->parent) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close parent file")
-
- /* Unmount and close each child before closing the current file. */
- if(H5F_close_mounts(f) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child files")
-
- /* If there is more than one reference to the shared file struct and the
- * file has an external file cache, we should see if it can be closed. This
- * can happen if a cycle is formed with external file caches */
- if(f->shared->efc && (f->shared->nrefs > 1))
- if(H5F_efc_try_close(f) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't attempt to close EFC")
-
- /* Delay flush until the shared file struct is closed, in H5F_dest. If the
- * application called H5Fclose, it would have been flushed in that function
- * (unless it will have been flushed in H5F_dest anyways). */
-
- /*
- * Destroy the H5F_t struct and decrement the reference count for the
- * shared H5F_file_t struct. If the reference count for the H5F_file_t
- * struct reaches zero then destroy it also.
- */
- if(H5F_dest(f, H5AC_dxpl_id, TRUE) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_try_close() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5Fclose
*
* Purpose: This function closes the file specified by FILE_ID by
@@ -2196,382 +900,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5F_get_id
- *
- * Purpose: Get the file ID, incrementing it, or "resurrecting" it as
- * appropriate.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Raymond Lu
- * Oct 29, 2003
- *
- *-------------------------------------------------------------------------
- */
-hid_t
-H5F_get_id(H5F_t *file, hbool_t app_ref)
-{
- hid_t ret_value;
-
- FUNC_ENTER_NOAPI_NOINIT
-
- HDassert(file);
-
- if(file->file_id == -1) {
- /* Get an atom for the file */
- if((file->file_id = H5I_register(H5I_FILE, file, app_ref)) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file")
- } else {
- /* Increment reference count on atom. */
- if(H5I_inc_ref(file->file_id, app_ref) < 0)
- HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed")
- } /* end else */
-
- ret_value = file->file_id;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5F_get_id() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_incr_nopen_objs
- *
- * Purpose: Increment the number of open objects for a file.
- *
- * Return: Success: The number of open objects, after the increment
- *
- * Failure: (can't happen)
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Mar 6 2007
- *
- *-------------------------------------------------------------------------
- */
-unsigned
-H5F_incr_nopen_objs(H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- HDassert(f);
-
- FUNC_LEAVE_NOAPI(++f->nopen_objs)
-} /* end H5F_incr_nopen_objs() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_decr_nopen_objs
- *
- * Purpose: Decrement the number of open objects for a file.
- *
- * Return: Success: The number of open objects, after the decrement
- *
- * Failure: (can't happen)
- *
- * Programmer: Quincey Koziol
- * koziol@hdfgroup.org
- * Mar 6 2007
- *
- *-------------------------------------------------------------------------
- */
-unsigned
-H5F_decr_nopen_objs(H5F_t *f)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- HDassert(f);
-
- FUNC_LEAVE_NOAPI(--f->nopen_objs)
-} /* end H5F_decr_nopen_objs() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_build_actual_name
- *
- * Purpose: Retrieve the name of a file, after following symlinks, etc.
- *
- * Note: Currently only working for "POSIX I/O compatible" VFDs
- *
- * Return: Success: 0
- * Failure: -1
- *
- * Programmer: Quincey Koziol
- * November 25, 2009
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5F_build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, const char *name,
- char **actual_name/*out*/)
-{
- hid_t new_fapl_id = -1; /* ID for duplicated FAPL */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- /* Sanity check */
- HDassert(f);
- HDassert(fapl);
- HDassert(name);
- HDassert(actual_name);
-
- /* Clear actual name pointer to begin with */
- *actual_name = NULL;
-
-/* Assume that if the OS can't create symlinks, that we don't need to worry
- * about resolving them either. -QAK
- */
-#ifdef H5_HAVE_SYMLINK
- /* Check for POSIX I/O compatible file handle */
- if(H5F_HAS_FEATURE(f, H5FD_FEAT_POSIX_COMPAT_HANDLE)) {
- h5_stat_t lst; /* Stat info from lstat() call */
-
- /* Call lstat() on the file's name */
- if(HDlstat(name, &lst) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve stat info for file")
-
- /* Check for symbolic link */
- if(S_IFLNK == (lst.st_mode & S_IFMT)) {
- H5P_genplist_t *new_fapl; /* Duplicated FAPL */
- int *fd; /* POSIX I/O file descriptor */
- h5_stat_t st; /* Stat info from stat() call */
- h5_stat_t fst; /* Stat info from fstat() call */
- char realname[PATH_MAX]; /* Fully resolved path name of file */
- hbool_t want_posix_fd; /* Flag for retrieving file descriptor from VFD */
-
- /* Perform a sanity check that the file or link wasn't switched
- * between when we opened it and when we called lstat(). This is
- * according to the security best practices for lstat() documented
- * here: https://www.securecoding.cert.org/confluence/display/seccode/POS35-C.+Avoid+race+conditions+while+checking+for+the+existence+of+a+symbolic+link
- */
-
- /* Copy the FAPL object to modify */
- if((new_fapl_id = H5P_copy_plist(fapl, FALSE)) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy file access property list")
- if(NULL == (new_fapl = (H5P_genplist_t *)H5I_object(new_fapl_id)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "can't get property list")
-
- /* Set the character encoding on the new property list */
- want_posix_fd = TRUE;
- if(H5P_set(new_fapl, H5F_ACS_WANT_POSIX_FD_NAME, &want_posix_fd) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set character encoding")
-
- /* Retrieve the file handle */
- if(H5F_get_vfd_handle(f, new_fapl_id, (void **)&fd) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve POSIX file descriptor")
-
- /* Stat the filename we're resolving */
- if(HDstat(name, &st) < 0)
- HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to stat file")
-
- /* Stat the file we opened */
- if(HDfstat(*fd, &fst) < 0)
- HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to fstat file")
-
- /* Verify that the files are really the same */
- if(st.st_mode != fst.st_mode || st.st_ino != fst.st_ino || st.st_dev != fst.st_dev)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "files' st_ino or st_dev fields changed!")
-
- /* Get the resolved path for the file name */
- if(NULL == HDrealpath(name, realname))
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve real path for file")
-
- /* Duplicate the resolved path for the file name */
- if(NULL == (*actual_name = (char *)H5MM_strdup(realname)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't duplicate real path")
- } /* end if */
- } /* end if */
-#endif /* H5_HAVE_SYMLINK */
-
- /* Check if we've resolved the file's name */
- if(NULL == *actual_name) {
- /* Just duplicate the name used to open the file */
- if(NULL == (*actual_name = (char *)H5MM_strdup(name)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't duplicate open name")
- } /* end else */
-
-done:
- /* Close the property list */
- if(new_fapl_id > 0)
- if(H5I_dec_app_ref(new_fapl_id) < 0)
- HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close duplicated FAPL")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5F_build_actual_name() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_addr_encode_len
- *
- * Purpose: Encodes an address into the buffer pointed to by *PP and
- * then increments the pointer to the first byte after the
- * address. An undefined value is stored as all 1's.
- *
- * Return: void
- *
- * Programmer: Robb Matzke
- * Friday, November 7, 1997
- *
- *-------------------------------------------------------------------------
- */
-void
-H5F_addr_encode_len(size_t addr_len, uint8_t **pp/*in,out*/, haddr_t addr)
-{
- unsigned u; /* Local index variable */
-
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- HDassert(addr_len);
- HDassert(pp && *pp);
-
- if(H5F_addr_defined(addr)) {
- for(u = 0; u < addr_len; u++) {
- *(*pp)++ = (uint8_t)(addr & 0xff);
- addr >>= 8;
- } /* end for */
- HDassert("overflow" && 0 == addr);
- } /* end if */
- else {
- for(u = 0; u < addr_len; u++)
- *(*pp)++ = 0xff;
- } /* end else */
-
- FUNC_LEAVE_NOAPI_VOID
-} /* end H5F_addr_encode_len() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_addr_encode
- *
- * Purpose: Encodes an address into the buffer pointed to by *PP and
- * then increments the pointer to the first byte after the
- * address. An undefined value is stored as all 1's.
- *
- * Return: void
- *
- * Programmer: Robb Matzke
- * Friday, November 7, 1997
- *
- *-------------------------------------------------------------------------
- */
-void
-H5F_addr_encode(const H5F_t *f, uint8_t **pp/*in,out*/, haddr_t addr)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- HDassert(f);
-
- H5F_addr_encode_len(H5F_SIZEOF_ADDR(f), pp, addr);
-
- FUNC_LEAVE_NOAPI_VOID
-} /* end H5F_addr_encode() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_addr_decode_len
- *
- * Purpose: Decodes an address from the buffer pointed to by *PP and
- * updates the pointer to point to the next byte after the
- * address.
- *
- * If the value read is all 1's then the address is returned
- * with an undefined value.
- *
- * Return: void
- *
- * Programmer: Robb Matzke
- * Friday, November 7, 1997
- *
- *-------------------------------------------------------------------------
- */
-void
-H5F_addr_decode_len(size_t addr_len, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*out*/)
-{
- hbool_t all_zero = TRUE; /* True if address was all zeroes */
- unsigned u; /* Local index variable */
-
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- HDassert(addr_len);
- HDassert(pp && *pp);
- HDassert(addr_p);
-
- /* Reset value in destination */
- *addr_p = 0;
-
- /* Decode bytes from address */
- for(u = 0; u < addr_len; u++) {
- uint8_t c; /* Local decoded byte */
-
- /* Get decoded byte (and advance pointer) */
- c = *(*pp)++;
-
- /* Check for non-undefined address byte value */
- if(c != 0xff)
- all_zero = FALSE;
-
- if(u < sizeof(*addr_p)) {
- haddr_t tmp = c; /* Local copy of address, for casting */
-
- /* Shift decoded byte to correct position */
- tmp <<= (u * 8); /*use tmp to get casting right */
-
- /* Merge into already decoded bytes */
- *addr_p |= tmp;
- } /* end if */
- else
- if(!all_zero)
- HDassert(0 == **pp); /*overflow */
- } /* end for */
-
- /* If 'all_zero' is still TRUE, the address was entirely composed of '0xff'
- * bytes, which is the encoded form of 'HADDR_UNDEF', so set the destination
- * to that value */
- if(all_zero)
- *addr_p = HADDR_UNDEF;
-
- FUNC_LEAVE_NOAPI_VOID
-} /* end H5F_addr_decode_len() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_addr_decode
- *
- * Purpose: Decodes an address from the buffer pointed to by *PP and
- * updates the pointer to point to the next byte after the
- * address.
- *
- * If the value read is all 1's then the address is returned
- * with an undefined value.
- *
- * Return: void
- *
- * Programmer: Robb Matzke
- * Friday, November 7, 1997
- *
- *-------------------------------------------------------------------------
- */
-void
-H5F_addr_decode(const H5F_t *f, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*out*/)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- HDassert(f);
-
- H5F_addr_decode_len(H5F_SIZEOF_ADDR(f), pp, addr_p);
-
- FUNC_LEAVE_NOAPI_VOID
-} /* end H5F_addr_decode() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5Fget_freespace
*
* Purpose: Retrieves the amount of free space in the file.
@@ -2699,8 +1027,6 @@ ssize_t
H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len)
{
H5F_t *file; /* File object for file ID */
- H5FD_t *fd_ptr; /* file driver */
- haddr_t eoa; /* End of file address */
ssize_t ret_value; /* Return value */
FUNC_ENTER_API(FAIL)
@@ -2709,79 +1035,11 @@ H5Fget_file_image(hid_t file_id, void *buf_ptr, size_t buf_len)
/* Check args */
if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID")
- if(!file || !file->shared || !file->shared->lf)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file_id yields invalid file pointer")
- fd_ptr = file->shared->lf;
- if(!fd_ptr->cls)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "fd_ptr yields invalid class pointer")
-
- /* the address space used by the split and multi file drivers is not
- * a good fit for this call. Since the plan is to depreciate these
- * drivers anyway, don't bother to do a "force fit".
- *
- * The following clause tests for the multi file driver, and fails
- * if the supplied file has the multi file driver as its top level
- * file driver. However, this test will not work if there is some
- * other file driver sitting on top of the multi file driver.
- *
- * I'm not sure if this is possible at present, but in all likelyhood,
- * it will become possible in the future. On the other hand, we may
- * remove the split/multi file drivers before then.
- *
- * I am leaving this solution in for now, but we should review it,
- * and improve the solution if necessary.
- *
- * JRM -- 11/11/22
- */
- if(HDstrcmp(fd_ptr->cls->name, "multi") == 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Not supported for multi file driver.")
-
- /* While the family file driver is conceptually fully compatible
- * with the get file image operation, it sets a file driver message
- * in the super block that prevents the image being opened with any
- * driver other than the family file driver. Needless to say, this
- * rather defeats the purpose of the get file image operation.
- *
- * While this problem is quire solvable, the required time and
- * resources are lacking at present. Hence, for now, we don't
- * allow the get file image operation to be perfomed on files
- * opened with the family file driver.
- *
- * Observe that the following test only looks at the top level
- * driver, and fails if there is some other driver sitting on to
- * of the family file driver.
- *
- * I don't think this can happen at present, but that may change
- * in the future.
- * JRM -- 12/21/11
- */
- if(HDstrcmp(fd_ptr->cls->name, "family") == 0)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "Not supported for family file driver.")
-
-
- /* Go get the actual file size */
- if(HADDR_UNDEF == (eoa = H5FD_get_eoa(file->shared->lf, H5FD_MEM_DEFAULT)))
- HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size")
-
- /* set ret_value = to eoa -- will overwrite this if appropriate */
- ret_value = (ssize_t)eoa;
-
- /* test to see if a buffer was provided -- if not, we are done */
- if(buf_ptr != NULL) {
- size_t space_needed; /* size of file image */
- /* Check for buffer too small */
- if((haddr_t)buf_len < eoa)
- HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "supplied buffer too small")
+ /* call private get_file_image function */
+ if((ret_value = H5F_get_file_image(file, buf_ptr, buf_len)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file image")
- space_needed = (size_t)eoa;
-
- /* read in the file image */
- /* (Note compensation for base address addition in internal routine) */
- if(H5FD_read(fd_ptr, H5AC_ind_dxpl_g, H5FD_MEM_DEFAULT, 0, space_needed, buf_ptr) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "file image read request failed")
- } /* end if */
-
done:
FUNC_LEAVE_API(ret_value)
} /* H5Fget_file_image() */
@@ -3209,150 +1467,3 @@ H5Fclear_elink_file_cache(hid_t file_id)
done:
FUNC_LEAVE_API(ret_value)
} /* end H5Fclear_elink_file_cache() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_set_grp_btree_shared
- *
- * Purpose: Set the grp_btree_shared field with a valid ref-count pointer.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- * 7/19/11
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_set_grp_btree_shared(H5F_t *f, H5UC_t *rc)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- /* Sanity check */
- HDassert(f);
- HDassert(f->shared);
- HDassert(rc);
-
- f->shared->grp_btree_shared = rc;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5F_set_grp_btree_shared() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_set_sohm_addr
- *
- * Purpose: Set the sohm_addr field with a new value.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- * 7/20/11
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_set_sohm_addr(H5F_t *f, haddr_t addr)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- /* Sanity check */
- HDassert(f);
- HDassert(f->shared);
-
- f->shared->sohm_addr = addr;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5F_set_sohm_addr() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_set_sohm_vers
- *
- * Purpose: Set the sohm_vers field with a new value.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- * 7/20/11
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_set_sohm_vers(H5F_t *f, unsigned vers)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- /* Sanity check */
- HDassert(f);
- HDassert(f->shared);
-
- f->shared->sohm_vers = vers;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5F_set_sohm_vers() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_set_sohm_nindexes
- *
- * Purpose: Set the sohm_nindexes field with a new value.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- * 7/20/11
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_set_sohm_nindexes(H5F_t *f, unsigned nindexes)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- /* Sanity check */
- HDassert(f);
- HDassert(f->shared);
-
- f->shared->sohm_nindexes = nindexes;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5F_set_sohm_nindexes() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5F_set_store_msg_crt_idx
- *
- * Purpose: Set the store_msg_crt_idx field with a new value.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- * Programmer: Quincey Koziol
- * 7/20/11
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5F_set_store_msg_crt_idx(H5F_t *f, hbool_t flag)
-{
- /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- /* Sanity check */
- HDassert(f);
- HDassert(f->shared);
-
- f->shared->store_msg_crt_idx = flag;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* H5F_set_store_msg_crt_idx() */
-
diff --git a/src/H5Fint.c b/src/H5Fint.c
new file mode 100644
index 0000000..48a8d1f
--- /dev/null
+++ b/src/H5Fint.c
@@ -0,0 +1,2051 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+
+/* Interface initialization */
+#define H5_INTERFACE_INIT_FUNC H5F_init_interface
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Aprivate.h" /* Attributes */
+#include "H5ACprivate.h" /* Metadata cache */
+#include "H5Dprivate.h" /* Datasets */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5FDprivate.h" /* File drivers */
+#include "H5Gprivate.h" /* Groups */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Pprivate.h" /* Property lists */
+#include "H5SMprivate.h" /* Shared Object Header Messages */
+#include "H5Tprivate.h" /* Datatypes */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* Struct only used by functions H5F_get_objects and H5F_get_objects_cb */
+typedef struct H5F_olist_t {
+ H5I_type_t obj_type; /* Type of object to look for */
+ hid_t *obj_id_list; /* Pointer to the list of open IDs to return */
+ size_t *obj_id_count; /* Number of open IDs */
+ struct {
+ hbool_t local; /* Set flag for "local" file searches */
+ union {
+ H5F_file_t *shared; /* Pointer to shared file to look inside */
+ const H5F_t *file; /* Pointer to file to look inside */
+ } ptr;
+ } file_info;
+ size_t list_index; /* Current index in open ID array */
+ size_t max_nobjs; /* Maximum # of IDs to put into array */
+} H5F_olist_t;
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key);
+static herr_t H5F_build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl,
+ const char *name, char ** /*out*/ actual_name);/* Declare a free list to manage the H5F_t struct */
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage the H5F_t struct */
+H5FL_DEFINE(H5F_t);
+
+/* Declare a free list to manage the H5F_file_t struct */
+H5FL_DEFINE(H5F_file_t);
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_init_interface
+ *
+ * Purpose: Initialize interface-specific information.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 20, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F_init_interface(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_init_interface() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_access_plist
+ *
+ * Purpose: Returns a copy of the file access property list of the
+ * specified file.
+ *
+ * NOTE: Make sure that, if you are going to overwrite
+ * information in the copied property list that was
+ * previously opened and assigned to the property list, then
+ * you must close it before overwriting the values.
+ *
+ * Return: Success: Object ID for a copy of the file access
+ * property list.
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, May 25, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5F_get_access_plist(H5F_t *f, hbool_t app_ref)
+{
+ H5P_genplist_t *new_plist; /* New property list */
+ H5P_genplist_t *old_plist; /* Old property list */
+ void *driver_info=NULL;
+ unsigned efc_size = 0;
+ hid_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check args */
+ HDassert(f);
+
+ /* Make a copy of the default file access property list */
+ if(NULL == (old_plist = (H5P_genplist_t *)H5I_object(H5P_LST_FILE_ACCESS_ID_g)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+ if((ret_value = H5P_copy_plist(old_plist, app_ref)) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "can't copy file access property list")
+ if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(ret_value)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+
+ /* Copy properties of the file access property list */
+ if(H5P_set(new_plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set initial metadata cache resize config.")
+ if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(f->shared->rdcc_nslots)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache number of slots")
+ if(H5P_set(new_plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set data cache byte size")
+ if(H5P_set(new_plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &(f->shared->rdcc_w0)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set preempt read chunks")
+ if(H5P_set(new_plist, H5F_ACS_ALIGN_THRHD_NAME, &(f->shared->threshold)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set alignment threshold")
+ if(H5P_set(new_plist, H5F_ACS_ALIGN_NAME, &(f->shared->alignment)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set alignment")
+ if(H5P_set(new_plist, H5F_ACS_GARBG_COLCT_REF_NAME, &(f->shared->gc_ref)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set garbage collect reference")
+ if(H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set metadata cache size")
+ if(H5P_set(new_plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't sieve buffer size")
+ if(H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'small data' cache size")
+ if(H5P_set(new_plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set 'latest format' flag")
+ if(f->shared->efc)
+ efc_size = H5F_efc_max_nfiles(f->shared->efc);
+ if(H5P_set(new_plist, H5F_ACS_EFC_SIZE_NAME, &efc_size) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set elink file cache size")
+
+ /*
+ * Since we're resetting the driver ID and info, close them if they
+ * exist in this new property list.
+ */
+ if(H5P_facc_close(ret_value, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTFREE, FAIL, "can't free the old driver information")
+
+ /* Increment the reference count on the driver ID and insert it into the property list */
+ if(H5I_inc_ref(f->shared->lf->driver_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINC, FAIL, "unable to increment ref count on VFL driver")
+ if(H5P_set(new_plist, H5F_ACS_FILE_DRV_ID_NAME, &(f->shared->lf->driver_id)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file driver ID")
+
+ /* Set the driver "info" in the property list */
+ driver_info = H5FD_fapl_get(f->shared->lf);
+ if(driver_info != NULL && H5P_set(new_plist, H5F_ACS_FILE_DRV_INFO_NAME, &driver_info) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file driver info")
+
+ /* Set the file close degree appropriately */
+ if(f->shared->fc_degree == H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_ACS_CLOSE_DEGREE_NAME, &(f->shared->lf->cls->fc_degree)) < 0) {
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree")
+ } else if(f->shared->fc_degree != H5F_CLOSE_DEFAULT && H5P_set(new_plist, H5F_ACS_CLOSE_DEGREE_NAME, &(f->shared->fc_degree)) < 0) {
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set file close degree")
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_get_access_plist() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_obj_count
+ *
+ * Purpose: Private function return the number of opened object IDs
+ * (files, datasets, groups, datatypes) in the same file.
+ *
+ * Return: SUCCEED on success, FAIL on failure.
+ *
+ * Programmer: Raymond Lu
+ * Wednesday, Dec 5, 2001
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(obj_id_count_ptr);
+
+ /* Perform the query */
+ if((ret_value = H5F_get_objects(f, types, 0, NULL, app_ref, obj_id_count_ptr)) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_get_obj_count() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_obj_ids
+ *
+ * Purpose: Private function to return a list of opened object IDs.
+ *
+ * Return: Non-negative on success; can't fail.
+ *
+ * Programmer: Raymond Lu
+ * Wednesday, Dec 5, 2001
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref, size_t *obj_id_count_ptr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(obj_id_count_ptr);
+
+ /* Perform the query */
+ if((ret_value = H5F_get_objects(f, types, max_objs, oid_list, app_ref, obj_id_count_ptr)) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_objects failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_get_obj_ids() */
+
+
+/*---------------------------------------------------------------------------
+ * Function: H5F_get_objects
+ *
+ * Purpose: This function is called by H5F_get_obj_count or
+ * H5F_get_obj_ids to get number of object IDs and/or a
+ * list of opened object IDs (in return value).
+ * Return: Non-negative on success; Can't fail.
+ *
+ * Programmer: Raymond Lu
+ * Wednesday, Dec 5, 2001
+ *
+ *---------------------------------------------------------------------------
+ */
+herr_t
+H5F_get_objects(const H5F_t *f, unsigned types, size_t max_nobjs, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr)
+{
+ size_t obj_id_count=0; /* Number of open IDs */
+ H5F_olist_t olist; /* Structure to hold search results */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity check */
+ HDassert(obj_id_count_ptr);
+
+ /* Set up search information */
+ olist.obj_id_list = (max_nobjs==0 ? NULL : obj_id_list);
+ olist.obj_id_count = &obj_id_count;
+ olist.list_index = 0;
+ olist.max_nobjs = max_nobjs;
+
+ /* Determine if we are searching for local or global objects */
+ if(types & H5F_OBJ_LOCAL) {
+ olist.file_info.local = TRUE;
+ olist.file_info.ptr.file = f;
+ } /* end if */
+ else {
+ olist.file_info.local = FALSE;
+ olist.file_info.ptr.shared = f ? f->shared : NULL;
+ } /* end else */
+
+ /* Iterate through file IDs to count the number, and put their
+ * IDs on the object list. */
+ if(types & H5F_OBJ_FILE) {
+ olist.obj_type = H5I_FILE;
+ if(H5I_iterate(H5I_FILE, H5F_get_objects_cb, &olist, app_ref) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(1)")
+ } /* end if */
+
+ /* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
+ * or the caller wants to get the list of IDs and the list isn't full,
+ * search through dataset IDs to count number of datasets, and put their
+ * IDs on the object list */
+ if(!olist.max_nobjs || (olist.max_nobjs && olist.list_index<olist.max_nobjs)) {
+ if (types & H5F_OBJ_DATASET) {
+ olist.obj_type = H5I_DATASET;
+ if(H5I_iterate(H5I_DATASET, H5F_get_objects_cb, &olist, app_ref) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(2)")
+ } /* end if */
+ }
+
+ /* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
+ * or the caller wants to get the list of IDs and the list isn't full,
+ * search through group IDs to count number of groups, and put their
+ * IDs on the object list */
+ if(!olist.max_nobjs || (olist.max_nobjs && olist.list_index<olist.max_nobjs)) {
+ if(types & H5F_OBJ_GROUP) {
+ olist.obj_type = H5I_GROUP;
+ if(H5I_iterate(H5I_GROUP, H5F_get_objects_cb, &olist, app_ref) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(3)")
+ } /* end if */
+ }
+
+ /* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
+ * or the caller wants to get the list of IDs and the list isn't full,
+ * search through datatype IDs to count number of named datatypes, and put their
+ * IDs on the object list */
+ if(!olist.max_nobjs || (olist.max_nobjs && olist.list_index<olist.max_nobjs)) {
+ if(types & H5F_OBJ_DATATYPE) {
+ olist.obj_type = H5I_DATATYPE;
+ if(H5I_iterate(H5I_DATATYPE, H5F_get_objects_cb, &olist, app_ref) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(4)")
+ } /* end if */
+ }
+
+ /* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
+ * or the caller wants to get the list of IDs and the list isn't full,
+ * search through attribute IDs to count number of attributes, and put their
+ * IDs on the object list */
+ if(!olist.max_nobjs || (olist.max_nobjs && olist.list_index<olist.max_nobjs)) {
+ if(types & H5F_OBJ_ATTR) {
+ olist.obj_type = H5I_ATTR;
+ if(H5I_iterate(H5I_ATTR, H5F_get_objects_cb, &olist, app_ref) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(5)")
+ } /* end if */
+ }
+
+ /* Set the number of objects currently open */
+ *obj_id_count_ptr = obj_id_count;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_get_objects() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_objects_cb
+ *
+ * Purpose: H5F_get_objects' callback function. It verifies if an
+ * object is in the file, and either count it or put its ID
+ * on the list.
+ *
+ * Return: H5_ITER_STOP if the array of object IDs is filled up.
+ * H5_ITER_CONT otherwise.
+ *
+ * Programmer: Raymond Lu
+ * Wednesday, Dec 5, 2001
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
+{
+ H5F_olist_t *olist = (H5F_olist_t *)key; /* Alias for search info */
+ int ret_value = H5_ITER_CONT; /* Return value */
+ hbool_t add_obj = FALSE;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(obj_ptr);
+ HDassert(olist);
+
+ /* Count file IDs */
+ if(olist->obj_type == H5I_FILE) {
+ if((olist->file_info.local &&
+ (!olist->file_info.ptr.file || (olist->file_info.ptr.file && (H5F_t*)obj_ptr == olist->file_info.ptr.file) ))
+ || (!olist->file_info.local &&
+ ( !olist->file_info.ptr.shared || (olist->file_info.ptr.shared && ((H5F_t*)obj_ptr)->shared == olist->file_info.ptr.shared) ))) {
+ add_obj = TRUE;
+ }
+ } /* end if */
+ else { /* either count opened object IDs or put the IDs on the list */
+ H5O_loc_t *oloc; /* Group entry info for object */
+
+ switch(olist->obj_type) {
+ case H5I_ATTR:
+ oloc = H5A_oloc((H5A_t *)obj_ptr);
+ break;
+
+ case H5I_GROUP:
+ oloc = H5G_oloc((H5G_t *)obj_ptr);
+ break;
+
+ case H5I_DATASET:
+ oloc = H5D_oloc((H5D_t *)obj_ptr);
+ break;
+
+ case H5I_DATATYPE:
+ if(H5T_is_named((H5T_t*)obj_ptr)==TRUE)
+ oloc = H5T_oloc((H5T_t*)obj_ptr);
+ else
+ oloc = NULL;
+ break;
+
+ case H5I_UNINIT:
+ case H5I_BADID:
+ case H5I_FILE:
+ case H5I_DATASPACE:
+ case H5I_REFERENCE:
+ case H5I_VFL:
+ case H5I_GENPROP_CLS:
+ case H5I_GENPROP_LST:
+ case H5I_ERROR_CLASS:
+ case H5I_ERROR_MSG:
+ case H5I_ERROR_STACK:
+ case H5I_NTYPES:
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "unknown data object")
+ } /* end switch */
+
+ if((olist->file_info.local &&
+ ( (!olist->file_info.ptr.file && olist->obj_type == H5I_DATATYPE && H5T_is_immutable((H5T_t *)obj_ptr) == FALSE)
+ || (!olist->file_info.ptr.file && olist->obj_type != H5I_DATATYPE)
+ || (oloc && oloc->file == olist->file_info.ptr.file)))
+ || (!olist->file_info.local &&
+ ((!olist->file_info.ptr.shared && olist->obj_type == H5I_DATATYPE && H5T_is_immutable((H5T_t *)obj_ptr) == FALSE)
+ || (!olist->file_info.ptr.shared && olist->obj_type != H5I_DATATYPE)
+ || (oloc && oloc->file && oloc->file->shared == olist->file_info.ptr.shared)))) {
+ add_obj = TRUE;
+ } /* end if */
+ } /* end else */
+
+ if(TRUE==add_obj) {
+ /* Add the object's ID to the ID list, if appropriate */
+ if(olist->obj_id_list) {
+ olist->obj_id_list[olist->list_index] = obj_id;
+ olist->list_index++;
+ } /* end if */
+
+ /* Increment the number of open objects */
+ if(olist->obj_id_count)
+ (*olist->obj_id_count)++;
+
+ /* Check if we've filled up the array. Return H5_ITER_STOP only if
+ * we have filled up the array. Otherwise return H5_ITER_CONT(RET_VALUE is
+ * preset to H5_ITER_CONT) because H5I_iterate needs the return value of
+ * H5_ITER_CONT to continue the iteration. */
+ if(olist->max_nobjs>0 && olist->list_index>=olist->max_nobjs)
+ HGOTO_DONE(H5_ITER_STOP) /* Indicate that the iterator should stop */
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_get_objects_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_is_hdf5
+ *
+ * Purpose: Check the file signature to detect an HDF5 file.
+ *
+ * Bugs: This function is not robust: it only uses the default file
+ * driver when attempting to open the file when in fact it
+ * should use all known file drivers.
+ *
+ * Return: Success: TRUE/FALSE
+ *
+ * Failure: Negative
+ *
+ * Programmer: Unknown
+ *
+ * Modifications:
+ * Robb Matzke, 1999-08-02
+ * Rewritten to use the virtual file layer.
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5F_is_hdf5(const char *name)
+{
+ H5FD_t *file = NULL; /* Low-level file struct */
+ haddr_t sig_addr; /* Addess of hdf5 file signature */
+ htri_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Open the file at the virtual file layer */
+ if(NULL == (file = H5FD_open(name, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT, HADDR_UNDEF)))
+ HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to open file")
+
+ /* The file is an hdf5 file if the hdf5 file signature can be found */
+ if(H5FD_locate_signature(file, H5AC_ind_dxpl_g, &sig_addr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to locate file signature")
+ ret_value = (HADDR_UNDEF != sig_addr);
+
+done:
+ /* Close the file */
+ if(file)
+ if(H5FD_close(file) < 0 && ret_value >= 0)
+ HDONE_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_is_hdf5() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_new
+ *
+ * Purpose: Creates a new file object and initializes it. The
+ * H5Fopen and H5Fcreate functions then fill in various
+ * fields. If SHARED is a non-null pointer then the shared info
+ * to which it points has the reference count incremented.
+ * Otherwise a new, empty shared info struct is created and
+ * initialized with the specified file access property list.
+ *
+ * Errors:
+ *
+ * Return: Success: Ptr to a new file struct.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 18 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+H5F_t *
+H5F_new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
+{
+ H5F_t *f = NULL, *ret_value;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ if(NULL == (f = H5FL_CALLOC(H5F_t)))
+ HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate top file structure")
+ f->file_id = -1;
+
+ if(shared) {
+ HDassert(lf == NULL);
+ f->shared = shared;
+ } /* end if */
+ else {
+ H5P_genplist_t *plist; /* Property list */
+ unsigned efc_size; /* External file cache size */
+ size_t u; /* Local index variable */
+
+ HDassert(lf != NULL);
+ if(NULL == (f->shared = H5FL_CALLOC(H5F_file_t)))
+ HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared file structure")
+
+ f->shared->flags = flags;
+ f->shared->sohm_addr = HADDR_UNDEF;
+ f->shared->sohm_vers = HDF5_SHAREDHEADER_VERSION;
+ for(u = 0; u < NELMTS(f->shared->fs_addr); u++)
+ f->shared->fs_addr[u] = HADDR_UNDEF;
+ f->shared->accum.loc = HADDR_UNDEF;
+ f->shared->lf = lf;
+
+ /*
+ * Copy the file creation and file access property lists into the
+ * new file handle. We do this early because some values might need
+ * to change as the file is being opened.
+ */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fcpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not property list")
+ f->shared->fcpl_id = H5P_copy_plist(plist, FALSE);
+
+ /* Get the FCPL values to cache */
+ if(H5P_get(plist, H5F_CRT_ADDR_BYTE_NUM_NAME, &f->shared->sizeof_addr) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for address")
+ if(H5P_get(plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &f->shared->sizeof_size) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for object size")
+ if(H5P_get(plist, H5F_CRT_SHMSG_NINDEXES_NAME, &f->shared->sohm_nindexes) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get number of SOHM indexes")
+ HDassert(f->shared->sohm_nindexes < 255);
+ if(H5P_get(plist, H5F_CRT_FILE_SPACE_STRATEGY_NAME, &f->shared->fs_strategy) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file space strategy")
+ if(H5P_get(plist, H5F_CRT_FREE_SPACE_THRESHOLD_NAME, &f->shared->fs_threshold) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get free-space section threshold")
+
+ /* Get the FAPL values to cache */
+ if(NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list")
+ if(H5P_get(plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial metadata cache resize config")
+ if(H5P_get(plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(f->shared->rdcc_nslots)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache number of slots")
+ if(H5P_get(plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache byte size")
+ if(H5P_get(plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &(f->shared->rdcc_w0)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get preempt read chunk")
+ if(H5P_get(plist, H5F_ACS_ALIGN_THRHD_NAME, &(f->shared->threshold)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment threshold")
+ if(H5P_get(plist, H5F_ACS_ALIGN_NAME, &(f->shared->alignment)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment")
+ if(H5P_get(plist, H5F_ACS_GARBG_COLCT_REF_NAME,&(f->shared->gc_ref)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get garbage collect reference")
+ if(H5P_get(plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get sieve buffer size")
+ if(H5P_get(plist, H5F_ACS_LATEST_FORMAT_NAME, &(f->shared->latest_format)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'latest format' flag")
+ if(H5P_get(plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get metadata cache size")
+ f->shared->meta_aggr.feature_flag = H5FD_FEAT_AGGREGATE_METADATA;
+ if(H5P_get(plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'small data' cache size")
+ f->shared->sdata_aggr.feature_flag = H5FD_FEAT_AGGREGATE_SMALLDATA;
+ if(H5P_get(plist, H5F_ACS_EFC_SIZE_NAME, &efc_size) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get elink file cache size")
+ if(efc_size > 0)
+ if(NULL == (f->shared->efc = H5F_efc_create(efc_size)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't create external file cache")
+
+ /* Get the VFD values to cache */
+ f->shared->maxaddr = H5FD_get_maxaddr(lf);
+ if(!H5F_addr_defined(f->shared->maxaddr))
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad maximum address from VFD")
+ if(H5FD_get_feature_flags(lf, &f->shared->feature_flags) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get feature flags from VFD")
+ if(H5FD_get_fs_type_map(lf, f->shared->fs_type_map) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get free space type mapping from VFD")
+ if(H5MF_init_merge_flags(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "problem initializing free space merge flags")
+ f->shared->tmp_addr = f->shared->maxaddr;
+ /* Disable temp. space allocation for parallel I/O (for now) */
+ /* (When we've arranged to have the relocated metadata addresses (and
+ * sizes) broadcast during the "end of epoch" metadata operations,
+ * this can be enabled - QAK)
+ */
+ /* (This should be disabled when the metadata journaling branch is
+ * merged into the trunk and journaling is enabled, at least until
+ * we make it work. - QAK)
+ */
+ f->shared->use_tmp_space = !H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI);
+
+ /*
+ * Create a metadata cache with the specified number of elements.
+ * The cache might be created with a different number of elements and
+ * the access property list should be updated to reflect that.
+ */
+ if(H5AC_create(f, &(f->shared->mdc_initCacheCfg)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create metadata cache")
+
+ /* Create the file's "open object" information */
+ if(H5FO_create(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure")
+
+ /* Add new "shared" struct to list of open files */
+ if(H5F_sfile_add(f->shared) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to append to list of open files")
+ } /* end else */
+
+ f->shared->nrefs++;
+
+ /* Create the file's "top open object" information */
+ if(H5FO_top_create(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure")
+
+ /* Set return value */
+ ret_value = f;
+
+done:
+ if(!ret_value && f) {
+ if(!shared) {
+ /* Attempt to clean up some of the shared file structures */
+ if(f->shared->efc)
+ if(H5F_efc_destroy(f->shared->efc) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, NULL, "can't destroy external file cache")
+ if(f->shared->fcpl_id > 0)
+ if(H5I_dec_ref(f->shared->fcpl_id) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTDEC, NULL, "can't close property list")
+
+ f->shared = H5FL_FREE(H5F_file_t, f->shared);
+ } /* end if */
+ f = H5FL_FREE(H5F_t, f);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_new() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_dest
+ *
+ * Purpose: Destroys a file structure. This function flushes the cache
+ * but doesn't do any other cleanup other than freeing memory
+ * for the file struct. The shared info for the file is freed
+ * only when its reference count reaches zero.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Jul 18 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(f->shared);
+
+ if(1 == f->shared->nrefs) {
+ H5F_io_info_t fio_info; /* I/O info for operation */
+
+ /* Flush at this point since the file will be closed.
+ * Only try to flush the file if it was opened with write access, and if
+ * the caller requested a flush.
+ */
+ if((H5F_ACC_RDWR & H5F_INTENT(f)) && flush)
+ if(H5F_flush(f, dxpl_id, TRUE) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
+
+ /* Release the external file cache */
+ if(f->shared->efc) {
+ if(H5F_efc_destroy(f->shared->efc) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't destroy external file cache")
+ f->shared->efc = NULL;
+ } /* end if */
+
+ /* Release objects that depend on the superblock being initialized */
+ if(f->shared->sblock) {
+ /* Shutdown file free space manager(s) */
+ /* (We should release the free space information now (before truncating
+ * the file and before the metadata cache is shut down) since the
+ * free space manager is holding some data structures in memory
+ * and also because releasing free space can shrink the file's
+ * 'eoa' value)
+ */
+ if(H5F_ACC_RDWR & H5F_INTENT(f)) {
+ if(H5MF_close(f, dxpl_id) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file free space info")
+
+ /* Flush the file again (if requested), as shutting down the
+ * free space manager may dirty some data structures again.
+ */
+ if(flush)
+ if(H5F_flush(f, dxpl_id, TRUE) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
+ } /* end if */
+
+ /* Unpin the superblock, since we're about to destroy the cache */
+ if(H5AC_unpin_entry(f->shared->sblock) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin superblock")
+ f->shared->sblock = NULL;
+ } /* end if */
+
+ /* Remove shared file struct from list of open files */
+ if(H5F_sfile_remove(f->shared) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
+
+ /* Shutdown the metadata cache */
+ if(H5AC_dest(f, dxpl_id))
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
+
+ /*
+ * Do not close the root group since we didn't count it, but free
+ * the memory associated with it.
+ */
+ if(f->shared->root_grp) {
+ /* Free the root group */
+ if(H5G_root_free(f->shared->root_grp) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
+ f->shared->root_grp = NULL;
+ } /* end if */
+
+ /* Set up I/O info for operation */
+ fio_info.f = f;
+ if(NULL == (fio_info.dxpl = (H5P_genplist_t *)H5I_object(dxpl_id)))
+ HDONE_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
+
+ /* Destroy other components of the file */
+ if(H5F__accum_reset(&fio_info, TRUE) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
+ if(H5FO_dest(f) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
+ f->shared->cwfs = (struct H5HG_heap_t **)H5MM_xfree(f->shared->cwfs);
+ if(H5G_node_close(f) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
+
+ /* Destroy file creation properties */
+ if(H5I_GENPROP_LST != H5I_get_type(f->shared->fcpl_id))
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "not a property list")
+ if(H5I_dec_ref(f->shared->fcpl_id) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't close property list")
+
+ /* Only truncate the file on an orderly close, with write-access */
+ if(f->closing && (H5F_ACC_RDWR & H5F_INTENT(f))) {
+ /* Truncate the file to the current allocated size */
+ if(H5FD_truncate(f->shared->lf, dxpl_id, (unsigned)TRUE) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "low level truncate failed")
+ } /* end if */
+
+ /* Close the file */
+ if(H5FD_close(f->shared->lf) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
+
+ /* Free mount table */
+ f->shared->mtab.child = (H5F_mount_t *)H5MM_xfree(f->shared->mtab.child);
+ f->shared->mtab.nalloc = 0;
+
+ /* Destroy shared file struct */
+ f->shared = (H5F_file_t *)H5FL_FREE(H5F_file_t, f->shared);
+
+ } else if(f->shared->nrefs > 0) {
+ /*
+ * There are other references to the shared part of the file.
+ * Only decrement the reference count.
+ */
+ --f->shared->nrefs;
+ }
+
+ /* Free the non-shared part of the file */
+ f->open_name = (char *)H5MM_xfree(f->open_name);
+ f->actual_name = (char *)H5MM_xfree(f->actual_name);
+ f->extpath = (char *)H5MM_xfree(f->extpath);
+ if(H5FO_top_dest(f) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "problems closing file")
+ f->shared = NULL;
+ f = H5FL_FREE(H5F_t, f);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_dest() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_open
+ *
+ * Purpose: Opens (or creates) a file. This function understands the
+ * following flags which are similar in nature to the Posix
+ * open(2) flags.
+ *
+ * H5F_ACC_RDWR: Open with read/write access. If the file is
+ * currently open for read-only access then it
+ * will be reopened. Absence of this flag
+ * implies read-only access.
+ *
+ * H5F_ACC_CREAT: Create a new file if it doesn't exist yet.
+ * The permissions are 0666 bit-wise AND with
+ * the current umask. H5F_ACC_WRITE must also
+ * be specified.
+ *
+ * H5F_ACC_EXCL: This flag causes H5F_open() to fail if the
+ * file already exists.
+ *
+ * H5F_ACC_TRUNC: The file is truncated and a new HDF5 superblock
+ * is written. This operation will fail if the
+ * file is already open.
+ *
+ * Unlinking the file name from the group directed graph while
+ * the file is opened causes the file to continue to exist but
+ * one will not be able to upgrade the file from read-only
+ * access to read-write access by reopening it. Disk resources
+ * for the file are released when all handles to the file are
+ * closed. NOTE: This paragraph probably only applies to Unix;
+ * deleting the file name in other OS's has undefined results.
+ *
+ * The CREATE_PARMS argument is optional. A null pointer will
+ * cause the default file creation parameters to be used.
+ *
+ * The ACCESS_PARMS argument is optional. A null pointer will
+ * cause the default file access parameters to be used.
+ *
+ * Return: Success: A new file pointer.
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, September 23, 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+H5F_t *
+H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id,
+ hid_t dxpl_id)
+{
+ H5F_t *file = NULL; /*the success return value */
+ H5F_file_t *shared = NULL; /*shared part of `file' */
+ H5FD_t *lf = NULL; /*file driver part of `shared' */
+ unsigned tent_flags; /*tentative flags */
+ H5FD_class_t *drvr; /*file driver class info */
+ H5P_genplist_t *a_plist; /*file access property list */
+ H5F_close_degree_t fc_degree; /*file close degree */
+ H5F_t *ret_value; /*actual return value */
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /*
+ * If the driver has a `cmp' method then the driver is capable of
+ * determining when two file handles refer to the same file and the
+ * library can insure that when the application opens a file twice
+ * that the two handles coordinate their operations appropriately.
+ * Otherwise it is the application's responsibility to never open the
+ * same file more than once at a time.
+ */
+ if(NULL == (drvr = H5FD_get_class(fapl_id)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to retrieve VFL class")
+
+ /*
+ * Opening a file is a two step process. First we try to open the
+ * file in a way which doesn't affect its state (like not truncating
+ * or creating it) so we can compare it with files that are already
+ * open. If that fails then we try again with the full set of flags
+ * (only if they're different than the original failed attempt).
+ * However, if the file driver can't distinquish between files then
+ * there's no reason to open the file tentatively because it's the
+ * application's responsibility to prevent this situation (there's no
+ * way for us to detect it here anyway).
+ */
+ if(drvr->cmp)
+ tent_flags = flags & ~(H5F_ACC_CREAT|H5F_ACC_TRUNC|H5F_ACC_EXCL);
+ else
+ tent_flags = flags;
+
+ if(NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) {
+ if(tent_flags == flags) {
+#ifndef H5_USING_MEMCHECKER
+ time_t mytime = HDtime(NULL);
+
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: time = %s, name = '%s', tent_flags = %x", HDctime(&mytime), name, tent_flags)
+#else /* H5_USING_MEMCHECKER */
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', tent_flags = %x", name, tent_flags)
+#endif /* H5_USING_MEMCHECKER */
+ } /* end if */
+ H5E_clear_stack(NULL);
+ tent_flags = flags;
+ if(NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) {
+#ifndef H5_USING_MEMCHECKER
+ time_t mytime = HDtime(NULL);
+
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: time = %s, name = '%s', tent_flags = %x", HDctime(&mytime), name, tent_flags)
+#else /* H5_USING_MEMCHECKER */
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', tent_flags = %x", name, tent_flags)
+#endif /* H5_USING_MEMCHECKER */
+ } /* end if */
+ } /* end if */
+
+ /* Is the file already open? */
+ if((shared = H5F_sfile_search(lf)) != NULL) {
+ /*
+ * The file is already open, so use that one instead of the one we
+ * just opened. We only one one H5FD_t* per file so one doesn't
+ * confuse the other. But fail if this request was to truncate the
+ * file (since we can't do that while the file is open), or if the
+ * request was to create a non-existent file (since the file already
+ * exists), or if the new request adds write access (since the
+ * readers don't expect the file to change under them).
+ */
+ if(H5FD_close(lf) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info")
+ if(flags & H5F_ACC_TRUNC)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to truncate a file which is already open")
+ if(flags & H5F_ACC_EXCL)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file exists")
+ if((flags & H5F_ACC_RDWR) && 0 == (shared->flags & H5F_ACC_RDWR))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file is already open for read-only")
+
+ /* Allocate new "high-level" file struct */
+ if((file = H5F_new(shared, flags, fcpl_id, fapl_id, NULL)) == NULL)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object")
+ } /* end if */
+ else {
+ /* Check if tentative open was good enough */
+ if(flags != tent_flags) {
+ /*
+ * This file is not yet open by the library and the flags we used to
+ * open it are different than the desired flags. Close the tentative
+ * file and open it for real.
+ */
+ if(H5FD_close(lf) < 0) {
+ file = NULL; /*to prevent destruction of wrong file*/
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info")
+ } /* end if */
+ if(NULL == (lf = H5FD_open(name, flags, fapl_id, HADDR_UNDEF))) {
+ file = NULL; /*to prevent destruction of wrong file*/
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file")
+ } /* end if */
+ } /* end if */
+
+ if(NULL == (file = H5F_new(NULL, flags, fcpl_id, fapl_id, lf)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object")
+ } /* end else */
+
+ /* Retain the name the file was opened with */
+ file->open_name = H5MM_xstrdup(name);
+
+ /* Short cuts */
+ shared = file->shared;
+ lf = shared->lf;
+
+ /*
+ * Read or write the file superblock, depending on whether the file is
+ * empty or not.
+ */
+ if(0 == H5FD_get_eof(lf) && (flags & H5F_ACC_RDWR)) {
+ /*
+ * We've just opened a fresh new file (or truncated one). We need
+ * to create & write the superblock.
+ */
+
+ /* Initialize information about the superblock and allocate space for it */
+ /* (Writes superblock extension messages, if there are any) */
+ if(H5F_super_init(file, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to allocate file superblock")
+
+ /* Create and open the root group */
+ /* (This must be after the space for the superblock is allocated in
+ * the file, since the superblock must be at offset 0)
+ */
+ if(H5G_mkroot(file, dxpl_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create/open root group")
+ } else if (1 == shared->nrefs) {
+ /* Read the superblock if it hasn't been read before. */
+ if(H5F_super_read(file, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock")
+
+ /* Open the root group */
+ if(H5G_mkroot(file, dxpl_id, FALSE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read root group")
+ } /* end if */
+
+ /* Get the file access property list, for future queries */
+ if(NULL == (a_plist = (H5P_genplist_t *)H5I_object(fapl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list")
+
+ /*
+ * Decide the file close degree. If it's the first time to open the
+ * file, set the degree to access property list value; if it's the
+ * second time or later, verify the access property list value matches
+ * the degree in shared file structure.
+ */
+ if(H5P_get(a_plist, H5F_ACS_CLOSE_DEGREE_NAME, &fc_degree) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file close degree")
+
+ if(shared->nrefs == 1) {
+ if(fc_degree == H5F_CLOSE_DEFAULT)
+ shared->fc_degree = lf->cls->fc_degree;
+ else
+ shared->fc_degree = fc_degree;
+ } else if(shared->nrefs > 1) {
+ if(fc_degree == H5F_CLOSE_DEFAULT && shared->fc_degree != lf->cls->fc_degree)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match")
+ if(fc_degree != H5F_CLOSE_DEFAULT && fc_degree != shared->fc_degree)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match")
+ } /* end if */
+
+ /* Formulate the absolute path for later search of target file for external links */
+ if(H5_build_extpath(name, &file->extpath) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build extpath")
+
+ /* Formulate the actual file name, after following symlinks, etc. */
+ if(H5F_build_actual_name(file, a_plist, name, &file->actual_name) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build actual name")
+
+ /* Success */
+ ret_value = file;
+
+done:
+ if(!ret_value && file)
+ if(H5F_dest(file, dxpl_id, FALSE) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_open() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_flush
+ *
+ * Purpose: Flushes cached data.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Aug 29 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_flush(H5F_t *f, hid_t dxpl_id, hbool_t closing)
+{
+ H5F_io_info_t fio_info; /* I/O info for operation */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check arguments */
+ HDassert(f);
+
+ /* Flush any cached dataset storage raw data */
+ if(H5D_flush(f, dxpl_id) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush dataset cache")
+
+ /* Release any space allocated to space aggregators, so that the eoa value
+ * corresponds to the end of the space written to in the file.
+ */
+ /* (needs to happen before cache flush, with superblock write, since the
+ * 'eoa' value is written in superblock -QAK)
+ */
+ if(H5MF_free_aggrs(f, dxpl_id) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file space")
+
+ /* Flush the entire metadata cache */
+ if(H5AC_flush(f, dxpl_id) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush metadata cache")
+
+ /* Set up I/O info for operation */
+ fio_info.f = f;
+ if(NULL == (fio_info.dxpl = (H5P_genplist_t *)H5I_object(dxpl_id)))
+ HDONE_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
+
+ /* Flush out the metadata accumulator */
+ if(H5F__accum_flush(&fio_info) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush metadata accumulator")
+
+ /* Flush file buffers to disk. */
+ if(H5FD_flush(f->shared->lf, dxpl_id, closing) < 0)
+ /* Push error, but keep going*/
+ HDONE_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_flush() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_close
+ *
+ * Purpose: Closes a file or causes the close operation to be pended.
+ * This function is called two ways: from the API it gets called
+ * by H5Fclose->H5I_dec_ref->H5F_close when H5I_dec_ref()
+ * decrements the file ID reference count to zero. The file ID
+ * is removed from the H5I_FILE group by H5I_dec_ref() just
+ * before H5F_close() is called. If there are open object
+ * headers then the close is pended by moving the file to the
+ * H5I_FILE_CLOSING ID group (the f->closing contains the ID
+ * assigned to file).
+ *
+ * This function is also called directly from H5O_close() when
+ * the last object header is closed for the file and the file
+ * has a pending close.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, September 23, 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_close(H5F_t *f)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(f->file_id > 0); /* This routine should only be called when a file ID's ref count drops to zero */
+
+ /* Perform checks for "semi" file close degree here, since closing the
+ * file is not allowed if there are objects still open */
+ if(f->shared->fc_degree == H5F_CLOSE_SEMI) {
+ unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */
+ unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */
+
+ /* Get the number of open objects and open files on this file/mount hierarchy */
+ if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy")
+
+ /* If there are no other file IDs open on this file/mount hier., but
+ * there are still open objects, issue an error and bail out now,
+ * without decrementing the file ID's reference count and triggering
+ * a "real" attempt at closing the file */
+ if(nopen_files == 1 && nopen_objs > 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open")
+ } /* end if */
+
+ /* Reset the file ID for this file */
+ f->file_id = -1;
+
+ /* Attempt to close the file/mount hierarchy */
+ if(H5F_try_close(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_try_close
+ *
+ * Purpose: Attempts to close a file due to one of several actions:
+ * - The reference count on the file ID dropped to zero
+ * - The last open object was closed in the file
+ * - The file was unmounted
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, July 19, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_try_close(H5F_t *f)
+{
+ unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */
+ unsigned nopen_objs = 0; /* Number of open objects in file/mount hierarchy */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(f->shared);
+
+ /* Check if this file is already in the process of closing */
+ if(f->closing)
+ HGOTO_DONE(SUCCEED)
+
+ /* Get the number of open objects and open files on this file/mount hierarchy */
+ if(H5F_mount_count_ids(f, &nopen_files, &nopen_objs) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy")
+
+ /*
+ * Close file according to close degree:
+ *
+ * H5F_CLOSE_WEAK: if there are still objects open, wait until
+ * they are all closed.
+ * H5F_CLOSE_SEMI: if there are still objects open, return fail;
+ * otherwise, close file.
+ * H5F_CLOSE_STRONG: if there are still objects open, close them
+ * first, then close file.
+ */
+ switch(f->shared->fc_degree) {
+ case H5F_CLOSE_WEAK:
+ /*
+ * If file or object IDS are still open then delay deletion of
+ * resources until they have all been closed. Flush all
+ * caches and update the object header anyway so that failing to
+ * close all objects isn't a major problem.
+ */
+ if((nopen_files + nopen_objs) > 0)
+ HGOTO_DONE(SUCCEED)
+ break;
+
+ case H5F_CLOSE_SEMI:
+ /* Can leave safely if file IDs are still open on this file */
+ if(nopen_files > 0)
+ HGOTO_DONE(SUCCEED)
+
+ /* Sanity check: If close degree if "semi" and we have gotten this
+ * far and there are objects left open, bail out now */
+ HDassert(nopen_files == 0 && nopen_objs == 0);
+
+ /* If we've gotten this far (ie. there are no open objects in the file), fall through to flush & close */
+ break;
+
+ case H5F_CLOSE_STRONG:
+ /* If there are other open files in the hierarchy, we can leave now */
+ if(nopen_files > 0)
+ HGOTO_DONE(SUCCEED)
+
+ /* If we've gotten this far (ie. there are no open file IDs in the file/mount hierarchy), fall through to flush & close */
+ break;
+
+ case H5F_CLOSE_DEFAULT:
+ default:
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, unknown file close degree")
+ } /* end switch */
+
+ /* Mark this file as closing (prevents re-entering file shutdown code below) */
+ f->closing = TRUE;
+
+ /* If the file close degree is "strong", close all the open objects in this file */
+ if(f->shared->fc_degree == H5F_CLOSE_STRONG) {
+ HDassert(nopen_files == 0);
+
+ /* Forced close of all opened objects in this file */
+ if(f->nopen_objs > 0) {
+ size_t obj_count; /* # of open objects */
+ hid_t objs[128]; /* Array of objects to close */
+ herr_t result; /* Local result from obj ID query */
+ size_t u; /* Local index variable */
+
+ /* Get the list of IDs of open dataset, group, & attribute objects */
+ while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATASET | H5F_OBJ_GROUP | H5F_OBJ_ATTR, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0
+ && obj_count != 0 ) {
+
+ /* Try to close all the open objects in this file */
+ for(u = 0; u < obj_count; u++)
+ if(H5I_dec_ref(objs[u]) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
+ } /* end while */
+ if(result < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(1)")
+
+ /* Get the list of IDs of open named datatype objects */
+ /* (Do this separately from the dataset & attribute IDs, because
+ * they could be using one of the named datatypes and then the
+ * open named datatype ID will get closed twice)
+ */
+ while((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATATYPE, (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0
+ && obj_count != 0) {
+
+ /* Try to close all the open objects in this file */
+ for(u = 0; u < obj_count; u++)
+ if(H5I_dec_ref(objs[u]) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
+ } /* end while */
+ if(result < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(2)")
+ } /* end if */
+ } /* end if */
+
+ /* Check if this is a child file in a mounting hierarchy & proceed up the
+ * hierarchy if so.
+ */
+ if(f->parent)
+ if(H5F_try_close(f->parent) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close parent file")
+
+ /* Unmount and close each child before closing the current file. */
+ if(H5F_close_mounts(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child files")
+
+ /* If there is more than one reference to the shared file struct and the
+ * file has an external file cache, we should see if it can be closed. This
+ * can happen if a cycle is formed with external file caches */
+ if(f->shared->efc && (f->shared->nrefs > 1))
+ if(H5F_efc_try_close(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't attempt to close EFC")
+
+ /* Delay flush until the shared file struct is closed, in H5F_dest. If the
+ * application called H5Fclose, it would have been flushed in that function
+ * (unless it will have been flushed in H5F_dest anyways). */
+
+ /*
+ * Destroy the H5F_t struct and decrement the reference count for the
+ * shared H5F_file_t struct. If the reference count for the H5F_file_t
+ * struct reaches zero then destroy it also.
+ */
+ if(H5F_dest(f, H5AC_dxpl_id, TRUE) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_try_close() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_id
+ *
+ * Purpose: Get the file ID, incrementing it, or "resurrecting" it as
+ * appropriate.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * Oct 29, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5F_get_id(H5F_t *file, hbool_t app_ref)
+{
+ hid_t ret_value;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ HDassert(file);
+
+ if(file->file_id == -1) {
+ /* Get an atom for the file */
+ if((file->file_id = H5I_register(H5I_FILE, file, app_ref)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to atomize file")
+ } else {
+ /* Increment reference count on atom. */
+ if(H5I_inc_ref(file->file_id, app_ref) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTSET, FAIL, "incrementing file ID failed")
+ } /* end else */
+
+ ret_value = file->file_id;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_get_id() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_incr_nopen_objs
+ *
+ * Purpose: Increment the number of open objects for a file.
+ *
+ * Return: Success: The number of open objects, after the increment
+ *
+ * Failure: (can't happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Mar 6 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5F_incr_nopen_objs(H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(f);
+
+ FUNC_LEAVE_NOAPI(++f->nopen_objs)
+} /* end H5F_incr_nopen_objs() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_decr_nopen_objs
+ *
+ * Purpose: Decrement the number of open objects for a file.
+ *
+ * Return: Success: The number of open objects, after the decrement
+ *
+ * Failure: (can't happen)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@hdfgroup.org
+ * Mar 6 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5F_decr_nopen_objs(H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(f);
+
+ FUNC_LEAVE_NOAPI(--f->nopen_objs)
+} /* end H5F_decr_nopen_objs() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_build_actual_name
+ *
+ * Purpose: Retrieve the name of a file, after following symlinks, etc.
+ *
+ * Note: Currently only working for "POSIX I/O compatible" VFDs
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Quincey Koziol
+ * November 25, 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F_build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, const char *name,
+ char **actual_name/*out*/)
+{
+ hid_t new_fapl_id = -1; /* ID for duplicated FAPL */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(fapl);
+ HDassert(name);
+ HDassert(actual_name);
+
+ /* Clear actual name pointer to begin with */
+ *actual_name = NULL;
+
+/* Assume that if the OS can't create symlinks, that we don't need to worry
+ * about resolving them either. -QAK
+ */
+#ifdef H5_HAVE_SYMLINK
+ /* Check for POSIX I/O compatible file handle */
+ if(H5F_HAS_FEATURE(f, H5FD_FEAT_POSIX_COMPAT_HANDLE)) {
+ h5_stat_t lst; /* Stat info from lstat() call */
+
+ /* Call lstat() on the file's name */
+ if(HDlstat(name, &lst) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve stat info for file")
+
+ /* Check for symbolic link */
+ if(S_IFLNK == (lst.st_mode & S_IFMT)) {
+ H5P_genplist_t *new_fapl; /* Duplicated FAPL */
+ int *fd; /* POSIX I/O file descriptor */
+ h5_stat_t st; /* Stat info from stat() call */
+ h5_stat_t fst; /* Stat info from fstat() call */
+ char realname[PATH_MAX]; /* Fully resolved path name of file */
+ hbool_t want_posix_fd; /* Flag for retrieving file descriptor from VFD */
+
+ /* Perform a sanity check that the file or link wasn't switched
+ * between when we opened it and when we called lstat(). This is
+ * according to the security best practices for lstat() documented
+ * here: https://www.securecoding.cert.org/confluence/display/seccode/POS35-C.+Avoid+race+conditions+while+checking+for+the+existence+of+a+symbolic+link
+ */
+
+ /* Copy the FAPL object to modify */
+ if((new_fapl_id = H5P_copy_plist(fapl, FALSE)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy file access property list")
+ if(NULL == (new_fapl = (H5P_genplist_t *)H5I_object(new_fapl_id)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "can't get property list")
+
+ /* Set the character encoding on the new property list */
+ want_posix_fd = TRUE;
+ if(H5P_set(new_fapl, H5F_ACS_WANT_POSIX_FD_NAME, &want_posix_fd) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set character encoding")
+
+ /* Retrieve the file handle */
+ if(H5F_get_vfd_handle(f, new_fapl_id, (void **)&fd) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve POSIX file descriptor")
+
+ /* Stat the filename we're resolving */
+ if(HDstat(name, &st) < 0)
+ HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to stat file")
+
+ /* Stat the file we opened */
+ if(HDfstat(*fd, &fst) < 0)
+ HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to fstat file")
+
+ /* Verify that the files are really the same */
+ if(st.st_mode != fst.st_mode || st.st_ino != fst.st_ino || st.st_dev != fst.st_dev)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "files' st_ino or st_dev fields changed!")
+
+ /* Get the resolved path for the file name */
+ if(NULL == HDrealpath(name, realname))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve real path for file")
+
+ /* Duplicate the resolved path for the file name */
+ if(NULL == (*actual_name = (char *)H5MM_strdup(realname)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't duplicate real path")
+ } /* end if */
+ } /* end if */
+#endif /* H5_HAVE_SYMLINK */
+
+ /* Check if we've resolved the file's name */
+ if(NULL == *actual_name) {
+ /* Just duplicate the name used to open the file */
+ if(NULL == (*actual_name = (char *)H5MM_strdup(name)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't duplicate open name")
+ } /* end else */
+
+done:
+ /* Close the property list */
+ if(new_fapl_id > 0)
+ if(H5I_dec_app_ref(new_fapl_id) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close duplicated FAPL")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F_build_actual_name() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_encode_len
+ *
+ * Purpose: Encodes an address into the buffer pointed to by *PP and
+ * then increments the pointer to the first byte after the
+ * address. An undefined value is stored as all 1's.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5F_addr_encode_len(size_t addr_len, uint8_t **pp/*in,out*/, haddr_t addr)
+{
+ unsigned u; /* Local index variable */
+
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(addr_len);
+ HDassert(pp && *pp);
+
+ if(H5F_addr_defined(addr)) {
+ for(u = 0; u < addr_len; u++) {
+ *(*pp)++ = (uint8_t)(addr & 0xff);
+ addr >>= 8;
+ } /* end for */
+ HDassert("overflow" && 0 == addr);
+ } /* end if */
+ else {
+ for(u = 0; u < addr_len; u++)
+ *(*pp)++ = 0xff;
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5F_addr_encode_len() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_encode
+ *
+ * Purpose: Encodes an address into the buffer pointed to by *PP and
+ * then increments the pointer to the first byte after the
+ * address. An undefined value is stored as all 1's.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5F_addr_encode(const H5F_t *f, uint8_t **pp/*in,out*/, haddr_t addr)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(f);
+
+ H5F_addr_encode_len(H5F_SIZEOF_ADDR(f), pp, addr);
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5F_addr_encode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_decode_len
+ *
+ * Purpose: Decodes an address from the buffer pointed to by *PP and
+ * updates the pointer to point to the next byte after the
+ * address.
+ *
+ * If the value read is all 1's then the address is returned
+ * with an undefined value.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5F_addr_decode_len(size_t addr_len, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*out*/)
+{
+ hbool_t all_zero = TRUE; /* True if address was all zeroes */
+ unsigned u; /* Local index variable */
+
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(addr_len);
+ HDassert(pp && *pp);
+ HDassert(addr_p);
+
+ /* Reset value in destination */
+ *addr_p = 0;
+
+ /* Decode bytes from address */
+ for(u = 0; u < addr_len; u++) {
+ uint8_t c; /* Local decoded byte */
+
+ /* Get decoded byte (and advance pointer) */
+ c = *(*pp)++;
+
+ /* Check for non-undefined address byte value */
+ if(c != 0xff)
+ all_zero = FALSE;
+
+ if(u < sizeof(*addr_p)) {
+ haddr_t tmp = c; /* Local copy of address, for casting */
+
+ /* Shift decoded byte to correct position */
+ tmp <<= (u * 8); /*use tmp to get casting right */
+
+ /* Merge into already decoded bytes */
+ *addr_p |= tmp;
+ } /* end if */
+ else
+ if(!all_zero)
+ HDassert(0 == **pp); /*overflow */
+ } /* end for */
+
+ /* If 'all_zero' is still TRUE, the address was entirely composed of '0xff'
+ * bytes, which is the encoded form of 'HADDR_UNDEF', so set the destination
+ * to that value */
+ if(all_zero)
+ *addr_p = HADDR_UNDEF;
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5F_addr_decode_len() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_addr_decode
+ *
+ * Purpose: Decodes an address from the buffer pointed to by *PP and
+ * updates the pointer to point to the next byte after the
+ * address.
+ *
+ * If the value read is all 1's then the address is returned
+ * with an undefined value.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Friday, November 7, 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5F_addr_decode(const H5F_t *f, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*out*/)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(f);
+
+ H5F_addr_decode_len(H5F_SIZEOF_ADDR(f), pp, addr_p);
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5F_addr_decode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_set_grp_btree_shared
+ *
+ * Purpose: Set the grp_btree_shared field with a valid ref-count pointer.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * 7/19/11
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_set_grp_btree_shared(H5F_t *f, H5UC_t *rc)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(rc);
+
+ f->shared->grp_btree_shared = rc;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5F_set_grp_btree_shared() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_set_sohm_addr
+ *
+ * Purpose: Set the sohm_addr field with a new value.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * 7/20/11
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_set_sohm_addr(H5F_t *f, haddr_t addr)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(f->shared);
+
+ f->shared->sohm_addr = addr;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5F_set_sohm_addr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_set_sohm_vers
+ *
+ * Purpose: Set the sohm_vers field with a new value.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * 7/20/11
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_set_sohm_vers(H5F_t *f, unsigned vers)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(f->shared);
+
+ f->shared->sohm_vers = vers;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5F_set_sohm_vers() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_set_sohm_nindexes
+ *
+ * Purpose: Set the sohm_nindexes field with a new value.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * 7/20/11
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_set_sohm_nindexes(H5F_t *f, unsigned nindexes)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(f->shared);
+
+ f->shared->sohm_nindexes = nindexes;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5F_set_sohm_nindexes() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_set_store_msg_crt_idx
+ *
+ * Purpose: Set the store_msg_crt_idx field with a new value.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer: Quincey Koziol
+ * 7/20/11
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_set_store_msg_crt_idx(H5F_t *f, hbool_t flag)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(f->shared);
+
+ f->shared->store_msg_crt_idx = flag;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5F_set_store_msg_crt_idx() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_file_image
+ *
+ * Purpose: Private version of H5Fget_file_image
+ *
+ * Return: Success: Bytes copied / number of bytes needed.
+ * Failure: negative value
+ *
+ * Programmer: John Mainzer
+ * 11/15/11
+ *
+ *-------------------------------------------------------------------------
+ */
+ssize_t
+H5F_get_file_image(H5F_t *file, void *buf_ptr, size_t buf_len)
+{
+ H5FD_t *fd_ptr; /* file driver */
+ haddr_t eoa; /* End of file address */
+ ssize_t ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Check args */
+ if(!file || !file->shared || !file->shared->lf)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file_id yields invalid file pointer")
+ fd_ptr = file->shared->lf;
+ if(!fd_ptr->cls)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "fd_ptr yields invalid class pointer")
+
+ /* the address space used by the split and multi file drivers is not
+ * a good fit for this call. Since the plan is to depreciate these
+ * drivers anyway, don't bother to do a "force fit".
+ *
+ * The following clause tests for the multi file driver, and fails
+ * if the supplied file has the multi file driver as its top level
+ * file driver. However, this test will not work if there is some
+ * other file driver sitting on top of the multi file driver.
+ *
+ * I'm not sure if this is possible at present, but in all likelyhood,
+ * it will become possible in the future. On the other hand, we may
+ * remove the split/multi file drivers before then.
+ *
+ * I am leaving this solution in for now, but we should review it,
+ * and improve the solution if necessary.
+ *
+ * JRM -- 11/11/22
+ */
+ if(HDstrcmp(fd_ptr->cls->name, "multi") == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Not supported for multi file driver.")
+
+ /* While the family file driver is conceptually fully compatible
+ * with the get file image operation, it sets a file driver message
+ * in the super block that prevents the image being opened with any
+ * driver other than the family file driver. Needless to say, this
+ * rather defeats the purpose of the get file image operation.
+ *
+ * While this problem is quire solvable, the required time and
+ * resources are lacking at present. Hence, for now, we don't
+ * allow the get file image operation to be perfomed on files
+ * opened with the family file driver.
+ *
+ * Observe that the following test only looks at the top level
+ * driver, and fails if there is some other driver sitting on to
+ * of the family file driver.
+ *
+ * I don't think this can happen at present, but that may change
+ * in the future.
+ * JRM -- 12/21/11
+ */
+ if(HDstrcmp(fd_ptr->cls->name, "family") == 0)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "Not supported for family file driver.")
+
+ /* Go get the actual file size */
+ if(HADDR_UNDEF == (eoa = H5FD_get_eoa(file->shared->lf, H5FD_MEM_DEFAULT)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get file size")
+
+ /* set ret_value = to eoa -- will overwrite this if appropriate */
+ ret_value = (ssize_t)eoa;
+
+ /* test to see if a buffer was provided -- if not, we are done */
+ if(buf_ptr != NULL) {
+ size_t space_needed; /* size of file image */
+
+ /* Check for buffer too small */
+ if((haddr_t)buf_len < eoa)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "supplied buffer too small")
+
+ space_needed = (size_t)eoa;
+
+ /* read in the file image */
+ /* (Note compensation for base address addition in internal routine) */
+ if(H5FD_read(fd_ptr, H5AC_ind_dxpl_g, H5FD_MEM_DEFAULT, 0, space_needed, buf_ptr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "file image read request failed")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F_get_file_image() */
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 9f48070..53fe0d9 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -292,7 +292,13 @@ H5_DLLVAR const H5AC_class_t H5AC_SUPERBLOCK[1];
/* General routines */
H5_DLL herr_t H5F_init(void);
H5_DLL herr_t H5F__term_deprec_interface(void);
+H5F_t *H5F_new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id,
+ hid_t fapl_id, H5FD_t *lf);
+herr_t H5F_dest(H5F_t *f, hid_t dxpl_id, hbool_t flush);
H5_DLL herr_t H5F_flush(H5F_t *f, hid_t dxpl_id, hbool_t closing);
+H5_DLL htri_t H5F_is_hdf5(const char *name);
+H5_DLL herr_t H5F_get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list, hbool_t app_ref, size_t *obj_id_count_ptr);
+H5_DLL herr_t H5F_close(H5F_t *f);
/* File mount related routines */
H5_DLL herr_t H5F_close_mounts(H5F_t *f);
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index fc0a01e..fe81edc 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -598,6 +598,7 @@ H5_DLL unsigned H5F_get_nopen_objs(const H5F_t *f);
H5_DLL unsigned H5F_incr_nopen_objs(H5F_t *f);
H5_DLL unsigned H5F_decr_nopen_objs(H5F_t *f);
H5_DLL hid_t H5F_get_file_id(const H5F_t *f);
+H5_DLL ssize_t H5F_get_file_image(H5F_t *f, void *buf_ptr, size_t buf_len);
H5_DLL H5F_t *H5F_get_parent(const H5F_t *f);
H5_DLL unsigned H5F_get_nmounts(const H5F_t *f);
H5_DLL hid_t H5F_get_access_plist(H5F_t *f, hbool_t app_ref);
diff --git a/src/Makefile.am b/src/Makefile.am
index adc3032..4b55144 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -52,7 +52,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5E.c H5Edeprec.c H5Eint.c \
H5EA.c H5EAcache.c H5EAdbg.c H5EAdblkpage.c H5EAdblock.c H5EAhdr.c \
H5EAiblock.c H5EAint.c H5EAsblock.c H5EAstat.c H5EAtest.c \
- H5F.c H5Faccum.c H5Fcwfs.c \
+ H5F.c H5Fint.c H5Faccum.c H5Fcwfs.c \
H5Fdbg.c H5Fdeprec.c H5Fefc.c H5Ffake.c H5Fio.c \
H5Fmount.c H5Fmpi.c H5Fquery.c \
H5Fsfile.c H5Fsuper.c H5Fsuper_cache.c H5Ftest.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index b08463c..552fa61 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -158,19 +158,19 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \
H5Dtest.lo H5E.lo H5Edeprec.lo H5Eint.lo H5EA.lo H5EAcache.lo \
H5EAdbg.lo H5EAdblkpage.lo H5EAdblock.lo H5EAhdr.lo \
H5EAiblock.lo H5EAint.lo H5EAsblock.lo H5EAstat.lo H5EAtest.lo \
- H5F.lo H5Faccum.lo H5Fcwfs.lo H5Fdbg.lo H5Fdeprec.lo H5Fefc.lo \
- H5Ffake.lo H5Fio.lo H5Fmount.lo H5Fmpi.lo H5Fquery.lo \
- H5Fsfile.lo H5Fsuper.lo H5Fsuper_cache.lo H5Ftest.lo H5FA.lo \
- H5FAcache.lo H5FAdbg.lo H5FAdblock.lo H5FAdblkpage.lo \
- H5FAhdr.lo H5FAstat.lo H5FAtest.lo H5FD.lo H5FDcore.lo \
- H5FDdirect.lo H5FDfamily.lo H5FDint.lo H5FDlog.lo H5FDmpi.lo \
- H5FDmpio.lo H5FDmulti.lo H5FDsec2.lo H5FDspace.lo H5FDstdio.lo \
- H5FL.lo H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo H5FSsection.lo \
- H5FSstat.lo H5FStest.lo H5G.lo H5Gbtree2.lo H5Gcache.lo \
- H5Gcompact.lo H5Gdense.lo H5Gdeprec.lo H5Gent.lo H5Gint.lo \
- H5Glink.lo H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo \
- H5Groot.lo H5Gstab.lo H5Gtest.lo H5Gtraverse.lo H5HF.lo \
- H5HFbtree2.lo H5HFcache.lo H5HFdbg.lo H5HFdblock.lo \
+ H5F.lo H5Fint.lo H5Faccum.lo H5Fcwfs.lo H5Fdbg.lo H5Fdeprec.lo \
+ H5Fefc.lo H5Ffake.lo H5Fio.lo H5Fmount.lo H5Fmpi.lo \
+ H5Fquery.lo H5Fsfile.lo H5Fsuper.lo H5Fsuper_cache.lo \
+ H5Ftest.lo H5FA.lo H5FAcache.lo H5FAdbg.lo H5FAdblock.lo \
+ H5FAdblkpage.lo H5FAhdr.lo H5FAstat.lo H5FAtest.lo H5FD.lo \
+ H5FDcore.lo H5FDdirect.lo H5FDfamily.lo H5FDint.lo H5FDlog.lo \
+ H5FDmpi.lo H5FDmpio.lo H5FDmulti.lo H5FDsec2.lo H5FDspace.lo \
+ H5FDstdio.lo H5FL.lo H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo \
+ H5FSsection.lo H5FSstat.lo H5FStest.lo H5G.lo H5Gbtree2.lo \
+ H5Gcache.lo H5Gcompact.lo H5Gdense.lo H5Gdeprec.lo H5Gent.lo \
+ H5Gint.lo H5Glink.lo H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo \
+ H5Goh.lo H5Groot.lo H5Gstab.lo H5Gtest.lo H5Gtraverse.lo \
+ H5HF.lo H5HFbtree2.lo H5HFcache.lo H5HFdbg.lo H5HFdblock.lo \
H5HFdtable.lo H5HFhdr.lo H5HFhuge.lo H5HFiblock.lo H5HFiter.lo \
H5HFman.lo H5HFsection.lo H5HFspace.lo H5HFstat.lo H5HFtest.lo \
H5HFtiny.lo H5HG.lo H5HGcache.lo H5HGdbg.lo H5HGquery.lo \
@@ -758,7 +758,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5E.c H5Edeprec.c H5Eint.c \
H5EA.c H5EAcache.c H5EAdbg.c H5EAdblkpage.c H5EAdblock.c H5EAhdr.c \
H5EAiblock.c H5EAint.c H5EAsblock.c H5EAstat.c H5EAtest.c \
- H5F.c H5Faccum.c H5Fcwfs.c \
+ H5F.c H5Fint.c H5Faccum.c H5Fcwfs.c \
H5Fdbg.c H5Fdeprec.c H5Fefc.c H5Ffake.c H5Fio.c \
H5Fmount.c H5Fmpi.c H5Fquery.c \
H5Fsfile.c H5Fsuper.c H5Fsuper_cache.c H5Ftest.c \
@@ -1054,6 +1054,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fdeprec.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fefc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ffake.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fint.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fmount.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fmpi.Plo@am__quote@
diff --git a/test/testfiles/err_compat_1 b/test/testfiles/err_compat_1
index 3a85b86..d471e13 100644
--- a/test/testfiles/err_compat_1
+++ b/test/testfiles/err_compat_1
@@ -54,9 +54,6 @@ HDF5-DIAG: Error detected in HDF5 (version (number)) thread (IDs):
#001: (file name) line (number) in test_error2(): H5Dwrite shouldn't succeed
major: Error API
minor: Write failed
- #002: (file name) line (number) in H5Dwrite(): can't prepare for writing data
- major: Dataset
- minor: Write failed
- #003: (file name) line (number) in H5D__pre_write(): not a dataset
+ #002: (file name) line (number) in H5Dwrite(): not a dataset
major: Invalid arguments to routine
minor: Inappropriate type