diff options
Diffstat (limited to 'tools/h5ls/h5ls.c')
-rw-r--r-- | tools/h5ls/h5ls.c | 524 |
1 files changed, 204 insertions, 320 deletions
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 */ |