summaryrefslogtreecommitdiffstats
path: root/tools/lib/h5diff.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lib/h5diff.c')
-rw-r--r--tools/lib/h5diff.c835
1 files changed, 697 insertions, 138 deletions
diff --git a/tools/lib/h5diff.c b/tools/lib/h5diff.c
index 998e96a..9e753fe 100644
--- a/tools/lib/h5diff.c
+++ b/tools/lib/h5diff.c
@@ -20,6 +20,28 @@
#include "h5tools.h"
#include "h5tools_utils.h"
+/* This code is layout for common code among tools */
+typedef enum toolname_t {
+ TOOL_H5DIFF, TOOL_H5LS, TOOL__H5DUMP /* add as necessary */
+} h5tool_toolname_t;
+/* this struct can be used to differntiate among tools if necessary */
+typedef struct {
+ h5tool_toolname_t toolname;
+ int msg_mode;
+} h5tool_opt_t;
+
+/* To return link info
+ * Functions:
+ * H5tools_get_link_info()
+ * Note: this may be move to h5tools code if used by other tools
+ */
+typedef struct {
+ H5O_type_t trg_type; /* OUT: target type */
+ const char *trg_path; /* OUT: target obj path. This must be freed
+ * when used with H5tools_get_link_info() */
+ H5L_info_t linfo; /* OUT: link info */
+ h5tool_opt_t opt; /* IN: options */
+} h5tool_link_info_t;
/*
* Debug printf macros. The prefix allows output filtering by test scripts.
*/
@@ -65,6 +87,21 @@ do_print_objname (const char *OBJ, const char *path1, const char *path2)
parallel_print("%-7s: <%s> and <%s>\n", OBJ, path1, path2);
}
+/*-------------------------------------------------------------------------
+ * Function: print_warn
+ *
+ * Purpose: check print warning condition.
+ * Return:
+ * 1 if verbose mode
+ * 0 if not verbos mode
+ * Programmer: Jonathan Kim
+ * Date: Feb 4, 2010
+ *-------------------------------------------------------------------------
+ */
+static int print_warn(diff_opt_t *options)
+{
+ return ((options->m_verbose))?1:0;
+}
#ifdef H5_HAVE_PARALLEL
@@ -83,9 +120,9 @@ do_print_objname (const char *OBJ, const char *path1, const char *path2)
*/
void phdiff_dismiss_workers(void)
{
- int i;
- for(i=1; i<g_nTasks; i++)
- MPI_Send(NULL, 0, MPI_BYTE, i, MPI_TAG_END, MPI_COMM_WORLD);
+ int i;
+ for(i=1; i<g_nTasks; i++)
+ MPI_Send(NULL, 0, MPI_BYTE, i, MPI_TAG_END, MPI_COMM_WORLD);
}
@@ -105,31 +142,29 @@ void phdiff_dismiss_workers(void)
*/
void print_manager_output(void)
{
- /* If there was something we buffered, let's print it now */
- if( (outBuffOffset>0) && g_Parallel)
- {
- printf("%s", outBuff);
-
- if(overflow_file)
- {
- int tmp;
-
- rewind(overflow_file);
- while((tmp = getc(overflow_file)) >= 0)
- putchar(tmp);
-
- fclose(overflow_file);
- overflow_file = NULL;
- }
-
- fflush(stdout);
- memset(outBuff, 0, OUTBUFF_SIZE);
- outBuffOffset = 0;
- }
- else if( (outBuffOffset>0) && !g_Parallel)
- {
- fprintf(stderr, "h5diff error: outBuffOffset>0, but we're not in parallel!\n");
- }
+ /* If there was something we buffered, let's print it now */
+ if( (outBuffOffset>0) && g_Parallel)
+ {
+ printf("%s", outBuff);
+
+ if(overflow_file)
+ {
+ int tmp;
+ rewind(overflow_file);
+ while((tmp = getc(overflow_file)) >= 0)
+ putchar(tmp);
+ fclose(overflow_file);
+ overflow_file = NULL;
+ }
+
+ fflush(stdout);
+ memset(outBuff, 0, OUTBUFF_SIZE);
+ outBuffOffset = 0;
+ }
+ else if( (outBuffOffset>0) && !g_Parallel)
+ {
+ fprintf(stderr, "h5diff error: outBuffOffset>0, but we're not in parallel!\n");
+ }
}
/*-------------------------------------------------------------------------
@@ -149,25 +184,201 @@ void print_manager_output(void)
static void print_incoming_data(void)
{
- char data[PRINT_DATA_MAX_SIZE+1];
- int incomingMessage;
- MPI_Status Status;
-
- do
- {
- MPI_Iprobe(MPI_ANY_SOURCE, MPI_TAG_PRINT_DATA, MPI_COMM_WORLD, &incomingMessage, &Status);
- if(incomingMessage)
- {
- memset(data, 0, PRINT_DATA_MAX_SIZE+1);
- MPI_Recv(data, PRINT_DATA_MAX_SIZE, MPI_CHAR, Status.MPI_SOURCE, MPI_TAG_PRINT_DATA, MPI_COMM_WORLD, &Status);
-
- printf("%s", data);
- }
- } while(incomingMessage);
+ char data[PRINT_DATA_MAX_SIZE+1];
+ int incomingMessage;
+ MPI_Status Status;
+
+ do
+ {
+ MPI_Iprobe(MPI_ANY_SOURCE, MPI_TAG_PRINT_DATA, MPI_COMM_WORLD, &incomingMessage, &Status);
+ if(incomingMessage)
+ {
+ memset(data, 0, PRINT_DATA_MAX_SIZE+1);
+ MPI_Recv(data, PRINT_DATA_MAX_SIZE, MPI_CHAR, Status.MPI_SOURCE, MPI_TAG_PRINT_DATA, MPI_COMM_WORLD, &Status);
+
+ printf("%s", data);
+ }
+ } while(incomingMessage);
}
#endif
/*-------------------------------------------------------------------------
+ * Function: is_valid_options
+ *
+ * Purpose: check if options are valid
+ *
+ * Return:
+ * 1 : Valid
+ * 0 : Not valid
+ *
+ * Programmer: Jonathan Kim
+ *
+ * Date: Feb 17, 2010
+ *
+ *------------------------------------------------------------------------*/
+static int is_valid_options(diff_opt_t *options)
+{
+ int ret=1; /* init to valid */
+
+ /*-----------------------------------------------
+ * no -q(quiet) with -v (verbose) or -r (report) */
+ if(options->m_quiet && (options->m_verbose || options->m_report))
+ {
+ parallel_print("Error: -q (quiet mode) cannot be added to verbose or report modes\n");
+ options->err_stat=1;
+ ret = 0;
+ goto out;
+ }
+
+ /* -------------------------------------------------------
+ * only allow --no-dangling-links along with --follow-links */
+ if(options->no_dangle_links && !options->follow_links)
+ {
+ parallel_print("Error: --no-dangling-links must be used along with --follow-links option.\n");
+ options->err_stat=1;
+ ret = 0;
+ goto out;
+ }
+
+out:
+ if (!ret)
+ {
+#ifdef H5_HAVE_PARALLEL
+ if(g_Parallel)
+ /* Let tasks know that they won't be needed */
+ phdiff_dismiss_workers();
+#endif
+ }
+
+ return ret;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5tools_get_link_info
+ *
+ * Purpose: Get link (soft, external) info and its target object type
+ (dataset, group, named datatype) and path, if exist
+ *
+ * Patameters:
+ * - [IN] fileid : link file id
+ * - [IN] linkpath : link path
+ * - [OUT] h5li : link's info (H5L_info_t)
+ * - [OUT] link_info: returning target object info (h5tool_link_info_t)
+ *
+ * Return:
+ * 1 : Succed to get link info.
+ * 0 : Detected as a dangling link
+ * -1 : H5 API failed.
+ *
+ * NOTE:
+ * link_info->trg_path must be freed out of this function
+ *
+ * Programmer: Jonathan Kim
+ *
+ * Date: Feb 8, 2010
+ *-------------------------------------------------------------------------*/
+static int H5tools_get_link_info(hid_t file_id, const char * linkpath, h5tool_link_info_t *link_info)
+{
+ int Ret = -1; /* init to fail */
+ htri_t l_ret;
+ H5O_info_t trg_oinfo;
+ hid_t fapl;
+ hid_t lapl = H5P_DEFAULT;
+
+ /* init */
+ link_info->trg_type = H5O_TYPE_UNKNOWN;
+
+ /* check if link itself exist */
+ if((H5Lexists(file_id, linkpath, H5P_DEFAULT) <= 0))
+ {
+ if(link_info->opt.msg_mode==1)
+ parallel_print("Warning: link <%s> doesn't exist \n",linkpath);
+ goto out;
+ }
+
+ /* get info from link */
+ if(H5Lget_info(file_id, linkpath, &(link_info->linfo), H5P_DEFAULT) < 0)
+ {
+ if(link_info->opt.msg_mode==1)
+ parallel_print("Warning: unable to get link info from <%s>\n",linkpath);
+ goto out;
+ }
+
+ /* trg_path must be freed out of this function when finished using */
+ link_info->trg_path = (char*)HDcalloc(link_info->linfo.u.val_size, sizeof(char));
+ HDassert(link_info->trg_path);
+
+ /* get link value */
+ if(H5Lget_val(file_id, linkpath, link_info->trg_path, link_info->linfo.u.val_size, H5P_DEFAULT) < 0)
+ {
+ if(link_info->opt.msg_mode==1)
+ parallel_print("Warning: unable to get link value from <%s>\n",linkpath);
+ goto out;
+ }
+
+ /*-----------------------------------------------------
+ * if link type is external link use different lapl to
+ * follow object in other file
+ */
+ if (link_info->linfo.type == H5L_TYPE_EXTERNAL)
+ {
+ fapl = H5Pcreate(H5P_FILE_ACCESS);
+ H5Pset_fapl_sec2(fapl);
+ lapl = H5Pcreate(H5P_LINK_ACCESS);
+ H5Pset_elink_fapl(lapl, fapl);
+ }
+
+ /*--------------------------------------------------------------
+ * if link's target object exist, get type
+ */
+ /* check if target object exist */
+ l_ret = H5Oexists_by_name(file_id, linkpath, lapl);
+
+ /* detect dangling link */
+ if(l_ret == FALSE)
+ {
+ Ret = 0;
+ goto out;
+ }
+ /* function failed */
+ else if (l_ret < 0)
+ {
+ goto out;
+ }
+
+ /* get target object info */
+ if(H5Oget_info_by_name(file_id, linkpath, &trg_oinfo, lapl) < 0)
+ {
+ if(link_info->opt.msg_mode==1)
+ parallel_print("Warning: unable to get object information for <%s>\n", linkpath);
+ goto out;
+ }
+
+ /* check unknown type */
+ if (trg_oinfo.type < H5O_TYPE_GROUP || trg_oinfo.type >=H5O_TYPE_NTYPES)
+ {
+ if(link_info->opt.msg_mode==1)
+ parallel_print("Warning: target object of <%s> is unknown type\n", linkpath);
+ goto out;
+ }
+
+ /* set target obj type to return */
+ link_info->trg_type = trg_oinfo.type;
+
+ /* succeed */
+ Ret = 1;
+out:
+ if (link_info->linfo.type == H5L_TYPE_EXTERNAL)
+ {
+ H5Pclose(fapl);
+ H5Pclose(lapl);
+ }
+
+ return Ret;
+}
+
+/*-------------------------------------------------------------------------
* Function: h5diff
*
* Purpose: public function, can be called in an application program.
@@ -181,7 +392,6 @@ static void print_incoming_data(void)
*
*-------------------------------------------------------------------------
*/
-
hsize_t h5diff(const char *fname1,
const char *fname2,
const char *objname1,
@@ -197,12 +407,11 @@ hsize_t h5diff(const char *fname1,
HDmemset(filenames, 0, 1024 * 2);
- if(options->m_quiet && (options->m_verbose || options->m_report))
- {
- parallel_print("Error: -q (quiet mode) cannot be added to verbose or report modes\n");
- options->err_stat=1;
- return 0;
- } /* end if */
+ /*-------------------------------------------------------------------------
+ * check invalid combination of options
+ *-----------------------------------------------------------------------*/
+ if(!is_valid_options(options))
+ goto out;
/*-------------------------------------------------------------------------
* open the files first; if they are not valid, no point in continuing
@@ -214,7 +423,7 @@ hsize_t h5diff(const char *fname1,
{
/* open file 1 */
- if((file1_id = h5tools_fopen(fname1, H5F_ACC_RDONLY, H5P_DEFAULT, NULL, NULL, (size_t)0)) < 0)
+ if((file1_id = h5tools_fopen(fname1, H5F_ACC_RDONLY, H5P_DEFAULT, NULL, NULL, (size_t)0)) < 0)
{
parallel_print("h5diff: <%s>: unable to open file\n", fname1);
@@ -230,8 +439,8 @@ hsize_t h5diff(const char *fname1,
/* open file 2 */
-
- if((file2_id = h5tools_fopen(fname2, H5F_ACC_RDONLY, H5P_DEFAULT, NULL, NULL, (size_t)0)) < 0)
+
+ if((file2_id = h5tools_fopen(fname2, H5F_ACC_RDONLY, H5P_DEFAULT, NULL, NULL, (size_t)0)) < 0)
{
parallel_print("h5diff: <%s>: unable to open file\n", fname2);
@@ -292,12 +501,10 @@ hsize_t h5diff(const char *fname1,
info2,
options);
} /* end if */
-
/*-------------------------------------------------------------------------
* compare all
*-------------------------------------------------------------------------
*/
-
else
{
#ifdef H5_HAVE_PARALLEL
@@ -461,14 +668,14 @@ hsize_t diff_match(hid_t file1_id,
* 2) the graph must match, i.e same names (absolute path)
* 3) objects with the same name must be of the same type
*-------------------------------------------------------------------------
- */
-
+ */
+
/* number of different objects */
if ( info1->nused != info2->nused )
{
options->contents = 0;
}
-
+
/* objects in one file and not the other */
for( i = 0; i < table->nobjs; i++)
{
@@ -479,7 +686,7 @@ hsize_t diff_match(hid_t file1_id,
}
/* objects with the same name but different HDF5 types */
- for( i = 0; i < table->nobjs; i++)
+ for( i = 0; i < table->nobjs; i++)
{
if ( table->objs[i].flags[0] && table->objs[i].flags[1] )
{
@@ -497,8 +704,8 @@ hsize_t diff_match(hid_t file1_id,
*-------------------------------------------------------------------------
*/
#ifdef H5_HAVE_PARALLEL
-{
- char *workerTasks = HDmalloc((g_nTasks - 1) * sizeof(char));
+ {
+ char *workerTasks = (char*)HDmalloc((g_nTasks - 1) * sizeof(char));
int n;
int busyTasks = 0;
struct diffs_found nFoundbyWorker;
@@ -789,7 +996,7 @@ hsize_t diff_match(hid_t file1_id,
h5diffdebug("done with if block\n");
free(workerTasks);
-}
+ }
#endif /* H5_HAVE_PARALLEL */
/* free table */
@@ -807,9 +1014,10 @@ hsize_t diff_match(hid_t file1_id,
* Return: Number of differences found
*
* Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
- *
* Date: May 9, 2003
*
+ * Programmer: Jonathan Kim
+ * - add following links feature (Feb 11,2010)
*-------------------------------------------------------------------------
*/
@@ -826,9 +1034,24 @@ hsize_t diff_compare(hid_t file1_id,
int f1 = 0;
int f2 = 0;
hsize_t nfound = 0;
+ ssize_t i,j;
+ int l_ret;
+ int is_dangle_link1 = 0;
+ int is_dangle_link2 = 0;
+
+ /* local variables for diff() */
+ h5trav_type_t obj1type, obj2type;
- ssize_t i = h5trav_getindex (info1, obj1_name);
- ssize_t j = h5trav_getindex (info2, obj2_name);
+ /* to get link info */
+ h5tool_link_info_t linkinfo1;
+ h5tool_link_info_t linkinfo2;
+
+ /* init link info struct */
+ HDmemset(&linkinfo1, 0, sizeof(h5tool_link_info_t));
+ HDmemset(&linkinfo2, 0, sizeof(h5tool_link_info_t));
+
+ i = h5trav_getindex (info1, obj1_name);
+ j = h5trav_getindex (info2, obj2_name);
if (i == -1)
{
@@ -852,25 +1075,217 @@ hsize_t diff_compare(hid_t file1_id,
obj1_name = info1->paths[i].path;
obj2_name = info2->paths[j].path;
+ obj1type = info1->paths[i].type;
+ obj2type = info2->paths[j].type;
+
+ /*-----------------------------------------------------------------
+ * follow link option, compare with target object
+ */
+ if (options->follow_links)
+ {
+ /* pass how to handle printing warning to linkinfo option */
+ if(print_warn(options))
+ linkinfo1.opt.msg_mode = linkinfo2.opt.msg_mode = 1;
+
+ /*------------------------------------------------------------
+ * Soft links
+ *------------------------------------------------------------*/
+
+ /*--------------------------
+ * if object1 soft link */
+ if (obj1type == H5TRAV_TYPE_LINK)
+ {
+ /* get type of target object */
+ l_ret = H5tools_get_link_info(file1_id, obj1_name, &linkinfo1);
+ /* dangling link */
+ if (l_ret == 0)
+ {
+ if (options->no_dangle_links)
+ {
+ /* gangling link is error */
+ if(options->m_verbose)
+ parallel_print("Warning: <%s> is a dangling link.\n", obj1_name);
+ options->err_stat = 1;
+ goto out;
+ }
+ else
+ is_dangle_link1 = 1;
+ }
+ /* fail */
+ else if(l_ret < 0)
+ {
+ options->err_stat = 1;
+ goto out;
+ }
+ else /* OK */
+ {
+ /* target type for diff() */
+ obj1type = linkinfo1.trg_type;
+ }
+ }
+
+ /*-----------------------------
+ * if object2 is soft link */
+ if (obj2type == H5TRAV_TYPE_LINK)
+ {
+ /* get type target object */
+ l_ret = H5tools_get_link_info(file2_id, obj2_name, &linkinfo2);
+ /* dangling link */
+ if (l_ret == 0)
+ {
+ if (options->no_dangle_links)
+ {
+ /* gangling link is error */
+ if(options->m_verbose)
+ parallel_print("Warning: <%s> is a dangling link.\n", obj2_name);
+ options->err_stat = 1;
+ goto out;
+ }
+ else
+ is_dangle_link2=1;
+ }
+ /* fail */
+ else if(l_ret < 0)
+ {
+ options->err_stat = 1;
+ goto out;
+ }
+ else /* OK */
+ {
+ /* target type for diff() */
+ obj2type = linkinfo2.trg_type;
+ }
+ }
+
+ /*------------------------------------------------------------
+ * External links
+ *------------------------------------------------------------*/
+
+ /*--------------------------------
+ * if object1 is external link */
+ if (obj1type == H5TRAV_TYPE_UDLINK)
+ {
+ /* get type and name of target object */
+ l_ret = H5tools_get_link_info(file1_id, obj1_name, &linkinfo1);
+ /* dangling link */
+ if (l_ret == 0)
+ {
+ if (options->no_dangle_links)
+ {
+ /* gangling link is error */
+ if(options->m_verbose)
+ parallel_print("Warning: <%s> is a dangling link.\n", obj1_name);
+ options->err_stat = 1;
+ goto out;
+ }
+ else
+ is_dangle_link1 = 1;
+ }
+ /* fail */
+ else if(l_ret < 0)
+ {
+ options->err_stat = 1;
+ goto out;
+ }
+ else /* OK */
+ {
+ /* for external link */
+ if(linkinfo1.linfo.type == H5L_TYPE_EXTERNAL)
+ obj1type = linkinfo1.trg_type;
+ }
+ }
+
+ /*--------------------------------
+ * if object2 is external link */
+ if (obj2type == H5TRAV_TYPE_UDLINK)
+ {
+ /* get type and name of target object */
+ l_ret = H5tools_get_link_info(file2_id, obj2_name, &linkinfo2);
+ /* dangling link */
+ if (l_ret == 0)
+ {
+ if (options->no_dangle_links)
+ {
+ /* gangling link is error */
+ if(options->m_verbose)
+ parallel_print("Warning: <%s> is a dangling link.\n", obj2_name);
+ options->err_stat = 1;
+ goto out;
+ }
+ else
+ is_dangle_link2 = 1;
+ }
+ /* fail */
+ else if(l_ret < 0)
+ {
+ options->err_stat = 1;
+ goto out;
+ }
+ else /* OK */
+ {
+ /* for external link */
+ if(linkinfo2.linfo.type == H5L_TYPE_EXTERNAL)
+ obj2type = linkinfo2.trg_type;
+ }
+ }
+ /* found dangling link */
+ if (is_dangle_link1 || is_dangle_link2)
+ goto out;
+ } /* end of follow_links */
+
/* objects are not the same type */
- if (info1->paths[i].type != info2->paths[j].type)
+ if (obj1type != obj2type)
{
if (options->m_verbose||options->m_list_not_cmp)
{
parallel_print("<%s> is of type %s and <%s> is of type %s\n",
- obj1_name, get_type(info1->paths[i].type), obj2_name,
- get_type(info2->paths[j].type));
+ obj1_name, get_type(obj1type),
+ obj2_name, get_type(obj2type));
}
options->not_cmp=1;
- return 0;
+ goto out;
+ }
+
+ nfound = diff(file1_id, obj1_name,
+ file2_id, obj2_name,
+ options, obj1type);
+
+out:
+ /*-------------------------------
+ * handle dangling link(s) */
+ /* both obj1 and obj2 are dangling links */
+ if(is_dangle_link1 && is_dangle_link2)
+ {
+ if(print_objname(options, nfound))
+ {
+ do_print_objname("dangling link", obj1_name, obj2_name);
+ print_found(nfound);
+ }
+ }
+ /* obj1 is dangling link */
+ else if (is_dangle_link1)
+ {
+ if(options->m_verbose)
+ parallel_print("obj1 <%s> is a dangling link.\n", obj1_name);
+ nfound++;
+ if(print_objname(options, nfound))
+ print_found(nfound);
+ }
+ /* obj2 is dangling link */
+ else if (is_dangle_link2)
+ {
+ if(options->m_verbose)
+ parallel_print("obj2 <%s> is a dangling link.\n", obj2_name);
+ nfound++;
+ if(print_objname(options, nfound))
+ print_found(nfound);
}
- nfound = diff(file1_id,
- obj1_name,
- file2_id,
- obj2_name,
- options,
- info1->paths[i].type);
+ /* free link info buffer */
+ if (linkinfo1.trg_path)
+ HDfree(linkinfo1.trg_path);
+ if (linkinfo2.trg_path)
+ HDfree(linkinfo2.trg_path);
return nfound;
}
@@ -889,9 +1304,10 @@ hsize_t diff_compare(hid_t file1_id,
* Return: Number of differences found
*
* Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
- *
* Date: May 9, 2003
*
+ * Programmer: Jonathan Kim
+ * - add following links feature (Feb 11,2010)
*-------------------------------------------------------------------------
*/
@@ -907,13 +1323,28 @@ hsize_t diff(hid_t file1_id,
hid_t grp1_id = (-1);
hid_t grp2_id = (-1);
int ret;
+ int is_dangle_link1 = 0;
+ int is_dangle_link2 = 0;
hsize_t nfound = 0;
+
+ /* to get link info */
+ h5tool_link_info_t linkinfo1;
+ h5tool_link_info_t linkinfo2;
+
+ /*init link info struct */
+ HDmemset(&linkinfo1,0,sizeof(h5tool_link_info_t));
+ HDmemset(&linkinfo2,0,sizeof(h5tool_link_info_t));
+
+ /* pass how to handle printing warnings to linkinfo option */
+ if(print_warn(options))
+ linkinfo1.opt.msg_mode = linkinfo2.opt.msg_mode = 1;
+
switch(type)
{
- /*-------------------------------------------------------------------------
+ /*----------------------------------------------------------------------
* H5TRAV_TYPE_DATASET
- *-------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
case H5TRAV_TYPE_DATASET:
/* verbose (-v) and report (-r) mode */
@@ -932,18 +1363,18 @@ hsize_t diff(hid_t file1_id,
else
{
nfound = diff_dataset(file1_id, file2_id, path1, path2, options);
- /* not comparable, no display the different number */
+ /* print info if compatible and difference found */
if (!options->not_cmp && nfound)
{
do_print_objname("dataset", path1, path2);
- print_found(nfound);
+ print_found(nfound);
}
}
break;
- /*-------------------------------------------------------------------------
+ /*----------------------------------------------------------------------
* H5TRAV_TYPE_NAMED_DATATYPE
- *-------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
case H5TRAV_TYPE_NAMED_DATATYPE:
if((type1_id = H5Topen2(file1_id, path1, H5P_DEFAULT)) < 0)
@@ -964,10 +1395,11 @@ hsize_t diff(hid_t file1_id,
if(options->m_verbose)
print_found(nfound);
- /*-------------------------------------------------------------------------
+ /*-----------------------------------------------------------------
* compare attributes
- * the if condition refers to cases when the dataset is a referenced object
- *-------------------------------------------------------------------------
+ * the if condition refers to cases when the dataset is a
+ * referenced object
+ *-----------------------------------------------------------------
*/
if(path1)
nfound += diff_attr(type1_id, type2_id, path1, path2, options);
@@ -978,9 +1410,9 @@ hsize_t diff(hid_t file1_id,
goto out;
break;
- /*-------------------------------------------------------------------------
+ /*----------------------------------------------------------------------
* H5TRAV_TYPE_GROUP
- *-------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
case H5TRAV_TYPE_GROUP:
ret = HDstrcmp(path1, path2);
@@ -1000,10 +1432,11 @@ hsize_t diff(hid_t file1_id,
if((grp2_id = H5Gopen2(file2_id, path2, H5P_DEFAULT)) < 0)
goto out;
- /*-------------------------------------------------------------------------
+ /*-----------------------------------------------------------------
* compare attributes
- * the if condition refers to cases when the dataset is a referenced object
- *-------------------------------------------------------------------------
+ * the if condition refers to cases when the dataset is a
+ * referenced object
+ *-----------------------------------------------------------------
*/
if(path1)
nfound += diff_attr(grp1_id, grp2_id, path1, path2, options);
@@ -1015,93 +1448,180 @@ hsize_t diff(hid_t file1_id,
break;
- /*-------------------------------------------------------------------------
+ /*----------------------------------------------------------------------
* H5TRAV_TYPE_LINK
- *-------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
case H5TRAV_TYPE_LINK:
{
- H5L_info_t li1, li2;
- char *buf1, *buf2;
-
- if(H5Lget_info(file1_id, path1, &li1, H5P_DEFAULT) < 0)
- goto out;
- if(H5Lget_info(file2_id, path2, &li2, H5P_DEFAULT) < 0)
+ /* get type and name of target object */
+ ret = H5tools_get_link_info(file1_id, path1, &linkinfo1);
+ /* dangling link */
+ if (ret == 0)
+ {
+ if (options->no_dangle_links)
+ {
+ /* gangling link is error */
+ if(options->m_verbose)
+ parallel_print("Warning: <%s> is a dangling link.\n", path1);
+ goto out;
+ }
+ else
+ is_dangle_link1 = 1;
+ }
+ else if (ret < 0)
goto out;
- buf1 = HDmalloc(li1.u.val_size);
- buf2 = HDmalloc(li2.u.val_size);
-
- if(H5Lget_val(file1_id, path1, buf1, li1.u.val_size, H5P_DEFAULT) < 0)
- goto out;
- if(H5Lget_val(file2_id, path2, buf2, li2.u.val_size, H5P_DEFAULT) < 0)
+ /* get type and name of target object */
+ ret = H5tools_get_link_info(file2_id, path2, &linkinfo2);
+ /* dangling link */
+ if (ret == 0)
+ {
+ if (options->no_dangle_links)
+ {
+ /* gangling link is error */
+ if(options->m_verbose)
+ parallel_print("Warning: <%s> is a dangling link.\n", path2);
+ goto out;
+ }
+ else
+ is_dangle_link2 = 1;
+ }
+ else if (ret < 0)
goto out;
+
+
+ /* found dangling link */
+ if (is_dangle_link1 || is_dangle_link2)
+ goto out2;
- ret = HDstrcmp(buf1, buf2);
+ ret = HDstrcmp(linkinfo1.trg_path, linkinfo2.trg_path);
- /* if "buf1" != "buf2" then the links are "different" */
+ /* if the target link name is not same then the links are "different" */
nfound = (ret != 0) ? 1 : 0;
if(print_objname(options, nfound))
do_print_objname("link", path1, path2);
+ if (options->follow_links)
+ {
+ /* objects are not the same type */
+ if (linkinfo1.trg_type != linkinfo2.trg_type)
+ {
+ if (options->m_verbose||options->m_list_not_cmp)
+ {
+ parallel_print("<%s> is of type %s and <%s> is of type %s\n", path1, get_type(linkinfo1.trg_type), path2, get_type(linkinfo2.trg_type));
+ }
+ options->not_cmp=1;
+ goto out;
+ }
+
+ /* call self to compare target object */
+ nfound += diff(file1_id, path1,
+ file2_id, path2,
+ options, linkinfo1.trg_type);
+ }
+
/* always print the number of differences found in verbose mode */
if(options->m_verbose)
print_found(nfound);
- HDfree(buf1);
- HDfree(buf2);
+ /* free link info buffer */
+ HDfree(linkinfo1.trg_path);
+ HDfree(linkinfo2.trg_path);
}
break;
- /*-------------------------------------------------------------------------
+ /*----------------------------------------------------------------------
* H5TRAV_TYPE_UDLINK
- *-------------------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
case H5TRAV_TYPE_UDLINK:
{
- H5L_info_t li1, li2;
-
- if(H5Lget_info(file1_id, path1, &li1, H5P_DEFAULT) < 0)
- goto out;
- if(H5Lget_info(file2_id, path2, &li2, H5P_DEFAULT) < 0)
+ /* get type and name of target object */
+ ret = H5tools_get_link_info(file1_id, path1, &linkinfo1);
+ /* dangling link */
+ if (ret == 0)
+ {
+ if (options->no_dangle_links)
+ {
+ /* gangling link is error */
+ if(options->m_verbose)
+ parallel_print("Warning: <%s> is a dangling link.\n", path1);
+ goto out;
+ }
+ else
+ is_dangle_link1=1;
+ }
+ else if (ret < 0)
goto out;
- /* Only external links will have a query function registered */
- if(li1.type == H5L_TYPE_EXTERNAL && li2.type == H5L_TYPE_EXTERNAL) {
- char *buf1, *buf2;
-
- buf1 = HDmalloc(li1.u.val_size);
- buf2 = HDmalloc(li2.u.val_size);
-
- if(H5Lget_val(file1_id, path1, buf1, li1.u.val_size, H5P_DEFAULT) < 0) {
- HDfree(buf1);
- HDfree(buf2);
- goto out;
- } /* end if */
- if(H5Lget_val(file2_id, path2, buf2, li2.u.val_size, H5P_DEFAULT) < 0) {
- HDfree(buf1);
- HDfree(buf2);
+ /* get type and name of target object */
+ ret = H5tools_get_link_info(file2_id, path2, &linkinfo2);
+ /* dangling link */
+ if (ret == 0)
+ {
+ if (options->no_dangle_links)
+ {
+ /* gangling link is error */
+ if(options->m_verbose)
+ parallel_print("Warning: <%s> is a dangling link.\n", path2);
goto out;
- } /* end if */
+ }
+ else
+ is_dangle_link2=1;
+ }
+ else if (ret < 0)
+ goto out;
+
+ /* found dangling link */
+ if (is_dangle_link1 || is_dangle_link2)
+ goto out2;
+ /* Only external links will have a query function registered */
+ if(linkinfo1.linfo.type == H5L_TYPE_EXTERNAL && linkinfo2.linfo.type == H5L_TYPE_EXTERNAL)
+ {
/* If the buffers are the same size, compare them */
- if(li1.u.val_size == li2.u.val_size) {
- ret = HDmemcmp(buf1, buf2, li1.u.val_size);
+ if(linkinfo1.linfo.u.val_size == linkinfo2.linfo.u.val_size)
+ {
+ ret = HDmemcmp(linkinfo1.trg_path, linkinfo2.trg_path, linkinfo1.linfo.u.val_size);
}
else
ret = 1;
- /* if "buf1" != "buf2" then the links are "different" */
+ /* if "linkinfo1.trg_path" != "linkinfo2.trg_path" then the links
+ * are "different" extlinkinfo#.path is combination string of
+ * file_name and obj_name
+ */
nfound = (ret != 0) ? 1 : 0;
if(print_objname(options, nfound))
do_print_objname("external link", path1, path2);
- HDfree(buf1);
- HDfree(buf2);
+ if (options->follow_links)
+ {
+ /* objects are not the same type */
+ if (linkinfo1.trg_type != linkinfo2.trg_type)
+ {
+ if (options->m_verbose||options->m_list_not_cmp)
+ {
+ parallel_print("<%s> is of type %s and <%s> is of type %s\n", path1, get_type(linkinfo1.trg_type), path2, get_type(linkinfo2.trg_type));
+ }
+ options->not_cmp=1;
+ goto out;
+ }
+
+ nfound = diff(file1_id, path1,
+ file2_id, path2,
+ options, linkinfo1.trg_type);
+ }
+
+ /* free link info buffer */
+ HDfree(linkinfo1.trg_path);
+ HDfree(linkinfo2.trg_path);
} /* end if */
- else {
+ else
+ {
/* If one or both of these links isn't an external link, we can only
* compare information from H5Lget_info since we don't have a query
* function registered for them.
@@ -1109,7 +1629,8 @@ hsize_t diff(hid_t file1_id,
* If the link classes or the buffer length are not the
* same, the links are "different"
*/
- if((li1.type != li2.type) || (li1.u.val_size != li2.u.val_size))
+ if((linkinfo1.linfo.type != linkinfo2.linfo.type) ||
+ (linkinfo1.linfo.u.val_size != linkinfo2.linfo.u.val_size))
nfound = 1;
else
nfound = 0;
@@ -1137,6 +1658,44 @@ hsize_t diff(hid_t file1_id,
out:
options->err_stat = 1;
+out2:
+ /*-----------------------------------
+ * handle dangling link(s)
+ */
+ /* both path1 and path2 are dangling links */
+ if(is_dangle_link1 && is_dangle_link2)
+ {
+ if(print_objname(options, nfound))
+ {
+ do_print_objname("dangling link", path1, path2);
+ print_found(nfound);
+ }
+ }
+ /* path1 is dangling link */
+ else if (is_dangle_link1)
+ {
+ if(options->m_verbose)
+ parallel_print("obj1 <%s> is a dangling link.\n", path1);
+ nfound++;
+ if(print_objname(options, nfound))
+ print_found(nfound);
+ }
+ /* path2 is dangling link */
+ else if (is_dangle_link2)
+ {
+ if(options->m_verbose)
+ parallel_print("obj2 <%s> is a dangling link.\n", path2);
+ nfound++;
+ if(print_objname(options, nfound))
+ print_found(nfound);
+ }
+
+ /* free link info buffer */
+ if (linkinfo1.trg_path)
+ HDfree(linkinfo1.trg_path);
+ if (linkinfo2.trg_path)
+ HDfree(linkinfo2.trg_path);
+
/* close */
/* disable error reporting */
H5E_BEGIN_TRY {