From 54188b4abb180273692d2bea0066c79dcbfb3cad Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Wed, 8 Jun 2005 00:22:28 -0500 Subject: [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 --- release_docs/RELEASE.txt | 2 + src/H5G.c | 543 ++++++++++++++++++++++++----------------------- test/mount.c | 270 +++++++++++++++++++++++ 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."); -- cgit v0.12