mirror of
https://github.com/HDFGroup/hdf5.git
synced 2025-02-17 16:10:24 +08:00
[svn-r7377] Purpose:
Bug fix Description: Linking and unlinking objects with multiple internal and/or trailing '/'s was not handled well in the library. Solution: "Normalize" strings by removing trailing '/'s and collapsing multiple internal '/'s down into just one '/' before operating on the name. Platforms tested: FreeBSD 4.8 (sleipnir) h5committested
This commit is contained in:
parent
f126a1cf6f
commit
d99164a9ed
@ -73,6 +73,8 @@ Bug Fixes since HDF5-1.6.0 release
|
||||
|
||||
Library
|
||||
-------
|
||||
- Corrected bugs with multiple '/' characters in names for H5Glink
|
||||
and H5Gunlink. QAK - 2003/08/16
|
||||
- Corrected bug with user blocks that didn't allow a user block to
|
||||
be inserted in front of a file after the file was created.
|
||||
QAK - 2003/08/13
|
||||
|
115
src/H5G.c
115
src/H5G.c
@ -1176,6 +1176,72 @@ H5G_basename(const char *name, size_t *size_p)
|
||||
FUNC_LEAVE_NOAPI(name+i);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5G_normalize
|
||||
*
|
||||
* Purpose: Returns a pointer to a new string which has duplicate and
|
||||
* trailing slashes removed from it.
|
||||
*
|
||||
* Return: Success: Ptr to normalized name.
|
||||
* Failure: NULL
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* Saturday, August 16, 2003
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static char *
|
||||
H5G_normalize(const char *name)
|
||||
{
|
||||
char *norm; /* Pointer to the normalized string */
|
||||
size_t s,d; /* Positions within the strings */
|
||||
unsigned last_slash; /* Flag to indicate last character was a slash */
|
||||
char *ret_value; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOINIT(H5G_normalize);
|
||||
|
||||
/* Sanity check */
|
||||
assert(name);
|
||||
|
||||
/* Duplicate the name, to return */
|
||||
if (NULL==(norm=H5MM_strdup(name)))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for normalized string");
|
||||
|
||||
/* Walk through the characters, omitting duplicated '/'s */
|
||||
s=d=0;
|
||||
last_slash=0;
|
||||
while(name[s]!='\0') {
|
||||
if(name[s]=='/')
|
||||
if(last_slash)
|
||||
;
|
||||
else {
|
||||
norm[d++]=name[s];
|
||||
last_slash=1;
|
||||
} /* end else */
|
||||
else {
|
||||
norm[d++]=name[s];
|
||||
last_slash=0;
|
||||
} /* end else */
|
||||
s++;
|
||||
} /* end while */
|
||||
|
||||
/* Terminate normalized string */
|
||||
norm[d]='\0';
|
||||
|
||||
/* Check for final '/' on normalized name & eliminate it */
|
||||
if(d>1 && last_slash)
|
||||
norm[d-1]='\0';
|
||||
|
||||
/* Set return value */
|
||||
ret_value=norm;
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value);
|
||||
} /* end H5G_normalize() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5G_namei
|
||||
@ -2232,9 +2298,12 @@ H5G_link (H5G_entry_t *cur_loc, const char *cur_name, H5G_entry_t *new_loc,
|
||||
const char *new_name, H5G_link_t type, unsigned namei_flags, hid_t dxpl_id)
|
||||
{
|
||||
H5G_entry_t cur_obj; /*entry for the link tail */
|
||||
unsigned cur_obj_init=0; /* Flag to indicate that the current object is initialized */
|
||||
H5G_entry_t grp_ent; /*ent for grp containing link hd*/
|
||||
H5O_stab_t stab_mesg; /*symbol table message */
|
||||
const char *rest = NULL; /*last component of new name */
|
||||
char *norm_cur_name = NULL; /* Pointer to normalized current name */
|
||||
char *norm_new_name = NULL; /* Pointer to normalized current name */
|
||||
char _comp[1024]; /*name component */
|
||||
size_t nchars; /*characters in component */
|
||||
size_t offset; /*offset to sym-link value */
|
||||
@ -2248,13 +2317,19 @@ H5G_link (H5G_entry_t *cur_loc, const char *cur_name, H5G_entry_t *new_loc,
|
||||
assert (cur_name && *cur_name);
|
||||
assert (new_name && *new_name);
|
||||
|
||||
/* Get normalized copies of the current and new names */
|
||||
if((norm_cur_name=H5G_normalize(cur_name))==NULL)
|
||||
HGOTO_ERROR (H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name");
|
||||
if((norm_new_name=H5G_normalize(new_name))==NULL)
|
||||
HGOTO_ERROR (H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name");
|
||||
|
||||
switch (type) {
|
||||
case H5G_LINK_SOFT:
|
||||
/*
|
||||
* Lookup the the new_name so we can get the group which will contain
|
||||
* the new entry. The entry shouldn't exist yet.
|
||||
*/
|
||||
if (H5G_namei(new_loc, new_name, &rest, &grp_ent, NULL,
|
||||
if (H5G_namei(new_loc, norm_new_name, &rest, &grp_ent, NULL,
|
||||
H5G_TARGET_NORMAL, NULL, H5G_NAMEI_TRAVERSE, NULL, dxpl_id)>=0)
|
||||
HGOTO_ERROR (H5E_SYM, H5E_EXISTS, FAIL, "already exists");
|
||||
H5E_clear (NULL); /*it's okay that we didn't find it*/
|
||||
@ -2265,9 +2340,7 @@ H5G_link (H5G_entry_t *cur_loc, const char *cur_name, H5G_entry_t *new_loc,
|
||||
* terminated and that `rest' points to it.
|
||||
*/
|
||||
if (rest[nchars]) {
|
||||
if (H5G_component (rest+nchars, NULL)) {
|
||||
HGOTO_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL, "component not found");
|
||||
} else if (nchars+1 > sizeof _comp) {
|
||||
if (nchars+1 > sizeof _comp) {
|
||||
HGOTO_ERROR (H5E_SYM, H5E_COMPLEN, FAIL, "name component is too long");
|
||||
} else {
|
||||
HDmemcpy (_comp, rest, nchars);
|
||||
@ -2283,7 +2356,7 @@ H5G_link (H5G_entry_t *cur_loc, const char *cur_name, H5G_entry_t *new_loc,
|
||||
if (NULL==H5O_read (&grp_ent, H5O_STAB_ID, 0, &stab_mesg, dxpl_id))
|
||||
HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to determine local heap address");
|
||||
if ((size_t)(-1)==(offset=H5HL_insert (grp_ent.file, dxpl_id,
|
||||
stab_mesg.heap_addr, HDstrlen(cur_name)+1, cur_name)))
|
||||
stab_mesg.heap_addr, HDstrlen(norm_cur_name)+1, norm_cur_name)))
|
||||
HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to write link value to local heap");
|
||||
H5O_reset (H5O_STAB_ID, &stab_mesg);
|
||||
|
||||
@ -2296,6 +2369,7 @@ H5G_link (H5G_entry_t *cur_loc, const char *cur_name, H5G_entry_t *new_loc,
|
||||
cur_obj.file = grp_ent.file;
|
||||
cur_obj.type = H5G_CACHED_SLINK;
|
||||
cur_obj.cache.slink.lval_offset = offset;
|
||||
cur_obj_init=1; /* Indicate that the cur_obj struct is initialized */
|
||||
|
||||
/*
|
||||
* Insert the link head in the symbol table. This shouldn't ever
|
||||
@ -2309,9 +2383,10 @@ H5G_link (H5G_entry_t *cur_loc, const char *cur_name, H5G_entry_t *new_loc,
|
||||
break;
|
||||
|
||||
case H5G_LINK_HARD:
|
||||
if (H5G_namei(cur_loc, cur_name, NULL, NULL, &cur_obj, namei_flags, NULL, H5G_NAMEI_TRAVERSE, NULL, dxpl_id)<0)
|
||||
if (H5G_namei(cur_loc, norm_cur_name, NULL, NULL, &cur_obj, namei_flags, NULL, H5G_NAMEI_TRAVERSE, NULL, dxpl_id)<0)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "source object not found");
|
||||
if (H5G_insert (new_loc, new_name, &cur_obj, dxpl_id)<0)
|
||||
cur_obj_init=1; /* Indicate that the cur_obj struct is initialized */
|
||||
if (H5G_insert (new_loc, norm_new_name, &cur_obj, dxpl_id)<0)
|
||||
HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL, "unable to create new name/link for object");
|
||||
break;
|
||||
|
||||
@ -2325,7 +2400,14 @@ done:
|
||||
H5G_free_ent_name(&grp_ent);
|
||||
|
||||
/* Free the ID to name buffer */
|
||||
H5G_free_ent_name(&cur_obj);
|
||||
if(cur_obj_init)
|
||||
H5G_free_ent_name(&cur_obj);
|
||||
|
||||
/* Free the normalized path names */
|
||||
if(norm_cur_name)
|
||||
H5MM_xfree(norm_cur_name);
|
||||
if(norm_new_name)
|
||||
H5MM_xfree(norm_new_name);
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value);
|
||||
}
|
||||
@ -2784,6 +2866,7 @@ H5G_unlink(H5G_entry_t *loc, const char *name, hid_t dxpl_id)
|
||||
H5G_entry_t grp_ent, obj_ent;
|
||||
size_t len;
|
||||
const char *base=NULL;
|
||||
char *norm_name = NULL; /* Pointer to normalized name */
|
||||
H5G_stat_t statbuf; /* Info about object to unlink */
|
||||
H5RS_str_t *name_r; /* Ref-counted version of name */
|
||||
herr_t ret_value=SUCCEED; /* Return value */
|
||||
@ -2792,21 +2875,25 @@ H5G_unlink(H5G_entry_t *loc, const char *name, hid_t dxpl_id)
|
||||
assert(loc);
|
||||
assert(name && *name);
|
||||
|
||||
/* Get normalized copy of the name */
|
||||
if((norm_name=H5G_normalize(name))==NULL)
|
||||
HGOTO_ERROR (H5E_SYM, H5E_BADVALUE, FAIL, "can't normalize name");
|
||||
|
||||
/* Reset the group entries to known values in a portable way */
|
||||
HDmemset(&grp_ent,0,sizeof(H5G_entry_t));
|
||||
HDmemset(&obj_ent,0,sizeof(H5G_entry_t));
|
||||
|
||||
/* Get object type before unlink */
|
||||
if (H5G_get_objinfo(loc, name, FALSE, &statbuf, dxpl_id)<0)
|
||||
if (H5G_get_objinfo(loc, norm_name, FALSE, &statbuf, dxpl_id)<0)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found");
|
||||
|
||||
/* Get the entry for the group that contains the object to be unlinked */
|
||||
if (H5G_namei(loc, name, NULL, &grp_ent, &obj_ent,
|
||||
if (H5G_namei(loc, norm_name, NULL, &grp_ent, &obj_ent,
|
||||
H5G_TARGET_SLINK|H5G_TARGET_MOUNT, NULL, H5G_NAMEI_TRAVERSE, NULL, dxpl_id)<0)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object not found");
|
||||
if (!H5F_addr_defined(grp_ent.header))
|
||||
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "no containing group specified");
|
||||
if (NULL==(base=H5G_basename(name, &len)) || '/'==*base)
|
||||
if (NULL==(base=H5G_basename(norm_name, &len)) || '/'==*base)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "problems obtaining object base name");
|
||||
|
||||
/* Remove the name from the symbol table */
|
||||
@ -2814,7 +2901,7 @@ H5G_unlink(H5G_entry_t *loc, const char *name, hid_t dxpl_id)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to unlink name from symbol table");
|
||||
|
||||
/* Search the open IDs and replace names for unlinked object */
|
||||
name_r=H5RS_wrap(name);
|
||||
name_r=H5RS_wrap(norm_name);
|
||||
assert(name_r);
|
||||
if (H5G_replace_name(statbuf.type, &obj_ent, name_r, NULL, NULL, NULL, OP_UNLINK )<0)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to replace name");
|
||||
@ -2825,6 +2912,10 @@ done:
|
||||
H5G_free_ent_name(&grp_ent);
|
||||
H5G_free_ent_name(&obj_ent);
|
||||
|
||||
/* Free the normalized path name */
|
||||
if(norm_name)
|
||||
H5MM_xfree(norm_name);
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value);
|
||||
}
|
||||
|
||||
|
149
test/unlink.c
149
test/unlink.c
@ -28,6 +28,7 @@ const char *FILENAME[] = {
|
||||
"new_move_b",
|
||||
"lunlink",
|
||||
"filespace",
|
||||
"slashes",
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -57,6 +58,11 @@ const char *FILENAME[] = {
|
||||
#define FILESPACE_TOP_GROUPS 10
|
||||
#define FILESPACE_NESTED_GROUPS 50
|
||||
#define FILESPACE_NDATASETS 50
|
||||
#define SLASHES_GROUP_NAME "Group///"
|
||||
#define SLASHES_HARDLINK_NAME "Hard///"
|
||||
#define SLASHES_SOFTLINK_NAME "Soft///"
|
||||
#define SLASHES_SOFTLINK2_NAME "Soft2///"
|
||||
#define SLASHES_ROOTLINK_NAME "Root///"
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
@ -1295,6 +1301,146 @@ error:
|
||||
return -1;
|
||||
} /* end test_create_unlink() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: test_link_slashes
|
||||
*
|
||||
* Purpose: Tests creating links with various multiple & trailing slashes
|
||||
*
|
||||
* Return: Success: 0
|
||||
* Failure: number of errors
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* Saturday, August 16, 2003
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
test_link_slashes(void)
|
||||
{
|
||||
hid_t fapl; /* File access property list */
|
||||
hid_t fid; /* File ID */
|
||||
hid_t gid,gid2; /* Group ID */
|
||||
char filename[1024];
|
||||
|
||||
TESTING("creating links with multiple slashes");
|
||||
|
||||
/* Create file */
|
||||
fapl = h5_fileaccess();
|
||||
h5_fixname(FILENAME[5], fapl, filename, sizeof filename);
|
||||
|
||||
/* Create a file */
|
||||
if((fid=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT))<0) TEST_ERROR;
|
||||
|
||||
/* Create a group in the root group */
|
||||
if((gid = H5Gcreate(fid, SLASHES_GROUP_NAME, 0))<0) TEST_ERROR;
|
||||
|
||||
/* Create a nested group in the root group */
|
||||
if((gid2 = H5Gcreate(gid, SLASHES_GROUP_NAME, 0))<0) TEST_ERROR;
|
||||
|
||||
/* Close the nested group */
|
||||
if(H5Gclose(gid2)<0) TEST_ERROR;
|
||||
|
||||
/* Create a hard link to the nested group */
|
||||
if(H5Glink2(gid, SLASHES_GROUP_NAME, H5G_LINK_HARD, H5G_SAME_LOC, SLASHES_HARDLINK_NAME)<0) TEST_ERROR;
|
||||
|
||||
/* Create a soft link with a relative path to the nested group */
|
||||
if(H5Glink2(gid, SLASHES_GROUP_NAME, H5G_LINK_SOFT, H5G_SAME_LOC, SLASHES_SOFTLINK_NAME)<0) TEST_ERROR;
|
||||
|
||||
/* Create a soft link with the full path to the nested group */
|
||||
if(H5Glink2(gid, "////"SLASHES_GROUP_NAME""SLASHES_GROUP_NAME, H5G_LINK_SOFT, H5G_SAME_LOC, SLASHES_SOFTLINK2_NAME)<0) TEST_ERROR;
|
||||
|
||||
/* Create a soft link to the root group */
|
||||
if(H5Glink2(gid, "////", H5G_LINK_SOFT, H5G_SAME_LOC, SLASHES_ROOTLINK_NAME)<0) TEST_ERROR;
|
||||
|
||||
/* Close the group */
|
||||
if(H5Gclose(gid)<0) TEST_ERROR;
|
||||
|
||||
/* Create a hard link to the existing group */
|
||||
if(H5Glink2(fid, SLASHES_GROUP_NAME, H5G_LINK_HARD, H5G_SAME_LOC, SLASHES_HARDLINK_NAME)<0) TEST_ERROR;
|
||||
|
||||
/* Close the file */
|
||||
if(H5Fclose(fid)<0) TEST_ERROR;
|
||||
|
||||
PASSED();
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
} /* end test_link_slashes() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: test_unlink_slashes
|
||||
*
|
||||
* Purpose: Tests deleting links with various multiple & trailing slashes
|
||||
*
|
||||
* Return: Success: 0
|
||||
* Failure: number of errors
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* Saturday, August 16, 2003
|
||||
*
|
||||
* Modifications:
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
test_unlink_slashes(void)
|
||||
{
|
||||
hid_t fapl; /* File access property list */
|
||||
hid_t fid; /* File ID */
|
||||
hid_t gid; /* Group ID */
|
||||
char filename[1024];
|
||||
|
||||
TESTING("deleting links with multiple slashes");
|
||||
|
||||
/* Create file */
|
||||
fapl = h5_fileaccess();
|
||||
h5_fixname(FILENAME[5], fapl, filename, sizeof filename);
|
||||
|
||||
/* Open the file */
|
||||
if((fid=H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT))<0) TEST_ERROR;
|
||||
|
||||
/* Open the top level group */
|
||||
if((gid = H5Gopen(fid, SLASHES_GROUP_NAME))<0) TEST_ERROR;
|
||||
|
||||
/* Delete the root link */
|
||||
if(H5Gunlink(gid,SLASHES_ROOTLINK_NAME)<0) TEST_ERROR;
|
||||
|
||||
/* Delete the soft link with the full path */
|
||||
if(H5Gunlink(gid,SLASHES_SOFTLINK2_NAME)<0) TEST_ERROR;
|
||||
|
||||
/* Delete the soft link with the relative path */
|
||||
if(H5Gunlink(gid,SLASHES_SOFTLINK_NAME)<0) TEST_ERROR;
|
||||
|
||||
/* Delete the hard link */
|
||||
if(H5Gunlink(gid,SLASHES_HARDLINK_NAME)<0) TEST_ERROR;
|
||||
|
||||
/* Delete the group itself */
|
||||
if(H5Gunlink(gid,SLASHES_GROUP_NAME)<0) TEST_ERROR;
|
||||
|
||||
/* Close the group */
|
||||
if(H5Gclose(gid)<0) TEST_ERROR;
|
||||
|
||||
/* Delete the hard link */
|
||||
if(H5Gunlink(fid,SLASHES_HARDLINK_NAME)<0) TEST_ERROR;
|
||||
|
||||
/* Delete the group itself */
|
||||
if(H5Gunlink(fid,SLASHES_GROUP_NAME)<0) TEST_ERROR;
|
||||
|
||||
/* Close the file */
|
||||
if(H5Fclose(fid)<0) TEST_ERROR;
|
||||
|
||||
PASSED();
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
} /* end test_link_slashes() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: main
|
||||
@ -1360,6 +1506,9 @@ main(void)
|
||||
nerrors += test_create_unlink("create and unlink large number of objects",fapl);
|
||||
/* Test creating & unlinking lots of objects with a 1-element metadata cache FAPL */
|
||||
nerrors += test_create_unlink("create and unlink large number of objects with small cache",fapl2);
|
||||
|
||||
nerrors += test_link_slashes();
|
||||
nerrors += test_unlink_slashes();
|
||||
|
||||
/* Close */
|
||||
if (H5Fclose(file)<0) TEST_ERROR;
|
||||
|
Loading…
Reference in New Issue
Block a user