diff options
Diffstat (limited to 'src/H5G.c')
-rw-r--r-- | src/H5G.c | 560 |
1 files changed, 306 insertions, 254 deletions
@@ -110,9 +110,11 @@ static size_t H5G_comp_alloc_g = 0; /*sizeof component buffer */ /* Struct only used by change name callback function */ typedef struct H5G_names_t { + H5G_entry_t *loc; const char *src_name; + H5G_entry_t *src_loc; const char *dst_name; - H5G_entry_t *loc; + H5G_entry_t *dst_loc; H5G_names_op_t op; } H5G_names_t; @@ -121,6 +123,8 @@ H5FL_DEFINE(H5G_t); /* Private prototypes */ static herr_t H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key); +static herr_t H5G_traverse_slink(H5G_entry_t *grp_ent/*in,out*/, + H5G_entry_t *obj_ent/*in,out*/, int *nlinks/*in,out*/); /*------------------------------------------------------------------------- @@ -1050,7 +1054,7 @@ H5G_basename(const char *name, size_t *size_p) static herr_t H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, H5G_entry_t *grp_ent/*out*/, H5G_entry_t *obj_ent/*out*/, - unsigned target, int *nlinks) + unsigned target, int *nlinks/*out*/) { H5G_entry_t _grp_ent; /*entry for current group */ H5G_entry_t _obj_ent; /*entry found */ @@ -1064,10 +1068,19 @@ H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, FUNC_ENTER_NOINIT(H5G_namei); - if (rest) *rest = name; - if (!grp_ent) grp_ent = &_grp_ent; - if (!obj_ent) obj_ent = &_obj_ent; - if (!nlinks) nlinks = &_nlinks; + /* Set up "out" parameters */ + if (rest) + *rest = name; + if (!grp_ent) { + HDmemset(&_grp_ent,0,sizeof(H5G_entry_t)); + grp_ent = &_grp_ent; + } /* end if */ + if (!obj_ent) { + HDmemset(&_obj_ent,0,sizeof(H5G_entry_t)); + obj_ent = &_obj_ent; + } /* end if */ + if (!nlinks) + nlinks = &_nlinks; /* Check args */ if (!name || !*name) @@ -1091,7 +1104,7 @@ H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, } /* end if */ /* Deep copy of the symbol table entry */ - if (H5G_ent_copy( loc_ent, obj_ent )<0) + if (H5G_ent_copy(obj_ent, loc_ent,H5G_COPY_DEEP)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to copy entry"); HDmemset(grp_ent, 0, sizeof(H5G_entry_t)); @@ -1136,7 +1149,7 @@ H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, H5G_free_ent_name(grp_ent); /* Transfer "ownership" of the entry's information to the group entry */ - *grp_ent = *obj_ent; + H5G_ent_copy(grp_ent,obj_ent,H5G_COPY_SHALLOW); HDmemset(obj_ent, 0, sizeof(H5G_entry_t)); obj_ent->header = HADDR_UNDEF; @@ -1156,9 +1169,8 @@ H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, * is the last component of the name and the H5G_TARGET_SLINK bit of * TARGET is set then we don't follow it. */ - if (H5G_CACHED_SLINK==obj_ent->type && - (0==(target & H5G_TARGET_SLINK) || - ((s=H5G_component(name+nchars, NULL)) && *s))) { + if(H5G_CACHED_SLINK==obj_ent->type && (0==(target & H5G_TARGET_SLINK) || + ((s=H5G_component(name+nchars, NULL)) && *s))) { if ((*nlinks)-- <= 0) HGOTO_ERROR (H5E_SYM, H5E_SLINK, FAIL, "too many symbolic links"); if (H5G_traverse_slink (grp_ent, obj_ent, nlinks)<0) @@ -1171,14 +1183,12 @@ H5G_namei(H5G_entry_t *loc_ent, const char *name, const char **rest/*out*/, * component of the name. */ if (0==(target & H5G_TARGET_MOUNT) || - ((s=H5G_component(name+nchars, NULL)) && *s)) { + ((s=H5G_component(name+nchars, NULL)) && *s)) { H5F_mountpoint(obj_ent/*in,out*/); } /* next component */ name += nchars; - - } /* end while */ /* Update the "rest of name" pointer */ @@ -1220,7 +1230,7 @@ done: * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5G_traverse_slink (H5G_entry_t *grp_ent/*in,out*/, H5G_entry_t *obj_ent/*in,out*/, int *nlinks/*in,out*/) @@ -1229,11 +1239,14 @@ H5G_traverse_slink (H5G_entry_t *grp_ent/*in,out*/, const char *clv = NULL; /*cached link value */ char *linkval = NULL; /*the copied link value */ H5G_entry_t tmp_grp_ent; /* Temporary copy of group entry */ - char *tmp_name, *tmp_old_name; /* Temporary pointer to object's name & "old name" */ + char *tmp_user_path=NULL, *tmp_canon_path=NULL; /* Temporary pointer to object's user path & canonical path */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_traverse_slink, FAIL); + /* Portably initialize the temporary group entry */ + HDmemset(&tmp_grp_ent,0,sizeof(H5G_entry_t)); + /* Get the link value */ if (NULL==H5O_read (grp_ent, H5O_STAB, 0, &stab_mesg)) HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address"); @@ -1242,14 +1255,17 @@ H5G_traverse_slink (H5G_entry_t *grp_ent/*in,out*/, HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read symbolic link value"); linkval = H5MM_xstrdup (clv); - /* Copy the entry's name (& old_name) to restore later, then free the names for the entries */ - tmp_name= H5MM_xstrdup(obj_ent->name); - tmp_old_name= H5MM_xstrdup(obj_ent->old_name); - H5G_free_ent_name(obj_ent); + /* Hold the entry's name (& old_name) to restore later */ + tmp_user_path=obj_ent->user_path; + obj_ent->user_path=NULL; + tmp_canon_path=obj_ent->canon_path; + obj_ent->canon_path=NULL; + + /* Free the names for the group entry */ H5G_free_ent_name(grp_ent); /* Clone the group entry, so we can track the names properly */ - H5G_ent_copy(grp_ent,&tmp_grp_ent); + H5G_ent_copy(&tmp_grp_ent,grp_ent,H5G_COPY_DEEP); /* Traverse the link */ if (H5G_namei (&tmp_grp_ent, linkval, NULL, grp_ent, obj_ent, H5G_TARGET_NORMAL, nlinks)) @@ -1259,15 +1275,17 @@ H5G_traverse_slink (H5G_entry_t *grp_ent/*in,out*/, H5G_free_ent_name(obj_ent); /* Restore previous name for object */ - obj_ent->name = tmp_name; - obj_ent->old_name = tmp_old_name; + obj_ent->user_path = tmp_user_path; + tmp_user_path=NULL; + obj_ent->canon_path = tmp_canon_path; + tmp_canon_path=NULL; done: /* Error cleanup */ - if (ret_value == FAIL ) { - H5MM_xfree(tmp_name); - H5MM_xfree(tmp_old_name); - } /* end if */ + if(tmp_user_path) + H5MM_xfree(tmp_user_path); + if(tmp_canon_path) + H5MM_xfree(tmp_canon_path); /* Release cloned copy of group entry */ H5G_free_ent_name(&tmp_grp_ent); @@ -1337,10 +1355,12 @@ H5G_mkroot (H5F_t *f, H5G_entry_t *ent) H5O_reset (H5O_STAB, &stab); } - /* Create the name for the root group's entry */ - ent->name = HDstrdup("/"); - assert(ent->name); - ent->old_name = NULL; + /* Create the path names for the root group's entry */ + ent->user_path=HDstrdup("/"); + assert(ent->user_path); + ent->canon_path=HDstrdup("/"); + assert(ent->canon_path); + ent->user_path_hidden=0; /* * Create the group pointer. Also decrement the open object count so we @@ -1580,7 +1600,7 @@ H5G_open_oid(H5G_entry_t *ent) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); /* Copy over (take ownership) of the group entry object */ - HDmemcpy(&(grp->ent),ent,sizeof(H5G_entry_t)); + H5G_ent_copy(&(grp->ent),ent,H5G_COPY_SHALLOW); /* Grab the object header */ if (H5O_open(&(grp->ent)) < 0) @@ -2460,7 +2480,7 @@ H5G_unlink(H5G_entry_t *loc, const char *name) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to unlink name from symbol table"); /* Search the open IDs and replace names for unlinked object */ - if (H5G_replace_name(statbuf.type, loc, name, NULL, OP_UNLINK )<0) + if (H5G_replace_name(statbuf.type, &obj_ent, name, NULL, NULL, NULL, OP_UNLINK )<0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name"); done: @@ -2499,7 +2519,8 @@ H5G_move(H5G_entry_t *src_loc, const char *src_name, H5G_entry_t *dst_loc, H5G_stat_t sb; char *linkval=NULL; size_t lv_size=32; - herr_t ret_value=SUCCEED; /* Return value */ + H5G_entry_t obj_ent; /* Object entry for object being moved */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5G_move, FAIL); assert(src_loc); @@ -2539,8 +2560,11 @@ H5G_move(H5G_entry_t *src_loc, const char *src_name, H5G_entry_t *dst_loc, * This has to be done here because H5G_link and H5G_unlink have * internal object entries, and do not modify the entries list */ - if (H5G_replace_name(sb.type, src_loc, src_name, dst_name, OP_MOVE )<0) + if (H5G_namei (src_loc, src_name, NULL, NULL, &obj_ent, H5G_TARGET_NORMAL|H5G_TARGET_SLINK, NULL)) + HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "unable to follow symbolic link"); + if (H5G_replace_name(sb.type, &obj_ent, src_name, src_loc, dst_name, dst_loc, OP_MOVE )<0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name "); + H5G_free_ent_name(&obj_ent); /* Remove the old name */ if (H5G_unlink(src_loc, src_name)<0) @@ -2678,10 +2702,10 @@ H5G_free_ent_name(H5G_entry_t *ent) /* Check args */ assert(ent); - if ( ent->name ) - ent->name = H5MM_xfree(ent->name); - if ( ent->old_name ) - ent->old_name = H5MM_xfree(ent->old_name); + if(ent->user_path) + ent->user_path = H5MM_xfree(ent->user_path); + if(ent->canon_path) + ent->canon_path = H5MM_xfree(ent->canon_path); done: FUNC_LEAVE(ret_value); @@ -2689,69 +2713,14 @@ done: /*------------------------------------------------------------------------- - * Function: H5G_insert_name - * - * Purpose: Insert a name into the symbol entry OBJ, located at LOC - * - * Return: Success: 0, Failure: -1 - * - * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu - * - * Date: August 22, 2002 - * - * Comments: The allocated memory (H5MM_malloc) is freed in H5O_close - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5G_insert_name(H5G_entry_t *loc, H5G_entry_t *obj, const char *name) -{ - size_t loc_name_len, name_len; /* Length of location's name and name to append */ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI(H5G_insert_name, FAIL); - - /* Only attempt to build a new name if the location's name exists */ - if(loc->name) { - loc_name_len = HDstrlen(loc->name); - name_len = HDstrlen(name); - assert(name_len>0 && loc_name_len>0); - - /* Free the object's name, if it exists */ - if(obj->name) - obj->name=H5MM_xfree(obj->name); - - /* The location's name already has a '/' separator */ - if ('/'==loc->name[loc_name_len-1]) { - if (NULL==(obj->name = H5MM_malloc (loc_name_len+name_len+1))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - HDstrcpy(obj->name, loc->name); - HDstrcat(obj->name, name); - } /* end if */ - /* The location's name needs a separator */ - else { - if (NULL==(obj->name = H5MM_malloc (loc_name_len+1+name_len+1))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - HDstrcpy(obj->name, loc->name); - HDstrcat(obj->name, "/"); - HDstrcat(obj->name, name); - } /* end else */ - } /* end if */ - -done: - FUNC_LEAVE(ret_value); -} - - -/*------------------------------------------------------------------------- * Function: H5G_replace_name * * 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. + * 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 * @@ -2766,8 +2735,9 @@ done: *------------------------------------------------------------------------- */ herr_t -H5G_replace_name( int type, H5G_entry_t *loc, const char *src_name, - const char *dst_name, H5G_names_op_t op ) +H5G_replace_name( int type, H5G_entry_t *loc, + const char *src_name, H5G_entry_t *src_loc, + const char *dst_name, H5G_entry_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 */ @@ -2781,6 +2751,8 @@ H5G_replace_name( int type, H5G_entry_t *loc, const char *src_name, 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 */ @@ -2840,47 +2812,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5G_rest - * - * Purpose: Get the last component of the name - * - * Return: Pointer to the last component of a name, if found, otherwise NULL - * - * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu - * - * Date: July 5, 2002 - * - * Comments: - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static const char * -H5G_rest(const char *name) -{ - size_t nchars; /* Number of characters in component */ - const char *rest=NULL; /* Pointer to last component, if found */ - - FUNC_ENTER_NOINIT(H5G_rest); - - /* traverse the name to find the last component */ - while ((name = H5G_component(name, &nchars)) && *name) { - /* Get pointer to current component of name */ - rest = name; - - /* Advance to next component */ - name = rest+nchars; - } /* end while */ - -#ifdef LATER -done: -#endif /* LATER */ - FUNC_LEAVE(rest); -} - - -/*------------------------------------------------------------------------- * Function: H5G_common_path * * Purpose: Determine if one path is a valid prefix of another path @@ -2966,8 +2897,8 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) { const H5G_names_t *names = (const H5G_names_t *)key; /* Get operation's information */ H5G_entry_t *ent = NULL; /* Group entry for object that the ID refers to */ - const char *rest; /* The base name of an object */ - unsigned i; /* Local index variable */ + 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_NOINIT(H5G_replace_ent); @@ -2997,68 +2928,30 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) } /* end switch */ assert(ent); - /* Check if ID's entry is in a mounted file */ - if(ent->file->mtab.parent) { - /* If the ID's entry's parent file is not in the file we operated on, skip it */ - if(ent->file->mtab.parent->shared != names->loc->file->shared ) - HGOTO_DONE(SUCCEED); /* Do not exit search over IDs */ - - /* We need to recurse into the child's file for unlink and move operations */ - if(names->op==OP_UNLINK || names->op==OP_MOVE) { - H5F_t *parent_file=ent->file->mtab.parent; /* Pointer to the parent's file info */ - - /* Search through mounted files for the one which contains the ID's entry */ - for(i=0; i<parent_file->mtab.nmounts; i++) { - H5F_mount_t *child_mnt = &parent_file->mtab.child[i]; /* Mount information for child file */ - H5F_t *child_file = child_mnt->file; /* Child's file info */ - - /* we found the right file */ - if(ent->file->shared == child_file->shared ) { - H5G_entry_t *child_grp_ent = &child_mnt->group->ent; /* Mount point's group entry */ - size_t child_len; /* Length of mount point's name */ - size_t dst_offset=0; /* Offset into destination name */ - - /* Get the length of the child group's name (i.e. the mount point's name in parent group) */ - child_len = HDstrlen(child_grp_ent->name); - - /* Find the prefix of the name */ - if(HDstrncmp( child_grp_ent->name, names->src_name, child_len) == 0) { - /* Advance the offset in the destination also for moves in mounted files */ - if (names->op==OP_MOVE) - dst_offset=child_len; - - /* Search the open ID list and replace names */ - if (H5G_replace_name( H5G_UNKNOWN, child_grp_ent, - names->src_name+child_len, names->dst_name+dst_offset, - names->op )<0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to replace name"); - } /* end if */ - } /* end if */ - } /* end for */ - } /* end if */ - } /* end if */ - /* Verify if file IDs refer to the same file */ - else { - /* If the ID's entry is not in the file we operated on, skip it */ - if( ent->file->shared != names->loc->file->shared ) - HGOTO_DONE(SUCCEED); /* Do not exit search over IDs */ - } /* end else */ - - /* Get the type of call we are doing */ switch(names->op) { /*------------------------------------------------------------------------- * OP_MOUNT *------------------------------------------------------------------------- */ case OP_MOUNT: - /* Find entries that might contain part of this name */ - if(ent->name) { - if(HDstrstr(ent->name, names->src_name)) { - /* Keep the old name for when file is unmounted */ - ent->old_name = ent->name; - - /* Set the new name for the object */ - ent->name=H5MM_xstrdup(names->dst_name); + if(ent->file->mtab.parent && HDstrcmp(ent->user_path,ent->canon_path)) { + /* Find the "top" file in the chain of mounted files */ + top_ent_file=ent->file->mtab.parent; + while(top_ent_file->mtab.parent!=NULL) { + top_ent_file=top_ent_file->mtab.parent; + } /* end while */ + } /* end if */ + else + top_ent_file=ent->file; + + /* Check for entry being in correct file (or mounted file) */ + if(top_ent_file->shared == names->loc->file->shared) { + /* Check if the source is along the entry's path */ + /* (But not actually the entry itself) */ + if(H5G_common_path(ent->user_path,names->src_name) && + HDstrcmp(ent->user_path,names->src_name)!=0) { + /* Hide the user path */ + ent->user_path_hidden++; } /* end if */ } /* end if */ break; @@ -3068,28 +2961,44 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) *------------------------------------------------------------------------- */ case OP_UNMOUNT: - /* Find entries that might contain part of current name */ - if(ent->name) { - if(HDstrstr(ent->name, names->src_name)) { - /* Delete the old name */ - H5MM_xfree(ent->name); - - /* Copy the new name */ - ent->name=H5MM_xstrdup(names->dst_name); - } /* end if */ - } /* end if*/ - - /* See if the entry old name matches */ - if(ent->old_name) { - if(HDstrstr(ent->old_name, names->src_name)) { - /* Delete the old name */ - H5MM_xfree(ent->name); - - /* Copy the old name to the entry */ - ent->name = ent->old_name; - ent->old_name = NULL; + if(ent->file->mtab.parent) { + /* Find the "top" file in the chain of mounted files for the entry */ + top_ent_file=ent->file->mtab.parent; + while(top_ent_file->mtab.parent!=NULL) { + top_ent_file=top_ent_file->mtab.parent; + } /* end while */ + } /* end if */ + else + top_ent_file=ent->file; + + if(names->loc->file->mtab.parent) { + /* Find the "top" file in the chain of mounted files for the location */ + top_loc_file=names->loc->file->mtab.parent; + while(top_loc_file->mtab.parent!=NULL) { + top_loc_file=top_loc_file->mtab.parent; + } /* end while */ + } /* end if */ + else + top_loc_file=names->loc->file; + + if(ent->user_path_hidden) { + /* 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(H5G_common_path(ent->user_path,names->src_name)) { + /* Un-hide the user path */ + ent->user_path_hidden--; + } /* end if */ } /* end if */ } /* end if */ + else { + /* 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(ent->user_path && H5G_common_path(ent->user_path,names->src_name)) { + /* Free user path */ + ent->user_path=H5MM_xfree(ent->user_path); + } /* end if */ + } /* end if */ + } /* end else */ break; /*------------------------------------------------------------------------- @@ -3097,21 +3006,24 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) *------------------------------------------------------------------------- */ case OP_UNLINK: - if(ent->name) { - /* Found the correct entry, just replace the name */ - if(HDstrcmp(ent->name, names->src_name)==0) { - /* Delete the old name */ - H5MM_xfree(ent->name); - - /* Copy destination name */ - ent->name=H5MM_xstrdup(names->dst_name); + /* If the ID's entry is not in the file we operated on, skip it */ + if(ent->file->shared == names->loc->file->shared) { + /* Check if we are referring to the same object */ + if(H5F_addr_eq(ent->header, names->loc->header)) { + /* Check if the object was opened with the same canonical path as the one being moved */ + if(HDstrcmp(ent->canon_path,names->loc->canon_path)==0) { + /* Free user path */ + ent->user_path=H5MM_xfree(ent->user_path); + } /* end if */ } /* end if */ - /* Find other entries that might contain part of this name */ else { - if(H5G_common_path(ent->name, names->src_name)) - ent->name=H5MM_xfree(ent->name); /* Delete the old name and clear the entry */ + /* Check if the location being unlinked is in the canonical path for the current object */ + if(H5G_common_path(ent->canon_path,names->loc->canon_path)) { + /* Free user path */ + ent->user_path=H5MM_xfree(ent->user_path); + } /* end if */ } /* end else */ - } /* end if*/ + } /* end if */ break; /*------------------------------------------------------------------------- @@ -3119,32 +3031,172 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, const void *key) *------------------------------------------------------------------------- */ case OP_MOVE: /* H5Gmove case, check for relative names case */ - if(ent->name) { - /* Verify if we have the wanted entry */ - if(HDstrcmp(ent->name, names->src_name)==0) { - /* Delete the old name */ - H5MM_xfree(ent->name); - - /* Set the new name */ - ent->name=H5MM_xstrdup(names->dst_name); + /* If the ID's entry is not in the file we operated on, skip it */ + if(ent->file->shared == names->loc->file->shared) { + char *src_path; /* Full user path of source name */ + char *dst_path; /* Full user path of destination name */ + char *canon_src_path; /* Pointer to canonical part of source path */ + char *canon_dst_path; /* Pointer to canonical part of destination path */ + + /* Make certain that the source and destination names are full (not relative) paths */ + if(*(names->src_name)!='/') { + size_t src_path_len; /* Length of the source path */ + unsigned need_sep; /* Flag to indicate if separator is needed */ + + /* Get the length of the name for the source group's user path */ + src_path_len=HDstrlen(names->src_loc->user_path); + + /* Determine if there is a trailing separator in the name */ + if(names->src_loc->user_path[src_path_len-1]=='/') + need_sep=0; + else + need_sep=1; + + /* Add in the length needed for the '/' separator and the relative path */ + src_path_len+=HDstrlen(names->src_name)+need_sep; + + /* Allocate space for the path */ + if(NULL==(src_path = H5MM_malloc(src_path_len+1))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + + HDstrcpy(src_path,names->src_loc->user_path); + if(need_sep) + HDstrcat(src_path,"/"); + HDstrcat(src_path,names->src_name); + } /* end if */ + else + src_path=HDstrdup(names->src_name); + if(*(names->dst_name)!='/') { + size_t dst_path_len; /* Length of the destination path */ + unsigned need_sep; /* Flag to indicate if separator is needed */ + + /* Get the length of the name for the destination group's user path */ + dst_path_len=HDstrlen(names->dst_loc->user_path); + + /* Determine if there is a trailing separator in the name */ + if(names->dst_loc->user_path[dst_path_len-1]=='/') + need_sep=0; + else + need_sep=1; + + /* Add in the length needed for the '/' separator and the relative path */ + dst_path_len+=HDstrlen(names->dst_name)+need_sep; + + /* Allocate space for the path */ + if(NULL==(dst_path = H5MM_malloc(dst_path_len+1))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + + HDstrcpy(dst_path,names->dst_loc->user_path); + if(need_sep) + HDstrcat(dst_path,"/"); + HDstrcat(dst_path,names->dst_name); + } /* end if */ + else + dst_path=HDstrdup(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(HDstrcmp(names->loc->user_path,names->loc->canon_path)!=0) { + size_t non_canon_name_len; /* Length of non-canonical part of name */ + + /* Get current string lengths */ + non_canon_name_len=HDstrlen(names->loc->user_path)-HDstrlen(names->loc->canon_path); + + canon_src_path=src_path+non_canon_name_len; + canon_dst_path=dst_path+non_canon_name_len; } /* end if */ else { - /* Get the last component of the name */ - rest=H5G_rest(ent->name); - - /* Relative names case, build the full pathname */ - if(rest && HDstrcmp(rest, names->src_name)==0) { - size_t ent_name_len = HDstrlen(ent->name); /* Length of entry's full pathname */ - size_t rest_len = HDstrlen(rest); /* Length of entry's last component of pathname */ - - /* Reallocate buffer for entry's name */ - ent->name=H5MM_realloc(ent->name, - ent_name_len+(HDstrlen(names->dst_name)-rest_len)+1); - - /* Overwrite last component of name */ - HDstrcpy(ent->name+(ent_name_len-rest_len),names->dst_name); - } /* Relative names case */ - } /* wanted entry */ + canon_src_path=src_path; + canon_dst_path=dst_path; + } /* end else */ + + /* Check if the link being changed in the file is along the canonical path for this object */ + if(H5G_common_path(ent->canon_path,canon_src_path)) { + size_t user_dst_len; /* Length of destination user path */ + size_t canon_dst_len; /* Length of destination canonical path */ + char *old_user_path; /* Pointer to previous user path */ + 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 */ + + /* Get the source & destination components */ + src_comp=HDstrrchr(canon_src_path,'/'); + assert(src_comp); + dst_comp=HDstrrchr(canon_dst_path,'/'); + assert(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'; + + /* Find the user prefix for the entry */ + user_prefix_len=HDstrlen(ent->user_path)-HDstrlen(ent->canon_path); + if(NULL==(user_prefix = H5MM_malloc(user_prefix_len+1))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + HDstrncpy(user_prefix,ent->user_path,user_prefix_len); + user_prefix[user_prefix_len]='\0'; + + /* Hold this for later use */ + old_user_path=ent->user_path; + + /* 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); + + /* Free the old canonical path */ + H5MM_xfree(ent->canon_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==(ent->user_path = H5MM_malloc(user_dst_len+1))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + + /* Allocate space for the new canonical path */ + if(NULL==(ent->canon_path = H5MM_malloc(canon_dst_len+1))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + + /* Create the new names */ + HDstrcpy(ent->user_path,user_prefix); + HDstrcat(ent->user_path,dst_canon_prefix); + HDstrcat(ent->user_path,dst_comp); + HDstrcat(ent->user_path,tail_path); + HDstrcpy(ent->canon_path,dst_canon_prefix); + HDstrcat(ent->canon_path,dst_comp); + HDstrcat(ent->canon_path,tail_path); + + /* Free the old user path */ + H5MM_xfree(old_user_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 */ + H5MM_xfree(src_path); + H5MM_xfree(dst_path); } /* end if */ break; |