diff options
Diffstat (limited to 'tools')
38 files changed, 662 insertions, 1108 deletions
diff --git a/tools/h5copy/h5copy.c b/tools/h5copy/h5copy.c index cadb0d0..216b2bb 100644 --- a/tools/h5copy/h5copy.c +++ b/tools/h5copy/h5copy.c @@ -199,8 +199,8 @@ main (int argc, const char *argv[]) unsigned flag=0; unsigned verbose=0; unsigned parents=0; - hid_t ocpl_id; /* Object copy property list */ - hid_t lcpl_id; /* Link creation property list */ + hid_t ocpl_id = (-1); /* Object copy property list */ + hid_t lcpl_id = (-1); /* Link creation property list */ char str_flag[20]; int opt; diff --git a/tools/h5dump/h5dump.c b/tools/h5dump/h5dump.c index c69c5d70..28534bf 100644 --- a/tools/h5dump/h5dump.c +++ b/tools/h5dump/h5dump.c @@ -3952,7 +3952,7 @@ main(int argc, const char *argv[]) /* allocate and initialize internal data structure */ init_prefix(&prefix, prefix_len); - /* find all objects that might be targets of a reference */ + /* Prepare to find objects that might be targets of a reference */ fill_ref_path_table(fid); if(doxml) { @@ -4094,7 +4094,6 @@ done: free_table(type_table); HDfree(prefix); - HDfree(info.prefix); HDfree(fname); /* To Do: clean up XML table */ @@ -5342,8 +5341,7 @@ xml_dump_group(hid_t gid, const char *name) if(HDstrcmp(name, "/") == 0) { isRoot = 1; - tmp = HDmalloc(2); - HDstrcpy(tmp, "/"); + tmp = HDstrdup("/"); } else { tmp = HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2); HDstrcpy(tmp, prefix); @@ -5401,8 +5399,8 @@ xml_dump_group(hid_t gid, const char *name) ptrstr = malloc(100); t_objname = xml_escape_the_name(found_obj->objname); par_name = xml_escape_the_name(par); - xml_name_to_XID(par,parentxid,100,1); - xml_name_to_XID(found_obj->objname,ptrstr,100,1); + xml_name_to_XID(found_obj->objname, ptrstr, 100, 1); + xml_name_to_XID(par, parentxid, 100, 1); printf("<%sGroupPtr OBJ-XID=\"%s\" H5Path=\"%s\" " "Parents=\"%s\" H5ParentPaths=\"%s\" />\n", xmlnsprefix, diff --git a/tools/h5ls/h5ls.c b/tools/h5ls/h5ls.c index 2c56cb5..80b45d8 100644 --- a/tools/h5ls/h5ls.c +++ b/tools/h5ls/h5ls.c @@ -27,6 +27,15 @@ #include "H5private.h" #include "h5tools.h" #include "h5tools_utils.h" +#include "h5trav.h" + +#define NAME_BUF_SIZE 2048 + +/* Struct to pass through to visitors */ +typedef struct { + hid_t fid; /* File ID */ + const char *fname; /* Filename */ +}iter_t; /* Command-line switches */ static int verbose_g = 0; /* lots of extra output */ @@ -43,21 +52,7 @@ static hbool_t show_errors_g = FALSE; /* print HDF5 error messages */ static hbool_t simple_output_g = FALSE; /* make output more machine-readable */ static hbool_t show_file_name_g = FALSE; /* show file name for full names */ static hbool_t no_line_wrap_g = FALSE; /* show data content without line wrap */ - -/* Info to pass to the iteration functions */ -typedef struct iter_t { - const char *container; /* full name of the container object */ -} iter_t; - -/* Table containing object id and object name */ -static struct { - int nalloc; /* number of slots allocated */ - int nobjs; /* number of objects */ - struct { - haddr_t id; /* object number */ - char *name; /* full object name */ - } *obj; -} idtab_g; +static hbool_t display_root_g = FALSE; /* show root group in output? */ /* Information about how to display each type of object */ static struct dispatch_t { @@ -68,17 +63,13 @@ static struct dispatch_t { herr_t (*list2)(hid_t obj, const char *name); } dispatch_g[H5O_TYPE_NTYPES]; -#define DISPATCH(TYPE, NAME, OPEN, CLOSE, LIST1, LIST2) { \ +#define DISPATCH(TYPE, NAME, LIST1, LIST2) { \ dispatch_g[TYPE].name = (NAME); \ - dispatch_g[TYPE].open = (OPEN); \ - dispatch_g[TYPE].close = (CLOSE); \ dispatch_g[TYPE].list1 = (LIST1); \ dispatch_g[TYPE].list2 = (LIST2); \ } -static herr_t list(hid_t group, const char *name, const H5L_info_t *linfo, void *cd); static void display_type(hid_t type, int ind); -static char *fix_name(const char *path, const char *base); const char *progname="h5ls"; int d_status; @@ -131,76 +122,6 @@ usage: %s [OPTIONS] [OBJECTS...]\n\ /*------------------------------------------------------------------------- - * Function: sym_insert - * - * Purpose: Add a symbol to the table. - * - * Return: void - * - * Programmer: Robb Matzke - * Thursday, January 21, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static void -sym_insert(const H5O_info_t *oi, const char *name) -{ - int n; - - /* Don't add it if the link count is 1 because such an object can only - * have one name. */ - if(oi->rc < 2) - return; - - /* Extend the table */ - if(idtab_g.nobjs >= idtab_g.nalloc) { - idtab_g.nalloc = MAX(256, 2*idtab_g.nalloc); - idtab_g.obj = realloc(idtab_g.obj, idtab_g.nalloc*sizeof(idtab_g.obj[0])); - } /* end if */ - - /* Insert the entry */ - n = idtab_g.nobjs++; - idtab_g.obj[n].id = oi->addr; - idtab_g.obj[n].name = HDstrdup(name); -} - - -/*------------------------------------------------------------------------- - * Function: sym_lookup - * - * Purpose: Find another name for the specified object. - * - * Return: Success: Ptr to another name. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Thursday, January 21, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static char * -sym_lookup(const H5O_info_t *oi) -{ - int n; - - /*only one name possible*/ - if(oi->rc < 2) - return NULL; - - for(n = 0; n < idtab_g.nobjs; n++) - if(idtab_g.obj[n].id == oi->addr) - return idtab_g.obj[n].name; - - return NULL; -} - - -/*------------------------------------------------------------------------- * Function: display_string * * Purpose: Print a string value by escaping unusual characters. If @@ -278,6 +199,55 @@ display_string(FILE *stream, const char *s, hbool_t escape_spaces) /*------------------------------------------------------------------------- + * Function: display_obj_name + * + * Purpose: Print an object name and another string. + * + * Return: Success: TRUE + * + * Failure: FALSE, nothing printed + * + * Programmer: Quincey Koziol + * Tuesday, November 6, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +display_obj_name(FILE *stream, const iter_t *iter, const char *oname, + const char *s) +{ + static char fullname[NAME_BUF_SIZE]; /* Buffer for file and/or object name */ + const char *name = fullname; /* Pointer to buffer for printing */ + int n; + + if(show_file_name_g) + sprintf(fullname, "%s/%s", iter->fname, oname); + else + name = oname; + + /* Print the object name, either full name or base name */ + if(fullname_g) + n = display_string(stream, name, TRUE); + else { + const char *last_sep; /* The location of the last group separator */ + + /* Find the last component of the path name */ + if(NULL == (last_sep = HDstrrchr(name, '/'))) + last_sep = name; + else { + last_sep++; + } /* end else */ + n = display_string(stream, last_sep, TRUE); + } /* end else */ + printf("%*s ", MAX(0, (24 - n)), s); + + return TRUE; +} + + +/*------------------------------------------------------------------------- * Function: display_native_type * * Purpose: Prints the name of a native C data type. @@ -1326,7 +1296,7 @@ list_attr(hid_t obj, const char *attr_name, const H5A_info_t UNUSED *ainfo, void UNUSED *op_data) { hid_t attr, space, type, p_type; - hsize_t size[64], nelmts = 1; + hsize_t size[H5S_MAX_RANK], nelmts = 1; int ndims, i, n; size_t need; hsize_t temp_need; @@ -1460,8 +1430,8 @@ list_attr(hid_t obj, const char *attr_name, const H5A_info_t UNUSED *ainfo, static herr_t dataset_list1(hid_t dset) { - hsize_t cur_size[64]; /* current dataset dimensions */ - hsize_t max_size[64]; /* maximum dataset dimensions */ + hsize_t cur_size[H5S_MAX_RANK]; /* current dataset dimensions */ + hsize_t max_size[H5S_MAX_RANK]; /* maximum dataset dimensions */ hid_t space; /* data space */ int ndims; /* dimensionality */ H5S_class_t space_type; /* type of dataspace */ @@ -1524,7 +1494,6 @@ dataset_list2(hid_t dset, const char UNUSED *name) off_t f_offset; /* offset in external file */ hsize_t f_size; /* bytes used in external file */ hsize_t total, used; /* total size or offset */ - hsize_t chsize[64]; /* chunk size in elements */ int ndims; /* dimensionality */ int n, max_len; /* max extern file name length */ double utilization; /* percent utilization of storage */ @@ -1537,6 +1506,8 @@ dataset_list2(hid_t dset, const char UNUSED *name) /* Print information about chunked storage */ if (H5D_CHUNKED==H5Pget_layout(dcpl)) { + hsize_t chsize[64]; /* chunk size in elements */ + ndims = H5Pget_chunk(dcpl, NELMTS(chsize), chsize/*out*/); printf(" %-10s {", "Chunks:"); total = H5Tget_size(type); @@ -1645,39 +1616,9 @@ dataset_list2(hid_t dset, const char UNUSED *name) /*------------------------------------------------------------------------- - * Function: group_list2 - * - * Purpose: List information about a group which should appear after - * information which is general to all objects. - * - * Return: Success: 0 - * - * Failure: -1 - * - * Programmer: Robb Matzke - * Thursday, January 21, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -group_list2(hid_t grp, const char *name) -{ - iter_t iter; - - if (recursive_g) { - iter.container = name; - H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, NULL, list, &iter); - } - return 0; -} - - -/*------------------------------------------------------------------------- * Function: datatype_list2 * - * Purpose: List information about a data type which should appear after + * Purpose: List information about a datatype which should appear after * information which is general to all objects. * * Return: Success: 0 @@ -1704,80 +1645,56 @@ datatype_list2(hid_t type, const char UNUSED *name) /*------------------------------------------------------------------------- - * Function: list + * Function: list_obj * - * Purpose: Prints the group member name. + * Purpose: Prints information about an object * * Return: Success: 0 * * Failure: -1 * - * Programmer: Robb Matzke - * Monday, March 23, 1998 + * Programmer: Quincey Koziol + * Tuesday, November 6, 2007 * - * Modifications: - * Robb Matzke, LLNL, 2003-06-06 - * If simple_output_g (set by `--simple') is turned on then - * the modification time is printed as UTC instead of the - * local timezone. *------------------------------------------------------------------------- */ static herr_t -list(hid_t group, const char *name, const H5L_info_t *linfo, void *_iter) +list_obj(const char *name, const H5O_info_t *oinfo, const char *first_seen, void *_iter) { + H5O_type_t obj_type = oinfo->type; /* Type of the object */ iter_t *iter = (iter_t*)_iter; - char *fullname = NULL; - int n; - /* Print the object name, either full name or base name */ - fullname = fix_name(iter->container, name); - if(fullname_g) - n = display_string(stdout, fullname, TRUE); - else - n = display_string(stdout, name, TRUE); - printf("%*s ", MAX(0, (24 - n)), ""); - - /* Actions on objects */ - if(linfo->type == H5L_TYPE_HARD) { - H5O_info_t oi; - char *s; - hid_t obj; - - /* Get object information */ - if(H5Oget_info_by_name(group, name, &oi, H5P_DEFAULT) < 0) { - puts("**NOT FOUND**"); - return 0; - } else if(oi.type < 0 || oi.type >= H5O_TYPE_NTYPES) { - printf("Unknown type(%d)", (int)oi.type); - oi.type = H5O_TYPE_UNKNOWN; - } - if(oi.type >= 0 && dispatch_g[oi.type].name) - fputs(dispatch_g[oi.type].name, stdout); - - /* If the object has already been printed then just show the object ID - * and return. */ - if((s = sym_lookup(&oi))) { - printf(", same as "); - display_string(stdout, s, TRUE); - printf("\n"); - goto done; - } /* end if */ - else - sym_insert(&oi, fullname); + /* Print the link's name, either full name or base name */ + display_obj_name(stdout, iter, name, ""); + + /* Check object information */ + if(oinfo->type < 0 || oinfo->type >= H5O_TYPE_NTYPES) { + printf("Unknown type(%d)", (int)oinfo->type); + obj_type = H5O_TYPE_UNKNOWN; + } + if(obj_type >= 0 && dispatch_g[obj_type].name) + fputs(dispatch_g[obj_type].name, stdout); + + /* Check if we've seen this object before */ + if(first_seen) { + printf(", same as "); + display_string(stdout, first_seen, TRUE); + printf("\n"); + } /* end if */ + else { + hid_t obj = (-1); /* ID of object opened */ /* Open the object. Not all objects can be opened. If this is the case * then return right away. */ - if(oi.type >= 0 && - (NULL == dispatch_g[oi.type].open || - (obj = (dispatch_g[oi.type].open)(group, name, H5P_DEFAULT)) < 0)) { + if(obj_type >= 0 && (obj = H5Oopen(iter->fid, name, H5P_DEFAULT)) < 0) { printf(" *ERROR*\n"); goto done; } /* end if */ /* List the first line of information for the object. */ - if(oi.type >= 0 && dispatch_g[oi.type].list1) - (dispatch_g[oi.type].list1)(obj); + if(obj_type >= 0 && dispatch_g[obj_type].list1) + (dispatch_g[obj_type].list1)(obj); putchar('\n'); /* Show detailed information about the object, beginning with information @@ -1786,22 +1703,22 @@ list(hid_t group, const char *name, const H5L_info_t *linfo, void *_iter) char comment[50]; /* Display attributes */ - if(oi.type >= 0) + if(obj_type >= 0) H5Aiterate2(obj, H5_INDEX_NAME, H5_ITER_INC, NULL, list_attr, NULL); /* Object location & reference count */ - printf(" %-10s %lu:"H5_PRINTF_HADDR_FMT"\n", "Location:", oi.fileno, oi.addr); - printf(" %-10s %u\n", "Links:", (unsigned)oi.rc); + printf(" %-10s %lu:"H5_PRINTF_HADDR_FMT"\n", "Location:", oinfo->fileno, oinfo->addr); + printf(" %-10s %u\n", "Links:", (unsigned)oinfo->rc); /* Modification time */ - if(oi.mtime > 0) { + if(oinfo->mtime > 0) { char buf[256]; struct tm *tm; if(simple_output_g) - tm = HDgmtime(&(oi.mtime)); + tm = HDgmtime(&(oinfo->mtime)); else - tm = HDlocaltime(&(oi.mtime)); + tm = HDlocaltime(&(oinfo->mtime)); if(tm) { HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm); printf(" %-10s %s\n", "Modified:", buf); @@ -1810,7 +1727,7 @@ list(hid_t group, const char *name, const H5L_info_t *linfo, void *_iter) /* Object comment */ comment[0] = '\0'; - H5Oget_comment_by_name(group, name, comment, sizeof(comment), H5P_DEFAULT); + H5Oget_comment(obj, comment, sizeof(comment)); HDstrcpy(comment + sizeof(comment) - 4, "..."); if(comment[0]) { printf(" %-10s \"", "Comment:"); @@ -1820,118 +1737,91 @@ list(hid_t group, const char *name, const H5L_info_t *linfo, void *_iter) } /* end if */ /* Detailed list for object */ - if(oi.type >= 0 && dispatch_g[oi.type].list2) - (dispatch_g[oi.type].list2)(obj, fullname); + if(obj_type >= 0 && dispatch_g[obj_type].list2) + (dispatch_g[obj_type].list2)(obj, name); /* Close the object. */ - if(oi.type >= 0 && dispatch_g[oi.type].close) - (dispatch_g[oi.type].close)(obj); - } /* end if */ - /* Actions on links */ - else { - char *buf; - - HDfputs("-> ", stdout); - switch(linfo->type) { - case H5L_TYPE_SOFT: - if((buf = HDmalloc(linfo->u.val_size)) == NULL) - goto done; - - if(H5Lget_val(group, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) { - HDfree(buf); - goto done; - } /* end if */ - - HDfputs(buf, stdout); - HDfree(buf); - break; - - case H5L_TYPE_EXTERNAL: - { - const char *filename; - const char *path; - - if((buf = HDmalloc(linfo->u.val_size)) == NULL) - goto done; - - if(H5Lget_val(group, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) { - HDfree(buf); - goto done; - } /* end if */ - if(H5Lunpack_elink_val(buf, linfo->u.val_size, NULL, &filename, &path) < 0) { - HDfree(buf); - goto done; - } /* end if */ - - HDfputs("file: ", stdout); - HDfputs(filename, stdout); - HDfputs(" path: ", stdout); - HDfputs(path, stdout); - } - break; - - default: - HDfputs("cannot follow UD links", stdout); - break; - } /* end switch */ - HDfputc('\n', stdout); + if(obj_type >= 0) + H5Oclose(obj); } /* end else */ done: - if(fullname) - free(fullname); return 0; -} /* end list() */ +} /* end list_obj() */ /*------------------------------------------------------------------------- - * Function: fix_name + * Function: list_lnk * - * Purpose: Returns a malloc'd buffer that contains the PATH and BASE - * names separated by a single slash. It also removes duplicate - * and trailing slashes. + * Purpose: Prints information about a link * - * Return: Success: Ptr to fixed name from malloc() - * - * Failure: NULL + * Return: Success: 0 * - * Programmer: Robb Matzke - * Thursday, January 21, 1999 + * Failure: -1 * - * Modifications: + * Programmer: Quincey Koziol + * Thursday, November 8, 2007 * *------------------------------------------------------------------------- */ -static char * -fix_name(const char *path, const char *base) +static herr_t +list_lnk(const char *name, const H5L_info_t *linfo, void *_iter) { - size_t n = (path ? HDstrlen(path) : 0) + (base ? HDstrlen(base) : 0) + 3; - char *s = HDmalloc(n), prev='\0'; - size_t len = 0; - - if (path) { - /* Path, followed by slash */ - for (/*void*/; *path; path++) - if ('/'!=*path || '/'!=prev) - prev = s[len++] = *path; - if ('/' != prev) - prev = s[len++] = '/'; - } + char *buf; + iter_t *iter = (iter_t*)_iter; - if (base) { - /* Base name w/o trailing slashes */ - const char *end = base + HDstrlen(base); - while (end > base && '/' == end[-1]) - --end; + /* Print the link's name, either full name or base name */ + display_obj_name(stdout, iter, name, ""); - for (/*void*/; base < end; base++) - if ('/' != *base || '/' != prev) - prev = s[len++] = *base; - } + HDfputs("-> ", stdout); + switch(linfo->type) { + case H5L_TYPE_SOFT: + if((buf = HDmalloc(linfo->u.val_size)) == NULL) + goto done; - s[len] = '\0'; - return s; -} + if(H5Lget_val(iter->fid, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) { + HDfree(buf); + goto done; + } /* end if */ + + HDfputs(buf, stdout); + HDfree(buf); + break; + + case H5L_TYPE_EXTERNAL: + { + const char *filename; + const char *path; + + if((buf = HDmalloc(linfo->u.val_size)) == NULL) + goto done; + + if(H5Lget_val(iter->fid, name, buf, linfo->u.val_size, H5P_DEFAULT) < 0) { + HDfree(buf); + goto done; + } /* end if */ + if(H5Lunpack_elink_val(buf, linfo->u.val_size, NULL, &filename, &path) < 0) { + HDfree(buf); + goto done; + } /* end if */ + + HDfputs("file: ", stdout); + HDfputs(filename, stdout); + HDfputs(" path: ", stdout); + HDfputs(path, stdout); + HDfree(buf); + } + break; + + default: + HDfputs("cannot follow UD links", stdout); + break; + } /* end switch */ + HDfputc('\n', stdout); + +done: + return 0; +} /* end list_lnk() */ /*------------------------------------------------------------------------- @@ -2059,10 +1949,10 @@ leave(int ret) int main(int argc, const char *argv[]) { - hid_t file = -1, root = -1; + hid_t file = -1; char *fname = NULL, *oname = NULL, *x; const char *s = NULL; - char *rest, *container = NULL; + char *rest; int argno; static char root_name[] = "/"; char drivername[50]; @@ -2072,9 +1962,9 @@ main(int argc, const char *argv[]) h5tools_init(); /* Build object display table */ - DISPATCH(H5O_TYPE_GROUP, "Group", H5Gopen2, H5Gclose, NULL, group_list2); - DISPATCH(H5O_TYPE_DATASET, "Dataset", H5Dopen2, H5Dclose, dataset_list1, dataset_list2); - DISPATCH(H5O_TYPE_NAMED_DATATYPE, "Type", H5Topen2, H5Tclose, NULL, datatype_list2); + DISPATCH(H5O_TYPE_GROUP, "Group", NULL, NULL); + DISPATCH(H5O_TYPE_DATASET, "Dataset", dataset_list1, dataset_list2); + DISPATCH(H5O_TYPE_NAMED_DATATYPE, "Type", NULL, datatype_list2); /* Default output width */ width_g = get_width(); @@ -2230,6 +2120,13 @@ main(int argc, const char *argv[]) leave(1); } /* end if */ + /* Check for conflicting arguments */ + if(recursive_g && grp_literal_g) { + fprintf(stderr, "Error: 'recursive' option not compatible with 'group info' option!\n\n"); + usage(); + leave(1); + } /* end if */ + /* Turn off HDF5's automatic error printing unless you're debugging h5ls */ if(!show_errors_g) H5Eset_auto2(H5E_DEFAULT, NULL, NULL); @@ -2249,7 +2146,6 @@ main(int argc, const char *argv[]) * doesn't exist). */ show_file_name_g = (argc-argno > 1); /*show file names if more than one*/ while(argno < argc) { - H5O_info_t oi; H5L_info_t li; iter_t iter; @@ -2281,24 +2177,21 @@ main(int argc, const char *argv[]) } /* end if */ if(oname) oname++; - if(!oname || !*oname) + if(!oname || !*oname) { oname = root_name; + if(recursive_g) + display_root_g = TRUE; + } /* end if */ + + /* Remember the file information for later */ + iter.fname = fname; + iter.fid = file; /* Check for root group as object name */ if(HDstrcmp(oname, root_name)) { /* Check the type of link given */ if(H5Lget_info(file, oname, &li, H5P_DEFAULT) < 0) { - char *fullname = NULL; - int n; - - fullname = fix_name(oname, "/"); - if(fullname_g) - n = display_string(stdout, fullname, TRUE); - else - n = display_string(stdout, oname, TRUE); - printf("%*s \n", MAX(0, (24 - n)), "**NOT FOUND**"); - - HDfree(fullname); + display_obj_name(stdout, &iter, oname, "**NOT FOUND**"); leave(1); } /* end if */ } /* end if */ @@ -2306,34 +2199,25 @@ main(int argc, const char *argv[]) li.type = H5L_TYPE_HARD; /* Open the object and display it's information */ - if(li.type == H5L_TYPE_HARD && H5Oget_info_by_name(file, oname, &oi, H5P_DEFAULT) >= 0 && H5O_TYPE_GROUP == oi.type && !grp_literal_g) { - /* Specified name is a group. List the complete contents of the group. */ - sym_insert(&oi, oname); - iter.container = container = fix_name((show_file_name_g ? fname : ""), oname); - - /* list root attributes */ - if(verbose_g > 0) { - if((root = H5Gopen2(file, "/", H5P_DEFAULT)) < 0) - leave(1); - H5Aiterate2(root, H5_INDEX_NAME, H5_ITER_INC, NULL, list_attr, NULL); - if(H5Gclose(root) < 0) - leave(1); - } /* end if */ + if(li.type == H5L_TYPE_HARD) { + H5O_info_t oi; /* Information for object */ - /* list */ - H5Literate_by_name(file, oname, H5_INDEX_NAME, H5_ITER_INC, NULL, list, &iter, H5P_DEFAULT); - free(container); - } else if((root = H5Gopen2(file, "/", H5P_DEFAULT)) < 0) { - leave(1); /*major problem!*/ - } else { - /* Specified name is a non-group object -- list that object. The - * container for the object is everything up to the base name. - */ - iter.container = show_file_name_g ? fname : "/"; - list(root, oname, &li, &iter); - if(H5Gclose(root) < 0) + /* Retrieve info for object to list */ + if(H5Oget_info_by_name(file, oname, &oi, H5P_DEFAULT) < 0) { + display_obj_name(stdout, &iter, oname, "**NOT FOUND**"); leave(1); - } + } /* end if */ + + /* Check for group iteration */ + if(H5O_TYPE_GROUP == oi.type && !grp_literal_g) + /* Specified name is a group. List the complete contents of the group. */ + h5trav_visit(file, oname, display_root_g, recursive_g, list_obj, list_lnk, &iter); + else + /* Specified name is a non-group object -- list that object */ + list_obj(oname, &oi, NULL, &iter); + } else + /* Specified name is not for object -- list that link */ + list_lnk(oname, &li, &iter); H5Fclose(file); free(fname); } /* end while */ diff --git a/tools/h5ls/testh5ls.sh b/tools/h5ls/testh5ls.sh index ab36eb4..f25db4e 100755 --- a/tools/h5ls/testh5ls.sh +++ b/tools/h5ls/testh5ls.sh @@ -112,6 +112,7 @@ TOOLTEST tgroup.ls -w80 tgroup.h5 # test for displaying groups TOOLTEST tgroup-1.ls -w80 -r -g tgroup.h5 +TOOLTEST tgroup-2.ls -w80 -g tgroup.h5/g1 # test for displaying simple space datasets TOOLTEST tdset-1.ls -w80 -r -d tdset.h5 diff --git a/tools/h5stat/h5stat.c b/tools/h5stat/h5stat.c index c69d801..f03efd7 100644 --- a/tools/h5stat/h5stat.c +++ b/tools/h5stat/h5stat.c @@ -47,8 +47,7 @@ typedef struct ohdr_info_t { /* Info to pass to the iteration functions */ typedef struct iter_t { - const char *container; /* Full name of the container object */ - unsigned long curr_depth; /* Current depth of hierarchy */ + hid_t fid; /* File ID */ unsigned long uniq_groups; /* Number of unique groups */ unsigned long uniq_dsets; /* Number of unique datasets */ @@ -56,7 +55,6 @@ typedef struct iter_t { unsigned long uniq_links; /* Number of unique links */ unsigned long uniq_others; /* Number of other unique objects */ - unsigned long max_depth; /* Maximum depth of hierarchy */ unsigned long max_links; /* Maximum # of links to an object */ hsize_t max_fanout; /* Maximum fanout from a group */ unsigned long num_small_groups[SIZE_SMALL_GROUPS]; /* Size of small groups tracked */ @@ -95,16 +93,6 @@ typedef struct iter_t { } iter_t; -/* Table containing object id and object name */ -static struct { - int nalloc; /* number of slots allocated */ - int nobjs; /* number of objects */ - struct { - haddr_t id; /* object number */ - char *name; /* full object name */ - } *obj; -} idtab_g; - const char *progname = "h5stat"; int d_status = EXIT_SUCCESS; static int display_all = TRUE; @@ -260,123 +248,6 @@ ceil_log10(unsigned long x) /*------------------------------------------------------------------------- - * Function: sym_insert - * - * Purpose: Add a symbol to the table. - * - * Return: void - * - * Programmer: Robb Matzke - * Thursday, January 21, 1999 - * - *------------------------------------------------------------------------- - */ -static void -sym_insert(H5O_info_t *oi, const char *name) -{ - /* Don't add it if the link count is 1 because such an object can only - * have one name. */ - if(oi->rc > 1) { - int n; - - /* Extend the table */ - if(idtab_g.nobjs >= idtab_g.nalloc) { - idtab_g.nalloc = MAX(256, 2 * idtab_g.nalloc); - idtab_g.obj = realloc(idtab_g.obj, idtab_g.nalloc * sizeof(idtab_g.obj[0])); - } /* end if */ - - /* Insert the entry */ - n = idtab_g.nobjs++; - idtab_g.obj[n].id = oi->addr; - idtab_g.obj[n].name = strdup(name); - } /* end if */ -} /* end sym_insert() */ - - -/*------------------------------------------------------------------------- - * Function: sym_lookup - * - * Purpose: Find another name for the specified object. - * - * Return: Success: Ptr to another name. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Thursday, January 21, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static char * -sym_lookup(H5O_info_t *oi) -{ - int n; - - /*only one name possible*/ - if(oi->rc < 2) - return NULL; - - for(n = 0; n < idtab_g.nobjs; n++) - if(idtab_g.obj[n].id == oi->addr) - return idtab_g.obj[n].name; - - return NULL; -} /* end sym_lookup() */ - - -/*------------------------------------------------------------------------- - * Function: fix_name - * - * Purpose: Returns a malloc'd buffer that contains the PATH and BASE - * names separated by a single slash. It also removes duplicate - * and trailing slashes. - * - * Return: Success: Ptr to fixed name from malloc() - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Thursday, January 21, 1999 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static char * -fix_name(const char *path, const char *base) -{ - size_t n = (path ? strlen(path) : 0) + (base ? strlen(base) : 0) + 3; - char *s = malloc(n), prev='\0'; - size_t len = 0; - - if (path) { - /* Path, followed by slash */ - for (/*void*/; *path; path++) - if ('/'!=*path || '/'!=prev) - prev = s[len++] = *path; - if ('/' != prev) - prev = s[len++] = '/'; - } - - if (base) { - /* Base name w/o trailing slashes */ - const char *end = base + strlen(base); - while (end > base && '/' == end[-1]) - --end; - - for (/*void*/; base < end; base++) - if ('/' != *base || '/' != prev) - prev = s[len++] = *base; - } - - s[len] = '\0'; - return s; -} - - -/*------------------------------------------------------------------------- * Function: attribute_stats * * Purpose: Gather statistics about attributes on an object @@ -453,25 +324,21 @@ attribute_stats(iter_t *iter, const H5O_info_t *oi) *------------------------------------------------------------------------- */ static herr_t -group_stats(hid_t group, const char *name, const char *fullname, - const H5O_info_t *oi, H5L_iterate_t walk, iter_t *iter) +group_stats(iter_t *iter, const char *name, const H5O_info_t *oi) { - const char *last_container; H5G_info_t ginfo; /* Group information */ unsigned bin; /* "bin" the number of objects falls in */ herr_t ret; /* Gather statistics about this type of object */ iter->uniq_groups++; - if(iter->curr_depth > iter->max_depth) - iter->max_depth = iter->curr_depth; /* Get object header information */ iter->group_ohdr_info.total_size += oi->hdr.space.total; iter->group_ohdr_info.free_size += oi->hdr.space.free; /* Get group information */ - ret = H5Gget_info_by_name(group, name, &ginfo, H5P_DEFAULT); + ret = H5Gget_info_by_name(iter->fid, name, &ginfo, H5P_DEFAULT); assert(ret >= 0); /* Update link stats */ @@ -506,18 +373,6 @@ group_stats(hid_t group, const char *name, const char *fullname, ret = attribute_stats(iter, oi); assert(ret >= 0); - /* Update current container info */ - last_container = iter->container; - iter->container = fullname; - iter->curr_depth++; - - /* Recursively descend into current group's objects */ - H5Literate_by_name(group, name, H5_INDEX_NAME, H5_ITER_INC, NULL, walk, iter, H5P_DEFAULT); - - /* Revert current container info */ - iter->container = last_container; - iter->curr_depth--; - return 0; } /* end group_stats() */ @@ -549,7 +404,7 @@ group_stats(hid_t group, const char *name, const char *fullname, *------------------------------------------------------------------------- */ static herr_t -dataset_stats(hid_t group, const char *name, const H5O_info_t *oi, iter_t *iter) +dataset_stats(iter_t *iter, const char *name, const H5O_info_t *oi) { unsigned bin; /* "bin" the number of objects falls in */ hid_t did; /* Dataset ID */ @@ -575,7 +430,7 @@ dataset_stats(hid_t group, const char *name, const H5O_info_t *oi, iter_t *iter) iter->dset_ohdr_info.total_size += oi->hdr.space.total; iter->dset_ohdr_info.free_size += oi->hdr.space.free; - did = H5Dopen2(group, name, H5P_DEFAULT); + did = H5Dopen2(iter->fid, name, H5P_DEFAULT); assert(did > 0); /* Update dataset metadata info */ @@ -710,89 +565,90 @@ dataset_stats(hid_t group, const char *name, const H5O_info_t *oi, iter_t *iter) /*------------------------------------------------------------------------- - * Function: walk + * Function: obj_stats * - * Purpose: Gather statistics about the file + * Purpose: Gather statistics about an object * * Return: Success: 0 - * Failure: -1 * - * Programmer: Quincey Koziol - * Tuesday, August 16, 2005 + * Failure: -1 * - * Modifications: + * Programmer: Quincey Koziol + * Tuesday, November 6, 2007 * *------------------------------------------------------------------------- */ static herr_t -walk(hid_t group, const char *name, const H5L_info_t *linfo, void *_iter) +obj_stats(const char *path, const H5O_info_t *oi, const char *already_visited, + void *_iter) { iter_t *iter = (iter_t *)_iter; - char *fullname = NULL; - herr_t ret; /* Generic return value */ - - if(!linfo || linfo->type == H5L_TYPE_HARD) { - H5O_info_t oi; - char *s; - - /* Get object information */ - ret = H5Oget_info_by_name(group, name, &oi, H5P_DEFAULT); - assert(ret >= 0); - - /* If the object has already been printed then just show the object ID - * and return. */ - if((s = sym_lookup(&oi))) { - printf("%s same as %s\n", name, s); - } else { - /* Get the full object name */ - fullname = fix_name(iter->container, name); - sym_insert(&oi, fullname); - - /* Gather some statistics about the object */ - if(oi.rc > iter->max_links) - iter->max_links = oi.rc; - - switch(oi.type) { - case H5O_TYPE_GROUP: - group_stats(group, name, fullname, &oi, walk, iter); - break; - - case H5O_TYPE_DATASET: - dataset_stats(group, name, &oi, iter); - break; - - case H5O_TYPE_NAMED_DATATYPE: - /* Gather statistics about this type of object */ - iter->uniq_types++; - break; - - default: - /* Gather statistics about this type of object */ - iter->uniq_others++; - break; - } /* end switch */ - } - } /* end if */ - else { - switch(linfo->type) { - case H5L_TYPE_SOFT: - case H5L_TYPE_EXTERNAL: - /* Gather statistics about links and UD links */ - iter->uniq_links++; + + /* If the object has already been seen then just return */ + if(NULL == already_visited) { + /* Gather some general statistics about the object */ + if(oi->rc > iter->max_links) + iter->max_links = oi->rc; + + switch(oi->type) { + case H5O_TYPE_GROUP: + group_stats(iter, path, oi); + break; + + case H5O_TYPE_DATASET: + dataset_stats(iter, path, oi); + break; + + case H5O_TYPE_NAMED_DATATYPE: + /* Gather statistics about this type of object */ + iter->uniq_types++; break; default: /* Gather statistics about this type of object */ iter->uniq_others++; break; - } /* end switch() */ - } /* end else */ + } /* end switch */ + } /* end if */ - if(fullname) - free(fullname); + return 0; +} /* end obj_stats() */ + + +/*------------------------------------------------------------------------- + * Function: lnk_stats + * + * Purpose: Gather statistics about a link + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Quincey Koziol + * Tuesday, November 6, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +lnk_stats(const char UNUSED *path, const H5L_info_t *li, void *_iter) +{ + iter_t *iter = (iter_t *)_iter; + + switch(li->type) { + case H5L_TYPE_SOFT: + case H5L_TYPE_EXTERNAL: + /* Gather statistics about links and UD links */ + iter->uniq_links++; + break; + + default: + /* Gather statistics about this type of object */ + iter->uniq_others++; + break; + } /* end switch() */ return 0; -} +} /* end lnk_stats() */ /*------------------------------------------------------------------------- @@ -915,13 +771,13 @@ parse_command_line(int argc, const char *argv[]) *------------------------------------------------------------------------- */ static herr_t -iter_init(iter_t *iter) +iter_init(iter_t *iter, hid_t fid) { /* Clear everything to zeros */ - memset(iter, 0, sizeof(*iter)); + HDmemset(iter, 0, sizeof(*iter)); - /* Initialize non-zero information */ - iter->container = "/"; + /* Set the file ID for later use in callbacks */ + iter->fid = fid; return 0; } @@ -953,7 +809,6 @@ print_file_info(const iter_t *iter) printf("\t# of unique links: %lu\n", iter->uniq_links); printf("\t# of unique other: %lu\n", iter->uniq_others); printf("\tMax. # of links to object: %lu\n", iter->max_links); - printf("\tMax. depth of hierarchy: %lu\n", iter->max_depth); HDfprintf(stdout, "\tMax. # of objects in group: %Hu\n", iter->max_fanout); return 0; @@ -1318,8 +1173,6 @@ main(int argc, const char *argv[]) const char *fname = NULL; hid_t fid; struct handler_t *hand; - char root[] = "/"; - int i; H5F_info_t finfo; @@ -1329,25 +1182,23 @@ main(int argc, const char *argv[]) /* Initialize h5tools lib */ h5tools_init(); hand = parse_command_line (argc, argv); - if (!hand) { + if(!hand) { error_msg(progname, "unable to parse command line arguments \n"); leave(EXIT_FAILURE); - } + } /* end if */ fname = argv[opt_ind]; - if(!display_object) - hand[0].obj = root; printf("Filename: %s\n", fname); fid = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT); - if (fid < 0) { + if(fid < 0) { error_msg(progname, "unable to open file \"%s\"\n", fname); leave(EXIT_FAILURE); - } + } /* end if */ /* Initialize iter structure */ - iter_init(&iter); + iter_init(&iter, fid); /* Get storge info for SOHM's btree/list/heap and superblock extension */ if(H5Fget_info(fid, &finfo) < 0) @@ -1357,15 +1208,23 @@ main(int argc, const char *argv[]) iter.SM_hdr_storage_size = finfo.sohm.hdr_size; iter.SM_index_storage_size = finfo.sohm.msgs_info.index_size; iter.SM_heap_storage_size = finfo.sohm.msgs_info.heap_size; - } + } /* end else */ /* Walk the objects or all file */ - i = 0; - while(hand[i].obj) { - walk(fid, hand[i].obj, NULL, &iter); - print_statistics(hand[i].obj, &iter); - i++; - } /* end while */ + if(display_object) { + unsigned u; + + u = 0; + while(hand[u].obj) { + h5trav_visit(fid, hand[u].obj, TRUE, TRUE, obj_stats, lnk_stats, &iter); + print_statistics(hand[u].obj, &iter); + u++; + } /* end while */ + } /* end if */ + else { + h5trav_visit(fid, "/", TRUE, TRUE, obj_stats, lnk_stats, &iter); + print_statistics("/", &iter); + } /* end else */ free(hand); diff --git a/tools/h5stat/testfiles/h5stat_filters-file.ddl b/tools/h5stat/testfiles/h5stat_filters-file.ddl index c6aeef0..7b8f47f 100644 --- a/tools/h5stat/testfiles/h5stat_filters-file.ddl +++ b/tools/h5stat/testfiles/h5stat_filters-file.ddl @@ -9,5 +9,4 @@ File information # of unique links: 0 # of unique other: 0 Max. # of links to object: 1 - Max. depth of hierarchy: 0 Max. # of objects in group: 16 diff --git a/tools/h5stat/testfiles/h5stat_filters.ddl b/tools/h5stat/testfiles/h5stat_filters.ddl index 4dd6aee..df2e304 100644 --- a/tools/h5stat/testfiles/h5stat_filters.ddl +++ b/tools/h5stat/testfiles/h5stat_filters.ddl @@ -9,7 +9,6 @@ File information # of unique links: 0 # of unique other: 0 Max. # of links to object: 1 - Max. depth of hierarchy: 0 Max. # of objects in group: 16 Object header size: (total/unused) Groups: 48/8 diff --git a/tools/h5stat/testfiles/h5stat_newgrat.ddl b/tools/h5stat/testfiles/h5stat_newgrat.ddl index 228d565..6881ca9 100644 --- a/tools/h5stat/testfiles/h5stat_newgrat.ddl +++ b/tools/h5stat/testfiles/h5stat_newgrat.ddl @@ -9,7 +9,6 @@ File information # of unique links: 0 # of unique other: 0 Max. # of links to object: 1 - Max. depth of hierarchy: 1 Max. # of objects in group: 351 Object header size: (total/unused) Groups: 51597/32292 diff --git a/tools/h5stat/testfiles/h5stat_tsohm.ddl b/tools/h5stat/testfiles/h5stat_tsohm.ddl index 572965e..15a058e 100644 --- a/tools/h5stat/testfiles/h5stat_tsohm.ddl +++ b/tools/h5stat/testfiles/h5stat_tsohm.ddl @@ -9,7 +9,6 @@ File information # of unique links: 0 # of unique other: 0 Max. # of links to object: 1 - Max. depth of hierarchy: 0 Max. # of objects in group: 2 Object header size: (total/unused) Groups: 51/2 diff --git a/tools/lib/h5tools_ref.c b/tools/lib/h5tools_ref.c index 123065b..de1e2c3 100644 --- a/tools/lib/h5tools_ref.c +++ b/tools/lib/h5tools_ref.c @@ -20,6 +20,7 @@ #include "H5SLprivate.h" #include "h5tools.h" #include "h5tools_utils.h" +#include "h5trav.h" /* @@ -42,15 +43,12 @@ typedef struct { } ref_path_node_t; static H5SL_t *ref_path_table = NULL; /* the "table" (implemented with a skip list) */ -static hid_t thefile; +static hid_t thefile = (-1); extern char *progname; extern int d_status; static int ref_path_table_put(const char *, haddr_t objno); -static hbool_t ref_path_table_find(haddr_t objno); -static herr_t fill_ref_path_table_cb(hid_t group, const char *obj_name, - const H5L_info_t *linfo, void *op_data); /*------------------------------------------------------------------------- * Function: free_ref_path_info @@ -77,6 +75,61 @@ free_ref_path_info(void *item, void UNUSED *key, void UNUSED *operator_data/*in, } /*------------------------------------------------------------------------- + * Function: init_ref_path_cb + * + * Purpose: Called by interator to create references for + * all objects and enter them in the table. + * + * Return: Error status. + * + * Programmer: REMcG + * + *------------------------------------------------------------------------- + */ +static herr_t +init_ref_path_cb(const char *obj_name, const H5O_info_t *oinfo, + const char *already_seen, void UNUSED *_udata) +{ + /* Check if the object is already in the path table */ + if(NULL == already_seen) { + /* Insert the object into the path table */ + ref_path_table_put(obj_name, oinfo->addr); + } /* end if */ + + return 0; +} + +/*------------------------------------------------------------------------- + * Function: init_ref_path_table + * + * Purpose: Initalize the reference path table + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * + *------------------------------------------------------------------------- + */ +static int +init_ref_path_table(void) +{ + /* Sanity check */ + HDassert(thefile > 0); + + /* Create skip list to store reference path information */ + if((ref_path_table = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16))==NULL) + return (-1); + + /* Iterate over objects in this file */ + if(h5trav_visit(thefile, "/", TRUE, TRUE, init_ref_path_cb, NULL, NULL) < 0) { + error_msg(progname, "unable to construct reference path table\n"); + d_status = EXIT_FAILURE; + } /* end if */ + + return(0); +} + +/*------------------------------------------------------------------------- * Function: term_ref_path_table * * Purpose: Terminate the reference path table @@ -137,39 +190,11 @@ ref_path_table_lookup(const char *thepath) if(H5Oget_info_by_name(thefile, thepath, &oi, H5P_DEFAULT) < 0) return HADDR_UNDEF; - /* All existing objects in the file had better be in the table */ - HDassert(ref_path_table_find(oi.addr)); - /* Return OID */ return(oi.addr); } /*------------------------------------------------------------------------- - * Function: ref_path_table_find - * - * Purpose: Looks up a table entry given a object number. - * Used during construction of the table. - * - * Return: TRUE/FALSE on success, can't fail - * - * Programmer: Quincey Koziol - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static hbool_t -ref_path_table_find(haddr_t objno) -{ - HDassert(ref_path_table); - - if(H5SL_search(ref_path_table, &objno) == NULL) - return FALSE; - else - return TRUE; -} - -/*------------------------------------------------------------------------- * Function: ref_path_table_put * * Purpose: Enter the 'obj' with 'path' in the table (assumes its not @@ -200,7 +225,7 @@ ref_path_table_put(const char *path, haddr_t objno) return(-1); new_node->objno = objno; - new_node->path = path; + new_node->path = HDstrdup(path); return(H5SL_insert(ref_path_table, new_node, &(new_node->objno))); } @@ -237,17 +262,17 @@ get_fake_xid (void) { haddr_t ref_path_table_gen_fake(const char *path) { - const char *dup_path; haddr_t fake_objno; - if((dup_path = HDstrdup(path)) == NULL) - return HADDR_UNDEF; - /* Generate fake ID for string */ fake_objno = get_fake_xid(); - /* Insert "fake" object into table (takes ownership of path) */ - ref_path_table_put(dup_path, fake_objno); + /* Create ref path table, if it hasn't already been created */ + if(ref_path_table == NULL) + init_ref_path_table(); + + /* Insert "fake" object into table */ + ref_path_table_put(path, fake_objno); return(fake_objno); } @@ -271,74 +296,19 @@ lookup_ref_path(haddr_t ref) ref_path_node_t *node; /* Be safer for h5ls */ - if(!ref_path_table) + if(thefile < 0) return(NULL); + /* Create ref path table, if it hasn't already been created */ + if(ref_path_table == NULL) + init_ref_path_table(); + node = H5SL_search(ref_path_table, &ref); return(node ? node->path : NULL); } /*------------------------------------------------------------------------- - * Function: fill_ref_path_table_cb - * - * Purpose: Called by interator to create references for - * all objects and enter them in the table. - * - * Return: Error status. - * - * Programmer: REMcG - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -fill_ref_path_table_cb(hid_t group, const char *obj_name, const H5L_info_t *linfo, - void *op_data) -{ - if(linfo->type == H5L_TYPE_HARD) { - H5O_info_t oinfo; - - H5Oget_info_by_name(group, obj_name, &oinfo, H5P_DEFAULT); - - /* Check if the object is already in the path table */ - if(!ref_path_table_find(oinfo.addr)) { - const char *obj_prefix = (const char *)op_data; - size_t tmp_len; - char *thepath; - - /* Compute length for this object's path */ - tmp_len = HDstrlen(obj_prefix) + HDstrlen(obj_name) + 2; - - /* Allocate room for the path for this object */ - if((thepath = (char *)HDmalloc(tmp_len)) == NULL) - return FAIL; - - /* Build the name for this object */ - HDstrcpy(thepath, obj_prefix); - HDstrcat(thepath, "/"); - HDstrcat(thepath, obj_name); - - /* Insert the object into the path table (takes ownership of the path) */ - ref_path_table_put(thepath, oinfo.addr); - - if(oinfo.type == H5O_TYPE_GROUP) { - /* Iterate over objects in this group, using this group's - * name as their prefix - */ - if(H5Literate_by_name(group, obj_name, H5_INDEX_NAME, H5_ITER_INC, NULL, fill_ref_path_table_cb, thepath, H5P_DEFAULT) < 0) { - error_msg(progname, "unable to dump group \"%s\"\n", thepath); - d_status = EXIT_FAILURE; - } /* end if */ - } /* end if */ - } /* end if */ - } /* end if */ - - return 0; -} - -/*------------------------------------------------------------------------- * Function: fill_ref_path_table * * Purpose: Called by interator to create references for @@ -348,37 +318,15 @@ fill_ref_path_table_cb(hid_t group, const char *obj_name, const H5L_info_t *linf * * Programmer: REMcG * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t fill_ref_path_table(hid_t fid) { - H5O_info_t oinfo; - char *root_path; - /* Set file ID for later queries (XXX: this should be fixed) */ thefile = fid; - /* Create skip list to store reference path information */ - if((ref_path_table = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16))==NULL) - return (-1); - - /* Build the name for root group */ - root_path = HDstrdup("/"); - - /* Get info for root group */ - H5Oget_info_by_name(fid, root_path, &oinfo, H5P_DEFAULT); - - /* Insert the root group into the path table (takes ownership of path) */ - ref_path_table_put(root_path, oinfo.addr); - - /* Iterate over objects in this file */ - if(H5Literate(fid, H5_INDEX_NAME, H5_ITER_INC, NULL, fill_ref_path_table_cb, (void *)"") < 0) { - error_msg(progname, "unable to dump root group\n"); - d_status = EXIT_FAILURE; - } /* end if */ + /* Defer creating the ref path table until it's needed */ return 0; } diff --git a/tools/lib/h5tools_utils.c b/tools/lib/h5tools_utils.c index cb38e7a..512a3fb 100644 --- a/tools/lib/h5tools_utils.c +++ b/tools/lib/h5tools_utils.c @@ -30,6 +30,7 @@ #include "h5tools_utils.h" #include "H5private.h" +#include "h5trav.h" /* global variables */ int nCols = 80; @@ -44,10 +45,7 @@ static void init_table(table_t **tbl); #ifdef H5DUMP_DEBUG static void dump_table(char* tablename, table_t *table); #endif /* H5DUMP_DEBUG */ -static void add_obj(table_t *table, haddr_t objno, char *objname, hbool_t recorded); -static char * build_obj_path_name(const char *prefix, const char *name); -static herr_t find_objs_cb(hid_t group, const char *name, const H5L_info_t *info, - void *op_data); +static void add_obj(table_t *table, haddr_t objno, const char *objname, hbool_t recorded); /*------------------------------------------------------------------------- @@ -428,44 +426,15 @@ search_obj(table_t *table, haddr_t objno) { unsigned u; - for (u = 0; u < table->nobjs; u++) - if (table->objs[u].objno == objno) - return &(table->objs[u]); + for(u = 0; u < table->nobjs; u++) + if(table->objs[u].objno == objno) + return &(table->objs[u]); return NULL; } /*------------------------------------------------------------------------- - * Function: build_obj_path_name - * - * Purpose: Allocate space & build path name from prefix & name - * - * Return: Success: SUCCEED - * - * Failure: FAIL - * - * Programmer: Quincey Koziol - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static char * -build_obj_path_name(const char *prefix, const char *name) -{ - char *path; - - path = HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2); - HDstrcpy(path, prefix); - HDstrcat(path,"/"); - HDstrcat(path,name); /* absolute name of the data set */ - - return(path); -} /* end build_obj_path_name() */ - - -/*------------------------------------------------------------------------- * Function: find_objs_cb * * Purpose: Callback to find objects, committed types and store them in tables @@ -481,90 +450,65 @@ build_obj_path_name(const char *prefix, const char *name) *------------------------------------------------------------------------- */ static herr_t -find_objs_cb(hid_t group, const char *name, const H5L_info_t UNUSED *linfo, void *op_data) +find_objs_cb(const char *name, const H5O_info_t *oinfo, const char *already_seen, + void *op_data) { - H5O_info_t oinfo; find_objs_t *info = (find_objs_t*)op_data; herr_t ret_value = 0; - if(H5Oget_info_by_name(group, name, &oinfo, H5P_DEFAULT) < 0) - ; /* keep going */ - else { - switch(oinfo.type) { - char *tmp; - size_t tmp_len; - - case H5O_TYPE_GROUP: - if(search_obj(info->group_table, oinfo.addr) == NULL) { - char *old_prefix; + switch(oinfo->type) { + case H5O_TYPE_GROUP: + if(NULL == already_seen) + add_obj(info->group_table, oinfo->addr, name, TRUE); + break; - tmp = build_obj_path_name(info->prefix, name); - add_obj(info->group_table, oinfo.addr, tmp, TRUE); + case H5O_TYPE_DATASET: + if(NULL == already_seen) { + hid_t dset; - old_prefix = info->prefix; - tmp_len = HDstrlen(tmp); - info->prefix = HDmalloc(tmp_len+1); - HDstrcpy(info->prefix, tmp); + /* Add the dataset to the list of objects */ + add_obj(info->dset_table, oinfo->addr, name, TRUE); - if(H5Literate_by_name(group, name, H5_INDEX_NAME, H5_ITER_INC, NULL, find_objs_cb, (void *)info, H5P_DEFAULT) < 0) - ret_value = FAIL; + /* Check for a dataset that uses a named datatype */ + if((dset = H5Dopen2(info->fid, name, H5P_DEFAULT)) >= 0) { + hid_t type = H5Dget_type(dset); - info->prefix = old_prefix; - } /* end if */ - break; - - case H5O_TYPE_DATASET: - if(search_obj(info->dset_table, oinfo.addr) == NULL) { - hid_t dset; - - tmp = build_obj_path_name(info->prefix, name); - add_obj(info->dset_table, oinfo.addr, tmp, TRUE); - - if((dset = H5Dopen2(group, name, H5P_DEFAULT)) >= 0) { - hid_t type; + if(H5Tcommitted(type) > 0) { + H5O_info_t type_oinfo; - type = H5Dget_type(dset); - - if(H5Tcommitted(type) > 0) { - H5Oget_info(type, &oinfo); - if(search_obj(info->type_table, oinfo.addr) == NULL) { - char *type_name = HDstrdup(tmp); - - add_obj(info->type_table, oinfo.addr, type_name, FALSE); - } /* end if */ - } /* end if */ - - H5Tclose(type); - H5Dclose(dset); + H5Oget_info(type, &type_oinfo); + if(search_obj(info->type_table, type_oinfo.addr) == NULL) + add_obj(info->type_table, type_oinfo.addr, name, FALSE); } /* end if */ - else - ret_value = FAIL; - } /* end if */ - break; - case H5O_TYPE_NAMED_DATATYPE: - { - obj_t *found_obj; - - tmp = build_obj_path_name(info->prefix, name); - if((found_obj = search_obj(info->type_table, oinfo.addr)) == NULL) - add_obj(info->type_table, oinfo.addr, tmp, TRUE); - else { - /* Use latest version of name */ - HDfree(found_obj->objname); - found_obj->objname = HDstrdup(tmp); - - /* Mark named datatype as having valid name */ - found_obj->recorded = TRUE; - } /* end else */ - break; - } - - default: - /* Ignore links, etc. */ - break; + H5Tclose(type); + H5Dclose(dset); + } /* end if */ + else + ret_value = FAIL; + } /* end if */ + break; + + case H5O_TYPE_NAMED_DATATYPE: + { + obj_t *found_obj; + + if((found_obj = search_obj(info->type_table, oinfo->addr)) == NULL) + add_obj(info->type_table, oinfo->addr, name, TRUE); + else { + /* Use latest version of name */ + HDfree(found_obj->objname); + found_obj->objname = HDstrdup(name); + + /* Mark named datatype as having valid name */ + found_obj->recorded = TRUE; + } /* end else */ + break; } - } /* end else */ + + default: + break; + } /* end switch */ return ret_value; } @@ -589,31 +533,19 @@ herr_t init_objs(hid_t fid, find_objs_t *info, table_t **group_table, table_t **dset_table, table_t **type_table) { - H5O_info_t oinfo; - /* Initialize the tables */ init_table(group_table); init_table(dset_table); init_table(type_table); /* Init the find_objs_t */ - info->prefix = HDcalloc(1, 1); + info->fid = fid; info->group_table = *group_table; info->type_table = *type_table; info->dset_table = *dset_table; - /* add the root group as an object, it may have hard links to it */ - if(H5Oget_info(fid, &oinfo) < 0) - return FAIL; - else { - /* call with an empty string, it appends '/' group separator */ - char *tmp = build_obj_path_name(info->prefix, ""); - - add_obj(info->group_table, oinfo.addr, tmp, TRUE); - } /* end else */ - /* Find all shared objects */ - return(H5Literate(fid, H5_INDEX_NAME, H5_ITER_INC, NULL, find_objs_cb, (void *)info)); + return(h5trav_visit(fid, "/", TRUE, TRUE, find_objs_cb, NULL, info)); } @@ -632,22 +564,22 @@ init_objs(hid_t fid, find_objs_t *info, table_t **group_table, *------------------------------------------------------------------------- */ static void -add_obj(table_t *table, haddr_t objno, char *objname, hbool_t record) +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) { + if(table->nobjs == table->size) { table->size *= 2; - table->objs = HDrealloc(table->objs, table->size * sizeof(obj_t)); - } + table->objs = 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 = objname; + table->objs[u].objname = HDstrdup(objname); table->objs[u].recorded = record; table->objs[u].displayed = 0; } diff --git a/tools/lib/h5tools_utils.h b/tools/lib/h5tools_utils.h index e604e5a..e7b175c 100644 --- a/tools/lib/h5tools_utils.h +++ b/tools/lib/h5tools_utils.h @@ -95,7 +95,7 @@ typedef struct table_t { /*this struct stores the information that is passed to the find_objs function*/ typedef struct find_objs_t { - char *prefix; + hid_t fid; table_t *group_table; table_t *type_table; table_t *dset_table; diff --git a/tools/lib/h5trav.c b/tools/lib/h5trav.c index 97de021..14ced60 100644 --- a/tools/lib/h5trav.c +++ b/tools/lib/h5trav.c @@ -24,24 +24,25 @@ typedef struct trav_addr_t { size_t nalloc; size_t nused; - haddr_t *addrs; + struct { + haddr_t addr; + char *path; + } *objs; } trav_addr_t; typedef struct { - herr_t (*visit_obj)(const char *path_name, const H5O_info_t *oinfo, hbool_t already_visited, void *udata); - herr_t (*visit_lnk)(const char *path_name, const H5L_info_t *linfo, void *udata); + h5trav_obj_func_t visit_obj; /* Callback for visiting objects */ + h5trav_lnk_func_t visit_lnk; /* Callback for visiting links */ void *udata; /* User data to pass to callbacks */ } trav_visitor_t; typedef struct { trav_addr_t *seen; /* List of addresses seen already */ - const char *curr_path; /* Current path to parent group */ const trav_visitor_t *visitor; /* Information for visiting each link/object */ } trav_ud_traverse_t; typedef struct { hid_t fid; /* File ID being traversed */ - trav_table_t *table; /* Table for tracking name of objects with >1 hard link */ } trav_print_udata_t; /*------------------------------------------------------------------------- @@ -52,10 +53,8 @@ static void trav_table_add(trav_table_t *table, const char *objname, const H5O_info_t *oinfo); -static size_t trav_table_search(const trav_table_t *table, haddr_t objno); - static void trav_table_addlink(trav_table_t *table, - size_t j /* the object index */, + haddr_t objno, const char *path); /*------------------------------------------------------------------------- @@ -78,19 +77,20 @@ static void trav_table_addlink(trav_table_t *table, *------------------------------------------------------------------------- */ static void -trav_addr_add(trav_addr_t *visited, haddr_t addr) +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->addrs = (haddr_t *)HDrealloc(visited->addrs, visited->nalloc * sizeof(haddr_t)); + visited->objs = HDrealloc(visited->objs, visited->nalloc * sizeof(visited->objs[0])); } /* end if */ /* Append it */ idx = visited->nused++; - visited->addrs[idx] = addr; + visited->objs[idx].addr = addr; + visited->objs[idx].path = HDstrdup(path); } /* end trav_addr_add() */ @@ -107,7 +107,7 @@ trav_addr_add(trav_addr_t *visited, haddr_t addr) * *------------------------------------------------------------------------- */ -static hbool_t +static const char * trav_addr_visited(trav_addr_t *visited, haddr_t addr) { size_t u; /* Local index variable */ @@ -115,11 +115,11 @@ trav_addr_visited(trav_addr_t *visited, haddr_t addr) /* Look for address */ for(u = 0; u < visited->nused; u++) /* Check for address already in array */ - if(visited->addrs[u] == addr) - return(TRUE); + if(visited->objs[u].addr == addr) + return(visited->objs[u].path); /* Didn't find address */ - return(FALSE); + return(NULL); } /* end trav_addr_visited() */ @@ -135,68 +135,44 @@ trav_addr_visited(trav_addr_t *visited, haddr_t addr) *------------------------------------------------------------------------- */ static herr_t -traverse_cb(hid_t loc_id, const char *link_name, const H5L_info_t *linfo, +traverse_cb(hid_t loc_id, const char *path, const H5L_info_t *linfo, void *_udata) { trav_ud_traverse_t *udata = (trav_ud_traverse_t *)_udata; /* User data */ - hbool_t is_group = FALSE; /* If the object is a group */ - hbool_t already_visited = FALSE; /* Whether the link/object was already visited */ - char *link_path; /* Full path name of a link */ + char *full_name; + const char *already_visited = NULL; /* Whether the link/object was already visited */ - /* Construct the full path name of this link */ - link_path = (char*)HDmalloc(HDstrlen(udata->curr_path) + HDstrlen(link_name) + 2); - HDassert(link_path); - HDstrcpy(link_path, udata->curr_path); - HDstrcat(link_path, "/"); - HDstrcat(link_path, link_name); + /* Create the full path name for the link */ + full_name = HDmalloc(HDstrlen(path) + 2); + *full_name = '/'; + HDstrcpy(full_name + 1, path); /* Perform the correct action for different types of links */ if(linfo->type == H5L_TYPE_HARD) { H5O_info_t oinfo; /* Get information about the object */ - if(H5Oget_info_by_name(loc_id, link_name, &oinfo, H5P_DEFAULT) < 0) + if(H5Oget_info_by_name(loc_id, path, &oinfo, H5P_DEFAULT) < 0) return(H5_ITER_ERROR); /* If the object has multiple links, add it to the list of addresses * already visited, if it isn't there already */ - if(oinfo.rc > 1) { - already_visited = trav_addr_visited(udata->seen, oinfo.addr); - if(!already_visited) - trav_addr_add(udata->seen, oinfo.addr); - } /* end if */ - - /* Check if object is a group, for later */ - is_group = (oinfo.type == H5O_TYPE_GROUP) ? TRUE : FALSE; + if(oinfo.rc > 1) + if(NULL == (already_visited = trav_addr_visited(udata->seen, oinfo.addr))) + trav_addr_add(udata->seen, oinfo.addr, full_name); /* Make 'visit object' callback */ if(udata->visitor->visit_obj) - (*udata->visitor->visit_obj)(link_path, &oinfo, already_visited, udata->visitor->udata); + (*udata->visitor->visit_obj)(full_name, &oinfo, already_visited, udata->visitor->udata); } /* end if */ else { /* Make 'visit link' callback */ if(udata->visitor->visit_lnk) - (*udata->visitor->visit_lnk)(link_path, linfo, udata->visitor->udata); + (*udata->visitor->visit_lnk)(full_name, linfo, udata->visitor->udata); } /* end else */ - /* Check for group that we haven't visited yet & recurse */ - if(is_group && !already_visited) { - const char *prev_path = udata->curr_path; /* Previous path to link's parent group */ - - /* Set current path to this object */ - udata->curr_path = link_path; - - /* Iterate over all links in group object */ - if(H5Literate_by_name(loc_id, link_name, H5_INDEX_NAME, H5_ITER_INC, NULL, traverse_cb, udata, H5P_DEFAULT) < 0) - return(H5_ITER_ERROR); - - /* Restore path in udata */ - udata->curr_path = prev_path; - } /* end if */ - - /* Free path name for current link/object */ - HDfree(link_path); + HDfree(full_name); return(H5_ITER_CONT); } /* end traverse_cb() */ @@ -217,39 +193,58 @@ traverse_cb(hid_t loc_id, const char *link_name, const H5L_info_t *linfo, *------------------------------------------------------------------------- */ static int -traverse(hid_t file_id, const trav_visitor_t *visitor) +traverse(hid_t file_id, const char *grp_name, hbool_t visit_start, + hbool_t recurse, const trav_visitor_t *visitor) { - H5O_info_t oinfo; /* Object info for root group */ - trav_addr_t seen; /* List of addresses seen */ - trav_ud_traverse_t udata; /* User data for iteration callback */ + H5O_info_t oinfo; /* Object info for starting group */ - /* Get info for root group */ - if(H5Oget_info(file_id, &oinfo) < 0) + /* Get info for starting object */ + if(H5Oget_info_by_name(file_id, grp_name, &oinfo, H5P_DEFAULT) < 0) return -1; - /* Visit the root group of the file */ - (*visitor->visit_obj)("/", &oinfo, FALSE, visitor->udata); + /* Visit the starting object */ + if(visit_start && visitor->visit_obj) + (*visitor->visit_obj)(grp_name, &oinfo, NULL, visitor->udata); - /* Init addresses seen */ - seen.nused = seen.nalloc = 0; - seen.addrs = NULL; + /* Go visiting, if the object is a group */ + if(oinfo.type == H5O_TYPE_GROUP) { + trav_addr_t seen; /* List of addresses seen */ + trav_ud_traverse_t udata; /* User data for iteration callback */ - /* Check for multiple links to root group */ - if(oinfo.rc > 1) - trav_addr_add(&seen, oinfo.addr); + /* Init addresses seen */ + seen.nused = seen.nalloc = 0; + seen.objs = NULL; - /* Set up user data structure */ - udata.seen = &seen; - udata.curr_path = ""; - udata.visitor = visitor; + /* Check for multiple links to top group */ + if(oinfo.rc > 1) + trav_addr_add(&seen, oinfo.addr, grp_name); - /* Iterate over all links in root group */ - if(H5Literate(file_id, H5_INDEX_NAME, H5_ITER_INC, NULL, traverse_cb, &udata) < 0) - return -1; + /* Set up user data structure */ + udata.seen = &seen; + udata.visitor = visitor; - /* Free visited addresses table */ - if(seen.addrs) - HDfree(seen.addrs); + /* Check for iteration of links vs. visiting all links recursively */ + if(recurse) { + /* Visit all links in group, recursively */ + if(H5Lvisit_by_name(file_id, grp_name, H5_INDEX_NAME, H5_ITER_INC, traverse_cb, &udata, H5P_DEFAULT) < 0) + return -1; + } /* end if */ + else { + /* Iterate over links in group */ + if(H5Literate_by_name(file_id, grp_name, H5_INDEX_NAME, H5_ITER_INC, NULL, traverse_cb, &udata, H5P_DEFAULT) < 0) + return -1; + } /* end else */ + + /* Free visited addresses table */ + if(seen.objs) { + size_t u; /* Local index variable */ + + /* Free paths to objects */ + for(u = 0; u < seen.nused; u++) + HDfree(seen.objs[u].path); + HDfree(seen.objs); + } /* end if */ + } /* end if */ return 0; } @@ -301,7 +296,7 @@ trav_info_add(trav_info_t *info, const char *path, h5trav_type_t obj_type) */ static int trav_info_visit_obj(const char *path, const H5O_info_t *oinfo, - hbool_t UNUSED already_visited, void *udata) + const char UNUSED *already_visited, void *udata) { /* Add the object to the 'info' struct */ /* (object types map directly to "traversal" types) */ @@ -359,7 +354,7 @@ h5trav_getinfo(hid_t file_id, trav_info_t *info) info_visitor.udata = info; /* Traverse all objects in the file, visiting each object & link */ - if(traverse(file_id, &info_visitor) < 0) + if(traverse(file_id, "/", TRUE, TRUE, &info_visitor) < 0) return -1; return 0; @@ -470,24 +465,17 @@ trav_info_free(trav_info_t *info) */ static int trav_table_visit_obj(const char *path, const H5O_info_t *oinfo, - hbool_t already_visited, void *udata) + const char *already_visited, void *udata) { trav_table_t *table = (trav_table_t *)udata; /* Check if we've already seen this object */ - if(!already_visited) + if(NULL == already_visited) /* add object to table */ trav_table_add(table, path, oinfo); - else { - size_t found; /* Index of original object seen */ - - /* Look for object in existing table */ - found = trav_table_search(table, oinfo->addr); - HDassert(found < table->nobjs); - + else /* Add alias for object to table */ - trav_table_addlink(table, found, path); - } /* end else */ + trav_table_addlink(table, oinfo->addr, path); return(0); } /* end trav_table_visit_obj() */ @@ -541,7 +529,7 @@ h5trav_gettable(hid_t fid, trav_table_t *table) table_visitor.udata = table; /* Traverse all objects in the file, visiting each object & link */ - if(traverse(fid, &table_visitor) < 0) + if(traverse(fid, "/", TRUE, TRUE, &table_visitor) < 0) return -1; return 0; } @@ -670,25 +658,33 @@ trav_table_add(trav_table_t *table, */ static void -trav_table_addlink(trav_table_t *table, - size_t j /* the object index */, - const char *path) +trav_table_addlink(trav_table_t *table, haddr_t objno, const char *path) { - size_t new; + size_t i; /* Local index variable */ - /* already inserted */ - if(HDstrcmp(table->objs[j].name, path) == 0) - return; + for(i = 0; i < table->nobjs; i++) { + if(table->objs[i].objno == objno) { + size_t n; - /* allocate space if necessary */ - if(table->objs[j].nlinks == (unsigned)table->objs[j].sizelinks) { - table->objs[j].sizelinks = MAX(1, table->objs[j].sizelinks * 2); - table->objs[j].links = (trav_link_t*)HDrealloc(table->objs[j].links, table->objs[j].sizelinks * sizeof(trav_link_t)); - } /* end if */ + /* 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 */ - new = table->objs[j].nlinks++; - table->objs[j].links[new].new_name = (char *)HDstrdup(path); + /* 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?!?"); } @@ -809,10 +805,8 @@ void trav_table_free( trav_table_t *table ) */ static int trav_print_visit_obj(const char *path, const H5O_info_t *oinfo, - hbool_t already_visited, void *udata) + const char *already_visited, void UNUSED *udata) { - trav_print_udata_t *print_udata = (trav_print_udata_t *)udata; - /* Print the name of the object */ /* (no new-line, so that objects that we've encountered before can print * the name of the original object) @@ -836,26 +830,12 @@ trav_print_visit_obj(const char *path, const H5O_info_t *oinfo, } /* end switch */ /* Check if we've already seen this object */ - if(!already_visited) { + if(NULL == already_visited) /* Finish printing line about object */ printf("\n"); - - /* Check if we will encounter another hard link to this object */ - if(oinfo->rc > 1) { - /* Add object to table */ - trav_table_add(print_udata->table, path, oinfo); - } /* end if */ - } /* end if */ - else { - size_t found; /* Index of original object seen */ - - /* Locate object in table */ - found = trav_table_search(print_udata->table, oinfo->addr); - HDassert(found < print_udata->table->nobjs); - - /* Print the link's destination */ - printf(" -> %s\n", print_udata->table->objs[found].name); - } /* end else */ + else + /* Print the link's original name */ + printf(" -> %s\n", already_visited); return(0); } /* end trav_print_visit_obj() */ @@ -938,16 +918,11 @@ trav_print_visit_lnk(const char *path, const H5L_info_t *linfo, void *udata) int h5trav_print(hid_t fid) { - trav_table_t *table = NULL; /* Table for objects w/multiple hard links */ trav_print_udata_t print_udata; /* User data for traversal */ trav_visitor_t print_visitor; /* Visitor structure for printing objects */ - /* Initialize the table */ - trav_table_init(&table); - /* Init user data for printing */ print_udata.fid = fid; - print_udata.table = table; /* Init visitor structure */ print_visitor.visit_obj = trav_print_visit_obj; @@ -955,11 +930,42 @@ h5trav_print(hid_t fid) print_visitor.udata = &print_udata; /* Traverse all objects in the file, visiting each object & link */ - if(traverse(fid, &print_visitor) < 0) + if(traverse(fid, "/", TRUE, TRUE, &print_visitor) < 0) return -1; - /* Free table */ - trav_table_free(table); + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: h5trav_visit + * + * Purpose: Generic traversal routine for visiting objects and links + * + * Return: 0, -1 on error + * + * Programmer: Quincey Koziol, koziol@hdfgroup.org + * + * Date: November 6, 2007 + * + *------------------------------------------------------------------------- + */ + +int +h5trav_visit(hid_t fid, const char *grp_name, hbool_t visit_start, + hbool_t recurse, h5trav_obj_func_t visit_obj, h5trav_lnk_func_t visit_lnk, + void *udata) +{ + trav_visitor_t visitor; /* Visitor structure for objects */ + + /* Init visitor structure */ + visitor.visit_obj = visit_obj; + visitor.visit_lnk = visit_lnk; + visitor.udata = udata; + + /* Traverse all objects in the file, visiting each object & link */ + if(traverse(fid, grp_name, visit_start, recurse, &visitor) < 0) + return -1; return 0; } diff --git a/tools/lib/h5trav.h b/tools/lib/h5trav.h index 05bc3cb..5c07331 100644 --- a/tools/lib/h5trav.h +++ b/tools/lib/h5trav.h @@ -18,6 +18,12 @@ #include "hdf5.h" +/* Typedefs for visiting objects */ +typedef herr_t (*h5trav_obj_func_t)(const char *path_name, const H5O_info_t *oinfo, + const char *first_seen, void *udata); +typedef herr_t (*h5trav_lnk_func_t)(const char *path_name, const H5L_info_t *linfo, + void *udata); + /*------------------------------------------------------------------------- * public enum to specify type of an object * the TYPE can be: @@ -101,6 +107,14 @@ extern "C" { #endif /*------------------------------------------------------------------------- + * "h5trav general" public functions + *------------------------------------------------------------------------- + */ +int h5trav_visit(hid_t file_id, const char *grp_name, hbool_t visit_start, + hbool_t recurse, h5trav_obj_func_t visit_obj, h5trav_lnk_func_t visit_lnk, + void *udata); + +/*------------------------------------------------------------------------- * "h5trav info" public functions *------------------------------------------------------------------------- */ diff --git a/tools/testfiles/h5copytst.out.ls b/tools/testfiles/h5copytst.out.ls index c4d1778..785c3f0 100644 --- a/tools/testfiles/h5copytst.out.ls +++ b/tools/testfiles/h5copytst.out.ls @@ -2,6 +2,9 @@ Expected output for 'h5ls ../testfiles/h5copytst.out.h5' ############################# Opened "../testfiles/h5copytst.out.h5" with sec2 driver. +/ Group + Location: 1:96 + Links: 1 /A Group Location: 1:90344 Links: 1 diff --git a/tools/testfiles/h5mkgrp_nested.ls b/tools/testfiles/h5mkgrp_nested.ls index 2b9fb25..472656d 100644 --- a/tools/testfiles/h5mkgrp_nested.ls +++ b/tools/testfiles/h5mkgrp_nested.ls @@ -2,6 +2,9 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_nested.h5' ############################# Opened "../testfiles/h5mkgrp_nested.h5" with sec2 driver. +/ Group + Location: 1:96 + Links: 1 /one Group Location: 1:800 Links: 1 diff --git a/tools/testfiles/h5mkgrp_nested_latest.ls b/tools/testfiles/h5mkgrp_nested_latest.ls index f0bab6f..c00292d 100644 --- a/tools/testfiles/h5mkgrp_nested_latest.ls +++ b/tools/testfiles/h5mkgrp_nested_latest.ls @@ -2,6 +2,10 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_nested_latest.h5' ############################# Opened "../testfiles/h5mkgrp_nested_latest.h5" with sec2 driver. +/ Group + Location: 1:48 + Links: 1 + Modified: XXXX-XX-XX XX:XX:XX XXX /one Group Location: 1:195 Links: 1 diff --git a/tools/testfiles/h5mkgrp_nested_mult.ls b/tools/testfiles/h5mkgrp_nested_mult.ls index 4fccd83..6a22ffd 100644 --- a/tools/testfiles/h5mkgrp_nested_mult.ls +++ b/tools/testfiles/h5mkgrp_nested_mult.ls @@ -2,6 +2,9 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_nested_mult.h5' ############################# Opened "../testfiles/h5mkgrp_nested_mult.h5" with sec2 driver. +/ Group + Location: 1:96 + Links: 1 /one Group Location: 1:800 Links: 1 diff --git a/tools/testfiles/h5mkgrp_nested_mult_latest.ls b/tools/testfiles/h5mkgrp_nested_mult_latest.ls index 7835050..0b19ff9 100644 --- a/tools/testfiles/h5mkgrp_nested_mult_latest.ls +++ b/tools/testfiles/h5mkgrp_nested_mult_latest.ls @@ -2,6 +2,10 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_nested_mult_latest.h5' ############################# Opened "../testfiles/h5mkgrp_nested_mult_latest.h5" with sec2 driver. +/ Group + Location: 1:48 + Links: 1 + Modified: XXXX-XX-XX XX:XX:XX XXX /one Group Location: 1:195 Links: 1 diff --git a/tools/testfiles/h5mkgrp_several.ls b/tools/testfiles/h5mkgrp_several.ls index dcbe3eb..bbf5c92 100644 --- a/tools/testfiles/h5mkgrp_several.ls +++ b/tools/testfiles/h5mkgrp_several.ls @@ -2,6 +2,9 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_several.h5' ############################# Opened "../testfiles/h5mkgrp_several.h5" with sec2 driver. +/ Group + Location: 1:96 + Links: 1 /one Group Location: 1:800 Links: 1 diff --git a/tools/testfiles/h5mkgrp_several_latest.ls b/tools/testfiles/h5mkgrp_several_latest.ls index c59107e..a3b5224 100644 --- a/tools/testfiles/h5mkgrp_several_latest.ls +++ b/tools/testfiles/h5mkgrp_several_latest.ls @@ -2,6 +2,10 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_several_latest.h5' ############################# Opened "../testfiles/h5mkgrp_several_latest.h5" with sec2 driver. +/ Group + Location: 1:48 + Links: 1 + Modified: XXXX-XX-XX XX:XX:XX XXX /one Group Location: 1:195 Links: 1 diff --git a/tools/testfiles/h5mkgrp_single.ls b/tools/testfiles/h5mkgrp_single.ls index 1f7e828..e9932f7 100644 --- a/tools/testfiles/h5mkgrp_single.ls +++ b/tools/testfiles/h5mkgrp_single.ls @@ -2,6 +2,9 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_single.h5' ############################# Opened "../testfiles/h5mkgrp_single.h5" with sec2 driver. +/ Group + Location: 1:96 + Links: 1 /single Group Location: 1:800 Links: 1 diff --git a/tools/testfiles/h5mkgrp_single_latest.ls b/tools/testfiles/h5mkgrp_single_latest.ls index 7f5ee72..b6e6ea4 100644 --- a/tools/testfiles/h5mkgrp_single_latest.ls +++ b/tools/testfiles/h5mkgrp_single_latest.ls @@ -2,6 +2,10 @@ Expected output for 'h5ls ../testfiles/h5mkgrp_single_latest.h5' ############################# Opened "../testfiles/h5mkgrp_single_latest.h5" with sec2 driver. +/ Group + Location: 1:48 + Links: 1 + Modified: XXXX-XX-XX XX:XX:XX XXX /latest Group Location: 1:195 Links: 1 diff --git a/tools/testfiles/tall-2.ls b/tools/testfiles/tall-2.ls index 5513214..2e4cd37 100644 --- a/tools/testfiles/tall-2.ls +++ b/tools/testfiles/tall-2.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tall.h5' ############################# +/ Group /g1 Group /g1/g1.1 Group /g1/g1.1/dset1.1.1 Dataset {10, 10} diff --git a/tools/testfiles/tarray1.ls b/tools/testfiles/tarray1.ls index 83a51a8..60c002d 100644 --- a/tools/testfiles/tarray1.ls +++ b/tools/testfiles/tarray1.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tarray1.h5' ############################# +/ Group /Dataset1 Dataset {4} Data: (0) [0,1,2,3], [10,11,12,13], [20,21,22,23], [30,31,32,33] diff --git a/tools/testfiles/tattr2.ls b/tools/testfiles/tattr2.ls index 88b24cd..0448868 100644 --- a/tools/testfiles/tattr2.ls +++ b/tools/testfiles/tattr2.ls @@ -2,149 +2,6 @@ output for 'h5ls -w80 -v -S tattr2.h5' ############################# Opened "tattr2.h5" with sec2 driver. - Attribute: array {2} - Type: [3] 32-bit little-endian integer - Data: [1,2,3], [4,5,6] - Attribute: array2D {3, 2} - Type: [3] 32-bit little-endian integer - Data: - (0,0) [1,2,3], [4,5,6], [7,8,9], [10,11,12], [13,14,15], [16,17,18] - Attribute: array3D {4, 3, 2} - Type: [3] 32-bit little-endian integer - Data: - (0,0,0) [1,2,3], [4,5,6], [7,8,9], [10,11,12], [13,14,15], - (0,2,1) [16,17,18], [19,20,21], [22,23,24], [25,26,27], [28,29,30], - (1,2,0) [31,32,33], [34,35,36], [37,38,39], [40,41,42], [43,44,45], - (2,1,1) [46,47,48], [49,50,51], [52,53,54], [55,56,57], [58,59,60], - (3,1,0) [61,62,63], [64,65,66], [67,68,69], [70,71,72] - Attribute: bitfield {2} - Type: 8-bit bitfield - Data: 0x01, 0x02 - Attribute: bitfield2D {3, 2} - Type: 8-bit bitfield - Data: - (0,0) 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 - Attribute: bitfield3D {4, 3, 2} - Type: 8-bit bitfield - Data: - (0,0,0) 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, - (1,2,0) 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, - (3,1,0) 0x15, 0x16, 0x17, 0x18 - Attribute: compound {2} - Type: struct { - "a" +0 8-bit integer - "b" +4 IEEE 64-bit little-endian float - } 12 bytes - Data: {1, 2}, {3, 4} - Attribute: compound2D {3, 2} - Type: struct { - "a" +0 8-bit integer - "b" +4 IEEE 64-bit little-endian float - } 12 bytes - Data: - (0,0) {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12} - Attribute: compound3D {4, 3, 2} - Type: struct { - "a" +0 8-bit integer - "b" +4 IEEE 64-bit little-endian float - } 12 bytes - Data: - (0,0,0) {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}, {13, - (1,0,0) 14}, {15, 16}, {17, 18}, {19, 20}, {21, 22}, {23, 24}, - (2,0,0) {25, 26}, {27, 28}, {29, 30}, {31, 32}, {33, 34}, {35, 36}, - (3,0,0) {37, 38}, {39, 40}, {41, 42}, {43, 44}, {45, 46}, {47, 48} - Attribute: enum {2} - Type: enum 32-bit little-endian integer { - RED = 0 - GREEN = 1 - } - Data: RED, RED - Attribute: enum2D {3, 2} - Type: enum 32-bit little-endian integer { - RED = 0 - GREEN = 1 - } - Data: - (0,0) RED, RED, RED, RED, RED, RED - Attribute: enum3D {4, 3, 2} - Type: enum 32-bit little-endian integer { - RED = 0 - GREEN = 1 - } - Data: - (0,0,0) RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, - (2,0,0) RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED, RED - Attribute: float {2} - Type: IEEE 32-bit little-endian float - Data: 1, 2 - Attribute: float2D {3, 2} - Type: IEEE 32-bit little-endian float - Data: - (0,0) 1, 2, 3, 4, 5, 6 - Attribute: float3D {4, 3, 2} - Type: IEEE 32-bit little-endian float - Data: - (0,0,0) 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - (2,2,1) 18, 19, 20, 21, 22, 23, 24 - Attribute: integer {2} - Type: 32-bit little-endian integer - Data: 1, 2 - Attribute: integer2D {3, 2} - Type: 32-bit little-endian integer - Data: - (0,0) 1, 2, 3, 4, 5, 6 - Attribute: integer3D {4, 3, 2} - Type: 32-bit little-endian integer - Data: - (0,0,0) 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - (2,2,1) 18, 19, 20, 21, 22, 23, 24 - Attribute: opaque {2} - Type: 1-byte opaque type - (tag = "1-byte opaque type") - Data: 0x01, 0x02 - Attribute: opaque2D {3, 2} - Type: 1-byte opaque type - (tag = "1-byte opaque type") - Data: - (0,0) 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 - Attribute: opaque3D {4, 3, 2} - Type: 1-byte opaque type - (tag = "1-byte opaque type") - Data: - (0,0,0) 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, - (1,2,0) 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, - (3,1,0) 0x15, 0x16, 0x17, 0x18 - Attribute: string {2} - Type: 2-byte null-terminated ASCII string - Data: "ab", "de" - Attribute: string2D {3, 2} - Type: 2-byte null-terminated ASCII string - Data: - (0,0) "ab", "cd", "ef", "gh", "ij", "kl" - Attribute: string3D {4, 3, 2} - Type: 2-byte null-terminated ASCII string - Data: - (0,0,0) "ab", "cd", "ef", "gh", "ij", "kl", "mn", "pq", "rs", "tu", - (1,2,0) "vw", "xz", "AB", "CD", "EF", "GH", "IJ", "KL", "MN", "PQ", - (3,1,0) "RS", "TU", "VW", "XZ" - Attribute: vlen {2} - Type: variable length of - 32-bit little-endian integer - Data: (1), (2,3) - Attribute: vlen2D {3, 2} - Type: variable length of - 32-bit little-endian integer - Data: - (0,0) (0), (1), (2,3), (4,5), (6,7,8), (9,10,11) - Attribute: vlen3D {4, 3, 2} - Type: variable length of - 32-bit little-endian integer - Data: - (0,0,0) (0), (1), (2), (3), (4), (5), (6,7), (8,9), (10,11), - (1,1,1) (12,13), (14,15), (16,17), (18,19,20), (21,22,23), - (2,1,0) (24,25,26), (27,28,29), (30,31,32), (33,34,35), - (3,0,0) (36,37,38,39), (40,41,42,43), (44,45,46,47), (48,49,50,51), - (3,2,0) (52,53,54,55), (56,57,58,59) dset Dataset {2/2} Attribute: array {2} Type: [3] 32-bit little-endian integer diff --git a/tools/testfiles/tcomp-1.ls b/tools/testfiles/tcomp-1.ls index 599fe68..9cfb47d 100644 --- a/tools/testfiles/tcomp-1.ls +++ b/tools/testfiles/tcomp-1.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tcompound.h5' ############################# +/ Group /dset1 Dataset {5} Data: (0) {0, 0, 1}, {1, 1, 0.5}, {2, 4, 0.333333333333333}, {3, 9, 0.25}, diff --git a/tools/testfiles/tdset-1.ls b/tools/testfiles/tdset-1.ls index 6853429..b6e4671 100644 --- a/tools/testfiles/tdset-1.ls +++ b/tools/testfiles/tdset-1.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tdset.h5' ############################# +/ Group /dset1 Dataset {10, 20} Data: (0,0) 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, diff --git a/tools/testfiles/textlink-1.ls b/tools/testfiles/textlink-1.ls index f92786b..87be5a7 100644 --- a/tools/testfiles/textlink-1.ls +++ b/tools/testfiles/textlink-1.ls @@ -1,5 +1,6 @@ ############################# output for 'h5ls -w80 -r textlink.h5' ############################# +/ Group /extlink1 -> file: filename path: objname /extlink2 -> file: anotherfile path: anotherobj diff --git a/tools/testfiles/tgroup-1.ls b/tools/testfiles/tgroup-1.ls index 62ebe70..0ca929d 100644 --- a/tools/testfiles/tgroup-1.ls +++ b/tools/testfiles/tgroup-1.ls @@ -1,17 +1,29 @@ ############################# output for 'h5ls -w80 -r -g tgroup.h5' ############################# -/ Group -/g1 Group -/g1/g1.1 Group -/g1/g1.2 Group -/g2 Group -/g2/g2.1 Group -/g2/g2.1/g2.1.1 Group -/g2/g2.1/g2.1.2 Group -/g2/g2.1/g2.1.3 Group -/g3 Group -/g3/g3.1 Group -/g3/g3.2 Group -/g3/g3.3 Group -/g3/g3.4 Group +Error: 'recursive' option not compatible with 'group info' option! + +usage: h5ls [OPTIONS] [OBJECTS...] + OPTIONS + -h, -?, --help Print a usage message and exit + -a, --address Print addresses for raw data + -d, --data Print the values of datasets + -e, --errors Show all HDF5 error reporting + -f, --full Print full path names instead of base names + -g, --group Show information about a group, not its contents + -l, --label Label members of compound datasets + -r, --recursive List all groups recursively, avoiding cycles + -s, --string Print 1-byte integer datasets as ASCII + -S, --simple Use a machine-readable output format + -wN, --width=N Set the number of columns of output + -v, --verbose Generate more verbose output + -V, --version Print version number and exit + --vfd=DRIVER Use the specified virtual file driver + -x, --hexdump Show raw data in hexadecimal format + + OBJECTS + Each object consists of an HDF5 file name optionally followed by a + slash and an object name within the file (if no object is specified + within the file then the contents of the root group are displayed). + The file name may include a printf(3C) integer format such as + "%05d" to open a file family. diff --git a/tools/testfiles/tgroup-2.ls b/tools/testfiles/tgroup-2.ls new file mode 100644 index 0000000..0817d93 --- /dev/null +++ b/tools/testfiles/tgroup-2.ls @@ -0,0 +1,4 @@ +############################# + output for 'h5ls -w80 -g tgroup.h5/g1' +############################# +g1 Group diff --git a/tools/testfiles/tloop-1.ls b/tools/testfiles/tloop-1.ls index b9631b7..22cb6c7 100644 --- a/tools/testfiles/tloop-1.ls +++ b/tools/testfiles/tloop-1.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tloop.h5' ############################# +/ Group /g1 Group /g1/g1.1 Group /g1/g1.1/g2.1 Group, same as /g1 diff --git a/tools/testfiles/tnestcomp-1.ls b/tools/testfiles/tnestcomp-1.ls index eef41ef..9dc193d 100644 --- a/tools/testfiles/tnestcomp-1.ls +++ b/tools/testfiles/tnestcomp-1.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tnestedcomp.h5' ############################# +/ Group /ArrayOfStructures Dataset {10} Data: (0) {0, 0, 1, {"A", [-100,100]}}, {1, 1, 0.5, {"B", [-100,100]}}, diff --git a/tools/testfiles/tsaf.ls b/tools/testfiles/tsaf.ls index 8efc0f2..96d4811 100644 --- a/tools/testfiles/tsaf.ls +++ b/tools/testfiles/tsaf.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tsaf.h5' ############################# +/ Group /.DSL_METADATA Dataset {5919/Inf} Data: (0) 47, 32, 67, 79, 78, 84, 65, 73, 78, 69, 82, 10, 47, 46, 97, 116, diff --git a/tools/testfiles/tslink-1.ls b/tools/testfiles/tslink-1.ls index 05b9bca..4c16958 100644 --- a/tools/testfiles/tslink-1.ls +++ b/tools/testfiles/tslink-1.ls @@ -1,5 +1,6 @@ ############################# output for 'h5ls -w80 -r tslink.h5' ############################# +/ Group /slink1 -> somevalue /slink2 -> linkvalue diff --git a/tools/testfiles/tstr-1.ls b/tools/testfiles/tstr-1.ls index 1961fd4..8a223cc 100644 --- a/tools/testfiles/tstr-1.ls +++ b/tools/testfiles/tstr-1.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tstr.h5' ############################# +/ Group /comp1 Dataset {3, 6} Data: (0,0) {[0,1,4,9,16,25,36,49,64,81,1,4,9,16,25,36,49,64,81,100,4,9,16, diff --git a/tools/testfiles/tudlink-1.ls b/tools/testfiles/tudlink-1.ls index e83fce7..b8578ce 100644 --- a/tools/testfiles/tudlink-1.ls +++ b/tools/testfiles/tudlink-1.ls @@ -1,5 +1,6 @@ ############################# output for 'h5ls -w80 -r tudlink.h5' ############################# +/ Group /udlink1 -> cannot follow UD links /udlink2 -> cannot follow UD links diff --git a/tools/testfiles/tvldtypes1.ls b/tools/testfiles/tvldtypes1.ls index cf1688e..4c4c162 100644 --- a/tools/testfiles/tvldtypes1.ls +++ b/tools/testfiles/tvldtypes1.ls @@ -1,6 +1,7 @@ ############################# output for 'h5ls -w80 -r -d tvldtypes1.h5' ############################# +/ Group /Dataset1.0 Dataset {4} Data: (0) (0), (10,11), (20,21,22), (30,31,32,33) |