diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2005-12-26 05:28:18 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2005-12-26 05:28:18 (GMT) |
commit | 83929ea716220890e41f923566aa5c89e8e735d3 (patch) | |
tree | 22193da0d9129fc7c06a57db35b2f4a57458cf50 /src/H5Gname.c | |
parent | db551ec15e771b4536c35cc6f3eabb7d28681510 (diff) | |
download | hdf5-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.c | 792 |
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) |