summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2005-06-08 05:22:28 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2005-06-08 05:22:28 (GMT)
commit54188b4abb180273692d2bea0066c79dcbfb3cad (patch)
tree218d12ae57b2e6a1c13f5bdc7d718e218deb61d9
parent8921cbc80267db8bf168e1fa9acb974721fa68da (diff)
downloadhdf5-54188b4abb180273692d2bea0066c79dcbfb3cad.zip
hdf5-54188b4abb180273692d2bea0066c79dcbfb3cad.tar.gz
hdf5-54188b4abb180273692d2bea0066c79dcbfb3cad.tar.bz2
[svn-r10875] Purpose:
Bug fix Description: Fix several NULL pointer dereferences when tracking the name of open objects during some unusual sequences of mount & unmount operations. Platforms tested: FreeBSD 4.11 (sleipnir) Too minor to require h5committest
-rw-r--r--release_docs/RELEASE.txt2
-rw-r--r--src/H5G.c543
-rw-r--r--test/mount.c270
3 files changed, 548 insertions, 267 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index fa407f6..c7f87a0 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -290,6 +290,8 @@ Bug Fixes since HDF5-1.6.0 release
Library
-------
+ - Fixed various errors in maintaining names for open objects in the
+ face of unusual mount & unmount operations. QAK - 2005/06/08
- "SEMI" and "STRONG" file close degree settings now apply only to the
particular file ID being closed, instead of operating on all open
file IDs for a given file. QAK - 2005/06/01
diff --git a/src/H5G.c b/src/H5G.c
index 6156846..c38bb96 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -3604,25 +3604,27 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, void *key)
*-------------------------------------------------------------------------
*/
case OP_MOUNT:
- if(ent->file->mtab.parent && H5RS_cmp(ent->user_path_r,ent->canon_path_r)) {
- /* 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 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_r,names->src_name) &&
- H5RS_cmp(ent->user_path_r,names->src_name)!=0) {
- /* Hide the user path */
- ent->user_path_hidden++;
- } /* end if */
- } /* end if */
+ if(ent->user_path_r) {
+ if(ent->file->mtab.parent && H5RS_cmp(ent->user_path_r,ent->canon_path_r)) {
+ /* 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 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_r,names->src_name) &&
+ H5RS_cmp(ent->user_path_r,names->src_name)!=0) {
+ /* Hide the user path */
+ ent->user_path_hidden++;
+ } /* end if */
+ } /* end if */
+ } /* end if */
break;
/*-------------------------------------------------------------------------
@@ -3630,45 +3632,42 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, void *key)
*-------------------------------------------------------------------------
*/
case OP_UNMOUNT:
- 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 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 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_r,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_r && H5G_common_path(ent->user_path_r,names->src_name)) {
- /* Free user path */
- if(ent->user_path_r!=NULL) {
- H5RS_decr(ent->user_path_r);
- ent->user_path_r=NULL;
- } /* end if */
- } /* end if */
- } /* end if */
- } /* end else */
+ if(ent->user_path_r) {
+ 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 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 if */
+ else
+ top_loc_file=names->loc->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(ent->user_path_hidden) {
+ if(H5G_common_path(ent->user_path_r,names->src_name)) {
+ /* Un-hide the user path */
+ ent->user_path_hidden--;
+ } /* end if */
+ } /* end if */
+ else {
+ if(H5G_common_path(ent->user_path_r,names->src_name)) {
+ /* Free user path */
+ H5RS_decr(ent->user_path_r);
+ ent->user_path_r=NULL;
+ } /* end if */
+ } /* end else */
+ } /* end if */
+ } /* end if */
break;
/*-------------------------------------------------------------------------
@@ -3677,26 +3676,22 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, void *key)
*/
case OP_UNLINK:
/* If the ID's entry is not in the file we operated on, skip it */
- if(ent->file->shared == names->loc->file->shared) {
+ if(ent->file->shared == names->loc->file->shared && ent->user_path_r) {
/* 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(H5RS_cmp(ent->canon_path_r,names->loc->canon_path_r)==0) {
/* Free user path */
- if(ent->user_path_r!=NULL) {
- H5RS_decr(ent->user_path_r);
- ent->user_path_r=NULL;
- } /* end if */
+ H5RS_decr(ent->user_path_r);
+ ent->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(ent->canon_path_r,names->loc->canon_path_r)) {
/* Free user path */
- if(ent->user_path_r!=NULL) {
- H5RS_decr(ent->user_path_r);
- ent->user_path_r=NULL;
- } /* end if */
+ H5RS_decr(ent->user_path_r);
+ ent->user_path_r=NULL;
} /* end if */
} /* end else */
} /* end if */
@@ -3709,206 +3704,220 @@ H5G_replace_ent(void *obj_ptr, hid_t obj_id, void *key)
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(ent->file->shared == names->loc->file->shared) {
- 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 */
-
- /* Make certain that the source and destination names are full (not relative) paths */
- if(*(H5RS_get_str(names->src_name))!='/') {
- const char *src_name; /* Pointer to raw string of src_name */
- char *src_path; /* Full user path of source name */
- const char *src_user_path; /* Pointer to raw string of src path */
- size_t src_path_len; /* Length of the source path */
- unsigned need_sep; /* Flag to indicate if separator is needed */
-
- /* Get the pointer to the raw src user path */
- src_user_path=H5RS_get_str(names->src_loc->user_path_r);
-
- /* Get the length of the name for the source group's user path */
- src_path_len=HDstrlen(src_user_path);
-
- /* Determine if there is a trailing separator in the name */
- if(src_user_path[src_path_len-1]=='/')
- need_sep=0;
- else
- need_sep=1;
-
- /* Get the pointer to the raw src user path */
- src_name=H5RS_get_str(names->src_name);
-
- /* Add in the length needed for the '/' separator and the relative path */
- src_path_len+=HDstrlen(src_name)+need_sep;
-
- /* Allocate space for the path */
- if(NULL==(src_path = H5FL_BLK_MALLOC(str_buf,src_path_len+1)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
-
- HDstrcpy(src_path,src_user_path);
- if(need_sep)
- HDstrcat(src_path,"/");
- HDstrcat(src_path,src_name);
-
- /* Create reference counted string for src path */
- src_path_r=H5RS_own(src_path);
- } /* end if */
- else
- src_path_r=H5RS_dup(names->src_name);
- if(*(H5RS_get_str(names->dst_name))!='/') {
- const char *dst_name; /* Pointer to raw string of dst_name */
- char *dst_path; /* Full user path of destination name */
- const char *dst_user_path; /* Pointer to raw string of dst path */
- size_t dst_path_len; /* Length of the destination path */
- unsigned need_sep; /* Flag to indicate if separator is needed */
-
- /* Get the pointer to the raw dst user path */
- dst_user_path=H5RS_get_str(names->dst_loc->user_path_r);
-
- /* Get the length of the name for the destination group's user path */
- dst_path_len=HDstrlen(dst_user_path);
-
- /* Determine if there is a trailing separator in the name */
- if(dst_user_path[dst_path_len-1]=='/')
- need_sep=0;
- else
- need_sep=1;
-
- /* Get the pointer to the raw dst user path */
- dst_name=H5RS_get_str(names->dst_name);
-
- /* Add in the length needed for the '/' separator and the relative path */
- dst_path_len+=HDstrlen(dst_name)+need_sep;
-
- /* Allocate space for the path */
- if(NULL==(dst_path = H5FL_BLK_MALLOC(str_buf,dst_path_len+1)))
- HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
-
- HDstrcpy(dst_path,dst_user_path);
- if(need_sep)
- HDstrcat(dst_path,"/");
- HDstrcat(dst_path,dst_name);
-
- /* Create reference counted string for dst path */
- dst_path_r=H5RS_own(dst_path);
- } /* 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->user_path_r,names->loc->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->user_path_r)-H5RS_len(names->loc->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(ent->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,'/');
- 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';
-
- /* Hold this for later use */
- old_user_path=H5RS_get_str(ent->user_path_r);
-
- /* Find the user prefix for the entry */
- user_prefix_len=HDstrlen(old_user_path)-H5RS_len(ent->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(ent->user_path_r);
- H5RS_decr(ent->canon_path_r);
-
- /* Take ownership of the new user & canonical paths */
- ent->user_path_r=H5RS_own(new_user_path);
- ent->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);
+ if(ent->user_path_r && names->loc->user_path_r &&
+ names->src_loc->user_path_r && names->dst_loc->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))!='/') {
+ const char *src_name; /* Pointer to raw string of src_name */
+ char *src_path; /* Full user path of source name */
+ const char *src_user_path; /* Pointer to raw string of src path */
+ size_t src_path_len; /* Length of the source path */
+ unsigned need_sep; /* Flag to indicate if separator is needed */
+
+ /* Get the pointer to the raw src user path */
+ src_user_path=H5RS_get_str(names->src_loc->user_path_r);
+
+ /* Get the length of the name for the source group's user path */
+ src_path_len=HDstrlen(src_user_path);
+
+ /* Determine if there is a trailing separator in the name */
+ if(src_user_path[src_path_len-1]=='/')
+ need_sep=0;
+ else
+ need_sep=1;
+
+ /* Get the pointer to the raw src user path */
+ src_name=H5RS_get_str(names->src_name);
+
+ /* Add in the length needed for the '/' separator and the relative path */
+ src_path_len+=HDstrlen(src_name)+need_sep;
+
+ /* Allocate space for the path */
+ if(NULL==(src_path = H5FL_BLK_MALLOC(str_buf,src_path_len+1)))
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
+
+ HDstrcpy(src_path,src_user_path);
+ if(need_sep)
+ HDstrcat(src_path,"/");
+ HDstrcat(src_path,src_name);
+
+ /* Create reference counted string for src path */
+ src_path_r=H5RS_own(src_path);
+ } /* end if */
+ else
+ src_path_r=H5RS_dup(names->src_name);
+ if(*(H5RS_get_str(names->dst_name))!='/') {
+ const char *dst_name; /* Pointer to raw string of dst_name */
+ char *dst_path; /* Full user path of destination name */
+ const char *dst_user_path; /* Pointer to raw string of dst path */
+ size_t dst_path_len; /* Length of the destination path */
+ unsigned need_sep; /* Flag to indicate if separator is needed */
+
+ /* Get the pointer to the raw dst user path */
+ dst_user_path=H5RS_get_str(names->dst_loc->user_path_r);
+
+ /* Get the length of the name for the destination group's user path */
+ dst_path_len=HDstrlen(dst_user_path);
+
+ /* Determine if there is a trailing separator in the name */
+ if(dst_user_path[dst_path_len-1]=='/')
+ need_sep=0;
+ else
+ need_sep=1;
+
+ /* Get the pointer to the raw dst user path */
+ dst_name=H5RS_get_str(names->dst_name);
+
+ /* Add in the length needed for the '/' separator and the relative path */
+ dst_path_len+=HDstrlen(dst_name)+need_sep;
+
+ /* Allocate space for the path */
+ if(NULL==(dst_path = H5FL_BLK_MALLOC(str_buf,dst_path_len+1)))
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
+
+ HDstrcpy(dst_path,dst_user_path);
+ if(need_sep)
+ HDstrcat(dst_path,"/");
+ HDstrcat(dst_path,dst_name);
+
+ /* Create reference counted string for dst path */
+ dst_path_r=H5RS_own(dst_path);
+ } /* 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->user_path_r,names->loc->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->user_path_r)-H5RS_len(names->loc->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(ent->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,'/');
+ 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';
+
+ /* Hold this for later use */
+ old_user_path=H5RS_get_str(ent->user_path_r);
+
+ /* Find the user prefix for the entry */
+ user_prefix_len=HDstrlen(old_user_path)-H5RS_len(ent->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(ent->user_path_r);
+ H5RS_decr(ent->canon_path_r);
+
+ /* Take ownership of the new user & canonical paths */
+ ent->user_path_r=H5RS_own(new_user_path);
+ ent->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(ent->user_path_r) {
+ H5RS_decr(ent->user_path_r);
+ ent->user_path_r = NULL;
+ } /* end if */
+ } /* end else */
} /* end if */
break;
diff --git a/test/mount.c b/test/mount.c
index 7a42790..389c48e 100644
--- a/test/mount.c
+++ b/test/mount.c
@@ -24,6 +24,7 @@ const char *FILENAME[] = {
"mount_1",
"mount_2",
"mount_3",
+ "mount_4",
NULL
};
@@ -1248,6 +1249,274 @@ error:
return 1;
}
+
+/*-------------------------------------------------------------------------
+ * Function: test_mount_after_unmount
+ *
+ * Purpose: Test that the library handles mounting a file while holding
+ * objects open in a file which has been unmounted.
+ *
+ * Return: Success: 0
+ *
+ * Failure: number of errors
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 6, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_mount_after_unmount(hid_t fapl)
+{
+ hid_t fid1=-1, fid2=-1, fid3=-1, fid4=-1; /* File IDs */
+ hid_t gidA=-1, gidB=-1, gidX=-1, gidY=-1, gidZ=-1; /* Group identifiers */
+ hid_t gidBM=-1; /* Group identifiers */
+ hid_t gidBMZ=-1; /* Group identifiers */
+ hid_t gidAM=-1; /* Group identifiers */
+ hid_t gidAMX=-1; /* Group identifiers */
+ hid_t gidAMXX=-1; /* Group identifiers */
+ hid_t gidAMXMY=-1; /* Group identifiers */
+ hid_t gidXM=-1; /* Group identifiers */
+ hid_t gidXX=-1; /* Group identifiers */
+ char filename1[1024],
+ filename2[1024],
+ filename3[1024],
+ filename4[1024]; /* Name of files to mount */
+ char objname[NAME_BUF_SIZE]; /* Name of object opened */
+
+ TESTING("mounting after file is unmounted");
+ h5_fixname(FILENAME[0], fapl, filename1, sizeof filename1);
+ h5_fixname(FILENAME[1], fapl, filename2, sizeof filename2);
+ h5_fixname(FILENAME[2], fapl, filename3, sizeof filename3);
+ h5_fixname(FILENAME[3], fapl, filename4, sizeof filename4);
+
+ /* Create first file and some groups in it. */
+ if((fid1 = H5Fcreate(filename1, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ if((gidA = H5Gcreate(fid1, "A", (size_t)0)) < 0)
+ TEST_ERROR
+ if((gidAM = H5Gcreate(gidA, "M", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidAM) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+ if((gidB = H5Gcreate(fid1, "B", (size_t)0)) < 0)
+ TEST_ERROR
+ if((gidBM = H5Gcreate(gidB, "M", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidBM) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidB) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+ /* Create second file and a group in it. */
+ if((fid2 = H5Fcreate(filename2, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ if((gidX = H5Gcreate(fid2, "/X", (size_t)0)) < 0)
+ TEST_ERROR
+ if((gidXM = H5Gcreate(gidX, "M", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidXM) < 0)
+ TEST_ERROR
+ if((gidXX = H5Gcreate(gidX, "X", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidXX) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidX) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+
+ /* Create third file and a group in it. */
+ if((fid3 = H5Fcreate(filename3, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ if((gidY = H5Gcreate(fid3, "/Y", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidY) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+
+ /* Create fourth file and a group in it. */
+ if((fid4 = H5Fcreate(filename4, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ if((gidZ = H5Gcreate(fid4, "/Z", (size_t)0)) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidZ) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid4) < 0)
+ TEST_ERROR
+
+
+/* Beginning of the actual test code */
+
+ /*
+ * Reopen all three files
+ */
+ if((fid1 = H5Fopen(filename1, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((fid2 = H5Fopen(filename2, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((fid3 = H5Fopen(filename3, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+ if((fid4 = H5Fopen(filename4, H5F_ACC_RDWR, fapl)) < 0)
+ TEST_ERROR
+
+ /*
+ * Open /A & /B to use as a mount points
+ */
+ if((gidA = H5Gopen(fid1, "/A")) < 0)
+ TEST_ERROR
+ if((gidB = H5Gopen(fid1, "/B")) < 0)
+ TEST_ERROR
+
+ /*
+ * Mount second file on /A/M in the first file.
+ */
+ if(H5Fmount(gidA, "M", fid2, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Open group in mounted file */
+ /* (This shows we successfully mounted) */
+ if((gidAMXX = H5Gopen(gidA, "M/X/X")) < 0)
+ TEST_ERROR
+
+ /* Check name */
+ if(H5Iget_name( gidAMXX, objname, (size_t)NAME_BUF_SIZE ) < 0)
+ TEST_ERROR
+ if(HDstrcmp(objname, "/A/M/X/X"))
+ TEST_ERROR
+
+ /* Open group in mounted file #2 */
+ if((gidAMX = H5Gopen(gidA, "M/X")) < 0)
+ TEST_ERROR
+
+ /* Mount third file */
+ if(H5Fmount(gidAMX, "M", fid3, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Open group in mounted file #3 */
+ /* (This shows we successfully mounted) */
+ if((gidAMXMY = H5Gopen(gidAMX, "M/Y")) < 0)
+ TEST_ERROR
+
+ /* Check name */
+ if(H5Iget_name( gidAMXMY, objname, (size_t)NAME_BUF_SIZE ) < 0)
+ TEST_ERROR
+ if(HDstrcmp(objname, "/A/M/X/M/Y"))
+ TEST_ERROR
+
+ /* Unmount second file */
+ if (H5Funmount(fid1, "/A/M")<0)
+ TEST_ERROR
+
+ /* Check name */
+ *objname = '\0';
+ if(H5Iget_name( gidAMXMY, objname, (size_t)NAME_BUF_SIZE ) < 0)
+ TEST_ERROR
+ if(HDstrcmp(objname, ""))
+ TEST_ERROR
+
+ /* Rename object in file #3 that is "disconnected" from name hiearchy */
+ /* (It is "disconnected" because it's parent file has been unmounted) */
+ if(H5Gmove2(gidAMX,"M/Y",gidAMX,"M/Z") < 0)
+ TEST_ERROR
+
+ /* Close group in file #3 */
+ if(H5Gclose(gidAMXMY) < 0)
+ TEST_ERROR
+
+ /* Re-open group in file #3 */
+ if((gidAMXMY = H5Gopen(gidAMX, "M/Z")) < 0)
+ TEST_ERROR
+
+ /* Check name again */
+ *objname = '\0';
+ if(H5Iget_name( gidAMXMY, objname, (size_t)NAME_BUF_SIZE ) < 0)
+ TEST_ERROR
+ if(HDstrcmp(objname, ""))
+ TEST_ERROR
+
+ /* Mount fourth file */
+ if(H5Fmount(gidB, "M", fid4, H5P_DEFAULT) < 0)
+ TEST_ERROR
+
+ /* Open group in mounted file */
+ /* (This shows we successfully mounted) */
+ if((gidBMZ = H5Gopen(gidB, "M/Z")) < 0)
+ TEST_ERROR
+
+ /* Check name */
+ if(H5Iget_name( gidBMZ, objname, (size_t)NAME_BUF_SIZE ) < 0)
+ TEST_ERROR
+ if(HDstrcmp(objname, "/B/M/Z"))
+ TEST_ERROR
+
+ /* Unmount third file */
+ if (H5Funmount(fid2, "/X/M")<0)
+ TEST_ERROR
+
+ /* Unmount fourth file */
+ if (H5Funmount(fid1, "/B/M")<0)
+ TEST_ERROR
+
+ /* Close objects in mounted files */
+ if(H5Gclose(gidBMZ) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidAMXMY) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidAMXX) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidAMX) < 0)
+ TEST_ERROR
+
+ /* Close objects in original file */
+ if(H5Gclose(gidB) < 0)
+ TEST_ERROR
+ if(H5Gclose(gidA) < 0)
+ TEST_ERROR
+
+ /* Close files */
+ if(H5Fclose(fid4) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid3) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid2) < 0)
+ TEST_ERROR
+ if(H5Fclose(fid1) < 0)
+ TEST_ERROR
+
+ /* Shut down */
+ PASSED();
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Gclose(gidZ);
+ H5Gclose(gidY);
+ H5Gclose(gidXX);
+ H5Gclose(gidXM);
+ H5Gclose(gidX);
+ H5Gclose(gidBMZ);
+ H5Gclose(gidBM);
+ H5Gclose(gidB);
+ H5Gclose(gidAMXMY);
+ H5Gclose(gidAMXX);
+ H5Gclose(gidAMX);
+ H5Gclose(gidAM);
+ H5Gclose(gidA);
+ H5Fclose(fid4);
+ H5Fclose(fid3);
+ H5Fclose(fid2);
+ H5Fclose(fid1);
+ } H5E_END_TRY;
+ return 1;
+}
/*-------------------------------------------------------------------------
@@ -1290,6 +1559,7 @@ main(void)
nerrors += test_uniformity(fapl);
nerrors += test_close(fapl);
nerrors += test_mount_after_close(fapl);
+ nerrors += test_mount_after_unmount(fapl);
if (nerrors) goto error;
puts("All mount tests passed.");