diff options
Diffstat (limited to 'tools/lib/h5diff.c')
-rw-r--r-- | tools/lib/h5diff.c | 835 |
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 { |