hdf5/tools/lib/h5diff.c
Pedro Vicente Nunes 8f65e4252d [svn-r7969] Purpose:
h5repack new features

Description:
addded the copy routines for hard links
changed the traversal structure to store information about the hard links
added tests

Solution:

Platforms tested:
linux
solaris
IRIX

Misc. update:
2003-12-18 11:18:09 -05:00

542 lines
14 KiB
C

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF5. The full HDF5 copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the files COPYING and Copyright.html. COPYING can be found at the root *
* of the source code distribution tree; Copyright.html can be found at the *
* root level of an installed copy of the electronic HDF5 document set and *
* is linked from the top-level documents page. It can also be found at *
* http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
* access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "h5diff.h"
#include "H5private.h"
#include <stdlib.h>
#include <assert.h>
/*-------------------------------------------------------------------------
* Function: h5diff
*
* Purpose: public function, can be called in an applicattion program.
* return differences between 2 HDF5 files
*
* Return: Number of differences found; -1 for error.
*
* Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
*
* Date: October 22, 2003
*
*-------------------------------------------------------------------------
*/
int h5diff(const char *fname1,
const char *fname2,
const char *objname1,
const char *objname2,
diff_opt_t *options)
{
int nobjects1, nobjects2;
trav_info_t *info1=NULL;
trav_info_t *info2=NULL;
hid_t file1_id, file2_id;
int nfound=0;
/*-------------------------------------------------------------------------
* open the files first; if they are not valid, no point in continuing
*-------------------------------------------------------------------------
*/
/* disable error reporting */
H5E_BEGIN_TRY {
/* Open the files */
if ((file1_id=H5Fopen(fname1,H5F_ACC_RDONLY,H5P_DEFAULT))<0 )
{
printf("h5diff: %s: No such file or directory\n", fname1 );
nfound = -1;
}
if ((file2_id=H5Fopen(fname2,H5F_ACC_RDONLY,H5P_DEFAULT))<0 )
{
printf("h5diff: %s: No such file or directory\n", fname2 );
nfound = -1;
}
/* enable error reporting */
} H5E_END_TRY;
if (nfound<0)
return -1;
/*-------------------------------------------------------------------------
* get the number of objects in the files
*-------------------------------------------------------------------------
*/
nobjects1 = h5trav_getinfo( file1_id, NULL );
nobjects2 = h5trav_getinfo( file2_id, NULL );
/*-------------------------------------------------------------------------
* get the list of objects in the files
*-------------------------------------------------------------------------
*/
info1 = (trav_info_t*) malloc( nobjects1 * sizeof(trav_info_t));
info2 = (trav_info_t*) malloc( nobjects2 * sizeof(trav_info_t));
if (info1==NULL || info2==NULL)
{
nfound=-1;
goto out;
}
h5trav_getinfo( file1_id, info1 );
h5trav_getinfo( file2_id, info2 );
/*-------------------------------------------------------------------------
* object name was supplied
*-------------------------------------------------------------------------
*/
if ( objname1 )
{
assert(objname2);
nfound=diff_compare(file1_id,fname1,objname1,nobjects1,info1,
file2_id,fname2,objname2,nobjects2,info2,options);
}
/*-------------------------------------------------------------------------
* compare all
*-------------------------------------------------------------------------
*/
else
{
nfound=diff_match(file1_id,nobjects1,info1,
file2_id,nobjects2,info2,options);
}
h5trav_freeinfo(info1,nobjects1);
h5trav_freeinfo(info2,nobjects2);
out:
/* close */
H5Fclose(file1_id);
H5Fclose(file2_id);
return nfound;
}
/*-------------------------------------------------------------------------
* Function: diff_match
*
* Purpose: Find common objects; the algorithm used for this search is the
* cosequential match algorithm and is described in
* Folk, Michael; Zoellick, Bill. (1992). File Structures. Addison-Wesley.
*
* Return: Number of differences found
*
* Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
*
* Date: May 9, 2003
*
*-------------------------------------------------------------------------
*/
int diff_match( hid_t file1_id,
int nobjects1,
trav_info_t *info1,
hid_t file2_id,
int nobjects2,
trav_info_t *info2,
diff_opt_t *options )
{
int more_names_exist = (nobjects1>0 && nobjects2>0) ? 1 : 0;
trav_table_t *table=NULL;
int cmp;
int curr1=0;
int curr2=0;
unsigned infile[2];
char c1, c2;
int nfound=0, i;
/*-------------------------------------------------------------------------
* build the list
*-------------------------------------------------------------------------
*/
trav_table_init( &table );
while ( more_names_exist )
{
/* criteria is string compare */
cmp = strcmp( info1[curr1].name, info2[curr2].name );
if ( cmp == 0 )
{
infile[0]=1; infile[1]=1;
trav_table_addflags(infile, info1[curr1].name, info1[curr1].type, table );
curr1++;
curr2++;
}
else if ( cmp < 0 )
{
infile[0]=1; infile[1]=0;
trav_table_addflags(infile, info1[curr1].name, info1[curr1].type, table );
curr1++;
}
else
{
infile[0]=0; infile[1]=1;
trav_table_addflags(infile, info2[curr2].name, info2[curr2].type, table );
curr2++;
}
more_names_exist = (curr1<nobjects1 && curr2<nobjects2) ? 1 : 0;
} /* end while */
/* list1 did not end */
if (curr1<nobjects1)
{
while ( curr1<nobjects1 )
{
infile[0]=1; infile[1]=0;
trav_table_addflags(infile, info1[curr1].name, info1[curr1].type, table );
curr1++;
}
}
/* list2 did not end */
if (curr2<nobjects2)
{
while ( curr2<nobjects2 )
{
infile[0]=0; infile[1]=1;
trav_table_addflags(infile, info2[curr2].name, info2[curr2].type, table );
curr2++;
}
}
/*-------------------------------------------------------------------------
* print the list
*-------------------------------------------------------------------------
*/
if (options->verbose)
{
printf("\n");
printf("file1 file2\n");
printf("---------------------------------------\n");
for (i = 0; i < table->nobjs; i++)
{
c1 = (table->objs[i].flags[0]) ? 'x' : ' ';
c2 = (table->objs[i].flags[1]) ? 'x' : ' ';
printf("%5c %6c %-15s\n", c1, c2, table->objs[i].name);
}
printf("\n");
}
/*-------------------------------------------------------------------------
* do the diff for common objects
*-------------------------------------------------------------------------
*/
for (i = 0; i < table->nobjs; i++)
{
if ( table->objs[i].flags[0] && table->objs[i].flags[1] )
nfound+=diff( file1_id,
table->objs[i].name,
file2_id,
table->objs[i].name,
options,
table->objs[i].type );
}
/* free table */
trav_table_free(table);
/*-------------------------------------------------------------------------
* do the diff for the root.
* this is a special case, we get an ID for the root group and call diff()
* with this ID; it compares only the root group attributes
*-------------------------------------------------------------------------
*/
nfound+=diff( file1_id,
"/",
file2_id,
"/",
options,
H5G_GROUP );
return nfound;
}
/*-------------------------------------------------------------------------
* Function: diff_compare
*
* Purpose: get objects from list, and check for the same type
*
* Return: Number of differences found
*
* Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
*
* Date: May 9, 2003
*
*-------------------------------------------------------------------------
*/
int diff_compare( hid_t file1_id,
const char *file1_name,
const char *obj1_name,
int nobjects1,
trav_info_t *info1,
hid_t file2_id,
const char *file2_name,
const char *obj2_name,
int nobjects2,
trav_info_t *info2,
diff_opt_t *options )
{
int f1=0, f2=0;
int nfound=0;
int i = h5trav_getindex( obj1_name, nobjects1, info1 );
int j = h5trav_getindex( obj2_name, nobjects2, info2 );
if ( i == -1 )
{
printf( "Object <%s> could not be found in <%s>\n", obj1_name, file1_name );
f1=1;
}
if ( j == -1 )
{
printf( "Object <%s> could not be found in <%s>\n", obj2_name, file2_name );
f2=1;
}
if ( f1 || f2 )
return -1;
/* use the name with "/" first, as obtained by iterator function */
obj1_name=info1[i].name;
obj2_name=info2[j].name;
/* objects are not the same type */
if ( info1[i].type != info2[j].type && options->verbose)
{
printf("Comparison not possible: <%s> is of type %s and <%s> is of type %s\n",
obj1_name, get_type(info1[i].type),
obj2_name, get_type(info2[j].type) );
return 1;
}
nfound=diff( file1_id, obj1_name, file2_id, obj2_name, options, info1[i].type );
return nfound;
}
/*-------------------------------------------------------------------------
* Function: diff
*
* Purpose: switch between types and choose the diff function
* TYPE is either
* H5G_LINK Object is a symbolic link
* H5G_GROUP Object is a group
* H5G_DATASET Object is a dataset
* H5G_TYPE Object is a named data type
*
* Return: Number of differences found
*
* Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
*
* Date: May 9, 2003
*
*-------------------------------------------------------------------------
*/
int diff( hid_t file1_id,
const char *path1,
hid_t file2_id,
const char *path2,
diff_opt_t *options,
H5G_obj_t type )
{
hid_t type1_id;
hid_t type2_id;
hid_t grp1_id;
hid_t grp2_id;
int ret;
H5G_stat_t sb1;
H5G_stat_t sb2;
char *buf1=NULL;
char *buf2=NULL;
int nfound=-1;
switch ( type )
{
/*-------------------------------------------------------------------------
* H5G_DATASET
*-------------------------------------------------------------------------
*/
case H5G_DATASET:
if (options->verbose)
printf( "Dataset: <%s> and <%s>\n",path1,path2);
nfound=diff_dataset(file1_id,file2_id,path1,path2,options);
break;
/*-------------------------------------------------------------------------
* H5G_TYPE
*-------------------------------------------------------------------------
*/
case H5G_TYPE:
if (options->verbose)
printf( "Datatype: <%s> and <%s>\n",path1,path2);
if ((type1_id = H5Topen(file1_id, path1))<0)
goto out;
if ((type2_id = H5Topen(file2_id, path2))<0)
goto out;
if ((ret = H5Tequal(type1_id,type2_id))<0)
goto out;
/* if H5Tequal is > 0 then the datatypes refer to the same datatype */
nfound = (ret>0) ? 0 : 1;
/*-------------------------------------------------------------------------
* compare attributes
* 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);
if ( H5Tclose(type1_id)<0)
goto out;
if ( H5Tclose(type2_id)<0)
goto out;
break;
/*-------------------------------------------------------------------------
* H5G_GROUP
*-------------------------------------------------------------------------
*/
case H5G_GROUP:
if (options->verbose)
printf( "Group: <%s> and <%s>\n",path1,path2);
if ((grp1_id = H5Gopen(file1_id, path1))<0)
goto out;
if ((grp2_id = H5Gopen(file2_id, path2))<0)
goto out;
ret = HDstrcmp(path1,path2);
/* if "path1" != "path2" then the groups are "different" */
nfound = (ret!=0) ? 1 : 0;
/*-------------------------------------------------------------------------
* compare attributes
* 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);
if ( H5Gclose(grp1_id)<0)
goto out;
if ( H5Gclose(grp2_id)<0)
goto out;
break;
/*-------------------------------------------------------------------------
* H5G_LINK
*-------------------------------------------------------------------------
*/
case H5G_LINK:
if (options->verbose)
printf( "Link: <%s> and <%s>\n",path1,path2);
if (H5Gget_objinfo(file1_id,path1,FALSE,&sb1)<0)
goto out;
if (H5Gget_objinfo(file1_id,path1,FALSE,&sb2)<0)
goto out;
buf1 = malloc(sb1.linklen);
buf2 = malloc(sb2.linklen);
if (H5Gget_linkval(file1_id,path1,sb1.linklen,buf1)<0)
goto out;
if (H5Gget_linkval(file2_id,path2,sb1.linklen,buf2)<0)
goto out;
ret = HDstrcmp(buf1,buf2);
/* if "buf1" != "buf2" then the links are "different" */
nfound = (ret!=0) ? 1 : 0;
if (buf1) {
free(buf1);
buf1=NULL;
}
if (buf2) {
free(buf2);
buf2=NULL;
}
break;
default:
nfound=0;
if (options->verbose) {
printf("Comparison not supported: <%s> and <%s> are of type %s\n",
path1, path2, get_type(type) );
}
break;
}
out:
/* close */
/* disable error reporting */
H5E_BEGIN_TRY {
H5Tclose(type1_id);
H5Tclose(type2_id);
H5Gclose(grp1_id);
H5Tclose(grp2_id);
/* enable error reporting */
} H5E_END_TRY;
if (buf1)
free(buf1);
if (buf2)
free(buf2);
return nfound;
}