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 "h5repack.h"
15 #include "h5diff.h"
16 #include "h5tools.h"
17
18
19 /*-------------------------------------------------------------------------
20 * local functions
21 *-------------------------------------------------------------------------
22 */
23
24 static const char* MapIdToName(hid_t refobj_id,trav_table_t *travt);
25 static int copy_refs_attr(hid_t loc_in, hid_t loc_out, pack_opt_t *options,
26 trav_table_t *travt, hid_t fidout);
27 static herr_t update_ref_value(hid_t obj_id, H5R_type_t ref_type, void *ref_in,
28 hid_t fid_out, void *ref_out, trav_table_t *travt);
29
30 /*-------------------------------------------------------------------------
31 * Function: do_copy_refobjs
32 *
33 * Purpose: duplicate all referenced HDF5 objects in the file
34 * and create hard links
35 *
36 * Return: 0, ok, -1 no
37 *-------------------------------------------------------------------------
38 */
39
do_copy_refobjs(hid_t fidin,hid_t fidout,trav_table_t * travt,pack_opt_t * options)40 int do_copy_refobjs(hid_t fidin,
41 hid_t fidout,
42 trav_table_t *travt,
43 pack_opt_t *options) /* repack options */
44 {
45 int ret_value = 0; /*no need to LEAVE() on ERROR: HERR_INIT(int, SUCCEED) */
46 hid_t grp_in = -1; /* read group ID */
47 hid_t grp_out = -1; /* write group ID */
48 hid_t dset_in = -1; /* read dataset ID */
49 hid_t dset_out = -1; /* write dataset ID */
50 hid_t type_in = -1; /* named type ID */
51 hid_t dcpl_id = -1; /* dataset creation property list ID */
52 hid_t space_id = -1; /* space ID */
53 hid_t ftype_id = -1; /* file data type ID */
54 hid_t mtype_id = -1; /* memory data type ID */
55 size_t msize; /* memory size of memory type */
56 hsize_t nelmts; /* number of elements in dataset */
57 int rank; /* rank of dataset */
58 hsize_t dims[H5S_MAX_RANK]; /* dimensions of dataset */
59 unsigned int i, j;
60 int k;
61 named_dt_t *named_dt_head = NULL; /* Pointer to the stack of named datatypes copied */
62
63 /*-------------------------------------------------------------------------
64 * browse
65 *-------------------------------------------------------------------------
66 */
67 for(i = 0; i < travt->nobjs; i++) {
68 switch(travt->objs[i].type) {
69 /*-------------------------------------------------------------------------
70 * H5TRAV_TYPE_GROUP
71 *-------------------------------------------------------------------------
72 */
73 case H5TRAV_TYPE_GROUP:
74 /*-------------------------------------------------------------------------
75 * copy referenced objects in attributes
76 *-------------------------------------------------------------------------
77 */
78 if((grp_out = H5Gopen2(fidout, travt->objs[i].name, H5P_DEFAULT)) < 0)
79 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gopen2 failed");
80
81 if((grp_in = H5Gopen2(fidin, travt->objs[i].name, H5P_DEFAULT)) < 0)
82 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gopen2 failed");
83
84 if(copy_refs_attr(grp_in, grp_out, options, travt, fidout) < 0)
85 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_refs_attr failed");
86
87 if(H5Gclose(grp_out) < 0)
88 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gclose failed");
89 if(H5Gclose(grp_in) < 0)
90 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gclose failed");
91
92 /*-------------------------------------------------------------------------
93 * check for hard links
94 *-------------------------------------------------------------------------
95 */
96 if(travt->objs[i].nlinks)
97 for(j = 0; j < travt->objs[i].nlinks; j++)
98 H5Lcreate_hard(fidout, travt->objs[i].name, H5L_SAME_LOC, travt->objs[i].links[j].new_name, H5P_DEFAULT, H5P_DEFAULT);
99 break;
100
101 /*-------------------------------------------------------------------------
102 * H5TRAV_TYPE_DATASET
103 *-------------------------------------------------------------------------
104 */
105 case H5TRAV_TYPE_DATASET:
106 if((dset_in = H5Dopen2(fidin, travt->objs[i].name, H5P_DEFAULT)) < 0)
107 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dopen2 failed");
108 if((space_id = H5Dget_space(dset_in)) < 0)
109 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_space failed");
110 if((ftype_id = H5Dget_type(dset_in)) < 0)
111 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_type failed");
112 if((dcpl_id = H5Dget_create_plist(dset_in)) < 0)
113 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_create_plist failed");
114 if((rank = H5Sget_simple_extent_ndims(space_id)) < 0)
115 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sget_simple_extent_ndims failed");
116 if(H5Sget_simple_extent_dims(space_id, dims, NULL) < 0)
117 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sget_simple_extent_dims failed");
118 nelmts = 1;
119 for(k = 0; k < rank; k++)
120 nelmts *= dims[k];
121
122 if((mtype_id = H5Tget_native_type(ftype_id, H5T_DIR_DEFAULT)) < 0)
123 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tget_native_type failed");
124
125 if((msize = H5Tget_size(mtype_id)) == 0)
126 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tget_size failed");
127
128 /*-------------------------------------------------------------------------
129 * check if the dataset creation property list has filters that
130 * are not registered in the current configuration
131 * 1) the external filters GZIP and SZIP might not be available
132 * 2) the internal filters might be turned off
133 *-------------------------------------------------------------------------
134 */
135 if(h5tools_canreadf(NULL, dcpl_id) == 1) {
136 /*-------------------------------------------------------------------------
137 * test for a valid output dataset
138 *-------------------------------------------------------------------------
139 */
140 dset_out = FAIL;
141
142 /*-------------------------------------------------------------------------
143 * object references are a special case
144 * we cannot just copy the buffers, but instead we recreate the reference
145 *-------------------------------------------------------------------------
146 */
147 if(H5Tequal(mtype_id, H5T_STD_REF_OBJ)) {
148 hid_t refobj_id = -1;
149 hobj_ref_t *refbuf = NULL; /* buffer for object references */
150 hobj_ref_t *buf = NULL;
151 const char* refname;
152 unsigned u;
153
154 /*-------------------------------------------------------------------------
155 * read to memory
156 *-------------------------------------------------------------------------
157 */
158 if(nelmts) {
159 buf = (hobj_ref_t *)HDmalloc((unsigned)(nelmts * msize));
160 if(buf==NULL) {
161 printf("cannot read into memory\n" );
162 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDmalloc failed");
163 } /* end if */
164 if(H5Dread(dset_in, mtype_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
165 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dread failed");
166
167 refbuf = (hobj_ref_t*) HDcalloc((unsigned)nelmts, msize);
168 if(refbuf == NULL){
169 printf("cannot allocate memory\n" );
170 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDcalloc failed");
171 } /* end if */
172 for(u = 0; u < nelmts; u++) {
173 H5E_BEGIN_TRY {
174 if((refobj_id = H5Rdereference(dset_in, H5R_OBJECT, &buf[u])) < 0)
175 continue;
176 } H5E_END_TRY;
177
178 /* get the name. a valid name could only occur
179 * in the second traversal of the file
180 */
181 if((refname = MapIdToName(refobj_id, travt)) != NULL) {
182 /* create the reference, -1 parameter for objects */
183 if(H5Rcreate(&refbuf[u], fidout, refname, H5R_OBJECT, (hid_t)-1) < 0)
184 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Rcreate failed");
185 if(options->verbose) {
186 printf(FORMAT_OBJ,"dset",travt->objs[i].name );
187 printf("object <%s> object reference created to <%s>\n",
188 travt->objs[i].name,
189 refname);
190 }
191 } /*refname*/
192 if (H5Oclose(refobj_id) < 0)
193 H5TOOLS_INFO(H5E_tools_min_id_g, "H5Oclose refob failed");
194 } /* u */
195 } /*nelmts*/
196
197 /*-------------------------------------------------------------------------
198 * create/write dataset/close
199 *-------------------------------------------------------------------------
200 */
201 if((dset_out = H5Dcreate2(fidout, travt->objs[i].name, mtype_id, space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT)) < 0)
202 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dcreate2 failed");
203 if(nelmts)
204 if(H5Dwrite(dset_out, mtype_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, refbuf) < 0)
205 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dwrite failed");
206
207 if(buf)
208 HDfree(buf);
209 if(refbuf)
210 HDfree(refbuf);
211
212 /*------------------------------------------------------
213 * copy attrs
214 *----------------------------------------------------*/
215 if(copy_attr(dset_in, dset_out, &named_dt_head, travt, options) < 0)
216 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_attr failed");
217 } /*H5T_STD_REF_OBJ*/
218
219 /*-------------------------------------------------------------------------
220 * dataset region references
221 *-------------------------------------------------------------------------
222 */
223 else if(H5Tequal(mtype_id, H5T_STD_REF_DSETREG)) {
224 hid_t refobj_id = -1;
225 hdset_reg_ref_t *refbuf = NULL; /* input buffer for region references */
226 hdset_reg_ref_t *buf = NULL; /* output buffer */
227 const char* refname;
228 unsigned u;
229
230 /*-------------------------------------------------------------------------
231 * read input to memory
232 *-------------------------------------------------------------------------
233 */
234 if(nelmts) {
235 buf = (hdset_reg_ref_t *)HDmalloc((unsigned)(nelmts * msize));
236 if(buf == NULL) {
237 printf("cannot read into memory\n");
238 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDmalloc failed");
239 } /* end if */
240 if(H5Dread(dset_in, mtype_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0)
241 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dread failed");
242
243 /*-------------------------------------------------------------------------
244 * create output
245 *-------------------------------------------------------------------------
246 */
247 refbuf = (hdset_reg_ref_t *)HDcalloc(sizeof(hdset_reg_ref_t), (size_t)nelmts); /*init to zero */
248 if(refbuf == NULL) {
249 printf("cannot allocate memory\n");
250 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDcalloc failed");
251 } /* end if */
252
253 for(u = 0; u < nelmts; u++) {
254 H5E_BEGIN_TRY {
255 if((refobj_id = H5Rdereference(dset_in, H5R_DATASET_REGION, &buf[u])) < 0)
256 continue;
257 } H5E_END_TRY;
258
259 /* get the name. a valid name could only occur
260 * in the second traversal of the file
261 */
262 if((refname = MapIdToName(refobj_id, travt)) != NULL) {
263 hid_t region_id = -1; /* region id of the referenced dataset */
264
265 if((region_id = H5Rget_region(dset_in, H5R_DATASET_REGION, &buf[u])) < 0)
266 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Rget_region failed");
267
268 /* create the reference, we need the space_id */
269 if(H5Rcreate(&refbuf[u], fidout, refname, H5R_DATASET_REGION, region_id) < 0)
270 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Rcreate failed");
271 if(H5Sclose(region_id) < 0)
272 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sclose failed");
273 if(options->verbose) {
274 printf(FORMAT_OBJ,"dset",travt->objs[i].name );
275 printf("object <%s> region reference created to <%s>\n",
276 travt->objs[i].name,
277 refname);
278 }
279 } /*refname*/
280 if (H5Oclose(refobj_id) < 0)
281 H5TOOLS_INFO(H5E_tools_min_id_g, "H5Oclose refobj_id failed");
282 } /* u */
283 } /*nelmts*/
284
285 /*-------------------------------------------------------------------------
286 * create/write dataset/close
287 *-------------------------------------------------------------------------
288 */
289 if((dset_out = H5Dcreate2(fidout, travt->objs[i].name, mtype_id, space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT)) < 0)
290 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dcreate2 failed");
291 if(nelmts)
292 if(H5Dwrite(dset_out, mtype_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, refbuf) < 0)
293 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dwrite failed");
294
295 if(buf)
296 HDfree(buf);
297 if(refbuf)
298 HDfree(refbuf);
299
300 /*-----------------------------------------------------
301 * copy attrs
302 *----------------------------------------------------*/
303 if(copy_attr(dset_in, dset_out, &named_dt_head, travt, options) < 0)
304 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_attr failed");
305 } /* H5T_STD_REF_DSETREG */
306 /*-------------------------------------------------------------------------
307 * not references, open previously created object in 1st traversal
308 *-------------------------------------------------------------------------
309 */
310 else {
311 if((dset_out = H5Dopen2(fidout, travt->objs[i].name, H5P_DEFAULT)) < 0)
312 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dopen2 failed");
313 } /* end else */
314
315 /*-------------------------------------------------------------------------
316 * copy referenced objects in attributes
317 *-------------------------------------------------------------------------
318 */
319 if(copy_refs_attr(dset_in, dset_out, options, travt, fidout) < 0)
320 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_refs_attr failed");
321
322 /*-------------------------------------------------------------------------
323 * check for hard links
324 *-------------------------------------------------------------------------
325 */
326 if(travt->objs[i].nlinks)
327 for(j = 0; j < travt->objs[i].nlinks; j++)
328 H5Lcreate_hard(fidout, travt->objs[i].name, H5L_SAME_LOC, travt->objs[i].links[j].new_name, H5P_DEFAULT, H5P_DEFAULT);
329
330 if(H5Dclose(dset_out) < 0)
331 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dclose failed");
332 } /*can_read*/
333
334 /*-------------------------------------------------------------------------
335 * close
336 *-------------------------------------------------------------------------
337 */
338 if(H5Tclose(ftype_id) < 0)
339 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed");
340 if(H5Tclose(mtype_id) < 0)
341 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed");
342 if(H5Pclose(dcpl_id) < 0)
343 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed");
344 if(H5Sclose(space_id) < 0)
345 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sclose failed");
346 if(H5Dclose(dset_in) < 0)
347 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dclose failed");
348 break;
349
350 /*-------------------------------------------------------------------------
351 * H5TRAV_TYPE_NAMED_DATATYPE
352 *-------------------------------------------------------------------------
353 */
354 case H5TRAV_TYPE_NAMED_DATATYPE:
355 if((type_in = H5Topen2(fidin, travt->objs[i].name, H5P_DEFAULT)) < 0)
356 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Topen2 failed");
357 if(H5Tclose(type_in) < 0)
358 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed");
359 break;
360
361 /*-------------------------------------------------------------------------
362 * H5TRAV_TYPE_LINK
363 *-------------------------------------------------------------------------
364 */
365 case H5TRAV_TYPE_LINK:
366 /*nothing to do */
367 break;
368
369 case H5TRAV_TYPE_UNKNOWN:
370 case H5TRAV_TYPE_UDLINK:
371 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5TRAV invalid type");
372
373 default:
374 break;
375 } /* end switch */
376 } /* end for */
377
378 /* Finalize (link) the stack of named datatypes (if any)
379 * This function is paired with copy_named_datatype() which is called
380 * in copy_attr(), so need to free.
381 */
382 if (named_datatype_free(&named_dt_head, 0) < 0)
383 H5TOOLS_INFO(H5E_tools_min_id_g, "named_datatype_free failed");
384
385 return ret_value;
386
387 done:
388 H5E_BEGIN_TRY {
389 H5Gclose(grp_in);
390 H5Gclose(grp_out);
391 H5Pclose(dcpl_id);
392 H5Sclose(space_id);
393 H5Dclose(dset_in);
394 H5Dclose(dset_out);
395 H5Tclose(ftype_id);
396 H5Tclose(mtype_id);
397 H5Tclose(type_in);
398 named_datatype_free(&named_dt_head, 1);
399 } H5E_END_TRY;
400
401 return ret_value;
402 }
403
404
405 /*-------------------------------------------------------------------------
406 * Function: copy_refs_attr
407 *
408 * Purpose: duplicate all referenced HDF5 located in attributes
409 * relative to LOC_IN, which is obtained either from
410 * loc_id = H5Gopen2(fid, name, H5P_DEFAULT);
411 * loc_id = H5Dopen2(fid, name, H5P_DEFAULT);
412 * loc_id = H5Topen2(fid, name, H5P_DEFAULT);
413 *
414 * Return: 0, ok, -1 no
415 *
416 * Modified:
417 * Update values of references(object and region) for the following types:
418 * 1) References,
419 * 2) ARRAY of reference,
420 * 3) VLEN of references.
421 * 4) COMPOUND of references.
422 * This function does not handle references in other complicated structures,
423 * such as references in nested compound datatypes.
424 *-------------------------------------------------------------------------
425 */
426
copy_refs_attr(hid_t loc_in,hid_t loc_out,pack_opt_t * options,trav_table_t * travt,hid_t fidout)427 static int copy_refs_attr(hid_t loc_in,
428 hid_t loc_out,
429 pack_opt_t *options,
430 trav_table_t *travt,
431 hid_t fidout) /* for saving references */
432 {
433 int ret_value = 0; /*no need to LEAVE() on ERROR: HERR_INIT(int, SUCCEED) */
434 hid_t attr_id = -1; /* attr ID */
435 hid_t attr_out = -1; /* attr ID */
436 hid_t space_id = -1; /* space ID */
437 hid_t ftype_id = -1; /* file data type ID */
438 hid_t mtype_id = -1; /* memory data type ID */
439 size_t msize; /* memory size of type */
440 hsize_t nelmts; /* number of elements in dataset */
441 hsize_t dims[H5S_MAX_RANK];/* dimensions of dataset */
442 char name[255];
443 H5O_info_t oinfo; /* Object info */
444 unsigned u, i, j;
445 int rank;
446 H5T_class_t type_class = -1;
447 hbool_t is_ref = 0,
448 is_ref_vlen = 0,
449 is_ref_array = 0,
450 is_ref_comp = 0;
451 void *refbuf = NULL;
452 void *buf = NULL;
453 const char *refname = NULL;
454 unsigned *ref_comp_index = NULL;
455 size_t *ref_comp_size = NULL;
456 int ref_comp_field_n = 0;
457
458
459 if(H5Oget_info(loc_in, &oinfo) < 0)
460 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Oget_info failed");
461
462 for(u = 0; u < (unsigned)oinfo.num_attrs; u++) {
463 is_ref = is_ref_vlen = is_ref_array = is_ref_comp = 0;
464
465 /* open attribute */
466 if((attr_id = H5Aopen_by_idx(loc_in, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)u, H5P_DEFAULT, H5P_DEFAULT)) < 0)
467 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aopen_by_idx failed");
468
469 /* get the file datatype */
470 if((ftype_id = H5Aget_type(attr_id)) < 0)
471 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aget_type failed");
472
473 type_class = H5Tget_class(ftype_id);
474
475 if((mtype_id = H5Tget_native_type(ftype_id, H5T_DIR_DEFAULT)) < 0)
476 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tget_native_type failed");
477
478 if((msize = H5Tget_size(mtype_id)) == 0)
479 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tget_size failed");
480
481 is_ref = (type_class == H5T_REFERENCE);
482
483 if(type_class == H5T_VLEN ) {
484 hid_t base_type = H5Tget_super(ftype_id);
485
486 is_ref_vlen = (H5Tget_class(base_type) == H5T_REFERENCE);
487 msize = H5Tget_size(base_type);
488 if (H5Tclose(base_type) < 0)
489 H5TOOLS_INFO(H5E_tools_min_id_g, "H5Tclose base_type failed");
490 }
491 else if(type_class == H5T_ARRAY ) {
492 hid_t base_type = H5Tget_super(ftype_id);
493
494 is_ref_array = (H5Tget_class(base_type) == H5T_REFERENCE);
495 msize = H5Tget_size(base_type);
496 if (H5Tclose(base_type) < 0)
497 H5TOOLS_INFO(H5E_tools_min_id_g, "H5Tclose base_type failed");
498 }
499 else if(type_class == H5T_COMPOUND) {
500 int nmembers = H5Tget_nmembers(ftype_id) ;
501
502 if (nmembers < 1)
503 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tget_nmembers failed");
504
505 ref_comp_index = (unsigned *)HDmalloc((size_t)nmembers*sizeof(unsigned));
506 ref_comp_size = (size_t *)HDmalloc((size_t)nmembers*sizeof(ref_comp_size));
507 ref_comp_field_n = 0;
508
509 for (i=0; i<(unsigned)nmembers; i++) {
510 hid_t mtid = H5Tget_member_type(ftype_id, i);
511
512 if ((H5Tget_class(mtid) == H5T_REFERENCE)) {
513 ref_comp_index[ref_comp_field_n] = i;
514 ref_comp_size[ref_comp_field_n] = H5Tget_size(mtid);
515 ref_comp_field_n++;
516 }
517 if (H5Tclose(mtid) < 0)
518 H5TOOLS_INFO(H5E_tools_min_id_g, "H5Tclose mtid failed");
519 }
520
521 /* if compound don't contain reference type member, free the above
522 * mallocs. Otherwise there can be memory leaks by the 'continue'
523 * statement below. */
524 if (!ref_comp_field_n) {
525 if (ref_comp_index) {
526 HDfree(ref_comp_index);
527 ref_comp_index = NULL;
528 }
529
530 if (ref_comp_size) {
531 HDfree(ref_comp_size);
532 ref_comp_size = NULL;
533 }
534 }
535 }
536
537 is_ref_comp = (ref_comp_field_n > 0);
538
539 if (!(is_ref || is_ref_vlen || is_ref_array || is_ref_comp)) {
540 if (H5Tclose(mtype_id) < 0)
541 H5TOOLS_INFO(H5E_tools_min_id_g, "H5Tclose mtype_id failed");
542 if (H5Tclose(ftype_id) < 0)
543 H5TOOLS_INFO(H5E_tools_min_id_g, "H5Tclose ftype_id failed");
544 if (H5Aclose(attr_id) < 0)
545 H5TOOLS_INFO(H5E_tools_min_id_g, "H5Aclose attr_id failed");
546 continue;
547 }
548
549 /* get name */
550 if(H5Aget_name(attr_id, 255, name) < 0)
551 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aget_name failed");
552
553 /* get the dataspace handle */
554 if((space_id = H5Aget_space(attr_id)) < 0)
555 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aget_space failed");
556
557 /* get dimensions */
558 if((rank = H5Sget_simple_extent_dims(space_id, dims, NULL)) < 0)
559 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sget_simple_extent_dims failed");
560
561
562 /*-------------------------------------------------------------------------
563 * elements
564 *-------------------------------------------------------------------------
565 */
566 nelmts = 1;
567 for(j = 0; j < (unsigned)rank; j++)
568 nelmts *= dims[j];
569
570 if (is_ref_array) {
571 unsigned array_rank = 0;
572 hsize_t array_size = 1;
573 hsize_t array_dims[H5S_MAX_RANK];
574 hid_t base_type = H5Tget_super(ftype_id);
575
576 msize = H5Tget_size(base_type);
577 if (H5Tclose(base_type) < 0)
578 H5TOOLS_INFO(H5E_tools_min_id_g, "H5Tclose base_type failed");
579
580 array_rank = (unsigned)H5Tget_array_ndims(mtype_id);
581 H5Tget_array_dims2(mtype_id, array_dims);
582 for(j = 0; j <array_rank; j++)
583 array_size *= array_dims[j];
584 nelmts *= array_size;
585 }
586
587 if((attr_out = H5Acreate2(loc_out, name, ftype_id, space_id, H5P_DEFAULT, H5P_DEFAULT)) < 0)
588 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Acreate2 failed");
589
590 if (nelmts>0) {
591 /* handle object references */
592 if((is_ref || is_ref_array) && (H5R_OBJ_REF_BUF_SIZE==msize)) {
593 buf = (hobj_ref_t *)HDmalloc((unsigned)(nelmts * msize));
594 if(buf == NULL) {
595 printf("cannot read into memory\n");
596 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDmalloc failed");
597 } /* end if */
598 if(H5Aread(attr_id, mtype_id, buf) < 0)
599 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aread failed");
600
601 refbuf = (hobj_ref_t *)HDcalloc((unsigned)nelmts, msize);
602 if(refbuf == NULL) {
603 printf("cannot allocate memory\n");
604 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDcalloc failed");
605 } /* end if */
606
607 for(i = 0; i < (unsigned)nelmts; i++) {
608 if (update_ref_value(attr_id, H5R_OBJECT, &((hobj_ref_t *)buf)[i], fidout, &((hobj_ref_t *)refbuf)[i], travt)<0)
609 continue;
610 if(options->verbose)
611 printf("object <%s> reference created to <%s>\n", name, refname);
612 } /* i */
613 } /* H5T_STD_REF_OBJ */
614 /* handle region references */
615 else if((is_ref || is_ref_array) && (H5R_DSET_REG_REF_BUF_SIZE == msize)) {
616 buf = (hdset_reg_ref_t *)HDmalloc((unsigned)(nelmts * msize));
617
618 if(buf == NULL) {
619 printf( "cannot read into memory\n" );
620 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDmalloc failed");
621 } /* end if */
622 if(H5Aread(attr_id, mtype_id, buf) < 0)
623 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aread failed");
624
625 /*-------------------------------------------------------------------------
626 * create output
627 *-------------------------------------------------------------------------
628 */
629 refbuf = (hdset_reg_ref_t *)HDcalloc(sizeof(hdset_reg_ref_t), (size_t)nelmts); /*init to zero */
630 if(refbuf == NULL) {
631 printf( "cannot allocate memory\n" );
632 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDcalloc failed");
633 } /* end if */
634
635 for(i = 0; i < (unsigned)nelmts; i++) {
636 if (update_ref_value(attr_id, H5R_DATASET_REGION, &((hdset_reg_ref_t *)buf)[i], fidout, &((hdset_reg_ref_t *)refbuf)[i], travt)<0)
637 continue;
638 if(options->verbose)
639 printf("object <%s> region reference created to <%s>\n", name, refname);
640 }
641 } /* H5T_STD_REF_DSETREG */
642 else if (is_ref_vlen) {
643 /* handle VLEN of references */
644
645 buf = (hvl_t *)HDmalloc((unsigned)(nelmts * sizeof(hvl_t)));
646 refbuf = buf; /* reuse the read buffer for write */
647
648 if(buf == NULL) {
649 printf( "cannot read into memory\n" );
650 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDmalloc failed");
651 } /* end if */
652
653 if(H5Aread(attr_id, mtype_id, buf) < 0)
654 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aread failed");
655
656 if (H5R_OBJ_REF_BUF_SIZE==msize) {
657 hobj_ref_t ref_out;
658
659 for (i=0; i<(unsigned)nelmts; i++) {
660 hobj_ref_t *ptr = (hobj_ref_t *)((hvl_t *)buf)[i].p;
661
662 for (j=0; j<((hvl_t *)buf)[i].len; j++ ) {
663 if (update_ref_value(attr_id, H5R_OBJECT, &(ptr[j]), fidout, &ref_out, travt)<0)
664 continue;
665 HDmemcpy(&(ptr[j]), &ref_out, msize);
666 }
667 } /* for (i=0; i<nelems; i++) */
668 }
669 else if (H5R_DSET_REG_REF_BUF_SIZE == msize) {
670 hdset_reg_ref_t ref_out;
671
672 for (i=0; i<(unsigned)nelmts; i++) {
673 hdset_reg_ref_t *ptr = (hdset_reg_ref_t *)((hvl_t *)buf)[i].p;
674
675 for (j=0; j<((hvl_t *)buf)[i].len; j++ ) {
676 if (update_ref_value(attr_id, H5R_DATASET_REGION, &(ptr[j]), fidout, &ref_out, travt)<0)
677 continue;
678 HDmemcpy(&(ptr[j]), &ref_out, msize);
679 }
680 } /* for (i=0; i<nelems; i++) */
681 }
682 } /* else if (is_ref_vlen) */
683 else if (is_ref_comp) {
684 /* handle ref fields in a compound */
685
686 buf = HDmalloc((unsigned)(nelmts * msize));
687 refbuf = buf; /* reuse the read buffer for write */
688
689 if(buf == NULL) {
690 printf( "cannot read into memory\n" );
691 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDmalloc failed");
692 } /* end if */
693
694 if(H5Aread(attr_id, mtype_id, buf) < 0)
695 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aread failed");
696
697 for (i=0; i<(unsigned)nelmts; i++) {
698 for (j=0; j<(unsigned)ref_comp_field_n; j++) {
699 if (ref_comp_size[j] == H5R_OBJ_REF_BUF_SIZE) {
700 size_t idx = (i * msize) + H5Tget_member_offset(mtype_id, ref_comp_index[j]);
701 hobj_ref_t ref_out;
702
703 if (update_ref_value(attr_id, H5R_OBJECT, (hobj_ref_t *)(((char *)buf)+idx), fidout, &ref_out, travt)<0)
704 continue;
705 HDmemcpy(((char *)buf)+idx, &ref_out, ref_comp_size[j]);
706 } /* if */
707 else if (ref_comp_size[j] == H5R_DSET_REG_REF_BUF_SIZE) {
708 size_t idx = i * msize + H5Tget_member_offset(mtype_id, ref_comp_index[j]);
709 hdset_reg_ref_t ref_out;
710
711 if (update_ref_value(attr_id, H5R_DATASET_REGION, (hdset_reg_ref_t *)(((char *)buf)+idx), fidout, &ref_out, travt)<0)
712 continue;
713 HDmemcpy(((char *)buf)+idx, &ref_out, ref_comp_size[j]);
714 } /* else if */
715 } /* j */
716 } /* i */
717 } /* else if (is_ref_comp) */
718
719 if(H5Awrite(attr_out, mtype_id, refbuf) < 0)
720 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Awrite failed");
721
722 if (is_ref_vlen && buf)
723 H5Dvlen_reclaim (mtype_id, space_id, H5P_DEFAULT, buf);
724 } /* if (nelmts) */
725
726 if (refbuf == buf)
727 refbuf = NULL; /* set it to NULL to avoid double free since buf and refbuf are the same. */
728
729 if(buf) {
730 HDfree(buf);
731 buf = NULL;
732 }
733
734 if(refbuf) {
735 HDfree(refbuf);
736 refbuf = NULL;
737 }
738
739 if (ref_comp_index) {
740 HDfree(ref_comp_index);
741 ref_comp_index = NULL;
742 }
743
744 if (ref_comp_size) {
745 HDfree(ref_comp_size);
746 ref_comp_size = NULL;
747 }
748
749 if(H5Aclose(attr_out) < 0)
750 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aclose failed");
751
752 /*-------------------------------------------------------------------------
753 * close
754 *-------------------------------------------------------------------------
755 */
756 if(H5Tclose(ftype_id) < 0)
757 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed");
758 if(H5Tclose(mtype_id) < 0)
759 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed");
760 if(H5Sclose(space_id) < 0)
761 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sclose failed");
762 if(H5Aclose(attr_id) < 0)
763 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aclose failed");
764 } /* for(u = 0; u < (unsigned)oinfo.num_attrs; u++) */
765
766 done:
767 if(refbuf)
768 HDfree(refbuf);
769 if(buf)
770 HDfree(buf);
771
772 if (ref_comp_index)
773 HDfree(ref_comp_index);
774
775 if (ref_comp_size)
776 HDfree(ref_comp_size);
777
778 H5E_BEGIN_TRY {
779 H5Tclose(ftype_id);
780 H5Tclose(mtype_id);
781 H5Sclose(space_id);
782 H5Aclose(attr_id);
783 H5Aclose(attr_out);
784 } H5E_END_TRY;
785
786 return ret_value;
787 }
788
789 /*-------------------------------------------------------------------------
790 * Function: MapIdToName
791 *
792 * Purpose: map a ID from a reference to a dataset name
793 *
794 *-------------------------------------------------------------------------
795 */
796 static const char*
MapIdToName(hid_t refobj_id,trav_table_t * travt)797 MapIdToName(hid_t refobj_id, trav_table_t *travt)
798 {
799 unsigned int u;
800 const char *ret = NULL;
801
802 /* linear search */
803 for(u = 0; u < travt->nobjs; u++) {
804 if(travt->objs[u].type == (h5trav_type_t)H5O_TYPE_DATASET ||
805 travt->objs[u].type == (h5trav_type_t)H5O_TYPE_GROUP ||
806 travt->objs[u].type == (h5trav_type_t)H5O_TYPE_NAMED_DATATYPE) {
807 H5O_info_t ref_oinfo; /* Stat for the refobj id */
808
809 /* obtain information to identify the referenced object uniquely */
810 if(H5Oget_info(refobj_id, &ref_oinfo) < 0)
811 goto out;
812
813 if(ref_oinfo.addr == travt->objs[u].objno) {
814 ret = travt->objs[u].name;
815 goto out;
816 } /* end if */
817 } /* end if */
818 } /* u */
819
820 out:
821 return ret;
822 }
823
824 /*-------------------------------------------------------------------------
825 * Function: Update_Ref_value
826 *
827 * Purpose: Update a reference value
828 *-------------------------------------------------------------------------
829 */
update_ref_value(hid_t obj_id,H5R_type_t ref_type,void * ref_in,hid_t fid_out,void * ref_out,trav_table_t * travt)830 static herr_t update_ref_value(hid_t obj_id, H5R_type_t ref_type, void *ref_in,
831 hid_t fid_out, void *ref_out, trav_table_t *travt)
832 {
833 int ret_value = 0; /*no need to LEAVE() on ERROR: HERR_INIT(int, SUCCEED) */
834 const char *ref_obj_name;
835 hid_t space_id = -1;
836 hid_t ref_obj_id = -1;
837
838 ref_obj_id = H5Rdereference(obj_id, ref_type, ref_in);
839 if (ref_obj_id < 0)
840 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Rdereference2 failed");
841
842 ref_obj_name = MapIdToName(ref_obj_id, travt);
843 if (ref_obj_name == NULL)
844 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "MapIdToName failed");
845
846 if (ref_type == H5R_DATASET_REGION) {
847 space_id = H5Rget_region(obj_id, H5R_DATASET_REGION, ref_in);
848 if (space_id < 0)
849 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Rget_region failed");
850 }
851
852 if(H5Rcreate(ref_out, fid_out, ref_obj_name, ref_type, space_id) < 0)
853 HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Rcreate failed");
854
855 done:
856 H5E_BEGIN_TRY {
857 H5Sclose(space_id);
858 H5Oclose(ref_obj_id);
859 } H5E_END_TRY;
860
861 return ret_value;
862 }
863
864