diff options
author | Jonathan Kim <jkm@hdfgroup.org> | 2010-01-25 21:43:48 (GMT) |
---|---|---|
committer | Jonathan Kim <jkm@hdfgroup.org> | 2010-01-25 21:43:48 (GMT) |
commit | 79cd5838d1fb36b3b5385a8f3741fc33a53537d2 (patch) | |
tree | 4c2d0e6e8e9fa2f675891283f2f9b2f636c61c61 | |
parent | bb25c85e794449d3bf59d8811e53288569161790 (diff) | |
download | hdf5-79cd5838d1fb36b3b5385a8f3741fc33a53537d2.zip hdf5-79cd5838d1fb36b3b5385a8f3741fc33a53537d2.tar.gz hdf5-79cd5838d1fb36b3b5385a8f3741fc33a53537d2.tar.bz2 |
[svn-r18164] Purpose:
Add a feature to compare through links. Relate to bugzilla report 1754.
Description:
Currently, h5diff command only compares the name(path) of target object
not the actual data. With this feature, h5diff will go through the link(s)
and figure out the actual object at the end of the link and compare data
if exist. Internally we have hard-link, soft-link, external-link (as part
of user_defined-link). This feature will provide a user transparent
experience when comparing link objects as the user can specify any of
those 3 type of links to be compared in any combination.
Tested on Jam.
-rw-r--r-- | tools/h5diff/h5diff_common.c | 7 | ||||
-rw-r--r-- | tools/lib/h5diff.c | 625 | ||||
-rw-r--r-- | tools/lib/h5diff.h | 1 |
3 files changed, 593 insertions, 40 deletions
diff --git a/tools/h5diff/h5diff_common.c b/tools/h5diff/h5diff_common.c index 3403935..64b0097 100644 --- a/tools/h5diff/h5diff_common.c +++ b/tools/h5diff/h5diff_common.c @@ -31,7 +31,7 @@ const char *progname = "h5diff"; * Command-line options: The user can specify short or long-named * parameters. */ -static const char *s_opts = "hVrvqn:d:p:Nc"; +static const char *s_opts = "hVrvqn:d:p:Ncl"; static struct long_options l_opts[] = { { "help", no_arg, 'h' }, { "version", no_arg, 'V' }, @@ -44,6 +44,7 @@ static struct long_options l_opts[] = { { "nan", no_arg, 'N' }, { "compare", no_arg, 'c' }, { "use-system-epsilon", no_arg, 'e' }, + { "link-follow", no_arg, 'l' }, { NULL, 0, '\0' } }; @@ -100,6 +101,9 @@ void parse_command_line(int argc, case 'r': options->m_report = 1; break; + case 'l': + options->linkfollow = 1; + break; case 'd': options->d=1; @@ -360,6 +364,7 @@ void usage(void) printf(" -r, --report Report mode. Print differences\n"); printf(" -v, --verbose Verbose mode. Print differences, list of objects\n"); printf(" -q, --quiet Quiet mode. Do not do output\n"); + printf(" -l, --link-follow Follow link(s)\n"); printf(" -c, --compare List objects that are not comparable\n"); printf(" -N, --nan Avoid NaNs detection\n"); printf(" -n C, --count=C Print differences up to C number, C is a positive integer.\n"); diff --git a/tools/lib/h5diff.c b/tools/lib/h5diff.c index ad42a94..1615b8c 100644 --- a/tools/lib/h5diff.c +++ b/tools/lib/h5diff.c @@ -20,6 +20,31 @@ #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 mode; +} h5tool_opt_t; + +/* To return link's target info + * Functions: + * H5tools_get_softlink_target_info() + * H5tools_get_extlink_target_info() + * Note: this may be move to h5tools code if used by other tools + */ +typedef struct { + const char *buf; /* IN: must be allocated along with H5Lget_info[li.u.val_size] */ + H5O_type_t type; /* OUT: target type */ + const char *path; /* OUT: target name */ + int is_path_malloced; /* VAR: Set to TRUE if path is malloced, so can be freed by checking this later. Needed when ext-link's target is soft-link */ + const char *extfile; /* OUT: if external link, external filename */ + hid_t extfile_id; /* OUT: if external link, external file id */ + h5tool_opt_t opt; /* IN: options */ +} h5tool_link_trg_info_t; /* * Debug printf macros. The prefix allows output filtering by test scripts. */ @@ -168,6 +193,236 @@ static void print_incoming_data(void) #endif /*------------------------------------------------------------------------- + * Function: H5tools_get_softlink_target_info + * + * Purpose: Get target object's type and path from soft-link path + * + * Patameters: + * - [IN] fileid : soft-link file id + * - [IN] linkpath : soft-link's source path + * - [IN] h5li : soft-link's source H5L_info_t + * - [OUT] trg_info: returning target info (refer to struct) + * + * Return: + * Success - 1 and return data via trg_info struct + * Fail - 0 + * + * Note: + * trg_info->buf must be allocated along with H5Lget_info[li.u.val_size] + * before passing to this function. + * + * Programmer: Jonathan Kim + * + * Date: Jan 20, 2010 + *-------------------------------------------------------------------------*/ +static int H5tools_get_softlink_target_info(hid_t file_id, const char * linkpath, H5L_info_t h5li, h5tool_link_trg_info_t *s_trg_info) +{ + H5O_type_t otype = H5O_TYPE_UNKNOWN; + H5O_info_t oinfo; + H5L_info_t linfo; + int ret = 0; /* init to fail */ + + + if((H5Lexists(file_id, linkpath, H5P_DEFAULT) <= 0)) + { + parallel_print("error: \"%s\" doesn't exist \n",linkpath); + goto out; + } + + if(H5Lget_info(file_id, linkpath, &linfo, H5P_DEFAULT) < 0) + { + parallel_print("error: unable to get link info from \"%s\"\n",linkpath); + goto out; + } + + /* get target name for softlink */ + if(linfo.type == H5L_TYPE_SOFT) + { + /* s_trg_info->buf should be already allocated out of + * this function and free when done */ + if(H5Lget_val(file_id, linkpath, s_trg_info->buf, h5li.u.val_size, H5P_DEFAULT) < 0) + { + parallel_print("error: unable to get link value from \"%s\"\n",s_trg_info->path); + goto out; + } + /* target path */ + s_trg_info->path = s_trg_info->buf; + } + /* if obj is hard link, will still get the type */ + else if (linfo.type == H5L_TYPE_HARD) + { + s_trg_info->path = linkpath; + } + + /*-------------------------------------------------------------- + * if link target or object exit, get type + */ + if((H5Lexists(file_id, s_trg_info->path, H5P_DEFAULT) == TRUE)) + { + + if(H5Oget_info_by_name(file_id, s_trg_info->path, &oinfo, H5P_DEFAULT) < 0) + { + parallel_print("error: unable to get object information for \"%s\"\n", s_trg_info->path); + goto out; + } + + otype = oinfo.type; + + + /* check unknown type */ + if (otype < H5O_TYPE_GROUP || otype >=H5O_TYPE_NTYPES) + { + parallel_print("<%s> is unknown type\n", s_trg_info->path); + goto out; + } + } + else + { + parallel_print("error: \"%s\" doesn't exist \n", s_trg_info->path); + goto out; + } + + /* set target obj type to return */ + s_trg_info->type = otype; + + /* succeed */ + ret = 1; +out: + return ret; +} + +/*------------------------------------------------------------------------- + * Function: H5tools_get_extlink_target_info + * + * Purpose: Get target object's type, path, file_id and filename from + * external-link + * + * Patameters: + * - [IN] fileid : external-link source file-id + * - [IN] linkpath : external-link source path + * - [IN] h5li : external-link source H5L_info_t + * - [OUT] trg_info : returning target info (refer to struct) + * + * Return: + * Success - 1 and return data via trg_info struct + * Fail - 0 + * + * Note: + * - trg_info->buf must be allocated along with H5Lget_info[li.u.val_size] + * before passing to this function. + * - if target is soft-link, trg_info->path will be malloced. so check if + * trg_info->is_path_malloced==TRUE, then free trg_info->path along with freeing + * trg_info->buf outside of this function. + * + * Programmer: Jonathan Kim + * + * Date: Jan 20, 2010 + *-------------------------------------------------------------------------*/ +static int H5tools_get_extlink_target_info(hid_t fileid, const char *linkpath, H5L_info_t h5li, h5tool_link_trg_info_t *trg_info) +{ + + hid_t extfile_id; + const char *extlink_file; + const char *extlink_path; + h5tool_link_trg_info_t soft_trg_info; + H5L_info_t slinfo; + int ret=0; /* init to Fail */ + + /* init */ + HDmemset(&soft_trg_info, 0, sizeof(h5tool_link_trg_info_t)); + trg_info->type = H5O_TYPE_UNKNOWN; + + if(H5Lget_val(fileid, linkpath, trg_info->buf, h5li.u.val_size, H5P_DEFAULT) < 0) + { + parallel_print("error: unable to get link value from \"%s\"\n",linkpath); + goto out; + } + /*--------------------------------------- + * get target filename and object path + */ + if(H5Lunpack_elink_val(trg_info->buf, h5li.u.val_size, NULL, &extlink_file, &extlink_path)<0) + { + parallel_print("error: unable to unpack external link value\n"); + goto out; + } + + /* return target filename and obj path */ + trg_info->path = extlink_path; + trg_info->extfile = extlink_file; + + /* --------------------------------- + * get file id from external file + * mimicked from h5diff() for Parallel code + * , but not sure if it's needed + */ + H5E_BEGIN_TRY + { + /* open file */ + if((extfile_id = h5tools_fopen(extlink_file, H5F_ACC_RDONLY, H5P_DEFAULT, NULL, NULL, (size_t)0)) < 0) + { + parallel_print("error: <%s>: unable to open file\n", extlink_file); +#ifdef H5_HAVE_PARALLEL + if(g_Parallel) + /* Let tasks know that they won't be needed */ + phdiff_dismiss_workers(); +#endif + goto out; + } /* end if */ + } H5E_END_TRY; + + /* get external file id */ + trg_info->extfile_id = extfile_id; + + /* -------------------------------------------------- + * check if target is soft link, if so allocate buffer + */ + if((H5Lexists(trg_info->extfile_id, trg_info->path, H5P_DEFAULT) <= 0)) + { + parallel_print("error: \"%s\" doesn't exist \n", trg_info->path); + goto out; + } + if(H5Lget_info(trg_info->extfile_id, trg_info->path, &slinfo, H5P_DEFAULT) < 0) + { + parallel_print("error: unable to get link info from \"%s\"\n", trg_info->path); + goto out; + } + + /* if ext-link's target is soft-link */ + if(slinfo.type == H5L_TYPE_SOFT) + { + size_t bufsize = (h5li.u.val_size > slinfo.u.val_size)?h5li.u.val_size:slinfo.u.val_size; + soft_trg_info.buf = (char*)HDcalloc(bufsize, sizeof(char)); + HDassert(trg_info->path); + } + + /* get target obj type */ + if(H5tools_get_softlink_target_info(trg_info->extfile_id, trg_info->path, h5li, &soft_trg_info)==0) + { + parallel_print("error: unable to get link info from \"%s\"\n", trg_info->path); + goto out; + } + + /* target obj type */ + trg_info->type = soft_trg_info.type; + + /* if ext-link's target is soft-link */ + if(slinfo.type == H5L_TYPE_SOFT) + { + trg_info->path = HDstrdup(soft_trg_info.buf); + HDassert(trg_info->path); + /* set TRUE so this can be freed later */ + trg_info->is_path_malloced = TRUE; + } + + /* Success */ + ret=1; +out: + if(soft_trg_info.buf) + HDfree(soft_trg_info.buf); + + return ret; +} +/*------------------------------------------------------------------------- * Function: h5diff * * Purpose: public function, can be called in an application program. @@ -826,9 +1081,34 @@ hsize_t diff_compare(hid_t file1_id, int f1 = 0; int f2 = 0; hsize_t nfound = 0; + ssize_t i,j; + + /* local variables for diff() */ + hid_t l_fileid1=file1_id; + hid_t l_fileid2=file2_id; + h5trav_type_t obj1type, obj2type; + const char *obj1name, *obj2name; + + /* softlink info to get target name and type */ + h5tool_link_trg_info_t softlinkinfo1; + h5tool_link_trg_info_t softlinkinfo2; + + /* external link file id */ + hid_t extfile1_id = (-1); + hid_t extfile2_id = (-1); + h5tool_link_trg_info_t extlinkinfo1; + h5tool_link_trg_info_t extlinkinfo2; - ssize_t i = h5trav_getindex (info1, obj1_name); - ssize_t j = h5trav_getindex (info2, obj2_name); + /* init softlink info */ + HDmemset(&softlinkinfo1, 0, sizeof(h5tool_link_trg_info_t)); + HDmemset(&softlinkinfo2, 0, sizeof(h5tool_link_trg_info_t)); + + /* init external link info */ + HDmemset(&extlinkinfo1, 0, sizeof(h5tool_link_trg_info_t)); + HDmemset(&extlinkinfo2, 0, sizeof(h5tool_link_trg_info_t)); + + i = h5trav_getindex (info1, obj1_name); + j = h5trav_getindex (info2, obj2_name); if (i == -1) { @@ -849,28 +1129,206 @@ hsize_t diff_compare(hid_t file1_id, } /* use the name with "/" first, as obtained by iterator function */ - obj1_name = info1->paths[i].path; - obj2_name = info2->paths[j].path; + obj1name = info1->paths[i].path; + obj2name = info2->paths[j].path; + + obj1type = info1->paths[i].type; + obj2type = info2->paths[j].type; + /*----------------------------------------------------------------- + * follow link option, compare with target object + */ + if (options->linkfollow) + { + H5L_info_t li1, li2; + + /*------------------------------------------------------------ + * Soft links + *------------------------------------------------------------*/ + + /*------------------------ + * if object1 softlink + */ + if (obj1type == H5TRAV_TYPE_LINK) + { + if(H5Lget_info(file1_id, obj1_name, &li1, H5P_DEFAULT) < 0) + { + parallel_print("error: unable to get link info from \"%s\"\n",obj1_name); + goto out; + } + + softlinkinfo1.buf = (char*)HDcalloc(li1.u.val_size, sizeof(char)); + HDassert(softlinkinfo1.buf); + + /* get type and name of target object */ + if(H5tools_get_softlink_target_info(file1_id, obj1_name, li1, &softlinkinfo1)==0) + { + parallel_print("error: unable to get softlink info from \"%s\"\n",obj1_name); + goto out; + } + + /* set target name and type to pass diff() */ + obj1type = softlinkinfo1.type; + obj1name = softlinkinfo1.path; + } + + /*------------------------ + * if object2 is softlink + */ + if (obj2type == H5TRAV_TYPE_LINK) + { + if(H5Lget_info(file2_id, obj2_name, &li2, H5P_DEFAULT) < 0) + { + parallel_print("error: unable to get link info from \"%s\"\n",obj2_name); + goto out; + } + + + softlinkinfo2.buf = (char*)HDcalloc(li2.u.val_size, sizeof(char)); + HDassert(softlinkinfo2.buf); + + /* get type and name of target object */ + if(H5tools_get_softlink_target_info(file2_id, obj2_name, li2, &softlinkinfo2)==0) + { + parallel_print("error: unable to get softlink info from \"%s\"\n",obj2_name); + goto out; + } + + /* set target name and type to pass diff() */ + obj2type = softlinkinfo2.type; + obj2name = softlinkinfo2.path; + } + + /*------------------------------------------------------------ + * External links + *------------------------------------------------------------*/ + + /*------------------------------- + * if object1 is external link + */ + if (obj1type == H5TRAV_TYPE_UDLINK) + { + if(H5Lget_info(file1_id, obj1_name, &li1, H5P_DEFAULT) < 0) + { + parallel_print("error: unable to get link info from \"%s\"\n",obj1_name); + goto out; + } + + /* for external link */ + if(li1.type == H5L_TYPE_EXTERNAL) + { + extlinkinfo1.buf = (char*)HDcalloc(li1.u.val_size, sizeof(char)); + HDassert(extlinkinfo1.buf); + + /* get type and name of target object */ + if(H5tools_get_extlink_target_info(file1_id, obj1_name, li1, &extlinkinfo1)==0) + { + parallel_print("error: unable to get external link info from \"%s\"\n",obj1_name); + goto out; + } + + /* if valid actual object */ + if (extlinkinfo1.type < H5O_TYPE_GROUP || extlinkinfo1.type >= H5O_TYPE_NTYPES) + { + if (options->m_verbose) + { + parallel_print("<%s> is invaild type\n", obj1_name); + } + goto out; + } + + /* set target fileid, name and type to pass diff() */ + l_fileid1 = extlinkinfo1.extfile_id; + obj1name = extlinkinfo1.path; + obj1type = extlinkinfo1.type; + } + } + + /*------------------------------- + * if object2 is external link + */ + if (obj2type == H5TRAV_TYPE_UDLINK) + { + if(H5Lget_info(file2_id, obj2_name, &li2, H5P_DEFAULT) < 0) + { + parallel_print("error: unable to get link info from \"%s\"\n",obj2_name); + goto out; + } + /* for external link */ + if(li2.type == H5L_TYPE_EXTERNAL) + { + extlinkinfo2.buf = (char*)HDcalloc(li2.u.val_size, sizeof(char)); + HDassert(extlinkinfo2.buf); + + /* get type and name of target object */ + if(H5tools_get_extlink_target_info(file2_id, obj2_name, li2, &extlinkinfo2)==0) + { + parallel_print("error: unable to get external link info from \"%s\"\n",obj2_name); + goto out; + } + /* if valid actual object */ + if (extlinkinfo2.type < H5O_TYPE_GROUP || extlinkinfo2.type >= H5O_TYPE_NTYPES) + { + if (options->m_verbose) + { + parallel_print("<%s> is invaild type\n", obj2_name); + } + goto out; + } + + /* set target fileid, name and type to pass diff() */ + l_fileid2 = extlinkinfo2.extfile_id; + obj2name = extlinkinfo2.path; + obj2type = extlinkinfo2.type; + } + } + } /* end of linkfollow */ + /* 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)); + obj1name, get_type(obj1type), obj2name, + get_type(obj2type)); } options->not_cmp=1; - return 0; + goto out; } - nfound = diff(file1_id, - obj1_name, - file2_id, - obj2_name, - options, - info1->paths[i].type); + nfound = diff(l_fileid1, obj1name, + l_fileid2, obj2name, + options, obj1type); + +out: + /* free soft link buffer */ + if (softlinkinfo1.buf) + HDfree(softlinkinfo1.buf); + if (softlinkinfo2.buf) + HDfree(softlinkinfo2.buf); + /* free external link buffer */ + if (extlinkinfo1.buf); + { + HDfree(extlinkinfo1.buf); + /* case for ext-link's target is soft-link */ + if(extlinkinfo1.is_path_malloced) + HDfree(extlinkinfo1.path); + } + if (extlinkinfo2.buf); + { + HDfree(extlinkinfo2.buf); + /* case for ext-link's target is soft-link */ + if(extlinkinfo2.is_path_malloced) + HDfree(extlinkinfo2.path); + } + + /* close external file */ + H5E_BEGIN_TRY + { + H5Fclose(extfile1_id); + H5Fclose(extfile2_id); + } H5E_END_TRY; return nfound; } @@ -909,6 +1367,17 @@ hsize_t diff(hid_t file1_id, int ret; hsize_t nfound = 0; + char *extlinkbuf1=NULL; + char *extlinkbuf2=NULL; + + /* used in soft link case (H5TRAV_TYPE_LINK) */ + h5tool_link_trg_info_t softlinkinfo1; + h5tool_link_trg_info_t softlinkinfo2; + /*init */ + HDmemset(&softlinkinfo1,0,sizeof(h5tool_link_trg_info_t)); + HDmemset(&softlinkinfo2,0,sizeof(h5tool_link_trg_info_t)); + + switch(type) { /*------------------------------------------------------------------------- @@ -1022,35 +1491,66 @@ hsize_t diff(hid_t file1_id, case H5TRAV_TYPE_LINK: { H5L_info_t li1, li2; - char *buf1, *buf2; if(H5Lget_info(file1_id, path1, &li1, H5P_DEFAULT) < 0) + { + parallel_print("error: unable to get link info from \"%s\"\n", path1); goto out; + } if(H5Lget_info(file2_id, path2, &li2, H5P_DEFAULT) < 0) + { + parallel_print("error: unable to get link info from \"%s\"\n", path2); goto out; + } - buf1 = HDmalloc(li1.u.val_size); - buf2 = HDmalloc(li2.u.val_size); + softlinkinfo1.buf = (char*)HDcalloc(li1.u.val_size, sizeof(char)); + HDassert(softlinkinfo1.buf); + softlinkinfo2.buf = (char*)HDcalloc(li2.u.val_size, sizeof(char)); + HDassert(softlinkinfo2.buf); - if(H5Lget_val(file1_id, path1, buf1, li1.u.val_size, H5P_DEFAULT) < 0) + if(H5tools_get_softlink_target_info(file1_id,path1,li1,&softlinkinfo1)==0) + { + parallel_print("error: unable to get softlink info from \"%s\"\n", path1); goto out; - if(H5Lget_val(file2_id, path2, buf2, li2.u.val_size, H5P_DEFAULT) < 0) + } + if(H5tools_get_softlink_target_info(file2_id,path2,li2,&softlinkinfo2)==0) + { + parallel_print("error: unable to get softlink info from \"%s\"\n", path2); goto out; + } - ret = HDstrcmp(buf1, buf2); + ret = HDstrcmp(softlinkinfo1.path, softlinkinfo2.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->linkfollow) + { + /* objects are not the same type */ + if (softlinkinfo1.type != softlinkinfo2.type) + { + if (options->m_verbose||options->m_list_not_cmp) + { + parallel_print("<%s> is of type %d and <%s> is of type %d\n", softlinkinfo1.path, softlinkinfo1.type, softlinkinfo2.path, softlinkinfo2.type); + } + options->not_cmp=1; + goto out; + } + + nfound += diff(file1_id, softlinkinfo1.path, + file2_id, softlinkinfo2.path, + options, softlinkinfo1.type); + } + /* always print the number of differences found in verbose mode */ if(options->m_verbose) print_found(nfound); - HDfree(buf1); - HDfree(buf2); + HDfree(softlinkinfo1.buf); + HDfree(softlinkinfo2.buf); } break; @@ -1063,45 +1563,80 @@ hsize_t diff(hid_t file1_id, H5L_info_t li1, li2; if(H5Lget_info(file1_id, path1, &li1, H5P_DEFAULT) < 0) + { + parallel_print("error: unable to get udlink info from \"%s\"\n", path1); goto out; + } if(H5Lget_info(file2_id, path2, &li2, H5P_DEFAULT) < 0) + { + parallel_print("error: unable to get udlink info from \"%s\"\n", path2); 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; + if(li1.type == H5L_TYPE_EXTERNAL && li2.type == H5L_TYPE_EXTERNAL) + { - buf1 = HDmalloc(li1.u.val_size); - buf2 = HDmalloc(li2.u.val_size); + extlinkbuf1 = (char*)HDcalloc(li1.u.val_size, sizeof(char)); + HDassert(extlinkbuf1); + extlinkbuf2 = (char*)HDcalloc(li2.u.val_size, sizeof(char)); + HDassert(extlinkbuf2); - if(H5Lget_val(file1_id, path1, buf1, li1.u.val_size, H5P_DEFAULT) < 0) { - HDfree(buf1); - HDfree(buf2); + if(H5Lget_val(file1_id, path1, extlinkbuf1, li1.u.val_size, H5P_DEFAULT) < 0) + { + parallel_print("error: unable to get link value from \"%s\"\n",path1); goto out; } /* end if */ - if(H5Lget_val(file2_id, path2, buf2, li2.u.val_size, H5P_DEFAULT) < 0) { - HDfree(buf1); - HDfree(buf2); + if(H5Lget_val(file2_id, path2, extlinkbuf2, li2.u.val_size, H5P_DEFAULT) < 0) + { + parallel_print("error: unable to get link value from \"%s\"\n",path2); goto out; } /* end if */ /* 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(li1.u.val_size == li2.u.val_size) + { + ret = HDmemcmp(extlinkbuf1, extlinkbuf2, li1.u.val_size); } else ret = 1; - /* if "buf1" != "buf2" then the links are "different" */ + /* if "extlinkbuf1" != "extlinkbuf2" then the links are "different" */ nfound = (ret != 0) ? 1 : 0; if(print_objname(options, nfound)) do_print_objname("external link", path1, path2); - HDfree(buf1); - HDfree(buf2); + if (options->linkfollow) + { + const char *extlink_file1; + const char *extlink_path1; + const char *extlink_file2; + const char *extlink_path2; + + /* get file name and obj path */ + if(H5Lunpack_elink_val(extlinkbuf1, li1.u.val_size, NULL, &extlink_file1, &extlink_path1)<0) + { + parallel_print("error: unable to unpack external link value of obj1\n"); + goto out; + } + + /* get file name and obj path */ + if(H5Lunpack_elink_val(extlinkbuf2, li2.u.val_size, NULL, &extlink_file2, &extlink_path2)<0) + { + parallel_print("error: unable to unpack external link value of obj2\n"); + goto out; + } + + nfound = h5diff(extlink_file1, extlink_file2, + extlink_path1, extlink_path2, options); + } + + HDfree(extlinkbuf1); + HDfree(extlinkbuf2); } /* 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. @@ -1137,6 +1672,18 @@ hsize_t diff(hid_t file1_id, out: options->err_stat = 1; + /* free buf used for softlink */ + if (softlinkinfo1.buf) + HDfree(softlinkinfo1.buf); + if (softlinkinfo2.buf) + HDfree(softlinkinfo2.buf); + + /* free buf used for softlink */ + if (extlinkbuf1) + HDfree(extlinkbuf1); + if (extlinkbuf2) + HDfree(extlinkbuf2); + /* close */ /* disable error reporting */ H5E_BEGIN_TRY { diff --git a/tools/lib/h5diff.h b/tools/lib/h5diff.h index df264dd..090d3d9 100644 --- a/tools/lib/h5diff.h +++ b/tools/lib/h5diff.h @@ -35,6 +35,7 @@ typedef struct { double percent; /* relative error value */ int n; /* count, compare up to count */ hsize_t count; /* count value */ + int linkfollow; /* link follow*/ int err_stat; /* an error ocurred (1, error, 0, no error) */ int cmn_objs; /* do we have common objects */ int not_cmp; /* are the objects comparable */ |