1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Copyright by The HDF Group. *
3 * Copyright by the Board of Trustees of the University of Illinois. *
4 * All rights reserved. *
5 * *
6 * This file is part of HDF5. The full HDF5 copyright notice, including *
7 * terms governing use, modification, and redistribution, is contained in *
8 * the COPYING file, which can be found at the root of the source code *
9 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
10 * If you do not have access to either file, you may request a copy from *
11 * help@hdfgroup.org. *
12 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13
14 #include "H5private.h"
15 #include "h5tools.h"
16 #include "h5tools_utils.h"
17 #include "h5diff.h"
18
19 #define ATTR_NAME_MAX 255
20
21 typedef struct table_attr_t {
22 char *name;
23 unsigned exist[2];
24 } match_attr_t;
25
26 typedef struct table_attrs_t {
27 size_t size;
28 size_t nattrs;
29 size_t nattrs_only1;
30 size_t nattrs_only2;
31 match_attr_t *attrs;
32 } table_attrs_t;
33
34
35 /*-------------------------------------------------------------------------
36 * Function: table_attrs_init
37 *
38 * Purpose: Initialize the table
39 *
40 * Parameter:
41 * - tbl [OUT]
42 *
43 * Programmer: Jonathan Kim
44 *
45 * Date: March 15, 2011
46 *------------------------------------------------------------------------*/
table_attrs_init(table_attrs_t ** tbl)47 static void table_attrs_init(table_attrs_t **tbl)
48 {
49 table_attrs_t* table_attrs = (table_attrs_t*) HDmalloc(sizeof(table_attrs_t));
50
51 table_attrs->size = 0;
52 table_attrs->nattrs = 0;
53 table_attrs->nattrs_only1 = 0;
54 table_attrs->nattrs_only2 = 0;
55 table_attrs->attrs = NULL;
56
57 *tbl = table_attrs;
58 }
59
60 /*-------------------------------------------------------------------------
61 * Function: table_attrs_free
62 *
63 * Purpose: free given table
64 *
65 * Parameter:
66 * - table [IN]
67 *
68 * Programmer: Jonathan Kim
69 *
70 * Date: March 15, 2011
71 *------------------------------------------------------------------------*/
table_attrs_free(table_attrs_t * table)72 static void table_attrs_free( table_attrs_t *table )
73 {
74 unsigned int i;
75
76 if (table) {
77 if (table->attrs) {
78 for (i = 0; i < table->nattrs; i++) {
79 if (table->attrs[i].name) {
80 HDfree(table->attrs[i].name);
81 }
82 } /* end for */
83 HDfree(table->attrs);
84 table->attrs = NULL;
85 } /* end if */
86 HDfree(table);
87 table = NULL;
88 }
89 }
90
91 /*-------------------------------------------------------------------------
92 * Function: table_attr_mark_exist
93 *
94 * Purpose: mark given attribute name to table as sign of exist
95 *
96 * Parameter:
97 * - exist [IN]
98 * - name [IN] : attribute name
99 * - table [OUT]
100 *
101 * Programmer: Jonathan Kim
102 *
103 * Date: March 15, 2011
104 *------------------------------------------------------------------------*/
table_attr_mark_exist(unsigned * exist,char * name,table_attrs_t * table)105 static void table_attr_mark_exist(unsigned *exist, char *name, table_attrs_t *table)
106 {
107 if(table->nattrs == table->size) {
108 match_attr_t *new_attrs;
109
110 table->size = MAX(1, table->size * 2);
111 new_attrs = (match_attr_t *)HDrealloc(table->attrs, table->size * sizeof(match_attr_t));
112 if(new_attrs)
113 table->attrs = new_attrs;
114 } /* end if */
115
116 if(table->nattrs < table->size) {
117 size_t curr_val;
118
119 curr_val = table->nattrs;
120 table->attrs[curr_val].exist[0] = exist[0];
121 table->attrs[curr_val].exist[1] = exist[1];
122 if(name)
123 table->attrs[curr_val].name = (char *)HDstrdup(name);
124 table->nattrs++;
125 }
126 }
127
128 /*-------------------------------------------------------------------------
129 * Function: build_match_list_attrs
130 *
131 * Purpose: get list of matching attribute name from obj1 and obj2
132 *
133 * Note:
134 * Find common attribute; the algorithm for search is referred from
135 * build_match_list() in h5diff.c .
136 *
137 * Parameter:
138 * table_out [OUT] : return the list
139 *------------------------------------------------------------------------*/
build_match_list_attrs(hid_t loc1_id,hid_t loc2_id,table_attrs_t ** table_out,diff_opt_t * opts)140 static herr_t build_match_list_attrs(hid_t loc1_id, hid_t loc2_id, table_attrs_t ** table_out, diff_opt_t *opts)
141 {
142 int ret_value = 0;
143 H5O_info_t oinfo1, oinfo2; /* Object info */
144 hid_t attr1_id = -1; /* attr ID */
145 hid_t attr2_id = -1; /* attr ID */
146 size_t curr1 = 0;
147 size_t curr2 = 0;
148 unsigned infile[2];
149 char name1[ATTR_NAME_MAX];
150 char name2[ATTR_NAME_MAX];
151 int cmp;
152 unsigned i;
153 table_attrs_t *table_lp = NULL;
154
155 h5difftrace("build_match_list_attrs start\n");
156
157 if(H5Oget_info(loc1_id, &oinfo1) < 0)
158 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Oget_info first object failed");
159 if(H5Oget_info(loc2_id, &oinfo2) < 0)
160 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Oget_info second object failed");
161
162 table_attrs_init(&table_lp);
163 if (table_lp == NULL)
164 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "Table allocation failed");
165
166 /*--------------------------------------------------
167 * build the list
168 */
169 while(curr1 < oinfo1.num_attrs && curr2 < oinfo2.num_attrs) {
170 h5diffdebug3("build_match_list_attrs 1: %ld - %ld\n", curr1, oinfo1.num_attrs);
171 h5diffdebug3("build_match_list_attrs 2: %ld - %ld\n", curr2, oinfo2.num_attrs);
172
173 /*------------------
174 * open attribute1 */
175 if((attr1_id = H5Aopen_by_idx(loc1_id, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)curr1, H5P_DEFAULT, H5P_DEFAULT)) < 0)
176 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aopen_by_idx first attribute failed");
177 /* get name */
178 if(H5Aget_name(attr1_id, (size_t)ATTR_NAME_MAX, name1) < 0)
179 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aget_name first attribute failed");
180
181 /*------------------
182 * open attribute2 */
183 if((attr2_id = H5Aopen_by_idx(loc2_id, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)curr2, H5P_DEFAULT, H5P_DEFAULT)) < 0)
184 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aopen_by_idx second attribute failed");
185 /* get name */
186 if(H5Aget_name(attr2_id, (size_t)ATTR_NAME_MAX, name2) < 0)
187 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aget_name second attribute failed");
188
189 /* criteria is string compare */
190 cmp = HDstrcmp(name1, name2);
191
192 if(cmp == 0) {
193 infile[0] = 1;
194 infile[1] = 1;
195 table_attr_mark_exist(infile, name1, table_lp);
196 curr1++;
197 curr2++;
198 }
199 else if(cmp < 0) {
200 infile[0] = 1;
201 infile[1] = 0;
202 table_attr_mark_exist(infile, name1, table_lp);
203 table_lp->nattrs_only1++;
204 curr1++;
205 }
206 else {
207 infile[0] = 0;
208 infile[1] = 1;
209 table_attr_mark_exist(infile, name2, table_lp);
210 table_lp->nattrs_only2++;
211 curr2++;
212 }
213
214 /* close for next turn */
215 H5Aclose(attr1_id);
216 attr1_id = -1;
217 H5Aclose(attr2_id);
218 attr2_id = -1;
219 } /* end while */
220
221 /* list1 did not end */
222 infile[0] = 1;
223 infile[1] = 0;
224 while(curr1 < oinfo1.num_attrs) {
225 h5diffdebug3("build_match_list_attrs 1: %ld - %ld\n", curr1, oinfo1.num_attrs);
226
227 /*------------------
228 * open attribute1 */
229 if((attr1_id = H5Aopen_by_idx(loc1_id, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)curr1, H5P_DEFAULT, H5P_DEFAULT)) < 0)
230 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aopen_by_idx first attribute failed");
231 /* get name */
232 if(H5Aget_name(attr1_id, (size_t)ATTR_NAME_MAX, name1) < 0)
233 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aget_name first attribute failed");
234 h5diffdebug2("build_match_list_attrs #1 name - %s\n", name1);
235
236 table_attr_mark_exist(infile, name1, table_lp);
237 table_lp->nattrs_only1++;
238 curr1++;
239
240 /* close for next turn */
241 H5Aclose(attr1_id);
242 attr1_id = -1;
243 }
244
245 /* list2 did not end */
246 infile[0] = 0;
247 infile[1] = 1;
248 while(curr2 < oinfo2.num_attrs) {
249 h5diffdebug3("build_match_list_attrs 2: %ld - %ld\n", curr2, oinfo2.num_attrs);
250 /*------------------
251 * open attribute2 */
252 if((attr2_id = H5Aopen_by_idx(loc2_id, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)curr2, H5P_DEFAULT, H5P_DEFAULT)) < 0)
253 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aopen_by_idx second attribute failed");
254 /* get name */
255 if(H5Aget_name(attr2_id, (size_t)ATTR_NAME_MAX, name2) < 0)
256 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aget_name second attribute failed");
257 h5diffdebug2("build_match_list_attrs #2 name - %s\n", name2);
258
259 table_attr_mark_exist(infile, name2, table_lp);
260 table_lp->nattrs_only2++;
261 curr2++;
262
263 /* close for next turn */
264 H5Aclose(attr2_id);
265 attr2_id = -1;
266 }
267
268 /*------------------------------------------------------
269 * print the list
270 */
271 if(opts->m_verbose_level == 2) {
272 /* if '-v2' is detected */
273 parallel_print(" obj1 obj2\n");
274 parallel_print(" --------------------------------------\n");
275 for(i = 0; i < (unsigned int) table_lp->nattrs; i++) {
276 char c1, c2;
277 c1 = (table_lp->attrs[i].exist[0]) ? 'x' : ' ';
278 c2 = (table_lp->attrs[i].exist[1]) ? 'x' : ' ';
279 parallel_print("%5c %6c %-15s\n", c1, c2, table_lp->attrs[i].name);
280 } /* end for */
281 }
282
283 if(opts->m_verbose_level >= 1)
284 parallel_print("Attributes status: %d common, %d only in obj1, %d only in obj2\n",
285 table_lp->nattrs - table_lp->nattrs_only1 - table_lp->nattrs_only2,
286 table_lp->nattrs_only1, table_lp->nattrs_only2);
287
288 done:
289 *table_out = table_lp;
290
291 /* disable error reporting */
292 H5E_BEGIN_TRY {
293 H5Aclose(attr1_id);
294 H5Aclose(attr2_id);
295 } H5E_END_TRY;
296
297 h5diffdebug2("build_match_list_attrs end - errstat:%d\n", opts->err_stat);
298
299 return ret_value;
300 }
301
302 /*-------------------------------------------------------------------------
303 * Function: diff_attr
304 *
305 * Purpose: compare attributes located in LOC1_ID and LOC2_ID, which are
306 * obtained either from
307 * loc_id = H5Gopen2(fid, name, H5P_DEFAULT);
308 * loc_id = H5Dopen2(fid, name);
309 * loc_id = H5Topen2(fid, name, H5P_DEFAULT);
310 *
311 * Return: number of differences found
312 *-------------------------------------------------------------------------
313 */
314
diff_attr(hid_t loc1_id,hid_t loc2_id,const char * path1,const char * path2,diff_opt_t * opts)315 hsize_t diff_attr(hid_t loc1_id,
316 hid_t loc2_id,
317 const char *path1,
318 const char *path2,
319 diff_opt_t *opts)
320 {
321 int ret_value = opts->err_stat;
322 hid_t attr1_id = -1; /* attr ID */
323 hid_t attr2_id = -1; /* attr ID */
324 hid_t space1_id = -1; /* space ID */
325 hid_t space2_id = -1; /* space ID */
326 hid_t ftype1_id = -1; /* file data type ID */
327 hid_t ftype2_id = -1; /* file data type ID */
328 hid_t mtype1_id = -1; /* memory data type ID */
329 hid_t mtype2_id = -1; /* memory data type ID */
330 size_t msize1; /* memory size of memory type */
331 size_t msize2; /* memory size of memory type */
332 void *buf1 = NULL; /* data buffer */
333 void *buf2 = NULL; /* data buffer */
334 hbool_t buf1hasdata = FALSE; /* buffer has data */
335 hbool_t buf2hasdata = FALSE; /* buffer has data */
336 hsize_t nelmts1; /* number of elements in dataset */
337 int rank1; /* rank of dataset */
338 int rank2; /* rank of dataset */
339 hsize_t dims1[H5S_MAX_RANK]; /* dimensions of dataset */
340 hsize_t dims2[H5S_MAX_RANK]; /* dimensions of dataset */
341 char *name1 = NULL;
342 char *name2 = NULL;
343 char np1[512];
344 char np2[512];
345 unsigned u; /* Local index variable */
346 hsize_t nfound = 0;
347 hsize_t nfound_total = 0;
348 int j;
349
350 table_attrs_t *match_list_attrs = NULL;
351 h5difftrace("diff_attr start\n");
352
353 if(build_match_list_attrs(loc1_id, loc2_id, &match_list_attrs, opts) < 0) {
354 HGOTO_ERROR(1, H5E_tools_min_id_g, "build_match_list_attrs failed");
355 }
356 h5diffdebug2("build_match_list_attrs - errstat:%d\n", opts->err_stat);
357
358 /* if detect any unique extra attr */
359 if(match_list_attrs->nattrs_only1 || match_list_attrs->nattrs_only2) {
360 h5difftrace("diff_attr attributes only in one file\n");
361 /* exit will be 1 */
362 opts->contents = 0;
363 }
364 h5diffdebug2("match_list_attrs info - errstat:%d\n", opts->err_stat);
365
366 for(u = 0; u < (unsigned)match_list_attrs->nattrs; u++) {
367 h5diffdebug3("match_list_attrs loop[%d] - errstat:%d\n", u, opts->err_stat);
368 if((match_list_attrs->attrs[u].exist[0]) && (match_list_attrs->attrs[u].exist[1])) {
369 name1 = name2 = match_list_attrs->attrs[u].name;
370 h5diffdebug2("diff_attr name - %s\n", name1);
371
372 /*--------------
373 * attribute 1 */
374 if((attr1_id = H5Aopen(loc1_id, name1, H5P_DEFAULT)) < 0)
375 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aopen first attribute failed");
376
377 /*--------------
378 * attribute 2 */
379 if((attr2_id = H5Aopen(loc2_id, name2, H5P_DEFAULT)) < 0)
380 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aopen second attribute failed");
381
382 h5difftrace("diff_attr got attributes\n");
383 /* get the datatypes */
384 if((ftype1_id = H5Aget_type(attr1_id)) < 0)
385 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aget_type first attribute failed");
386 if((ftype2_id = H5Aget_type(attr2_id)) < 0)
387 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aget_type second attribute failed");
388
389 if((mtype1_id = H5Tget_native_type(ftype1_id, H5T_DIR_DEFAULT)) < 0)
390 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Tget_native_type first attribute ftype failed");
391 if((mtype2_id = H5Tget_native_type(ftype2_id, H5T_DIR_DEFAULT)) < 0)
392 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Tget_native_type second attribute ftype failed");
393 if((msize1 = H5Tget_size(mtype1_id)) == 0)
394 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Tget_size first attribute mtype failed");
395 if((msize2 = H5Tget_size(mtype2_id)) == 0)
396 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Tget_size second attribute mtype failed");
397
398 /* get the dataspace */
399 if((space1_id = H5Aget_space(attr1_id)) < 0)
400 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aget_space first attribute failed");
401 if((space2_id = H5Aget_space(attr2_id)) < 0)
402 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aget_space second attribute failed");
403
404 /* get dimensions */
405 if((rank1 = H5Sget_simple_extent_dims(space1_id, dims1, NULL)) < 0)
406 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Sget_simple_extent_dims first attribute failed");
407 if((rank2 = H5Sget_simple_extent_dims(space2_id, dims2, NULL)) < 0)
408 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Sget_simple_extent_dims second attribute failed");
409
410 /*----------------------------------------------------------------------
411 * check for comparable TYPE and SPACE
412 *----------------------------------------------------------------------
413 */
414
415 /* pass dims1 and dims2 for maxdims as well since attribute's maxdims
416 * are always same */
417 if(diff_can_type(ftype1_id, ftype2_id, rank1, rank2, dims1, dims2,
418 dims1, dims2, name1, name2, opts, 0) != 1) {
419 if(H5Tclose(ftype1_id) < 0)
420 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Tclose first attribute ftype failed");
421 if(H5Tclose(ftype2_id) < 0)
422 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Tclose second attribute ftype failed");
423 if(H5Sclose(space1_id) < 0)
424 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Sclose first attribute failed");
425 if(H5Sclose(space2_id) < 0)
426 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Sclose second attribute failed");
427 if(H5Aclose(attr1_id) < 0)
428 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aclose first attribute failed");
429 if(H5Aclose(attr2_id) < 0)
430 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aclose second attribute failed");
431 if(H5Tclose(mtype1_id) < 0)
432 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Tclose first attribute mtype failed");
433 if(H5Tclose(mtype2_id) < 0)
434 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Tclose second attribute mtype failed");
435
436 continue;
437 }
438
439 /*-----------------------------------------------------------------
440 * "upgrade" the smaller memory size
441 *------------------------------------------------------------------
442 */
443 if(FAIL == match_up_memsize(ftype1_id, ftype2_id, &mtype1_id,
444 &mtype2_id, &msize1, &msize2))
445 HGOTO_ERROR(1, H5E_tools_min_id_g, "match_up_memsize failed");
446
447 /*---------------------------------------------------------------------
448 * read
449 *----------------------------------------------------------------------
450 */
451 nelmts1 = 1;
452 for(j = 0; j < rank1; j++)
453 nelmts1 *= dims1[j];
454
455 buf1 = (void *)HDcalloc((size_t)(nelmts1), msize1);
456 buf2 = (void *)HDcalloc((size_t)(nelmts1), msize2);
457 if(buf1 == NULL || buf2 == NULL) {
458 parallel_print("cannot read into memory\n");
459 HGOTO_ERROR(1, H5E_tools_min_id_g, "buffer allocation failed");
460 }
461 if(H5Aread(attr1_id, mtype1_id, buf1) < 0) {
462 parallel_print("Failed reading attribute1 %s/%s\n", path1, name1);
463 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aget_type first attribute failed");
464 }
465 else
466 buf1hasdata = TRUE;
467
468 if(H5Aread(attr2_id, mtype2_id, buf2) < 0) {
469 parallel_print("Failed reading attribute2 %s/%s\n", path2, name2);
470 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aget_type second attribute failed");
471 }
472 else
473 buf2hasdata = TRUE;
474
475 /* format output string */
476 HDsnprintf(np1, sizeof(np1), "%s of <%s>", name1, path1);
477 HDsnprintf(np2, sizeof(np1), "%s of <%s>", name2, path2);
478
479 /*---------------------------------------------------------------------
480 * array compare
481 *----------------------------------------------------------------------
482 */
483
484 /* always print name */
485 /* verbose (-v) and report (-r) mode */
486 if(opts->m_verbose || opts->m_report) {
487 do_print_attrname("attribute", np1, np2);
488
489 nfound = diff_array(buf1, buf2, nelmts1, (hsize_t) 0, rank1,
490 dims1, opts, np1, np2, mtype1_id, attr1_id, attr2_id);
491 print_found(nfound);
492 }
493 /* quiet mode (-q), just count differences */
494 else if(opts->m_quiet) {
495 nfound = diff_array(buf1, buf2, nelmts1, (hsize_t) 0, rank1,
496 dims1, opts, np1, np2, mtype1_id, attr1_id, attr2_id);
497 }
498 /* the rest (-c, none, ...) */
499 else {
500 nfound = diff_array(buf1, buf2, nelmts1, (hsize_t) 0, rank1,
501 dims1, opts, np1, np2, mtype1_id, attr1_id, attr2_id);
502
503 /* print info if compatible and difference found */
504 if (nfound) {
505 do_print_attrname("attribute", np1, np2);
506 print_found(nfound);
507 } /* end if */
508 } /* end else */
509
510 /*----------------------------------------------------------------------
511 * close
512 *----------------------------------------------------------------------
513 */
514
515 /* Free buf1 and buf2, check both VLEN-data VLEN-string to reclaim any
516 * VLEN memory first */
517 if(TRUE == h5tools_detect_vlen(mtype1_id))
518 H5Dvlen_reclaim(mtype1_id, space1_id, H5P_DEFAULT, buf1);
519 HDfree(buf1);
520 buf1 = NULL;
521
522 if(TRUE == h5tools_detect_vlen(mtype2_id))
523 H5Dvlen_reclaim(mtype2_id, space2_id, H5P_DEFAULT, buf2);
524 HDfree(buf2);
525 buf2 = NULL;
526
527 if(H5Tclose(ftype1_id) < 0)
528 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aget_type first attribute failed");
529 if(H5Tclose(ftype2_id) < 0)
530 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aget_type second attribute failed");
531 if(H5Sclose(space1_id) < 0)
532 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aget_type first attribute failed");
533 if(H5Sclose(space2_id) < 0)
534 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aget_type second attribute failed");
535 if(H5Aclose(attr1_id) < 0)
536 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aget_type first attribute failed");
537 if(H5Aclose(attr2_id) < 0)
538 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Aget_type second attribute failed");
539 if(H5Tclose(mtype1_id) < 0)
540 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Tclose first attribute mtype failed");
541 if(H5Tclose(mtype2_id) < 0)
542 HGOTO_ERROR(1, H5E_tools_min_id_g, "H5Tclose second attribute mtype failed");
543
544 nfound_total += nfound;
545 }
546 } /* u */
547
548 done:
549 opts->err_stat = opts->err_stat | ret_value;
550
551 H5E_BEGIN_TRY {
552 if(buf1) {
553 if(buf1hasdata && TRUE == h5tools_detect_vlen(mtype1_id))
554 H5Dvlen_reclaim(mtype1_id, space1_id, H5P_DEFAULT, buf1);
555 HDfree(buf1);
556 } /* end if */
557 if(buf2) {
558 if(buf2hasdata && TRUE == h5tools_detect_vlen(mtype2_id))
559 H5Dvlen_reclaim(mtype2_id, space2_id, H5P_DEFAULT, buf2);
560 HDfree(buf2);
561 } /* end if */
562
563 table_attrs_free(match_list_attrs);
564
565 H5Tclose(ftype1_id);
566 H5Tclose(ftype2_id);
567 H5Tclose(mtype1_id);
568 H5Tclose(mtype2_id);
569 H5Sclose(space1_id);
570 H5Sclose(space2_id);
571 H5Aclose(attr1_id);
572 H5Aclose(attr2_id);
573 } H5E_END_TRY;
574
575 h5diffdebug2("diff_attr end - errstat:%d\n", opts->err_stat);
576 return nfound_total;
577 }
578
579