summaryrefslogtreecommitdiffstats
path: root/src/H5Gname.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2005-12-26 05:28:18 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2005-12-26 05:28:18 (GMT)
commit83929ea716220890e41f923566aa5c89e8e735d3 (patch)
tree22193da0d9129fc7c06a57db35b2f4a57458cf50 /src/H5Gname.c
parentdb551ec15e771b4536c35cc6f3eabb7d28681510 (diff)
downloadhdf5-83929ea716220890e41f923566aa5c89e8e735d3.zip
hdf5-83929ea716220890e41f923566aa5c89e8e735d3.tar.gz
hdf5-83929ea716220890e41f923566aa5c89e8e735d3.tar.bz2
[svn-r11838] Purpose:
Bug fix Description: Retrieving an object's name could fail (in various ways) under certain circumstances (mostly having to do with mounted files). Solution: Re-write & simplify "get object name" code to fix error in a better way than adding yet another hack to the previous pile of hacks... :-) Platforms tested: FreeBSD 4.11 (sleipnir) h5committest
Diffstat (limited to 'src/H5Gname.c')
-rw-r--r--src/H5Gname.c792
1 files changed, 445 insertions, 347 deletions
diff --git a/src/H5Gname.c b/src/H5Gname.c
index 1d1a141..c4f5c95 100644
--- a/src/H5Gname.c
+++ b/src/H5Gname.c
@@ -34,18 +34,16 @@
#include "H5FLprivate.h" /* Free Lists */
#include "H5Gpkg.h" /* Groups */
#include "H5Iprivate.h" /* IDs */
-#include "H5MMprivate.h" /* Memory management */
/* Private typedefs */
/* Struct used by change name callback function */
typedef struct H5G_names_t {
- H5G_loc_t *loc;
- H5RS_str_t *src_name;
- H5G_loc_t *src_loc;
- H5RS_str_t *dst_name;
- H5G_loc_t *dst_loc;
- H5G_names_op_t op;
+ H5G_names_op_t op; /* Operation performed on file */
+ H5G_loc_t *loc; /* [src] Location affected */
+ H5F_t *top_loc_file; /* Top file in src location's mounted file hier. */
+ H5G_loc_t *dst_loc; /* Destination location */
+ H5RS_str_t *dst_name; /* Name of object relative to destination location */
} H5G_names_t;
/* Private macros */
@@ -60,6 +58,8 @@ static htri_t H5G_common_path(const H5RS_str_t *fullpath_r, const H5RS_str_t *pr
static H5RS_str_t *H5G_build_fullpath(const char *prefix, const char *name);
static H5RS_str_t *H5G_build_fullpath_refstr_refstr(const H5RS_str_t *prefix_r, const H5RS_str_t *name_r);
static H5RS_str_t *H5G_build_fullpath_refstr_str(H5RS_str_t *path_r, const char *name);
+static herr_t H5G_name_move_path(H5RS_str_t **path_r_ptr,
+ const char *full_suffix, const char *src_path, const char *dst_path);
static int H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key);
@@ -223,7 +223,7 @@ H5G_build_fullpath_refstr_str(H5RS_str_t *prefix_r, const char *name)
/*-------------------------------------------------------------------------
- * Function: H5G_name_concat_refstr_refstr
+ * Function: H5G_name_build_refstr_refstr
*
* Purpose: Build a full path from a prefix & base pair of reference counted
* strings
@@ -280,11 +280,11 @@ H5G_name_init(H5G_name_t *name, const char *path)
HDassert(name);
/* Set the initial paths for a name object */
- name->user_path_r=H5RS_create(path);
+ name->full_path_r = H5RS_create(path);
+ HDassert(name->full_path_r);
+ name->user_path_r = H5RS_create(path);
HDassert(name->user_path_r);
- name->canon_path_r=H5RS_create(path);
- HDassert(name->canon_path_r);
- name->user_path_hidden=0;
+ name->obj_hidden = 0;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5G_name_init() */
@@ -317,6 +317,13 @@ H5G_name_set(H5G_name_t *loc, H5G_name_t *obj, const char *name)
/* Free & reset the object's previous paths info (if they exist) */
H5G_name_free(obj);
+ /* Create the object's full path, if a full path exists in the location */
+ if(loc->full_path_r) {
+ /* Go build the new full path */
+ if((obj->full_path_r = H5G_build_fullpath_refstr_str(loc->full_path_r, name)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_PATH, FAIL, "can't build user path name")
+ } /* end if */
+
/* Create the object's user path, if a user path exists in the location */
if(loc->user_path_r) {
/* Go build the new user path */
@@ -324,13 +331,6 @@ H5G_name_set(H5G_name_t *loc, H5G_name_t *obj, const char *name)
HGOTO_ERROR(H5E_SYM, H5E_PATH, FAIL, "can't build user path name")
} /* end if */
- /* Create the object's canonical path, if a canonical path exists in the location */
- if(loc->canon_path_r) {
- /* Go build the new canonical path */
- if((obj->canon_path_r = H5G_build_fullpath_refstr_str(loc->canon_path_r, name)) == NULL)
- HGOTO_ERROR(H5E_SYM, H5E_PATH, FAIL, "can't build canonical path name")
- } /* end if */
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5G_name_set() */
@@ -348,48 +348,38 @@ done:
* Monday, September 12, 2005
*
* Notes: 'depth' parameter determines how much of the group entry
- * structure we want to copy. The new depths are:
- * H5G_COPY_SHALLOW - Copy all the fields from the source
+ * structure we want to copy. The depths are:
+ * H5_COPY_SHALLOW - Copy all the fields from the source
* to the destination, including the user path and
* canonical path. (Destination "takes ownership" of
* user and canonical paths)
- * H5G_COPY_CANON - Deep copy the canonical path and leave
- * the user path alone
- * H5G_COPY_DEEP - Copy all the fields from the source to
+ * H5_COPY_DEEP - Copy all the fields from the source to
* the destination, deep copying the user and canonical
* paths.
*
*-------------------------------------------------------------------------
*/
herr_t
-H5G_name_copy(H5G_name_t *dst, const H5G_name_t *src, H5G_copy_depth_t depth)
+H5G_name_copy(H5G_name_t *dst, const H5G_name_t *src, H5_copy_depth_t depth)
{
- H5RS_str_t *tmp_user_path_r = NULL; /* Temporary string pointer for entry's user path */
-
FUNC_ENTER_NOAPI_NOFUNC(H5G_name_copy)
/* Check arguments */
HDassert(src);
HDassert(dst);
- HDassert(depth == H5G_COPY_SHALLOW || depth == H5G_COPY_DEEP || depth == H5G_COPY_CANON);
-
- /* If only copying the canonical path, keep the old user path */
- if(depth == H5G_COPY_CANON) {
- tmp_user_path_r = dst->user_path_r;
- if(dst->canon_path_r)
- H5RS_decr(dst->canon_path_r);
- } /* end if */
+#if defined(H5_USING_PURIFY) || !defined(NDEBUG)
+ HDassert(dst->full_path_r == NULL);
+ HDassert(dst->user_path_r == NULL);
+#endif /* H5_USING_PURIFY */
+ HDassert(depth == H5_COPY_SHALLOW || depth == H5_COPY_DEEP);
/* Copy the top level information */
HDmemcpy(dst, src, sizeof(H5G_name_t));
/* Deep copy the names */
- if(depth == H5G_COPY_DEEP) {
+ if(depth == H5_COPY_DEEP) {
+ dst->full_path_r = H5RS_dup(src->full_path_r);
dst->user_path_r = H5RS_dup(src->user_path_r);
- dst->canon_path_r = H5RS_dup(src->canon_path_r);
- } else if(depth == H5G_COPY_CANON) {
- dst->user_path_r = tmp_user_path_r;
- dst->canon_path_r = H5RS_dup(src->canon_path_r);
} else {
/* Discarding 'const' qualifier OK - QAK */
H5G_name_reset((H5G_name_t *)src);
@@ -400,6 +390,51 @@ H5G_name_copy(H5G_name_t *dst, const H5G_name_t *src, H5G_copy_depth_t depth)
/*-------------------------------------------------------------------------
+ * Function: H5G_get_name
+ *
+ * Purpose: Gets a name of an object from its ID.
+ *
+ * Notes: Internal routine for H5Iget_name().
+
+ * Return: Success: Non-negative, length of name
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, December 13, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+ssize_t
+H5G_get_name(hid_t id, char *name/*out*/, size_t size)
+{
+ H5G_loc_t loc; /* Object location */
+ ssize_t ret_value = FAIL;
+
+ FUNC_ENTER_NOAPI_NOFUNC(H5G_get_name)
+
+ /* get object location */
+ if(H5G_loc(id, &loc) >= 0) {
+ size_t len = 0;
+
+ if(loc.path->user_path_r != NULL && loc.path->obj_hidden == 0) {
+ len = H5RS_len(loc.path->user_path_r);
+
+ if(name) {
+ HDstrncpy(name, H5RS_get_str(loc.path->user_path_r), MIN(len + 1, size));
+ if(len >= size)
+ name[size-1] = '\0';
+ } /* end if */
+ } /* end if */
+
+ /* Set return value */
+ ret_value = (ssize_t)len;
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_get_name() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5G_name_reset
*
* Purpose: Reset a group hierarchy name to an empty state
@@ -448,20 +483,124 @@ H5G_name_free(H5G_name_t *name)
/* Check args */
HDassert(name);
+ if(name->full_path_r) {
+ H5RS_decr(name->full_path_r);
+ name->full_path_r = NULL;
+ } /* end if */
if(name->user_path_r) {
H5RS_decr(name->user_path_r);
- name->user_path_r=NULL;
- } /* end if */
- if(name->canon_path_r) {
- H5RS_decr(name->canon_path_r);
- name->canon_path_r=NULL;
+ name->user_path_r = NULL;
} /* end if */
+ name->obj_hidden = 0;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5G_name_free() */
/*-------------------------------------------------------------------------
+ * Function: H5G_name_move_path
+ *
+ * Purpose: Update a user or canonical path after an object moves
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, December 13, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5G_name_move_path(H5RS_str_t **path_r_ptr, const char *full_suffix, const char *src_path,
+ const char *dst_path)
+{
+ const char *path; /* Path to update */
+ size_t path_len; /* Length of path */
+ size_t full_suffix_len; /* Length of full suffix */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_name_move_path)
+
+ /* Check arguments */
+ HDassert(path_r_ptr && *path_r_ptr);
+ HDassert(full_suffix);
+ HDassert(src_path);
+ HDassert(dst_path);
+
+ /* Get pointer to path to update */
+ path = H5RS_get_str(*path_r_ptr);
+ HDassert(path);
+
+ /* Check if path needs to be updated */
+ full_suffix_len = HDstrlen(full_suffix);
+ path_len = HDstrlen(path);
+ if(full_suffix_len < path_len) {
+ const char *dst_suffix; /* Destination suffix that changes */
+ const char *src_suffix; /* Source suffix that changes */
+ const char *path_prefix; /* Prefix for path */
+ size_t path_prefix_len; /* Length of path prefix */
+ const char *path_prefix2; /* 2nd prefix for path */
+ size_t path_prefix2_len; /* Length of 2nd path prefix */
+ const char *common_prefix; /* Common prefix for src & dst paths */
+ size_t common_prefix_len; /* Length of common prefix */
+ char *new_path; /* Pointer to new path */
+ size_t new_path_len; /* Length of new path */
+
+
+ /* Compute path prefix before full suffix*/
+ path_prefix = path;
+ path_prefix_len = path_len - full_suffix_len;
+
+ /* Determine the common prefix for src & dst paths */
+ common_prefix = src_path;
+ common_prefix_len = 0;
+ /* Find first character that is different */
+ while(*(src_path + common_prefix_len) == *(dst_path + common_prefix_len))
+ common_prefix_len++;
+ /* Back up to previous '/' */
+ while(*(common_prefix + common_prefix_len) != '/')
+ common_prefix_len--;
+ /* Include '/' */
+ common_prefix_len++;
+
+ /* Determine source suffix */
+ src_suffix = src_path + (common_prefix_len - 1);
+
+ /* Determine destination suffix */
+ dst_suffix = dst_path + (common_prefix_len - 1);
+
+ /* Compute path prefix before src suffix*/
+ path_prefix2 = path;
+ path_prefix2_len = path_prefix_len - HDstrlen(src_suffix);
+
+ /* Allocate space for the new path */
+ new_path_len = path_prefix2_len + HDstrlen(dst_suffix) + full_suffix_len;
+ if(NULL == (new_path = H5FL_BLK_MALLOC(str_buf, new_path_len + 1)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Create the new path */
+ if(path_prefix2_len > 0) {
+ HDstrncpy(new_path, path_prefix2, path_prefix2_len);
+ HDstrcpy(new_path + path_prefix2_len, dst_suffix);
+ } /* end if */
+ else
+ HDstrcpy(new_path, dst_suffix);
+ if(full_suffix_len > 0)
+ HDstrcat(new_path, full_suffix);
+
+ /* Release previous path */
+ H5RS_decr(*path_r_ptr);
+
+ /* Take ownership of the new full path */
+ *path_r_ptr = H5RS_own(new_path);
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_name_move_path() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5G_name_replace_cb
*
* Purpose: H5I_search callback function to replace group entry names
@@ -480,8 +619,8 @@ H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key)
const H5G_names_t *names = (const H5G_names_t *)key; /* Get operation's information */
H5O_loc_t *oloc; /* Object location for object that the ID refers to */
H5G_name_t *obj_path; /* Pointer to group hier. path for obj */
- H5F_t *top_ent_file; /* Top file in entry's mounted file chain */
- H5F_t *top_loc_file; /* Top file in location's mounted file chain */
+ H5F_t *top_obj_file; /* Top file in object's mounted file hier. */
+ hbool_t obj_in_child = FALSE; /* Flag to indicate that the object is in the child mount hier. */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5G_name_replace_cb)
@@ -515,268 +654,211 @@ H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key)
HDassert(oloc);
HDassert(obj_path);
+ /* Check if the object has a full path still */
+ if(!obj_path->full_path_r)
+ HGOTO_DONE(SUCCEED) /* No need to look at object, it's path is already invalid */
+
+ /* Find the top file in object's mount hier. */
+ if(oloc->file->mtab.parent) {
+ /* Check if object is in child file (for mount & unmount operations) */
+ if(names->dst_loc && oloc->file->shared == names->dst_loc->oloc->file->shared)
+ obj_in_child = TRUE;
+
+ /* Find the "top" file in the chain of mounted files */
+ top_obj_file = oloc->file->mtab.parent;
+ while(top_obj_file->mtab.parent != NULL) {
+ /* Check if object is in child mount hier. (for mount & unmount operations) */
+ if(names->dst_loc && top_obj_file->shared == names->dst_loc->oloc->file->shared)
+ obj_in_child = TRUE;
+
+ top_obj_file = top_obj_file->mtab.parent;
+ } /* end while */
+ } /* end if */
+ else
+ top_obj_file = oloc->file;
+
+ /* Check if object is in top of child mount hier. (for mount & unmount operations) */
+ if(names->dst_loc && top_obj_file->shared == names->dst_loc->oloc->file->shared)
+ obj_in_child = TRUE;
+
+ /* Check if the object is in same file mount hier. */
+ if(top_obj_file->shared != names->top_loc_file->shared)
+ HGOTO_DONE(SUCCEED) /* No need to look at object, it's path is already invalid */
+
switch(names->op) {
/*-------------------------------------------------------------------------
- * OP_MOUNT
+ * H5G_NAME_MOUNT
*-------------------------------------------------------------------------
*/
- case OP_MOUNT:
- if(obj_path->user_path_r) {
- if(oloc->file->mtab.parent && H5RS_cmp(obj_path->user_path_r, obj_path->canon_path_r)) {
- /* Find the "top" file in the chain of mounted files */
- top_ent_file = oloc->file->mtab.parent;
- while(top_ent_file->mtab.parent != NULL)
- top_ent_file = top_ent_file->mtab.parent;
- } /* end if */
- else
- top_ent_file = oloc->file;
-
- /* Check for entry being in correct file (or mounted file) */
- if(top_ent_file->shared == names->loc->oloc->file->shared) {
- /* Check if the source is along the entry's path */
- /* (But not actually the entry itself) */
- if(H5G_common_path(obj_path->user_path_r, names->src_name) &&
- H5RS_cmp(obj_path->user_path_r, names->src_name) != 0) {
- /* Hide the user path */
- (obj_path->user_path_hidden)++;
- } /* end if */
- } /* end if */
- } /* end if */
+ case H5G_NAME_MOUNT:
+ /* Check if object is in child mount hier. */
+ if(obj_in_child) {
+ const char *full_path; /* Full path of current object */
+ const char *src_path; /* Full path of source object */
+ char *new_full_path; /* New full path of object */
+ size_t new_full_len; /* Length of new full path */
+
+ /* Get pointers to paths of interest */
+ full_path = H5RS_get_str(obj_path->full_path_r);
+ src_path = H5RS_get_str(names->loc->path->full_path_r);
+
+ /* Build new full path */
+
+ /* Allocate space for the new full path */
+ new_full_len = HDstrlen(src_path) + HDstrlen(full_path);
+ if(NULL == (new_full_path = H5FL_BLK_MALLOC(str_buf, new_full_len + 1)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Create the new full path */
+ HDstrcpy(new_full_path, src_path);
+ HDstrcat(new_full_path, full_path);
+
+ /* Release previous full path */
+ H5RS_decr(obj_path->full_path_r);
+
+ /* Take ownership of the new full path */
+ obj_path->full_path_r = H5RS_own(new_full_path);
+ } /* end if */
+ /* Object must be in parent mount file hier. */
+ else {
+ /* Check if the source is along the entry's path */
+ /* (But not actually the entry itself) */
+ if(H5G_common_path(obj_path->full_path_r, names->loc->path->full_path_r) &&
+ H5RS_cmp(obj_path->full_path_r, names->loc->path->full_path_r)) {
+ /* Hide the user path */
+ (obj_path->obj_hidden)++;
+ } /* end if */
+ } /* end else */
break;
/*-------------------------------------------------------------------------
- * OP_UNMOUNT
+ * H5G_NAME_UNMOUNT
*-------------------------------------------------------------------------
*/
- case OP_UNMOUNT:
- if(obj_path->user_path_r) {
- if(oloc->file->mtab.parent) {
- /* Find the "top" file in the chain of mounted files for the entry */
- top_ent_file = oloc->file->mtab.parent;
- while(top_ent_file->mtab.parent != NULL)
- top_ent_file=top_ent_file->mtab.parent;
- } /* end if */
- else
- top_ent_file = oloc->file;
-
- if(names->loc->oloc->file->mtab.parent) {
- /* Find the "top" file in the chain of mounted files for the location */
- top_loc_file = names->loc->oloc->file->mtab.parent;
- while(top_loc_file->mtab.parent != NULL)
- top_loc_file = top_loc_file->mtab.parent;
- } /* end if */
- else
- top_loc_file = names->loc->oloc->file;
-
- /* If the ID's entry is not in the file we operated on, skip it */
- if(top_ent_file->shared == top_loc_file->shared) {
- if(obj_path->user_path_hidden) {
- if(H5G_common_path(obj_path->user_path_r, names->src_name)) {
- /* Un-hide the user path */
- (obj_path->user_path_hidden)--;
- } /* end if */
- } /* end if */
- else {
- if(H5G_common_path(obj_path->user_path_r, names->src_name)) {
- /* Free user path */
- H5RS_decr(obj_path->user_path_r);
- obj_path->user_path_r = NULL;
- } /* end if */
- } /* end else */
- } /* end if */
- } /* end if */
+ case H5G_NAME_UNMOUNT:
+ if(obj_in_child) {
+ const char *full_path; /* Full path of current object */
+ const char *full_suffix; /* Full path after source path */
+ const char *src_path; /* Full path of source object */
+ char *new_full_path; /* New full path of object */
+
+ /* Get pointers to paths of interest */
+ full_path = H5RS_get_str(obj_path->full_path_r);
+ src_path = H5RS_get_str(names->loc->path->full_path_r);
+
+ /* Construct full path suffix */
+ full_suffix = full_path + HDstrlen(src_path);
+
+ /* Build new full path */
+
+ /* Create the new full path */
+ if(NULL == (new_full_path = H5FL_BLK_MALLOC(str_buf, HDstrlen(full_suffix) + 1)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ HDstrcpy(new_full_path, full_suffix);
+
+ /* Release previous full path */
+ H5RS_decr(obj_path->full_path_r);
+
+ /* Take ownership of the new full path */
+ obj_path->full_path_r = H5RS_own(new_full_path);
+
+ /* Check if the object's user path should be invalidated */
+ if(obj_path->user_path_r && HDstrlen(new_full_path) < (size_t)H5RS_len(obj_path->user_path_r)) {
+ /* Free user path */
+ H5RS_decr(obj_path->user_path_r);
+ obj_path->user_path_r = NULL;
+ } /* end if */
+ } /* end if */
+ else {
+ /* Check if file being unmounted was hiding the object */
+ if(H5G_common_path(obj_path->full_path_r, names->loc->path->full_path_r) &&
+ H5RS_cmp(obj_path->full_path_r, names->loc->path->full_path_r)) {
+ /* Un-hide the user path */
+ (obj_path->obj_hidden)--;
+ } /* end if */
+ } /* end else */
break;
/*-------------------------------------------------------------------------
- * OP_UNLINK
+ * H5G_NAME_UNLINK
*-------------------------------------------------------------------------
*/
- case OP_UNLINK:
- /* If the ID's entry is not in the file we operated on, skip it */
- if(oloc->file->shared == names->loc->oloc->file->shared &&
- names->loc->path->canon_path_r && obj_path->canon_path_r && obj_path->user_path_r) {
- /* Check if we are referring to the same object */
- if(H5F_addr_eq(oloc->addr, names->loc->oloc->addr)) {
- /* Check if the object was opened with the same canonical path as the one being moved */
- if(H5RS_cmp(obj_path->canon_path_r, names->loc->path->canon_path_r) == 0) {
- /* Free user path */
- H5RS_decr(obj_path->user_path_r);
- obj_path->user_path_r=NULL;
- } /* end if */
- } /* end if */
- else {
- /* Check if the location being unlinked is in the canonical path for the current object */
- if(H5G_common_path(obj_path->canon_path_r, names->loc->path->canon_path_r)) {
- /* Free user path */
- H5RS_decr(obj_path->user_path_r);
- obj_path->user_path_r=NULL;
- } /* end if */
- } /* end else */
+ case H5G_NAME_UNLINK:
+ /* Check if the location being unlinked is in the path for the current object */
+ if(H5G_common_path(obj_path->full_path_r, names->loc->path->full_path_r)) {
+ /* Free paths for object */
+ H5G_name_free(obj_path);
} /* end if */
break;
/*-------------------------------------------------------------------------
- * OP_MOVE
+ * H5G_NAME_MOVE
*-------------------------------------------------------------------------
*/
- case OP_MOVE: /* H5Gmove case, check for relative names case */
- /* If the ID's entry is not in the file we operated on, skip it */
- if(oloc->file->shared == names->loc->oloc->file->shared) {
- if(obj_path->user_path_r && names->loc->path->user_path_r &&
- names->src_loc->path->user_path_r && names->dst_loc->path->user_path_r) {
- H5RS_str_t *src_path_r; /* Full user path of source name */
- H5RS_str_t *dst_path_r; /* Full user path of destination name */
- H5RS_str_t *canon_src_path_r; /* Copy of canonical part of source path */
- H5RS_str_t *canon_dst_path_r; /* Copy of canonical part of destination path */
-
- /* Sanity check */
- HDassert(names->src_name);
- HDassert(names->dst_name);
-
- /* Make certain that the source and destination names are full (not relative) paths */
- if(*(H5RS_get_str(names->src_name)) != '/') {
- /* Create reference counted string for full src path */
- if((src_path_r = H5G_build_fullpath_refstr_refstr(names->src_loc->path->user_path_r, names->src_name)) == NULL)
- HGOTO_ERROR(H5E_SYM, H5E_PATH, FAIL, "can't build source path name")
- } /* end if */
- else
- src_path_r = H5RS_dup(names->src_name);
- if(*(H5RS_get_str(names->dst_name)) != '/') {
- /* Create reference counted string for full dst path */
- if((dst_path_r = H5G_build_fullpath_refstr_refstr(names->dst_loc->path->user_path_r, names->dst_name)) == NULL)
- HGOTO_ERROR(H5E_SYM, H5E_PATH, FAIL, "can't build destination path name")
- } /* end if */
- else
- dst_path_r = H5RS_dup(names->dst_name);
-
- /* Get the canonical parts of the source and destination names */
-
- /* Check if the object being moved was accessed through a mounted file */
- if(H5RS_cmp(names->loc->path->user_path_r, names->loc->path->canon_path_r) != 0) {
- size_t non_canon_name_len; /* Length of non-canonical part of name */
-
- /* Get current string lengths */
- non_canon_name_len = H5RS_len(names->loc->path->user_path_r) - H5RS_len(names->loc->path->canon_path_r);
-
- canon_src_path_r = H5RS_create(H5RS_get_str(src_path_r) + non_canon_name_len);
- canon_dst_path_r = H5RS_create(H5RS_get_str(dst_path_r) + non_canon_name_len);
- } /* end if */
- else {
- canon_src_path_r = H5RS_dup(src_path_r);
- canon_dst_path_r = H5RS_dup(dst_path_r);
- } /* end else */
-
- /* Check if the link being changed in the file is along the canonical path for this object */
- if(H5G_common_path(obj_path->canon_path_r, canon_src_path_r)) {
- size_t user_dst_len; /* Length of destination user path */
- size_t canon_dst_len; /* Length of destination canonical path */
- const char *old_user_path; /* Pointer to previous user path */
- char *new_user_path; /* Pointer to new user path */
- char *new_canon_path; /* Pointer to new canonical path */
- const char *tail_path; /* Pointer to "tail" of path */
- size_t tail_len; /* Pointer to "tail" of path */
- char *src_canon_prefix; /* Pointer to source canonical path prefix of component which is moving */
- size_t src_canon_prefix_len;/* Length of the source canonical path prefix */
- char *dst_canon_prefix; /* Pointer to destination canonical path prefix of component which is moving */
- size_t dst_canon_prefix_len;/* Length of the destination canonical path prefix */
- char *user_prefix; /* Pointer to user path prefix of component which is moving */
- size_t user_prefix_len; /* Length of the user path prefix */
- char *src_comp; /* The source name of the component which is actually changing */
- char *dst_comp; /* The destination name of the component which is actually changing */
- const char *canon_src_path; /* pointer to canonical part of source path */
- const char *canon_dst_path; /* pointer to canonical part of destination path */
-
- /* Get the pointers to the raw strings */
- canon_src_path = H5RS_get_str(canon_src_path_r);
- canon_dst_path = H5RS_get_str(canon_dst_path_r);
-
- /* Get the source & destination components */
- src_comp = HDstrrchr(canon_src_path, '/');
- HDassert(src_comp);
- dst_comp = HDstrrchr(canon_dst_path, '/');
- HDassert(dst_comp);
-
- /* Find the canonical prefixes for the entry */
- src_canon_prefix_len = HDstrlen(canon_src_path) - HDstrlen(src_comp);
- if(NULL == (src_canon_prefix = H5MM_malloc(src_canon_prefix_len + 1)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- HDstrncpy(src_canon_prefix, canon_src_path, src_canon_prefix_len);
- src_canon_prefix[src_canon_prefix_len] = '\0';
-
- dst_canon_prefix_len = HDstrlen(canon_dst_path) - HDstrlen(dst_comp);
- if(NULL == (dst_canon_prefix = H5MM_malloc(dst_canon_prefix_len + 1)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- HDstrncpy(dst_canon_prefix, canon_dst_path, dst_canon_prefix_len);
- dst_canon_prefix[dst_canon_prefix_len] = '\0';
-
- /* Hold this for later use */
- old_user_path = H5RS_get_str(obj_path->user_path_r);
-
- /* Find the user prefix for the entry */
- user_prefix_len = HDstrlen(old_user_path) - H5RS_len(obj_path->canon_path_r);
- if(NULL == (user_prefix = H5MM_malloc(user_prefix_len + 1)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- HDstrncpy(user_prefix, old_user_path, user_prefix_len);
- user_prefix[user_prefix_len] = '\0';
-
- /* Set the tail path info */
- tail_path = old_user_path+user_prefix_len + src_canon_prefix_len + HDstrlen(src_comp);
- tail_len = HDstrlen(tail_path);
-
- /* Get the length of the destination paths */
- user_dst_len = user_prefix_len + dst_canon_prefix_len + HDstrlen(dst_comp) + tail_len;
- canon_dst_len = dst_canon_prefix_len + HDstrlen(dst_comp) + tail_len;
-
- /* Allocate space for the new user path */
- if(NULL == (new_user_path = H5FL_BLK_MALLOC(str_buf, user_dst_len + 1)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
-
- /* Allocate space for the new canonical path */
- if(NULL == (new_canon_path = H5FL_BLK_MALLOC(str_buf, canon_dst_len + 1)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
-
- /* Create the new names */
- HDstrcpy(new_user_path, user_prefix);
- HDstrcat(new_user_path, dst_canon_prefix);
- HDstrcat(new_user_path, dst_comp);
- HDstrcat(new_user_path, tail_path);
- HDstrcpy(new_canon_path, dst_canon_prefix);
- HDstrcat(new_canon_path, dst_comp);
- HDstrcat(new_canon_path, tail_path);
-
- /* Release the old user & canonical paths */
- H5RS_decr(obj_path->user_path_r);
- H5RS_decr(obj_path->canon_path_r);
-
- /* Take ownership of the new user & canonical paths */
- obj_path->user_path_r = H5RS_own(new_user_path);
- obj_path->canon_path_r = H5RS_own(new_canon_path);
-
- /* Free the extra paths allocated */
- H5MM_xfree(src_canon_prefix);
- H5MM_xfree(dst_canon_prefix);
- H5MM_xfree(user_prefix);
- } /* end if */
-
-
- /* Free the extra paths allocated */
- H5RS_decr(src_path_r);
- H5RS_decr(dst_path_r);
- H5RS_decr(canon_src_path_r);
- H5RS_decr(canon_dst_path_r);
- } /* end if */
- else {
- /* Release the old user path */
- if(obj_path->user_path_r) {
- H5RS_decr(obj_path->user_path_r);
- obj_path->user_path_r = NULL;
- } /* end if */
- } /* end else */
+ case H5G_NAME_MOVE: /* H5Gmove case, check for relative names case */
+ /* Check if the src object moved is in the current object's path */
+ if(H5G_common_path(obj_path->full_path_r, names->loc->path->full_path_r)) {
+ const char *full_path; /* Full path of current object */
+ const char *full_suffix; /* Suffix of full path, after src_path */
+ char *new_full_path; /* New full path of object */
+ size_t new_full_len; /* Length of new full path */
+ H5RS_str_t *src_path_r; /* Full path of source name */
+ const char *src_path; /* Full path of source object */
+ H5RS_str_t *dst_path_r; /* Full path of destination name */
+ const char *dst_path; /* Full path of destination object */
+
+ /* Sanity check */
+ HDassert(*(H5RS_get_str(names->loc->path->full_path_r)) == '/');
+ HDassert(names->dst_name);
+
+ /* Make certain that the source and destination names are full (not relative) paths */
+ src_path_r = H5RS_dup(names->loc->path->full_path_r);
+ if(*(H5RS_get_str(names->dst_name)) != '/') {
+ /* Create reference counted string for full dst path */
+ if((dst_path_r = H5G_build_fullpath_refstr_refstr(names->dst_loc->path->full_path_r, names->dst_name)) == NULL)
+ HGOTO_ERROR(H5E_SYM, H5E_PATH, FAIL, "can't build destination path name")
+ } /* end if */
+ else
+ dst_path_r = H5RS_dup(names->dst_name);
+
+ /* Get pointers to paths of interest */
+ full_path = H5RS_get_str(obj_path->full_path_r);
+ src_path = H5RS_get_str(src_path_r);
+ dst_path = H5RS_get_str(dst_path_r);
+
+ /* Get pointer to "full suffix" */
+ full_suffix = full_path + HDstrlen(src_path);
+
+ /* Update the user path, if one exists */
+ if(obj_path->user_path_r)
+ if(H5G_name_move_path(&(obj_path->user_path_r), full_suffix, src_path, dst_path) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_PATH, FAIL, "can't build user path name")
+
+ /* Build new full path */
+
+ /* Allocate space for the new full path */
+ new_full_len = HDstrlen(dst_path) + HDstrlen(full_suffix);
+ if(NULL == (new_full_path = H5FL_BLK_MALLOC(str_buf, new_full_len + 1)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Create the new full path */
+ HDstrcpy(new_full_path, dst_path);
+ HDstrcat(new_full_path, full_suffix);
+
+ /* Release previous full path */
+ H5RS_decr(obj_path->full_path_r);
+
+ /* Take ownership of the new full path */
+ obj_path->full_path_r = H5RS_own(new_full_path);
+
+ /* Release source & destination full paths */
+ H5RS_decr(src_path_r);
+ H5RS_decr(dst_path_r);
} /* end if */
break;
default:
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid call")
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid operation")
} /* end switch */
done:
@@ -789,10 +871,9 @@ done:
*
* Purpose: Search the list of open IDs and replace names according to a
* particular operation. The operation occured on the LOC
- * entry, which had SRC_NAME previously. The new name (if there
- * is one) is DST_NAME. Additional entry location information
- * (currently only needed for the 'move' operation) is passed
- * in SRC_LOC and DST_LOC.
+ * entry. The new name (if there is one) is DST_NAME.
+ * Additional entry location information (currently only needed
+ * for the 'move' operation) is passed in DST_LOC.
*
* Return: Success: 0, Failure: -1
*
@@ -804,75 +885,92 @@ done:
*/
herr_t
H5G_name_replace(H5G_obj_t type, H5G_loc_t *loc,
- H5RS_str_t *src_name, H5G_loc_t *src_loc,
H5RS_str_t *dst_name, H5G_loc_t *dst_loc, H5G_names_op_t op)
{
- H5G_names_t names; /* Structure to hold operation information for callback */
- unsigned search_group = 0; /* Flag to indicate that groups are to be searched */
- unsigned search_dataset = 0; /* Flag to indicate that datasets are to be searched */
- unsigned search_datatype = 0; /* Flag to indicate that datatypes are to be searched */
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI(H5G_name_replace, FAIL)
- /* Set up common information for callback */
- names.src_name = src_name;
- names.dst_name = dst_name;
- names.loc = loc;
- names.src_loc = src_loc;
- names.dst_loc = dst_loc;
- names.op = op;
-
- /* Determine which types of IDs need to be operated on */
- switch(type) {
- /* Object is a group */
- case H5G_GROUP:
- /* Search and replace names through group IDs */
- search_group = 1;
- break;
-
- /* Object is a dataset */
- case H5G_DATASET:
- /* Search and replace names through dataset IDs */
- search_dataset = 1;
- break;
-
- /* Object is a named datatype */
- case H5G_TYPE:
- /* Search and replace names through datatype IDs */
- search_datatype = 1;
- break;
-
- case H5G_UNKNOWN: /* We pass H5G_UNKNOWN as object type when we need to search all IDs */
- case H5G_LINK: /* Symbolic links might resolve to any object, so we need to search all IDs */
- /* Check if we will need to search groups */
- if(H5I_nmembers(H5I_GROUP) > 0)
+ /* Check if the object we are manipulating has a path */
+ if(loc->path->full_path_r) {
+ unsigned search_group = 0; /* Flag to indicate that groups are to be searched */
+ unsigned search_dataset = 0; /* Flag to indicate that datasets are to be searched */
+ unsigned search_datatype = 0; /* Flag to indicate that datatypes are to be searched */
+
+ /* Determine which types of IDs need to be operated on */
+ switch(type) {
+ /* Object is a group */
+ case H5G_GROUP:
+ /* Search and replace names through group IDs */
search_group = 1;
+ break;
- /* Check if we will need to search datasets */
- if(H5I_nmembers(H5I_DATASET) > 0)
+ /* Object is a dataset */
+ case H5G_DATASET:
+ /* Search and replace names through dataset IDs */
search_dataset = 1;
+ break;
- /* Check if we will need to search datatypes */
- if(H5I_nmembers(H5I_DATATYPE) > 0)
+ /* Object is a named datatype */
+ case H5G_TYPE:
+ /* Search and replace names through datatype IDs */
search_datatype = 1;
- break;
-
- default:
- HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not valid object type");
- } /* end switch */
-
- /* Search through group IDs */
- if(search_group)
- H5I_search(H5I_GROUP, H5G_name_replace_cb, &names);
-
- /* Search through dataset IDs */
- if(search_dataset)
- H5I_search(H5I_DATASET, H5G_name_replace_cb, &names);
-
- /* Search through datatype IDs */
- if(search_datatype)
- H5I_search(H5I_DATATYPE, H5G_name_replace_cb, &names);
+ break;
+
+ case H5G_UNKNOWN: /* We pass H5G_UNKNOWN as object type when we need to search all IDs */
+ case H5G_LINK: /* Symbolic links might resolve to any object, so we need to search all IDs */
+ /* Check if we will need to search groups */
+ if(H5I_nmembers(H5I_GROUP) > 0)
+ search_group = 1;
+
+ /* Check if we will need to search datasets */
+ if(H5I_nmembers(H5I_DATASET) > 0)
+ search_dataset = 1;
+
+ /* Check if we will need to search datatypes */
+ if(H5I_nmembers(H5I_DATATYPE) > 0)
+ search_datatype = 1;
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, FAIL, "not valid object type")
+ } /* end switch */
+
+ /* Check if we need to operate on the objects affected */
+ if(search_group || search_dataset || search_datatype) {
+ H5G_names_t names; /* Structure to hold operation information for callback */
+ H5F_t *top_loc_file; /* Top file in src location's mounted file hier. */
+
+ /* Find top file in src location's mount hierarchy */
+ if(loc->oloc->file->mtab.parent) {
+ /* Find the "top" file in the chain of mounted files for the location */
+ top_loc_file = loc->oloc->file->mtab.parent;
+ while(top_loc_file->mtab.parent != NULL)
+ top_loc_file = top_loc_file->mtab.parent;
+ } /* end if */
+ else
+ top_loc_file = loc->oloc->file;
+
+ /* Set up common information for callback */
+ names.loc = loc;
+ names.top_loc_file = top_loc_file;
+ names.dst_loc = dst_loc;
+ names.dst_name = dst_name;
+ names.op = op;
+
+ /* Search through group IDs */
+ if(search_group)
+ H5I_search(H5I_GROUP, H5G_name_replace_cb, &names);
+
+ /* Search through dataset IDs */
+ if(search_dataset)
+ H5I_search(H5I_DATASET, H5G_name_replace_cb, &names);
+
+ /* Search through datatype IDs */
+ if(search_datatype)
+ H5I_search(H5I_DATATYPE, H5G_name_replace_cb, &names);
+ } /* end if */
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)