summaryrefslogtreecommitdiffstats
path: root/src/H5Gname.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Gname.c')
-rw-r--r--src/H5Gname.c880
1 files changed, 880 insertions, 0 deletions
diff --git a/src/H5Gname.c b/src/H5Gname.c
new file mode 100644
index 0000000..1d1a141
--- /dev/null
+++ b/src/H5Gname.c
@@ -0,0 +1,880 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5Gname.c
+ * Sep 12 2005
+ * Quincey Koziol <koziol@ncsa.uiuc.edu>
+ *
+ * Purpose: Functions for handling group hierarchy paths.
+ *
+ *-------------------------------------------------------------------------
+ */
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5G_PACKAGE /*suppress error about including H5Gpkg */
+
+
+/* Packages needed by this file... */
+#include "H5private.h" /* Generic Functions */
+#include "H5Dprivate.h" /* Datasets */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#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_t;
+
+/* Private macros */
+
+/* Local variables */
+
+/* Declare extern the PQ free list for the wrapped strings */
+H5FL_BLK_EXTERN(str_buf);
+
+/* PRIVATE PROTOTYPES */
+static htri_t H5G_common_path(const H5RS_str_t *fullpath_r, const H5RS_str_t *prefix_r);
+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 int H5G_name_replace_cb(void *obj_ptr, hid_t obj_id, void *key);
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_common_path
+ *
+ * Purpose: Determine if one path is a valid prefix of another path
+ *
+ * Return: TRUE for valid prefix, FALSE for not a valid prefix, FAIL
+ * on error
+ *
+ * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu
+ *
+ * Date: September 24, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5G_common_path(const H5RS_str_t *fullpath_r, const H5RS_str_t *prefix_r)
+{
+ const char *fullpath; /* Pointer to actual fullpath string */
+ const char *prefix; /* Pointer to actual prefix string */
+ size_t nchars1,nchars2; /* Number of characters in components */
+ htri_t ret_value=FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_common_path)
+
+ /* Get component of each name */
+ fullpath=H5RS_get_str(fullpath_r);
+ assert(fullpath);
+ fullpath=H5G_component(fullpath,&nchars1);
+ assert(fullpath);
+ prefix=H5RS_get_str(prefix_r);
+ assert(prefix);
+ prefix=H5G_component(prefix,&nchars2);
+ assert(prefix);
+
+ /* Check if we have a real string for each component */
+ while(*fullpath && *prefix) {
+ /* Check that the components we found are the same length */
+ if(nchars1==nchars2) {
+ /* Check that the two components are equal */
+ if(HDstrncmp(fullpath,prefix,nchars1)==0) {
+ /* Advance the pointers in the names */
+ fullpath+=nchars1;
+ prefix+=nchars2;
+
+ /* Get next component of each name */
+ fullpath=H5G_component(fullpath,&nchars1);
+ assert(fullpath);
+ prefix=H5G_component(prefix,&nchars2);
+ assert(prefix);
+ } /* end if */
+ else
+ HGOTO_DONE(FALSE)
+ } /* end if */
+ else
+ HGOTO_DONE(FALSE)
+ } /* end while */
+
+ /* If we reached the end of the prefix path to check, it must be a valid prefix */
+ if(*prefix=='\0')
+ ret_value=TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_common_path() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_build_fullpath
+ *
+ * Purpose: Build a full path from a prefix & base pair of strings
+ *
+ * Return: Pointer to reference counted string on success, NULL on error
+ *
+ * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu
+ *
+ * Date: August 19, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5RS_str_t *
+H5G_build_fullpath(const char *prefix, const char *name)
+{
+ char *full_path; /* Full user path built */
+ size_t path_len; /* Length of the path */
+ unsigned need_sep; /* Flag to indicate if separator is needed */
+ H5RS_str_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_build_fullpath)
+
+ /* Sanity check */
+ HDassert(prefix);
+ HDassert(name);
+
+ /* Get the length of the prefix */
+ path_len = HDstrlen(prefix);
+
+ /* Determine if there is a trailing separator in the name */
+ if(prefix[path_len - 1] == '/')
+ need_sep = 0;
+ else
+ need_sep = 1;
+
+ /* Add in the length needed for the '/' separator and the relative path */
+ path_len += HDstrlen(name) + need_sep;
+
+ /* Allocate space for the path */
+ if(NULL == (full_path = H5FL_BLK_MALLOC(str_buf, path_len + 1)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Build full path */
+ HDstrcpy(full_path, prefix);
+ if(need_sep)
+ HDstrcat(full_path, "/");
+ HDstrcat(full_path, name);
+
+ /* Create reference counted string for path */
+ if((ret_value = H5RS_own(full_path)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_build_fullpath() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_build_fullpath_refstr_str
+ *
+ * Purpose: Append an object path to an existing ref-counted path
+ *
+ * Return: Success: Non-NULL, combined path
+ * Failure: NULL
+ *
+ * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu
+ * Tuesday, October 11, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5RS_str_t *
+H5G_build_fullpath_refstr_str(H5RS_str_t *prefix_r, const char *name)
+{
+ const char *prefix; /* Pointer to raw string for path */
+ H5RS_str_t *ret_value;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_build_fullpath_refstr_str)
+
+ HDassert(prefix_r);
+ HDassert(name);
+
+ /* Get the raw string for the user path */
+ prefix = H5RS_get_str(prefix_r);
+ HDassert(prefix);
+
+ /* Create reference counted string for path */
+ ret_value = H5G_build_fullpath(prefix, name);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_build_fullpath_refstr_str() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_name_concat_refstr_refstr
+ *
+ * Purpose: Build a full path from a prefix & base pair of reference counted
+ * strings
+ *
+ * Return: Pointer to reference counted string on success, NULL on error
+ *
+ * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu
+ *
+ * Date: August 19, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5RS_str_t *
+H5G_build_fullpath_refstr_refstr(const H5RS_str_t *prefix_r, const H5RS_str_t *name_r)
+{
+ const char *prefix; /* Pointer to raw string of prefix */
+ const char *name; /* Pointer to raw string of name */
+ H5RS_str_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_build_fullpath_refstr_refstr)
+
+ /* Get the pointer to the prefix */
+ prefix = H5RS_get_str(prefix_r);
+
+ /* Get the pointer to the raw src user path */
+ name = H5RS_get_str(name_r);
+
+ /* Create reference counted string for path */
+ ret_value = H5G_build_fullpath(prefix, name);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_build_fullpath_refstr_refstr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_name_init
+ *
+ * Purpose: Set the initial path for a group hierarchy name
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, September 12, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_name_init(H5G_name_t *name, const char *path)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5G_name_init)
+
+ /* Check arguments */
+ HDassert(name);
+
+ /* Set the initial paths for a name object */
+ 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;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5G_name_init() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_name_set
+ *
+ * Purpose: Set the name of a symbol entry OBJ, located at LOC
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ * Thursday, August 22, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_name_set(H5G_name_t *loc, H5G_name_t *obj, const char *name)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5G_name_set, FAIL)
+
+ HDassert(loc);
+ HDassert(obj);
+ HDassert(name);
+
+ /* Free & reset the object's previous paths info (if they exist) */
+ H5G_name_free(obj);
+
+ /* 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 */
+ if((obj->user_path_r = H5G_build_fullpath_refstr_str(loc->user_path_r, name)) == NULL)
+ 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() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_name_copy
+ *
+ * Purpose: Do a copy of group hier. names
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * 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
+ * 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
+ * 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)
+{
+ 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 */
+
+ /* Copy the top level information */
+ HDmemcpy(dst, src, sizeof(H5G_name_t));
+
+ /* Deep copy the names */
+ if(depth == H5G_COPY_DEEP) {
+ 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);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5G_name_copy() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_name_reset
+ *
+ * Purpose: Reset a group hierarchy name to an empty state
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, September 12, 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_name_reset(H5G_name_t *name)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5G_name_reset)
+
+ /* Check arguments */
+ HDassert(name);
+
+ /* Clear the group hier. name to an empty state */
+ HDmemset(name, 0, sizeof(H5G_name_t));
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5G_name_reset() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_name_free
+ *
+ * Purpose: Free the 'ID to name' buffers.
+ *
+ * Return: Success
+ *
+ * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ *
+ * Date: August 22, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_name_free(H5G_name_t *name)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5G_name_free)
+
+ /* Check args */
+ HDassert(name);
+
+ 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;
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5G_name_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_name_replace_cb
+ *
+ * Purpose: H5I_search callback function to replace group entry names
+ *
+ * Return: Success: 0, Failure: -1
+ *
+ * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ *
+ * Date: June 5, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+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 */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_name_replace_cb)
+
+ HDassert(obj_ptr);
+
+ /* Get the symbol table entry */
+ switch(H5I_get_type(obj_id)) {
+ case H5I_GROUP:
+ oloc = H5G_oloc((H5G_t *)obj_ptr);
+ obj_path = H5G_nameof((H5G_t *)obj_ptr);
+ break;
+
+ case H5I_DATASET:
+ oloc = H5D_oloc((H5D_t *)obj_ptr);
+ obj_path = H5D_nameof((H5D_t *)obj_ptr);
+ break;
+
+ case H5I_DATATYPE:
+ /* Avoid non-named datatypes */
+ if(!H5T_is_named((H5T_t *)obj_ptr))
+ HGOTO_DONE(SUCCEED) /* Do not exit search over IDs */
+
+ oloc = H5T_oloc((H5T_t *)obj_ptr);
+ obj_path = H5T_nameof((H5T_t *)obj_ptr);
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unknown data object")
+ } /* end switch */
+ HDassert(oloc);
+ HDassert(obj_path);
+
+ switch(names->op) {
+ /*-------------------------------------------------------------------------
+ * OP_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 */
+ break;
+
+ /*-------------------------------------------------------------------------
+ * OP_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 */
+ break;
+
+ /*-------------------------------------------------------------------------
+ * OP_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 */
+ } /* end if */
+ break;
+
+ /*-------------------------------------------------------------------------
+ * OP_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 */
+ } /* end if */
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid call")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5G_name_replace_cb() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_name_replace
+ *
+ * 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.
+ *
+ * Return: Success: 0, Failure: -1
+ *
+ * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ *
+ * Date: June 11, 2002
+ *
+ *-------------------------------------------------------------------------
+ */
+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)
+ 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_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);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_name_replace() */
+