void parse_command_line (int argc, const char *argv[]) { int opt = FALSE; /* parse command line options */ while ((opt = get_option (argc, argv, s_opts, l_opts)) != EOF) { switch ((char) opt) { case 'o': output_file = HDstrdup (opt_arg); break; case 'i': input_file = HDstrdup (opt_arg); break; case 'u': ub_file = HDstrdup (opt_arg); break; case 'c': do_clobber = TRUE; break; case 'h': usage (h5tools_getprogname()); leave (EXIT_SUCCESS); case 'V': print_version (h5tools_getprogname()); leave (EXIT_SUCCESS); case '?': default: usage (h5tools_getprogname()); leave (EXIT_FAILURE); } } }
/* NAME HDgettagsname -- return a text name of a tag USAGE char * HDgettagsname(tag) uint16 tag; IN: tag of element to find RETURNS Descriptive text or NULL DESCRIPTION Map a tag to a dynamically allocated text name of it. Checks for special elements now. --------------------------------------------------------------------------- */ char * HDgettagsname(uint16 tag) { CONSTR(FUNC, "HDgettagsname"); /* for HERROR */ char *ret = NULL; intn i; if (SPECIALTAG(tag)) ret = (char *) HDstrdup("Special "); tag = BASETAG(tag); for (i = 0; i < (intn)(sizeof(tag_descriptions) / sizeof(tag_descript_t)); i++) if (tag_descriptions[i].tag == tag) { if (ret == NULL) ret = (char *) HDstrdup(tag_descriptions[i].name); else { char *t; t = (char *) HDmalloc(HDstrlen(ret) + HDstrlen(tag_descriptions[i].name) + 2); if (t == NULL) { HDfree(ret); HRETURN_ERROR(DFE_NOSPACE, NULL) } /* end if */ HDstrcpy(t, ret); HDstrcat(t, tag_descriptions[i].name); HDfree(ret); ret = t; } /* end else */ } /* end if */
static void trav_table_addlink(trav_table_t *table, haddr_t objno, const char *path) { size_t i; /* Local index variable */ for(i = 0; i < table->nobjs; i++) { if(table->objs[i].objno == objno) { size_t n; /* already inserted? */ if(HDstrcmp(table->objs[i].name, path) == 0) return; /* allocate space if necessary */ if(table->objs[i].nlinks == (unsigned)table->objs[i].sizelinks) { table->objs[i].sizelinks = MAX(1, table->objs[i].sizelinks * 2); table->objs[i].links = (trav_link_t*)HDrealloc(table->objs[i].links, table->objs[i].sizelinks * sizeof(trav_link_t)); } /* end if */ /* insert it */ n = table->objs[i].nlinks++; table->objs[i].links[n].new_name = (char *)HDstrdup(path); return; } /* end for */ } /* end for */ HDassert(0 && "object not in table?!?"); }
/*------------------------------------------------------------------------- * Function: trav_table_addflags * * Purpose: Add FLAGS, NAME and TYPE of object to table * * Return: void *------------------------------------------------------------------------- */ void trav_table_addflags(unsigned *flags, char *name, h5trav_type_t type, trav_table_t *table) { size_t new_obj; if(table) { if(table->nobjs == table->size) { table->size = MAX(1, table->size * 2); table->objs = (trav_obj_t *)HDrealloc(table->objs, table->size * sizeof(trav_obj_t)); } /* end if */ new_obj = table->nobjs++; table->objs[new_obj].objno = 0; table->objs[new_obj].flags[0] = flags[0]; table->objs[new_obj].flags[1] = flags[1]; table->objs[new_obj].is_same_trgobj = 0; table->objs[new_obj].name = (char *)HDstrdup(name); table->objs[new_obj].type = type; table->objs[new_obj].nlinks = 0; table->objs[new_obj].sizelinks = 0; table->objs[new_obj].links = NULL; } }
void parse_command_line (int argc, const char *argv[]) { int opt = FALSE; /* parse command line options */ while ((opt = get_option (argc, argv, s_opts, l_opts)) != EOF) { switch ((char) opt) { case 'c': nbytes = HDstrdup (opt_arg); break; case '?': default: usage (h5tools_getprogname()); exit (EXIT_FAILURE); } } if (argc <= opt_ind) { error_msg("missing file name\n"); usage (h5tools_getprogname()); exit (EXIT_FAILURE); } }
static void parse_command_line(int argc, const char *argv[]) { int opt = FALSE; /* parse command line options */ while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { switch ((char) opt) { case 'o': output_file = HDstrdup (opt_arg); break; case 'i': input_file = HDstrdup (opt_arg); break; case 'u': ub_file = HDstrdup (opt_arg); break; case 'd': do_delete = TRUE; break; case 'h': usage(h5tools_getprogname()); leave(EXIT_SUCCESS); case 'V': print_version(h5tools_getprogname()); leave(EXIT_SUCCESS); case '?': default: usage(h5tools_getprogname()); leave(EXIT_FAILURE); } } /* check for file name to be processed */ /* if (argc <= opt_ind+2) { error_msg("missing file name\n"); usage(h5tools_getprogname()); HDexit(EXIT_FAILURE); } */ }
/*------------------------------------------------------------------------- * Function: symlink_visit_add * * Purpose: Add an symbolic link to visited data structure * * Return: 0 on success, -1 on failure * * Programmer: Neil Fortner, [email protected] * Adapted from trav_addr_add in h5trav.c by Quincey Koziol * * Date: September 5, 2008 * * Modified: * Jonathan Kim * - Moved from h5ls.c to share among tools. (Sep 16, 2010) * - Renamed from elink_trav_add to symlink_visit_add for both soft and * external links. (May 25, 2010) * - Add type parameter to distingush between soft and external link for * sure, which prevent from mixing up visited link when the target names * are same between the soft and external link, as code marks with the * target name. (May 25,2010) * *------------------------------------------------------------------------- */ herr_t symlink_visit_add(symlink_trav_t *visited, H5L_type_t type, const char *file, const char *path) { size_t idx; /* Index of address to use */ void *tmp_ptr; /* Allocate space if necessary */ if(visited->nused == visited->nalloc) { visited->nalloc = MAX(1, visited->nalloc * 2); if(NULL == (tmp_ptr = HDrealloc(visited->objs, visited->nalloc * sizeof(visited->objs[0])))) return -1; visited->objs = tmp_ptr; } /* end if */ /* Append it */ idx = visited->nused++; visited->objs[idx].type = type; visited->objs[idx].file = NULL; visited->objs[idx].path = NULL; if (type == H5L_TYPE_EXTERNAL) { if(NULL == (visited->objs[idx].file = HDstrdup(file))) { visited->nused--; return -1; } } if(NULL == (visited->objs[idx].path = HDstrdup(path))) { visited->nused--; if (visited->objs[idx].file) HDfree (visited->objs[idx].file); return -1; } return 0; } /* end symlink_visit_add() */
/*------------------------------------------------------------------------- * Function: symlink_visit_add * * Purpose: Add an symbolic link to visited data structure * * Return: 0 on success, * -1 on failure *------------------------------------------------------------------------- */ herr_t symlink_visit_add(symlink_trav_t *visited, H5L_type_t type, const char *file, const char *path) { herr_t ret_value = SUCCEED; size_t idx; /* Index of address to use */ /* Allocate space if necessary */ if(visited->nused == visited->nalloc) { void *tmp_ptr; visited->nalloc = MAX(1, visited->nalloc * 2); if(NULL == (tmp_ptr = HDrealloc(visited->objs, visited->nalloc * sizeof(symlink_trav_path_t)))) HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "visited data structure realloc failed"); visited->objs = (symlink_trav_path_t *)tmp_ptr; } /* end if */ /* Append it */ idx = visited->nused++; visited->objs[idx].type = type; visited->objs[idx].file = NULL; visited->objs[idx].path = NULL; if(type == H5L_TYPE_EXTERNAL) { if(NULL == (visited->objs[idx].file = HDstrdup(file))) { visited->nused--; HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "visited data structure name allocation failed"); } /* end if */ } /* end if */ if(NULL == (visited->objs[idx].path = HDstrdup(path))) { visited->nused--; if(visited->objs[idx].file) HDfree (visited->objs[idx].file); HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "visited data structure path allocation failed"); } /* end if */ done: return ret_value; } /* end symlink_visit_add() */
/*------------------------------------------------------------------------- * Function: table_attr_mark_exist * * Purpose: mark given attribute name to table as sign of exsit * * Parameter: * - exist [IN] * - name [IN] : attribute name * - table [OUT] * * Programmer: Jonathan Kim * * Date: March 15, 2011 *------------------------------------------------------------------------*/ static void table_attr_mark_exist(unsigned *exist, char *name, table_attrs_t *table) { size_t new_val; if(table->nattrs == table->size) { table->size = MAX(1, table->size * 2); table->attrs = (match_attr_t *)HDrealloc(table->attrs, table->size * sizeof(match_attr_t)); } /* end if */ new_val = table->nattrs++; table->attrs[new_val].exist[0] = exist[0]; table->attrs[new_val].exist[1] = exist[1]; table->attrs[new_val].name = (char *)HDstrdup(name); }
/*------------------------------------------------------------------------- * Function: trav_info_add * * Purpose: Add a link path & type to info struct * * Return: void * * Programmer: Quincey Koziol, [email protected] * * Date: September 1, 2007 * *------------------------------------------------------------------------- */ static void trav_info_add(trav_info_t *info, const char *path, h5trav_type_t obj_type) { size_t idx; /* Index of address to use */ /* Allocate space if necessary */ if(info->nused == info->nalloc) { info->nalloc = MAX(1, info->nalloc * 2);; info->paths = (trav_path_t *)HDrealloc(info->paths, info->nalloc * sizeof(trav_path_t)); } /* end if */ /* Append it */ idx = info->nused++; info->paths[idx].path = HDstrdup(path); info->paths[idx].type = obj_type; } /* end trav_info_add() */
/*------------------------------------------------------------------------- * Function: trav_addr_add * * Purpose: Add a hardlink address to visited data structure * * Return: void * * Programmer: Quincey Koziol, [email protected] * * Date: September 1, 2007 * *------------------------------------------------------------------------- */ static void trav_addr_add(trav_addr_t *visited, haddr_t addr, const char *path) { size_t idx; /* Index of address to use */ /* Allocate space if necessary */ if(visited->nused == visited->nalloc) { visited->nalloc = MAX(1, visited->nalloc * 2);; visited->objs = HDrealloc(visited->objs, visited->nalloc * sizeof(visited->objs[0])); } /* end if */ /* Append it */ idx = visited->nused++; visited->objs[idx].addr = addr; visited->objs[idx].path = HDstrdup(path); } /* end trav_addr_add() */
/*------------------------------------------------------------------------- * Function: ref_path_table_put * * Purpose: Enter the 'obj' with 'path' in the table (assumes its not * already there) * * Create an object reference, pte, and store them * in the table. * * NOTE: Takes ownership of the path name string passed in! * * Return: Non-negative on success, negative on failure * * Programmer: REMcG * * Modifications: * *------------------------------------------------------------------------- */ static int ref_path_table_put(const char *path, haddr_t objno) { ref_path_node_t *new_node; HDassert(ref_path_table); HDassert(path); if((new_node = HDmalloc(sizeof(ref_path_node_t))) == NULL) return(-1); new_node->objno = objno; new_node->path = HDstrdup(path); return(H5SL_insert(ref_path_table, new_node, &(new_node->objno))); }
/*------------------------------------------------------------------------- * Function: add_obj * * Purpose: add a shared object to the table * realloc the table if necessary * * Return: void * * Programmer: Ruey-Hsia Li * * Modifications: * *------------------------------------------------------------------------- */ static void add_obj(table_t *table, haddr_t objno, const char *objname, hbool_t record) { unsigned u; /* See if we need to make table larger */ if(table->nobjs == table->size) { table->size *= 2; table->objs = (struct obj_t *)HDrealloc(table->objs, table->size * sizeof(table->objs[0])); } /* end if */ /* Increment number of objects in table */ u = table->nobjs++; /* Set information about object */ table->objs[u].objno = objno; table->objs[u].objname = HDstrdup(objname); table->objs[u].recorded = record; table->objs[u].displayed = 0; }
static void trav_table_add(trav_table_t *table, const char *path, const H5O_info_t *oinfo) { size_t new_obj; if(table->nobjs == table->size) { table->size = MAX(1, table->size * 2); table->objs = (trav_obj_t*)HDrealloc(table->objs, table->size * sizeof(trav_obj_t)); } /* end if */ new_obj = table->nobjs++; table->objs[new_obj].objno = oinfo ? oinfo->addr : HADDR_UNDEF; table->objs[new_obj].flags[0] = table->objs[new_obj].flags[1] = 0; table->objs[new_obj].is_same_trgobj = 0; table->objs[new_obj].name = (char *)HDstrdup(path); table->objs[new_obj].type = oinfo ? (h5trav_type_t)oinfo->type : H5TRAV_TYPE_LINK; table->objs[new_obj].nlinks = 0; table->objs[new_obj].sizelinks = 0; table->objs[new_obj].links = NULL; }
/*------------------------------------------------------------------------- * Function: H5LD_get_dset_type_size * * Purpose: To return the size of the dataset's datatype in bytes * null "fields": return the size of the dataset's datatype * non-null "fields": return the size of the dataset's datatype * with respect to the selection in "fields" * * Return: Success: size of the dataset's datatype * Failure: 0 (valid datatypes are never zero size) * * Programmer: Vailin Choi; March 2010 * *------------------------------------------------------------------------- */ static size_t H5LD_get_dset_type_size(hid_t did, const char *fields) { hid_t dset_tid = -1; /* Dataset's type identifier */ hid_t tid = -1; /* Native Type identifier */ H5LD_memb_t **listv = NULL; /* Vector for storing information in "fields" */ char *dup_fields = NULL; /* A copy of "fields" */ size_t ret_value = 0; /* Return value */ /* Get the datatype of the dataset */ if((dset_tid = H5Dget_type(did)) < 0) goto done; if((tid = H5Tget_native_type(dset_tid, H5T_DIR_DEFAULT)) < 0) goto done; if(fields == NULL) /* If no "fields" is specified */ ret_value = H5Tget_size(tid); else { /* "fields" are specified */ size_t len; /* Estimate the number of comma-separated fields in "fields" */ size_t tot = 0; /* Data type size of all the fields in "fields" */ int n = 0, num = 0; /* Local index variables */ HDassert(fields && *fields); /* Should be a compound datatype if "fields" exists */ if(H5Tget_class(dset_tid) != H5T_COMPOUND) goto done; /* Get a copy of "fields" */ if(NULL == (dup_fields = HDstrdup(fields))) goto done; /* Allocate memory for a list of H5LD_memb_t pointers to store "fields" info */ len = (HDstrlen(fields) / 2) + 2; if(NULL == (listv = (H5LD_memb_t **)HDcalloc(len, sizeof(H5LD_memb_t *)))) goto done; /* Process and store info for "fields" */ if((num = H5LD_construct_vector(dup_fields, listv/*OUT*/, tid)) < 0) goto done; /* Sum up the size of all the datatypes in "fields" */ for(n = 0; n < num; n++) tot += listv[n]->last_tsize; /* Clean up the vector of H5LD_memb_t structures */ H5LD_clean_vector(listv); /* Return the total size */ ret_value = tot; } /* end else */ done: H5E_BEGIN_TRY H5Tclose(tid); H5Tclose(dset_tid); H5E_END_TRY /* Free the array of H5LD_memb_t pointers */ if(listv) HDfree(listv); /* Free memory */ if(dup_fields) HDfree(dup_fields); return(ret_value); } /* H5LD_get_dset_type_size() */
/*------------------------------------------------------------------------- * Function: H5LD_get_dset_elmts * * Purpose: To retrieve selected data from the dataset * * Return: Success: 0 * Failure: negative * * Programmer: Vailin Choi; August 2010 * *------------------------------------------------------------------------- */ static herr_t H5LD_get_dset_elmts(hid_t did, const hsize_t *prev_dims, const hsize_t *cur_dims, const char *fields, void *buf) { hid_t dtid = -1, tid = -1; /* Dataset type id */ hid_t sid = -1, mid = -1; /* Dataspace and memory space id */ hssize_t snum_elmts; /* Number of dataset elements in the selection (signed) */ hsize_t num_elmts; /* Number of dataset elements in the selection */ hsize_t start[H5S_MAX_RANK];/* Starting offset */ hsize_t count[H5S_MAX_RANK];/* ??offset */ H5LD_memb_t **listv = NULL; /* Vector for storing information in "fields" */ char *dup_fields = NULL; /* A copy of "fields" */ char *sav_buf = NULL; /* Saved pointer temporary buffer */ unsigned ctr; /* Counter for # of curr_dims > prev_dims */ int ndims; /* Number of dimensions for the dataset */ int i; /* Local index variable */ herr_t ret_value = FAIL; /* Return value */ /* Verify parameters */ if(prev_dims == NULL || cur_dims == NULL || buf == NULL) goto done; /* Get dataset's dataspace */ if((sid = H5Dget_space(did)) < 0) goto done; /* Get the number of dimensions */ if((ndims = H5Sget_simple_extent_ndims(sid)) < 0) goto done; /* Verify that cur_dims must have one dimension whose size is greater than prev_dims */ HDmemset(start, 0, sizeof start); HDmemset(count, 0, sizeof count); ctr = 0; for(i = 0; i < ndims; i++) if(cur_dims[i] > prev_dims[i]) { ++ctr; count[i] = cur_dims[i] - prev_dims[i]; start[i] = prev_dims[i]; } /* end if */ else { /* < or = */ start[i] = 0; count[i] = MIN(prev_dims[i], cur_dims[i]); } /* end else */ if(!ctr) goto done; if(ctr == 1) { /* changes for only one dimension */ /* Make the selection in the dataset based on "cur_dims" and "prev_dims" */ if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0) goto done; } /* end if */ else { /* changes for more than one dimensions */ HDmemset(start, 0, sizeof start); /* Make the selection in the dataset based on "cur_dims" and "prev_dims" */ if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, NULL, cur_dims, NULL) < 0) goto done; if(H5Sselect_hyperslab(sid, H5S_SELECT_NOTB, start, NULL, prev_dims, NULL) < 0) goto done; } /* end else */ /* Get the number of elements in the selection */ if(0 == (snum_elmts = H5Sget_select_npoints(sid))) goto done; num_elmts = (hsize_t)snum_elmts; /* Create the memory space for the selection */ if((mid = H5Screate_simple(1, &num_elmts, NULL)) < 0) goto done; /* Get the native datatype size */ if((dtid = H5Dget_type(did)) < 0) goto done; if((tid = H5Tget_native_type(dtid, H5T_DIR_DEFAULT)) < 0) goto done; if(fields == NULL) { /* nothing in "fields" */ /* Read and store all the elements in "buf" */ if(H5Dread(did, tid, mid, sid, H5P_DEFAULT, buf) < 0) goto done; } /* end if */ else { /* "fields" is specified */ unsigned char *buf_p = (unsigned char *)buf; /* Pointer to the destination buffer */ char *tmp_buf; /* Temporary buffer for data read */ size_t tot_tsize; /* Total datatype size */ size_t len; /* Estimate the number of comma-separated fields in "fields" */ /* should be a compound datatype if "fields" exists */ if(H5Tget_class(tid) != H5T_COMPOUND) goto done; /* Get the total size of the dataset's datatypes */ if(0 == (tot_tsize = H5LD_get_dset_type_size(did, NULL))) goto done; /* Allocate memory for reading in the elements in the dataset selection */ if(NULL == (sav_buf = tmp_buf = (char *)HDcalloc((size_t)num_elmts, tot_tsize))) goto done; /* Read the dataset elements in the selection */ if(H5Dread(did, tid, mid, sid, H5P_DEFAULT, tmp_buf) < 0) goto done; /* Make a copy of "fields" */ if(NULL == (dup_fields = HDstrdup(fields))) goto done; /* Allocate memory for the vector of H5LD_memb_t pointers */ len = (HDstrlen(fields) / 2) + 2; if(NULL == (listv = (H5LD_memb_t **)HDcalloc(len, sizeof(H5LD_memb_t *)))) goto done; /* Process and store information for "fields" */ if(H5LD_construct_vector(dup_fields, listv, tid) < 0) goto done; /* Copy data for each dataset element in the selection */ for(i = 0; i < (int)num_elmts; i++) { int j; /* Local index variable */ /* Copy data for "fields" to the input buffer */ for(j = 0; listv[j] != NULL; j++) { HDmemcpy(buf_p, tmp_buf + listv[j]->tot_offset, listv[j]->last_tsize); buf_p += listv[j]->last_tsize; } /* end for */ tmp_buf += tot_tsize; } /* end for */ /* Clean up the vector of H5LD_memb_t structures */ H5LD_clean_vector(listv); } /* end else */ /* Indicate success */ ret_value = SUCCEED; done: H5E_BEGIN_TRY H5Tclose(dtid); H5Tclose(tid); H5Sclose(sid); H5Sclose(mid); H5E_END_TRY /* Free the array of H5LD_memb_t pointers */ if(listv) HDfree(listv); /* Free memory */ if(dup_fields) HDfree(dup_fields); if(sav_buf) HDfree(sav_buf); return(ret_value); } /* H5LD_get_dset_elmts() */
int main (int argc, const char *argv[]) { int fd; unsigned int size; char *filename; long res; char *buf; h5tools_setprogname(PROGRAMNAME); h5tools_setstatus(EXIT_SUCCESS); /* Initialize h5tools lib */ h5tools_init(); parse_command_line (argc, argv); if (nbytes == NULL) { /* missing arg */ error_msg("missing size\n"); usage (h5tools_getprogname()); exit (EXIT_FAILURE); } if (argc <= (opt_ind)) { error_msg("missing file name\n"); usage (h5tools_getprogname()); exit (EXIT_FAILURE); } filename = HDstrdup (argv[opt_ind]); size = 0; res = sscanf (nbytes, "%u", &size); if (res == EOF) { /* fail */ error_msg("missing file name\n"); usage (h5tools_getprogname()); exit (EXIT_FAILURE); } fd = HDopen (filename, O_RDONLY, 0); if (fd < 0) { error_msg("can't open file %s\n", filename); exit (EXIT_FAILURE); } buf = (char *)HDmalloc ((unsigned)(size + 1)); if (buf == NULL) { HDclose (fd); exit (EXIT_FAILURE); } res = HDread (fd, buf, (unsigned)size); if (res < (long)size) { if (buf) HDfree (buf); HDclose (fd); exit (EXIT_FAILURE); } HDwrite (1, buf, (unsigned)size); if (buf) HDfree (buf); HDclose (fd); return (EXIT_SUCCESS); }
/*------------------------------------------------------------------------- * Function: main * * Purpose: HDF5 user block unjammer * * Return: Success: 0 * Failure: 1 * * Programmer: * * Modifications: * *------------------------------------------------------------------------- */ int main (int argc, const char *argv[]) { char *ifname; void *edata; H5E_auto2_t func; hid_t ifile; hsize_t usize; htri_t testval; herr_t status; hid_t plist; h5tools_setprogname(PROGRAMNAME); h5tools_setstatus(EXIT_SUCCESS); /* Initialize h5tools lib */ h5tools_init(); /* Disable error reporting */ H5Eget_auto2(H5E_DEFAULT, &func, &edata); H5Eset_auto2(H5E_DEFAULT, NULL, NULL); parse_command_line (argc, argv); if (argc <= (opt_ind)) { error_msg("missing file name\n"); usage (h5tools_getprogname()); return (EXIT_FAILURE); } ifname = HDstrdup (argv[opt_ind]); testval = H5Fis_hdf5 (ifname); if (testval <= 0) { error_msg("Input HDF5 file is not HDF \"%s\"\n", ifname); return (EXIT_FAILURE); } ifile = H5Fopen (ifname, H5F_ACC_RDONLY, H5P_DEFAULT); if (ifile < 0) { error_msg("Can't open input HDF5 file \"%s\"\n", ifname); return (EXIT_FAILURE); } plist = H5Fget_create_plist (ifile); if (plist < 0) { error_msg("Can't get file creation plist for file \"%s\"\n", ifname); return (EXIT_FAILURE); } status = H5Pget_userblock (plist, &usize); if (status < 0) { error_msg("Can't get user block for file \"%s\"\n", ifname); return (EXIT_FAILURE); } printf ("%ld\n", (long) usize); H5Pclose (plist); H5Fclose (ifile); return (EXIT_SUCCESS); }
/*------------------------------------------------------------------------- * Function: parse_command_line * * Purpose: Parses command line and sets up global variable to control output * * Return: Success: 0 * Failure: -1 * * Programmer: Quincey Koziol, 2/13/2007 * *------------------------------------------------------------------------- */ static int parse_command_line(int argc, const char *argv[], param_t *parms) { int opt; /* Option from command line */ size_t curr_group; /* Current group name to copy */ /* Check for empty command line */ if(argc == 1) { usage(); leave(EXIT_SUCCESS); } /* end if */ /* Parse command line options */ while((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { switch((char)opt) { /* Display 'help' */ case 'h': usage(); leave(EXIT_SUCCESS); /* Create objects with the latest version of the format */ case 'l': parms->latest = TRUE; break; /* Create parent groups */ case 'p': parms->parents = TRUE; break; /* Verbose output */ case 'v': parms->verbose = TRUE; break; /* Display version */ case 'V': print_version(h5tools_getprogname()); leave(EXIT_SUCCESS); /* Bad command line argument */ default: usage(); leave(EXIT_FAILURE); } /* end switch */ } /* end while */ /* Check for file name to be processed */ if(argc <= opt_ind) { error_msg("missing file name\n"); usage(); leave(EXIT_FAILURE); } /* end if */ /* Retrieve file name */ parms->fname = HDstrdup(argv[opt_ind]); opt_ind++; /* Check for group(s) to be created */ if(argc <= opt_ind) { error_msg("missing group name(s)\n"); usage(); leave(EXIT_FAILURE); } /* end if */ /* Allocate space for the group name pointers */ parms->ngroups = (size_t)(argc - opt_ind); parms->groups = (char **)HDmalloc(parms->ngroups * sizeof(char *)); /* Retrieve the group names */ curr_group = 0; while(opt_ind < argc) { parms->groups[curr_group] = HDstrdup(argv[opt_ind]); curr_group++; opt_ind++; } /* end while */ #ifdef QAK HDfprintf(stderr, "parms->parents = %t\n", parms->parents); HDfprintf(stderr, "parms->verbose = %t\n", parms->verbose); HDfprintf(stderr, "parms->fname = '%s'\n", parms->fname); HDfprintf(stderr, "parms->ngroups = %Zu\n", parms->ngroups); for(curr_group = 0; curr_group < parms->ngroups; curr_group++) HDfprintf(stderr, "parms->group[%Zu] = '%s'\n", curr_group, parms->groups[curr_group]); #endif /* QAK */ return(0); } /* parse_command_line() */
/*------------------------------------------------------------------------- * Function: parse_command_line * * Purpose: Parse the command line for h5watch (take only long options) * * Return: Success: Set the corresponding command flags and return void * Failure: Exits program with EXIT_FAILURE value. * * Programmer: Vailin Choi; August 2010 * * Modifications: * *------------------------------------------------------------------------- */ static void parse_command_line(int argc, const char *argv[]) { int opt; /* Command line option */ int tmp; /* no arguments */ if (argc == 1) { usage(h5tools_getprogname()); leave(EXIT_FAILURE); } /* parse command line options */ while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { switch ((char)opt) { case '?': case 'h': /* --help */ usage(h5tools_getprogname()); leave(EXIT_SUCCESS); case 'V': /* --version */ print_version(progname); leave(EXIT_SUCCESS); break; case 'w': /* --width=N */ g_display_width = (int)HDstrtol(opt_arg, NULL, 0); if(g_display_width < 0) { usage(h5tools_getprogname()); leave(EXIT_FAILURE); } break; case 'd': /* --dim */ g_monitor_size_only = TRUE; break; case 'S': /* --simple */ g_simple_output = TRUE; break; case 'l': /* --label */ g_label = TRUE; break; case 'p': /* --polling=N */ /* g_polling_interval = HDstrtod(opt_arg, NULL); */ if((tmp = (int)HDstrtol(opt_arg, NULL, 10)) <= 0) { usage(h5tools_getprogname()); leave(EXIT_FAILURE); } g_polling_interval = (unsigned)tmp; break; case 'f': /* --fields=<list_of_fields> */ if(g_list_of_fields == NULL) { if((g_list_of_fields = HDstrdup(opt_arg)) == NULL) { error_msg("memory allocation failed (file %s:line %d)\n", __FILE__, __LINE__); leave(EXIT_FAILURE); } } else { char *str; if((str = HDstrdup(opt_arg)) == NULL) { error_msg("memory allocation failed (file %s:line %d)\n", __FILE__, __LINE__); leave(EXIT_FAILURE); } if((g_list_of_fields = (char *)HDrealloc(g_list_of_fields, HDstrlen(g_list_of_fields) + HDstrlen(str) + 2)) == NULL) { error_msg("memory allocation failed (file %s:line %d)\n", __FILE__, __LINE__); leave(EXIT_FAILURE); } HDstrcat(g_list_of_fields, FIELD_SEP); HDstrcat(g_list_of_fields, str); } break; default: usage(h5tools_getprogname()); leave(EXIT_FAILURE); } } /* check for object to be processed */ if (argc <= opt_ind) { error_msg("missing dataset name\n"); usage(h5tools_getprogname()); leave(EXIT_FAILURE); } } /* parse_command_line() */
int main (int argc, const char *argv[]) { hid_t fid_src = -1; hid_t fid_dst = -1; unsigned flag = 0; unsigned verbose = 0; unsigned parents = 0; hid_t ocpl_id = (-1); /* Object copy property list */ hid_t lcpl_id = (-1); /* Link creation property list */ int opt; int li_ret; h5tool_link_info_t linkinfo; h5tools_setprogname(PROGRAMNAME); h5tools_setstatus(EXIT_SUCCESS); /* initialize h5tools lib */ h5tools_init(); /* init linkinfo struct */ HDmemset(&linkinfo, 0, sizeof(h5tool_link_info_t)); /* Check for no command line parameters */ if(argc == 1) { usage(); leave(EXIT_FAILURE); } /* end if */ /* parse command line options */ while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { switch ((char)opt) { case 'd': oname_dst = HDstrdup(opt_arg); break; case 'f': /* validate flag */ if (parse_flag(opt_arg,&flag)<0) { usage(); leave(EXIT_FAILURE); } str_flag = HDstrdup(opt_arg); break; case 'h': usage(); leave(EXIT_SUCCESS); break; case 'i': fname_src = HDstrdup(opt_arg); break; case 'o': fname_dst = HDstrdup(opt_arg); break; case 'p': parents = 1; break; case 's': oname_src = HDstrdup(opt_arg); break; case 'V': print_version(h5tools_getprogname()); leave(EXIT_SUCCESS); break; case 'v': verbose = 1; break; default: usage(); leave(EXIT_FAILURE); } } /* end of while */ /*------------------------------------------------------------------------- * check for missing file/object names *-------------------------------------------------------------------------*/ if (fname_src==NULL) { error_msg("Input file name missing\n"); usage(); leave(EXIT_FAILURE); } if (fname_dst==NULL) { error_msg("Output file name missing\n"); usage(); leave(EXIT_FAILURE); } if (oname_src==NULL) { error_msg("Source object name missing\n"); usage(); leave(EXIT_FAILURE); } if (oname_dst==NULL) { error_msg("Destination object name missing\n"); usage(); leave(EXIT_FAILURE); } /*------------------------------------------------------------------------- * open output file *-------------------------------------------------------------------------*/ /* Attempt to open an existing HDF5 file first. Need to open the dst file before the src file just in case that the dst and src are the same file */ fid_dst = h5tools_fopen(fname_dst, H5F_ACC_RDWR, H5P_DEFAULT, NULL, NULL, 0); /*------------------------------------------------------------------------- * open input file *-------------------------------------------------------------------------*/ fid_src = h5tools_fopen(fname_src, H5F_ACC_RDONLY, H5P_DEFAULT, NULL, NULL, 0); /*------------------------------------------------------------------------- * test for error in opening input file *-------------------------------------------------------------------------*/ if (fid_src==-1) { error_msg("Could not open input file <%s>...Exiting\n", fname_src); leave(EXIT_FAILURE); } /*------------------------------------------------------------------------- * create an output file when failed to open it *-------------------------------------------------------------------------*/ /* If we couldn't open an existing file, try creating file */ /* (use "EXCL" instead of "TRUNC", so we don't blow away existing non-HDF5 file) */ if(fid_dst < 0) fid_dst = H5Fcreate(fname_dst, H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT); /*------------------------------------------------------------------------- * test for error in opening output file *-------------------------------------------------------------------------*/ if (fid_dst==-1) { error_msg("Could not open output file <%s>...Exiting\n", fname_dst); leave(EXIT_FAILURE); } /*------------------------------------------------------------------------- * print some info *-------------------------------------------------------------------------*/ if (verbose) { printf("Copying file <%s> and object <%s> to file <%s> and object <%s>\n", fname_src, oname_src, fname_dst, oname_dst); if (flag) { HDassert(str_flag); printf("Using %s flag\n", str_flag); } } /*------------------------------------------------------------------------- * create property lists for copy *-------------------------------------------------------------------------*/ /* create property to pass copy options */ if ( (ocpl_id = H5Pcreate(H5P_OBJECT_COPY)) < 0) goto error; /* set options for object copy */ if (flag) { if ( H5Pset_copy_object(ocpl_id, flag) < 0) goto error; } /* Create link creation property list */ if((lcpl_id = H5Pcreate(H5P_LINK_CREATE)) < 0) { error_msg("Could not create link creation property list\n"); goto error; } /* end if */ /* Check for creating intermediate groups */ if(parents) { /* Set the intermediate group creation property */ if(H5Pset_create_intermediate_group(lcpl_id, 1) < 0) { error_msg("Could not set property for creating parent groups\n"); goto error; } /* end if */ /* Display some output if requested */ if(verbose) printf("%s: Creating parent groups\n", h5tools_getprogname()); } /* end if */ else /* error, if parent groups doesn't already exist in destination file */ { size_t i, len; len = HDstrlen(oname_dst); /* check if all the parents groups exist. skip root group */ for (i = 1; i < len; i++) { if ('/'==oname_dst[i]) { char *str_ptr; str_ptr = (char *)HDcalloc(i + 1, sizeof(char)); HDstrncpy(str_ptr, oname_dst, i); str_ptr[i]='\0'; if (H5Lexists(fid_dst, str_ptr, H5P_DEFAULT) <= 0) { error_msg("group <%s> doesn't exist. Use -p to create parent groups.\n", str_ptr); HDfree(str_ptr); goto error; } HDfree(str_ptr); } } } /*------------------------------------------------------------------------- * do the copy *-------------------------------------------------------------------------*/ if(verbose) linkinfo.opt.msg_mode = 1; li_ret = H5tools_get_symlink_info(fid_src, oname_src, &linkinfo, 1); if (li_ret == 0) /* dangling link */ { if(H5Lcopy(fid_src, oname_src, fid_dst, oname_dst, H5P_DEFAULT, H5P_DEFAULT) < 0) goto error; } else /* valid link */ { if (H5Ocopy(fid_src, /* Source file or group identifier */ oname_src, /* Name of the source object to be copied */ fid_dst, /* Destination file or group identifier */ oname_dst, /* Name of the destination object */ ocpl_id, /* Object copy property list */ lcpl_id)<0) /* Link creation property list */ goto error; } /* free link info path */ if (linkinfo.trg_path) HDfree(linkinfo.trg_path); /* close propertis */ if(H5Pclose(ocpl_id)<0) goto error; if(H5Pclose(lcpl_id)<0) goto error; /* close files */ if (H5Fclose(fid_src)<0) goto error; if (H5Fclose(fid_dst)<0) goto error; leave(EXIT_SUCCESS); error: printf("Error in copy...Exiting\n"); /* free link info path */ if (linkinfo.trg_path) HDfree(linkinfo.trg_path); H5E_BEGIN_TRY { H5Pclose(ocpl_id); H5Pclose(lcpl_id); H5Fclose(fid_src); H5Fclose(fid_dst); } H5E_END_TRY; leave(EXIT_FAILURE); }
/**************************************************************** ** ** test_grp_memb_funcs(): Test group member information ** functionality ** ****************************************************************/ static void test_grp_memb_funcs(hid_t fapl) { hid_t file; /* File ID */ hid_t dataset; /* Dataset ID */ hid_t datatype; /* Common datatype ID */ hid_t filespace; /* Common dataspace ID */ hid_t root_group,grp; /* Root group ID */ int i; /* counting variable */ char name[NAMELEN]; /* temporary name buffer */ char *dnames[NDATASETS+2];/* Names of the datasets created */ char *obj_names[NDATASETS+2];/* Names of the objects in group */ char dataset_name[NAMELEN]; /* dataset name */ ssize_t name_len; /* Length of object's name */ H5G_info_t ginfo; /* Buffer for querying object's info */ herr_t ret = SUCCEED; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Group Member Information Functionality\n")); /* Create the test file with the datasets */ file = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, fapl); CHECK(file, FAIL, "H5Fcreate"); datatype = H5Tcopy(H5T_NATIVE_INT); CHECK(datatype, FAIL, "H5Tcopy"); filespace = H5Screate(H5S_SCALAR); CHECK(filespace, FAIL, "H5Screate"); for(i = 0; i < NDATASETS; i++) { sprintf(name, "Dataset %d", i); dataset = H5Dcreate2(file, name, datatype, filespace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dcreate2"); /* Keep a copy of the dataset names around for later */ dnames[i] = HDstrdup(name); CHECK(dnames[i], NULL, "strdup"); ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); } /* end for */ /* Create a group and named datatype under root group for testing */ grp = H5Gcreate2(file, "grp", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(ret, FAIL, "H5Gcreate2"); dnames[NDATASETS] = HDstrdup("grp"); CHECK(dnames[NDATASETS], NULL, "strdup"); ret = H5Tcommit2(file, "dtype", datatype, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(ret, FAIL, "H5Tcommit2"); dnames[NDATASETS + 1] = HDstrdup("dtype"); CHECK(dnames[NDATASETS], NULL, "strdup"); /* Close everything up */ ret = H5Tclose(datatype); CHECK(ret, FAIL, "H5Tclose"); ret = H5Gclose(grp); CHECK(ret, FAIL, "H5Gclose"); ret = H5Sclose(filespace); CHECK(ret, FAIL, "H5Sclose"); ret = H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); /* Sort the dataset names */ HDqsort(dnames, (size_t)(NDATASETS + 2), sizeof(char *), iter_strcmp); /* Iterate through the datasets in the root group in various ways */ file = H5Fopen(DATAFILE, H5F_ACC_RDONLY, fapl); CHECK(file, FAIL, "H5Fopen"); /* These two functions, H5Oget_info_by_idx and H5Lget_name_by_idx, actually * iterate through B-tree for group members in internal library design. */ root_group = H5Gopen2(file, "/", H5P_DEFAULT); CHECK(root_group, FAIL, "H5Gopen2"); ret = H5Gget_info(root_group, &ginfo); CHECK(ret, FAIL, "H5Gget_info"); VERIFY(ginfo.nlinks, (NDATASETS + 2), "H5Gget_info"); for(i = 0; i < (int)ginfo.nlinks; i++) { H5O_info_t oinfo; /* Object info */ /* Test with NULL for name, to query length */ name_len = H5Lget_name_by_idx(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, NULL, (size_t)NAMELEN, H5P_DEFAULT); CHECK(name_len, FAIL, "H5Lget_name_by_idx"); ret = (herr_t)H5Lget_name_by_idx(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, dataset_name, (size_t)(name_len + 1), H5P_DEFAULT); CHECK(ret, FAIL, "H5Lget_name_by_idx"); /* Double-check that the length is the same */ VERIFY(ret, name_len, "H5Lget_name_by_idx"); /* Keep a copy of the dataset names around for later */ obj_names[i] = HDstrdup(dataset_name); CHECK(obj_names[i], NULL, "strdup"); ret = H5Oget_info_by_idx(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, &oinfo, H5P_DEFAULT); CHECK(ret, FAIL, "H5Oget_info_by_idx"); if(!HDstrcmp(dataset_name, "grp")) VERIFY(oinfo.type, H5O_TYPE_GROUP, "H5Lget_name_by_idx"); if(!HDstrcmp(dataset_name, "dtype")) VERIFY(oinfo.type, H5O_TYPE_NAMED_DATATYPE, "H5Lget_name_by_idx"); if(!HDstrncmp(dataset_name, "Dataset", (size_t)7)) VERIFY(oinfo.type, H5O_TYPE_DATASET, "H5Lget_name_by_idx"); } /* end for */ H5E_BEGIN_TRY { ret = (herr_t)H5Lget_name_by_idx(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)(NDATASETS+3), dataset_name, (size_t)NAMELEN, H5P_DEFAULT); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Lget_name_by_idx"); /* Sort the dataset names */ HDqsort(obj_names, (size_t)(NDATASETS + 2), sizeof(char *), iter_strcmp); /* Compare object names */ for(i = 0; i< (int)ginfo.nlinks; i++) { ret = HDstrcmp(dnames[i], obj_names[i]); VERIFY(ret, 0, "HDstrcmp"); } /* end for */ ret = H5Gclose(root_group); CHECK(ret, FAIL, "H5Gclose"); ret = H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); /* Free the dataset names */ for(i = 0; i< (NDATASETS + 2); i++) { HDfree(dnames[i]); HDfree(obj_names[i]); } /* end for */ } /* test_grp_memb_funcs() */
/*------------------------------------------------------------------------- * Function: main * * Purpose: h5watch * * Return: Success: 0 * Failure: 1 * * Programmer: Vailin Choi; August 2010 * *------------------------------------------------------------------------- */ int main(int argc, const char *argv[]) { char drivername[50]; char *fname = NULL; char *dname = NULL; void *edata; H5E_auto2_t func; char *x; hid_t fid = -1; hid_t fapl = -1; /* Set up tool name and exit status */ h5tools_setprogname(PROGRAMNAME); h5tools_setstatus(EXIT_SUCCESS); /* Disable error reporting */ H5Eget_auto2(H5E_DEFAULT, &func, &edata); H5Eset_auto2(H5E_DEFAULT, NULL, NULL); /* Initialize h5tools lib */ h5tools_init(); /* parse command line options */ parse_command_line(argc, argv); if(argc <= opt_ind) { error_msg("missing dataset name\n"); usage(h5tools_getprogname()); leave(EXIT_FAILURE); } /* Mostly copied from tools/h5ls coding & modified accordingly */ /* * [OBJECT] is specified as * [<filename>/<path_to_dataset>/<dsetname>] * * Example: ../dir1/foo/bar/dset * \_________/\______/ * file obj * * The dichotomy is determined by calling H5Fopen() repeatedly until it * succeeds. The first call uses the entire name and each subsequent call * chops off the last component. If we reach the beginning of the name * then there must have been something wrong with the file (perhaps it * doesn't exist). */ if((fname = HDstrdup(argv[opt_ind])) == NULL) { error_msg("memory allocation failed (file %s:line %d)\n", __FILE__, __LINE__); h5tools_setstatus(EXIT_FAILURE); } /* Create a copy of file access property list */ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) return -1; /* Set to use the latest library format */ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) return -1; do { while(fname && *fname) { fid = h5tools_fopen(fname, H5F_ACC_RDONLY|H5F_ACC_SWMR_READ, fapl, NULL, drivername, sizeof drivername); if(fid >= 0) { HDfprintf(stdout, "Opened \"%s\" with %s driver.\n", fname, drivername); break; /*success*/ } /* end if */ /* Shorten the file name; lengthen the object name */ x = dname; dname = HDstrrchr(fname, '/'); if(x) *x = '/'; if(!dname) break; *dname = '\0'; } /* end while */ /* Try opening the file again if somehow unstable */ } while(g_retry-- > 0 && fid == FAIL); if(fid < 0) { error_msg("unable to open file \"%s\"\n", fname); if(fname) HDfree(fname); if(fapl >= 0) H5Pclose(fapl); leave(EXIT_FAILURE); } if(!dname) { error_msg("no dataset specified\n"); h5tools_setstatus(EXIT_FAILURE); } else { *dname = '/'; x = dname; if((dname = HDstrdup(dname)) == NULL) { error_msg("memory allocation failed (file %s:line %d)\n", __FILE__, __LINE__); h5tools_setstatus(EXIT_FAILURE); } else { *x = '\0'; /* Validate dataset */ if(check_dataset(fid, dname) < 0) h5tools_setstatus(EXIT_FAILURE); /* Validate input "fields" */ else if(g_list_of_fields && *g_list_of_fields) if(process_cmpd_fields(fid, dname) < 0) h5tools_setstatus(EXIT_FAILURE); } } /* If everything is fine, start monitoring the datset */ if(h5tools_getstatus() != EXIT_FAILURE) if(monitor_dataset(fid, dname) < 0) h5tools_setstatus(EXIT_FAILURE); /* Free spaces */ if(fname) HDfree(fname); if(dname) HDfree(dname); if(g_list_of_fields) HDfree(g_list_of_fields); if(g_listv) { H5LD_clean_vector(g_listv); HDfree(g_listv); } if(g_dup_fields) HDfree(g_dup_fields); /* Close the file access property list */ if(fapl >= 0 && H5Pclose(fapl) < 0) { error_msg("unable to close file access property list\n"); h5tools_setstatus(EXIT_FAILURE); } /* Close the file */ if(H5Fclose(fid) < 0) { error_msg("unable to close file\n"); h5tools_setstatus(EXIT_FAILURE); } H5Eset_auto2(H5E_DEFAULT, func, edata); /* exit */ leave(h5tools_getstatus()); } /* main() */
/**************************************************************** ** ** test_iter_attr(): Test attribute iteration functionality ** ****************************************************************/ static void test_iter_attr(hid_t fapl, hbool_t new_format) { hid_t file; /* File ID */ hid_t dataset; /* Common Dataset ID */ hid_t filespace; /* Common dataspace ID */ hid_t attribute; /* Attribute ID */ int i; /* counting variable */ hsize_t idx; /* Index in the attribute list */ char name[NAMELEN]; /* temporary name buffer */ char *anames[NATTR]; /* Names of the attributes created */ iter_info info; /* Custom iteration information */ herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Attribute Iteration Functionality\n")); /* Create the test file with the datasets */ file = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, fapl); CHECK(file, FAIL, "H5Fcreate"); filespace = H5Screate(H5S_SCALAR); CHECK(filespace, FAIL, "H5Screate"); dataset = H5Dcreate2(file, "Dataset", H5T_NATIVE_INT, filespace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dcreate2"); for(i = 0; i < NATTR; i++) { sprintf(name, "Attribute %02d", i); attribute = H5Acreate2(dataset, name, H5T_NATIVE_INT, filespace, H5P_DEFAULT, H5P_DEFAULT); CHECK(attribute, FAIL, "H5Acreate2"); /* Keep a copy of the attribute names around for later */ anames[i] = HDstrdup(name); CHECK(anames[i], NULL, "strdup"); ret = H5Aclose(attribute); CHECK(ret, FAIL, "H5Aclose"); } /* end for */ /* Close everything up */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); ret = H5Sclose(filespace); CHECK(ret, FAIL, "H5Sclose"); ret = H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); /* Iterate through the attributes on the dataset in various ways */ file = H5Fopen(DATAFILE, H5F_ACC_RDONLY, fapl); CHECK(file, FAIL, "H5Fopen"); dataset = H5Dopen2(file, "Dataset", H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dopen2"); /* Test invalid indices for starting iteration */ info.command = RET_ZERO; /* Test skipping exactly as many attributes as there are */ idx = NATTR; H5E_BEGIN_TRY { ret = H5Aiterate2(dataset, H5_INDEX_NAME, H5_ITER_INC, &idx, aiter_cb, &info); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Aiterate2"); /* Test skipping more attributes than there are */ idx = NATTR + 1; H5E_BEGIN_TRY { ret = H5Aiterate2(dataset, H5_INDEX_NAME, H5_ITER_INC, &idx, aiter_cb, &info); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Aiterate2"); /* Test all attributes on dataset, when callback always returns 0 */ info.command = RET_ZERO; idx = 0; if((ret = H5Aiterate2(dataset, H5_INDEX_NAME, H5_ITER_INC, &idx, aiter_cb, &info)) > 0) TestErrPrintf("Attribute iteration function didn't return zero correctly!\n"); /* Test all attributes on dataset, when callback always returns 1 */ /* This also tests the "restarting" ability, because the index changes */ info.command = RET_TWO; idx = i = 0; while((ret = H5Aiterate2(dataset, H5_INDEX_NAME, H5_ITER_INC, &idx, aiter_cb, &info)) > 0) { /* Verify return value from iterator gets propagated correctly */ VERIFY(ret, 2, "H5Aiterate2"); /* Increment the number of times "2" is returned */ i++; /* Verify that the index is the correct value */ VERIFY(idx, (unsigned)i, "H5Aiterate2"); /* Don't check name when new format is used */ if(!new_format) { /* Verify that the correct name is retrieved */ if(HDstrcmp(info.name, anames[(size_t)idx - 1]) != 0) TestErrPrintf("%u: Attribute iteration function didn't set names correctly, info.name = '%s', anames[%u] = '%s'!\n", __LINE__, info.name, (unsigned)(idx - 1), anames[(size_t)idx - 1]); } /* end if */ } /* end while */ VERIFY(ret, -1, "H5Aiterate2"); if(i != 50 || idx != 50) TestErrPrintf("%u: Attribute iteration function didn't perform multiple iterations correctly!\n", __LINE__); /* Test all attributes on dataset, when callback changes return value */ /* This also tests the "restarting" ability, because the index changes */ info.command = new_format ? RET_CHANGE2 : RET_CHANGE; idx = i = 0; while((ret = H5Aiterate2(dataset, H5_INDEX_NAME, H5_ITER_INC, &idx, aiter_cb, &info)) > 0) { /* Verify return value from iterator gets propagated correctly */ VERIFY(ret, 1, "H5Aiterate2"); /* Increment the number of times "1" is returned */ i++; /* Verify that the index is the correct value */ VERIFY(idx, (unsigned)i + 10, "H5Aiterate2"); /* Don't check name when new format is used */ if(!new_format) { /* Verify that the correct name is retrieved */ if(HDstrcmp(info.name, anames[(size_t)idx - 1]) != 0) TestErrPrintf("%u: Attribute iteration function didn't set names correctly, info.name = '%s', anames[%u] = '%s'!\n", __LINE__, info.name, (unsigned)(idx - 1), anames[(size_t)idx - 1]); } /* end if */ } /* end while */ VERIFY(ret, -1, "H5Aiterate2"); if(i != 40 || idx != 50) TestErrPrintf("%u: Attribute iteration function didn't perform multiple iterations correctly!\n", __LINE__); ret=H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); ret=H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); /* Free the attribute names */ for(i=0; i< NATTR; i++) HDfree(anames[i]); } /* test_iter_attr() */
/**************************************************************** ** ** test_iter_group(): Test group iteration functionality ** ****************************************************************/ static void test_iter_group(hid_t fapl, hbool_t new_format) { hid_t file; /* File ID */ hid_t dataset; /* Dataset ID */ hid_t datatype; /* Common datatype ID */ hid_t filespace; /* Common dataspace ID */ hid_t root_group,grp; /* Root group ID */ int i; /* counting variable */ hsize_t idx; /* Index in the group */ char name[NAMELEN]; /* temporary name buffer */ char *lnames[NDATASETS + 2];/* Names of the links created */ char dataset_name[NAMELEN]; /* dataset name */ iter_info info; /* Custom iteration information */ H5G_info_t ginfo; /* Buffer for querying object's info */ herr_t ret; /* Generic return value */ /* Output message about test being performed */ MESSAGE(5, ("Testing Group Iteration Functionality\n")); /* Create the test file with the datasets */ file = H5Fcreate(DATAFILE, H5F_ACC_TRUNC, H5P_DEFAULT, fapl); CHECK(file, FAIL, "H5Fcreate"); /* Test iterating over empty group */ info.command = RET_ZERO; idx = 0; ret = H5Literate(file, H5_INDEX_NAME, H5_ITER_INC, &idx, liter_cb, &info); VERIFY(ret, SUCCEED, "H5Literate"); datatype = H5Tcopy(H5T_NATIVE_INT); CHECK(datatype, FAIL, "H5Tcopy"); filespace=H5Screate(H5S_SCALAR); CHECK(filespace, FAIL, "H5Screate"); for(i=0; i< NDATASETS; i++) { sprintf(name,"Dataset %d",i); dataset = H5Dcreate2(file, name, datatype, filespace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dcreate2"); /* Keep a copy of the dataset names around for later */ lnames[i] = HDstrdup(name); CHECK(lnames[i], NULL, "strdup"); ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); } /* end for */ /* Create a group and named datatype under root group for testing */ grp = H5Gcreate2(file, "grp", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(ret, FAIL, "H5Gcreate2"); lnames[NDATASETS] = HDstrdup("grp"); CHECK(lnames[NDATASETS], NULL, "strdup"); ret = H5Tcommit2(file, "dtype", datatype, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(ret, FAIL, "H5Tcommit2"); lnames[NDATASETS + 1] = HDstrdup("dtype"); CHECK(lnames[NDATASETS], NULL, "strdup"); /* Close everything up */ ret = H5Tclose(datatype); CHECK(ret, FAIL, "H5Tclose"); ret = H5Gclose(grp); CHECK(ret, FAIL, "H5Gclose"); ret = H5Sclose(filespace); CHECK(ret, FAIL, "H5Sclose"); ret = H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); /* Sort the dataset names */ HDqsort(lnames, (size_t)(NDATASETS + 2), sizeof(char *), iter_strcmp); /* Iterate through the datasets in the root group in various ways */ file = H5Fopen(DATAFILE, H5F_ACC_RDONLY, fapl); CHECK(file, FAIL, "H5Fopen"); /* These two functions, H5Oget_info_by_idx and H5Lget_name_by_idx, actually * iterate through B-tree for group members in internal library design. */ root_group = H5Gopen2(file, "/", H5P_DEFAULT); CHECK(root_group, FAIL, "H5Gopen2"); ret = H5Gget_info(root_group, &ginfo); CHECK(ret, FAIL, "H5Gget_info"); VERIFY(ginfo.nlinks, (NDATASETS + 2), "H5Gget_info"); for(i = 0; i< (int)ginfo.nlinks; i++) { H5O_info_t oinfo; /* Object info */ ret = (herr_t)H5Lget_name_by_idx(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, dataset_name, (size_t)NAMELEN, H5P_DEFAULT); CHECK(ret, FAIL, "H5Lget_name_by_idx"); ret = H5Oget_info_by_idx(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, &oinfo, H5P_DEFAULT); CHECK(ret, FAIL, "H5Oget_info_by_idx"); } /* end for */ H5E_BEGIN_TRY { ret = (herr_t)H5Lget_name_by_idx(root_group, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)(NDATASETS+3), dataset_name, (size_t)NAMELEN, H5P_DEFAULT); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Lget_name_by_idx"); ret = H5Gclose(root_group); CHECK(ret, FAIL, "H5Gclose"); /* These two functions, H5Oget_info_by_idx and H5Lget_name_by_idx, actually * iterate through B-tree for group members in internal library design. * (Same as test above, but with the file ID instead of opening the root group) */ ret = H5Gget_info(file, &ginfo); CHECK(ret, FAIL, "H5Gget_info"); VERIFY(ginfo.nlinks, NDATASETS + 2, "H5Gget_info"); for(i = 0; i< (int)ginfo.nlinks; i++) { H5O_info_t oinfo; /* Object info */ ret = (herr_t)H5Lget_name_by_idx(file, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, dataset_name, (size_t)NAMELEN, H5P_DEFAULT); CHECK(ret, FAIL, "H5Lget_name_by_idx"); ret = H5Oget_info_by_idx(file, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)i, &oinfo, H5P_DEFAULT); CHECK(ret, FAIL, "H5Oget_info_by_idx"); } /* end for */ H5E_BEGIN_TRY { ret = (herr_t)H5Lget_name_by_idx(file, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)(NDATASETS + 3), dataset_name, (size_t)NAMELEN, H5P_DEFAULT); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Lget_name_by_idx"); /* Test invalid indices for starting iteration */ info.command = RET_ZERO; idx = (hsize_t)-1; H5E_BEGIN_TRY { ret = H5Literate(file, H5_INDEX_NAME, H5_ITER_INC, &idx, liter_cb, &info); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Literate"); /* Test skipping exactly as many entries as in the group */ idx = NDATASETS + 2; H5E_BEGIN_TRY { ret = H5Literate(file, H5_INDEX_NAME, H5_ITER_INC, &idx, liter_cb, &info); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Literate"); /* Test skipping more entries than are in the group */ idx = NDATASETS + 3; H5E_BEGIN_TRY { ret = H5Literate(file, H5_INDEX_NAME, H5_ITER_INC, &idx, liter_cb, &info); } H5E_END_TRY; VERIFY(ret, FAIL, "H5Literate"); /* Test all objects in group, when callback always returns 0 */ info.command = RET_ZERO; idx = 0; if((ret = H5Literate(file, H5_INDEX_NAME, H5_ITER_INC, &idx, liter_cb, &info)) > 0) TestErrPrintf("Group iteration function didn't return zero correctly!\n"); /* Test all objects in group, when callback always returns 1 */ /* This also tests the "restarting" ability, because the index changes */ info.command = RET_TWO; idx = i = 0; while((ret = H5Literate(file, H5_INDEX_NAME, H5_ITER_INC, &idx, liter_cb, &info)) > 0) { /* Verify return value from iterator gets propagated correctly */ VERIFY(ret, 2, "H5Literate"); /* Increment the number of times "2" is returned */ i++; /* Verify that the index is the correct value */ VERIFY(idx, (hsize_t)i, "H5Literate"); if(idx > (NDATASETS + 2)) TestErrPrintf("Group iteration function walked too far!\n"); /* Verify that the correct name is retrieved */ if(HDstrcmp(info.name, lnames[(size_t)(idx - 1)]) != 0) TestErrPrintf("Group iteration function didn't return name correctly for link - lnames[%u] = '%s'!\n", (unsigned)(idx - 1), lnames[(size_t)(idx - 1)]); } /* end while */ VERIFY(ret, -1, "H5Literate"); if(i != (NDATASETS + 2)) TestErrPrintf("%u: Group iteration function didn't perform multiple iterations correctly!\n", __LINE__); /* Test all objects in group, when callback changes return value */ /* This also tests the "restarting" ability, because the index changes */ info.command = new_format ? RET_CHANGE2 : RET_CHANGE; idx = i = 0; while((ret = H5Literate(file, H5_INDEX_NAME, H5_ITER_INC, &idx, liter_cb, &info)) >= 0) { /* Verify return value from iterator gets propagated correctly */ VERIFY(ret, 1, "H5Literate"); /* Increment the number of times "1" is returned */ i++; /* Verify that the index is the correct value */ VERIFY(idx, (hsize_t)(i + 10), "H5Literate"); if(idx > (NDATASETS + 2)) TestErrPrintf("Group iteration function walked too far!\n"); /* Verify that the correct name is retrieved */ if(HDstrcmp(info.name, lnames[(size_t)(idx - 1)]) != 0) TestErrPrintf("Group iteration function didn't return name correctly for link - lnames[%u] = '%s'!\n", (unsigned)(idx - 1), lnames[(size_t)(idx - 1)]); } /* end while */ VERIFY(ret, -1, "H5Literate"); if(i != 42 || idx != 52) TestErrPrintf("%u: Group iteration function didn't perform multiple iterations correctly!\n", __LINE__); ret = H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); /* Free the dataset names */ for(i = 0; i< (NDATASETS + 2); i++) HDfree(lnames[i]); } /* test_iter_group() */
/*------------------------------------------------------------------------- * Function: parse_command_line * * Purpose: Parses command line and sets up global variable to control output * * Return: Success: 0 * * Failure: -1 * * Programmer: Elena Pourmal * Saturday, August 12, 2006 * *------------------------------------------------------------------------- */ static struct handler_t * parse_command_line(int argc, const char *argv[]) { int opt, i; struct handler_t *hand; /* Allocate space to hold the command line info */ hand = (struct handler_t *)calloc((size_t)argc, sizeof(struct handler_t)); /* parse command line options */ while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { switch ((char)opt) { case 'A': display_all = FALSE; display_attr = TRUE; break; case 'F': display_all = FALSE; display_file_metadata = TRUE; break; case 'f': display_all = FALSE; display_file = TRUE; break; case 'G': display_all = FALSE; break; case 'g': display_all = FALSE; display_group = TRUE; break; case 'T': display_all = FALSE; display_dtype_metadata = TRUE; break; case 'D': display_all = FALSE; break; case 'd': display_all = FALSE; display_dset = TRUE; break; case 'h': usage(progname); leave(EXIT_SUCCESS); case 'V': print_version(progname); leave(EXIT_SUCCESS); break; case 'O': display_object = TRUE; for(i = 0; i < argc; i++) if(!hand[i].obj) { hand[i].obj = HDstrdup(opt_arg); break; } /* end if */ break; default: usage(progname); leave(EXIT_FAILURE); } /* end switch */ } /* end while */ /* check for file name to be processed */ if (argc <= opt_ind) { error_msg(progname, "missing file name\n"); usage(progname); leave(EXIT_FAILURE); } /* end if */ return hand; }
/* * Function: h5_set_info_object * Purpose: Process environment variables setting to set up MPI Info * object. * Return: 0 if all is fine; otherwise non-zero. * Programmer: Albert Cheng, 2002/05/21. * Modifications: * Bill Wendling, 2002/05/31 * Modified so that the HDF5_MPI_INFO environment variable can * be a semicolon separated list of "key=value" pairings. Most * of the code is to remove any whitespaces which might be * surrounding the "key=value" pairs. */ int h5_set_info_object(void) { char *envp; /* environment pointer */ int ret_value=0; /* handle any MPI INFO hints via $HDF5_MPI_INFO */ if ((envp = getenv("HDF5_MPI_INFO")) != NULL){ char *next, *valp; valp = envp = next = HDstrdup(envp); if (!valp) return 0; /* create an INFO object if not created yet */ if (h5_io_info_g == MPI_INFO_NULL) MPI_Info_create(&h5_io_info_g); do { size_t len; char *key_val, *endp, *namep; if (*valp == ';') valp++; /* copy key/value pair into temporary buffer */ len = strcspn(valp, ";"); next = &valp[len]; key_val = (char *)HDcalloc(1, len + 1); /* increment the next pointer past the terminating semicolon */ if (*next == ';') ++next; namep = HDstrncpy(key_val, valp, len); /* pass up any beginning whitespaces */ while (*namep && (*namep == ' ' || *namep == '\t')) namep++; if (!*namep) continue; /* was all white space, so move to next k/v pair */ /* eat up any ending white spaces */ endp = &namep[HDstrlen(namep) - 1]; while (endp && (*endp == ' ' || *endp == '\t')) *endp-- = '\0'; /* find the '=' */ valp = HDstrchr(namep, '='); if (valp != NULL) { /* it's a valid key/value pairing */ char *tmp_val = valp + 1; /* change '=' to \0, move valp down one */ *valp-- = '\0'; /* eat up ending whitespace on the "key" part */ while (*valp == ' ' || *valp == '\t') *valp-- = '\0'; valp = tmp_val; /* eat up beginning whitespace on the "value" part */ while (*valp == ' ' || *valp == '\t') *valp++ = '\0'; /* actually set the darned thing */ if (MPI_SUCCESS != MPI_Info_set(h5_io_info_g, namep, valp)) { printf("MPI_Info_set failed\n"); ret_value = -1; } } valp = next; HDfree(key_val); } while (next && *next); HDfree(envp); } return ret_value; }
/*------------------------------------------------------------------------- * Function: process_cmpd_fields * * Purpose: To check whether the fields selected in "g_list_of_fields" * are valid fields associated with the dataset. * * Return: 0 on success; negative on failure * * Programmer: Vailin Choi; August 2010 * *------------------------------------------------------------------------- */ static herr_t process_cmpd_fields(hid_t fid, char *dsetname) { hid_t did=-1; /* dataset id */ hid_t dtid=-1, tid=-1; /* dataset's data type id */ size_t len; /* number of comma-separated fields in "g_list_of_fields" */ herr_t ret_value = SUCCEED; /* Return value */ HDassert(g_list_of_fields && *g_list_of_fields); /* Open the dataset */ if((did = H5Dopen2(fid, dsetname, H5P_DEFAULT)) < 0) { error_msg("error in opening dataset \"%s\"\n", dsetname); ret_value = FAIL; goto done; } /* Get the dataset's datatype */ if(((dtid = H5Dget_type(did)) < 0) || (tid = H5Tget_native_type(dtid, H5T_DIR_DEFAULT)) < 0) { error_msg("error in getting dataset's datatype\n"); ret_value = FAIL; goto done; } /* Check to make sure that the dataset's datatype is compound type */ if(H5Tget_class(dtid) != H5T_COMPOUND) { error_msg("dataset should be compound type for <list_of_fields>\n"); ret_value = FAIL; goto done; } /* Make a copy of "g_list_of_fields" */ if((g_dup_fields = HDstrdup(g_list_of_fields)) == NULL) { error_msg("error in duplicating g_list_of_fields\n"); ret_value = FAIL; goto done; } /* Estimate the number of comma-separated fields in "g_list of_fields" */ len = HDstrlen(g_list_of_fields)/2 + 2; /* Allocate memory for a list vector of H5LD_memb_t structures to store "g_list_of_fields" info */ if((g_listv = (H5LD_memb_t **)HDcalloc(len, sizeof(H5LD_memb_t *))) == NULL) { error_msg("error in allocating memory for H5LD_memb_t\n"); ret_value = FAIL; goto done; } /* Process and store info for "g_listv" */ if(H5LD_construct_vector(g_dup_fields, g_listv, tid) < 0) { error_msg("error in processing <list_of_fields>\n"); ret_value = FAIL; goto done; } /* Will free memory for g_listv and g_dup_fields when exiting from h5watch */ done: /* Closing */ H5E_BEGIN_TRY H5Tclose(dtid); H5Tclose(tid); H5Dclose(did); H5E_END_TRY return(ret_value); } /* process_cmpd_fields() */
/*------------------------------------------------------------------------- * Function: parse_command_line * * Purpose: Parse the command line for the h5dumper. * * Return: Success: EXIT_SUCCESS; * * Failure: Exits function with EXIT_FAILURE value. * *------------------------------------------------------------------------- */ static int parse_command_line(int argc, const char *argv[]) { int opt = FALSE; /* parse command line options */ while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { switch((char)opt) { case 'o': output_file = HDstrdup(opt_arg); if (output_file) h5tools_set_data_output_file(output_file, 1); break; case 'i': input_file = HDstrdup(opt_arg); if (input_file) h5tools_set_input_file(input_file, 1); break;; case 'u': ub_file = HDstrdup(opt_arg); if (ub_file) h5tools_set_output_file(ub_file, 1); else rawoutstream = stdout; break; case 'd': do_delete = TRUE; break; case 'h': usage(h5tools_getprogname()); h5tools_setstatus(EXIT_SUCCESS); goto done; case 'V': print_version (h5tools_getprogname()); h5tools_setstatus(EXIT_SUCCESS); goto done; case '?': default: usage(h5tools_getprogname()); h5tools_setstatus(EXIT_FAILURE); goto done; } } return EXIT_SUCCESS; done: if(input_file) HDfree(input_file); if(output_file) HDfree(output_file); if(ub_file) HDfree(ub_file); return EXIT_FAILURE; }
/*------------------------------------------------------------------------- * Function: parse_command_line * * Purpose: Parses command line and sets up global variable to control output * * Return: Success: 0 * * Failure: -1 * * Programmer: Elena Pourmal * Saturday, August 12, 2006 * *------------------------------------------------------------------------- */ static struct handler_t * parse_command_line(int argc, const char *argv[]) { int opt, i; struct handler_t *hand = NULL; /* Allocate space to hold the command line info */ if((hand = (struct handler_t *)HDcalloc((size_t)argc, sizeof(struct handler_t)))==NULL) { error_msg("unable to parse command line arguments \n"); goto error; } /* parse command line options */ while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { switch ((char)opt) { case 'h': usage(h5tools_getprogname()); h5tools_setstatus(EXIT_SUCCESS); if (hand) { for (i = 0; i < argc; i++) if(hand[i].obj) { free(hand[i].obj); hand[i].obj=NULL; } free(hand); hand = NULL; } goto done; break; case 'V': print_version(h5tools_getprogname()); h5tools_setstatus(EXIT_SUCCESS); if (hand) { for (i = 0; i < argc; i++) if(hand[i].obj) { free(hand[i].obj); hand[i].obj=NULL; } free(hand); hand = NULL; } goto done; break; case 'F': display_all = FALSE; display_file_metadata = TRUE; break; case 'f': display_all = FALSE; display_file = TRUE; break; case 'G': display_all = FALSE; display_group_metadata = TRUE; break; case 'g': display_all = FALSE; display_group = TRUE; break; case 'D': display_all = FALSE; display_dset_metadata = TRUE; break; case 'd': display_all = FALSE; display_dset = TRUE; break; case 'T': display_all = FALSE; display_dset_dtype_meta = TRUE; break; case 'A': display_all = FALSE; display_attr = TRUE; break; case 'S': display_all = FALSE; display_summary = TRUE; break; case 'O': display_all = FALSE; display_object = TRUE; for(i = 0; i < argc; i++) if(!hand[i].obj) { hand[i].obj = HDstrdup(opt_arg); break; } /* end if */ break; default: usage(h5tools_getprogname()); h5tools_setstatus(EXIT_FAILURE); goto error; } /* end switch */ } /* end while */ /* check for file name to be processed */ if (argc <= opt_ind) { error_msg("missing file name\n"); usage(h5tools_getprogname()); h5tools_setstatus(EXIT_FAILURE); goto error; } /* end if */ done: return hand; error: if (hand) { for (i = 0; i < argc; i++) if(hand[i].obj) { free(hand[i].obj); hand[i].obj=NULL; } free(hand); hand = NULL; } h5tools_setstatus(EXIT_FAILURE); return hand; }