diff options
author | Allen Byrne <byrn@hdfgroup.org> | 2016-10-27 15:06:00 (GMT) |
---|---|---|
committer | Allen Byrne <byrn@hdfgroup.org> | 2016-10-27 15:06:00 (GMT) |
commit | 2c6dbbf2129c4997606be4b130346d42fe12eae3 (patch) | |
tree | db8430aa5757b32f3bd46928798cc2b686a72bfb /tools/src | |
parent | 5b562d9ce9b2945d0378b9c03e01f42923da80f4 (diff) | |
download | hdf5-2c6dbbf2129c4997606be4b130346d42fe12eae3.zip hdf5-2c6dbbf2129c4997606be4b130346d42fe12eae3.tar.gz hdf5-2c6dbbf2129c4997606be4b130346d42fe12eae3.tar.bz2 |
Split tools into src and test - add folders
Diffstat (limited to 'tools/src')
57 files changed, 31285 insertions, 0 deletions
diff --git a/tools/src/CMakeLists.txt b/tools/src/CMakeLists.txt new file mode 100644 index 0000000..5001b26 --- /dev/null +++ b/tools/src/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required (VERSION 3.1.0) +PROJECT (HDF5_TOOLS_SRC) + +#----------------------------------------------------------------------------- +# Apply Definitions to compiler in this directory and below +#----------------------------------------------------------------------------- +add_definitions (${HDF_EXTRA_C_FLAGS}) + +#-- Add the h5diff and test executables +add_subdirectory (${HDF5_TOOLS_SRC_SOURCE_DIR}/h5diff) + +#-- Add the h5ls executable +add_subdirectory (${HDF5_TOOLS_SRC_SOURCE_DIR}/h5ls) + +#-- Misc Executables +add_subdirectory (${HDF5_TOOLS_SRC_SOURCE_DIR}/misc) + +#-- Add the h5import and test executables +add_subdirectory (${HDF5_TOOLS_SRC_SOURCE_DIR}/h5import) + +#-- h5Repack executables +add_subdirectory (${HDF5_TOOLS_SRC_SOURCE_DIR}/h5repack) + +#-- Add the h5dump and test executables +add_subdirectory (${HDF5_TOOLS_SRC_SOURCE_DIR}/h5jam) + +#-- Add the h5copy and test executables +add_subdirectory (${HDF5_TOOLS_SRC_SOURCE_DIR}/h5copy) + +#-- Add the h5stat and test executables +add_subdirectory (${HDF5_TOOLS_SRC_SOURCE_DIR}/h5stat) + +#-- Add the h5dump and test executables +add_subdirectory (${HDF5_TOOLS_SRC_SOURCE_DIR}/h5dump) + +#-- Add the h5format_convert and test executables +add_subdirectory (${HDF5_TOOLS_SRC_SOURCE_DIR}/h5format_convert) diff --git a/tools/src/Makefile.am b/tools/src/Makefile.am new file mode 100644 index 0000000..0cea969 --- /dev/null +++ b/tools/src/Makefile.am @@ -0,0 +1,29 @@ +# +# Copyright by The HDF Group. +# Copyright by the Board of Trustees of the University of Illinois. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the files COPYING and Copyright.html. COPYING can be found at the root +# of the source code distribution tree; Copyright.html can be found at the +# root level of an installed copy of the electronic HDF5 document set and +# is linked from the top-level documents page. It can also be found at +# http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have +# access to either file, you may request a copy from help@hdfgroup.org. +## +## Makefile.am +## Run automake to generate a Makefile.in from this file. +## +# +# Tools HDF5 Makefile(.in) +# + +include $(top_srcdir)/config/commence.am + +CONFIG=ordered + +# All subdirectories +SUBDIRS=h5diff h5ls h5dump misc h5import h5repack h5jam h5copy h5stat + +include $(top_srcdir)/config/conclude.am diff --git a/tools/src/h5copy/CMakeLists.txt b/tools/src/h5copy/CMakeLists.txt new file mode 100644 index 0000000..2a33c9e --- /dev/null +++ b/tools/src/h5copy/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required (VERSION 3.1.0) +PROJECT (HDF5_TOOLS_SRC_H5COPY) + +#----------------------------------------------------------------------------- +# Setup include Directories +#----------------------------------------------------------------------------- +INCLUDE_DIRECTORIES (${HDF5_TOOLS_DIR}/lib) + +# -------------------------------------------------------------------- +# Add the h5copy and test executables +# -------------------------------------------------------------------- +add_executable (h5copy ${HDF5_TOOLS_SRC_H5COPY_SOURCE_DIR}/h5copy.c) +TARGET_NAMING (h5copy STATIC) +TARGET_C_PROPERTIES (h5copy STATIC " " " ") +target_link_libraries (h5copy ${HDF5_TOOLS_LIB_TARGET} ${HDF5_LIB_TARGET}) +set_target_properties (h5copy PROPERTIES FOLDER tools) +set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};h5copy") + +set (H5_DEP_EXECUTABLES h5copy) + +############################################################################## +############################################################################## +### I N S T A L L A T I O N ### +############################################################################## +############################################################################## + +#----------------------------------------------------------------------------- +# Rules for Installation of tools using make Install target +#----------------------------------------------------------------------------- + +#INSTALL_PROGRAM_PDB (h5copy ${HDF5_INSTALL_BIN_DIR} toolsapplications) + +install ( + TARGETS + h5copy + EXPORT + ${HDF5_EXPORTED_TARGETS} + RUNTIME DESTINATION ${HDF5_INSTALL_BIN_DIR} COMPONENT toolsapplications +) diff --git a/tools/src/h5copy/Makefile.am b/tools/src/h5copy/Makefile.am new file mode 100644 index 0000000..b2cdf92 --- /dev/null +++ b/tools/src/h5copy/Makefile.am @@ -0,0 +1,40 @@ +# +# Copyright by The HDF Group. +# Copyright by the Board of Trustees of the University of Illinois. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the files COPYING and Copyright.html. COPYING can be found at the root +# of the source code distribution tree; Copyright.html can be found at the +# root level of an installed copy of the electronic HDF5 document set and +# is linked from the top-level documents page. It can also be found at +# http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have +# access to either file, you may request a copy from help@hdfgroup.org. +## +## Makefile.am +## Run automake to generate a Makefile.in from this file. +# +# HDF5 Library Makefile(.in) +# + +include $(top_srcdir)/config/commence.am + +# Include src and tools/lib directories +AM_CPPFLAGS+=-I$(top_srcdir)/src -I$(top_srcdir)/tools/lib + +# This is our main target, the h5copy tool +bin_PROGRAMS=h5copy +check_PROGRAMS=$(TEST_PROG) + +# Add h5copy specific linker flags here +h5copy_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) + +# All programs depend on the hdf5 and h5tools libraries +LDADD=$(LIBH5TOOLS) $(LIBHDF5) + +# Temporary files. *.h5 are generated by h5dumpgentest. They should +# copied to the testfiles/ directory if update is required. +CHECK_CLEANFILES+=*.h5 + +include $(top_srcdir)/config/conclude.am diff --git a/tools/src/h5copy/h5copy.c b/tools/src/h5copy/h5copy.c new file mode 100644 index 0000000..5371a21 --- /dev/null +++ b/tools/src/h5copy/h5copy.c @@ -0,0 +1,534 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "H5private.h" +#include "h5tools.h" +#include "h5tools_utils.h" +#include <string.h> +#include <stdlib.h> + +/* Name of tool */ +#define PROGRAMNAME "h5copy" + +/* command-line options: short and long-named parameters */ +static const char *s_opts = "d:f:hi:o:ps:vVE"; +static struct long_options l_opts[] = { + { "destination", require_arg, 'd' }, + { "flag", require_arg, 'f' }, + { "help", no_arg, 'h' }, + { "input", require_arg, 'i' }, + { "output", require_arg, 'o' }, + { "parents", no_arg, 'p' }, + { "source", require_arg, 's' }, + { "verbose", no_arg, 'v' }, + { "version", no_arg, 'V' }, + { "enable-error-stack", no_arg, 'E' }, + { NULL, 0, '\0' } +}; +char *fname_src = NULL; +char *fname_dst = NULL; +char *oname_src = NULL; +char *oname_dst = NULL; +char *str_flag = NULL; + +/*------------------------------------------------------------------------- + * Function: leave + * + * Purpose: Shutdown MPI & HDF5 and call exit() + * + * Return: Does not return + * + * Programmer: Quincey Koziol + * Saturday, 31. January 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +leave(int ret) +{ + if (fname_src) + HDfree(fname_src); + if (fname_dst) + HDfree(fname_dst); + if (oname_dst) + HDfree(oname_dst); + if (oname_src) + HDfree(oname_src); + if (str_flag) + HDfree(str_flag); + + h5tools_close(); + HDexit(ret); +} + + +/*------------------------------------------------------------------------- + * Function: usage + * + * Purpose: Prints a usage message on stderr and then returns. + * + * Return: void + * + * Programmer: Pedro Vicente Nunes, 7/8/2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +usage (void) +{ + FLUSHSTREAM(rawoutstream); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, "usage: h5copy [OPTIONS] [OBJECTS...]\n"); + PRINTVALSTREAM(rawoutstream, " OBJECTS\n"); + PRINTVALSTREAM(rawoutstream, " -i, --input input file name\n"); + PRINTVALSTREAM(rawoutstream, " -o, --output output file name\n"); + PRINTVALSTREAM(rawoutstream, " -s, --source source object name\n"); + PRINTVALSTREAM(rawoutstream, " -d, --destination destination object name\n"); + PRINTVALSTREAM(rawoutstream, " OPTIONS\n"); + PRINTVALSTREAM(rawoutstream, " -h, --help Print a usage message and exit\n"); + PRINTVALSTREAM(rawoutstream, " -p, --parents No error if existing, make parent groups as needed\n"); + PRINTVALSTREAM(rawoutstream, " -v, --verbose Print information about OBJECTS and OPTIONS\n"); + PRINTVALSTREAM(rawoutstream, " -V, --version Print version number and exit\n"); + PRINTVALSTREAM(rawoutstream, " -f, --flag Flag type\n\n"); + PRINTVALSTREAM(rawoutstream, " Flag type is one of the following strings:\n\n"); + PRINTVALSTREAM(rawoutstream, " shallow Copy only immediate members for groups\n\n"); + PRINTVALSTREAM(rawoutstream, " soft Expand soft links into new objects\n\n"); + PRINTVALSTREAM(rawoutstream, " ext Expand external links into new objects\n\n"); + PRINTVALSTREAM(rawoutstream, " ref Copy references and any referenced objects, i.e., objects\n"); + PRINTVALSTREAM(rawoutstream, " that the references point to.\n"); + PRINTVALSTREAM(rawoutstream, " Referenced objects are copied in addition to the objects\n"); + PRINTVALSTREAM(rawoutstream, " specified on the command line and reference datasets are\n"); + PRINTVALSTREAM(rawoutstream, " populated with correct reference values. Copies of referenced\n"); + PRINTVALSTREAM(rawoutstream, " datasets outside the copy range specified on the command line\n"); + PRINTVALSTREAM(rawoutstream, " will normally have a different name from the original.\n"); + PRINTVALSTREAM(rawoutstream, " (Default:Without this option, reference value(s) in any\n"); + PRINTVALSTREAM(rawoutstream, " reference datasets are set to NULL and referenced objects are\n"); + PRINTVALSTREAM(rawoutstream, " not copied unless they are otherwise within the copy range\n"); + PRINTVALSTREAM(rawoutstream, " specified on the command line.)\n\n"); + PRINTVALSTREAM(rawoutstream, " noattr Copy object without copying attributes\n\n"); + PRINTVALSTREAM(rawoutstream, " allflags Switches all flags from the default to the non-default setting\n\n"); + PRINTVALSTREAM(rawoutstream, " These flag types correspond to the following API symbols\n\n"); + PRINTVALSTREAM(rawoutstream, " H5O_COPY_SHALLOW_HIERARCHY_FLAG\n"); + PRINTVALSTREAM(rawoutstream, " H5O_COPY_EXPAND_SOFT_LINK_FLAG\n"); + PRINTVALSTREAM(rawoutstream, " H5O_COPY_EXPAND_EXT_LINK_FLAG\n"); + PRINTVALSTREAM(rawoutstream, " H5O_COPY_EXPAND_REFERENCE_FLAG\n"); + PRINTVALSTREAM(rawoutstream, " H5O_COPY_WITHOUT_ATTR_FLAG\n"); + PRINTVALSTREAM(rawoutstream, " H5O_COPY_ALL\n"); +} + + + +/*------------------------------------------------------------------------- + * Function: parse_flag + * + * Purpose: read the flag -f STRING + * + * STRING is one of the following (API symbol and description) + * + * shallow H5O_COPY_SHALLOW_HIERARCHY_FLAG: Copy only immediate members for groups + * soft H5O_COPY_EXPAND_SOFT_LINK_FLAG: Expand soft links into new objects + * ext H5O_COPY_EXPAND_EXT_LINK_FLAG: Expand external links into new objects + * ref H5O_COPY_EXPAND_OBJ_REFERENCE_FLAG: Copy objects that are pointed by references + * noattr H5O_COPY_WITHOUT_ATTR_FLAG Copy object without copying attributes + * allflags Switches all flags from the default to the non-default setting + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Pedro Vicente Nunes, 7/8/2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + + +static int parse_flag(const char* s_flag, unsigned *flag) +{ + unsigned fla=0; + + if (HDstrcmp(s_flag,"shallow")==0) + { + fla = H5O_COPY_SHALLOW_HIERARCHY_FLAG; + } + else if (HDstrcmp(s_flag,"soft")==0) + { + fla = H5O_COPY_EXPAND_SOFT_LINK_FLAG; + } + else if (HDstrcmp(s_flag,"ext")==0) + { + fla = H5O_COPY_EXPAND_EXT_LINK_FLAG; + } + else if (HDstrcmp(s_flag,"ref")==0) + { + fla = H5O_COPY_EXPAND_REFERENCE_FLAG; + } + else if (HDstrcmp(s_flag,"noattr")==0) + { + fla = H5O_COPY_WITHOUT_ATTR_FLAG; + } + else if (HDstrcmp(s_flag,"allflags")==0) + { + fla = H5O_COPY_ALL; + } + else if (HDstrcmp(s_flag,"nullmsg")==0) + { + fla = H5O_COPY_PRESERVE_NULL_FLAG; + } + else + { + error_msg("Error in input flag\n"); + return -1; + } + + *flag = (*flag) | fla; + + return 0; +} + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: main program + * + * Programmer: Pedro Vicente Nunes + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +int +main (int argc, const char *argv[]) +{ + int ret_value = 0; /*no need to LEAVE() on ERROR: HERR_INIT(int, SUCCEED) */ + H5E_auto2_t func; + H5E_auto2_t tools_func; + void *edata; + void *tools_edata; + hid_t fid_src = -1; + hid_t fid_dst = -1; + unsigned flag = 0; + unsigned verbose = 0; + unsigned parents = 0; + hid_t ocpl_id = (-1); /* Object copy property list */ + hid_t lcpl_id = (-1); /* Link creation property list */ + int opt; + int li_ret; + h5tool_link_info_t linkinfo; + + h5tools_setprogname(PROGRAMNAME); + h5tools_setstatus(EXIT_SUCCESS); + + /* Disable error reporting */ + H5Eget_auto2(H5E_DEFAULT, &func, &edata); + H5Eset_auto2(H5E_DEFAULT, NULL, NULL); + + /* Initialize h5tools lib */ + h5tools_init(); + + /* Disable tools error reporting */ + H5Eget_auto2(H5tools_ERR_STACK_g, &tools_func, &tools_edata); + H5Eset_auto2(H5tools_ERR_STACK_g, NULL, NULL); + + /* init linkinfo struct */ + HDmemset(&linkinfo, 0, sizeof(h5tool_link_info_t)); + + /* Check for no command line parameters */ + if(argc == 1) + { + usage(); + leave(EXIT_FAILURE); + } /* end if */ + + /* parse command line options */ + while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) + { + switch ((char)opt) + { + case 'd': + oname_dst = HDstrdup(opt_arg); + break; + + case 'f': + /* validate flag */ + if (parse_flag(opt_arg,&flag)<0) + { + usage(); + leave(EXIT_FAILURE); + } + str_flag = HDstrdup(opt_arg); + break; + + case 'h': + usage(); + leave(EXIT_SUCCESS); + break; + + case 'i': + fname_src = HDstrdup(opt_arg); + break; + + case 'o': + fname_dst = HDstrdup(opt_arg); + break; + + case 'p': + parents = 1; + break; + + case 's': + oname_src = HDstrdup(opt_arg); + break; + + case 'V': + print_version(h5tools_getprogname()); + leave(EXIT_SUCCESS); + break; + + case 'v': + verbose = 1; + break; + + case 'E': + enable_error_stack = TRUE; + break; + + default: + usage(); + leave(EXIT_FAILURE); + } + } /* end of while */ + +/*------------------------------------------------------------------------- + * check for missing file/object names + *-------------------------------------------------------------------------*/ + + if (fname_src==NULL) + { + error_msg("Input file name missing\n"); + usage(); + leave(EXIT_FAILURE); + } + + if (fname_dst==NULL) + { + error_msg("Output file name missing\n"); + usage(); + leave(EXIT_FAILURE); + } + + if (oname_src==NULL) + { + error_msg("Source object name missing\n"); + usage(); + leave(EXIT_FAILURE); + } + + if (oname_dst==NULL) + { + error_msg("Destination object name missing\n"); + usage(); + leave(EXIT_FAILURE); + } + + if (enable_error_stack) { + H5Eset_auto2(H5E_DEFAULT, func, edata); + H5Eset_auto2(H5tools_ERR_STACK_g, tools_func, tools_edata); + } + + /*------------------------------------------------------------------------- + * open output file + *-------------------------------------------------------------------------*/ + + /* Attempt to open an existing HDF5 file first. Need to open the dst file + before the src file just in case that the dst and src are the same file + */ + fid_dst = h5tools_fopen(fname_dst, H5F_ACC_RDWR, H5P_DEFAULT, NULL, NULL, 0); + + /*------------------------------------------------------------------------- + * open input file + *-------------------------------------------------------------------------*/ + + fid_src = h5tools_fopen(fname_src, H5F_ACC_RDONLY, H5P_DEFAULT, NULL, NULL, 0); + + /*------------------------------------------------------------------------- + * test for error in opening input file + *-------------------------------------------------------------------------*/ + if (fid_src==-1) + { + error_msg("Could not open input file <%s>...Exiting\n", fname_src); + leave(EXIT_FAILURE); + } + + + /*------------------------------------------------------------------------- + * create an output file when failed to open it + *-------------------------------------------------------------------------*/ + + /* If we couldn't open an existing file, try creating file */ + /* (use "EXCL" instead of "TRUNC", so we don't blow away existing non-HDF5 file) */ + if(fid_dst < 0) + fid_dst = H5Fcreate(fname_dst, H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT); + + /*------------------------------------------------------------------------- + * test for error in opening output file + *-------------------------------------------------------------------------*/ + if (fid_dst==-1) + { + error_msg("Could not open output file <%s>...Exiting\n", fname_dst); + leave(EXIT_FAILURE); + } + + /*------------------------------------------------------------------------- + * print some info + *-------------------------------------------------------------------------*/ + + if (verbose) + { + printf("Copying file <%s> and object <%s> to file <%s> and object <%s>\n", + fname_src, oname_src, fname_dst, oname_dst); + if (flag) { + HDassert(str_flag); + printf("Using %s flag\n", str_flag); + } + } + + + /*------------------------------------------------------------------------- + * create property lists for copy + *-------------------------------------------------------------------------*/ + + /* create property to pass copy options */ + if ( (ocpl_id = H5Pcreate(H5P_OBJECT_COPY)) < 0) + HGOTO_ERROR(EXIT_FAILURE, H5E_tools_min_id_g, "H5Pcreate failed"); + + /* set options for object copy */ + if (flag) + { + if ( H5Pset_copy_object(ocpl_id, flag) < 0) + HGOTO_ERROR(EXIT_FAILURE, H5E_tools_min_id_g, "H5Pset_copy_object failed"); + } + + /* Create link creation property list */ + if((lcpl_id = H5Pcreate(H5P_LINK_CREATE)) < 0) { + error_msg("Could not create link creation property list\n"); + HGOTO_ERROR(EXIT_FAILURE, H5E_tools_min_id_g, "H5Pcreate failed"); + } /* end if */ + + /* Check for creating intermediate groups */ + if(parents) { + /* Set the intermediate group creation property */ + if(H5Pset_create_intermediate_group(lcpl_id, 1) < 0) { + error_msg("Could not set property for creating parent groups\n"); + HGOTO_ERROR(EXIT_FAILURE, H5E_tools_min_id_g, "H5Pset_create_intermediate_group failed"); + } /* end if */ + + /* Display some output if requested */ + if(verbose) + printf("%s: Creating parent groups\n", h5tools_getprogname()); + } /* end if */ + else /* error, if parent groups doesn't already exist in destination file */ + { + size_t i, len; + + len = HDstrlen(oname_dst); + + /* check if all the parents groups exist. skip root group */ + for (i = 1; i < len; i++) + { + if ('/'==oname_dst[i]) + { + char *str_ptr; + + str_ptr = (char *)HDcalloc(i + 1, sizeof(char)); + HDstrncpy(str_ptr, oname_dst, i); + str_ptr[i]='\0'; + if (H5Lexists(fid_dst, str_ptr, H5P_DEFAULT) <= 0) + { + error_msg("group <%s> doesn't exist. Use -p to create parent groups.\n", str_ptr); + HDfree(str_ptr); + HGOTO_ERROR(EXIT_FAILURE, H5E_tools_min_id_g, "H5Lexists failed"); + } + HDfree(str_ptr); + } + } + } + + /*------------------------------------------------------------------------- + * do the copy + *-------------------------------------------------------------------------*/ + + if(verbose) + linkinfo.opt.msg_mode = 1; + + li_ret = H5tools_get_symlink_info(fid_src, oname_src, &linkinfo, 1); + if (li_ret == 0) /* dangling link */ + { + if(H5Lcopy(fid_src, oname_src, + fid_dst, oname_dst, + H5P_DEFAULT, H5P_DEFAULT) < 0) + HGOTO_ERROR(EXIT_FAILURE, H5E_tools_min_id_g, "H5Lcopy failed"); + } + else /* valid link */ + { + if (H5Ocopy(fid_src, /* Source file or group identifier */ + oname_src, /* Name of the source object to be copied */ + fid_dst, /* Destination file or group identifier */ + oname_dst, /* Name of the destination object */ + ocpl_id, /* Object copy property list */ + lcpl_id)<0) /* Link creation property list */ + HGOTO_ERROR(EXIT_FAILURE, H5E_tools_min_id_g, "H5Ocopy failed"); + } + + /* free link info path */ + if (linkinfo.trg_path) + HDfree(linkinfo.trg_path); + + /* close propertis */ + if(H5Pclose(ocpl_id)<0) + HGOTO_ERROR(EXIT_FAILURE, H5E_tools_min_id_g, "H5Pclose failed"); + if(H5Pclose(lcpl_id)<0) + HGOTO_ERROR(EXIT_FAILURE, H5E_tools_min_id_g, "H5Pclose failed"); + + /* close files */ + if (H5Fclose(fid_src)<0) + HGOTO_ERROR(EXIT_FAILURE, H5E_tools_min_id_g, "H5Fclose failed"); + if (H5Fclose(fid_dst)<0) + HGOTO_ERROR(EXIT_FAILURE, H5E_tools_min_id_g, "H5Fclose failed"); + + leave(EXIT_SUCCESS); + +done: + printf("Error in copy...Exiting\n"); + + /* free link info path */ + if (linkinfo.trg_path) + HDfree(linkinfo.trg_path); + + H5E_BEGIN_TRY { + H5Pclose(ocpl_id); + H5Pclose(lcpl_id); + H5Fclose(fid_src); + H5Fclose(fid_dst); + } H5E_END_TRY; + + leave(ret_value); +} + diff --git a/tools/src/h5diff/CMakeLists.txt b/tools/src/h5diff/CMakeLists.txt new file mode 100644 index 0000000..85a24ef --- /dev/null +++ b/tools/src/h5diff/CMakeLists.txt @@ -0,0 +1,67 @@ +cmake_minimum_required (VERSION 3.1.0) +PROJECT (HDF5_TOOLS_SRC_H5DIFF) + +#----------------------------------------------------------------------------- +# Setup include Directories +#----------------------------------------------------------------------------- +INCLUDE_DIRECTORIES (${HDF5_TOOLS_DIR}/lib) + +# -------------------------------------------------------------------- +# Add the h5diff executables +# -------------------------------------------------------------------- +add_executable (h5diff + ${HDF5_TOOLS_SRC_H5DIFF_SOURCE_DIR}/h5diff_common.c + ${HDF5_TOOLS_SRC_H5DIFF_SOURCE_DIR}/h5diff_main.c +) +TARGET_NAMING (h5diff STATIC) +TARGET_C_PROPERTIES (h5diff STATIC " " " ") +target_link_libraries (h5diff ${HDF5_TOOLS_LIB_TARGET} ${HDF5_LIB_TARGET}) +set_target_properties (h5diff PROPERTIES FOLDER tools) +set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};h5diff") + +set (H5_DEP_EXECUTABLES h5diff) + +if (H5_HAVE_PARALLEL) + add_executable (ph5diff + ${HDF5_TOOLS_SRC_H5DIFF_SOURCE_DIR}/h5diff_common.c + ${HDF5_TOOLS_SRC_H5DIFF_SOURCE_DIR}/ph5diff_main.c + ) + TARGET_NAMING (ph5diff STATIC) + TARGET_C_PROPERTIES (ph5diff STATIC " " " ") + target_link_libraries (ph5diff ${HDF5_TOOLS_LIB_TARGET} ${HDF5_LIB_TARGET}) + set_target_properties (ph5diff PROPERTIES FOLDER tools) + set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};ph5diff") +endif (H5_HAVE_PARALLEL) + +############################################################################## +############################################################################## +### I N S T A L L A T I O N ### +############################################################################## +############################################################################## + +#----------------------------------------------------------------------------- +# Rules for Installation of tools using make Install target +#----------------------------------------------------------------------------- + +#INSTALL_PROGRAM_PDB (h5diff ${HDF5_INSTALL_BIN_DIR} toolsapplications) + +install ( + TARGETS + h5diff + EXPORT + ${HDF5_EXPORTED_TARGETS} + RUNTIME DESTINATION ${HDF5_INSTALL_BIN_DIR} COMPONENT toolsapplications +) + +if (H5_HAVE_PARALLEL) + + #INSTALL_PROGRAM_PDB (ph5diff ${HDF5_INSTALL_BIN_DIR} toolsapplications) + + install ( + TARGETS + ph5diff + EXPORT + ${HDF5_EXPORTED_TARGETS} + RUNTIME DESTINATION ${HDF5_INSTALL_BIN_DIR} COMPONENT toolsapplications + ) +endif (H5_HAVE_PARALLEL) diff --git a/tools/src/h5diff/Makefile.am b/tools/src/h5diff/Makefile.am new file mode 100644 index 0000000..a5af3f2 --- /dev/null +++ b/tools/src/h5diff/Makefile.am @@ -0,0 +1,46 @@ +# +# Copyright by The HDF Group. +# Copyright by the Board of Trustees of the University of Illinois. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the files COPYING and Copyright.html. COPYING can be found at the root +# of the source code distribution tree; Copyright.html can be found at the +# root level of an installed copy of the electronic HDF5 document set and +# is linked from the top-level documents page. It can also be found at +# http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have +# access to either file, you may request a copy from help@hdfgroup.org. +## +## Makefile.am +## Run automake to generate a Makefile.in from this file. +# +# HDF5 Library Makefile(.in) +# + +include $(top_srcdir)/config/commence.am + +# Include src and tools/lib directories +AM_CPPFLAGS+=-I$(top_srcdir)/src -I$(top_srcdir)/tools/lib + +# Always build and test h5diff but build and test ph5diff only if parallel +# is enabled. +if BUILD_PARALLEL_CONDITIONAL + H5PDIFF=ph5diff +endif + +# Our main target, h5diff +bin_PROGRAMS=h5diff $(H5PDIFF) + +# Add h5diff specific linker flags here +h5diff_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) + +# Source files for the program +h5diff_SOURCES=h5diff_main.c h5diff_common.c +ph5diff_SOURCES=ph5diff_main.c h5diff_common.c + +# Programs depend on the main HDF5 library and tools library +LDADD=$(LIBH5TOOLS) $(LIBHDF5) + +include $(top_srcdir)/config/conclude.am + diff --git a/tools/src/h5diff/h5diff_common.c b/tools/src/h5diff/h5diff_common.c new file mode 100644 index 0000000..2453ffc --- /dev/null +++ b/tools/src/h5diff/h5diff_common.c @@ -0,0 +1,607 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include <stdlib.h> +#include <string.h> +#include "H5private.h" +#include "h5diff.h" +#include "h5diff_common.h" +#include "h5tools.h" +#include "h5tools_utils.h" + +static int check_n_input( const char* ); +static int check_p_input( const char* ); +static int check_d_input( const char* ); + +/* + * Command-line options: The user can specify short or long-named + * parameters. + */ +static const char *s_opts = "hVrv:qn:d:p:Nc"; +static struct long_options l_opts[] = { + { "help", no_arg, 'h' }, + { "version", no_arg, 'V' }, + { "report", no_arg, 'r' }, + { "verbose", optional_arg, 'v' }, + { "quiet", no_arg, 'q' }, + { "count", require_arg, 'n' }, + { "delta", require_arg, 'd' }, + { "relative", require_arg, 'p' }, + { "nan", no_arg, 'N' }, + { "compare", no_arg, 'c' }, + { "use-system-epsilon", no_arg, 'e' }, + { "follow-symlinks", no_arg, 'l' }, + { "no-dangling-links", no_arg, 'x' }, + { "exclude-path", require_arg, 'E' }, + { NULL, 0, '\0' } +}; + +/*------------------------------------------------------------------------- + * Function: check_options + * + * Purpose: parse command line input + * + *------------------------------------------------------------------------- + */ +static void check_options(diff_opt_t* options) +{ + /*-------------------------------------------------------------- + * check for mutually exclusive options + *--------------------------------------------------------------*/ + + /* check between -d , -p, --use-system-epsilon. + * These options are mutually exclusive. + */ + if ((options->d + options->p + options->use_system_epsilon) > 1) + { + printf("%s error: -d, -p and --use-system-epsilon options are mutually-exclusive;\n", PROGRAMNAME); + printf("use no more than one.\n"); + printf("Try '-h' or '--help' option for more information or see the %s entry in the 'HDF5 Reference Manual'.\n", PROGRAMNAME); + h5diff_exit(EXIT_FAILURE); + } +} + + +/*------------------------------------------------------------------------- + * Function: parse_command_line + * + * Purpose: parse command line input + * + *------------------------------------------------------------------------- + */ + +void parse_command_line(int argc, + const char* argv[], + const char** fname1, + const char** fname2, + const char** objname1, + const char** objname2, + diff_opt_t* options) +{ + int i; + int opt; + struct exclude_path_list *exclude_head, *exclude_prev, *exclude_node; + + /* process the command-line */ + memset(options, 0, sizeof (diff_opt_t)); + + /* assume equal contents initially */ + options->contents = 1; + + /* NaNs are handled by default */ + options->do_nans = 1; + + /* not Listing objects that are not comparable */ + options->m_list_not_cmp = 0; + + /* initially no not-comparable. */ + /**this is bad in mixing option with results**/ + options->not_cmp=0; + + /* init for exclude-path option */ + exclude_head = NULL; + + /* parse command line options */ + while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) + { + switch ((char)opt) + { + default: + usage(); + h5diff_exit(EXIT_FAILURE); + case 'h': + usage(); + h5diff_exit(EXIT_SUCCESS); + case 'V': + print_version(h5tools_getprogname()); + h5diff_exit(EXIT_SUCCESS); + case 'v': + options->m_verbose = 1; + /* This for loop is for handling style like + * -v, -v1, --verbose, --verbose=1. + */ + for (i = 1; i < argc; i++) + { + /* + * short opt + */ + if (!strcmp (argv[i], "-v")) /* no arg */ + { + opt_ind--; + options->m_verbose_level = 0; + break; + } + else if (!strncmp (argv[i], "-v", (size_t)2)) + { + options->m_verbose_level = atoi(&argv[i][2]); + break; + } + + /* + * long opt + */ + if (!strcmp (argv[i], "--verbose")) /* no arg */ + { + options->m_verbose_level = 0; + break; + } + else if ( !strncmp (argv[i], "--verbose", (size_t)9) && argv[i][9]=='=') + { + options->m_verbose_level = atoi(&argv[i][10]); + break; + } + } + break; + case 'q': + /* use quiet mode; supress the message "0 differences found" */ + options->m_quiet = 1; + break; + case 'r': + options->m_report = 1; + break; + case 'l': + options->follow_links = TRUE; + break; + case 'x': + options->no_dangle_links = 1; + break; + case 'E': + options->exclude_path = 1; + + /* create linked list of excluding objects */ + if( (exclude_node = (struct exclude_path_list*) HDmalloc(sizeof(struct exclude_path_list))) == NULL) + { + printf("Error: lack of memory!\n"); + h5diff_exit(EXIT_FAILURE); + } + + /* init */ + exclude_node->obj_path = (char*)opt_arg; + exclude_node->obj_type = H5TRAV_TYPE_UNKNOWN; + exclude_prev = exclude_head; + + if (NULL == exclude_head) + { + exclude_head = exclude_node; + exclude_head->next = NULL; + } + else + { + while(NULL != exclude_prev->next) + exclude_prev=exclude_prev->next; + + exclude_node->next = NULL; + exclude_prev->next = exclude_node; + } + break; + case 'd': + options->d=1; + + if ( check_d_input( opt_arg )==-1) + { + printf("<-d %s> is not a valid option\n", opt_arg ); + usage(); + h5diff_exit(EXIT_FAILURE); + } + options->delta = atof( opt_arg ); + + /* -d 0 is the same as default */ + if (H5_DBL_ABS_EQUAL(options->delta, (double)0.0F)) + options->d=0; + + break; + + case 'p': + + options->p=1; + if ( check_p_input( opt_arg )==-1) + { + printf("<-p %s> is not a valid option\n", opt_arg ); + usage(); + h5diff_exit(EXIT_FAILURE); + } + options->percent = atof( opt_arg ); + + /* -p 0 is the same as default */ + if (H5_DBL_ABS_EQUAL(options->percent, (double)0.0F)) + options->p = 0; + + break; + + case 'n': + + options->n=1; + if ( check_n_input( opt_arg )==-1) + { + printf("<-n %s> is not a valid option\n", opt_arg ); + usage(); + h5diff_exit(EXIT_FAILURE); + } + options->count = HDstrtoull(opt_arg, NULL, 0); + break; + + case 'N': + options->do_nans = 0; + break; + + case 'c': + options->m_list_not_cmp = 1; + break; + + case 'e': + options->use_system_epsilon = 1; + break; + } + } + + /* check options */ + check_options(options); + + /* if exclude-path option is used, keep the exclude path list */ + if (options->exclude_path) + options->exclude = exclude_head; + + /* check for file names to be processed */ + if (argc <= opt_ind || argv[ opt_ind + 1 ] == NULL) + { + error_msg("missing file names\n"); + usage(); + h5diff_exit(EXIT_FAILURE); + } + + *fname1 = argv[ opt_ind ]; + *fname2 = argv[ opt_ind + 1 ]; + *objname1 = argv[ opt_ind + 2 ]; + + if ( *objname1 == NULL ) + { + *objname2 = NULL; + return; + } + + if ( argv[ opt_ind + 3 ] != NULL) + { + *objname2 = argv[ opt_ind + 3 ]; + } + else + { + *objname2 = *objname1; + } + + +} + + +/*------------------------------------------------------------------------- + * Function: print_info + * + * Purpose: print several information messages after h5diff call + * + *------------------------------------------------------------------------- + */ + + void print_info(diff_opt_t* options) + { + if (options->m_quiet || options->err_stat ) + return; + + if (options->cmn_objs==0) + { + printf("No common objects found. Files are not comparable.\n"); + if (!options->m_verbose) + printf("Use -v for a list of objects.\n"); + } + + if (options->not_cmp==1) + { + if ( options->m_list_not_cmp == 0 ) + { + printf("--------------------------------\n"); + printf("Some objects are not comparable\n"); + printf("--------------------------------\n"); + if (options->m_verbose) + printf("Use -c for a list of objects without details of differences.\n"); + else + printf("Use -c for a list of objects.\n"); + } + + + } + + } + +/*------------------------------------------------------------------------- + * Function: check_n_input + * + * Purpose: check for valid input + * + * Return: 1 for ok, -1 for fail + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: May 9, 2003 + * + * Comments: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5_ATTR_PURE static int +check_n_input( const char *str ) +{ + unsigned i; + char c; + + for ( i = 0; i < strlen(str); i++) + { + c = str[i]; + if ( i==0 ) + { + if ( c < 49 || c > 57 ) /* ascii values between 1 and 9 */ + return -1; + } + else + if ( c < 48 || c > 57 ) /* 0 also */ + return -1; + } + return 1; +} + +/*------------------------------------------------------------------------- + * Function: check_p_input + * + * Purpose: check for a valid p option input + * + * Return: 1 for ok, -1 for fail + * + * Date: May 9, 2003 + * + * Comments: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +check_p_input( const char *str ) +{ + double x; + + /* + the atof return value on a hexadecimal input is different + on some systems; we do a character check for this + */ + if (strlen(str)>2 && str[0]=='0' && str[1]=='x') + return -1; + + x=atof(str); + if (x<0) + return -1; + + return 1; +} + +/*------------------------------------------------------------------------- + * Function: check_d_input + * + * Purpose: check for a valid d option input + * + * Return: 1 for ok, -1 for fail + * + * Date: November 11, 2007 + * + * Comments: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +check_d_input( const char *str ) +{ + double x; + + /* + the atof return value on a hexadecimal input is different + on some systems; we do a character check for this + */ + if (strlen(str)>2 && str[0]=='0' && str[1]=='x') + return -1; + + x=atof(str); + if (x <0) + return -1; + + return 1; +} + +/*------------------------------------------------------------------------- + * Function: usage + * + * Purpose: print a usage message + * + * Return: void + * + *------------------------------------------------------------------------- + */ + +void usage(void) +{ + printf("usage: h5diff [OPTIONS] file1 file2 [obj1[ obj2]] \n"); + printf(" file1 File name of the first HDF5 file\n"); + printf(" file2 File name of the second HDF5 file\n"); + printf(" [obj1] Name of an HDF5 object, in absolute path\n"); + printf(" [obj2] Name of an HDF5 object, in absolute path\n"); + printf("\n"); + printf(" OPTIONS\n"); + printf(" -h, --help\n"); + printf(" Print a usage message and exit.\n"); + printf(" -V, --version\n"); + printf(" Print version number and exit.\n"); + printf(" -r, --report\n"); + printf(" Report mode. Print differences.\n"); + printf(" -v --verbose\n"); + printf(" Verbose mode. Print differences information and list of objects.\n"); + printf(" -vN --verbose=N\n"); + printf(" Verbose mode with level. Print differences and list of objects.\n"); + printf(" Level of detail depends on value of N:\n"); + printf(" 0 : Identical to '-v' or '--verbose'.\n"); + printf(" 1 : All level 0 information plus one-line attribute\n"); + printf(" status summary.\n"); + printf(" 2 : All level 1 information plus extended attribute\n"); + printf(" status report.\n"); + printf(" -q, --quiet\n"); + printf(" Quiet mode. Do not produce output.\n"); + printf(" --follow-symlinks\n"); + printf(" Follow symbolic links (soft links and external links and compare the)\n"); + printf(" links' target objects.\n"); + printf(" If symbolic link(s) with the same name exist in the files being\n"); + printf(" compared, then determine whether the target of each link is an existing\n"); + printf(" object (dataset, group, or named datatype) or the link is a dangling\n"); + printf(" link (a soft or external link pointing to a target object that does\n"); + printf(" not yet exist).\n"); + printf(" - If both symbolic links are dangling links, they are treated as being\n"); + printf(" the same; by default, h5diff returns an exit code of 0.\n"); + printf(" If, however, --no-dangling-links is used with --follow-symlinks,\n"); + printf(" this situation is treated as an error and h5diff returns an\n"); + printf(" exit code of 2.\n"); + printf(" - If only one of the two links is a dangling link,they are treated as\n"); + printf(" being different and h5diff returns an exit code of 1.\n"); + printf(" If, however, --no-dangling-links is used with --follow-symlinks,\n"); + printf(" this situation is treated as an error and h5diff returns an\n"); + printf(" exit code of 2.\n"); + printf(" - If both symbolic links point to existing objects, h5diff compares the\n"); + printf(" two objects.\n"); + printf(" If any symbolic link specified in the call to h5diff does not exist,\n"); + printf(" h5diff treats it as an error and returns an exit code of 2.\n"); + printf(" --no-dangling-links\n"); + printf(" Must be used with --follow-symlinks option; otherwise, h5diff shows\n"); + printf(" error message and returns an exit code of 2.\n"); + printf(" Check for any symbolic links (soft links or external links) that do not\n"); + printf(" resolve to an existing object (dataset, group, or named datatype).\n"); + printf(" If any dangling link is found, this situation is treated as an error\n"); + printf(" and h5diff returns an exit code of 2.\n"); + printf(" -c, --compare\n"); + printf(" List objects that are not comparable\n"); + printf(" -N, --nan\n"); + printf(" Avoid NaNs detection\n"); + printf(" -n C, --count=C\n"); + printf(" Print differences up to C. C must be a positive integer.\n"); + printf(" -d D, --delta=D\n"); + printf(" Print difference if (|a-b| > D). D must be a positive number.\n"); + printf(" Can not use with '-p' or '--use-system-epsilon'.\n"); + printf(" -p R, --relative=R\n"); + printf(" Print difference if (|(a-b)/b| > R). R must be a positive number.\n"); + printf(" Can not use with '-d' or '--use-system-epsilon'.\n"); + printf(" --use-system-epsilon\n"); + printf(" Print difference if (|a-b| > EPSILON), EPSILON is system defined value.\n"); + printf(" If the system epsilon is not defined,one of the following predefined\n"); + printf(" values will be used:\n"); + printf(" FLT_EPSILON = 1.19209E-07 for floating-point type\n"); + printf(" DBL_EPSILON = 2.22045E-16 for double precision type\n"); + printf(" Can not use with '-p' or '-d'.\n"); + printf(" --exclude-path \"path\" \n"); + printf(" Exclude the specified path to an object when comparing files or groups.\n"); + printf(" If a group is excluded, all member objects will also be excluded.\n"); + printf(" The specified path is excluded wherever it occurs.\n"); + printf(" This flexibility enables the same option to exclude either objects that\n"); + printf(" exist only in one file or common objects that are known to differ.\n"); + printf("\n"); + printf(" When comparing files, \"path\" is the absolute path to the excluded;\n"); + printf(" object; when comparing groups, \"path\" is similar to the relative\n"); + printf(" path from the group to the excluded object. This \"path\" can be\n"); + printf(" taken from the first section of the output of the --verbose option.\n"); + printf(" For example, if you are comparing the group /groupA in two files and\n"); + printf(" you want to exclude /groupA/groupB/groupC in both files, the exclude\n"); + printf(" option would read as follows:\n"); + printf(" --exclude-path \"/groupB/groupC\"\n"); + printf("\n"); + printf(" If there are multiple paths to an object, only the specified path(s)\n"); + printf(" will be excluded; the comparison will include any path not explicitly\n"); + printf(" excluded.\n"); + printf(" This option can be used repeatedly to exclude multiple paths.\n"); + printf("\n"); + + printf(" Modes of output:\n"); + printf(" Default mode: print the number of differences found and where they occured\n"); + printf(" -r Report mode: print the above plus the differences\n"); + printf(" -v Verbose mode: print the above plus a list of objects and warnings\n"); + printf(" -q Quiet mode: do not print output\n"); + + printf("\n"); + + printf(" File comparison:\n"); + printf(" If no objects [obj1[ obj2]] are specified, the h5diff comparison proceeds as\n"); + printf(" a comparison of the two files' root groups. That is, h5diff first compares\n"); + printf(" the names of root group members, generates a report of root group objects\n"); + printf(" that appear in only one file or in both files, and recursively compares\n"); + printf(" common objects.\n"); + printf("\n"); + + printf(" Object comparison:\n"); + printf(" 1) Groups \n"); + printf(" First compares the names of member objects (relative path, from the\n"); + printf(" specified group) and generates a report of objects that appear in only\n"); + printf(" one group or in both groups. Common objects are then compared recursively.\n"); + printf(" 2) Datasets \n"); + printf(" Array rank and dimensions, datatypes, and data values are compared.\n"); + printf(" 3) Datatypes \n"); + printf(" The comparison is based on the return value of H5Tequal.\n"); + printf(" 4) Symbolic links \n"); + printf(" The paths to the target objects are compared.\n"); + printf(" (The option --follow-symlinks overrides the default behavior when\n"); + printf(" symbolic links are compared.).\n"); + printf("\n"); + + printf(" Exit code:\n"); + printf(" 0 if no differences, 1 if differences found, 2 if error\n"); + printf("\n"); + printf(" Examples of use:\n"); + printf(" 1) h5diff file1 file2 /g1/dset1 /g1/dset2\n"); + printf(" Compares object '/g1/dset1' in file1 with '/g1/dset2' in file2\n"); + printf("\n"); + printf(" 2) h5diff file1 file2 /g1/dset1\n"); + printf(" Compares object '/g1/dset1' in both files\n"); + printf("\n"); + printf(" 3) h5diff file1 file2\n"); + printf(" Compares all objects in both files\n"); + printf("\n"); + printf(" Notes:\n"); + printf(" file1 and file2 can be the same file.\n"); + printf(" Use h5diff file1 file1 /g1/dset1 /g1/dset2 to compare\n"); + printf(" '/g1/dset1' and '/g1/dset2' in the same file\n"); + printf("\n"); +} diff --git a/tools/src/h5diff/h5diff_common.h b/tools/src/h5diff/h5diff_common.h new file mode 100644 index 0000000..5b1317f --- /dev/null +++ b/tools/src/h5diff/h5diff_common.h @@ -0,0 +1,36 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef H5DIFFCOMMON_H__ +#define H5DIFFCOMMON_H__ + +#include "h5tools.h" +/* Name of tool */ +#define PROGRAMNAME "h5diff" + +#ifdef __cplusplus +extern "C" { +#endif + +void usage(void); +void parse_command_line(int argc, const char* argv[], const char** fname1, const char** fname2, const char** objname1, const char** objname2, diff_opt_t* options); +void h5diff_exit(int status); +void print_info(diff_opt_t* options); + +#ifdef __cplusplus +} +#endif + +#endif /* H5DIFFCOMMON_H__ */ diff --git a/tools/src/h5diff/h5diff_main.c b/tools/src/h5diff/h5diff_main.c new file mode 100644 index 0000000..cdaca29 --- /dev/null +++ b/tools/src/h5diff/h5diff_main.c @@ -0,0 +1,145 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include <stdlib.h> +#include <assert.h> +#include <memory.h> +#include "H5private.h" +#include "h5diff.h" +#include "h5diff_common.h" +#include "h5tools.h" +#include "h5tools_utils.h" + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: h5diff main program + * + * Return: An exit status of 0 means no differences were found, 1 means some + * differences were found. + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: May 9, 2003 + * + * Comments: + * + * Modifications: July 2004 + * Introduced the four modes: + * Normal mode: print the number of differences found and where they occured + * Report mode: print the above plus the differences + * Verbose mode: print the above plus a list of objects and warnings + * Quiet mode: do not print output + * + * November 2004: Leon Arber (larber@uiuc.edu) + * Additions that allow h5diff to be run in parallel + * + * February 2005: Leon Arber (larber@uiuc.edu) + * h5diff and ph5diff split into two files, one that is used + * to build a serial h5diff and one used to build a parallel h5diff + * Common functions have been moved to h5diff_common.c + * + * October 2005 + * Introduced a new field 'not_cmp' to 'diff_opt_t' that detects + * if some objects are not comparable and prints the message + * "Some objects are not comparable" + * + * February 2007 + * Added comparison for dataset regions. + * Added support for reading and comparing by hyperslabs for large files. + * Inclusion of a relative error formula to compare floating + * point numbers in order to deal with floating point uncertainty. + * Printing of dataset dimensions along with dataset name + * + * November 19, 2007 + * adopted the syntax h5diff [OPTIONS] file1 file2 [obj1[obj2]] + * + *------------------------------------------------------------------------- + */ + + +int main(int argc, const char *argv[]) +{ + int ret; + const char *fname1 = NULL; + const char *fname2 = NULL; + const char *objname1 = NULL; + const char *objname2 = NULL; + hsize_t nfound=0; + diff_opt_t options; + + h5tools_setprogname(PROGRAMNAME); + h5tools_setstatus(EXIT_SUCCESS); + + /* Initialize h5tools lib */ + h5tools_init(); + + /*------------------------------------------------------------------------- + * process the command-line + *------------------------------------------------------------------------- + */ + parse_command_line(argc, argv, &fname1, &fname2, &objname1, &objname2, &options); + + /*------------------------------------------------------------------------- + * do the diff + *------------------------------------------------------------------------- + */ + + nfound = h5diff(fname1,fname2,objname1,objname2,&options); + + print_info(&options); + + /*------------------------------------------------------------------------- + * exit code + * 1 if differences, 0 if no differences, 2 if error + *------------------------------------------------------------------------- + */ + + ret = (nfound == 0 ? 0 : 1 ); + + /* if graph difference return 1 for differences */ + if ( options.contents == 0 ) + ret = 1; + + /* and return 2 for error */ + if (options.err_stat) + ret = 2; + + return ret; +} + +/*------------------------------------------------------------------------- + * Function: h5diff_exit + * + * Purpose: dismiss phdiff worker processes and exit + * + * Return: none + * + * Programmer: Albert Cheng + * Date: Feb 6, 2005 + * + * Comments: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5_ATTR_NORETURN void +h5diff_exit(int status) +{ + HDexit(status); +} + diff --git a/tools/src/h5diff/ph5diff_main.c b/tools/src/h5diff/ph5diff_main.c new file mode 100644 index 0000000..a26b6e9 --- /dev/null +++ b/tools/src/h5diff/ph5diff_main.c @@ -0,0 +1,329 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include "H5private.h" +#include "h5diff.h" +#include "ph5diff.h" +#include "h5diff_common.h" +#include "h5tools.h" +#include "h5tools_utils.h" + +/* Name of tool */ +#define PROGRAMNAME "h5diff" + +static void ph5diff_worker(int ); + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: ph5diff main program + * + * Return: An exit status of 0 means no differences were found, 1 means some + * differences were found. + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: May 9, 2003 + * + * Comments: + * + * This function drives the diff process and will do a serial or parallel diff depending + * on the value of the global variable g_Parallel (default is 0), set to 1 when the program + * is run as "ph5diff" + *------------------------------------------------------------------------- + */ + +int main(int argc, const char *argv[]) +{ + int nID = 0; + const char *fname1 = NULL; + const char *fname2 = NULL; + const char *objname1 = NULL; + const char *objname2 = NULL; + diff_opt_t options; + + h5tools_setprogname(PROGRAMNAME); + h5tools_setstatus(EXIT_SUCCESS); + + /* Initialize h5tools lib */ + h5tools_init(); + + outBuffOffset = 0; + g_Parallel = 1; + + MPI_Init(&argc, (char***) &argv); + + MPI_Comm_rank(MPI_COMM_WORLD, &nID); + MPI_Comm_size(MPI_COMM_WORLD, &g_nTasks); + + if(g_nTasks == 1) + { + printf("Only 1 task available...doing serial diff\n"); + + g_Parallel = 0; + + parse_command_line(argc, argv, &fname1, &fname2, &objname1, &objname2, &options); + + h5diff(fname1, fname2, objname1, objname2, &options); + + print_info(&options); + } + /* Parallel h5diff */ + else { + + /* Have the manager process the command-line */ + if(nID == 0) + { + parse_command_line(argc, argv, &fname1, &fname2, &objname1, &objname2, &options); + + h5diff(fname1, fname2, objname1, objname2, &options); + + MPI_Barrier(MPI_COMM_WORLD); + + print_info(&options); + print_manager_output(); + } + /* All other tasks become workers and wait for assignments. */ + else { + ph5diff_worker(nID); + + MPI_Barrier(MPI_COMM_WORLD); + } /* end else */ + + } /* end else */ + + MPI_Finalize(); + + return 0; +} + +/*------------------------------------------------------------------------- + * Function: ph5diff_worker + * + * Purpose: worker process of ph5diff + * + * Return: none + * + * Programmer: Leon Arber + * Date: January 2005 + * + * Comments: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +ph5diff_worker(int nID) +{ + hid_t file1_id = -1, file2_id = -1; + + while(1) + { + MPI_Status Status; + + MPI_Probe(0, MPI_ANY_TAG, MPI_COMM_WORLD, &Status); + + /* Check for filenames */ + if(Status.MPI_TAG == MPI_TAG_PARALLEL) + { + char filenames[2][MAX_FILENAME]; + + /* Retrieve filenames */ + MPI_Recv(filenames, MAX_FILENAME*2, MPI_CHAR, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &Status); + + /* disable error reporting */ + H5E_BEGIN_TRY + { + /* Open the files */ + if ((file1_id = H5Fopen (filenames[0], H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + { + printf ("h5diff Task [%d]: <%s>: unable to open file\n", nID, filenames[0]); + MPI_Abort(MPI_COMM_WORLD, 0); + } + if ((file2_id = H5Fopen (filenames[1], H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) + { + printf ("h5diff Task [%d]: <%s>: unable to open file\n", nID, filenames[1]); + MPI_Abort(MPI_COMM_WORLD, 0); + } + /* enable error reporting */ + } + H5E_END_TRY; + } + /* Check for work */ + else if(Status.MPI_TAG == MPI_TAG_ARGS) + { + struct diff_mpi_args args; + struct diffs_found diffs; + int i; + + /* Make certain we've received the filenames and opened the files already */ + if(file1_id < 0 || file2_id < 0) + { + printf("ph5diff_worker: ERROR: work received before/without filenames\n"); + break; + } + + /* Recv parameters for diff from manager task */ + MPI_Recv(&args, sizeof(args), MPI_BYTE, 0, MPI_TAG_ARGS, MPI_COMM_WORLD, &Status); + + /* Do the diff */ + diffs.nfound = diff(file1_id, args.name1, file2_id, args.name2, &(args.options), &(args.argdata)); + diffs.not_cmp = args.options.not_cmp; + + /* If print buffer has something in it, request print token.*/ + if(outBuffOffset>0) + { + MPI_Send(NULL, 0, MPI_BYTE, 0, MPI_TAG_TOK_REQUEST, MPI_COMM_WORLD); + + /* Wait for print token. */ + MPI_Recv(NULL, 0, MPI_BYTE, 0, MPI_TAG_PRINT_TOK, MPI_COMM_WORLD, &Status); + + /* When get token, send all of our output to the manager task and then return the token */ + for(i=0; i<outBuffOffset; i+=PRINT_DATA_MAX_SIZE) + MPI_Send(outBuff+i, PRINT_DATA_MAX_SIZE, MPI_BYTE, 0, MPI_TAG_PRINT_DATA, MPI_COMM_WORLD); + + /* An overflow file exists, so we send it's output to the manager too and then delete it */ + if(overflow_file) + { + char out_data[PRINT_DATA_MAX_SIZE]; + int tmp; + + memset(out_data, 0, PRINT_DATA_MAX_SIZE); + i=0; + + rewind(overflow_file); + while((tmp = getc(overflow_file)) >= 0) + { + *(out_data + i++) = (char)tmp; + if(i==PRINT_DATA_MAX_SIZE) + { + MPI_Send(out_data, PRINT_DATA_MAX_SIZE, MPI_BYTE, 0, MPI_TAG_PRINT_DATA, MPI_COMM_WORLD); + i=0; + memset(out_data, 0, PRINT_DATA_MAX_SIZE); + } + } + + if(i>0) + MPI_Send(out_data, PRINT_DATA_MAX_SIZE, MPI_BYTE, 0, MPI_TAG_PRINT_DATA, MPI_COMM_WORLD); + + fclose(overflow_file); + overflow_file = NULL; + } + + fflush(stdout); + memset(outBuff, 0, OUTBUFF_SIZE); + outBuffOffset = 0; + + MPI_Send(&diffs, sizeof(diffs), MPI_BYTE, 0, MPI_TAG_TOK_RETURN, MPI_COMM_WORLD); + } + else + MPI_Send(&diffs, sizeof(diffs), MPI_BYTE, 0, MPI_TAG_DONE, MPI_COMM_WORLD); + } + /* Check for leaving */ + else if(Status.MPI_TAG == MPI_TAG_END) + { + MPI_Recv(NULL, 0, MPI_BYTE, 0, MPI_TAG_END, MPI_COMM_WORLD, &Status); + break; + } + else + { + printf("ph5diff_worker: ERROR: invalid tag (%d) received\n", Status.MPI_TAG); + break; + } + + } + + return; +} + +/*------------------------------------------------------------------------- + * Function: print_manager_output + * + * Purpose: special function that prints any output accumulated by the + * manager task. + * + * Return: none + * + * Programmer: Leon Arber + * + * Date: Feb 7, 2005 + * + *------------------------------------------------------------------------- + */ +void print_manager_output(void) +{ + /* If there was something we buffered, let's print it now */ + if( (outBuffOffset>0) && g_Parallel) + { + printf("%s", outBuff); + + if(overflow_file) + { + int tmp; + rewind(overflow_file); + while((tmp = getc(overflow_file)) >= 0) + putchar(tmp); + fclose(overflow_file); + overflow_file = NULL; + } + + HDfflush(stdout); + HDmemset(outBuff, 0, OUTBUFF_SIZE); + outBuffOffset = 0; + } + else if( (outBuffOffset>0) && !g_Parallel) + { + HDfprintf(stderr, "h5diff error: outBuffOffset>0, but we're not in parallel!\n"); + } +} + +/*------------------------------------------------------------------------- + * Function: h5diff_exit + * + * Purpose: dismiss phdiff worker processes and exit + * + * Return: none + * + * Programmer: Albert Cheng + * Date: Feb 6, 2005 + * + * Comments: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void h5diff_exit(int status) +{ + /* if in parallel mode, dismiss workers, close down MPI, then exit */ + if(g_Parallel) { + if(g_nTasks > 1) { + phdiff_dismiss_workers(); + MPI_Barrier(MPI_COMM_WORLD); + } + MPI_Finalize(); + status = EXIT_SUCCESS; /* Reset exit status, since some mpiexec commands generate output on failure status */ + } + + /* Always exit(0), since MPI implementations do weird stuff when they + * receive a non-zero exit value. - QAK + */ + exit(0); +} + diff --git a/tools/src/h5dump/CMakeLists.txt b/tools/src/h5dump/CMakeLists.txt new file mode 100644 index 0000000..ab310db --- /dev/null +++ b/tools/src/h5dump/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required (VERSION 3.1.0) +PROJECT (HDF5_TOOLS_SRC_H5DUMP) + +#----------------------------------------------------------------------------- +# Setup include Directories +#----------------------------------------------------------------------------- +INCLUDE_DIRECTORIES (${HDF5_TOOLS_DIR}/lib) + +# -------------------------------------------------------------------- +# Add the h5dump executables +# -------------------------------------------------------------------- +add_executable (h5dump + ${HDF5_TOOLS_SRC_H5DUMP_SOURCE_DIR}/h5dump.c + ${HDF5_TOOLS_SRC_H5DUMP_SOURCE_DIR}/h5dump_ddl.c + ${HDF5_TOOLS_SRC_H5DUMP_SOURCE_DIR}/h5dump_xml.c +) +TARGET_NAMING (h5dump STATIC) +TARGET_C_PROPERTIES (h5dump STATIC " " " ") +target_link_libraries (h5dump ${HDF5_TOOLS_LIB_TARGET} ${HDF5_LIB_TARGET}) +set_target_properties (h5dump PROPERTIES FOLDER tools) +set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};h5dump") + +set (H5_DEP_EXECUTABLES h5dump) + +############################################################################## +############################################################################## +### I N S T A L L A T I O N ### +############################################################################## +############################################################################## + +#----------------------------------------------------------------------------- +# Rules for Installation of tools using make Install target +#----------------------------------------------------------------------------- + +#INSTALL_PROGRAM_PDB (h5dump ${HDF5_INSTALL_BIN_DIR} toolsapplications) + +install ( + TARGETS + h5dump + EXPORT + ${HDF5_EXPORTED_TARGETS} + RUNTIME DESTINATION ${HDF5_INSTALL_BIN_DIR} COMPONENT toolsapplications +) diff --git a/tools/src/h5dump/Makefile.am b/tools/src/h5dump/Makefile.am new file mode 100644 index 0000000..dc43065 --- /dev/null +++ b/tools/src/h5dump/Makefile.am @@ -0,0 +1,38 @@ +# +# Copyright by The HDF Group. +# Copyright by the Board of Trustees of the University of Illinois. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the files COPYING and Copyright.html. COPYING can be found at the root +# of the source code distribution tree; Copyright.html can be found at the +# root level of an installed copy of the electronic HDF5 document set and +# is linked from the top-level documents page. It can also be found at +# http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have +# access to either file, you may request a copy from help@hdfgroup.org. +## +## Makefile.am +## Run automake to generate a Makefile.in from this file. +# +# HDF5 Library Makefile(.in) +# + +include $(top_srcdir)/config/commence.am + +# Include files in /src directory and /tools/lib directory +AM_CPPFLAGS+=-I$(top_srcdir)/src -I$(top_srcdir)/tools/lib + +# Our main target, the h5dump tool. +bin_PROGRAMS=h5dump + +# Add h5dump specific linker flags here +h5dump_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) + +# All the programs depend on the hdf5 and h5tools libraries +LDADD=$(LIBH5TOOLS) $(LIBHDF5) + +# Source files for the program +h5dump_SOURCES=h5dump.c h5dump_ddl.c h5dump_xml.c + +include $(top_srcdir)/config/conclude.am diff --git a/tools/src/h5dump/h5dump.c b/tools/src/h5dump/h5dump.c new file mode 100644 index 0000000..562cfd5 --- /dev/null +++ b/tools/src/h5dump/h5dump.c @@ -0,0 +1,1802 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#include <stdio.h> +#include <stdlib.h> + +#include "h5dump.h" +#include "h5dump_ddl.h" +#include "h5dump_xml.h" + +/* Name of tool */ +#define PROGRAMNAME "h5dump" + +static const char *driver = NULL; /* The driver to open the file with. */ +const char *outfname=NULL; +static int doxml = 0; +static int useschema = 1; +static const char *xml_dtd_uri = NULL; + +/* module-scoped variables for XML option */ +#define DEFAULT_XSD "http://www.hdfgroup.org/HDF5/XML/schema/HDF5-File.xsd" +#define DEFAULT_DTD "http://www.hdfgroup.org/HDF5/XML/DTD/HDF5-File.dtd" + +/* Standard DDL output */ +static const dump_functions ddl_function_table = { + dump_group, + dump_named_datatype, + dump_dataset, + dump_dataspace, + dump_datatype, + dump_attr_cb, + dump_data +}; + +/* XML output */ +static const dump_functions xml_function_table = { + xml_dump_group, + xml_dump_named_datatype, + xml_dump_dataset, + xml_dump_dataspace, + xml_dump_datatype, + xml_dump_attr, + xml_dump_data +}; + +/* internal functions */ +static void init_prefix(char **prfx, size_t prfx_len); + +/* a structure for handling the order command-line parameters come in */ +struct handler_t { + void (*func)(hid_t, const char *, void *, int, const char *); + char *obj; + struct subset_t *subset_info; +}; + +/* + * Command-line options: The user can specify short or long-named + * parameters. The long-named ones can be partially spelled. When + * adding more, make sure that they don't clash with each other. + */ +/* The following initialization makes use of C language cancatenating */ +/* "xxx" "yyy" into "xxxyyy". */ +static const char *s_opts = "hn*peyBHirVa:c:d:f:g:k:l:t:w:xD:uX:o*b*F:s:S:A*q:z:m:RECM:O*N:vG:"; +static struct long_options l_opts[] = { + { "help", no_arg, 'h' }, + { "hel", no_arg, 'h' }, + { "contents", optional_arg, 'n' }, + { "properties", no_arg, 'p' }, + { "superblock", no_arg, 'B' }, + { "boot-block", no_arg, 'B' }, + { "boot-bloc", no_arg, 'B' }, + { "boot-blo", no_arg, 'B' }, + { "boot-bl", no_arg, 'B' }, + { "boot-b", no_arg, 'B' }, + { "boot", no_arg, 'B' }, + { "boo", no_arg, 'B' }, + { "bo", no_arg, 'B' }, + { "header", no_arg, 'H' }, + { "heade", no_arg, 'H' }, + { "head", no_arg, 'H' }, + { "hea", no_arg, 'H' }, + { "object-ids", no_arg, 'i' }, + { "object-id", no_arg, 'i' }, + { "object-i", no_arg, 'i' }, + { "object", no_arg, 'i' }, + { "objec", no_arg, 'i' }, + { "obje", no_arg, 'i' }, + { "obj", no_arg, 'i' }, + { "ob", no_arg, 'i' }, + { "version", no_arg, 'V' }, + { "versio", no_arg, 'V' }, + { "versi", no_arg, 'V' }, + { "vers", no_arg, 'V' }, + { "ver", no_arg, 'V' }, + { "ve", no_arg, 'V' }, + { "attribute", require_arg, 'a' }, + { "attribut", require_arg, 'a' }, + { "attribu", require_arg, 'a' }, + { "attrib", require_arg, 'a' }, + { "attri", require_arg, 'a' }, + { "attr", require_arg, 'a' }, + { "att", require_arg, 'a' }, + { "at", require_arg, 'a' }, + { "block", require_arg, 'k' }, + { "bloc", require_arg, 'k' }, + { "blo", require_arg, 'k' }, + { "bl", require_arg, 'k' }, + { "count", require_arg, 'c' }, + { "coun", require_arg, 'c' }, + { "cou", require_arg, 'c' }, + { "co", require_arg, 'c' }, + { "dataset", require_arg, 'd' }, + { "datase", require_arg, 'd' }, + { "datas", require_arg, 'd' }, + { "datatype", require_arg, 't' }, + { "datatyp", require_arg, 't' }, + { "dataty", require_arg, 't' }, + { "datat", require_arg, 't' }, + { "filedriver", require_arg, 'f' }, + { "filedrive", require_arg, 'f' }, + { "filedriv", require_arg, 'f' }, + { "filedri", require_arg, 'f' }, + { "filedr", require_arg, 'f' }, + { "filed", require_arg, 'f' }, + { "file", require_arg, 'f' }, + { "fil", require_arg, 'f' }, + { "fi", require_arg, 'f' }, + { "group", require_arg, 'g' }, + { "grou", require_arg, 'g' }, + { "gro", require_arg, 'g' }, + { "gr", require_arg, 'g' }, + { "output", optional_arg, 'o' }, + { "outpu", optional_arg, 'o' }, + { "outp", optional_arg, 'o' }, + { "out", optional_arg, 'o' }, + { "ou", optional_arg, 'o' }, + { "soft-link", require_arg, 'l' }, + { "soft-lin", require_arg, 'l' }, + { "soft-li", require_arg, 'l' }, + { "soft-l", require_arg, 'l' }, + { "soft", require_arg, 'l' }, + { "sof", require_arg, 'l' }, + { "start", require_arg, 's' }, + { "star", require_arg, 's' }, + { "sta", require_arg, 's' }, + { "stride", require_arg, 'S' }, + { "strid", require_arg, 'S' }, + { "string", no_arg, 'r' }, + { "strin", no_arg, 'r' }, + { "use-dtd", no_arg, 'u' }, + { "use-dt", no_arg, 'u' }, + { "use-d", no_arg, 'u' }, + { "use-", no_arg, 'u' }, + { "use", no_arg, 'u' }, + { "us", no_arg, 'u' }, + { "u", no_arg, 'u' }, + { "width", require_arg, 'w' }, + { "widt", require_arg, 'w' }, + { "wid", require_arg, 'w' }, + { "wi", require_arg, 'w' }, + { "xml-dtd", require_arg, 'D' }, + { "xml-dt", require_arg, 'D' }, + { "xml-d", require_arg, 'D' }, + { "xml-ns", require_arg, 'X' }, + { "xml-n", require_arg, 'X' }, + { "xml", no_arg, 'x' }, + { "xm", no_arg, 'x' }, + { "onlyattr", optional_arg, 'A' }, + { "escape", no_arg, 'e' }, + { "noindex", no_arg, 'y' }, + { "binary", optional_arg, 'b' }, + { "form", require_arg, 'F' }, + { "sort_by", require_arg, 'q' }, + { "sort_order", require_arg, 'z' }, + { "format", require_arg, 'm' }, + { "region", no_arg, 'R' }, + { "enable-error-stack", no_arg, 'E' }, + { "packed-bits", require_arg, 'M' }, + { "no-compact-subset", no_arg, 'C' }, + { "ddl", optional_arg, 'O' }, + { "any_path", require_arg, 'N' }, + { "vds-view-first-missing", no_arg, 'v' }, + { "vds-gap-size", require_arg, 'G' }, + { NULL, 0, '\0' } +}; + + +/*------------------------------------------------------------------------- + * Function: leave + * + * Purpose: Shutdown MPI & HDF5 and call exit() + * + * Return: Does not return + * + * Programmer: Quincey Koziol + * Saturday, 31. January 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +leave(int ret) +{ + h5tools_close(); + + HDexit(ret); +} + + +/*------------------------------------------------------------------------- + * Function: usage + * + * Purpose: Print the usage message about dumper + * + * Return: void + *------------------------------------------------------------------------- + */ +static void +usage(const char *prog) +{ + FLUSHSTREAM(rawoutstream); + PRINTSTREAM(rawoutstream, "usage: %s [OPTIONS] files\n", prog); + PRINTVALSTREAM(rawoutstream, " OPTIONS\n"); + PRINTVALSTREAM(rawoutstream, " -h, --help Print a usage message and exit\n"); + PRINTVALSTREAM(rawoutstream, " -V, --version Print version number and exit\n"); + PRINTVALSTREAM(rawoutstream, "--------------- File Options ---------------\n"); + PRINTVALSTREAM(rawoutstream, " -n, --contents Print a list of the file contents and exit\n"); + PRINTVALSTREAM(rawoutstream, " Optional value 1 also prints attributes.\n"); + PRINTVALSTREAM(rawoutstream, " -B, --superblock Print the content of the super block\n"); + PRINTVALSTREAM(rawoutstream, " -H, --header Print the header only; no data is displayed\n"); + PRINTVALSTREAM(rawoutstream, " -f D, --filedriver=D Specify which driver to open the file with\n"); + PRINTVALSTREAM(rawoutstream, " -o F, --output=F Output raw data into file F\n"); + PRINTVALSTREAM(rawoutstream, " -b B, --binary=B Binary file output, of form B\n"); + PRINTVALSTREAM(rawoutstream, " -O F, --ddl=F Output ddl text into file F\n"); + PRINTVALSTREAM(rawoutstream, " Use blank(empty) filename F to suppress ddl display\n"); + PRINTVALSTREAM(rawoutstream, "--------------- Object Options ---------------\n"); + PRINTVALSTREAM(rawoutstream, " -a P, --attribute=P Print the specified attribute\n"); + PRINTVALSTREAM(rawoutstream, " If an attribute name contains a slash (/), escape the\n"); + PRINTVALSTREAM(rawoutstream, " slash with a preceding backslash (\\).\n"); + PRINTVALSTREAM(rawoutstream, " (See example section below.)\n"); + PRINTVALSTREAM(rawoutstream, " -d P, --dataset=P Print the specified dataset\n"); + PRINTVALSTREAM(rawoutstream, " -g P, --group=P Print the specified group and all members\n"); + PRINTVALSTREAM(rawoutstream, " -l P, --soft-link=P Print the value(s) of the specified soft link\n"); + PRINTVALSTREAM(rawoutstream, " -t P, --datatype=P Print the specified named datatype\n"); + PRINTVALSTREAM(rawoutstream, " -N P, --any_path=P Print any attribute, dataset, group, datatype, or link that matches P\n"); + PRINTVALSTREAM(rawoutstream, " P can be the absolute path or just a relative path.\n"); + PRINTVALSTREAM(rawoutstream, " -A, --onlyattr Print the header and value of attributes\n"); + PRINTVALSTREAM(rawoutstream, " Optional value 0 suppresses printing attributes.\n"); + PRINTVALSTREAM(rawoutstream, " --vds-view-first-missing Set the VDS bounds to first missing mapped elements.\n"); + PRINTVALSTREAM(rawoutstream, " --vds-gap-size=N Set the missing file gap size, N=non-negative integers\n"); + PRINTVALSTREAM(rawoutstream, "--------------- Object Property Options ---------------\n"); + PRINTVALSTREAM(rawoutstream, " -i, --object-ids Print the object ids\n"); + PRINTVALSTREAM(rawoutstream, " -p, --properties Print dataset filters, storage layout and fill value\n"); + PRINTVALSTREAM(rawoutstream, " -M L, --packedbits=L Print packed bits as unsigned integers, using mask\n"); + PRINTVALSTREAM(rawoutstream, " format L for an integer dataset specified with\n"); + PRINTVALSTREAM(rawoutstream, " option -d. L is a list of offset,length values,\n"); + PRINTVALSTREAM(rawoutstream, " separated by commas. Offset is the beginning bit in\n"); + PRINTVALSTREAM(rawoutstream, " the data value and length is the number of bits of\n"); + PRINTVALSTREAM(rawoutstream, " the mask.\n"); + PRINTVALSTREAM(rawoutstream, " -R, --region Print dataset pointed by region references\n"); + PRINTVALSTREAM(rawoutstream, "--------------- Formatting Options ---------------\n"); + PRINTVALSTREAM(rawoutstream, " -e, --escape Escape non printing characters\n"); + PRINTVALSTREAM(rawoutstream, " -r, --string Print 1-byte integer datasets as ASCII\n"); + PRINTVALSTREAM(rawoutstream, " -y, --noindex Do not print array indices with the data\n"); + PRINTVALSTREAM(rawoutstream, " -m T, --format=T Set the floating point output format\n"); + PRINTVALSTREAM(rawoutstream, " -q Q, --sort_by=Q Sort groups and attributes by index Q\n"); + PRINTVALSTREAM(rawoutstream, " -z Z, --sort_order=Z Sort groups and attributes by order Z\n"); + PRINTVALSTREAM(rawoutstream, " --enable-error-stack Prints messages from the HDF5 error stack as they\n"); + PRINTVALSTREAM(rawoutstream, " occur.\n"); + PRINTVALSTREAM(rawoutstream, " --no-compact-subset Disable compact form of subsetting and allow the use\n"); + PRINTVALSTREAM(rawoutstream, " of \"[\" in dataset names.\n"); + PRINTVALSTREAM(rawoutstream, " -w N, --width=N Set the number of columns of output. A value of 0 (zero)\n"); + PRINTVALSTREAM(rawoutstream, " sets the number of columns to the maximum (65535).\n"); + PRINTVALSTREAM(rawoutstream, " Default width is 80 columns.\n"); + PRINTVALSTREAM(rawoutstream, "--------------- XML Options ---------------\n"); + PRINTVALSTREAM(rawoutstream, " -x, --xml Output in XML using Schema\n"); + PRINTVALSTREAM(rawoutstream, " -u, --use-dtd Output in XML using DTD\n"); + PRINTVALSTREAM(rawoutstream, " -D U, --xml-dtd=U Use the DTD or schema at U\n"); + PRINTVALSTREAM(rawoutstream, " -X S, --xml-ns=S (XML Schema) Use qualified names n the XML\n"); + PRINTVALSTREAM(rawoutstream, " \":\": no namespace, default: \"hdf5:\"\n"); + PRINTVALSTREAM(rawoutstream, " E.g., to dump a file called `-f', use h5dump -- -f\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, "--------------- Subsetting Options ---------------\n"); + PRINTVALSTREAM(rawoutstream, " Subsetting is available by using the following options with a dataset\n"); + PRINTVALSTREAM(rawoutstream, " option. Subsetting is done by selecting a hyperslab from the data.\n"); + PRINTVALSTREAM(rawoutstream, " Thus, the options mirror those for performing a hyperslab selection.\n"); + PRINTVALSTREAM(rawoutstream, " One of the START, COUNT, STRIDE, or BLOCK parameters are mandatory if you do subsetting.\n"); + PRINTVALSTREAM(rawoutstream, " The STRIDE, COUNT, and BLOCK parameters are optional and will default to 1 in\n"); + PRINTVALSTREAM(rawoutstream, " each dimension. START is optional and will default to 0 in each dimension.\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " -s START, --start=START Offset of start of subsetting selection\n"); + PRINTVALSTREAM(rawoutstream, " -S STRIDE, --stride=STRIDE Hyperslab stride\n"); + PRINTVALSTREAM(rawoutstream, " -c COUNT, --count=COUNT Number of blocks to include in selection\n"); + PRINTVALSTREAM(rawoutstream, " -k BLOCK, --block=BLOCK Size of block in hyperslab\n"); + PRINTVALSTREAM(rawoutstream, " START, COUNT, STRIDE, and BLOCK - is a list of integers the number of which are equal to the\n"); + PRINTVALSTREAM(rawoutstream, " number of dimensions in the dataspace being queried\n"); + PRINTVALSTREAM(rawoutstream, " (Alternate compact form of subsetting is described in the Reference Manual)\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, "--------------- Option Argument Conventions ---------------\n"); + PRINTVALSTREAM(rawoutstream, " D - is the file driver to use in opening the file. Acceptable values\n"); + PRINTVALSTREAM(rawoutstream, " are \"sec2\", \"family\", \"split\", \"multi\", \"direct\", and \"stream\". Without\n"); + PRINTVALSTREAM(rawoutstream, " the file driver flag, the file will be opened with each driver in\n"); + PRINTVALSTREAM(rawoutstream, " turn and in the order specified above until one driver succeeds\n"); + PRINTVALSTREAM(rawoutstream, " in opening the file.\n"); + PRINTVALSTREAM(rawoutstream, " See examples below for family, split, and multi driver special file name usage.\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " F - is a filename.\n"); + PRINTVALSTREAM(rawoutstream, " P - is the full path from the root group to the object.\n"); + PRINTVALSTREAM(rawoutstream, " N - is an integer greater than 1.\n"); + PRINTVALSTREAM(rawoutstream, " T - is a string containing the floating point format, e.g '%%.3f'\n"); + PRINTVALSTREAM(rawoutstream, " U - is a URI reference (as defined in [IETF RFC 2396],\n"); + PRINTVALSTREAM(rawoutstream, " updated by [IETF RFC 2732])\n"); + PRINTVALSTREAM(rawoutstream, " B - is the form of binary output: NATIVE for a memory type, FILE for the\n"); + PRINTVALSTREAM(rawoutstream, " file type, LE or BE for pre-existing little or big endian types.\n"); + PRINTVALSTREAM(rawoutstream, " Must be used with -o (output file) and it is recommended that\n"); + PRINTVALSTREAM(rawoutstream, " -d (dataset) is used. B is an optional argument, defaults to NATIVE\n"); + PRINTVALSTREAM(rawoutstream, " Q - is the sort index type. It can be \"creation_order\" or \"name\" (default)\n"); + PRINTVALSTREAM(rawoutstream, " Z - is the sort order type. It can be \"descending\" or \"ascending\" (default)\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, "--------------- Examples ---------------\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 1) Attribute foo of the group /bar_none in file quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -a /bar_none/foo quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " Attribute \"high/low\" of the group /bar_none in the file quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -a \"/bar_none/high\\/low\" quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 2) Selecting a subset from dataset /foo in file quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -d /foo -s \"0,1\" -S \"1,1\" -c \"2,3\" -k \"2,2\" quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 3) Saving dataset 'dset' in file quux.h5 to binary file 'out.bin'\n"); + PRINTVALSTREAM(rawoutstream, " using a little-endian type\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -d /dset -b LE -o out.bin quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 4) Display two packed bits (bits 0-1 and bits 4-6) in the dataset /dset\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -d /dset -M 0,1,4,3 quux.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 5) Dataset foo in files file1.h5 file2.h5 file3.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -d /foo file1.h5 file2.h5 file3.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 6) Dataset foo in split files splitfile-m.h5 splitfile-r.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -d /foo -f split splitfile\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 7) Dataset foo in multi files mf-s.h5, mf-b.h5, mf-r.h5, mf-g.h5, mf-l.h5 and mf-o.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -d /foo -f multi mf\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " 8) Dataset foo in family files fam00000.h5 fam00001.h5 and fam00002.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " h5dump -d /foo -f family fam%%05d.h5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); +} + + +/*------------------------------------------------------------------------- + * Function: table_list_add + * + * Purpose: Add a new set of tables + * + * Return: index of added table on success, -1 on failure + * + * Programmer: Neil Fortner, nfortne2@hdfgroup.org + * Adapted from trav_addr_add in h5trav.c by Quincey Koziol + * + * Date: October 13, 2008 + * + *------------------------------------------------------------------------- + */ +ssize_t +table_list_add(hid_t oid, unsigned long file_no) +{ + size_t idx; /* Index of table to use */ + find_objs_t info; + + /* Allocate space if necessary */ + if(table_list.nused == table_list.nalloc) { + h5dump_table_items_t *tmp_ptr; + + table_list.nalloc = MAX(1, table_list.nalloc * 2); + if(NULL == (tmp_ptr = (h5dump_table_items_t *)HDrealloc(table_list.tables, table_list.nalloc * sizeof(table_list.tables[0])))) + return -1; + table_list.tables = tmp_ptr; + } /* end if */ + + /* Append it */ + idx = table_list.nused++; + table_list.tables[idx].fileno = file_no; + table_list.tables[idx].oid = oid; + if(H5Iinc_ref(oid) < 0) { + table_list.nused--; + return -1; + } + if(init_objs(oid, &info, &table_list.tables[idx].group_table, + &table_list.tables[idx].dset_table, &table_list.tables[idx].type_table) < 0) { + H5Idec_ref(oid); + table_list.nused--; + return -1; + } + +#ifdef H5DUMP_DEBUG + dump_tables(&info); +#endif /* H5DUMP_DEBUG */ + + return((ssize_t) idx); +} /* end table_list_add() */ + + +/*------------------------------------------------------------------------- + * Function: table_list_visited + * + * Purpose: Check if a table already exists for the specified fileno + * + * Return: The index of the matching table, or -1 if no matches found + * + * Programmer: Neil Fortner, nfortne2@hdfgroup.org + * Adapted from trav_addr_visited in h5trav.c by Quincey Koziol + * + * Date: October 13, 2008 + * + *------------------------------------------------------------------------- + */ +H5_ATTR_PURE ssize_t +table_list_visited(unsigned long file_no) +{ + size_t u; /* Local index variable */ + + /* Look for table */ + for(u = 0; u < table_list.nused; u++) + /* Check for fileno value already in array */ + if(table_list.tables[u].fileno == file_no) + return((ssize_t) u); + + /* Didn't find table */ + return(-1); +} /* end table_list_visited() */ + + +/*------------------------------------------------------------------------- + * Function: table_list_free + * + * Purpose: Frees the table list + * + * Return: void + * + * Programmer: Neil Fortner, nfortne2@hdfgroup.org + * + * Date: October 13, 2008 + * + *------------------------------------------------------------------------- + */ +static void +table_list_free(void) +{ + size_t u; /* Local index variable */ + + /* Iterate over tables */ + for(u = 0; u < table_list.nused; u++) { + /* Release object id */ + if(H5Idec_ref(table_list.tables[u].oid) < 0) + h5tools_setstatus(EXIT_FAILURE); + + /* Free each table */ + free_table(table_list.tables[u].group_table); + HDfree(table_list.tables[u].group_table); + free_table(table_list.tables[u].dset_table); + HDfree(table_list.tables[u].dset_table); + free_table(table_list.tables[u].type_table); + HDfree(table_list.tables[u].type_table); + } + + /* Free the table list */ + HDfree(table_list.tables); + table_list.tables = NULL; + table_list.nalloc = table_list.nused = 0; +} /* end table_list_free() */ + +/*------------------------------------------------------------------------- + * Function: set_binary_form + * + * Purpose: set the binary form of output by translating from a string input + * parameter to a integer return value + * + * Return: integer form of binary output or -1 if none found + * + * Programmer: Pedro Vicente Nunes + * June 28, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +set_binary_form(const char *form) +{ + int bform = -1; + + if (HDstrcmp(form,"NATIVE") == 0 || HDstrcmp(form,"MEMORY") == 0) { + /* native form */ + bform = 0; + } + else if (HDstrcmp(form,"FILE") == 0) /* file type form */ + bform = 1; + else if (HDstrcmp(form,"LE") == 0) /* convert to little endian */ + bform = 2; + else if (HDstrcmp(form,"BE") == 0) /* convert to big endian */ + bform = 3; + + return bform; +} + +/*------------------------------------------------------------------------- + * Function: set_sort_by + * + * Purpose: set the "by" form of sorting by translating from a string input + * parameter to a H5_index_t return value + * current sort values are [creation_order | name] + * + * Return: H5_index_t form of sort or H5_INDEX_UNKNOWN if none found + * + * Programmer: Pedro Vicente Nunes + * October 1, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5_index_t +set_sort_by(const char *form) +{ + H5_index_t idx_type = H5_INDEX_UNKNOWN; + + if (HDstrcmp(form,"name")==0) /* H5_INDEX_NAME */ + idx_type = H5_INDEX_NAME; + else if (HDstrcmp(form,"creation_order")==0) /* H5_INDEX_CRT_ORDER */ + idx_type = H5_INDEX_CRT_ORDER; + + return idx_type; +} + +/*------------------------------------------------------------------------- + * Function: set_sort_order + * + * Purpose: set the order of sorting by translating from a string input + * parameter to a H5_iter_order_t return value + * current order values are [ascending | descending ] + * + * Return: H5_iter_order_t form of order or H5_ITER_UNKNOWN if none found + * + * Programmer: Pedro Vicente Nunes + * October 1, 2007 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5_iter_order_t +set_sort_order(const char *form) +{ + H5_iter_order_t iter_order = H5_ITER_UNKNOWN; + + if (HDstrcmp(form,"ascending")==0) /* H5_ITER_INC */ + iter_order = H5_ITER_INC; + else if (HDstrcmp(form,"descending")==0) /* H5_ITER_DEC */ + iter_order = H5_ITER_DEC; + + return iter_order; +} + +/*------------------------------------------------------------------------- + * Function: parse_hsize_list + * + * Purpose: Parse a list of comma or space separated integers and return + * them in a list. The string being passed into this function + * should be at the start of the list you want to parse. You are + * responsible for freeing the array returned from here. + * + * Lists in the so-called "terse" syntax are separated by + * semicolons (;). The lists themselves can be separated by + * either commas (,) or white spaces. + * + * Return: <none> + * + * Programmer: Bill Wendling + * Tuesday, 6. February 2001 + * + *------------------------------------------------------------------------- + */ +static void +parse_hsize_list(const char *h_list, subset_d *d) +{ + hsize_t *p_list; + const char *ptr; + unsigned int size_count = 0; + unsigned int i = 0; + unsigned int last_digit = 0; + + if (!h_list || !*h_list || *h_list == ';') + return; + + /* count how many integers do we have */ + for (ptr = h_list; ptr && *ptr && *ptr != ';' && *ptr != ']'; ptr++) + if (HDisdigit(*ptr)) { + if (!last_digit) + /* the last read character wasn't a digit */ + size_count++; + + last_digit = 1; + } + else + last_digit = 0; + + if (size_count == 0) + /* there aren't any integers to read */ + return; + + /* allocate an array for the integers in the list */ + p_list = (hsize_t *)HDcalloc(size_count, sizeof(hsize_t)); + + for (ptr = h_list; i < size_count && ptr && *ptr && *ptr != ';' && *ptr != ']'; ptr++) + if(HDisdigit(*ptr)) { + /* we should have an integer now */ + p_list[i++] = (hsize_t)HDstrtoull(ptr, NULL, 0); + + while (HDisdigit(*ptr)) + /* scroll to end of integer */ + ptr++; + } + d->data = p_list; + d->len = size_count; +} + +/*------------------------------------------------------------------------- + * Function: parse_subset_params + * + * Purpose: Parse the so-called "terse" syntax for specifying subsetting + * parameters. + * + * Return: Success: struct subset_t object + * Failure: NULL + * + * Programmer: Bill Wendling + * Tuesday, 6. February 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static struct subset_t * +parse_subset_params(char *dset) +{ + struct subset_t *s = NULL; + char *brace; + + if (!disable_compact_subset && ((brace = HDstrrchr(dset, '[')) != NULL)) { + *brace++ = '\0'; + + s = (struct subset_t *)HDcalloc(1, sizeof(struct subset_t)); + parse_hsize_list(brace, &s->start); + + while (*brace && *brace != ';') + brace++; + + if (*brace) brace++; + + parse_hsize_list(brace, &s->stride); + + while (*brace && *brace != ';') + brace++; + + if (*brace) brace++; + + parse_hsize_list(brace, &s->count); + + while (*brace && *brace != ';') + brace++; + + if (*brace) brace++; + + parse_hsize_list(brace, &s->block); + } + + return s; +} + +/*------------------------------------------------------------------------- + * Function: parse_mask_list + * + * Purpose: Parse a list of comma or space separated integers and fill + * the packed_bits list and counter. The string being passed into this function + * should be at the start of the list you want to parse. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + *------------------------------------------------------------------------- + */ +static int +parse_mask_list(const char *h_list) +{ + int soffset_value; + unsigned offset_value; + int slength_value; + unsigned length_value; + unsigned long long temp_mask; + const char *ptr = NULL; + + /* sanity check */ + HDassert(h_list); + + HDmemset(packed_mask,0,sizeof(packed_mask)); + + packed_bits_num = 0; + /* scan in pair of offset,length separated by commas. */ + ptr = h_list; + while (*ptr) { + /* scan for an offset which is an unsigned int */ + if (!HDisdigit(*ptr)) { + error_msg("Bad mask list(%s)\n", h_list); + return FAIL; + } + soffset_value = HDatoi(ptr); + offset_value = (unsigned)soffset_value; + if (soffset_value < 0 || offset_value >= PACKED_BITS_SIZE_MAX) { + error_msg("Packed Bit offset value(%d) must be between 0 and %u\n", + soffset_value, (unsigned)(PACKED_BITS_SIZE_MAX - 1)); + return FAIL; + } + + /* skip to end of integer */ + while (HDisdigit(*++ptr)) + ; + /* Look for the common separator */ + if (*ptr++ != ',') { + error_msg("Bad mask list(%s), missing expected comma separator.\n", h_list); + return FAIL; + } + + /* scan for a length which is a positive int */ + if (!HDisdigit(*ptr)) { + error_msg("Bad mask list(%s)\n", h_list); + return FAIL; + } + slength_value = HDatoi(ptr); + if (slength_value <= 0) { + error_msg("Packed Bit length value(%d) must be positive.\n", slength_value); + return FAIL; + } + length_value = (unsigned)slength_value; + if ((offset_value + length_value) > PACKED_BITS_SIZE_MAX) { + error_msg("Packed Bit offset+length value(%u) too large. Max is %u\n", + offset_value+length_value, (unsigned)PACKED_BITS_SIZE_MAX); + return FAIL; + } + + /* skip to end of int */ + while (HDisdigit(*++ptr)) + ; + + /* store the offset,length pair */ + if (packed_bits_num >= PACKED_BITS_MAX) { + /* too many requests */ + error_msg("Too many masks requested (max. %d). Mask list(%s)\n", PACKED_BITS_MAX, h_list); + return FAIL; + } + packed_offset[packed_bits_num] = offset_value; + packed_length[packed_bits_num] = length_value; + /* create the bit mask by left shift 1's by length, then negate it. */ + /* After packed_mask is calculated, packed_length is not needed but */ + /* keep it for debug purpose. */ + temp_mask = ~0ULL; + if(length_value < (int)(8 *sizeof(unsigned long long))) { + temp_mask = temp_mask << length_value; + packed_mask[packed_bits_num] = ~temp_mask; + } + else + packed_mask[packed_bits_num] = temp_mask; + packed_bits_num++; + + /* skip a possible comma separator */ + if (*ptr == ',') { + if (!(*++ptr)) { + /* unexpected end of string */ + error_msg("Bad mask list(%s), unexpected end of string.\n", h_list); + return FAIL; + } + } + } + HDassert(packed_bits_num <= PACKED_BITS_MAX); + if (packed_bits_num == 0) { + /* got no masks! */ + error_msg("Bad mask list(%s)\n", h_list); + return FAIL; + } + return SUCCEED; +} + + +/*------------------------------------------------------------------------- + * Function: free_handler + * + * Purpose: Convenience function to free the handler_t structures. Needs a + * length variable (LEN) to know how many in the array it needs + * to free + * + * Return: Nothing + * + * Programmer: Bill Wendling + * Tuesday, 20. February 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +free_handler(struct handler_t *hand, int len) +{ + int i; + + if(hand) { + for (i = 0; i < len; i++) { + if(hand[i].obj) { + HDfree(hand[i].obj); + hand[i].obj=NULL; + } + + if (hand[i].subset_info) { + if(hand[i].subset_info->start.data) + HDfree(hand[i].subset_info->start.data); + if(hand[i].subset_info->stride.data) + HDfree(hand[i].subset_info->stride.data); + if(hand[i].subset_info->count.data) + HDfree(hand[i].subset_info->count.data); + if(hand[i].subset_info->block.data) + HDfree(hand[i].subset_info->block.data); + + HDfree(hand[i].subset_info); + hand[i].subset_info=NULL; + } + } + + HDfree(hand); + } +} + + +/*------------------------------------------------------------------------- + * Function: parse_command_line + * + * Purpose: Parse the command line for the h5dumper. + * + * Return: Success: A pointer to an array of handler_t structures. + * These contain all the information needed to dump + * the necessary object. + * + * Failure: Exits program with EXIT_FAILURE value. + * + * Programmer: Bill Wendling + * Tuesday, 20. February 2001 + * + * Modifications: + * pvn June, 1, 2006. Add a switch for binary output + * + *------------------------------------------------------------------------- + */ +static struct handler_t * +parse_command_line(int argc, const char *argv[]) +{ + struct handler_t *hand = NULL; + struct handler_t *last_dset = NULL; + int i; + int opt; + int last_was_dset = FALSE; + + /* no arguments */ + if (argc == 1) { + usage(h5tools_getprogname()); + goto error; + } + + /* this will be plenty big enough to hold the info */ + if((hand = (struct handler_t *)HDcalloc((size_t)argc, sizeof(struct handler_t)))==NULL) { + goto error; + } + + /* parse command line options */ + while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { +parse_start: + switch ((char)opt) { + case 'R': + display_region = TRUE; + region_output = TRUE; + break; + case 'B': + display_bb = TRUE; + last_was_dset = FALSE; + break; + case 'n': + display_fi = TRUE; + last_was_dset = FALSE; + if ( opt_arg != NULL) { + h5trav_set_verbose(HDatoi(opt_arg)); + } + break; + case 'p': + display_dcpl = TRUE; + break; + case 'y': + display_ai = FALSE; + break; + case 'e': + display_escape = TRUE; + break; + case 'H': + display_data = FALSE; + display_attr_data = FALSE; + last_was_dset = FALSE; + break; + case 'A': + if ( opt_arg != NULL) { + if(0 == HDatoi(opt_arg)) include_attrs = FALSE; + } + else { + display_data = FALSE; + display_attr_data = TRUE; + last_was_dset = FALSE; + } + break; + case 'i': + display_oid = TRUE; + last_was_dset = FALSE; + break; + case 'r': + display_char = TRUE; + break; + case 'V': + print_version(h5tools_getprogname()); + free_handler(hand, argc); + hand = NULL; + h5tools_setstatus(EXIT_SUCCESS); + goto done; + break; + case 'w': + { + int sh5tools_nCols = HDatoi(opt_arg); + + if (sh5tools_nCols <= 0) + h5tools_nCols = 65535; + else + h5tools_nCols = (unsigned)sh5tools_nCols; + last_was_dset = FALSE; + } + break; + case 'N': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_paths; + hand[i].obj = HDstrdup(opt_arg); + break; + } + + last_was_dset = FALSE; + break; + case 'a': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_attributes; + hand[i].obj = HDstrdup(opt_arg); + break; + } + + last_was_dset = FALSE; + break; + case 'd': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_datasets; + hand[i].obj = HDstrdup(opt_arg); + hand[i].subset_info = parse_subset_params(hand[i].obj); + last_dset = &hand[i]; + break; + } + + last_was_dset = TRUE; + break; + case 'f': + driver = opt_arg; + break; + case 'g': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_groups; + hand[i].obj = HDstrdup(opt_arg); + break; + } + + last_was_dset = FALSE; + break; + case 'l': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_links; + hand[i].obj = HDstrdup(opt_arg); + break; + } + + last_was_dset = FALSE; + break; + case 't': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_datatypes; + hand[i].obj = HDstrdup(opt_arg); + break; + } + + last_was_dset = FALSE; + break; + + case 'O': + if (h5tools_set_output_file(opt_arg, 0) < 0) { + usage(h5tools_getprogname()); + goto error; + } + break; + + case 'o': + if ( bin_output ) { + if (h5tools_set_data_output_file(opt_arg, 1) < 0) { + usage(h5tools_getprogname()); + goto error; + } + } + else { + if(display_attr_data && !display_data) { + if (h5tools_set_attr_output_file(opt_arg, 0) < 0) { + usage(h5tools_getprogname()); + goto error; + } + } + if(display_data || display_all) { + if (h5tools_set_data_output_file(opt_arg, 0) < 0) { + usage(h5tools_getprogname()); + goto error; + } + } + } + + usingdasho = TRUE; + last_was_dset = FALSE; + outfname = opt_arg; + break; + + case 'b': + if ( opt_arg != NULL) { + if ( ( bin_form = set_binary_form(opt_arg)) < 0) { + /* failed to set binary form */ + usage(h5tools_getprogname()); + goto error; + } + } + bin_output = TRUE; + if (outfname!=NULL) { + if (h5tools_set_data_output_file(outfname, 1) < 0) { + /* failed to set output file */ + usage(h5tools_getprogname()); + goto error; + } + + last_was_dset = FALSE; + } + break; + + case 'q': + if ( ( sort_by = set_sort_by(opt_arg)) < 0) { + /* failed to set "sort by" form */ + usage(h5tools_getprogname()); + goto error; + } + break; + + case 'z': + if ( ( sort_order = set_sort_order(opt_arg)) < 0) { + /* failed to set "sort order" form */ + usage(h5tools_getprogname()); + goto error; + } + break; + + case 'M': + if (!last_was_dset) { + error_msg("option `-%c' can only be used after --dataset option\n", opt); + goto error; + } + if (parse_mask_list(opt_arg) != SUCCEED){ + usage(h5tools_getprogname()); + goto error; + } + display_packed_bits = TRUE; + break; + case 'v': + display_vds_first = TRUE; + break; + case 'G': + vds_gap_size = HDatoi(opt_arg); + if (vds_gap_size < 0) { + usage(h5tools_getprogname()); + goto error; + } + break; + + /** begin XML parameters **/ + case 'x': + /* select XML output */ + doxml = TRUE; + useschema = TRUE; + h5tools_dump_header_format = NULL; + dump_function_table = &xml_function_table; + h5tools_nCols = 0; + break; + case 'u': + doxml = TRUE; + useschema = FALSE; + xmlnsprefix = ""; + h5tools_dump_header_format = NULL; + dump_function_table = &xml_function_table; + h5tools_nCols = 0; + break; + case 'D': + /* specify alternative XML DTD or schema */ + /* To Do: check format of this value? */ + xml_dtd_uri = opt_arg; + h5tools_nCols = 0; + break; + + case 'm': + /* specify alternative floating point printing format */ + fp_format = opt_arg; + h5tools_nCols = 0; + break; + + case 'X': + /* specify XML namespace (default="hdf5:"), or none */ + /* To Do: check format of this value? */ + if (!useschema) { + usage(h5tools_getprogname()); + goto error; + } + if (HDstrcmp(opt_arg,":") == 0) + xmlnsprefix = ""; + else + xmlnsprefix = opt_arg; + h5tools_nCols = 0; + break; + /** end XML parameters **/ + + /** begin subsetting parameters **/ + case 's': + case 'S': + case 'c': + case 'k': { + struct subset_t *s; + + if (!last_was_dset) { + error_msg("option `-%c' can only be used after --dataset option\n", opt); + goto error; + } + + if (last_dset->subset_info) { + /* + * This overrides the "terse" syntax if they actually mixed + * the two. + */ + s = last_dset->subset_info; + } + else { + last_dset->subset_info = s = (struct subset_t *)HDcalloc(1, sizeof(struct subset_t)); + } + + /* + * slightly convoluted, but...we are only interested in options + * for subsetting: "--start", "--stride", "--count", and "--block" + * which can come in any order. If we run out of parameters (EOF) + * or run into one which isn't a subsetting parameter (NOT s, S, + * c, or K), then we exit the do-while look, set the subset_info + * to the structure we've been filling. If we've reached the end + * of the options, we exit the parsing (goto parse_end) otherwise, + * since we've "read" the next option, we need to parse it. So we + * jump to the beginning of the switch statement (goto parse_start). + */ + do { + switch ((char)opt) { + case 's': + if (s->start.data) { + HDfree(s->start.data); + s->start.data = NULL; + } + parse_hsize_list(opt_arg, &s->start); + break; + case 'S': + if (s->stride.data) { + HDfree(s->stride.data); + s->stride.data = NULL; + } + parse_hsize_list(opt_arg, &s->stride); + break; + case 'c': + if (s->count.data) { + HDfree(s->count.data); + s->count.data = NULL; + } + parse_hsize_list(opt_arg, &s->count); + break; + case 'k': + if (s->block.data) { + HDfree(s->block.data); + s->block.data = NULL; + } + parse_hsize_list(opt_arg, &s->block); + break; + default: + goto end_collect; + } + } while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF); + +end_collect: + last_was_dset = FALSE; + + if (opt != EOF) + goto parse_start; + else + goto parse_end; + } + /** end subsetting parameters **/ + + case 'E': + enable_error_stack = TRUE; + break; + case 'C': + disable_compact_subset = TRUE; + break; + case 'h': + usage(h5tools_getprogname()); + free_handler(hand, argc); + hand = NULL; + h5tools_setstatus(EXIT_SUCCESS); + goto done; + case '?': + default: + usage(h5tools_getprogname()); + goto error; + } + } + +parse_end: + /* check for file name to be processed */ + if (argc <= opt_ind) { + error_msg("missing file name\n"); + usage(h5tools_getprogname()); + goto error; + } +done: + return hand; + +error: + if (hand) { + free_handler(hand, argc); + hand = NULL; + } + h5tools_setstatus(EXIT_FAILURE); + + return hand; +} + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: HDF5 dumper + * + * Return: Success: 0 + * Failure: 1 + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * Albert Cheng + * 30. September 2000 + * Add the -o option--output file for datasets raw data + * + * REMcG + * November 2000 + * Changes to support XML. + * + * Bill Wendling + * Wednesday, 10. January 2001 + * Modified the way command line parameters are interpreted. They go + * through one function call now (get_option). + * + * Bill Wendling + * Tuesday, 20. February 2001 + * Moved command line parsing to separate function. Made various + * "display_*" flags global. + * + * REMcG + * August 2003 + * Major upgrade to XML support. + * + * Pedro Vicente + * September 2007 + * list objects in requested order (creation order or alphabetically) + * + *------------------------------------------------------------------------- + */ +int +main(int argc, const char *argv[]) +{ + hid_t fid = -1; + hid_t gid = -1; + H5E_auto2_t func; + H5E_auto2_t tools_func; + H5O_info_t oi; + struct handler_t *hand = NULL; + int i; + unsigned u; + void *edata; + void *tools_edata; + char *fname = NULL; + + h5tools_setprogname(PROGRAMNAME); + h5tools_setstatus(EXIT_SUCCESS); + h5tools_dump_header_format = &h5tools_standardformat; + dump_function_table = &ddl_function_table; + dump_indent = 0; + + /* Disable error reporting */ + H5Eget_auto2(H5E_DEFAULT, &func, &edata); + H5Eset_auto2(H5E_DEFAULT, NULL, NULL); + + /* Initialize h5tools lib */ + h5tools_init(); + + /* Disable tools error reporting */ + H5Eget_auto2(H5tools_ERR_STACK_g, &tools_func, &tools_edata); + H5Eset_auto2(H5tools_ERR_STACK_g, NULL, NULL); + + if((hand = parse_command_line(argc, argv))==NULL) { + goto done; + } + + if (bin_output && outfname == NULL) { + error_msg("binary output requires a file name, use -o <filename>\n"); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + if (enable_error_stack) { + H5Eset_auto2(H5E_DEFAULT, func, edata); + H5Eset_auto2(H5tools_ERR_STACK_g, tools_func, tools_edata); + } + + /* Check for conflicting options */ + if (doxml) { + if (!display_all) { + error_msg("option \"%s\" not available for XML\n", + "to display selected objects"); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + else if (display_bb) { + error_msg("option \"%s\" not available for XML\n", "--boot-block"); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + else if (display_oid == 1) { + error_msg("option \"%s\" not available for XML\n", "--object-ids"); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + else if (display_char == TRUE) { + error_msg("option \"%s\" not available for XML\n", "--string"); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + else if (usingdasho) { + error_msg("option \"%s\" not available for XML\n", "--output"); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + } + else { + if (xml_dtd_uri) { + warn_msg("option \"%s\" only applies with XML: %s\n", "--xml-dtd", xml_dtd_uri); + } + } + + if (argc <= opt_ind) { + error_msg("missing file name\n"); + usage(h5tools_getprogname()); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + /* Initialize indexing options */ + h5trav_set_index(sort_by, sort_order); + + while(opt_ind < argc) { + fname = HDstrdup(argv[opt_ind++]); + + fid = h5tools_fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT, driver, NULL, 0); + + if (fid < 0) { + error_msg("unable to open file \"%s\"\n", fname); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + /* allocate and initialize internal data structure */ + init_prefix(&prefix, prefix_len); + + /* Prepare to find objects that might be targets of a reference */ + fill_ref_path_table(fid); + + if(doxml) { + /* initialize XML */ + /* reset prefix! */ + HDstrcpy(prefix, ""); + + /* make sure the URI is initialized to something */ + if (xml_dtd_uri == NULL) { + if (useschema) { + xml_dtd_uri = DEFAULT_XSD; + } + else { + xml_dtd_uri = DEFAULT_DTD; + xmlnsprefix = ""; + } + } + else { + if (useschema && HDstrcmp(xmlnsprefix,"")) { + error_msg("Cannot set Schema URL for a qualified namespace--use -X or -U option with -D \n"); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + } + } + + /* Get object info for root group */ + if(H5Oget_info_by_name(fid, "/", &oi, H5P_DEFAULT) < 0) { + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + /* Initialize object tables */ + if(table_list_add(fid, oi.fileno) < 0) { + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + group_table = table_list.tables[0].group_table; + dset_table = table_list.tables[0].dset_table; + type_table = table_list.tables[0].type_table; + + /* does there exist unamed committed datatype */ + for (u = 0; u < type_table->nobjs; u++) + if (!type_table->objs[u].recorded) { + unamedtype = 1; + break; + } /* end if */ + + /* start to dump - display file header information */ + if (!doxml) { + begin_obj(h5tools_dump_header_format->filebegin, fname, h5tools_dump_header_format->fileblockbegin); + } + else { + PRINTVALSTREAM(rawoutstream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); + + /* alternative first element, depending on schema or DTD. */ + if (useschema) { + if (HDstrcmp(xmlnsprefix,"") == 0) { + PRINTSTREAM(rawoutstream, "<HDF5-File xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"%s\">\n", + xml_dtd_uri); + } + else { + /* TO DO: make -url option work in this case (may need new option) */ + char *ns; + char *indx; + + ns = HDstrdup(xmlnsprefix); + indx = HDstrrchr(ns,(int)':'); + if (indx) *indx = '\0'; + + PRINTSTREAM(rawoutstream, "<%sHDF5-File xmlns:%s=\"http://hdfgroup.org/HDF5/XML/schema/HDF5-File.xsd\" " + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " + "xsi:schemaLocation=\"http://hdfgroup.org/HDF5/XML/schema/HDF5-File " + "http://www.hdfgroup.org/HDF5/XML/schema/HDF5-File.xsd\">\n",xmlnsprefix,ns); + HDfree(ns); + } + } + else { + PRINTSTREAM(rawoutstream, "<!DOCTYPE HDF5-File PUBLIC \"HDF5-File.dtd\" \"%s\">\n", xml_dtd_uri); + PRINTVALSTREAM(rawoutstream, "<HDF5-File>\n"); + } + } + + if (!doxml) { + if (display_fi) { + PRINTVALSTREAM(rawoutstream, "\n"); + dump_fcontents(fid); + end_obj(h5tools_dump_header_format->fileend,h5tools_dump_header_format->fileblockend); + PRINTVALSTREAM(rawoutstream, "\n"); + goto done; + } + + if (display_bb) + dump_fcpl(fid); + } + + if(display_all) { + if((gid = H5Gopen2(fid, "/", H5P_DEFAULT)) < 0) { + error_msg("unable to open root group\n"); + h5tools_setstatus(EXIT_FAILURE); + } + else { + if (!doxml) + dump_indent += COL; + dump_function_table->dump_group_function(gid, "/" ); + if (!doxml) + dump_indent -= COL; + PRINTVALSTREAM(rawoutstream, "\n"); + } + + if(H5Gclose(gid) < 0) { + error_msg("unable to close root group\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + } + else { + /* Note: this option is not supported for XML */ + if(doxml) { + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } /* end if */ + + for(i = 0; i < argc; i++) { + if(hand[i].func) { + hand[i].func(fid, hand[i].obj, hand[i].subset_info, 1, NULL); + } + } + PRINTVALSTREAM(rawoutstream, "\n"); + } + + if (!doxml) { + end_obj(h5tools_dump_header_format->fileend, h5tools_dump_header_format->fileblockend); + PRINTVALSTREAM(rawoutstream, "\n"); + } + else { + PRINTSTREAM(rawoutstream, "</%sHDF5-File>\n", xmlnsprefix); + } + /* Free tables for objects */ + table_list_free(); + + if(fid >=0) + if (H5Fclose(fid) < 0) + h5tools_setstatus(EXIT_FAILURE); + + if(prefix) { + HDfree(prefix); + prefix = NULL; + } + if(fname) { + HDfree(fname); + fname = NULL; + } + } /* end while */ + + if(hand) + free_handler(hand, argc); + + /* To Do: clean up XML table */ + + leave(h5tools_getstatus()); + +done: + /* Free tables for objects */ + table_list_free(); + + if(fid >=0) + if (H5Fclose(fid) < 0) + h5tools_setstatus(EXIT_FAILURE); + + if(prefix) { + HDfree(prefix); + prefix = NULL; + } + if(fname) { + HDfree(fname); + fname = NULL; + } + + if(hand) + free_handler(hand, argc); + + /* To Do: clean up XML table */ + + H5Eset_auto2(H5E_DEFAULT, func, edata); + + leave(h5tools_getstatus()); +} + +/*------------------------------------------------------------------------- + * Function: h5_fileaccess + * + * Purpose: Returns a file access template which is the default template + * but with a file driver set according to the constant or + * environment variable HDF5_DRIVER + * + * Return: Success: A file access property list + * + * Failure: -1 + * + * Programmer: Robb Matzke + * Thursday, November 19, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +h5_fileaccess(void) +{ + static const char *multi_letters = "msbrglo"; + const char *val = NULL; + const char *name; + char s[1024]; + hid_t fapl = -1; + + /* First use the environment variable, then the constant */ + val = HDgetenv("HDF5_DRIVER"); +#ifdef HDF5_DRIVER + if (!val) val = HDF5_DRIVER; +#endif + + if ((fapl=H5Pcreate(H5P_FILE_ACCESS))<0) return -1; + if (!val || !*val) return fapl; /*use default*/ + + HDstrncpy(s, val, sizeof s); + s[sizeof(s)-1] = '\0'; + if (NULL==(name=HDstrtok(s, " \t\n\r"))) return fapl; + + if (!HDstrcmp(name, "sec2")) { + /* Unix read() and write() system calls */ + if (H5Pset_fapl_sec2(fapl)<0) return -1; + } + else if (!HDstrcmp(name, "stdio")) { + /* Standard C fread() and fwrite() system calls */ + if (H5Pset_fapl_stdio(fapl)<0) return -1; + } + else if (!HDstrcmp(name, "core")) { + /* In-core temporary file with 1MB increment */ + if (H5Pset_fapl_core(fapl, 1024*1024, FALSE)<0) return -1; + } + else if (!HDstrcmp(name, "split")) { + /* Split meta data and raw data each using default driver */ + if (H5Pset_fapl_split(fapl, "-m.h5", H5P_DEFAULT, "-r.h5", H5P_DEFAULT) < 0) + return -1; + } + else if (!HDstrcmp(name, "multi")) { + /* Multi-file driver, general case of the split driver */ + H5FD_mem_t memb_map[H5FD_MEM_NTYPES]; + hid_t memb_fapl[H5FD_MEM_NTYPES]; + const char *memb_name[H5FD_MEM_NTYPES]; + char sv[H5FD_MEM_NTYPES][1024]; + haddr_t memb_addr[H5FD_MEM_NTYPES]; + H5FD_mem_t mt; + + HDmemset(memb_map, 0, sizeof memb_map); + HDmemset(memb_fapl, 0, sizeof memb_fapl); + HDmemset(memb_name, 0, sizeof memb_name); + HDmemset(memb_addr, 0, sizeof memb_addr); + + HDassert(HDstrlen(multi_letters)==H5FD_MEM_NTYPES); + for (mt=H5FD_MEM_DEFAULT; mt<H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t,mt)) { + memb_fapl[mt] = H5P_DEFAULT; + memb_map[mt] = mt; + sprintf(sv[mt], "%%s-%c.h5", multi_letters[mt]); + memb_name[mt] = sv[mt]; + memb_addr[mt] = (haddr_t)MAX(mt - 1, 0) * (HADDR_MAX / 10); + } + + if (H5Pset_fapl_multi(fapl, memb_map, memb_fapl, memb_name, memb_addr, FALSE) < 0) + return -1; + } + else if (!HDstrcmp(name, "family")) { + hsize_t fam_size = 100*1024*1024; /*100 MB*/ + + /* Family of files, each 1MB and using the default driver */ + if ((val=HDstrtok(NULL, " \t\n\r"))) + fam_size = (hsize_t)(HDstrtod(val, NULL) * 1024*1024); + if (H5Pset_fapl_family(fapl, fam_size, H5P_DEFAULT)<0) + return -1; + } + else if (!HDstrcmp(name, "log")) { + long log_flags = H5FD_LOG_LOC_IO; + + /* Log file access */ + if ((val = HDstrtok(NULL, " \t\n\r"))) + log_flags = HDstrtol(val, NULL, 0); + + if (H5Pset_fapl_log(fapl, NULL, (unsigned)log_flags, 0) < 0) + return -1; + } + else if (!HDstrcmp(name, "direct")) { + /* Substitute Direct I/O driver with sec2 driver temporarily because + * some output has sec2 driver as the standard. */ + if (H5Pset_fapl_sec2(fapl)<0) return -1; + } + else { + /* Unknown driver */ + return -1; + } + + return fapl; +} + + +/*------------------------------------------------------------------------- + * Function: init_prefix + * + * Purpose: allocate and initialize prefix + * + * Return: void + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +init_prefix(char **prfx, size_t prfx_len) +{ + HDassert(prfx_len > 0); + *prfx = (char *)HDcalloc(prfx_len, 1); +} + + +/*------------------------------------------------------------------------- + * Function: add_prefix + * + * Purpose: Add object to prefix + * + * Return: void + * + *------------------------------------------------------------------------- + */ +void +add_prefix(char **prfx, size_t *prfx_len, const char *name) +{ + size_t new_len = HDstrlen(*prfx) + HDstrlen(name) + 2; + + /* Check if we need more space */ + if(*prfx_len <= new_len) { + *prfx_len = new_len + 1; + *prfx = (char *)HDrealloc(*prfx, *prfx_len); + } + + /* Append object name to prefix */ + HDstrcat(HDstrcat(*prfx, "/"), name); +} /* end add_prefix */ + diff --git a/tools/src/h5dump/h5dump.h b/tools/src/h5dump/h5dump.h new file mode 100644 index 0000000..8224c02 --- /dev/null +++ b/tools/src/h5dump/h5dump.h @@ -0,0 +1,115 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#ifndef H5DUMP_H__ +#define H5DUMP_H__ + +#include "hdf5.h" +#include "H5private.h" +#include "h5tools.h" +#include "h5tools_utils.h" +#include "h5tools_ref.h" +#include "h5trav.h" +#include "h5dump_defines.h" + +/** + ** This is the global dispatch table for the dump functions. + **/ +/* the table of dump functions */ +typedef struct dump_functions_t { + void (*dump_group_function) (hid_t, const char *); + void (*dump_named_datatype_function) (hid_t, const char *); + void (*dump_dataset_function) (hid_t, const char *, struct subset_t *); + void (*dump_dataspace_function) (hid_t); + void (*dump_datatype_function) (hid_t); + herr_t (*dump_attribute_function) (hid_t, const char *, const H5A_info_t *, void *); + void (*dump_data_function) (hid_t, int, struct subset_t *, int); +} dump_functions; + +/* List of table structures. There is one table structure for each file */ +typedef struct h5dump_table_items_t { + unsigned long fileno; /* File number that these tables refer to */ + hid_t oid; /* ID of an object in this file, held open so fileno is consistent */ + table_t *group_table; /* Table of groups */ + table_t *dset_table; /* Table of datasets */ + table_t *type_table; /* Table of datatypes */ +} h5dump_table_items_t; +typedef struct h5dump_table_list_t { + size_t nalloc; + size_t nused; + h5dump_table_items_t *tables; +} h5dump_table_list_t; + +h5dump_table_list_t table_list = {0, 0, NULL}; +table_t *group_table = NULL, *dset_table = NULL, *type_table = NULL; +unsigned dump_indent = 0; /*how far in to indent the line */ + +int unamedtype = 0; /* shared datatype with no name */ +hbool_t hit_elink = FALSE; /* whether we have traversed an external link */ +size_t prefix_len = 1024; +char *prefix = NULL; +const char *fp_format = NULL; + +/* things to display or which are set via command line parameters */ +int display_all = TRUE; +int display_oid = FALSE; +int display_data = TRUE; +int display_attr_data = TRUE; +int display_char = FALSE; /*print 1-byte numbers as ASCII */ +int usingdasho = FALSE; +int display_bb = FALSE; /*superblock */ +int display_dcpl = FALSE; /*dcpl */ +int display_fi = FALSE; /*file index */ +int display_ai = TRUE; /*array index */ +int display_escape = FALSE; /*escape non printable characters */ +int display_region = FALSE; /*print region reference data */ +int disable_compact_subset= FALSE; /* disable compact form of subset notation */ +int display_packed_bits = FALSE; /*print 1-8 byte numbers as packed bits*/ +int include_attrs = TRUE; /* Display attributes */ +int display_vds_first = FALSE; /* vds display to all by default*/ +int vds_gap_size = 0; /* vds skip missing files default is none */ + +/* sort parameters */ +H5_index_t sort_by = H5_INDEX_NAME; /*sort_by [creation_order | name] */ +H5_iter_order_t sort_order = H5_ITER_INC; /*sort_order [ascending | descending] */ + +#define PACKED_BITS_MAX 8 /* Maximum number of packed-bits to display */ +#define PACKED_BITS_SIZE_MAX (8*sizeof(long long)) /* Maximum bits size of integer types of packed-bits */ +/* mask list for packed bits */ +unsigned long long packed_mask[PACKED_BITS_MAX]; /* packed bits are restricted to 8*sizeof(llong) bytes */ + +/* packed bits display parameters */ +unsigned packed_offset[PACKED_BITS_MAX]; +unsigned packed_length[PACKED_BITS_MAX]; + +/* + * The global table is set to either ddl_function_table or + * xml_function_table in the initialization. + */ +const dump_functions *dump_function_table; + +#ifdef __cplusplus +"C" { +#endif + +void add_prefix(char **prfx, size_t *prfx_len, const char *name); +hid_t h5_fileaccess(void); +ssize_t table_list_add(hid_t oid, unsigned long file_no); +ssize_t table_list_visited(unsigned long file_no); + +#ifdef __cplusplus +} +#endif + +#endif /* !H5DUMP_H__ */ diff --git a/tools/src/h5dump/h5dump_ddl.c b/tools/src/h5dump/h5dump_ddl.c new file mode 100644 index 0000000..182d570 --- /dev/null +++ b/tools/src/h5dump/h5dump_ddl.c @@ -0,0 +1,2178 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#include <stdio.h> +#include <stdlib.h> + +#include "H5private.h" +#include "h5tools.h" +#include "h5tools_dump.h" +#include "h5tools_utils.h" +#include "h5tools_ref.h" +#include "h5trav.h" +#include "h5dump_extern.h" +#include "h5dump_ddl.h" + +typedef struct { + hid_t fid; /* File ID being traversed */ + const char *op_name; /* Object name wanted */ +} trav_handle_udata_t; + +typedef struct { + const char *path; /* Path of object being searched */ + const char *op_name; /* Object name wanted */ +} trav_attr_udata_t; + +/* callback function used by H5Literate() */ +static herr_t dump_all_cb(hid_t group, const char *name, const H5L_info_t *linfo, void *op_data); +static int dump_extlink(hid_t group, const char *linkname, const char *objname); + +/*------------------------------------------------------------------------- + * Function: dump_datatype + * + * Purpose: Dump the datatype. Datatype can be HDF5 predefined + * atomic datatype or committed/transient datatype. + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +dump_datatype(hid_t type) +{ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + h5dump_type_table = type_table; + h5tools_dump_datatype(rawoutstream, outputformat, &ctx, type); + h5dump_type_table = NULL; +} + +/*------------------------------------------------------------------------- + * Function: dump_dataspace + * + * Purpose: Dump the dataspace. Dataspace can be named dataspace, + * array, or others. + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +dump_dataspace(hid_t space) +{ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + h5tools_dump_dataspace(rawoutstream, outputformat, &ctx, space); +} + + +/*------------------------------------------------------------------------- + * Function: dump_attr_cb + * + * Purpose: attribute function callback called by H5Aiterate2, displays the attribute + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Ruey-Hsia Li + * + * Modifications: Pedro Vicente, October 4, 2007 + * Added H5A_info_t parameter to conform with H5Aiterate2 + * + *------------------------------------------------------------------------- + */ +herr_t +dump_attr_cb(hid_t oid, const char *attr_name, const H5A_info_t H5_ATTR_UNUSED *info, void H5_ATTR_UNUSED *_op_data) +{ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + h5tool_format_t string_dataformat; + + hid_t attr_id; + herr_t ret = SUCCEED; + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + attr_id = H5Aopen(oid, attr_name, H5P_DEFAULT); + oid_output = display_oid; + data_output = display_data; + attr_data_output = display_attr_data; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + h5dump_type_table = type_table; + h5tools_dump_attribute(rawoutstream, outputformat, &ctx, attr_name, attr_id, display_ai, display_char); + h5dump_type_table = NULL; + + if(attr_id < 0) { + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + + return ret; +} + + +/*------------------------------------------------------------------------- + * Function: dump_all_cb + * + * Purpose: function callback called by H5Literate, + * displays everything in the specified object + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * RMcG, November 2000 + * Added XML support. Also, optionally checks the op_data argument + * + * PVN, May 2008 + * Dump external links + * + *------------------------------------------------------------------------- + */ +static herr_t +dump_all_cb(hid_t group, const char *name, const H5L_info_t *linfo, void H5_ATTR_UNUSED *op_data) +{ + hid_t obj; + hid_t dapl_id = H5P_DEFAULT; /* dataset access property list ID */ + herr_t ret = SUCCEED; + char *obj_path = NULL; /* Full path of object */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + /* Build the object's path name */ + obj_path = (char *)HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2); + if(!obj_path) { + ret = FAIL; + goto done; + } + + HDstrcpy(obj_path, prefix); + HDstrcat(obj_path, "/"); + HDstrcat(obj_path, name); + + if(linfo->type == H5L_TYPE_HARD) { + H5O_info_t oinfo; + + /* Stat the object */ + if(H5Oget_info_by_name(group, name, &oinfo, H5P_DEFAULT) < 0) { + error_msg("unable to get object information for \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + goto done; + } /* end if */ + + switch(oinfo.type) { + case H5O_TYPE_GROUP: + if((obj = H5Gopen2(group, name, H5P_DEFAULT)) < 0) { + error_msg("unable to dump group \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + char *old_prefix; /* Pointer to previous prefix */ + + /* Keep copy of prefix before iterating into group */ + old_prefix = HDstrdup(prefix); + HDassert(old_prefix); + + /* Append group name to prefix */ + add_prefix(&prefix, &prefix_len, name); + + /* Iterate into group */ + dump_function_table->dump_group_function(obj, name); + + /* Restore old prefix name */ + HDstrcpy(prefix, old_prefix); + HDfree(old_prefix); + + /* Close group */ + H5Gclose(obj); + } + break; + + case H5O_TYPE_DATASET: + if(display_data) { + if ((dapl_id = H5Pcreate(H5P_DATASET_ACCESS)) < 0) { + error_msg("error in creating default access property list ID\n"); + } + if (display_vds_first) { + if(H5Pset_virtual_view(dapl_id, H5D_VDS_FIRST_MISSING) < 0) + error_msg("error in setting access property list ID, virtual_view\n"); + } + if (vds_gap_size > 0) { + if(H5Pset_virtual_printf_gap(dapl_id, (hsize_t)vds_gap_size) < 0) + error_msg("error in setting access property list ID, virtual_printf_gap\n"); + } + } + if((obj = H5Dopen2(group, name, dapl_id)) >= 0) { + if(oinfo.rc > 1 || hit_elink) { + obj_t *found_obj; /* Found object */ + + found_obj = search_obj(dset_table, oinfo.addr); + + if(found_obj == NULL) { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->datasetbegin, name, + h5tools_dump_header_format->datasetblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->datasetblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetblockend); + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + if (dapl_id != H5P_DEFAULT) + H5Pclose(dapl_id); + H5Dclose(obj); + goto done; + } + else if(found_obj->displayed) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->datasetbegin, name, + h5tools_dump_header_format->datasetblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\"", HARDLINK, found_obj->objname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->datasetblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetblockend); + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + if (dapl_id != H5P_DEFAULT) + H5Pclose(dapl_id); + H5Dclose(obj); + goto done; + } + else { + found_obj->displayed = TRUE; + } + } /* end if */ + + dump_function_table->dump_dataset_function(obj, name, NULL); + if (dapl_id != H5P_DEFAULT) + H5Pclose(dapl_id); + H5Dclose(obj); + } + else { + if (dapl_id != H5P_DEFAULT) + H5Pclose(dapl_id); + error_msg("unable to dump dataset \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + break; + + case H5O_TYPE_NAMED_DATATYPE: + if((obj = H5Topen2(group, name, H5P_DEFAULT)) < 0) { + error_msg("unable to dump datatype \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + dump_function_table->dump_named_datatype_function(obj, name); + H5Tclose(obj); + } + break; + + case H5O_TYPE_UNKNOWN: + case H5O_TYPE_NTYPES: + default: + error_msg("unknown object \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + } /* end if */ + else { + char *targbuf; + + switch(linfo->type) { + case H5L_TYPE_SOFT: + targbuf = (char *)HDmalloc(linfo->u.val_size); + HDassert(targbuf); + + ctx.need_prefix = TRUE; + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->softlinkbegin, name, + h5tools_dump_header_format->softlinkblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + + if(H5Lget_val(group, name, targbuf, linfo->u.val_size, H5P_DEFAULT) < 0) { + error_msg("unable to get link value\n"); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + /* print the value of a soft link */ + /* Standard DDL: no modification */ + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "LINKTARGET \"%s\"", targbuf); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->softlinkblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->softlinkblockend); + if(HDstrlen(h5tools_dump_header_format->softlinkend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->softlinkend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->softlinkend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(targbuf); + break; + + case H5L_TYPE_EXTERNAL: + targbuf = (char *)HDmalloc(linfo->u.val_size); + HDassert(targbuf); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->extlinkbegin, name, + h5tools_dump_header_format->extlinkblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + if(H5Lget_val(group, name, targbuf, linfo->u.val_size, H5P_DEFAULT) < 0) { + indentation(dump_indent); + error_msg("unable to get external link value\n"); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } /* end if */ + else { + const char *filename; + const char *targname; + + if(H5Lunpack_elink_val(targbuf, linfo->u.val_size, NULL, &filename, &targname) < 0) { + indentation(dump_indent); + error_msg("unable to unpack external link value\n"); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } /* end if */ + else { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "TARGETFILE \"%s\"", filename); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "TARGETPATH \"%s\"", targname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + /* dump the external link */ + dump_extlink(group, name, targname); + ctx.indent_level--; + } /* end else */ + } /* end else */ + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->extlinkblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->extlinkblockend); + if(HDstrlen(h5tools_dump_header_format->extlinkend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->extlinkend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->extlinkend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(targbuf); + break; + + case H5L_TYPE_ERROR: + case H5L_TYPE_MAX: + HDassert(0); + /* fall through */ + case H5L_TYPE_HARD: + default: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->udlinkbegin, name, + h5tools_dump_header_format->udlinkblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "LINKCLASS %d", linfo->type); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->udlinkblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->udlinkblockend); + if(HDstrlen(h5tools_dump_header_format->udlinkend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->udlinkend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->udlinkend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + break; + } /* end switch */ + } /* end else */ + +done: + + h5tools_str_close(&buffer); + + if(obj_path) + HDfree(obj_path); + return ret; +} + +/*------------------------------------------------------------------------- + * Function: attr_iteration + * + * Purpose: Iterate and display attributes within the specified group + * + * Return: void + * + *------------------------------------------------------------------------- + */ +void +attr_iteration(hid_t gid, unsigned attr_crt_order_flags) +{ + /* attribute iteration: if there is a request to do H5_INDEX_CRT_ORDER and tracking order is set + in the group for attributes, then, sort by creation order, otherwise by name */ + if(include_attrs) { + if((sort_by == H5_INDEX_CRT_ORDER) && (attr_crt_order_flags & H5P_CRT_ORDER_TRACKED)) { + if(H5Aiterate2(gid, sort_by, sort_order, NULL, dump_attr_cb, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end if */ + else { + if(H5Aiterate2(gid, H5_INDEX_NAME, sort_order, NULL, dump_attr_cb, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end else */ + } +} + +/*------------------------------------------------------------------------- + * Function: link_iteration + * + * Purpose: Iterate and display links within the specified group + * + * Return: void + * + *------------------------------------------------------------------------- + */ +void +link_iteration(hid_t gid, unsigned crt_order_flags) +{ + + /* if there is a request to do H5_INDEX_CRT_ORDER and tracking order is set + in the group, then, sort by creation order, otherwise by name */ + if((sort_by == H5_INDEX_CRT_ORDER) && (crt_order_flags & H5P_CRT_ORDER_TRACKED)) + H5Literate(gid, sort_by, sort_order, NULL, dump_all_cb, NULL); + else + H5Literate(gid, H5_INDEX_NAME, sort_order, NULL, dump_all_cb, NULL); +} + +/*------------------------------------------------------------------------- + * Function: dump_named_datatype + * + * Purpose: Dump named datatype + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * Pedro Vicente, March 27, 2006 + * added display of attributes + * Pedro Vicente, October 4, 2007, added parameters to H5Aiterate2() to allow for + * other iteration orders + * + *------------------------------------------------------------------------- + */ +void +dump_named_datatype(hid_t tid, const char *name) +{ + H5O_info_t oinfo; + unsigned attr_crt_order_flags; + hid_t tcpl_id = -1; /* datatype creation property list ID */ + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + h5tool_format_t string_dataformat; + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + if ((tcpl_id = H5Tget_create_plist(tid)) < 0) { + error_msg("error in getting creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the creation properties for attributes */ + if (H5Pget_attr_creation_order(tcpl_id, &attr_crt_order_flags) < 0) { + error_msg("error in getting creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + if(H5Pclose(tcpl_id) < 0) { + error_msg("error in closing creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + ctx.need_prefix = TRUE; + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->datatypebegin, name, + h5tools_dump_header_format->datatypeblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + H5Oget_info(tid, &oinfo); + + /* Must check for uniqueness of all objects if we've traversed an elink, + * otherwise only check if the reference count > 1. + */ + if(oinfo.rc > 1 || hit_elink) { + obj_t *found_obj; /* Found object */ + + found_obj = search_obj(type_table, oinfo.addr); + + if (found_obj == NULL) { + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + else if (found_obj->displayed) { + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\"", HARDLINK, found_obj->objname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + goto done; + } + else + found_obj->displayed = TRUE; + } /* end if */ + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_print_datatype(rawoutstream, &buffer, outputformat, &ctx, tid, FALSE); + + if(H5Tget_class(tid) != H5T_COMPOUND) { + h5tools_str_append(&buffer, ";"); + } + + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + /* print attributes */ + dump_indent += COL; + + attr_iteration(tid, attr_crt_order_flags); + + dump_indent -= COL; + +done: + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->datatypeblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datatypeblockend); + if(HDstrlen(h5tools_dump_header_format->datatypeend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->datatypeend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datatypeend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: dump_group + * + * Purpose: Dump everything within the specified group + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * + * Call to dump_all_cb -- add parameter to select everything. + * + * Pedro Vicente, October 1, 2007 + * handle several iteration orders for attributes and groups + * + *------------------------------------------------------------------------- + */ +void +dump_group(hid_t gid, const char *name) +{ + H5O_info_t oinfo; + hid_t dset; + hid_t type; + hid_t gcpl_id; + unsigned crt_order_flags; + unsigned attr_crt_order_flags; + char type_name[1024]; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + if ((gcpl_id = H5Gget_create_plist(gid)) < 0) { + error_msg("error in getting group creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the group creation properties for attributes */ + if (H5Pget_attr_creation_order(gcpl_id, &attr_crt_order_flags) < 0) { + error_msg("error in getting group creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the group creation properties */ + if(H5Pget_link_creation_order(gcpl_id, &crt_order_flags) < 0) { + error_msg("error in getting group creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + if(H5Pclose(gcpl_id) < 0) { + error_msg("error in closing group creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + ctx.need_prefix = TRUE; + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->groupbegin, name, + h5tools_dump_header_format->groupblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + dump_indent += COL; + + if(!HDstrcmp(name, "/") && unamedtype) { + unsigned u; /* Local index variable */ + + /* dump unamed type in root group */ + for(u = 0; u < type_table->nobjs; u++) + if(!type_table->objs[u].recorded) { + dset = H5Dopen2(gid, type_table->objs[u].objname, H5P_DEFAULT); + type = H5Dget_type(dset); + sprintf(type_name, "#"H5_PRINTF_HADDR_FMT, type_table->objs[u].objno); + dump_function_table->dump_named_datatype_function(type, type_name); + H5Tclose(type); + H5Dclose(dset); + } + } /* end if */ + + if(display_oid) + h5tools_dump_oid(rawoutstream, outputformat, &ctx, gid); + + h5tools_dump_comment(rawoutstream, outputformat, &ctx, gid); + + H5Oget_info(gid, &oinfo); + + /* Must check for uniqueness of all objects if we've traversed an elink, + * otherwise only check if the reference count > 1. + */ + if(oinfo.rc > 1 || hit_elink) { + obj_t *found_obj; /* Found object */ + + found_obj = search_obj(group_table, oinfo.addr); + + if (found_obj == NULL) { + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + h5tools_setstatus(EXIT_FAILURE); + } + else if (found_obj->displayed) { + ctx.need_prefix = TRUE; + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\"", HARDLINK, found_obj->objname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + found_obj->displayed = TRUE; + attr_iteration(gid, attr_crt_order_flags); + link_iteration(gid, crt_order_flags); + } + } + else { + attr_iteration(gid, attr_crt_order_flags); + link_iteration(gid, crt_order_flags); + } + + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->groupblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->groupblockend); + if(HDstrlen(h5tools_dump_header_format->groupend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->groupend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->groupend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: dump_dataset + * + * Purpose: Dump the specified data set + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * Pedro Vicente, 2004, added dataset creation property list display + * Pedro Vicente, October 4, 2007, added parameters to H5Aiterate2() to allow for + * other iteration orders + * + *------------------------------------------------------------------------- + */ +void +dump_dataset(hid_t did, const char *name, struct subset_t *sset) +{ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + h5tool_format_t string_dataformat; + hid_t type, space; + unsigned attr_crt_order_flags; + hid_t dcpl_id; /* dataset creation property list ID */ + h5tools_str_t buffer; /* string into which to render */ + hsize_t curr_pos = 0; /* total data element position */ + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + if ((dcpl_id = H5Dget_create_plist(did)) < 0) { + error_msg("error in getting creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the creation properties for attributes */ + if (H5Pget_attr_creation_order(dcpl_id, &attr_crt_order_flags) < 0) { + error_msg("error in getting creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->datasetbegin, name, + h5tools_dump_header_format->datasetblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_dump_comment(rawoutstream, outputformat, &ctx, did); + + dump_indent += COL; + ctx.indent_level++; + + type = H5Dget_type(did); + h5dump_type_table = type_table; + h5tools_dump_datatype(rawoutstream, outputformat, &ctx, type); + h5dump_type_table = NULL; + + space = H5Dget_space(did); + h5tools_dump_dataspace(rawoutstream, outputformat, &ctx, space); + H5Sclose(space); + + if(display_oid) { + h5tools_dump_oid(rawoutstream, outputformat, &ctx, did); + } + + if(display_dcpl) { + h5dump_type_table = type_table; + h5tools_dump_dcpl(rawoutstream, outputformat, &ctx, dcpl_id, type, did); + h5dump_type_table = NULL; + } + H5Pclose(dcpl_id); + + if(display_data) { + unsigned data_loop = 1; + unsigned u; + + if(display_packed_bits) + data_loop = packed_bits_num; + for(u = 0; u < data_loop; u++) { + if(display_packed_bits) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + /* Render the element */ + h5tools_str_reset(&buffer); + packed_data_mask = packed_mask[u]; + packed_data_offset = packed_offset[u]; + packed_data_length = packed_length[u]; + h5tools_print_packed_bits(&buffer, type); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + switch(H5Tget_class(type)) { + case H5T_TIME: + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "DATA{ not yet implemented.}"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + break; + + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_STRING: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_COMPOUND: + case H5T_REFERENCE: + case H5T_ENUM: + case H5T_VLEN: + case H5T_ARRAY: + { + h5tools_dump_data(rawoutstream, outputformat, &ctx, did, TRUE, sset, display_ai, display_char); + } + break; + + case H5T_NO_CLASS: + case H5T_NCLASSES: + default: + HDassert(0); + break; + } /* end switch */ + } /* for(u=0; u<data_loop; u++) */ + } + H5Tclose(type); + + if (!bin_output) { + attr_iteration(did, attr_crt_order_flags); + } + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->datasetblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetblockend); + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: dump_data + * + * Purpose: Dump attribute or dataset data + * + * Return: void + * + * Programmer: Ruey-Hsia Li + * + * Modifications: pvn, print the matrix indices + * Albert Cheng, 2004/11/18 + * Add --string printing for attributes too. + * + *------------------------------------------------------------------------- + */ +void +dump_data(hid_t obj_id, int obj_data, struct subset_t *sset, int display_index) +{ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + h5tool_format_t string_dataformat; + int print_dataset = FALSE; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + if(obj_data == DATASET_DATA) + print_dataset = TRUE; + h5tools_dump_data(rawoutstream, outputformat, &ctx, obj_id, print_dataset, sset, display_index, display_char); +} + + +/*------------------------------------------------------------------------- + * Function: dump_fcpl + * + * Purpose: prints file creation property list information + * + * Return: void + * + * Programmer: pvn + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +dump_fcpl(hid_t fid) +{ + hid_t fcpl; /* file creation property list ID */ + hsize_t userblock; /* userblock size retrieved from FCPL */ + size_t off_size; /* size of offsets in the file */ + size_t len_size; /* size of lengths in the file */ + H5F_file_space_type_t fs_strategy; /* file space strategy */ + hsize_t fs_threshold; /* free-space section threshold */ + H5F_info2_t finfo; /* file information */ +#ifdef SHOW_FILE_DRIVER + hid_t fapl; /* file access property list ID */ + hid_t fdriver; /* file driver */ + char dname[32]; /* buffer to store driver name */ +#endif + unsigned sym_lk; /* symbol table B-tree leaf 'K' value */ + unsigned sym_ik; /* symbol table B-tree internal 'K' value */ + unsigned istore_ik; /* indexed storage B-tree internal 'K' value */ + + fcpl=H5Fget_create_plist(fid); + H5Fget_info2(fid, &finfo); + H5Pget_userblock(fcpl,&userblock); + H5Pget_sizes(fcpl,&off_size,&len_size); + H5Pget_sym_k(fcpl,&sym_ik,&sym_lk); + H5Pget_istore_k(fcpl,&istore_ik); + H5Pget_file_space(fcpl, &fs_strategy, &fs_threshold); + H5Pclose(fcpl); +#ifdef SHOW_FILE_DRIVER + fapl=h5_fileaccess(); + fdriver=H5Pget_driver(fapl); + H5Pclose(fapl); +#endif + + /*------------------------------------------------------------------------- + * SUPER_BLOCK + *------------------------------------------------------------------------- + */ + PRINTSTREAM(rawoutstream, "\n%s %s\n",SUPER_BLOCK, BEGIN); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %u\n","SUPERBLOCK_VERSION", finfo.super.version); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %u\n","FREELIST_VERSION", finfo.free.version); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %u\n","SYMBOLTABLE_VERSION", 0); /* Retain this for backward compatibility, for now (QAK) */ + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %u\n","OBJECTHEADER_VERSION", finfo.sohm.version); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream,"%s %zu\n","OFFSET_SIZE", off_size); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream,"%s %zu\n","LENGTH_SIZE", len_size); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %u\n","BTREE_RANK", sym_ik); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %d\n","BTREE_LEAF", sym_lk); + +#ifdef SHOW_FILE_DRIVER + if(H5FD_CORE==fdriver) + HDstrcpy(dname,"H5FD_CORE"); +#ifdef H5_HAVE_DIRECT + else if(H5FD_DIRECT==fdriver) + HDstrcpy(dname,"H5FD_DIRECT"); +#endif + else if(H5FD_FAMILY==fdriver) + HDstrcpy(dname,"H5FD_FAMILY"); + else if(H5FD_LOG==fdriver) + HDstrcpy(dname,"H5FD_LOG"); + else if(H5FD_MPIO==fdriver) + HDstrcpy(dname,"H5FD_MPIO"); + else if(H5FD_MULTI==fdriver) + HDstrcpy(dname,"H5FD_MULTI"); + else if(H5FD_SEC2==fdriver) + HDstrcpy(dname,"H5FD_SEC2"); + else if(H5FD_STDIO==fdriver) + HDstrcpy(dname,"H5FD_STDIO"); + else + HDstrcpy(dname,"Unknown driver"); + + /* Take out this because the driver used can be different from the + * standard output. */ + /*indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %s\n","FILE_DRIVER", dname);*/ +#endif + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %u\n","ISTORE_K", istore_ik); + + indentation(dump_indent + COL); + if(fs_strategy == H5F_FILE_SPACE_ALL_PERSIST) { + PRINTSTREAM(rawoutstream, "%s %s\n", "FILE_SPACE_STRATEGY", "H5F_FILE_SPACE_ALL_PERSIST"); + } else if(fs_strategy == H5F_FILE_SPACE_ALL) { + PRINTSTREAM(rawoutstream, "%s %s\n", "FILE_SPACE_STRATEGY", "H5F_FILE_SPACE_ALL"); + } else if(fs_strategy == H5F_FILE_SPACE_AGGR_VFD) { + PRINTSTREAM(rawoutstream, "%s %s\n", "FILE_SPACE_STRATEGY", "H5F_FILE_SPACE_AGGR_VFD"); + } else if(fs_strategy == H5F_FILE_SPACE_VFD) { + PRINTSTREAM(rawoutstream, "%s %s\n", "FILE_SPACE_STRATEGY", "H5F_FILE_SPACE_VFD"); + } else + PRINTSTREAM(rawoutstream, "%s %s\n", "FILE_SPACE_STRATEGY", "Unknown strategy"); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s %Hu\n","FREE_SPACE_THRESHOLD", fs_threshold); + + /*------------------------------------------------------------------------- + * USER_BLOCK + *------------------------------------------------------------------------- + */ + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "USER_BLOCK %s\n",BEGIN); + indentation(dump_indent + COL + COL); + PRINTSTREAM(rawoutstream,"%s %Hu\n","USERBLOCK_SIZE", userblock); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s\n",END); + + PRINTSTREAM(rawoutstream, "%s",END); +} + +/*------------------------------------------------------------------------- + * Function: dump_fcontents + * + * Purpose: prints all objects + * + * Return: void + * + * Programmer: pvn + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +dump_fcontents(hid_t fid) +{ + PRINTSTREAM(rawoutstream, "%s %s\n",FILE_CONTENTS, BEGIN); + + /* special case of unamed types in root group */ + if (unamedtype) { + unsigned u; + + for (u = 0; u < type_table->nobjs; u++) { + if (!type_table->objs[u].recorded) + PRINTSTREAM(rawoutstream, " %-10s /#"H5_PRINTF_HADDR_FMT"\n", "datatype", type_table->objs[u].objno); + } + } + + /* print objects in the files */ + h5trav_print(fid); + + PRINTSTREAM(rawoutstream, " %s\n",END); +} + +static herr_t +attr_search(hid_t oid, const char *attr_name, const H5A_info_t H5_ATTR_UNUSED *ainfo, void *_op_data) +{ + herr_t ret = SUCCEED; + int j; + char *obj_op_name; + char *obj_name; + trav_attr_udata_t *attr_data = (trav_attr_udata_t*)_op_data; + const char *buf = attr_data->path; + const char *op_name = attr_data->op_name; + + j = (int)HDstrlen(op_name) - 1; + /* find the last / */ + while(j >= 0) { + if(op_name[j] == '/' && (j == 0 || (j > 0 && op_name[j - 1] != '\\'))) + break; + j--; + } + + obj_op_name = h5tools_str_replace(op_name + j + 1, "\\/", "/"); + + if(obj_op_name == NULL) { + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + if(HDstrcmp(attr_name, obj_op_name)==0) { + size_t u, v, w; + + /* object name */ + u = HDstrlen(buf); + v = HDstrlen(op_name); + w = u + 1 + v + 1 + 2; + obj_name = (char *)HDmalloc(w); + if(obj_name == NULL) { + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + HDmemset(obj_name, '\0', w); + if(op_name[0] != '/') { + HDstrncat(obj_name, buf, u + 1); + if(buf[u - 1] != '/') + HDstrncat(obj_name, "/", (size_t)2); + } + HDstrncat(obj_name, op_name, v + 1); + + handle_attributes(oid, obj_name, NULL, 0, NULL); + HDfree(obj_name); + } + } + HDfree(obj_op_name); + } + return ret; +} /* end attr_search() */ + +static herr_t +obj_search(const char *path, const H5O_info_t *oi, const char H5_ATTR_UNUSED *already_visited, void *_op_data) +{ + trav_handle_udata_t *handle_data = (trav_handle_udata_t*)_op_data; + const char *op_name = handle_data->op_name; + trav_attr_udata_t attr_data; + + attr_data.path = path; + attr_data.op_name = op_name; + H5Aiterate_by_name(handle_data->fid, path, H5_INDEX_NAME, H5_ITER_INC, NULL, attr_search, (void*)&attr_data, H5P_DEFAULT); + + if(HDstrcmp(path, op_name) == 0) { + switch(oi->type) { + case H5O_TYPE_GROUP: + handle_groups(handle_data->fid, path, NULL, 0, NULL); + break; + + case H5O_TYPE_DATASET: + handle_datasets(handle_data->fid, path, NULL, 0, NULL); + break; + + case H5O_TYPE_NAMED_DATATYPE: + handle_datatypes(handle_data->fid, path, NULL, 0, NULL); + break; + + case H5O_TYPE_UNKNOWN: + case H5O_TYPE_NTYPES: + default: + error_msg("unknown object type value\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end switch */ + } + + return 0; +} /* end obj_search() */ + +static herr_t +lnk_search(const char *path, const H5L_info_t *li, void *_op_data) +{ + size_t search_len; + size_t k; + char *search_name; + trav_handle_udata_t *handle_data = (trav_handle_udata_t*)_op_data; + const char *op_name = handle_data->op_name; + + search_len = HDstrlen(op_name); + if(search_len > 0 && op_name[0] != '/') + k = 2; + else + k = 1; + search_name = (char *)HDmalloc(search_len + k); + if(search_name == NULL) { + error_msg("creating temporary link\n"); + h5tools_setstatus(EXIT_FAILURE); + } + else { + if (k == 2) { + HDstrcpy(search_name, "/"); + HDstrncat(search_name, op_name, search_len + 1); + } + else + HDstrncpy(search_name, op_name, search_len + 1); + search_name[search_len + k - 1] = '\0'; + + if(HDstrcmp(path, search_name) == 0) { + switch(li->type) { + case H5L_TYPE_SOFT: + case H5L_TYPE_EXTERNAL: + handle_links(handle_data->fid, op_name, NULL, 0, NULL); + break; + + case H5L_TYPE_HARD: + case H5L_TYPE_MAX: + case H5L_TYPE_ERROR: + default: + error_msg("unknown link type value\n"); + h5tools_setstatus(EXIT_FAILURE); + break; + } /* end switch() */ + } + HDfree(search_name); + } + return 0; +} /* end lnk_search() */ + +/*------------------------------------------------------------------------- + * Function: handle_paths + * + * Purpose: Handle objects from the command. + * + * Return: void + * + *------------------------------------------------------------------------- + */ +void +handle_paths(hid_t fid, const char *path_name, void H5_ATTR_UNUSED * data, int H5_ATTR_UNUSED pe, const char H5_ATTR_UNUSED *display_name) +{ + hid_t gid = -1; + + if((gid = H5Gopen2(fid, "/", H5P_DEFAULT)) < 0) { + error_msg("unable to open root group\n"); + h5tools_setstatus(EXIT_FAILURE); + } + else { + hid_t gcpl_id; + unsigned crt_order_flags; + unsigned attr_crt_order_flags; + trav_handle_udata_t handle_udata; /* User data for traversal */ + + if ((gcpl_id = H5Gget_create_plist(gid)) < 0) { + error_msg("error in getting group creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the group creation properties for attributes */ + if (H5Pget_attr_creation_order(gcpl_id, &attr_crt_order_flags) < 0) { + error_msg("error in getting group creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the group creation properties */ + if(H5Pget_link_creation_order(gcpl_id, &crt_order_flags) < 0) { + error_msg("error in getting group creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + if(H5Pclose(gcpl_id) < 0) { + error_msg("error in closing group creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + handle_udata.fid = fid; + handle_udata.op_name = path_name; + if(h5trav_visit(fid, "/", TRUE, TRUE, obj_search, lnk_search, &handle_udata) < 0) { + error_msg("error traversing information\n"); + h5tools_setstatus(EXIT_FAILURE); + } + } +} + +/*------------------------------------------------------------------------- + * Function: handle_attributes + * + * Purpose: Handle the attributes from the command. + * + * Return: void + * + * Programmer: Bill Wendling + * Tuesday, 9. January 2001 + * + * Modifications: + * + * PVN, May 2008 + * add an extra parameter PE, to allow printing/not printing of error messages + * + *------------------------------------------------------------------------- + */ +void +handle_attributes(hid_t fid, const char *attr, void H5_ATTR_UNUSED * data, int H5_ATTR_UNUSED pe, const char H5_ATTR_UNUSED *display_name) +{ + hid_t oid = -1; + hid_t attr_id = -1; + char *obj_name = NULL; + char *attr_name = NULL; + int j; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &h5tools_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + j = (int)HDstrlen(attr) - 1; + obj_name = (char *)HDmalloc((size_t)j + 2); + if(obj_name == NULL) + goto error; + + /* find the last / */ + while(j >= 0) { + if (attr[j] == '/' && (j==0 || (j>0 && attr[j-1]!='\\'))) + break; + j--; + } + + /* object name */ + if(j == -1) + HDstrcpy(obj_name, "/"); + else { + HDstrncpy(obj_name, attr, (size_t)j + 1); + obj_name[j + 1] = '\0'; + } /* end else */ + + dump_indent += COL; + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + attr_name = h5tools_str_replace(attr + j + 1, "\\/", "/"); + + /* handle error case: cannot open the object with the attribute */ + if((oid = H5Oopen(fid, obj_name, H5P_DEFAULT)) < 0) { + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->attributebegin, attr, + h5tools_dump_header_format->attributeblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + error_msg("unable to open object \"%s\"\n", obj_name); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->attributeblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->attributeblockend); + if(HDstrlen(h5tools_dump_header_format->attributeend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->attributeend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->attributeend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); + + goto error; + } /* end if */ + + attr_id = H5Aopen(oid, attr_name, H5P_DEFAULT); + oid_output = display_oid; + data_output = display_data; + attr_data_output = display_attr_data; + + h5dump_type_table = type_table; + h5tools_dump_attribute(rawoutstream, outputformat, &ctx, attr_name, attr_id, display_ai, display_char); + h5dump_type_table = NULL; + + if(attr_id < 0) { + goto error; + } + + /* Close object */ + if(H5Oclose(oid) < 0) { + goto error; + } /* end if */ + + HDfree(obj_name); + HDfree(attr_name); + dump_indent -= COL; + return; + +error: + h5tools_setstatus(EXIT_FAILURE); + if(obj_name) + HDfree(obj_name); + + if (attr_name) + HDfree(attr_name); + + H5E_BEGIN_TRY { + H5Oclose(oid); + H5Aclose(attr_id); + } H5E_END_TRY; + dump_indent -= COL; +} + +/*------------------------------------------------------------------------- + * Function: handle_datasets + * + * Purpose: Handle the datasets from the command. + * + * Return: void + * + * Programmer: Bill Wendling + * Tuesday, 9. January 2001 + * + * Modifications: + * Pedro Vicente, Tuesday, January 15, 2008 + * check for block overlap\ + * + * Pedro Vicente, May 8, 2008 + * added a flag PE that prints/not prints error messages + * added for cases of external links not found, to avoid printing of + * objects not found, since external links are dumped on a trial error basis + * + *------------------------------------------------------------------------- + */ +void +handle_datasets(hid_t fid, const char *dset, void *data, int pe, const char *display_name) +{ + H5O_info_t oinfo; + hid_t dsetid; + hid_t dapl_id = H5P_DEFAULT; /* dataset access property list ID */ + struct subset_t *sset = (struct subset_t *)data; + const char *real_name = display_name ? display_name : dset; + + if(display_data) { + if ((dapl_id = H5Pcreate(H5P_DATASET_ACCESS)) < 0) { + error_msg("error in creating default access property list ID\n"); + } + if (display_vds_first) { + if(H5Pset_virtual_view(dapl_id, H5D_VDS_FIRST_MISSING) < 0) + error_msg("error in setting access property list ID, virtual_view\n"); + } + if (vds_gap_size > 0) { + if(H5Pset_virtual_printf_gap(dapl_id, (hsize_t)vds_gap_size) < 0) + error_msg("error in setting access property list ID, virtual_printf_gap\n"); + } + } + if((dsetid = H5Dopen2(fid, dset, dapl_id)) < 0) { + if (pe) + handle_links(fid, dset, data, pe, display_name); + return; + } /* end if */ + + if(sset) { + unsigned int i; + unsigned int ndims; + hid_t sid = H5Dget_space(dsetid); + int ndims_res = H5Sget_simple_extent_ndims(sid); + + H5Sclose(sid); + if(ndims_res < 0) { + error_msg("H5Sget_simple_extent_ndims failed\n"); + h5tools_setstatus(EXIT_FAILURE); + return; + } + ndims = (unsigned)ndims_res; + + if(!sset->start.data || !sset->stride.data || !sset->count.data || !sset->block.data) { + /* they didn't specify a ``stride'' or ``block''. default to 1 in all + * dimensions */ + if(!sset->start.data) { + /* default to (0, 0, ...) for the start coord */ + sset->start.data = (hsize_t *)HDcalloc((size_t)ndims, sizeof(hsize_t)); + sset->start.len = ndims; + } + + if(!sset->stride.data) { + sset->stride.data = (hsize_t *)HDcalloc((size_t)ndims, sizeof(hsize_t)); + sset->stride.len = ndims; + for (i = 0; i < ndims; i++) + sset->stride.data[i] = 1; + } + + if(!sset->count.data) { + sset->count.data = (hsize_t *)HDcalloc((size_t)ndims, sizeof(hsize_t)); + sset->count.len = ndims; + for (i = 0; i < ndims; i++) + sset->count.data[i] = 1; + } + + if(!sset->block.data) { + sset->block.data = (hsize_t *)HDcalloc((size_t)ndims, sizeof(hsize_t)); + sset->block.len = ndims; + for (i = 0; i < ndims; i++) + sset->block.data[i] = 1; + } + } + + /*------------------------------------------------------------------------- + * check for dimension overflow + *------------------------------------------------------------------------- + */ + if(sset->start.len > ndims) { + error_msg("number of start dims (%u) exceed dataset dims (%u)\n", sset->start.len, ndims); + h5tools_setstatus(EXIT_FAILURE); + return; + } + if(sset->stride.len > ndims) { + error_msg("number of stride dims (%u) exceed dataset dims (%u)\n", sset->stride.len, ndims); + h5tools_setstatus(EXIT_FAILURE); + return; + } + if(sset->count.len > ndims) { + error_msg("number of count dims (%u) exceed dataset dims (%u)\n", sset->count.len, ndims); + h5tools_setstatus(EXIT_FAILURE); + return; + } + if(sset->block.len > ndims) { + error_msg("number of block dims (%u) exceed dataset dims (%u)\n", sset->block.len, ndims); + h5tools_setstatus(EXIT_FAILURE); + return; + } + + /*------------------------------------------------------------------------- + * check for block overlap + *------------------------------------------------------------------------- + */ + for(i = 0; i < ndims; i++) { + if(sset->count.data[i] > 1) { + if(sset->stride.data[i] < sset->block.data[i]) { + error_msg("wrong subset selection; blocks overlap\n"); + h5tools_setstatus(EXIT_FAILURE); + return; + } /* end if */ + } /* end if */ + } /* end for */ + } /* end if */ + + + H5Oget_info(dsetid, &oinfo); + if(oinfo.rc > 1 || hit_elink) { + obj_t *found_obj; /* Found object */ + + found_obj = search_obj(dset_table, oinfo.addr); + + if(found_obj) { + if (found_obj->displayed) { + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(dump_indent); + begin_obj(h5tools_dump_header_format->datasetbegin, real_name, h5tools_dump_header_format->datasetblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(dump_indent + COL); + PRINTSTREAM(rawoutstream, "%s \"%s\"\n", HARDLINK, found_obj->objname); + indentation(dump_indent); + end_obj(h5tools_dump_header_format->datasetend, h5tools_dump_header_format->datasetblockend); + } + else { + found_obj->displayed = TRUE; + dump_indent += COL; + dump_dataset(dsetid, real_name, sset); + dump_indent -= COL; + } + } + else + h5tools_setstatus(EXIT_FAILURE); + } + else { + dump_indent += COL; + dump_dataset(dsetid, real_name, sset); + dump_indent -= COL; + } + if (dapl_id != H5P_DEFAULT) + H5Pclose(dapl_id); + if(H5Dclose(dsetid) < 0) + h5tools_setstatus(EXIT_FAILURE); +} + +/*------------------------------------------------------------------------- + * Function: handle_groups + * + * Purpose: Handle the groups from the command. + * + * Return: void + * + * Programmer: Bill Wendling + * Tuesday, 9. January 2001 + * + * Modifications: Pedro Vicente, September 26, 2007 + * handle creation order + * + * Pedro Vicente, May 8, 2008 + * added a flag PE that prints/not prints error messages + * added for cases of external links not found, to avoid printing of + * objects not found, since external links are dumped on a trial error basis + * + *------------------------------------------------------------------------- + */ +void +handle_groups(hid_t fid, const char *group, void H5_ATTR_UNUSED *data, int pe, const char *display_name) +{ + hid_t gid; + const char *real_name = display_name ? display_name : group; + + if((gid = H5Gopen2(fid, group, H5P_DEFAULT)) < 0) { + if (pe) { + PRINTVALSTREAM(rawoutstream, "\n"); + begin_obj(h5tools_dump_header_format->groupbegin, real_name, h5tools_dump_header_format->groupblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(COL); + error_msg("unable to open group \"%s\"\n", real_name); + end_obj(h5tools_dump_header_format->groupend, h5tools_dump_header_format->groupblockend); + h5tools_setstatus(EXIT_FAILURE); + } + } + else { + size_t new_len = HDstrlen(group) + 1; + + if(prefix_len <= new_len) { + prefix_len = new_len; + prefix = (char *)HDrealloc(prefix, prefix_len); + } /* end if */ + + HDstrcpy(prefix, group); + + dump_indent += COL; + dump_group(gid, real_name); + dump_indent -= COL; + + if(H5Gclose(gid) < 0) + h5tools_setstatus(EXIT_FAILURE); + } /* end else */ +} /* end handle_groups() */ + +/*------------------------------------------------------------------------- + * Function: handle_links + * + * Purpose: Handle soft or UD links from the command. + * + * Return: void + * + * Programmer: Bill Wendling + * Tuesday, 9. January 2001 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +handle_links(hid_t fid, const char *links, void H5_ATTR_UNUSED * data, int H5_ATTR_UNUSED pe, const char H5_ATTR_UNUSED *display_name) +{ + H5L_info_t linfo; + + if(H5Lget_info(fid, links, &linfo, H5P_DEFAULT) < 0) { + error_msg("unable to get link info from \"%s\"\n", links); + h5tools_setstatus(EXIT_FAILURE); + } + else if(linfo.type == H5L_TYPE_HARD) { + error_msg("\"%s\" is a hard link\n", links); + h5tools_setstatus(EXIT_FAILURE); + } + else { + char *buf = (char *)HDmalloc(linfo.u.val_size); + PRINTVALSTREAM(rawoutstream, "\n"); + + switch(linfo.type) { + case H5L_TYPE_SOFT: /* Soft link */ + begin_obj(h5tools_dump_header_format->softlinkbegin, links, h5tools_dump_header_format->softlinkblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(COL); + if(H5Lget_val(fid, links, buf, linfo.u.val_size, H5P_DEFAULT) >= 0) { + PRINTSTREAM(rawoutstream, "LINKTARGET \"%s\"\n", buf); + } + else { + error_msg("h5dump error: unable to get link value for \"%s\"\n", links); + h5tools_setstatus(EXIT_FAILURE); + } + end_obj(h5tools_dump_header_format->softlinkend, h5tools_dump_header_format->softlinkblockend); + break; + + case H5L_TYPE_EXTERNAL: + begin_obj(h5tools_dump_header_format->udlinkbegin, links, h5tools_dump_header_format->udlinkblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(COL); + begin_obj(h5tools_dump_header_format->extlinkbegin, links, h5tools_dump_header_format->extlinkblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + if(H5Lget_val(fid, links, buf, linfo.u.val_size, H5P_DEFAULT) >= 0) { + const char *elink_file; + const char *elink_path; + + if(H5Lunpack_elink_val(buf, linfo.u.val_size, NULL, &elink_file, &elink_path)>=0) { + indentation(COL); + PRINTSTREAM(rawoutstream, "LINKCLASS %d\n", linfo.type); + indentation(COL); + PRINTSTREAM(rawoutstream, "TARGETFILE \"%s\"\n", elink_file); + indentation(COL); + PRINTSTREAM(rawoutstream, "TARGETPATH \"%s\"\n", elink_path); + } + else { + error_msg("h5dump error: unable to unpack external link value for \"%s\"\n", links); + h5tools_setstatus(EXIT_FAILURE); + } + } + else { + error_msg("h5dump error: unable to get external link value for \"%s\"\n", links); + h5tools_setstatus(EXIT_FAILURE); + } + end_obj(h5tools_dump_header_format->extlinkend, h5tools_dump_header_format->extlinkblockend); + break; + + case H5L_TYPE_ERROR: + case H5L_TYPE_MAX: + HDassert(0); + /* fall through */ + case H5L_TYPE_HARD: + default: + begin_obj(h5tools_dump_header_format->udlinkbegin, links, h5tools_dump_header_format->udlinkblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(COL); + begin_obj(h5tools_dump_header_format->udlinkbegin, links, h5tools_dump_header_format->udlinkblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(COL); + PRINTSTREAM(rawoutstream, "LINKCLASS %d\n", linfo.type); + end_obj(h5tools_dump_header_format->udlinkend, h5tools_dump_header_format->udlinkblockend); + break; + } /* end switch */ + HDfree(buf); + } /* end else */ +} + +/*------------------------------------------------------------------------- + * Function: handle_datatypes + * + * Purpose: Handle the datatypes from the command. + * + * Return: void + * + * Programmer: Bill Wendling + * Tuesday, 9. January 2001 + * + * Modifications: + * + * Pedro Vicente, May 8, 2008 + * added a flag PE that prints/not prints error messages + * added for cases of external links not found, to avoid printing of + * objects not found, since external links are dumped on a trial error basis + * + *------------------------------------------------------------------------- + */ +void +handle_datatypes(hid_t fid, const char *type, void H5_ATTR_UNUSED * data, int pe, const char *display_name) +{ + hid_t type_id; + const char *real_name = display_name ? display_name : type; + + if((type_id = H5Topen2(fid, type, H5P_DEFAULT)) < 0) { + /* check if type is unamed datatype */ + unsigned idx = 0; + + while(idx < type_table->nobjs ) { + char name[128]; + + if(!type_table->objs[idx].recorded) { + /* unamed datatype */ + sprintf(name, "/#"H5_PRINTF_HADDR_FMT, type_table->objs[idx].objno); + + if(!HDstrcmp(name, real_name)) + break; + } /* end if */ + + idx++; + } /* end while */ + + if(idx == type_table->nobjs) { + if (pe) { + /* unknown type */ + PRINTVALSTREAM(rawoutstream, "\n"); + begin_obj(h5tools_dump_header_format->datatypebegin, real_name, h5tools_dump_header_format->datatypeblockbegin); + PRINTVALSTREAM(rawoutstream, "\n"); + indentation(COL); + error_msg("unable to open datatype \"%s\"\n", real_name); + end_obj(h5tools_dump_header_format->datatypeend, h5tools_dump_header_format->datatypeblockend); + h5tools_setstatus(EXIT_FAILURE); + } + } + else { + hid_t dsetid = H5Dopen2(fid, type_table->objs[idx].objname, H5P_DEFAULT); + type_id = H5Dget_type(dsetid); + + dump_indent += COL; + dump_named_datatype(type_id, real_name); + dump_indent -= COL; + + H5Tclose(type_id); + H5Dclose(dsetid); + } + } + else { + dump_indent += COL; + dump_named_datatype(type_id, real_name); + dump_indent -= COL; + + if(H5Tclose(type_id) < 0) + h5tools_setstatus(EXIT_FAILURE); + } +} + + +/*------------------------------------------------------------------------- + * Function: dump_extlink + * + * made by: PVN + * + * Purpose: Dump an external link + * Since external links are soft links, they are dumped on a trial error + * basis, attempting to dump as a dataset, as a group and as a named datatype + * Error messages are supressed + * + * Modifications: + * Neil Fortner + * 13 October 2008 + * Function basically rewritten. No longer directly opens the target file, + * now initializes a new set of tables for the external file. No longer + * dumps on a trial and error basis, but errors are still suppressed. + * + *------------------------------------------------------------------------- + */ +static int +dump_extlink(hid_t group, const char *linkname, const char *objname) +{ + hid_t oid; + H5O_info_t oi; + table_t *old_group_table = group_table; + table_t *old_dset_table = dset_table; + table_t *old_type_table = type_table; + hbool_t old_hit_elink; + ssize_t idx; + + /* Open target object */ + if ((oid = H5Oopen(group, linkname, H5P_DEFAULT)) < 0) + goto fail; + + /* Get object info */ + if (H5Oget_info(oid, &oi) < 0) { + H5Oclose(oid); + goto fail; + } + + /* Check if we have visited this file already */ + if ((idx = table_list_visited(oi.fileno)) < 0) { + /* We have not visited this file, build object tables */ + if ((idx = table_list_add(oid, oi.fileno)) < 0) { + H5Oclose(oid); + goto fail; + } + } + + /* Do not recurse through an external link into the original file (idx=0) */ + if (idx) { + /* Update table pointers */ + group_table = table_list.tables[idx].group_table; + dset_table = table_list.tables[idx].dset_table; + type_table = table_list.tables[idx].type_table; + + /* We will now traverse the external link, set this global to indicate this */ + old_hit_elink = hit_elink; + hit_elink = TRUE; + + /* add some indentation to distinguish that these objects are external */ + dump_indent += COL; + + /* Recurse into the external file */ + switch (oi.type) { + case H5O_TYPE_GROUP: + handle_groups(group, linkname, NULL, 0, objname); + break; + + case H5O_TYPE_DATASET: + handle_datasets(group, linkname, NULL, 0, objname); + break; + + case H5O_TYPE_NAMED_DATATYPE: + handle_datatypes(group, linkname, NULL, 0, objname); + break; + + case H5O_TYPE_UNKNOWN: + case H5O_TYPE_NTYPES: + default: + h5tools_setstatus(EXIT_FAILURE); + } + + dump_indent -= COL; + + /* Reset table pointers */ + group_table = old_group_table; + dset_table = old_dset_table; + type_table = old_type_table; + + /* Reset hit_elink */ + hit_elink = old_hit_elink; + } /* end if */ + + if (H5Idec_ref(oid) < 0) + h5tools_setstatus(EXIT_FAILURE); + + return SUCCEED; + +fail: + return FAIL; +} + diff --git a/tools/src/h5dump/h5dump_ddl.h b/tools/src/h5dump/h5dump_ddl.h new file mode 100644 index 0000000..2b3f61e --- /dev/null +++ b/tools/src/h5dump/h5dump_ddl.h @@ -0,0 +1,52 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef H5DUMP_DDL_H__ +#define H5DUMP_DDL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* The dump functions of the dump_function_table */ +/* standard format: no change */ +void dump_group(hid_t, const char *); +void dump_named_datatype(hid_t, const char *); +void dump_dataset(hid_t, const char *, struct subset_t *); +void dump_dataspace(hid_t space); +void dump_datatype(hid_t type); +void dump_data(hid_t, int, struct subset_t *, int); +void dump_fcpl(hid_t fid); +void dump_fcontents(hid_t fid); + +/* callback function used by H5Aiterate2() */ +herr_t dump_attr_cb(hid_t loc_id, const char *attr_name, const H5A_info_t *info, void *_op_data); + +/* other iteration functions */ +void link_iteration(hid_t gid, unsigned crt_order_flags); +void attr_iteration(hid_t gid, unsigned attr_crt_order_flags); + +void handle_paths(hid_t fid, const char *path_name, void *data, int pe, const char *display_name); +void handle_datasets(hid_t fid, const char *dset, void *data, int pe, const char *display_name); +void handle_attributes(hid_t fid, const char *attr, void H5_ATTR_UNUSED * data, int H5_ATTR_UNUSED pe, const char H5_ATTR_UNUSED *display_name); +void handle_groups(hid_t fid, const char *group, void H5_ATTR_UNUSED *data, int pe, const char *display_name); +void handle_links(hid_t fid, const char *links, void H5_ATTR_UNUSED * data, int H5_ATTR_UNUSED pe, const char H5_ATTR_UNUSED *display_name); +void handle_datatypes(hid_t fid, const char *type, void H5_ATTR_UNUSED * data, int pe, const char *display_name); + +#ifdef __cplusplus +} +#endif + +#endif /* !H5DUMP_DDL_H__ */ diff --git a/tools/src/h5dump/h5dump_defines.h b/tools/src/h5dump/h5dump_defines.h new file mode 100644 index 0000000..2be2dcc --- /dev/null +++ b/tools/src/h5dump/h5dump_defines.h @@ -0,0 +1,56 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#ifndef H5DUMP_DEFINES_H__ +#define H5DUMP_DEFINES_H__ + +#define H5DUMP_MAX_RANK H5S_MAX_RANK + +#define ATTRIBUTE_DATA 0 +#define DATASET_DATA 1 +#define ENUM_DATA 2 +#define COL 3 + +/* Macros for displaying objects */ +#define begin_obj(obj,name,begin) \ + do { \ + if ((name)) { \ + PRINTSTREAM(rawoutstream, "%s \"%s\" %s", (obj), (name), (begin)); \ + } \ + else { \ + PRINTSTREAM(rawoutstream, "%s %s", (obj), (begin)); \ + } \ + } while(0); + +#define end_obj(obj,end) \ + do { \ + if(HDstrlen(end)) { \ + PRINTSTREAM(rawoutstream, "%s", end); \ + if(HDstrlen(obj)) \ + PRINTVALSTREAM(rawoutstream, " "); \ + } \ + if(HDstrlen(obj)) \ + PRINTSTREAM(rawoutstream, "%s", obj); \ + } while(0); + + +/* 3 private values: can't be set, but can be read. + Note: these are defined in H5Zprivate, they are + duplicated here. + */ +#define H5_SZIP_LSB_OPTION_MASK 8 +#define H5_SZIP_MSB_OPTION_MASK 16 +#define H5_SZIP_RAW_OPTION_MASK 128 + +#endif /* !H5DUMP_DEFINES_H__ */ diff --git a/tools/src/h5dump/h5dump_extern.h b/tools/src/h5dump/h5dump_extern.h new file mode 100644 index 0000000..8fef1b9 --- /dev/null +++ b/tools/src/h5dump/h5dump_extern.h @@ -0,0 +1,114 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#ifndef H5DUMP_EXTERN_H__ +#define H5DUMP_EXTERN_H__ + +#include "hdf5.h" +#include "H5private.h" +#include "h5tools.h" +#include "h5tools_utils.h" +#include "h5tools_ref.h" +#include "h5trav.h" +#include "h5dump_defines.h" + +/** + ** This is the global dispatch table for the dump functions. + **/ +/* the table of dump functions */ +typedef struct dump_functions_t { + void (*dump_group_function) (hid_t, const char *); + void (*dump_named_datatype_function) (hid_t, const char *); + void (*dump_dataset_function) (hid_t, const char *, struct subset_t *); + void (*dump_dataspace_function) (hid_t); + void (*dump_datatype_function) (hid_t); + herr_t (*dump_attribute_function) (hid_t, const char *, const H5A_info_t *, void *); + void (*dump_data_function) (hid_t, int, struct subset_t *, int); +} dump_functions; + +/* List of table structures. There is one table structure for each file */ +typedef struct h5dump_table_list_t { + size_t nalloc; + size_t nused; + struct { + unsigned long fileno; /* File number that these tables refer to */ + hid_t oid; /* ID of an object in this file, held open so fileno is consistent */ + table_t *group_table; /* Table of groups */ + table_t *dset_table; /* Table of datasets */ + table_t *type_table; /* Table of datatypes */ + } *tables; +} h5dump_table_list_t; + +extern h5dump_table_list_t table_list; +extern table_t *group_table, *dset_table, *type_table; +extern unsigned dump_indent; /*how far in to indent the line */ + +extern int unamedtype; /* shared datatype with no name */ +extern hbool_t hit_elink; /* whether we have traversed an external link */ +extern size_t prefix_len; +extern char *prefix; +extern const char *fp_format; + +/* things to display or which are set via command line parameters */ +extern int display_all; +extern int display_oid; +extern int display_data; +extern int display_attr_data; +extern int display_char; /*print 1-byte numbers as ASCII */ +extern int usingdasho; +extern int display_bb; /*superblock */ +extern int display_dcpl; /*dcpl */ +extern int display_fi; /*file index */ +extern int display_ai; /*array index */ +extern int display_escape; /*escape non printable characters */ +extern int display_region; /*print region reference data */ +extern int disable_compact_subset; /* disable compact form of subset notation */ +extern int display_packed_bits; /*print 1-8 byte numbers as packed bits*/ +extern int include_attrs; /* Display attributes */ +extern int display_vds_first; /* vds display to first missing */ +extern int vds_gap_size; /* vds skip missing files */ + +/* sort parameters */ +extern H5_index_t sort_by; /*sort_by [creation_order | name] */ +extern H5_iter_order_t sort_order; /*sort_order [ascending | descending] */ + +#define PACKED_BITS_MAX 8 /* Maximum number of packed-bits to display */ +#define PACKED_BITS_SIZE_MAX 8*sizeof(long long) /* Maximum bits size of integer types of packed-bits */ +/* mask list for packed bits */ +extern unsigned long long packed_mask[PACKED_BITS_MAX]; /* packed bits are restricted to 8*sizeof(llong) bytes */ + +/* packed bits display parameters */ +extern unsigned packed_offset[PACKED_BITS_MAX]; +extern unsigned packed_length[PACKED_BITS_MAX]; + +/* + * The global table is set to either ddl_function_table or + * xml_function_table in the initialization. + */ +extern const dump_functions *dump_function_table; + +#ifdef __cplusplus +extern "C" { +#endif + +void add_prefix(char **prfx, size_t *prfx_len, const char *name); +hid_t h5_fileaccess(void); +ssize_t table_list_add(hid_t oid, unsigned long file_no); +ssize_t table_list_visited(unsigned long file_no); + +#ifdef __cplusplus +} +#endif + +#endif /* !H5DUMP_EXTERN_H__ */ diff --git a/tools/src/h5dump/h5dump_xml.c b/tools/src/h5dump/h5dump_xml.c new file mode 100644 index 0000000..41f3914 --- /dev/null +++ b/tools/src/h5dump/h5dump_xml.c @@ -0,0 +1,4567 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#include <stdio.h> +#include <stdlib.h> + +#include "H5private.h" +#include "h5tools.h" +#include "h5tools_dump.h" +#include "h5tools_utils.h" +#include "h5tools_ref.h" +#include "h5trav.h" +#include "h5dump_extern.h" +#include "h5dump_xml.h" + +const char *xmlnsprefix="hdf5:"; + +/* + * Alternative formating for data dumped to XML + * In general, the numbers are the same, but separators + * except spaces are not used. + * + * Some of these are not used, as some kinds of data are + * dumped in completely new subroutines. + * + * Some of this formatting may yet need to change. + * + * This table only affects XML output. + */ +static h5tool_format_t xml_dataformat = { + 0, /*raw */ + + "", /*fmt_raw */ + "%d", /*fmt_int */ + "%u", /*fmt_uint */ + "%hhd", /*fmt_schar */ + "%u", /*fmt_uchar */ + "%d", /*fmt_short */ + "%u", /*fmt_ushort */ + "%ld", /*fmt_long */ + "%lu", /*fmt_ulong */ + NULL, /*fmt_llong */ + NULL, /*fmt_ullong */ + "%g", /*fmt_double */ + "%g", /*fmt_float */ + + 0, /*ascii */ + 0, /*str_locale */ + 0, /*str_repeat */ + + "", /*arr_pre */ + "", /*arr_sep */ + "", /*arr_suf */ + 1, /*arr_linebreak */ + + "", /*cmpd_name */ + "", /*cmpd_sep */ + "", /*cmpd_pre */ + "", /*cmpd_suf */ + "", /*cmpd_end */ + + " ", /*vlen_sep */ + " ", /*vlen_pre */ + "", /*vlen_suf */ + "", /*vlen_end */ + + "%s", /*elmt_fmt */ + "", /*elmt_suf1 */ + " ", /*elmt_suf2 */ + + "", /*idx_n_fmt */ + "", /*idx_sep */ + "", /*idx_fmt */ + + 80, /*line_ncols *//*standard default columns */ + 0, /*line_per_line */ + "", /*line_pre */ + "%s", /*line_1st */ + "%s", /*line_cont */ + "", /*line_suf */ + "", /*line_sep */ + 1, /*line_multi_new */ + " ", /*line_indent */ + + 1, /*skip_first */ + + 1, /*obj_hidefileno */ + " "H5_PRINTF_HADDR_FMT, /*obj_format */ + + 1, /*dset_hidefileno */ + "DATASET %s ", /*dset_format */ + "%s", /*dset_blockformat_pre */ + "%s", /*dset_ptformat_pre */ + "%s", /*dset_ptformat */ + 0, /*array indices */ + 0 /*escape non printable characters */ +}; + + +/* internal functions */ +static int xml_name_to_XID(const char *, char *, int , int ); + +/* internal functions used by XML option */ +static void xml_print_datatype(hid_t, unsigned); +static void xml_print_enum(hid_t); +static int xml_print_refs(hid_t, int); +static int xml_print_strs(hid_t, int); +static char *xml_escape_the_string(const char *, int); +static char *xml_escape_the_name(const char *); + +/*------------------------------------------------------------------------- + * Function: xml_dump_all_cb + * + * Purpose: function callback called by H5Literate, + * displays everything in the specified object + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Ruey-Hsia Li + * + * Modifications: + * RMcG, November 2000 + * Added XML support. Also, optionally checks the op_data argument + * + * PVN, May 2008 + * Dump external links + * + *------------------------------------------------------------------------- + */ +static herr_t +xml_dump_all_cb(hid_t group, const char *name, const H5L_info_t *linfo, void H5_ATTR_UNUSED *op_data) +{ + hid_t obj; + herr_t ret = SUCCEED; + char *obj_path = NULL; /* Full path of object */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols==0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + /* Build the object's path name */ + obj_path = (char *)HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2); + if(!obj_path) { + ret = FAIL; + goto done; + } + + HDstrcpy(obj_path, prefix); + HDstrcat(obj_path, "/"); + HDstrcat(obj_path, name); + + if(linfo->type == H5L_TYPE_HARD) { + H5O_info_t oinfo; + + /* Stat the object */ + if(H5Oget_info_by_name(group, name, &oinfo, H5P_DEFAULT) < 0) { + error_msg("unable to get object information for \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + goto done; + } /* end if */ + + switch(oinfo.type) { + case H5O_TYPE_GROUP: + if((obj = H5Gopen2(group, name, H5P_DEFAULT)) < 0) { + error_msg("unable to dump group \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + char *old_prefix; /* Pointer to previous prefix */ + + /* Keep copy of prefix before iterating into group */ + old_prefix = HDstrdup(prefix); + HDassert(old_prefix); + + /* Append group name to prefix */ + add_prefix(&prefix, &prefix_len, name); + + /* Iterate into group */ + dump_function_table->dump_group_function(obj, name); + + /* Restore old prefix name */ + HDstrcpy(prefix, old_prefix); + HDfree(old_prefix); + + /* Close group */ + H5Gclose(obj); + } + break; + + case H5O_TYPE_DATASET: + if((obj = H5Dopen2(group, name, H5P_DEFAULT)) >= 0) { + if(oinfo.rc > 1 || hit_elink) { + obj_t *found_obj; /* Found object */ + + found_obj = search_obj(dset_table, oinfo.addr); + + if(found_obj == NULL) { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s \"%s\" %s", + h5tools_dump_header_format->datasetbegin, name, + h5tools_dump_header_format->datasetblockbegin); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(HDstrlen(h5tools_dump_header_format->datasetblockend)) { + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetblockend); + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, " "); + } + if(HDstrlen(h5tools_dump_header_format->datasetend)) + h5tools_str_append(&buffer, "%s", h5tools_dump_header_format->datasetend); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + H5Dclose(obj); + goto done; + } + else if(found_obj->displayed) { + /* the XML version */ + char *t_obj_path = xml_escape_the_name(obj_path); + char *t_prefix = xml_escape_the_name(HDstrcmp(prefix,"") ? prefix : "/"); + char *t_name = xml_escape_the_name(name); + char *t_objname = xml_escape_the_name(found_obj->objname); + char dsetxid[100]; + char parentxid[100]; + char pointerxid[100]; + + /* Create OBJ-XIDs for the parent and object */ + xml_name_to_XID(obj_path, dsetxid, (int)sizeof(dsetxid), 1); + xml_name_to_XID(prefix, parentxid, (int)sizeof(parentxid), 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataset Name=\"%s\" OBJ-XID=\"%s-%d\" " + "H5Path=\"%s\" Parents=\"%s\" " + "H5ParentPaths=\"%s\">", + xmlnsprefix, + t_name, /* Dataset Name */ + dsetxid, get_next_xid(), /* OBJ-XID */ + t_obj_path, /* H5Path */ + parentxid, /* Parents */ + t_prefix); /* H5ParentPaths */ + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + xml_name_to_XID(found_obj->objname, pointerxid, (int)sizeof(pointerxid), 1); + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDatasetPtr OBJ-XID=\"%s\" H5Path=\"%s\"/>", + xmlnsprefix, + pointerxid,t_objname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataset>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(t_name); + HDfree(t_obj_path); + HDfree(t_prefix); + HDfree(t_objname); + + H5Dclose(obj); + goto done; + } + else + found_obj->displayed = TRUE; + } /* end if */ + + dump_function_table->dump_dataset_function(obj, name, NULL); + H5Dclose(obj); + } + else { + error_msg("unable to dump dataset \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + break; + + case H5O_TYPE_NAMED_DATATYPE: + if((obj = H5Topen2(group, name, H5P_DEFAULT)) < 0) { + error_msg("unable to dump datatype \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + dump_function_table->dump_named_datatype_function(obj, name); + H5Tclose(obj); + } + break; + + case H5O_TYPE_UNKNOWN: + case H5O_TYPE_NTYPES: + default: + error_msg("unknown object \"%s\"\n", name); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + } /* end if */ + else { + char *targbuf; + + switch(linfo->type) { + case H5L_TYPE_SOFT: + targbuf = (char *)HDmalloc(linfo->u.val_size); + HDassert(targbuf); + + if(H5Lget_val(group, name, targbuf, linfo->u.val_size, H5P_DEFAULT) < 0) { + error_msg("unable to get link value\n"); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } + else { + /* print the value of a soft link */ + /* XML */ + char linkxid[100]; + char parentxid[100]; + char targetxid[100]; + char *t_prefix = xml_escape_the_name(HDstrcmp(prefix,"") ? prefix : "/"); + char *t_name = xml_escape_the_name(name); + char *t_targbuf = xml_escape_the_name(targbuf); + char *t_obj_path = xml_escape_the_name(obj_path); + char *t_link_path; + int res; + + t_link_path = (char *)HDmalloc(HDstrlen(prefix) + linfo->u.val_size + 1); + if(targbuf[0] == '/') + HDstrcpy(t_link_path, targbuf); + else { + HDstrcpy(t_link_path, prefix); + HDstrcat(HDstrcat(t_link_path, "/"), targbuf); + } /* end else */ + + /* Create OBJ-XIDs for the parent and object */ + xml_name_to_XID(t_obj_path, linkxid, (int)sizeof(linkxid), 1); + xml_name_to_XID(prefix, parentxid, (int)sizeof(parentxid), 1); + + /* Try to create an OBJ-XID for the object pointed to */ + res = xml_name_to_XID(t_link_path, targetxid, (int)sizeof(targetxid), 0); + if (res == 0) { + /* target obj found */ + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sSoftLink LinkName=\"%s\" " + "OBJ-XID=\"%s\" " + "H5SourcePath=\"%s\" " + "TargetPath=\"%s\" TargetObj=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\" />", + xmlnsprefix, + t_name, /* LinkName */ + linkxid, /* OBJ-XID */ + t_obj_path, /* H5SourcePath */ + t_targbuf, /* TargetPath */ + targetxid, /* TargetObj */ + parentxid, /* Parents */ + t_prefix); /* H5ParentPaths */ + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + /* dangling link -- omit from xml attributes */ + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sSoftLink LinkName=\"%s\" " + "OBJ-XID=\"%s\" " + "H5SourcePath=\"%s\" " + "TargetPath=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\" />", + xmlnsprefix, + t_name, /* LinkName */ + linkxid, /* OBJ-XID */ + t_obj_path, /* H5SourcePath */ + t_targbuf, /* TargetPath */ + parentxid, /* Parents */ + t_prefix); /* H5ParentPaths */ + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + + HDfree(t_prefix); + HDfree(t_name); + HDfree(t_targbuf); + HDfree(t_obj_path); + HDfree(t_link_path); + } + + HDfree(targbuf); + break; + + case H5L_TYPE_EXTERNAL: + targbuf = (char *)HDmalloc(linfo->u.val_size); + HDassert(targbuf); + + if(H5Lget_val(group, name, targbuf, linfo->u.val_size, H5P_DEFAULT) < 0) { + error_msg("unable to get external link value\n"); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } /* end if */ + else { + const char *filename; + const char *targname; + + if(H5Lunpack_elink_val(targbuf, linfo->u.val_size, NULL, &filename, &targname) < 0) { + error_msg("unable to unpack external link value\n"); + h5tools_setstatus(EXIT_FAILURE); + ret = FAIL; + } /* end if */ + else { + char linkxid[100]; + char parentxid[100]; + char *t_name = xml_escape_the_name(name); + char *t_prefix = xml_escape_the_name(HDstrcmp(prefix,"") ? prefix : "/"); + char *t_obj_path = xml_escape_the_name(obj_path); + char *t_filename = xml_escape_the_name(filename); + char *t_targname = xml_escape_the_name(targname); + + /* Create OBJ-XIDs for the parent and object */ + xml_name_to_XID(t_obj_path, linkxid, (int)sizeof(linkxid), 1); + xml_name_to_XID(prefix, parentxid, (int)sizeof(parentxid), 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sExternalLink LinkName=\"%s\" " + "OBJ-XID=\"%s\" " + "H5SourcePath=\"%s\" " + "TargetFilename=\"%s\" " + "TargetPath=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\" />", + xmlnsprefix, + t_name, /* LinkName */ + linkxid, /* OBJ-XID */ + t_obj_path, /* H5SourcePath */ + filename, /* TargetFilename */ + targname, /* TargetPath*/ + parentxid, /* Parents */ + t_prefix); /* H5ParentPaths */ + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(t_prefix); + HDfree(t_name); + HDfree(t_filename); + HDfree(t_targname); + HDfree(t_obj_path); + } /* end else */ + } /* end else */ + HDfree(targbuf); + break; + + case H5L_TYPE_ERROR: + case H5L_TYPE_MAX: + HDassert(0); + /* fall through */ + case H5L_TYPE_HARD: + default: + { + char linkxid[100]; + char parentxid[100]; + char *t_name = xml_escape_the_name(name); + char *t_prefix = xml_escape_the_name(HDstrcmp(prefix,"") ? prefix : "/"); + char *t_obj_path = xml_escape_the_name(obj_path); + + /* Create OBJ-XIDs for the parent and object */ + xml_name_to_XID(t_obj_path, linkxid, (int)sizeof(linkxid), 1); + xml_name_to_XID(prefix, parentxid, (int)sizeof(parentxid), 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sUserDefined LinkName=\"%s\" " + "OBJ-XID=\"%s\" " + "H5SourcePath=\"%s\" " + "LinkClass=\"%d\" " + "Parents=\"%s\" H5ParentPaths=\"%s\" />", + xmlnsprefix, + t_name, /* LinkName */ + linkxid, /* OBJ-XID */ + t_obj_path, /* H5SourcePath */ + linfo->type, /* LinkClass */ + parentxid, /* Parents */ + t_prefix); /* H5ParentPaths */ + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(t_prefix); + HDfree(t_name); + HDfree(t_obj_path); + } + break; + + } /* end switch */ + } /* end else */ + +done: + + h5tools_str_close(&buffer); + + if(obj_path) + HDfree(obj_path); + return ret; +} + +/* + * create a string suitable for and XML NCNAME. Uses the + * object reference to create the string. + * + * 'gen'; 0 - return null if not found + * 1 - generate a fake entry and return fake id. + */ +int +xml_name_to_XID(const char *str , char *outstr, int outlen, int gen) +{ + haddr_t objno; /* Object ID for object at path */ + + if (outlen < 22) return 1; + + objno = ref_path_table_lookup(str); + if (objno == HADDR_UNDEF) { + if (HDstrlen(str) == 0) { + objno = ref_path_table_lookup("/"); + if (objno == HADDR_UNDEF) { + if (gen) { + objno = ref_path_table_gen_fake(str); + sprintf(outstr, "xid_"H5_PRINTF_HADDR_FMT, objno); + return 0; + } + else { + return 1; + } + } + } + else { + if (gen) { + objno = ref_path_table_gen_fake(str); + sprintf(outstr, "xid_"H5_PRINTF_HADDR_FMT, objno); + return 0; + } + else { + return 1; + } + } + } + + sprintf(outstr, "xid_"H5_PRINTF_HADDR_FMT, objno); + + return(0); +} + +static const char *quote = """; +static const char *amp = "&"; +static const char *lt = "<"; +static const char *gt = ">"; +static const char *apos = "'"; + +/*------------------------------------------------------------------------- + * Function: xml_escape_the_name + * + * Purpose: Escape XML reserved chars in a name, so HDF5 strings + * and paths can be correctly read back in XML element. + * + * Return: The revised string. + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static char * +xml_escape_the_name(const char *str) +{ + size_t extra; + size_t len; + size_t i; + const char *cp; + char *ncp; + char *rcp; + size_t ncp_len; + + if (!str) + return NULL; + + cp = str; + len = HDstrlen(str); + extra = 0; + + for (i = 0; i < len; i++) { + if (*cp == '\"') + extra += (HDstrlen(quote) - 1); + else if (*cp == '\'') + extra += (HDstrlen(apos) - 1); + else if (*cp == '<') + extra += (HDstrlen(lt) - 1); + else if (*cp == '>') + extra += (HDstrlen(gt) - 1); + else if (*cp == '&') + extra += (HDstrlen(amp) - 1); + + cp++; + } + + if (extra == 0) + return HDstrdup(str); + + cp = str; + ncp_len = len + extra + 1; + rcp = ncp = (char *)HDmalloc(ncp_len); + + if (!ncp) + return NULL; /* ?? */ + + for (i = 0; i < len; i++) { + size_t esc_len; + + HDassert(ncp_len); + if (*cp == '\'') { + HDstrncpy(ncp, apos, ncp_len); + esc_len = HDstrlen(apos); + } + else if (*cp == '<') { + HDstrncpy(ncp, lt, ncp_len); + esc_len = HDstrlen(lt); + } + else if (*cp == '>') { + HDstrncpy(ncp, gt, ncp_len); + esc_len = HDstrlen(gt); + } + else if (*cp == '\"') { + HDstrncpy(ncp, quote, ncp_len); + esc_len = HDstrlen(quote); + } + else if (*cp == '&') { + HDstrncpy(ncp, amp, ncp_len); + esc_len = HDstrlen(amp); + } + else { + *ncp = *cp; + esc_len = 1; + } + ncp += esc_len; + ncp_len -= esc_len; + cp++; + } + + *ncp = '\0'; + return rcp; +} + +/*------------------------------------------------------------------------- + * Function: xml_escape_the_string + * + * Purpose: Escape XML reserved chars in a string, so HDF5 strings + * and paths can be correctly read back in XML CDATA. + * + * Return: The revised string. + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static char * +xml_escape_the_string(const char *str, int slen) +{ + size_t extra; + size_t len; + size_t i; + const char *cp; + char *ncp; + char *rcp; + size_t ncp_len; + + if (!str) + return NULL; + + cp = str; + + if (slen < 0) + len = HDstrlen(str); + else + len = (size_t)slen; + + extra = 0; + + for (i = 0; i < len; i++) { + if (*cp == '\\') + extra++; + else if (*cp == '\"') + extra++; + else if (*cp == '\'') + extra += (HDstrlen(apos) - 1); + else if (*cp == '<') + extra += (HDstrlen(lt) - 1); + else if (*cp == '>') + extra += (HDstrlen(gt) - 1); + else if (*cp == '&') + extra += (HDstrlen(amp) - 1); + cp++; + } + + cp = str; + ncp_len = len + extra + 1; + rcp = ncp = (char *) HDcalloc(ncp_len, sizeof(char)); + + if (ncp == NULL) + return NULL; /* ?? */ + + for (i = 0; i < len; i++) { + size_t esc_len; + + HDassert(ncp_len); + if (*cp == '\\') { + *ncp++ = '\\'; + *ncp = *cp; + esc_len = 1; + } + else if (*cp == '\"') { + *ncp++ = '\\'; + *ncp = *cp; + esc_len = 1; + } + else if (*cp == '\'') { + HDstrncpy(ncp, apos, ncp_len); + esc_len = HDstrlen(apos); + } + else if (*cp == '<') { + HDstrncpy(ncp, lt, ncp_len); + esc_len = HDstrlen(lt); + } + else if (*cp == '>') { + HDstrncpy(ncp, gt, ncp_len); + esc_len = HDstrlen(gt); + } + else if (*cp == '&') { + HDstrncpy(ncp, amp, ncp_len); + esc_len = HDstrlen(amp); + } + else { + *ncp = *cp; + esc_len = 1; + } + ncp += esc_len; + ncp_len -= esc_len; + cp++; + } + + *ncp = '\0'; + return rcp; +} + +/** + ** XML print functions--these replace some functions in the + ** h5tools.c suite. + **/ + +/*------------------------------------------------------------------------- + * Function: xml_print_datatype + * + * Purpose: Print description of a datatype in XML. + * Note: this is called inside a <DataType> element. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +xml_print_datatype(hid_t type, unsigned in_group) +{ + char *mname; + hid_t mtype; + unsigned nmembers; + unsigned ndims; + unsigned i; + size_t size; + hsize_t dims[H5DUMP_MAX_RANK]; + H5T_str_t str_pad; + H5T_cset_t cset; + hid_t super; + H5T_order_t ord; + H5T_sign_t sgn; + size_t sz; + size_t spos; + size_t epos; + size_t esize; + size_t mpos; + size_t msize; + int nmembs; + htri_t is_vlstr=FALSE; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols==0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + if(!in_group && H5Tcommitted(type) > 0) { + H5O_info_t oinfo; + obj_t *found_obj; /* Found object */ + + /* detect a shared datatype, output only once */ + H5Oget_info(type, &oinfo); + found_obj = search_obj(type_table, oinfo.addr); + + if(found_obj) { + /* This should be defined somewhere else */ + /* These 2 cases are handled the same right now, but + probably will have something different eventually */ + char * dtxid = (char *)HDmalloc((size_t)100); + + xml_name_to_XID(found_obj->objname, dtxid, 100, 1); + if (!found_obj->recorded) { + /* 'anonymous' NDT. Use it's object num. + as it's name. */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNamedDataTypePtr OBJ-XID=\"/%s\"/>", + xmlnsprefix, dtxid); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + /* point to the NDT by name */ + char *t_objname = xml_escape_the_name(found_obj->objname); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNamedDataTypePtr OBJ-XID=\"%s\" H5Path=\"%s\"/>", + xmlnsprefix, dtxid, t_objname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_objname); + } + HDfree(dtxid); + } + else { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- h5dump error: unknown committed type. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + h5tools_setstatus(EXIT_FAILURE); + } + } + else { + switch (H5Tget_class(type)) { + case H5T_INTEGER: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + /* <hdf5:IntegerType ByteOrder="bo" Sign="torf" Size="bytes"/> */ + ord = H5Tget_order(type); + sgn = H5Tget_sign(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sIntegerType ByteOrder=\"",xmlnsprefix); + switch (ord) { + case H5T_ORDER_LE: + h5tools_str_append(&buffer, "LE"); + break; + case H5T_ORDER_BE: + h5tools_str_append(&buffer, "BE"); + break; + case H5T_ORDER_VAX: + case H5T_ORDER_MIXED: + case H5T_ORDER_NONE: + case H5T_ORDER_ERROR: + default: + h5tools_str_append(&buffer, "ERROR_UNKNOWN"); + break; + } /* end switch */ + + h5tools_str_append(&buffer, "\" Sign=\""); + + switch (sgn) { + case H5T_SGN_NONE: + h5tools_str_append(&buffer, "false"); + break; + case H5T_SGN_2: + h5tools_str_append(&buffer, "true"); + break; + case H5T_SGN_ERROR: + case H5T_NSGN: + default: + h5tools_str_append(&buffer, "ERROR_UNKNOWN"); + break; + } /* end switch */ + + h5tools_str_append(&buffer, "\" Size=\""); + sz = H5Tget_size(type); + h5tools_str_append(&buffer, "%lu", (unsigned long)sz); + h5tools_str_append(&buffer, "\" />"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_FLOAT: + /* <hdf5:FloatType ByteOrder="bo" Size="bytes" + SignBitLocation="bytes" + ExponentBits="eb" ExponentLocation="el" + MantissaBits="mb" MantissaLocation="ml" /> */ + ord = H5Tget_order(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sFloatType ByteOrder=\"",xmlnsprefix); + + switch (ord) { + case H5T_ORDER_LE: + h5tools_str_append(&buffer, "LE"); + break; + case H5T_ORDER_BE: + h5tools_str_append(&buffer, "BE"); + break; + case H5T_ORDER_VAX: + h5tools_str_append(&buffer, "VAX"); + break; + case H5T_ORDER_MIXED: + case H5T_ORDER_NONE: + case H5T_ORDER_ERROR: + default: + h5tools_str_append(&buffer, "ERROR_UNKNOWN"); + } /* end switch */ + + h5tools_str_append(&buffer, "\" Size=\""); + sz = H5Tget_size(type); + h5tools_str_append(&buffer, "%lu", (unsigned long)sz); + H5Tget_fields(type, &spos, &epos, &esize, &mpos, &msize); + h5tools_str_append(&buffer, "\" SignBitLocation=\"%lu\" ", (unsigned long)spos); + h5tools_str_append(&buffer, "ExponentBits=\"%lu\" ExponentLocation=\"%lu\" ", (unsigned long)esize, (unsigned long)epos); + h5tools_str_append(&buffer, "MantissaBits=\"%lu\" MantissaLocation=\"%lu\" />", (unsigned long)msize, (unsigned long)mpos); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_TIME: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sTimeType />",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + h5tools_str_append(&buffer, "<!-- H5T_TIME: not yet implemented -->"); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_STRING: + /* <hdf5:StringType Cset="cs" StrSize="chars" StrPad="pad" /> */ + size = H5Tget_size(type); + str_pad = H5Tget_strpad(type); + cset = H5Tget_cset(type); + is_vlstr = H5Tis_variable_str(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sStringType Cset=\"",xmlnsprefix); + + if (cset == H5T_CSET_ASCII) + h5tools_str_append(&buffer, "H5T_CSET_ASCII\" "); + else + h5tools_str_append(&buffer, "unknown_cset\" "); + + if(is_vlstr) + h5tools_str_append(&buffer, "StrSize=\"H5T_VARIABLE\" StrPad=\""); + else + h5tools_str_append(&buffer, "StrSize=\"%d\" StrPad=\"", (int) size); + + if (str_pad == H5T_STR_NULLTERM) + h5tools_str_append(&buffer, "H5T_STR_NULLTERM\"/>"); + else if (str_pad == H5T_STR_NULLPAD) + h5tools_str_append(&buffer, "H5T_STR_NULLPAD\"/>"); + else if (str_pad == H5T_STR_SPACEPAD) + h5tools_str_append(&buffer, "H5T_STR_SPACEPAD\"/>"); + else + h5tools_str_append(&buffer, "H5T_STR_ERROR\"/>"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_BITFIELD: + /* <hdf5:BitfieldType ByteOrder="bo" Size="bytes"/> */ + ord = H5Tget_order(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sBitfieldType ByteOrder=\"",xmlnsprefix); + + switch (ord) { + case H5T_ORDER_LE: + h5tools_str_append(&buffer, "LE"); + break; + case H5T_ORDER_BE: + h5tools_str_append(&buffer, "BE"); + break; + case H5T_ORDER_VAX: + case H5T_ORDER_MIXED: + case H5T_ORDER_NONE: + case H5T_ORDER_ERROR: + default: + h5tools_str_append(&buffer, "ERROR_UNKNOWN"); + } /* end switch */ + + size = H5Tget_size(type); + h5tools_str_append(&buffer, "\" Size=\"%lu\"/>", (unsigned long)size); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_OPAQUE: + /* <hdf5:OpaqueType Tag="tag" Size="bytes" /> */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + mname = H5Tget_tag(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sOpaqueType Tag=\"%s\" ",xmlnsprefix, mname); + H5free_memory(mname); + size = H5Tget_size(type); + h5tools_str_append(&buffer, "Size=\"%lu\"/>", (unsigned long)size); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_COMPOUND: + /* recursively describe the components of a compound datatype */ + + /* type of a dataset */ + nmembers = (unsigned)H5Tget_nmembers(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sCompoundType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + /* List each member Field of the type */ + /* <hdf5:Field FieldName="name" > */ + /* <hdf5:DataType > */ + ctx.indent_level++; + dump_indent += COL; + for (i = 0; i < nmembers; i++) { + char *t_fname; + + mname = H5Tget_member_name(type, i); + mtype = H5Tget_member_type(type, i); + t_fname = xml_escape_the_name(mname); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sField FieldName=\"%s\">",xmlnsprefix, t_fname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + H5free_memory(mname); + HDfree(t_fname); + dump_indent += COL; + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + dump_indent += COL; + xml_print_datatype(mtype,0); + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sField>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sCompoundType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_REFERENCE: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + /* Only Object references supported at this time */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sReferenceType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sObjectReferenceType />",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sReferenceType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_ENUM: + /* <hdf5:EnumType Nelems="ne" > list Name, values of enum */ + nmembs = H5Tget_nmembers(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_indent += COL; + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sEnumType Nelems=\"%d\">",xmlnsprefix, nmembs); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + xml_print_enum(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sEnumType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAtomicType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_VLEN: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sVLType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + super = H5Tget_super(type); + dump_indent += COL; + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_indent += COL; + ctx.indent_level++; + xml_print_datatype(super,0); + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sVLType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + H5Tclose(super); + + break; + + case H5T_ARRAY: + /* Get array base type */ + super = H5Tget_super(type); + + /* Print lead-in */ + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sArrayType Ndims=\"",xmlnsprefix); + ndims = (unsigned)H5Tget_array_ndims(type); + h5tools_str_append(&buffer, "%u\">", ndims); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + /* Get array information */ + H5Tget_array_dims2(type, dims); + + /* list of dimensions */ + ctx.indent_level++; + for (i = 0; i < ndims; i++) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sArrayDimension DimSize=\"%u\"/>", xmlnsprefix, (int) dims[i]); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + ctx.indent_level--; + + dump_indent += COL; + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_indent += COL; + ctx.indent_level++; + xml_print_datatype(super,0); + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_indent -= COL; + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sArrayType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + /* Close array base type */ + H5Tclose(super); + break; + + case H5T_NO_CLASS: + case H5T_NCLASSES: + HDassert(0); + /* fall through */ + default: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- unknown datatype -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + h5tools_setstatus(EXIT_FAILURE); + break; + } + } /* end else */ + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_datatype + * + * Purpose: Dump description of a datatype in XML. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +xml_dump_datatype(hid_t type) +{ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + ctx.indent_level++; + dump_indent += COL; + + if(H5Tcommitted(type) > 0) { + H5O_info_t oinfo; + obj_t *found_obj; /* Found object */ + + /* Datatype is a shared or named datatype */ + H5Oget_info(type, &oinfo); + found_obj = search_obj(type_table, oinfo.addr); + + if(found_obj) { + /* Shared datatype, must be entered as an object */ + /* These 2 cases are the same now, but may change */ + char *dtxid = (char *)HDmalloc((size_t)100); + + xml_name_to_XID(found_obj->objname, dtxid, 100, 1); + if (!found_obj->recorded) { + /* anonymous stored datatype: + following the dumper's current + practice: + use it's object ref as its name + */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNamedDataTypePtr OBJ-XID=\"%s\"/>", + xmlnsprefix, dtxid); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + /* pointer to a named datatype already in XML */ + char *t_objname = xml_escape_the_name(found_obj->objname); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNamedDataTypePtr OBJ-XID=\"%s\" H5Path=\"%s\" />", + xmlnsprefix, dtxid, t_objname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_objname); + } + HDfree(dtxid); + } + else { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- h5dump error: unknown committed type. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + } + else { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataType>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + dump_indent += COL; + xml_print_datatype(type, 0); + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataType>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + ctx.indent_level--; + dump_indent -= COL; + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_dataspace + * + * Purpose: Dump description of a dataspace in XML. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +xml_dump_dataspace(hid_t space) +{ + hsize_t size[H5DUMP_MAX_RANK]; + hsize_t maxsize[H5DUMP_MAX_RANK]; + int i; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + int ndims = H5Sget_simple_extent_dims(space, size, maxsize); + H5S_class_t space_type = H5Sget_simple_extent_type(space); + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataspace>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + switch (space_type) { + case H5S_SCALAR: + /* scalar dataspace (just a tag, no XML attrs. defined */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sScalarDataspace />",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5S_SIMPLE: + /* simple dataspace */ + /* <hdf5:SimpleDataspace Ndims="nd"> */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sSimpleDataspace Ndims=\"%d\">",xmlnsprefix, ndims); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + /* print the <hdf5:Dimension> elements */ + ctx.indent_level++; + for (i = 0; i < ndims; i++) { + if (maxsize[i] == H5S_UNLIMITED) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDimension DimSize=\"%" H5_PRINTF_LL_WIDTH "u\" MaxDimSize=\"UNLIMITED\"/>", + xmlnsprefix,size[i]); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else if (maxsize[i] == (hsize_t) 0) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDimension DimSize=\"%" H5_PRINTF_LL_WIDTH "u\" MaxDimSize=\"%" H5_PRINTF_LL_WIDTH "u\"/>", + xmlnsprefix,size[i], size[i]); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDimension DimSize=\"%" H5_PRINTF_LL_WIDTH "u\" MaxDimSize=\"%" H5_PRINTF_LL_WIDTH "u\"/>", + xmlnsprefix, size[i], maxsize[i]); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + } + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sSimpleDataspace>", xmlnsprefix ); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + +#ifdef TMP + /* Commented out: wait until the schema is updated first */ + case H5S_NULL: + /* null dataspace (just a tag, no XML attrs. defined */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNullDataspace />",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; +#endif /* TMP */ + + case H5S_NULL: + case H5S_NO_CLASS: + default: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- unknown dataspace -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataspace>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_data + * + * Purpose: Dump description of data in XML. + * Note that this calls the h5dump_xxx calls in + * the h5tools library. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +xml_dump_data(hid_t obj_id, int obj_data, struct subset_t H5_ATTR_UNUSED * sset, int H5_ATTR_UNUSED pindex) +{ + hid_t space = -1; + hid_t type = -1; + hid_t p_type = -1; + hsize_t size[64]; + hsize_t nelmts = 1; + int ndims; + int i; + int status = -1; + void *buf = NULL; + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + /* Print all the values. */ + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + string_dataformat.cmpd_sep = " "; + string_dataformat.cmpd_pre = ""; + string_dataformat.cmpd_suf = ""; + string_dataformat.cmpd_end = ""; + string_dataformat.arr_linebreak = 0; + string_dataformat.arr_pre = ""; + outputformat = &string_dataformat; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + dump_indent += COL; + ctx.indent_level++; + + if (obj_data == DATASET_DATA) { + type = H5Dget_type(obj_id); + if (H5Tget_class(type) == H5T_REFERENCE) + status = xml_print_refs(obj_id, DATASET_DATA); + else if (H5Tget_class(type) == H5T_STRING) + status = xml_print_strs(obj_id, DATASET_DATA); + else { + h5tools_context_t datactx; + HDmemset(&datactx, 0, sizeof(datactx)); + datactx.need_prefix = TRUE; + datactx.indent_level = ctx.indent_level; + datactx.cur_column = ctx.cur_column; + status = h5tools_dump_dset(rawoutstream, outputformat, &datactx, obj_id, NULL); + } + } + else { + /* Attribute data */ + type = H5Aget_type(obj_id); + + if (H5Tget_class(type) == H5T_REFERENCE) { + /* references are done differently than + the standard output: + XML dumps a path to the object + referenced. + */ + status = xml_print_refs(obj_id, ATTRIBUTE_DATA); + H5Tclose(type); + } + else if (H5Tget_class(type) == H5T_STRING) { + status = xml_print_strs(obj_id, ATTRIBUTE_DATA); + } + else { /* all other data */ + /* VL data special information */ + unsigned int vl_data = 0; /* contains VL datatypes */ + + p_type = h5tools_get_native_type(type); + + /* Check if we have VL data in the dataset's datatype */ + if (h5tools_detect_vlen(p_type) == TRUE) + vl_data = TRUE; + + H5Tclose(type); + + space = H5Aget_space(obj_id); + + ndims = H5Sget_simple_extent_dims(space, size, NULL); + + for (i = 0; i < ndims; i++) + nelmts *= size[i]; + + buf = HDmalloc((size_t)(nelmts * MAX(H5Tget_size(type), H5Tget_size(p_type)))); + HDassert(buf); + + if (H5Aread(obj_id, p_type, buf) >= 0) { + h5tools_context_t datactx; + HDmemset(&datactx, 0, sizeof(datactx)); + datactx.need_prefix = TRUE; + datactx.indent_level = ctx.indent_level; + datactx.cur_column = ctx.cur_column; + status = h5tools_dump_mem(rawoutstream, outputformat, &datactx, obj_id, p_type, space, buf); + } + /* Reclaim any VL memory, if necessary */ + if (vl_data) + H5Dvlen_reclaim(p_type, space, H5P_DEFAULT, buf); + + HDfree(buf); + H5Tclose(p_type); + H5Sclose(space); + H5Tclose(type); + } + } + + if (status == FAIL) { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "Unable to print data."); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + status = 1; + } + ctx.indent_level--; + dump_indent -= COL; + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_attr + * + * Purpose: Dump a description of an HDF5 attribute in XML. + * + * Return: herr_t + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +xml_dump_attr(hid_t attr, const char *attr_name, const H5A_info_t H5_ATTR_UNUSED *info, + void H5_ATTR_UNUSED * op_data) +{ + hid_t attr_id = -1; + hid_t type = -1; + hid_t space = -1; + H5S_class_t space_type; + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + + char *t_aname = xml_escape_the_name(attr_name); + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sAttribute Name=\"%s\">", xmlnsprefix, t_aname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_aname); + + if ((attr_id = H5Aopen(attr, attr_name, H5P_DEFAULT)) >= 0) { + type = H5Aget_type(attr_id); + space = H5Aget_space(attr_id); + space_type = H5Sget_simple_extent_type(space); + + dump_function_table->dump_dataspace_function(space); + dump_function_table->dump_datatype_function(type); + + ctx.indent_level++; + dump_indent += COL; + + if (display_attr_data && space_type != H5S_NULL) { + switch (H5Tget_class(type)) { + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_STRING: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_ENUM: + case H5T_ARRAY: + dump_function_table->dump_data_function(attr_id, ATTRIBUTE_DATA, NULL, 0); + break; + + case H5T_TIME: + ctx.indent_level++; + dump_indent += COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Time data not yet implemented. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<hdf5:Data>"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + dump_indent -= COL; + break; + + case H5T_COMPOUND: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Note: format of compound data not specified -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + dump_function_table->dump_data_function(attr_id, ATTRIBUTE_DATA, NULL, 0); + break; + + case H5T_REFERENCE: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + if (!H5Tequal(type, H5T_STD_REF_OBJ)) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Note: Region references not supported -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + xml_print_refs(attr_id, ATTRIBUTE_DATA); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_VLEN: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Note: format of VL data not specified -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + dump_function_table->dump_data_function(attr_id, ATTRIBUTE_DATA, NULL, 0); + break; + case H5T_NO_CLASS: + case H5T_NCLASSES: + HDassert(0); + /* fall through */ + default: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Unknown datatype: %d -->", H5Tget_class(type)); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + } + } + else { + /* The case of an attribute never yet written ?? + * Or dataspace is H5S_NULL. */ + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + ctx.indent_level--; + dump_indent -= COL; + + H5Tclose(type); + H5Sclose(space); + H5Aclose(attr_id); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAttribute>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); + return SUCCEED; + } + else { + /* ?? failed */ + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- h5dump error: unable to open attribute. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sAttribute>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); + + h5tools_setstatus(EXIT_FAILURE); + return FAIL; + } +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_named_datatype + * + * Purpose: Dump a description of an HDF5 NDT in XML. + * + * Return: herr_t + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +xml_dump_named_datatype(hid_t type, const char *name) +{ + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + char *tmp; + char *dtxid; + char *parentxid; + char *t_tmp; + char *t_prefix; + char *t_name; + + tmp = (char *)HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2); + HDstrcpy(tmp, prefix); + HDstrcat(tmp, "/"); + HDstrcat(tmp, name); + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + dtxid = (char *)HDmalloc((size_t)100); + parentxid = (char *)HDmalloc((size_t)100); + t_tmp = xml_escape_the_name(tmp); + t_prefix = xml_escape_the_name(prefix); + t_name = xml_escape_the_name(name); + + xml_name_to_XID(tmp, dtxid, 100, 1); + xml_name_to_XID(prefix, parentxid, 100, 1); + if(HDstrncmp(name, "#", (size_t)1) == 0) { + /* Special: this is an 'anonymous' NDT, deleted but + still in use. + We follow the dumper's undocumented practice, and + use its object id as its name. + Exactly the same as normal, but a separate case + in the event we want to do something else in + the future. + */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNamedDataType Name=\"%s\" OBJ-XID=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\">", + xmlnsprefix, + name, dtxid, + parentxid, HDstrcmp(prefix,"") ? t_prefix : "/"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + H5O_info_t oinfo; /* Object info */ + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNamedDataType Name=\"%s\" OBJ-XID=\"%s\" " + "H5Path=\"%s\" Parents=\"%s\" H5ParentPaths=\"%s\">", + xmlnsprefix, + t_name, dtxid, + t_tmp, parentxid, (HDstrcmp(prefix, "") ? t_prefix : "/")); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + /* Check uniqueness of named datatype */ + H5Oget_info(type, &oinfo); + if(oinfo.rc > 1) { + obj_t *found_obj; /* Found object */ + + /* Group with more than one link to it... */ + found_obj = search_obj(type_table, oinfo.addr); + + if (found_obj == NULL) { + indentation(dump_indent); + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + else if(found_obj->displayed) { + /* We have already printed this named datatype, print it as a + * NamedDatatypePtr + */ + char pointerxid[100]; + char *t_objname = xml_escape_the_name(found_obj->objname); + + ctx.indent_level++; + + xml_name_to_XID(found_obj->objname, pointerxid, (int)sizeof(pointerxid), 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNamedDatatypePtr OBJ-XID=\"%s\" H5Path=\"%s\"/>", xmlnsprefix, pointerxid, t_objname); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sNamedDataType>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_objname); + goto done; + } + else + found_obj->displayed = TRUE; + } + } + + ctx.indent_level++; + dump_indent += COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + dump_indent += COL; + xml_print_datatype(type,1); + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sNamedDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + +done: + + h5tools_str_close(&buffer); + + HDfree(dtxid); + HDfree(parentxid); + HDfree(t_tmp); + HDfree(t_prefix); + HDfree(t_name); + HDfree(tmp); +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_group + * + * Purpose: Dump a description of an HDF5 Group (and its members) in XML. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * Pedro Vicente, October 9, 2007 + * added parameters to H5A(L)iterate to allow for other iteration orders + * + *------------------------------------------------------------------------- + */ +void +xml_dump_group(hid_t gid, const char *name) +{ + H5O_info_t oinfo; + hid_t gcpl_id; + hid_t dset, type; + unsigned crt_order_flags; + unsigned attr_crt_order_flags; + int isRoot = 0; + char type_name[1024]; + char *t_objname = NULL; + char *par_name = NULL; + char *cp = NULL; + char *tmp = NULL; + char *par = NULL; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + if ((gcpl_id = H5Gget_create_plist(gid)) < 0) { + error_msg("error in getting group creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the group creation properties for attributes */ + if (H5Pget_attr_creation_order(gcpl_id, &attr_crt_order_flags) < 0) { + error_msg("error in getting group creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* query the group creation properties */ + if(H5Pget_link_creation_order(gcpl_id, &crt_order_flags) < 0) { + error_msg("error in getting group creation properties\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + if(H5Pclose(gcpl_id) < 0) { + error_msg("error in closing group creation property list ID\n"); + h5tools_setstatus(EXIT_FAILURE); + } + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + if(HDstrcmp(name, "/") == 0) { + isRoot = 1; + tmp = HDstrdup("/"); + } + else { + tmp = (char *)HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2); + HDstrcpy(tmp, prefix); + par = HDstrdup(tmp); + cp = HDstrrchr(par, '/'); + if(cp) { + if((cp == par) && HDstrlen(par) > 1) + *(cp + 1) = '\0'; + else + *cp = '\0'; + } + } + + H5Oget_info(gid, &oinfo); + + if(oinfo.rc > 1) { + obj_t *found_obj; /* Found object */ + + /* Group with more than one link to it... */ + found_obj = search_obj(group_table, oinfo.addr); + + if (found_obj == NULL) { + indentation(dump_indent); + error_msg("internal error (file %s:line %d)\n", __FILE__, __LINE__); + h5tools_setstatus(EXIT_FAILURE); + } + else { + char *t_name = xml_escape_the_name(name); + char *grpxid = (char *)HDmalloc((size_t)100); + char *parentxid = (char *)HDmalloc((size_t)100); + + if(found_obj->displayed) { + char *ptrstr = (char *)HDmalloc((size_t)100); + + /* already seen: enter a groupptr */ + if(isRoot) { + /* probably can't happen! */ + xml_name_to_XID("/", grpxid, 100, 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sRootGroup OBJ-XID=\"%s\" H5Path=\"%s\">", + xmlnsprefix, grpxid, "/"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + t_objname = xml_escape_the_name(found_obj->objname); + par_name = xml_escape_the_name(par); + xml_name_to_XID(tmp, grpxid, 100, 1); + xml_name_to_XID(par, parentxid, 100, 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sGroup Name=\"%s\" OBJ-XID=\"%s-%d\" H5Path=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\">", + xmlnsprefix,t_name, grpxid, get_next_xid(), + t_objname, parentxid, par_name); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_objname); + HDfree(par_name); + + ctx.indent_level++; + + t_objname = xml_escape_the_name(found_obj->objname);/* point to the NDT by name */ + par_name = xml_escape_the_name(par); + xml_name_to_XID(found_obj->objname, ptrstr, 100, 1); + xml_name_to_XID(par, parentxid, 100, 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sGroupPtr OBJ-XID=\"%s\" H5Path=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\" />", + xmlnsprefix, + ptrstr, t_objname, parentxid, par_name); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + + HDfree(t_objname); + HDfree(par_name); + } + HDfree(ptrstr); + } + else { + + /* first time this group has been seen -- describe it */ + if(isRoot) { + xml_name_to_XID("/", grpxid, 100, 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sRootGroup OBJ-XID=\"%s\" H5Path=\"%s\">", + xmlnsprefix, grpxid, "/"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + char *t_tmp = xml_escape_the_name(tmp); + + par_name = xml_escape_the_name(par); + xml_name_to_XID(tmp, grpxid, 100, 1); + xml_name_to_XID(par, parentxid, 100, 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sGroup Name=\"%s\" OBJ-XID=\"%s\" H5Path=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\" >", + xmlnsprefix,t_name, grpxid, t_tmp, parentxid, par_name); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(t_tmp); + HDfree(par_name); + } + found_obj->displayed = TRUE; + + /* 1. do all the attributes of the group */ + + ctx.indent_level++; + dump_indent += COL; + + if((sort_by == H5_INDEX_CRT_ORDER) && (attr_crt_order_flags & H5P_CRT_ORDER_TRACKED)) { + if(H5Aiterate2(gid, sort_by, sort_order, NULL, dump_function_table->dump_attribute_function, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end if */ + else { + if(H5Aiterate2(gid, H5_INDEX_NAME, sort_order, NULL, dump_function_table->dump_attribute_function, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end else */ + + if(isRoot && unamedtype) { + unsigned u; + + /* Very special case: dump unamed type in root group */ + for(u = 0; u < type_table->nobjs; u++) { + if(!type_table->objs[u].recorded) { + dset = H5Dopen2(gid, type_table->objs[u].objname, H5P_DEFAULT); + type = H5Dget_type(dset); + sprintf(type_name, "#"H5_PRINTF_HADDR_FMT, type_table->objs[u].objno); + dump_function_table->dump_named_datatype_function(type, type_name); + H5Tclose(type); + H5Dclose(dset); + } + } + } + + /* iterate through all the links */ + + if((sort_by == H5_INDEX_CRT_ORDER) && (crt_order_flags & H5P_CRT_ORDER_TRACKED)) + H5Literate(gid, sort_by, sort_order, NULL, xml_dump_all_cb, NULL); + else + H5Literate(gid, H5_INDEX_NAME, sort_order, NULL, xml_dump_all_cb, NULL); + + dump_indent -= COL; + ctx.indent_level--; + } + HDfree(t_name); + HDfree(grpxid); + HDfree(parentxid); + } + } + else { + /* only link -- must be first time! */ + char *t_name = xml_escape_the_name(name); + char *grpxid = (char *)HDmalloc((size_t)100); + char *parentxid = (char *)HDmalloc((size_t)100); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + + if(isRoot) { + xml_name_to_XID("/", grpxid, 100, 1); + h5tools_str_append(&buffer, "<%sRootGroup OBJ-XID=\"%s\" H5Path=\"%s\">", xmlnsprefix, grpxid, "/"); + } + else { + char *t_tmp = xml_escape_the_name(tmp); + + par_name = xml_escape_the_name(par); + xml_name_to_XID(tmp, grpxid, 100, 1); + xml_name_to_XID(par, parentxid, 100, 1); + h5tools_str_append(&buffer, "<%sGroup Name=\"%s\" OBJ-XID=\"%s\" H5Path=\"%s\" " + "Parents=\"%s\" H5ParentPaths=\"%s\" >", + xmlnsprefix, t_name, grpxid, t_tmp, parentxid, par_name); + HDfree(t_tmp); + HDfree(par_name); + } + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(t_name); + HDfree(grpxid); + HDfree(parentxid); + + /* 1. do all the attributes of the group */ + + ctx.indent_level++; + dump_indent += COL; + + if((sort_by == H5_INDEX_CRT_ORDER) && (attr_crt_order_flags & H5P_CRT_ORDER_TRACKED)) { + if(H5Aiterate2(gid, sort_by, sort_order, NULL, dump_function_table->dump_attribute_function, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end if */ + else { + if(H5Aiterate2(gid, H5_INDEX_NAME, sort_order, NULL, dump_function_table->dump_attribute_function, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end else */ + + if(isRoot && unamedtype) { + unsigned u; + + /* Very special case: dump unamed type in root group */ + for(u = 0; u < type_table->nobjs; u++) { + if(!type_table->objs[u].recorded) { + dset = H5Dopen2(gid, type_table->objs[u].objname, H5P_DEFAULT); + type = H5Dget_type(dset); + sprintf(type_name, "#"H5_PRINTF_HADDR_FMT, type_table->objs[u].objno); + dump_function_table->dump_named_datatype_function(type, type_name); + H5Tclose(type); + H5Dclose(dset); + } + } + } + + /* iterate through all the links */ + + if((sort_by == H5_INDEX_CRT_ORDER) && (crt_order_flags & H5P_CRT_ORDER_TRACKED)) + H5Literate(gid, sort_by, sort_order, NULL, xml_dump_all_cb, NULL); + else + H5Literate(gid, H5_INDEX_NAME, sort_order, NULL, xml_dump_all_cb, NULL); + + dump_indent -= COL; + ctx.indent_level--; + } + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if(isRoot) + h5tools_str_append(&buffer, "</%sRootGroup>", xmlnsprefix); + else + h5tools_str_append(&buffer, "</%sGroup>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); + + if(par) + HDfree(par); + if(tmp) + HDfree(tmp); +} + +/*------------------------------------------------------------------------- + * Function: xml_print_refs + * + * Purpose: Print a path to the objects referenced by HDF5 Referneces. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +xml_print_refs(hid_t did, int source) +{ + herr_t e; + hid_t type = -1; + hid_t space = -1; + hssize_t ssiz = -1; + hsize_t i; + size_t tsiz; + hobj_ref_t *refbuf = NULL; + char *buf = NULL; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + if (source == DATASET_DATA) { + type = H5Dget_type(did); + } + else if (source == ATTRIBUTE_DATA) { + type = H5Aget_type(did); + } + else { + /* return an error */ + return FAIL; + } + if (H5Tget_class(type) != H5T_REFERENCE) { + /* return an error */ + goto error; + } + if (!H5Tequal(type, H5T_STD_REF_OBJ)) { + /* region ref not supported yet... */ + /* return an error */ + goto error; + } + if (source == DATASET_DATA) { + space = H5Dget_space(did); + if ((ssiz = H5Sget_simple_extent_npoints(space)) < 0) + goto error; + if ((tsiz = H5Tget_size(type)) == 0) + goto error; + + buf = (char *) HDcalloc((size_t)ssiz, tsiz); + if (buf == NULL) + goto error; + e = H5Dread(did, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf); + /* need to check result here */ + if (e < 0) + goto error; + } + else if (source == ATTRIBUTE_DATA) { + space = H5Aget_space(did); + if ((ssiz = H5Sget_simple_extent_npoints(space)) < 0) + goto error; + if ((tsiz = H5Tget_size(type)) == 0) + goto error; + + buf = (char *) HDcalloc((size_t)ssiz, tsiz); + if (buf == NULL) + goto error; + e = H5Aread(did, H5T_STD_REF_OBJ, buf); + /* need to check the result here */ + if (e < 0) + goto error; + } + + refbuf = (hobj_ref_t *) buf; + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + for (i = 0; i < (hsize_t)ssiz; i++) { + const char *path = lookup_ref_path(*refbuf); + ctx.indent_level++; + + if (!path) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%s\"", "NULL"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + char *t_path = xml_escape_the_string(path, -1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%s\"", t_path); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_path); + } + ctx.indent_level--; + + refbuf++; + } + + h5tools_str_close(&buffer); + + HDfree(buf); + H5Tclose(type); + H5Sclose(space); + return SUCCEED; + +error: + if(buf) + HDfree(buf); + + H5E_BEGIN_TRY { + H5Tclose(type); + H5Sclose(space); + } H5E_END_TRY; + return FAIL; +} + +/*------------------------------------------------------------------------- + * Function: xml_print_strs + * + * Purpose: Print strings. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +xml_print_strs(hid_t did, int source) +{ + herr_t e; + hid_t type = -1; + hid_t space = -1; + hssize_t ssiz = -1; + htri_t is_vlstr = FALSE; + size_t tsiz = 0; + hsize_t i; + size_t str_size = 0; + char *bp = NULL; + char *onestring = NULL; + void *buf = NULL; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + if (source == DATASET_DATA) + type = H5Dget_type(did); + else if (source == ATTRIBUTE_DATA) + type = H5Aget_type(did); + else + /* return an error */ + return FAIL; + if (H5Tget_class(type) != H5T_STRING) + /* return an error */ + goto error; + /* Check if we have VL data in the dataset's datatype */ + is_vlstr = H5Tis_variable_str(type); + + if (source == DATASET_DATA) { + space = H5Dget_space(did); + if((ssiz = H5Sget_simple_extent_npoints(space)) < 0) + goto error; + if((tsiz = H5Tget_size(type)) == 0) + goto error; + + buf = HDmalloc((size_t)ssiz * tsiz); + if (buf == NULL) + goto error; + + e = H5Dread(did, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf); + if (e < 0) + goto error; + } + else if (source == ATTRIBUTE_DATA) { + space = H5Aget_space(did); + if((ssiz = H5Sget_simple_extent_npoints(space)) < 0) + goto error; + if((tsiz = H5Tget_size(type)) == 0) + goto error; + + buf = HDmalloc((size_t)ssiz * tsiz); + if (buf == NULL) + goto error; + + e = H5Aread(did, type, buf); + if (e < 0) + goto error; + } + + bp = (char*) buf; + if (!is_vlstr) + onestring = (char *) HDcalloc(tsiz, sizeof(char)); + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + for (i = 0; i < (hsize_t)ssiz; i++) { + if (is_vlstr) { + onestring = *(char **) bp; + if (onestring) + str_size = HDstrlen(onestring); + } + else { + HDstrncpy(onestring, bp, tsiz); + str_size = tsiz; + } + + if (!onestring) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "NULL"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + char *t_onestring = xml_escape_the_string(onestring, (int)str_size); + if (t_onestring) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%s\"", t_onestring); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_onestring); + } + } + bp += tsiz; + } + + h5tools_str_close(&buffer); + + /* Reclaim any VL memory, if necessary */ + if (!is_vlstr) + if (onestring) + HDfree(onestring); + if (buf) { + if (is_vlstr) + H5Dvlen_reclaim(type, space, H5P_DEFAULT, buf); + HDfree(buf); + } + H5Tclose(type); + H5Sclose(space); + return SUCCEED; + +error: + if(buf) + HDfree(buf); + + H5E_BEGIN_TRY { + H5Tclose(type); + H5Sclose(space); + } H5E_END_TRY; + return FAIL; +} + +/*------------------------------------------------------------------------- + * Function: check_filters + * + * Purpose: private function to check for the filters and + * put tags in the XML. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +check_filters(hid_t dcpl) +{ + int nfilt; + int i; + H5Z_filter_t filter; + char namebuf[120]; + size_t cd_nelmts = 20; + unsigned int cd_values[20]; + unsigned int flags; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + nfilt = H5Pget_nfilters(dcpl); + if (nfilt <= 0) + return; + for (i = 0; i < nfilt; i++) { + filter = H5Pget_filter2(dcpl, (unsigned) i, &flags, (size_t *) &cd_nelmts, cd_values, (size_t)120, namebuf, NULL); + if (filter == H5Z_FILTER_DEFLATE) { + ctx.indent_level++; + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDeflate Level=\"", xmlnsprefix); + if (cd_nelmts < 1) { + /* not sure what this means? */ + h5tools_str_append(&buffer, "6"); + } + else { + h5tools_str_append(&buffer, "%d", cd_values[0]); + } + h5tools_str_append(&buffer, "\"/>"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + else if (filter == H5Z_FILTER_FLETCHER32) { + ctx.indent_level++; + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sFletcher32 />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + else if (filter == H5Z_FILTER_SHUFFLE) { + ctx.indent_level++; + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sShuffle />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + else if (filter == H5Z_FILTER_SZIP) { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sSZIP ", xmlnsprefix); + if (cd_nelmts < 2) { + /* no pixels ? */ + h5tools_str_append(&buffer, "Pixels_per_block=\"-1\" "); + } + else { + h5tools_str_append(&buffer, "Pixels_per_block=\"%d\" ", cd_values[1]); + } + /* analyse the options mask */ + if (cd_values[0] & H5_SZIP_CHIP_OPTION_MASK) { + h5tools_str_append(&buffer, "Mode =\"Hardware\" "); + } + else if (cd_values[0] & H5_SZIP_ALLOW_K13_OPTION_MASK) { + h5tools_str_append(&buffer, "Mode =\"K13\" "); + } + h5tools_str_append(&buffer, "Coding=\""); + if (cd_values[0] & H5_SZIP_EC_OPTION_MASK) { + h5tools_str_append(&buffer, "Entropy"); + } + else if (cd_values[0] & H5_SZIP_NN_OPTION_MASK) { + h5tools_str_append(&buffer, "NN"); + } + h5tools_str_append(&buffer, "\" "); + + h5tools_str_append(&buffer, "ByteOrder=\""); + if (cd_values[0] & H5_SZIP_LSB_OPTION_MASK) { + h5tools_str_append(&buffer, "LSB"); + } + else if (cd_values[0] & H5_SZIP_MSB_OPTION_MASK) { + h5tools_str_append(&buffer, "MSB"); + } + h5tools_str_append(&buffer, "\" "); + + if (cd_values[0] & H5_SZIP_RAW_OPTION_MASK) { + h5tools_str_append(&buffer, "Header=\"Raw\""); + } + h5tools_str_append(&buffer, "/>"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + else { + /* unknown option */ + } + } + + h5tools_str_close(&buffer); +} + +static void +xml_dump_fill_value(hid_t dcpl, hid_t type) +{ + size_t sz; + size_t i; + hsize_t space; + void *buf; + char *name; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + ctx.indent_level++; + dump_indent += COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + dump_indent += COL; + + space = H5Tget_size(type); + buf = HDmalloc((size_t) space); + + H5Pget_fill_value(dcpl, type, buf); + + if (H5Tget_class(type) == H5T_REFERENCE) { + const char * path = lookup_ref_path(*(hobj_ref_t *) buf); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + if (!path) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%s\"", "NULL"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + char *t_path = xml_escape_the_string(path, -1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%s\"", t_path); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_path); + } + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else if (H5Tget_class(type) == H5T_STRING) { + /* ????? */ + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- String fill values not yet implemented. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + /* all other data */ + switch (H5Tget_class(type)) { + case H5T_INTEGER: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%d\"", *(int *) buf); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_FLOAT: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%f\"", (double)*(float *)buf); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_BITFIELD: + case H5T_OPAQUE: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + sz = H5Tget_size(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\""); + for (i = 0; i < sz; i++) { + h5tools_str_append(&buffer, "%x ", *(unsigned int *) buf); + buf = (char *) buf + sizeof(unsigned int); + } + h5tools_str_append(&buffer, "\""); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_ENUM: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + name = H5Tget_member_name(type, *(unsigned *) buf); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\"%s\"", name); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + if(name) + H5free_memory(name); + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_ARRAY: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Array fill values not yet implemented. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_TIME: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Time fill not yet implemented. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_COMPOUND: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Compound fill not yet implemented. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_VLEN: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- VL fill not yet implemented. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + case H5T_NO_CLASS: + case H5T_NCLASSES: + HDassert(0); + /* fall through */ + case H5T_STRING: + case H5T_REFERENCE: + default: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Unknown fill datatype: %d -->", H5Tget_class(type)); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + } + } + HDfree(buf); + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + dump_indent -= COL; + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: xml_dump_dataset + * + * Purpose: Dump a description of an HDF5 dataset in XML. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * Pedro Vicente, October 9, 2007 + * added parameters to H5Aiterate2 to allow for other iteration orders + * + *------------------------------------------------------------------------- + */ +void +xml_dump_dataset(hid_t did, const char *name, struct subset_t H5_ATTR_UNUSED * sset) +{ + hid_t type; + hid_t space; + hid_t dcpl; + H5D_fill_value_t fvstatus; + int maxdims; + hsize_t *chsize; + int ndims; + int i; + H5D_alloc_time_t at; + H5D_fill_time_t ft; + hsize_t tempi; + char *tmp; + char *t_name; + char *t_tmp; + char *t_prefix; + unsigned attr_crt_order_flags; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + char *rstr = (char*) HDmalloc((size_t)100); + char *pstr = (char*) HDmalloc((size_t)100); + + tmp = (char*) HDmalloc(HDstrlen(prefix) + HDstrlen(name) + 2); + HDstrcpy(tmp, prefix); + HDstrcat(tmp, "/"); + HDstrcat(tmp, name); + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + t_name = xml_escape_the_name(name); + t_tmp = xml_escape_the_name(tmp); + t_prefix = xml_escape_the_name(prefix); + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + xml_name_to_XID(tmp, rstr, 100, 1); + xml_name_to_XID(prefix, pstr, 100, 1); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataset Name=\"%s\" OBJ-XID=\"%s\" H5Path= \"%s\" Parents=\"%s\" H5ParentPaths=\"%s\">", + xmlnsprefix, t_name, rstr, t_tmp, pstr, + strcmp(prefix, "") ? t_prefix : "/"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + HDfree(t_name); + HDfree(t_tmp); + HDfree(t_prefix); + HDfree(rstr); + HDfree(pstr); + HDfree(tmp); + + dcpl = H5Dget_create_plist(did); + type = H5Dget_type(did); + space = H5Dget_space(did); + + /* query the creation properties for attributes */ + H5Pget_attr_creation_order(dcpl, &attr_crt_order_flags); + + /* Print information about storage layout */ + if (H5D_CHUNKED == H5Pget_layout(dcpl)) { + maxdims = H5Sget_simple_extent_ndims(space); + HDassert(maxdims >= 0); + chsize = (hsize_t *)HDmalloc((size_t)maxdims * sizeof(hsize_t)); + ctx.indent_level++; + dump_indent += COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sStorageLayout>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + dump_indent += COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sChunkedLayout ", xmlnsprefix); + ndims = H5Pget_chunk(dcpl, maxdims, chsize); + h5tools_str_append(&buffer, "Ndims=\"%d\">", ndims); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + dump_indent += COL; + + for (i = 0; i < ndims; i++) { + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sChunkDimension DimSize=\"%" H5_PRINTF_LL_WIDTH "u\" />", xmlnsprefix, chsize[i]); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sRequiredFilter>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + dump_indent += COL; + check_filters(dcpl); + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sRequiredFilter>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sChunkedLayout>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sStorageLayout>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + dump_indent -= COL; + HDfree(chsize); + } + else if (H5D_CONTIGUOUS == H5Pget_layout(dcpl)) { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sStorageLayout>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sContiguousLayout/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sStorageLayout>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + else if (H5D_COMPACT == H5Pget_layout(dcpl)) { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sStorageLayout>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sCompactLayout/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sStorageLayout>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + /* and check for external.... ?? */ + + /* fill value */ + + ctx.indent_level++; + dump_indent += COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sFillValueInfo ", xmlnsprefix); + H5Pget_fill_time(dcpl, &ft); + h5tools_str_append(&buffer, "FillTime=\""); + switch (ft) { + case H5D_FILL_TIME_ALLOC: + h5tools_str_append(&buffer, "FillOnAlloc"); + break; + case H5D_FILL_TIME_NEVER: + h5tools_str_append(&buffer, "FillNever"); + break; + case H5D_FILL_TIME_IFSET: + h5tools_str_append(&buffer, "FillIfSet"); + break; + case H5D_FILL_TIME_ERROR: + HDassert(0); + /* fall through */ + default: + h5tools_str_append(&buffer, "?"); + break; + } /* end switch */ + h5tools_str_append(&buffer, "\" "); + H5Pget_alloc_time(dcpl, &at); + h5tools_str_append(&buffer, "AllocationTime=\""); + switch (at) { + case H5D_ALLOC_TIME_EARLY: + h5tools_str_append(&buffer, "Early"); + break; + case H5D_ALLOC_TIME_INCR: + h5tools_str_append(&buffer, "Incremental"); + break; + case H5D_ALLOC_TIME_LATE: + h5tools_str_append(&buffer, "Late"); + break; + case H5D_ALLOC_TIME_DEFAULT: + case H5D_ALLOC_TIME_ERROR: + HDassert(0); + /* fall through */ + default: + h5tools_str_append(&buffer, "?"); + break; + } /* end switch */ + h5tools_str_append(&buffer, "\""); + h5tools_str_append(&buffer, ">"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + dump_indent += COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sFillValue>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + H5Pfill_value_defined(dcpl, &fvstatus); + if (fvstatus == H5D_FILL_VALUE_UNDEFINED || (fvstatus == H5D_FILL_VALUE_DEFAULT && ft == H5D_FILL_TIME_IFSET)) { + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoFill/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + else { + xml_dump_fill_value(dcpl, type); + } + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sFillValue>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + dump_indent -= COL; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sFillValueInfo>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + dump_indent -= COL; + + dump_function_table->dump_dataspace_function(space); + dump_function_table->dump_datatype_function(type); + + ctx.indent_level++; + dump_indent += COL; + + if ((sort_by == H5_INDEX_CRT_ORDER) && (attr_crt_order_flags & H5P_CRT_ORDER_TRACKED)) { + if (H5Aiterate2(did, sort_by, sort_order, NULL, dump_function_table->dump_attribute_function, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end if */ + else { + if (H5Aiterate2(did, H5_INDEX_NAME, sort_order, NULL, dump_function_table->dump_attribute_function, NULL) < 0) { + error_msg("error getting attribute information\n"); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + } /* end else */ + + ctx.indent_level--; + dump_indent -= COL; + tempi = H5Dget_storage_size(did); + + if (display_data && (tempi > 0)) { + switch (H5Tget_class(type)) { + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_STRING: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_ENUM: + case H5T_ARRAY: + ctx.indent_level++; + dump_indent += COL; + dump_function_table->dump_data_function(did, DATASET_DATA, NULL, 0); + ctx.indent_level--; + dump_indent -= COL; + break; + + case H5T_TIME: + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Time data not yet implemented. -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level--; + break; + + case H5T_COMPOUND: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Note: format of compound data not specified -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.indent_level++; + dump_indent += COL; + dump_function_table->dump_data_function(did, DATASET_DATA, NULL, 0); + ctx.indent_level--; + dump_indent -= COL; + break; + + case H5T_REFERENCE: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + if (!H5Tequal(type, H5T_STD_REF_OBJ)) { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Note: Region references not supported -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData />", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + else { + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + xml_print_refs(did, DATASET_DATA); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataFromFile>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5T_VLEN: + ctx.indent_level--; + dump_indent -= COL; + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Note: format of VL data not specified -->"); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + dump_indent += COL; + + ctx.indent_level++; + dump_indent += COL; + dump_function_table->dump_data_function(did, DATASET_DATA, NULL, 0); + ctx.indent_level--; + dump_indent -= COL; + break; + case H5T_NO_CLASS: + case H5T_NCLASSES: + HDassert(0); + /* fall through */ + + default: + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<!-- Unknown datatype: %d -->", H5Tget_class(type)); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + break; + } + } + else { + /* no data written */ + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sNoData/>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sData>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + } + + H5Tclose(type); + H5Sclose(space); + H5Pclose(dcpl); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataset>", xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); +} + +/*------------------------------------------------------------------------- + * Function: xml_print_enum + * + * Purpose: Print the values of an HDF5 ENUM in XML. + * Very similar to regular DDL output. + * + * Return: void + * + * Programmer: REMcG + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +xml_print_enum(hid_t type) +{ + char **name = NULL; /*member names */ + unsigned char *value = NULL; /*value array */ + unsigned nmembs; /*number of members */ + hid_t super; /*enum base integer type */ + hid_t native = -1; /*native integer datatype */ + size_t dst_size; /*destination value type size */ + unsigned i; /*miscellaneous counters */ + size_t j; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *outputformat = &xml_dataformat; + h5tool_format_t string_dataformat; + hsize_t curr_pos = 0; /* total data element position */ + + /* setup */ + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + HDmemset(&ctx, 0, sizeof(ctx)); + ctx.indent_level = dump_indent / COL; + ctx.cur_column = dump_indent; + + string_dataformat = *outputformat; + + if (fp_format) { + string_dataformat.fmt_double = fp_format; + string_dataformat.fmt_float = fp_format; + } + + if (h5tools_nCols == 0) { + string_dataformat.line_ncols = 65535; + string_dataformat.line_per_line = 1; + } + else + string_dataformat.line_ncols = h5tools_nCols; + + string_dataformat.do_escape = display_escape; + outputformat = &string_dataformat; + + nmembs = (unsigned)H5Tget_nmembers(type); + super = H5Tget_super(type); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + xml_print_datatype(super,0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sDataType>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + /* + * Determine what datatype to use for the native values. To simplify + * things we entertain three possibilities: + * 1. long long -- the largest native signed integer + * 2. unsigned long long -- the largest native unsigned integer + * 3. raw format + */ + if (H5Tget_size(type) <= sizeof(long long)) { + dst_size = sizeof(long long); + + if (H5T_SGN_NONE == H5Tget_sign(type)) { + native = H5T_NATIVE_ULLONG; + } + else { + native = H5T_NATIVE_LLONG; + } + } + else { + dst_size = H5Tget_size(type); + } + + /* Get the names and raw values of all members */ + name = (char **)HDcalloc((size_t)nmembs, sizeof(char *)); + value = (unsigned char *)HDcalloc((size_t)nmembs, MAX(H5Tget_size(type), dst_size)); + + for (i = 0; i < nmembs; i++) { + name[i] = H5Tget_member_name(type, i); + H5Tget_member_value(type, i, value + i * H5Tget_size(type)); + } + + /* Convert values to native datatype */ + if (native > 0) + H5Tconvert(super, native, (size_t)nmembs, value, NULL, H5P_DEFAULT); + + /* Sort members by increasing value */ + /*not implemented yet */ + + /* Print members */ + ctx.indent_level++; + dump_indent += COL; + for (i = 0; i < nmembs; i++) { + char *t_name = xml_escape_the_name(name[i]); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sEnumElement>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "%s", t_name); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + HDfree(t_name); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sEnumElement>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "<%sEnumValue>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level++; + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + if (native < 0) { + h5tools_str_append(&buffer, "0x"); + + for (j = 0; j < dst_size; j++) + h5tools_str_append(&buffer, "%02x", value[i * dst_size + j]); + } + else if (H5T_SGN_NONE == H5Tget_sign(native)) { + h5tools_str_append(&buffer,"%" H5_PRINTF_LL_WIDTH "u", *((unsigned long long *) + ((void *) (value + i * dst_size)))); + } + else { + h5tools_str_append(&buffer,"%" H5_PRINTF_LL_WIDTH "d", + *((long long *) ((void *) (value + i * dst_size)))); + } + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.indent_level--; + + ctx.need_prefix = TRUE; + h5tools_simple_prefix(rawoutstream, outputformat, &ctx, (hsize_t)0, 0); + + /* Render the element */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "</%sEnumValue>",xmlnsprefix); + h5tools_render_element(rawoutstream, outputformat, &ctx, &buffer, &curr_pos, (size_t)outputformat->line_ncols, (hsize_t)0, (hsize_t)0); + } + ctx.indent_level--; + dump_indent -= COL; + + h5tools_str_close(&buffer); + + /* Release resources */ + for (i = 0; i < nmembs; i++) + H5free_memory(name[i]); + + HDfree(name); + HDfree(value); + H5Tclose(super); +} + diff --git a/tools/src/h5dump/h5dump_xml.h b/tools/src/h5dump/h5dump_xml.h new file mode 100644 index 0000000..c1d6c62 --- /dev/null +++ b/tools/src/h5dump/h5dump_xml.h @@ -0,0 +1,39 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#ifndef H5DUMP_XML_H__ +#define H5DUMP_XML_H__ + +extern const char *xmlnsprefix; + +#ifdef __cplusplus +extern "C" { +#endif + +/* The dump functions of the dump_function_table */ +/* XML format: same interface, alternative output */ + +void xml_dump_group(hid_t, const char *); +void xml_dump_named_datatype(hid_t, const char *); +void xml_dump_dataset(hid_t, const char *, struct subset_t *); +void xml_dump_dataspace(hid_t space); +void xml_dump_datatype(hid_t type); +herr_t xml_dump_attr(hid_t, const char *, const H5A_info_t *, void *); +void xml_dump_data(hid_t, int, struct subset_t *, int); + +#ifdef __cplusplus +} +#endif + +#endif /* !H5DUMP_XML_H__ */ diff --git a/tools/src/h5format_convert/CMakeLists.txt b/tools/src/h5format_convert/CMakeLists.txt new file mode 100644 index 0000000..957055d --- /dev/null +++ b/tools/src/h5format_convert/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required (VERSION 3.1.0) +PROJECT (HDF5_TOOLS_SRC_H5FC) + +#----------------------------------------------------------------------------- +# Setup include Directories +#----------------------------------------------------------------------------- +INCLUDE_DIRECTORIES (${HDF5_TOOLS_DIR}/lib) + +# -------------------------------------------------------------------- +# Add the h5format_convert executables +# -------------------------------------------------------------------- +add_executable (h5format_convert ${HDF5_TOOLS_SRC_H5FC_SOURCE_DIR}/h5format_convert.c) +TARGET_NAMING (h5format_convert STATIC) +TARGET_C_PROPERTIES (h5format_convert STATIC " " " ") +target_link_libraries (h5format_convert ${HDF5_TOOLS_LIB_TARGET} ${HDF5_LIB_TARGET}) +set_target_properties (h5format_convert PROPERTIES FOLDER tools) +set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};h5format_convert") + +set (H5_DEP_EXECUTABLES h5format_convert) + +############################################################################## +############################################################################## +### I N S T A L L A T I O N ### +############################################################################## +############################################################################## + +#----------------------------------------------------------------------------- +# Rules for Installation of tools using make Install target +#----------------------------------------------------------------------------- + +#INSTALL_PROGRAM_PDB (h5format_convert ${HDF5_INSTALL_BIN_DIR} toolsapplications) + +install ( + TARGETS + h5format_convert + EXPORT + ${HDF5_EXPORTED_TARGETS} + RUNTIME DESTINATION ${HDF5_INSTALL_BIN_DIR} COMPONENT toolsapplications +) diff --git a/tools/src/h5format_convert/Makefile.am b/tools/src/h5format_convert/Makefile.am new file mode 100644 index 0000000..e2d1acf --- /dev/null +++ b/tools/src/h5format_convert/Makefile.am @@ -0,0 +1,35 @@ +# +# Copyright by The HDF Group. +# Copyright by the Board of Trustees of the University of Illinois. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the files COPYING and Copyright.html. COPYING can be found at the root +# of the source code distribution tree; Copyright.html can be found at the +# root level of an installed copy of the electronic HDF5 document set and +# is linked from the top-level documents page. It can also be found at +# http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have +# access to either file, you may request a copy from help@hdfgroup.org. +## +## Makefile.am +## Run automake to generate a Makefile.in from this file. +# +# HDF5 Library Makefile(.in) +# + +include $(top_srcdir)/config/commence.am + +# Include src directory +AM_CPPFLAGS+=-I$(top_srcdir)/src -I$(top_srcdir)/tools/lib + +# These are our main targets, the tools +bin_PROGRAMS=h5format_convert + +# Add h5format_convert specific linker flags here +h5format_convert_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) + +# All programs rely on hdf5 library and h5tools library +LDADD=$(LIBH5TOOLS) $(LIBHDF5) + +include $(top_srcdir)/config/conclude.am diff --git a/tools/src/h5format_convert/h5format_convert.c b/tools/src/h5format_convert/h5format_convert.c new file mode 100644 index 0000000..8ce28dd --- /dev/null +++ b/tools/src/h5format_convert/h5format_convert.c @@ -0,0 +1,474 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Vailin Choi; Feb 2015 + */ + + +/* + * We include the private header file so we can get to the uniform + * programming environment it declares. + * HDF5 API functions (except for H5G_basename()) + */ +#include "H5private.h" +#include "h5tools.h" +#include "h5tools_utils.h" +#include "h5trav.h" + +/* Name of tool */ +#define PROGRAMNAME "h5format_convert" + +static char *fname_g = NULL; +static char *dname_g = NULL; +static int dset_g = FALSE; +static int noop_g = FALSE; +static int verbose_g = 0; + +/* + * Command-line options: The user can specify short or long-named + * parameters. + */ +static const char *s_opts = "hVvd:n"; +static struct long_options l_opts[] = { + { "help", no_arg, 'h' }, + { "hel", no_arg, 'h'}, + { "he", no_arg, 'h'}, + { "version", no_arg, 'V' }, + { "version", no_arg, 'V' }, + { "versio", no_arg, 'V' }, + { "versi", no_arg, 'V' }, + { "vers", no_arg, 'V' }, + { "verbose", no_arg, 'v' }, + { "verbos", no_arg, 'v' }, + { "verbo", no_arg, 'v' }, + { "verb", no_arg, 'v' }, + { "dname", require_arg, 'd' }, + { "dnam", require_arg, 'd' }, + { "dna", require_arg, 'd' }, + { "dn", require_arg, 'd' }, + { "noop", no_arg, 'n' }, + { "noo", no_arg, 'n' }, + { "no", no_arg, 'n' }, + { NULL, 0, '\0' } +}; + + +/*------------------------------------------------------------------------- + * Function: usage + * + * Purpose: print usage + * + * Return: void + * + *------------------------------------------------------------------------- + */ +static void usage(const char *prog) +{ + HDfprintf(stdout, "usage: %s [OPTIONS] file_name\n", prog); + HDfprintf(stdout, " OPTIONS\n"); + HDfprintf(stdout, " -h, --help Print a usage message and exit\n"); + HDfprintf(stdout, " -V, --version Print version number and exit\n"); + HDfprintf(stdout, " -v, --verbose Turn on verbose mode\n"); + HDfprintf(stdout, " -d dname, --dname=dataset_name Pathname for the dataset\n"); + HDfprintf(stdout, " -n, --noop Perform all the steps except the actual conversion\n"); + HDfprintf(stdout, "\n"); + HDfprintf(stdout, "Examples of use:\n"); + HDfprintf(stdout, "\n"); + HDfprintf(stdout, "h5format_convert -d /group/dataset file_name\n"); + HDfprintf(stdout, " Convert the dataset </group/dataset> in the HDF5 file <file_name>:\n"); + HDfprintf(stdout, " a. chunked dataset: convert the chunk indexing type to version 1 B-tree\n"); + HDfprintf(stdout, " b. compact/contiguous dataset: downgrade the layout version to 3\n"); + HDfprintf(stdout, " c. virtual dataset: no action\n"); + HDfprintf(stdout, "\n"); + HDfprintf(stdout, "h5format_convert file_name\n"); + HDfprintf(stdout, " Convert all datasets in the HDF5 file <file_name>:\n"); + HDfprintf(stdout, " a. chunked dataset: convert the chunk indexing type to version 1 B-tree\n"); + HDfprintf(stdout, " b. compact/contiguous dataset: downgrade the layout version to 3\n"); + HDfprintf(stdout, " c. virtual dataset: no action\n"); + HDfprintf(stdout, "\n"); + HDfprintf(stdout, "h5format_convert -n -d /group/dataset file_name\n"); + HDfprintf(stdout, " Go through all the steps except the actual conversion when \n"); + HDfprintf(stdout, " converting the dataset </group/dataset> in the HDF5 file <file_name>.\n"); +} /* usage() */ + +/*------------------------------------------------------------------------- + * Function: parse_command_line + * + * Purpose: parse command line input + * + * Return: Success: 0 + * Failure: 1 + * + *------------------------------------------------------------------------- + */ +static int +parse_command_line(int argc, const char **argv) +{ + int opt; + + /* no arguments */ + if (argc == 1) { + usage(h5tools_getprogname()); + h5tools_setstatus(EXIT_FAILURE); + goto error; + } + + /* parse command line options */ + while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { + switch((char) opt) { + case 'h': + usage(h5tools_getprogname()); + h5tools_setstatus(EXIT_SUCCESS); + goto error; + + case 'V': + print_version(h5tools_getprogname()); + h5tools_setstatus(EXIT_SUCCESS); + goto error; + + case 'v': + verbose_g = TRUE; + break; + + case 'd': /* -d dname */ + if(opt_arg != NULL && *opt_arg) + dname_g = HDstrdup(opt_arg); + if(dname_g == NULL) { + h5tools_setstatus(EXIT_FAILURE); + error_msg("No dataset name\n", opt_arg); + usage(h5tools_getprogname()); + goto error; + } + dset_g = TRUE; + break; + + case 'n': /* -n */ + noop_g = TRUE; + break; + + default: + h5tools_setstatus(EXIT_FAILURE); + usage(h5tools_getprogname()); + goto error; + break; + } /* switch */ + } /* while */ + + if (argc <= opt_ind) { + error_msg("missing file name\n"); + usage(h5tools_getprogname()); + h5tools_setstatus(EXIT_FAILURE); + goto error; + } + + fname_g = HDstrdup(argv[opt_ind]); + + return(0); + +error: + return(-1); ; +} /* parse_command_line() */ + + +/*------------------------------------------------------------------------- + * Function: leave + * + * Purpose: Close HDF5 + * + * Return: Does not return + * + *------------------------------------------------------------------------- + */ +static void +leave(int ret) +{ + h5tools_close(); + + HDexit(ret); +} /* leave() */ + +/*------------------------------------------------------------------------- + * Function: convert() + * + * Purpose: To downgrade a dataset's indexing type or layout version: + * For chunked: + * Downgrade the chunk indexing type to version 1 B-tree + * If type is already version 1 B-tree, no further action + * For compact/contiguous: + * Downgrade the layout version from 4 to 3 + * If version is already <= 3, no further action + * For virtual: + * No further action + * + * Return: Success: 0 + * Failure: 1 + * + *------------------------------------------------------------------------- + */ +static int +convert(hid_t fid, const char *dname) +{ + hid_t dcpl = -1; + hid_t did = -1; + H5D_layout_t layout_type; + H5D_chunk_index_t idx_type; + + /* Open the dataset */ + if((did = H5Dopen2(fid, dname, H5P_DEFAULT)) < 0) { + error_msg("unable to open dataset \"%s\"\n", dname); + h5tools_setstatus(EXIT_FAILURE); + goto error; + + } else if(verbose_g) + HDfprintf(stdout, "Open the dataset\n"); + + /* Get the dataset's creation property list */ + if((dcpl = H5Dget_create_plist(did)) < 0) { + error_msg("unable to get the dataset creation property list\n"); + h5tools_setstatus(EXIT_FAILURE); + goto error; + } + + /* Get the dataset's layout */ + if((layout_type = H5Pget_layout(dcpl)) < 0) { + error_msg("unable to get the dataset layout type\n"); + h5tools_setstatus(EXIT_FAILURE); + goto error; + + } else if(verbose_g) + HDfprintf(stdout, "Retrieve the dataset's layout\n"); + + switch(layout_type) { + case H5D_CHUNKED: + if(verbose_g) + HDfprintf(stdout, "Dataset is a chunked dataset\n"); + + /* Get the dataset's chunk indexing type */ + if(H5Dget_chunk_index_type(did, &idx_type) < 0) { + error_msg("unable to get the chunk indexing type for \"%s\"\n", dname); + h5tools_setstatus(EXIT_FAILURE); + goto error; + } else if(verbose_g) + HDfprintf(stdout, "Retrieve the dataset's chunk indexing type\n"); + + if(idx_type == H5D_CHUNK_IDX_BTREE) { + if(verbose_g) + HDfprintf(stdout, "Dataset's chunk indexing type is already version 1 B-tree: no further action\n"); + h5tools_setstatus(EXIT_SUCCESS); + goto done; + } else if (verbose_g) + HDfprintf(stdout, "Dataset's chunk indexing type is not version 1 B-tree\n"); + break; + + case H5D_CONTIGUOUS: + if(verbose_g) + HDfprintf(stdout, "Dataset is a contiguous dataset: downgrade layout version as needed\n"); + break; + + case H5D_COMPACT: + if(verbose_g) + HDfprintf(stdout, "Dataset is a compact dataset: downgrade layout version as needed\n"); + break; + + case H5D_VIRTUAL: + if(verbose_g) + HDfprintf(stdout, "No further action for virtual dataset\n"); + goto done; + + case H5D_NLAYOUTS: + case H5D_LAYOUT_ERROR: + default: + error_msg("unknown layout type for \"%s\"\n", dname); + h5tools_setstatus(EXIT_FAILURE); + goto error; + + } /* end switch */ + + /* No further action if it is a noop */ + if(noop_g) { + if(verbose_g) + HDfprintf(stdout, "Not converting the dataset\n"); + h5tools_setstatus(EXIT_SUCCESS); + goto done; + } + + if(verbose_g) + HDfprintf(stdout, "Converting the dataset...\n"); + + /* Downgrade the dataset */ + if(H5Dformat_convert(did) < 0) { + error_msg("unable to downgrade dataset \"%s\"\n", dname); + h5tools_setstatus(EXIT_FAILURE); + goto error; + } else if(verbose_g) + HDfprintf(stdout, "Done\n"); + +done: + /* Close the dataset */ + if(H5Dclose(did) < 0) { + error_msg("unable to close dataset \"%s\"\n", dname); + h5tools_setstatus(EXIT_FAILURE); + goto error; + } else if(verbose_g) + HDfprintf(stdout, "Close the dataset\n"); + + /* Close the dataset creation property list */ + if(H5Pclose(dcpl) < 0) { + error_msg("unable to close dataset creation property list\n"); + h5tools_setstatus(EXIT_FAILURE); + goto error; + } else if(verbose_g) + printf("Close the dataset creation property list\n"); + + return(0); + +error: + if(verbose_g) + HDfprintf(stdout, "Error encountered\n"); + + H5E_BEGIN_TRY { + H5Pclose(dcpl); + H5Dclose(did); + } H5E_END_TRY; + + return(-1); +} /* convert() */ + +/*------------------------------------------------------------------------- + * Function: convert_dsets_cb() + * + * Purpose: The callback routine from the traversal to convert the + * chunk indexing type of the dataset object. + * + * Return: Success: 0 + * Failure: 1 + *------------------------------------------------------------------------- + */ +static int +convert_dsets_cb(const char *path, const H5O_info_t *oi, const char *already_visited, void *_fid) +{ + hid_t fid = *(hid_t *)_fid; + + /* If the object has already been seen then just return */ + if(NULL == already_visited) { + if(oi->type == H5O_TYPE_DATASET) { + if(verbose_g) + HDfprintf(stdout, "Going to process dataset:%s...\n", path); + if(convert(fid, path) < 0) + goto error; + } /* end if */ + } /* end if */ + + return 0; + +error: + return -1; +} /* end convert_dsets_cb() */ + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: To convert the chunk indexing type of a dataset in a file to + * version 1 B-tree. + * + * Return: Success: 0 + * Failure: 1 + * + *------------------------------------------------------------------------- + */ +int +main(int argc, const char *argv[]) +{ + H5E_auto2_t func; + void *edata; + hid_t fid = -1; + + h5tools_setprogname(PROGRAMNAME); + h5tools_setstatus(EXIT_SUCCESS); + + /* Disable error reporting */ + H5Eget_auto2(H5E_DEFAULT, &func, &edata); + H5Eset_auto2(H5E_DEFAULT, NULL, NULL); + + /* Initialize h5tools lib */ + h5tools_init(); + + /* Parse command line options */ + if(parse_command_line(argc, argv) < 0) + goto done; + else if(verbose_g) + HDfprintf(stdout, "Process command line options\n"); + + if(noop_g && verbose_g) + HDfprintf(stdout, "It is noop...\n"); + + /* Open the HDF5 file */ + if((fid = h5tools_fopen(fname_g, H5F_ACC_RDWR, H5P_DEFAULT, NULL, NULL, 0)) < 0) { + error_msg("unable to open file \"%s\"\n", fname_g); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } else if(verbose_g) + HDfprintf(stdout, "Open the file %s\n", fname_g); + + if(dset_g) { /* Convert a specified dataset in the file */ + if(verbose_g) + HDfprintf(stdout, "Going to process dataset: %s...\n", dname_g); + if(convert(fid, dname_g) < 0) + goto done; + } else { /* Convert all datasets in the file */ + if(verbose_g) + HDfprintf(stdout, "Processing all datasets in the file...\n"); + if(h5trav_visit(fid, "/", TRUE, TRUE, convert_dsets_cb, NULL, &fid) < 0) + goto done; + } /* end else */ + + if(verbose_g) { + if(noop_g) { + HDfprintf(stdout, "Not processing the file's superblock...\n"); + h5tools_setstatus(EXIT_SUCCESS); + goto done; + } /* end if */ + HDfprintf(stdout, "Processing the file's superblock...\n"); + } /* end if */ + + /* Process superblock */ + if(H5Fformat_convert(fid) < 0) { + error_msg("unable to convert file's superblock\"%s\"\n", fname_g); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } /* end if */ + +done: + /* Close the file */ + if(fid >= 0) { + if(H5Fclose(fid) < 0) { + error_msg("unable to close file \"%s\"\n", fname_g); + h5tools_setstatus(EXIT_FAILURE); + } else if(verbose_g) + HDfprintf(stdout, "Close the file\n"); + } /* end if */ + + if(fname_g) + HDfree(fname_g); + if(dname_g) + HDfree(dname_g); + + H5Eset_auto2(H5E_DEFAULT, func, edata); + leave(h5tools_getstatus()); + +} /* end main() */ + diff --git a/tools/src/h5import/CMakeLists.txt b/tools/src/h5import/CMakeLists.txt new file mode 100644 index 0000000..97ab4ec --- /dev/null +++ b/tools/src/h5import/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required (VERSION 3.1.0) +PROJECT (HDF5_TOOLS_SRC_H5IMPORT) + +#----------------------------------------------------------------------------- +# Setup include Directories +#----------------------------------------------------------------------------- +INCLUDE_DIRECTORIES (${HDF5_TOOLS_DIR}/lib) + +# -------------------------------------------------------------------- +# Add the h5import executables +# -------------------------------------------------------------------- +add_executable (h5import ${HDF5_TOOLS_SRC_H5IMPORT_SOURCE_DIR}/h5import.c) +TARGET_NAMING (h5import STATIC) +TARGET_C_PROPERTIES (h5import STATIC " " " ") +target_link_libraries (h5import ${HDF5_TOOLS_LIB_TARGET} ${HDF5_LIB_TARGET}) +#set_target_properties (h5import PROPERTIES COMPILE_DEFINITIONS H5DEBUGIMPORT) +set_target_properties (h5import PROPERTIES FOLDER tools) +set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};h5import") + +set (H5_DEP_EXECUTABLES h5import) + +############################################################################## +############################################################################## +### I N S T A L L A T I O N ### +############################################################################## +############################################################################## + +#----------------------------------------------------------------------------- +# Rules for Installation of tools using make Install target +#----------------------------------------------------------------------------- + +#INSTALL_PROGRAM_PDB (h5import ${HDF5_INSTALL_BIN_DIR} toolsapplications) + +install ( + TARGETS + h5import + EXPORT + ${HDF5_EXPORTED_TARGETS} + RUNTIME DESTINATION ${HDF5_INSTALL_BIN_DIR} COMPONENT toolsapplications +) diff --git a/tools/src/h5import/Makefile.am b/tools/src/h5import/Makefile.am new file mode 100644 index 0000000..2eae9ec --- /dev/null +++ b/tools/src/h5import/Makefile.am @@ -0,0 +1,35 @@ +# +# Copyright by The HDF Group. +# Copyright by the Board of Trustees of the University of Illinois. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the files COPYING and Copyright.html. COPYING can be found at the root +# of the source code distribution tree; Copyright.html can be found at the +# root level of an installed copy of the electronic HDF5 document set and +# is linked from the top-level documents page. It can also be found at +# http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have +# access to either file, you may request a copy from help@hdfgroup.org. +## +## Makefile.am +## Run automake to generate a Makefile.in from this file. +# +# HDF5 Library Makefile(.in) +# + +include $(top_srcdir)/config/commence.am + +# Include src and tools/lib directories +AM_CPPFLAGS+=-I$(top_srcdir)/src -I$(top_srcdir)/tools/lib + +# Our main targets +bin_PROGRAMS=h5import + +# Add h5import specific linker flags here +h5import_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) + +# All programs depend on the main hdf5 library and the tools library +LDADD=$(LIBH5TOOLS) $(LIBHDF5) + +include $(top_srcdir)/config/conclude.am diff --git a/tools/src/h5import/h5import.c b/tools/src/h5import/h5import.c new file mode 100644 index 0000000..d1aab0c --- /dev/null +++ b/tools/src/h5import/h5import.c @@ -0,0 +1,4393 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "hdf5.h" +#include "H5private.h" +#include <stdio.h> +#include <math.h> +#include <string.h> +#include <ctype.h> +#include "h5import.h" +#include "h5tools.h" +#include "h5tools_utils.h" + +/* Name of tool */ +#define PROGRAMNAME "h5import" + +#ifdef H5_HAVE_WIN32_API +#define READ_OPEN_FLAGS "rb" +#else +#define READ_OPEN_FLAGS "r" +#endif + +/* Local function declarations */ +static int gtoken(char *s); +static int process(struct Options *opt); +static int processConfigurationFile(char *infile, struct Input *in); +static int mapKeywordToIndex(char *key); +static int parsePathInfo(struct path_info *path, char *strm); +static int parseDimensions(struct Input *in, char *strm); +static int getInputSize(struct Input *in, int ival); +static int getInputClass(struct Input *in, char * strm); +static int getInputClassType(struct Input *in, char * strm); +static int InputClassStrToInt(char *temp); +static int getRank(struct Input *in, FILE *strm); +static int getDimensionSizes(struct Input *in, FILE *strm); +static int getOutputSize(struct Input *in, FILE *strm); +static int getOutputClass(struct Input *in, FILE *strm); +static int OutputClassStrToInt(char *temp); +static int getOutputArchitecture(struct Input *in, FILE *strm); +static int OutputArchStrToInt(const char *temp); +static int getOutputByteOrder(struct Input *in, FILE *strm); +static int OutputByteOrderStrToInt(const char *temp); +static int getChunkedDimensionSizes(struct Input *in, FILE *strm); +static int getCompressionType(struct Input *in, FILE *strm); +static int CompressionTypeStrToInt(char *temp); +static int getCompressionParameter(struct Input *in, FILE *strm); +static int getExternalFilename(struct Input *in, FILE *strm); +static int getMaximumDimensionSizes(struct Input *in, FILE *strm); +static int processDataFile(char *infile, struct Input *in, hid_t file_id); +static int readIntegerData(FILE *strm, struct Input *in); +static int readFloatData(FILE *strm, struct Input *in); +static int allocateIntegerStorage(struct Input *in); +static int allocateFloatStorage(struct Input *in); +static int readUIntegerData(FILE *strm, struct Input *in); +static int allocateUIntegerStorage(struct Input *in); +static int validateConfigurationParameters(struct Input *in); +static int processStrData(FILE *strm, struct Input *in, hid_t file_id); +static int processStrHDFData(FILE *strm, struct Input *in, hid_t file_id); + +int main(int argc, char *argv[]) +{ + struct Options opt; + int outfile_named = FALSE; + int token; + int i; + int state = 0; + struct Input *in = NULL; + + const char *err1 = "Invalid number of arguments: %d.\n"; + const char *err2 = "Error in state table.\n"; + const char *err3 = "No output file given.\n"; + const char *err4 = "Program aborted.\n"; + const char *err5 = "Invalid path %s.\n"; + const char *err6 = "Invalid dimensions - %s.\n"; + const char *err7 = "Invalid type of data - %s.\n"; + const char *err8 = "Invalid size of data - %s.\n"; + const char *err9 = "Cannot specify more than 30 input files in one call to h5import.\n"; + + h5tools_setprogname(PROGRAMNAME); + h5tools_setstatus(EXIT_SUCCESS); + + /* Initialize h5tools lib */ + h5tools_init(); + + (void) HDsetvbuf(stderr, (char *) NULL, _IOLBF, 0); + (void) HDsetvbuf(stdout, (char *) NULL, _IOLBF, 0); + + if (argv[1] && (HDstrcmp("-V", argv[1]) == 0)) { + print_version(PROGRAMNAME); + HDexit(EXIT_SUCCESS); + } + + /* + * validate the number of command line arguments + */ + if (argc < 2) { + (void) HDfprintf(stderr, err1, argc); + usage(argv[0]); + goto err; + } + + /* Initialize the file structure to 0 */ + HDmemset(&opt, 0, sizeof(struct Options)); + + /* + * parse the command line + */ + for (i = 1; i < argc; i++) { + if ((token = gtoken(argv[i])) == ERR) { + usage(argv[0]); + goto err; + } + + state = state_table[state][token]; + + switch (state) { + + case 1: /* counting input files */ + if (opt.fcount < 29) { + (void) HDstrcpy(opt.infiles[opt.fcount].datafile, argv[i]); + in = &(opt.infiles[opt.fcount].in); + opt.infiles[opt.fcount].config = 0; + setDefaultValues(in, opt.fcount); + opt.fcount++; + } + else { + (void) HDfprintf(stderr, err9, argv[i]); + goto err; + } + + break; + + case 2: /* -c found; look for configfile */ + break; + + case 3: /* get configfile name */ + (void) HDstrcpy(opt.infiles[opt.fcount-1].configfile, argv[i]); + opt.infiles[opt.fcount - 1].config = 1; + break; + + case 4: /* -o found; look for outfile */ + break; + + case 5: /* get outfile found */ + (void) HDstrcpy(opt.outfile, argv[i]); + outfile_named = TRUE; + break; + + case 6: /* -h found; help, then exit */ + help(argv[0]); + HDexit(EXIT_SUCCESS); + break; + + case 7: /* -d found; look for dimensions */ + break; + + case 8: /* read dimensions */ + if (parseDimensions(in, argv[i]) == -1) { + (void) HDfprintf(stderr, err6, argv[i]); + goto err; + } + break; + + case 9: /* -p found; look for path name */ + break; + + case 10: /* read path name */ + if (parsePathInfo(&in->path, argv[i]) == -1) { + (void) HDfprintf(stderr, err5, argv[i]); + goto err; + } + break; + + case 11: /* -t found; look for data type */ + break; + + case 12: /* read data type */ + if (getInputClass(in, argv[i]) == -1) { + (void) HDfprintf(stderr, err7, argv[i]); + goto err; + } + + if (in->inputClass == 0 || in->inputClass == 4) + in->outputClass = 0; + if (in->inputClass == 1 || in->inputClass == 2 || in->inputClass == 3) + in->outputClass = 1; + if (in->inputClass == 6 || in->inputClass == 7) + in->outputClass = 2; + break; + + case 13: /* -s found; look for data size */ + break; + + case 14: /* read data size */ + if (getInputSize(in, (int) HDstrtol(argv[i], NULL, BASE_10)) == -1) { + (void) HDfprintf(stderr, err8, argv[i]); + goto err; + } + /*set default value for output-size */ + in->outputSize = in->inputSize; + break; + + case ERR: /* command syntax error */ + default: + (void) HDfprintf(stderr, "%s", err2); + usage(argv[0]); + goto err; + } + } + + if (FALSE == outfile_named) { + (void) HDfprintf(stderr, "%s", err3); + usage(argv[0]); + goto err; + } + + if (process(&opt) == -1) + goto err; + + for (i = 0; i < opt.fcount; i++) { + in = &(opt.infiles[i].in); + if (in->sizeOfDimension) + HDfree(in->sizeOfDimension); + if (in->sizeOfChunk) + HDfree(in->sizeOfChunk); + if (in->maxsizeOfDimension) + HDfree(in->maxsizeOfDimension); + if (in->externFilename) + HDfree(in->externFilename); + if (in->data) + HDfree(in->data); + } + + return (EXIT_SUCCESS); +err: + (void) HDfprintf(stderr, "%s", err4); + for (i = 0; i < opt.fcount; i++) { + in = &(opt.infiles[i].in); + if (in->sizeOfDimension) + HDfree(in->sizeOfDimension); + if (in->sizeOfChunk) + HDfree(in->sizeOfChunk); + if (in->maxsizeOfDimension) + HDfree(in->maxsizeOfDimension); + if (in->externFilename) + HDfree(in->externFilename); + if (in->data) + HDfree(in->data); + } + return (EXIT_FAILURE); +} + +static int gtoken(char *s) +{ + size_t len; + int token = ERR; + + const char *err1 = "Illegal argument: %s.\n"; + + /* + * identify the token type + */ + if (s[0] == '-') { /* option name (or negative number) */ + len = HDstrlen(&s[1]); + switch (s[1]) { + case 'o': + if (!HDstrncmp("outfile", &s[1], len)) + token = OPT_o; + break; + + case 'c': + if (!HDstrncmp("config", &s[1], len)) + token = OPT_c; + break; + + case 'h': + if (!HDstrncmp("help", &s[1], len)) + token = OPT_h; + break; + + case 'd': + if (!HDstrncmp("dims", &s[1], len)) + token = OPT_d; + break; + + case 'p': + if (!HDstrncmp("path", &s[1], len)) + token = OPT_p; + break; + + case 't': + if (!HDstrncmp("type", &s[1], len)) + token = OPT_t; + break; + + case 's': + if (!HDstrncmp("size", &s[1], len)) + token = OPT_s; + break; + default: + token = ERR; /* not a supported option tag */ + break; + } + + if (token == ERR) + (void) HDfprintf(stderr, err1, s); + } + else { /* filename */ + token = FILNAME; + } + return (token); +} + +/*------------------------------------------------------------------------- + * Function: processDataFile + * + * Purpose: allocate memory and read data file + * + * Return: 0, success, -1, error + * + * Programmer: pkmat + * + * Modifications: pvn + * 7/23/2007. Added support for STR type, extra parameter FILE_ID + * + *------------------------------------------------------------------------- + */ + +static int processDataFile(char *infile, struct Input *in, hid_t file_id) +{ + FILE *strm = NULL; + const char *err1 = "Unable to open the input file %s for reading.\n"; + const char *err2 = "Error in allocating integer data storage.\n"; + const char *err3 = "Error in allocating floating-point data storage.\n"; + const char *err4 = "Error in reading integer data.\n"; + const char *err5 = "Error in reading floating-point data.\n"; + const char *err6 = "Error in allocating unsigned integer data storage.\n"; + const char *err7 = "Error in reading unsigned integer data.\n"; + const char *err10 = "Unrecognized input class type.\n"; + const char *err11 = "Error in reading string data.\n"; + int retval = -1; + + /*------------------------------------------------------------------------- + * special case for opening binary classes in H5_HAVE_WIN32_API + * "FP" denotes a floating point binary file, + * "IN" denotes a signed integer binary file, + * "UIN" denotes an unsigned integer binary file, + *------------------------------------------------------------------------- + */ + if (in->inputClass == 4 /* "IN" */|| in->inputClass == 3 /* "FP" */|| in->inputClass == 7 /* "UIN" */) { + + if ((strm = HDfopen(infile, READ_OPEN_FLAGS)) == NULL) { + (void) HDfprintf(stderr, err1, infile); + goto error; + } + } + /*------------------------------------------------------------------------- + * if the input class is not binary, just use "r" + *------------------------------------------------------------------------- + */ + else { + if ((strm = HDfopen(infile, "r")) == NULL) { + (void) HDfprintf(stderr, err1, infile); + goto error; + } + } + + switch (in->inputClass) { + case 0: /* TEXTIN */ + case 4: /* IN */ + if (allocateIntegerStorage(in) == -1) { + (void) HDfprintf(stderr, err2, infile); + goto error; + } + + if (readIntegerData(strm, in) == -1) { + (void) HDfprintf(stderr, err4, infile); + goto error; + } + break; + + case 1: /* TEXTFP */ + case 2: /* TEXTFPE */ + case 3: /* FP */ + if (allocateFloatStorage(in) == -1) { + (void) HDfprintf(stderr, err3, infile); + goto error; + + } + + if (readFloatData(strm, in) == -1) { + (void) HDfprintf(stderr, err5, infile); + goto error; + } + break; + + case 5: /* STR */ + if (in->h5dumpInput) { + if (processStrHDFData(strm, in, file_id) == -1) { + (void) HDfprintf(stderr, err11, infile); + goto error; + } + } + else { + if (processStrData(strm, in, file_id) == -1) { + (void) HDfprintf(stderr, err11, infile); + goto error; + } + } + + break; + + case 6: /* TEXTUIN */ + case 7: /* UIN */ + if (allocateUIntegerStorage(in) == -1) { + (void) HDfprintf(stderr, err6, infile); + goto error; + } + if (readUIntegerData(strm, in) == -1) { + (void) HDfprintf(stderr, err7, infile); + goto error; + } + break; + + default: + (void) HDfprintf(stderr, "%s", err10); + goto error; + } + + /* Set success return value */ + retval = 0; + +error: + if(strm) + HDfclose(strm); + return(retval); +} + +static int readIntegerData(FILE *strm, struct Input *in) +{ + H5DT_INT8 *in08; + H5DT_INT16 *in16; + H5DT_INT16 temp; + H5DT_INT32 *in32; +#ifdef H5_SIZEOF_LONG_LONG + H5DT_INT64 *in64; + char buffer[256]; +#endif + hsize_t len = 1; + hsize_t i; + int j; + + const char *err1 = "Unable to get integer value from file.\n"; + const char *err2 = "Unrecognized input class type.\n"; + const char *err3 = "Invalid input size.\n"; + + for (j = 0; j < in->rank; j++) + len *= in->sizeOfDimension[j]; + + switch (in->inputSize) { + case 8: + switch (in->inputClass) { + case 0: /* TEXTIN */ + in08 = (H5DT_INT8 *) in->data; + for (i = 0; i < len; i++, in08++) { + if (fscanf(strm, "%hd", &temp) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + (*in08) = (H5DT_INT8) temp; + } + break; + + case 4: /* IN */ + in08 = (H5DT_INT8 *) in->data; + for (i = 0; i < len; i++, in08++) { + if (HDfread((char *) in08, sizeof(H5DT_INT8), 1, strm) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; + + case 16: + in16 = (H5DT_INT16 *) in->data; + switch (in->inputClass) { + case 0: /* TEXTIN */ + for (i = 0; i < len; i++, in16++) { + if (fscanf(strm, "%hd", in16) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + in16 = (H5DT_INT16 *) in->data; + break; + + case 4: /* IN */ + for (i = 0; i < len; i++, in16++) { + if (HDfread((char *) in16, sizeof(H5DT_INT16), 1, strm) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; + + case 32: + in32 = (H5DT_INT32 *) in->data; + switch (in->inputClass) { + case 0: /* TEXTIN */ + for (i = 0; i < len; i++, in32++) { + if (fscanf(strm, "%d", in32) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + break; + + case 4: /* IN */ + for (i = 0; i < len; i++, in32++) { + if (HDfread((char *) in32, sizeof(H5DT_INT32), 1, strm) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; + +#ifdef H5_SIZEOF_LONG_LONG + case 64: + in64 = (H5DT_INT64 *) in->data; + switch (in->inputClass) { + case 0: /* TEXTIN */ + for (i = 0; i < len; i++, in64++) { + if (fscanf(strm, "%s", buffer) < 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + *in64 = (H5DT_INT64) HDstrtoll(buffer, NULL, 10); + } + break; + + case 4: /* IN */ + for (i = 0; i < len; i++, in64++) { + if (HDfread((char *) in64, sizeof(H5DT_INT64), 1, strm) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; +#endif /* ifdef H5_SIZEOF_LONG_LONG */ + + default: + (void) HDfprintf(stderr, "%s", err3); + break; + } + return (0); +} + +static int readUIntegerData(FILE *strm, struct Input *in) +{ + H5DT_UINT8 *in08; + H5DT_UINT16 *in16; + H5DT_UINT16 temp; + H5DT_UINT32 *in32; +#ifdef H5_SIZEOF_LONG_LONG + H5DT_UINT64 *in64; + char buffer[256]; +#endif + hsize_t len = 1; + hsize_t i; + int j; + const char *err1 = "Unable to get unsigned integer value from file.\n"; + const char *err2 = "Unrecognized input class type.\n"; + const char *err3 = "Invalid input size.\n"; + + for (j = 0; j < in->rank; j++) + len *= in->sizeOfDimension[j]; + + switch (in->inputSize) { + case 8: + switch (in->inputClass) { + case 6: /* TEXTUIN */ + in08 = (H5DT_UINT8 *) in->data; + for (i = 0; i < len; i++, in08++) { + if (fscanf(strm, "%hu", &temp) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + (*in08) = (H5DT_UINT8) temp; + } + break; + + case 7: /* UIN */ + in08 = (H5DT_UINT8 *) in->data; + for (i = 0; i < len; i++, in08++) { + if (HDfread((char *) in08, sizeof(H5DT_UINT8), 1, strm) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; + + case 16: + in16 = (H5DT_UINT16 *) in->data; + switch (in->inputClass) { + case 6: /* TEXTUIN */ + for (i = 0; i < len; i++, in16++) { + if (fscanf(strm, "%hu", in16) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + break; + + case 7: /* UIN */ + for (i = 0; i < len; i++, in16++) { + if (HDfread((char *) in16, sizeof(H5DT_UINT16), 1, strm) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; + + case 32: + in32 = (H5DT_UINT32 *) in->data; + switch (in->inputClass) { + case 6: /* TEXTUIN */ + for (i = 0; i < len; i++, in32++) { + if (fscanf(strm, "%u", in32) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + break; + + case 7: /* UIN */ + for (i = 0; i < len; i++, in32++) { + if (HDfread((char *) in32, sizeof(H5DT_UINT32), 1, strm) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; + +#ifdef H5_SIZEOF_LONG_LONG + case 64: + in64 = (H5DT_UINT64 *) in->data; + switch (in->inputClass) { + case 6: /* TEXTUIN */ + for (i = 0; i < len; i++, in64++) { + if (fscanf(strm, "%s", buffer) < 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + *in64 = (H5DT_UINT64) HDstrtoll(buffer, NULL, 10); + } + break; + + case 7: /* UIN */ + for (i = 0; i < len; i++, in64++) { + if (HDfread((char *) in64, sizeof(H5DT_UINT64), 1, strm) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; +#endif /* ifdef H5_SIZEOF_LONG_LONG */ + + default: + (void) HDfprintf(stderr, "%s", err3); + break; + } + return (0); +} + +static int readFloatData(FILE *strm, struct Input *in) +{ + H5DT_FLOAT32 *fp32; + H5DT_FLOAT64 *fp64; + + hsize_t len = 1; + hsize_t i; + int j; + const char *err1 = "Unable to get integer value from file.\n"; + const char *err2 = "Unrecognized input class type.\n"; + const char *err3 = "Invalid input size type.\n"; + + for (j = 0; j < in->rank; j++) + len *= in->sizeOfDimension[j]; + + switch (in->inputSize) { + case 32: + fp32 = (H5DT_FLOAT32 *) in->data; + switch (in->inputClass) { + case 1: /* TEXTFP */ + for (i = 0; i < len; i++, fp32++) { + if (fscanf(strm, "%f", fp32) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + + fp32 = (H5DT_FLOAT32 *) in->data; + break; + + /* same as TEXTFP */ + case 2: /*TEXTFPE */ + + for (i = 0; i < len; i++, fp32++) { + if (fscanf(strm, "%f", fp32) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + + fp32 = (H5DT_FLOAT32 *) in->data; + break; + + case 3: /* FP */ + for (i = 0; i < len; i++, fp32++) { + if (HDfread((char *) fp32, sizeof(H5DT_FLOAT32), 1, strm) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; + + case 64: + fp64 = (H5DT_FLOAT64 *) in->data; + switch (in->inputClass) { + case 1: /* TEXTFP */ + for (i = 0; i < len; i++, fp64++) { + if (fscanf(strm, "%lf", fp64) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + + fp64 = (H5DT_FLOAT64 *) in->data; + break; + + /* same as TEXTFP */ + case 2: /*TEXTFPE */ + + for (i = 0; i < len; i++, fp64++) { + if (fscanf(strm, "%lf", fp64) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + + fp64 = (H5DT_FLOAT64 *) in->data; + break; + + case 3: /* FP */ + for (i = 0; i < len; i++, fp64++) { + if (HDfread((char *) fp64, sizeof(H5DT_FLOAT64), 1, strm) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; + + default: + (void) HDfprintf(stderr, "%s", err3); + break; + } + return (0); +} + +/*------------------------------------------------------------------------- + * Function: processStrData + * + * Purpose: read an ASCII file with string data and generate an HDF5 dataset + * with a variable length type + * + * Return: 0, ok, -1 no + * + * Programmer: Pedro Vicente, pvn@hdfgroup.org + * + * Date: July, 26, 2007 + * + *------------------------------------------------------------------------- + */ +static int processStrData(FILE *strm, struct Input *in, hid_t file_id) +{ + hid_t group_id; + hid_t dset_id; + hid_t space_id; + hid_t mspace_id; + hid_t type_id; + hid_t handle; + hsize_t dims[1]; + char str[1024]; + int c; + int i = 0; + int j; + hsize_t nlines = 0; + hsize_t line; + + /*------------------------------------------------------------------------- + * get number of lines in the input file + *------------------------------------------------------------------------- + */ + + while(EOF != (c = HDfgetc(strm))) + if (c == 10) /* eol */ + nlines++; + + if (!nlines) + return 0; + + /* number of records */ + dims[0] = nlines; + + /* rewind */ + HDfseek(strm, 0L, 0); + + /*------------------------------------------------------------------------- + * read file again and generate an HDF5 dataset + *------------------------------------------------------------------------- + */ + + if ((type_id = H5Tcopy(H5T_C_S1)) < 0) + goto out; + + if (H5Tset_size(type_id, H5T_VARIABLE) < 0) + goto out; + + /* disable error reporting */ + H5E_BEGIN_TRY + { + /* create parent groups */ + if (in->path.count > 1) { + j = 0; + handle = file_id; + while (j < in->path.count - 1) { + if ((group_id = H5Gopen2(handle, in->path.group[j], H5P_DEFAULT)) < 0) { + group_id = H5Gcreate2(handle, in->path.group[j++], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + for (; j < in->path.count - 1; j++) + group_id = H5Gcreate2(group_id, in->path.group[j], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + handle = group_id; + break; + } + handle = group_id; + j++; + } + } + else { + handle = file_id; + j = 0; + } + + /*enable error reporting */ + } + H5E_END_TRY; + + if ((space_id = H5Screate_simple(1, dims, NULL)) < 0) + goto out; + + if ((mspace_id = H5Screate(H5S_SCALAR)) < 0) + goto out; + + if ((dset_id = H5Dcreate2(handle, in->path.group[j], type_id, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + goto out; + + line = 0; + + while(EOF != (c = HDfgetc(strm))) { + str[i] = (char)c; + + i++; + + if (c == 10) { /* eol */ + char *str2 = str; + hid_t fspace_id; + hsize_t start[1]; + hsize_t count[1] = { 1 }; + + str[i - 1] = '\0'; /* terminate string */ + + if ((fspace_id = H5Dget_space(dset_id)) < 0) + goto out; + + start[0] = line++; + + if (H5Sselect_hyperslab(fspace_id, H5S_SELECT_SET, start, NULL, count, NULL) < 0) + goto out; + + if (H5Dwrite(dset_id, type_id, mspace_id, fspace_id, H5P_DEFAULT, &str2) < 0) + goto out; + + if (H5Sclose(fspace_id) < 0) + goto out; + + i = 0; + str[0] = '\0'; + + } + } + + /* close */ + H5Dclose(dset_id); + H5Sclose(space_id); + H5Sclose(mspace_id); + H5Tclose(type_id); + + return (0); + +out: + + return (-1); +} + +/*------------------------------------------------------------------------- + * Function: processStrData + * + * Purpose: read an ASCII file with string data and generate an HDF5 dataset + * with a variable length type + * + * Return: 0, ok, -1 no + * + *------------------------------------------------------------------------- + */ +static int processStrHDFData(FILE *strm, struct Input *in, hid_t file_id) +{ + hid_t group_id = -1; + hid_t dset_id = -1; + hid_t space_id = -1; + hid_t mspace_id = -1; + hid_t type_id = -1; + hid_t handle = -1; + char *str1 = NULL; + char *str2 = NULL; + char *str3 = NULL; + char str[1024] = ""; + int j; + hsize_t line; + + /*------------------------------------------------------------------------- + * read file and generate an HDF5 dataset + *------------------------------------------------------------------------- + */ +#ifdef H5DEBUGIMPORT + printf("processStrHDFData DATATYPE STRING\n"); +#endif + + if ((type_id = H5Tcopy(H5T_C_S1)) < 0) + goto out; + + if (H5Tset_size(type_id, H5T_VARIABLE) < 0) + goto out; + + /* disable error reporting */ + H5E_BEGIN_TRY + { + /* create parent groups */ + if (in->path.count > 1) { + j = 0; + handle = file_id; + while (j < in->path.count - 1) { + if ((group_id = H5Gopen2(handle, in->path.group[j], H5P_DEFAULT)) < 0) { + group_id = H5Gcreate2(handle, in->path.group[j++], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + for (; j < in->path.count - 1; j++) + group_id = H5Gcreate2(group_id, in->path.group[j], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + handle = group_id; + break; + } + handle = group_id; + j++; + } + } + else { + handle = file_id; + j = 0; + } + + /*enable error reporting */ + } + H5E_END_TRY; +#ifdef H5DEBUGIMPORT + printf("processStrHDFData DATATYPE STRING groups created\n"); +#endif + + if ((space_id = H5Screate_simple(in->rank, in->sizeOfDimension, NULL)) < 0) + goto out; + + if ((mspace_id = H5Screate(H5S_SCALAR)) < 0) + goto out; + + if ((dset_id = H5Dcreate2(handle, in->path.group[j], type_id, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) + goto out; + +#ifdef H5DEBUGIMPORT + printf("processStrHDFData DATATYPE STRING ready to process strings\n"); +#endif + line = 0; + j = 0; + + while (HDfgets(str,sizeof(str),strm)) { + str1 = str; + str2 = NULL; + str3 = NULL; +#ifdef H5DEBUGIMPORT + printf("processStrHDFData DATATYPE STRING[%llu]={%s}\n", (unsigned long long)line, str1); +#endif + /* process string to remove the first and last quote char */ + str2 = strchr(str1, '"'); + if (str2 != NULL) { +#ifdef H5DEBUGIMPORT + printf("processStrHDFData DATATYPE STRING len:%d for {%s}\n", strlen(str2), str2); +#endif + str2++; +#ifdef H5DEBUGIMPORT + printf("processStrHDFData DATATYPE STRING len:%d for {%s}\n", strlen(str2), str2); +#endif + str3 = strrchr(str2, '"'); + if (str3 != NULL) { +#ifdef H5DEBUGIMPORT + printf("processStrHDFData DATATYPE STRING len:%d for {%s}\n", strlen(str3), str3); +#endif + *str3 = '\0'; + +#ifdef H5DEBUGIMPORT + printf("processStrHDFData DATATYPE STRING len:%d for {%s}\n", strlen(str2), str2); +#endif + + if(strlen(str2) > 0) { + hid_t fspace_id; + hsize_t start[1]; + hsize_t count[1] = { 1 }; + +#ifdef H5DEBUGIMPORT + printf("processStrHDFData DATATYPE STRING[%llu] store %s\n", (unsigned long long)line, str2); +#endif + if ((fspace_id = H5Dget_space(dset_id)) < 0) + goto out; + + start[0] = line++; + + if (H5Sselect_hyperslab(fspace_id, H5S_SELECT_SET, start, NULL, count, NULL) < 0) + goto out; + + if (H5Dwrite(dset_id, type_id, mspace_id, fspace_id, H5P_DEFAULT, &str2) < 0) + goto out; + + if (H5Sclose(fspace_id) < 0) + goto out; + } + } + } + str[0] = '\0'; + j++; + } +#ifdef H5DEBUGIMPORT + printf("processStrHDFData DATATYPE STRING eof reached\n"); +#endif + + /* close */ + H5Dclose(dset_id); + H5Sclose(space_id); + H5Sclose(mspace_id); + H5Tclose(type_id); + + return (0); + +out: +#ifdef H5DEBUGIMPORT + printf("processStrHDFData DATATYPE STRING error exit\n"); +#endif +/* disable error reporting */ +H5E_BEGIN_TRY +{ + /* close */ + H5Dclose(dset_id); + H5Sclose(space_id); + H5Sclose(mspace_id); + H5Tclose(type_id); +} +H5E_END_TRY; + + return (-1); +} + +static int allocateIntegerStorage(struct Input *in) +{ + hsize_t len = 1; + int j; + const char *err1 = "Unable to allocate dynamic memory.\n"; + const char *err2 = "Invalid storage size for integer input data.\n"; + + for (j = 0; j < in->rank; j++) + len *= in->sizeOfDimension[j]; + + switch (in->inputSize) { + case 8: + if ((in->data = (VOIDP) HDmalloc((size_t) len * sizeof(H5DT_INT8))) == NULL) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + break; + + case 16: + if ((in->data = (VOIDP) HDmalloc((size_t) len * sizeof(H5DT_INT16))) == NULL) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + break; + + case 32: + if ((in->data = (VOIDP) HDmalloc((size_t) len * sizeof(H5DT_INT32))) == NULL) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + break; + + case 64: + if ((in->data = (VOIDP) HDmalloc((size_t) len * sizeof(H5DT_INT64))) == NULL) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + break; + } + return (0); +} + +static int allocateUIntegerStorage(struct Input *in) +{ + hsize_t len = 1; + const char *err1 = "Unable to allocate dynamic memory.\n"; + const char *err2 = "Invalid storage size for unsigned integer input data.\n"; + int j; + + for (j = 0; j < in->rank; j++) + len *= in->sizeOfDimension[j]; + + switch (in->inputSize) { + case 8: + if ((in->data = (VOIDP) HDmalloc((size_t) len * sizeof(H5DT_UINT8))) == NULL) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + break; + + case 16: + if ((in->data = (VOIDP) HDmalloc((size_t) len * sizeof(H5DT_UINT16))) == NULL) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + break; + + case 32: + if ((in->data = (VOIDP) HDmalloc((size_t) len * sizeof(H5DT_UINT32))) == NULL) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + break; + + case 64: + if ((in->data = (VOIDP) HDmalloc((size_t) len * sizeof(H5DT_UINT64))) == NULL) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + break; + } + return (0); +} + +static int allocateFloatStorage(struct Input *in) +{ + hsize_t len = 1; + int j; + const char *err1 = "Unable to allocate dynamic memory.\n"; + const char *err2 = "Invalid storage size for float input data.\n"; + + for (j = 0; j < in->rank; j++) + len *= in->sizeOfDimension[j]; + + switch (in->inputSize) { + case 32: + if ((in->data = (VOIDP) HDmalloc((size_t) len * sizeof(H5DT_FLOAT32))) == NULL) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + break; + + case 64: + if ((in->data = (VOIDP) HDmalloc((size_t) len * sizeof(H5DT_FLOAT64))) == NULL) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + break; + } + return (0); +} + +static int processConfigurationFile(char *infile, struct Input *in) +{ + FILE *strm = NULL; + char key[255]; + int kindex; + char temp[255]; + int ival; + int scanret; + int retval = -1; + + const char *err1 = "Unable to open the configuration file: %s for reading.\n"; + const char *err2 = "Unknown keyword in configuration file: %s\n"; + const char *err3a = "PATH keyword appears twice in %s.\n"; + const char *err3b = "Error in parsing the path information from %s.\n"; + const char *err4a = "INPUT-CLASS keyword appears twice in %s.\n"; + const char *err4b = "Error in retrieving the input class from %s.\n"; + const char *err5a = "INPUT-SIZE keyword appears twice in %s.\n"; + const char *err5b = "Error in retrieving the input size from %s.\n"; + const char *err6a = "RANK keyword appears twice in %s.\n"; + const char *err6b = "Error in retrieving the rank from %s.\n"; + const char *err7a = "DIMENSION-SIZES keyword appears twice in %s.\n"; + const char *err7b = "DIMENSION-SIZES cannot appear before RANK is provided.\n"; + const char *err7c = "Error in retrieving the dimension sizes from %s.\n"; + const char *err8a = "OUTPUT-CLASS keyword appears twice in %s.\n"; + const char *err8b = "Error in retrieving the output class from %s.\n"; + const char *err9a = "OUTPUT-SIZE keyword appears twice in %s.\n"; + const char *err9b = "Error in retrieving the output size from %s.\n"; + const char *err10a = "OUTPUT-ARCHITECTURE keyword appears twice in %s.\n"; + const char *err10b = "Error in retrieving the output architecture from %s.\n"; + const char *err11a = "OUTPUT-BYTE-ORDER keyword appears twice in %s.\n"; + const char *err11b = "Error in retrieving the output byte order from %s.\n"; + const char *err12a = "CHUNKED-DIMENSION-SIZES keyword appears twice in %s.\n"; + const char *err12b = "CHUNKED-DIMENSION-SIZES cannot appear before DIMENSION-SIZES are provided.\n"; + const char *err12c = "Error in retrieving the chunked dimension sizes from %s.\n"; + const char *err13a = "COMPRESSION-TYPE keyword appears twice in %s.\n"; + const char *err13b = "Error in retrieving the compression type from %s.\n"; + const char *err14a = "COMPRESSION-PARAM keyword appears twice in %s.\n"; + const char *err14b = "Error in retrieving the compression parameter from %s.\n"; + const char *err15a = "EXTERNAL-STORAGE keyword appears twice in %s.\n"; + const char *err15b = "Error in retrieving the external storage paramters from %s.\n"; + const char *err16a = "MAXIMUM-DIMENSIONS keyword appears twice in %s.\n"; + const char *err16b = "MAXIMUM-DIMENSIONS cannot appear before DIMENSION-SIZES are provided.\n"; + const char *err16c = "Error in retrieving the maximum dimension sizes from %s.\n"; + const char *err17 = "Configuration parameters are invalid in %s.\n"; + const char *err18 = "Unable to get string value.\n"; + const char *err19 = "Unable to get integer value.\n"; + + /* create vector to map which keywords have been found + check vector after each keyword to check for violation + at the end check vector to see if required fields have been provided + process the output file according to the options + */ + + if ((strm = HDfopen(infile, "r")) == NULL) { + (void) HDfprintf(stderr, err1, infile); + goto error; + } + + scanret = fscanf(strm, "%s", key); + if((scanret == 1) && !HDstrcmp("HDF5", key)) { +#ifdef H5DEBUGIMPORT + int pndx; + printf("\nh5dump file\n"); +#endif + in->h5dumpInput = 1; + scanret = fscanf(strm, "%s", temp); /* filename */ + scanret = fscanf(strm, "%s", temp); /* start bracket */ + scanret = fscanf(strm, "%s", key); /* DATASET */ + while (scanret == 1) { + if(!HDstrcmp("DATASET", key)) { /* PATH */ +#ifdef H5DEBUGIMPORT + printf("h5dump DATASET key\n"); +#endif + if (in->configOptionVector[PATH] == 1) { + (void) HDfprintf(stderr, err3a, infile); + goto error; + } + if (fscanf(strm, "%s", temp) != 1) { + (void) HDfprintf(stderr, "%s", err18); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATASET %s found\n", temp); +#endif + if (parsePathInfo(&in->path, temp) == -1) { + (void) HDfprintf(stderr, err3b, infile); + goto error; + } + in->configOptionVector[PATH] = 1; + scanret = fscanf(strm, "%s", temp); /* start bracket */ +#ifdef H5DEBUGIMPORT + printf("h5dump DATASET %s found\n", temp); +#endif + } /* if(!HDstrcmp("DATASET", key)) PATH */ + else if(!HDstrcmp("DATATYPE", key)) { /* INPUT-CLASS */ +#ifdef H5DEBUGIMPORT + printf("h5dump DATATYPE key\n"); +#endif + if (in->configOptionVector[INPUT_CLASS] == 1) { + (void) HDfprintf(stderr, err4a, infile); + goto error; + } + + if (fscanf(strm, "%s", temp) != 1) { + (void) HDfprintf(stderr, "%s", err18); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATATYPE %s found\n", temp); +#endif + if ((kindex = getInputClassType(in, temp)) == -1) { + (void) HDfprintf(stderr, err4b, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATATYPE type %d inputClass\n", in->inputClass); +#endif + + in->configOptionVector[INPUT_CLASS] = 1; + + /*set default value for output-class */ + if (in->configOptionVector[OUTPUT_CLASS] == 0) { + if (in->inputClass == 0 || in->inputClass == 4) + in->outputClass = 0; + if (in->inputClass == 1 || in->inputClass == 2 + || in->inputClass == 3) + in->outputClass = 1; + if (in->inputClass == 6 || in->inputClass == 7) + in->outputClass = 2; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATATYPE type %d outputClass\n", in->outputClass); +#endif + + if(in->inputClass == 5) { /* STRING */ + int get_next_prop = 1; + in->outputClass = -1; +#ifdef H5DEBUGIMPORT + printf("h5dump DATATYPE STRING found\n"); +#endif + if (fscanf(strm, "%s", temp) != 1) { /* start bracket */ + (void) HDfprintf(stderr, "%s", err18); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATATYPE STRING %s found\n", temp); +#endif + if (fscanf(strm, "%s", temp) != 1) { /* string properties */ + (void) HDfprintf(stderr, "%s", err18); + goto error; + } + while (get_next_prop) { + if(!HDstrcmp("STRSIZE", temp)) { /* STRSIZE */ + if (fscanf(strm, "%s", temp) != 1) { + (void) HDfprintf(stderr, "%s", err19); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATATYPE STRING STRSIZE %s found\n", temp); +#endif + if (HDstrcmp("H5T_VARIABLE;", temp)) { + char *more = temp; + ival = (int)HDstrtol(more, &more, 10); + if (getInputSize(in, ival) == -1) { + (void) HDfprintf(stderr, err5b, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATATYPE STRING %d InputSize\n", in->inputSize); +#endif + } + } + else if(!HDstrcmp("STRPAD", temp)) { /* STRPAD */ + if (fscanf(strm, "%s", temp) != 1) { /* STRPAD type */ + (void) HDfprintf(stderr, "%s", err18); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATATYPE STRING STRPAD %s found\n", temp); +#endif + } + else if(!HDstrcmp("CSET", key)) { /* CSET */ + if (fscanf(strm, "%s", temp) != 1) { /* CSET type */ + (void) HDfprintf(stderr, "%s", err18); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATATYPE STRING CSET %s found\n", temp); +#endif + + } + else if(!HDstrcmp("CTYPE", temp)) { /* CTYPE */ + if (fscanf(strm, "%s", temp) != 1) { /* CTYPE type */ + (void) HDfprintf(stderr, "%s", err18); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATATYPE STRING CTYPE %s found\n", temp); +#endif + } /* if(!HDstrcmp("CSET", key)) */ + if (fscanf(strm, "%s", temp) != 1) { + (void) HDfprintf(stderr, "%s", err18); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATATYPE STRING %s found\n", temp); +#endif + if(!HDstrcmp("}", temp)) { /* end bracket */ + get_next_prop = 0; + } + } /* while (get_next_prop) */ + } /* if(kindex == 5) STRING */ + } /* else if(!HDstrcmp("DATATYPE", key)) INPUT-CLASS */ + else if(!HDstrcmp("DATASPACE", key)) { /* RANK and DIMENSIONS */ + hsize_t temp_dims[MAX_NUM_DIMENSION]; + +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE key\n"); +#endif + if (fscanf(strm, "%s", temp) != 1) { + (void) HDfprintf(stderr, "%s", err18); + goto error; + } + if(!HDstrcmp("SCALAR", temp)) { /* SCALAR */ + in->rank = 0; + } /* if(!HDstrcmp("SCALAR", key)) */ + else if(!HDstrcmp("NULL", temp)) { /* NULL */ + (void) HDfprintf(stderr, err6b, infile); + goto error; + } /* else if(!HDstrcmp("NULL", key)) */ + else if(!HDstrcmp("SIMPLE", temp)) { /* SIMPLE */ + int icount = 0; +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE SIMPLE found\n"); +#endif + if (fscanf(strm, "%s", temp) != 1) { /* start bracket */ + (void) HDfprintf(stderr, err6b, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE SIMPLE %s found\n", temp); +#endif + if (fscanf(strm, "%s", temp) != 1) { /* start paren */ + (void) HDfprintf(stderr, err6b, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE SIMPLE %s found\n", temp); +#endif + if(!HDstrcmp("(", temp)) { /* start paren */ + int get_next_dim = 1; + int i = 0; + + if (fscanf(strm, "%s", temp) != 1) { /* Dimension with optional comma */ + (void) HDfprintf(stderr, err16c, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE SIMPLE %s found\n", temp); +#endif + while (get_next_dim) { + char *more = temp; + temp_dims[icount] = HDstrtoull(more, &more, 10); + if (fscanf(strm, "%s", temp) != 1) { /* Dimension or end paren */ + (void) HDfprintf(stderr, err6b, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE SIMPLE %s found\n", temp); +#endif + if(!HDstrcmp(")", temp)) { /* end paren */ + in->rank = ++icount; + in->configOptionVector[RANK] = 1; + get_next_dim = 0; + } + else { /* Dimension */ + icount++; + if (icount > MAX_NUM_DIMENSION) { + (void) HDfprintf(stderr, "Invalid value for rank.\n"); + goto error; + } + } + } /* while (get_next_dim) */ + + if ((in->sizeOfDimension = (hsize_t *) HDmalloc ((size_t) in->rank * sizeof(hsize_t))) == NULL) { + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE SIMPLE %d rank\n", in->rank); +#endif + for (i = 0; i < in->rank; i++) { + in->sizeOfDimension[i] = temp_dims[i]; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE SIMPLE dims:", in->rank); + for (pndx = 0; pndx < in->rank; pndx++) { + printf(" %d", in->sizeOfDimension[pndx]); + } + printf("\n"); +#endif + in->configOptionVector[DIM] = 1; + } /* if(!HDstrcmp("(", key)) start paren */ + else { + (void) HDfprintf(stderr, err5b, infile); + goto error; + } + if (fscanf(strm, "%s", temp) != 1) { + (void) HDfprintf(stderr, "%s", err18); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE SIMPLE %s found\n", temp); +#endif + if(!HDstrcmp("/", temp)) { /* / max dims */ + if ((in->maxsizeOfDimension = (hsize_t *) HDmalloc ((size_t) in->rank * sizeof(hsize_t))) == NULL) { + goto error; + } + if (fscanf(strm, "%s", temp) != 1) { /* start paren */ + (void) HDfprintf(stderr, err6b, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE SIMPLE %s found\n", temp); +#endif + if(!HDstrcmp("(", temp)) { /* start paren */ + int get_next_dim = 1; + int i = 0; + +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE SIMPLE process max dim values\n"); +#endif + if (fscanf(strm, "%s", temp) != 1) { /* max dim with optional comma */ + (void) HDfprintf(stderr, err16c, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE SIMPLE %s found\n", temp); +#endif + while (get_next_dim) { +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE SIMPLE get max dim value\n"); +#endif + if(!HDstrcmp("H5S_UNLIMITED", temp) || !HDstrcmp("H5S_UNLIMITED,", temp)) { /* unlimited */ + in->maxsizeOfDimension[i] = H5S_UNLIMITED; + in->configOptionVector[EXTEND] = 1; + } + else { + char *more = temp; + in->maxsizeOfDimension[i] = HDstrtoull(more, &more, 10); + } + if (fscanf(strm, "%s", temp) != 1) { /* max dim or end paren */ + (void) HDfprintf(stderr, err16c, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE SIMPLE %s found\n", temp); +#endif + if(!HDstrcmp(")", temp)) { /* end paren */ + get_next_dim = 0; + } + else { /* comma */ + i++; + if (i > MAX_NUM_DIMENSION) { + (void) HDfprintf(stderr, "Invalid value for rank.\n"); + goto error; + } + } + } /* while (get_next_dim) */ +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE SIMPLE maxdims:", in->rank); + for (pndx = 0; pndx < in->rank; pndx++) { + printf(" %d", in->maxsizeOfDimension[pndx]); + } + printf("\n"); + printf("h5dump DATASPACE SIMPLE get max dim finished\n"); +#endif + } /* if(!HDstrcmp("(", key)) start paren */ + else { + (void) HDfprintf(stderr, err16c, infile); + goto error; + } + scanret = fscanf(strm, "%s", temp); /* end bracket */ +#ifdef H5DEBUGIMPORT + printf("h5dump DATASPACE SIMPLE %s found\n", temp); +#endif + } /* if(!HDstrcmp("/", key)) max dims separator */ + } /* else if(!HDstrcmp("SIMPLE", key)) */ + else { + (void) HDfprintf(stderr, err5b, infile); + goto error; + } + } /* else if(!HDstrcmp("DATASPACE", key)) RANK and DIMENSIONS */ + else if(!HDstrcmp("STORAGE_LAYOUT", key)) { /* CHUNKED-DIMENSION-SIZES */ +#ifdef H5DEBUGIMPORT + printf("h5dump STORAGE_LAYOUT key\n"); +#endif + if (fscanf(strm, "%s", temp) != 1) { /* start bracket */ + (void) HDfprintf(stderr, err6b, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump STORAGE_LAYOUT %s found\n", temp); +#endif + if (fscanf(strm, "%s", temp) != 1) { /* CHUNKED */ + (void) HDfprintf(stderr, err6b, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump STORAGE_LAYOUT %s found\n", temp); +#endif + if(!HDstrcmp("CHUNKED", temp)) { /* CHUNKED */ + if ((in->sizeOfChunk = (hsize_t *) HDmalloc ((size_t) in->rank * sizeof(hsize_t))) == NULL) { + (void) HDfprintf(stderr, "Unable to allocate dynamic memory.\n"); + goto error; + } + if (fscanf(strm, "%s", temp) != 1) { /* start paren */ + (void) HDfprintf(stderr, err6b, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump STORAGE_LAYOUT CHUNKED %s found\n", temp); +#endif + if(!HDstrcmp("(", temp)) { /* start paren */ + int get_next_dim = 1; + int icount = 0; + + if (fscanf(strm, "%s", temp) != 1) { /* Dimension with optional comma */ + (void) HDfprintf(stderr, err16c, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump STORAGE_LAYOUT CHUNKED %s found\n", temp); +#endif + while (get_next_dim) { + char *more = temp; + in->sizeOfChunk[icount] = HDstrtoull(more, &more, 10); + if (fscanf(strm, "%s", temp) != 1) { /* Dimension or end paren */ + (void) HDfprintf(stderr, err6b, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump STORAGE_LAYOUT CHUNKED %s found\n", temp); +#endif + if(!HDstrcmp(")", temp)) { /* end paren */ + in->configOptionVector[RANK] = 1; + get_next_dim = 0; + } + else { /* Dimension */ + icount++; + if (icount > MAX_NUM_DIMENSION) { + (void) HDfprintf(stderr, "Invalid value for rank.\n"); + goto error; + } + } + } /* while (get_next_dim) */ +#ifdef H5DEBUGIMPORT + printf("h5dump STORAGE_LAYOUT CHUNKED dims:", in->rank); + for (pndx = 0; pndx < in->rank; pndx++) { + printf(" %d", in->sizeOfChunk[pndx]); + } + printf("\n"); +#endif + in->configOptionVector[DIM] = 1; + } /* if(!HDstrcmp("(", key)) start paren */ + else { + (void) HDfprintf(stderr, err5b, infile); + goto error; + } + if (fscanf(strm, "%s", temp) != 1) { /* SIZE */ + (void) HDfprintf(stderr, err6b, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump STORAGE_LAYOUT CHUNKED %s found\n", temp); +#endif + if(!HDstrcmp("SIZE", temp)) { /* SIZE */ + if (fscanf(strm, "%d", (&ival)) != 1) { + (void) HDfprintf(stderr, "%s", err19); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump STORAGE_LAYOUT CHUNKED SIZE %d found\n", ival); +#endif + } + while (HDstrcmp("}", temp)) { + if (fscanf(strm, "%s", temp) != 1) { /* end bracket */ + (void) HDfprintf(stderr, "%s", err18); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump STORAGE_LAYOUT CHUNKED %s found\n", temp); +#endif + } + in->configOptionVector[CHUNK] = 1; + } /* if(!HDstrcmp("CHUNKED", key)) CHUNKED */ + } /* else if(!HDstrcmp("STORAGE_LAYOUT", key)) CHUNKED-DIMENSION-SIZES */ + else if(!HDstrcmp("FILTERS", key)) { /* FILTERS */ +#ifdef H5DEBUGIMPORT + printf("h5dump FILTERS key\n"); +#endif + if (fscanf(strm, "%s", temp) != 1) { /* start bracket */ + (void) HDfprintf(stderr, err6b, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump FILTERS %s found\n", temp); +#endif + if (fscanf(strm, "%s", temp) != 1) { + (void) HDfprintf(stderr, err6b, infile); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump FILTERS %s found\n", temp); +#endif + if(!HDstrcmp("COMPRESSION", temp)) { /* COMPRESSION */ +#ifdef H5DEBUGIMPORT + printf("h5dump FILTERS COMPRESSION found\n"); +#endif + if (fscanf(strm, "%s", temp) != 1) { /* DEFLATE */ + (void) HDfprintf(stderr, "%s", err18); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump FILTERS COMPRESSION %s found\n", temp); +#endif + if (fscanf(strm, "%s", temp) != 1) { /* bgin bracket */ + (void) HDfprintf(stderr, "%s", err18); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump FILTERS COMPRESSION %s found\n", temp); +#endif + if (fscanf(strm, "%s", temp) != 1) { /* LEVEL */ + (void) HDfprintf(stderr, "%s", err18); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump FILTERS COMPRESSION %s found\n", temp); +#endif + if (fscanf(strm, "%d", (&ival)) != 1) { + (void) HDfprintf(stderr, "%s", err19); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump FILTERS COMPRESSION LEVEL %d found\n", ival); +#endif + in->compressionParam = ival; + if (fscanf(strm, "%s", temp) != 1) { /* end bracket */ + (void) HDfprintf(stderr, "%s", err18); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump FILTERS COMPRESSION %s found\n", temp); +#endif + in->compressionType = 0; /* ONLY GZIP supported */ + in->configOptionVector[COMPRESS] = 1; + } + else if(!HDstrcmp("CONTIGUOUS", temp)) { /* CONTIGUOUS */ +#ifdef H5DEBUGIMPORT + printf("h5dump FILTERS CONTIGUOUS found\n"); +#endif + in->configOptionVector[COMPRESS] = 0; + } + else if(!HDstrcmp("NONE", temp)) { /* NONE */ +#ifdef H5DEBUGIMPORT + printf("h5dump FILTERS NONE found\n"); +#endif + in->configOptionVector[COMPRESS] = 0; + } + if (fscanf(strm, "%s", temp) != 1) { /* end bracket */ + (void) HDfprintf(stderr, "%s", err18); + goto error; + } +#ifdef H5DEBUGIMPORT + printf("h5dump FILTERS %s found\n", temp); +#endif + } + else if(!HDstrcmp("DATA", key)) { /* FINSHED */ +#ifdef H5DEBUGIMPORT + printf("h5dump DATA key\n"); +#endif + scanret = 0; + break; + } + scanret = fscanf(strm, "%s", key); + } +#ifdef H5DEBUGIMPORT + printf("h5dump path"); + for (pndx = 0; pndx < in->path.count; pndx++) { + printf(" : %s", in->path.group[pndx]); + } + printf("\n"); + printf("h5dump inputClass=%d\n", in->inputClass); + printf("h5dump inputSize=%d\n", in->inputSize); + printf("h5dump rank=%d\n", in->rank); + printf("h5dump outputClass=%d\n", in->outputClass); + printf("h5dump outputSize=%d\n", in->outputSize); + printf("h5dump outputArchitecture=%d\n", in->outputArchitecture); + printf("h5dump outputByteOrder=%d\n", in->outputByteOrder); + printf("h5dump compressionType=%d\n", in->compressionType); + printf("h5dump compressionParam=%d\n", in->compressionParam); + printf("h5dump externFilename=%s\n", in->externFilename); + printf("h5dump configOptionVector:\n"); + for (pndx = 0; pndx < NUM_KEYS; pndx++) { + printf(" %s=%d\n", keytable[pndx], in->configOptionVector[pndx]); + } +#endif + } + else { + while (scanret == 1) { + if ((kindex = mapKeywordToIndex(key)) == -1) { + (void) HDfprintf(stderr, err2, infile); + goto error; + } + switch (kindex) { + case 0: /* PATH */ + if (in->configOptionVector[PATH] == 1) { + (void) HDfprintf(stderr, err3a, infile); + goto error; + } + if (fscanf(strm, "%s", temp) != 1) { + (void) HDfprintf(stderr, "%s", err18); + goto error; + } + if (parsePathInfo(&in->path, temp) == -1) { + (void) HDfprintf(stderr, err3b, infile); + goto error; + } + in->configOptionVector[PATH] = 1; + break; + + case 1: /* INPUT-CLASS */ + if (in->configOptionVector[INPUT_CLASS] == 1) { + (void) HDfprintf(stderr, err4a, infile); + goto error; + } + + if (fscanf(strm, "%s", temp) != 1) { + (void) HDfprintf(stderr, "%s", err18); + goto error; + } + if (getInputClass(in, temp) == -1) { + (void) HDfprintf(stderr, err4b, infile); + goto error; + } + + in->configOptionVector[INPUT_CLASS] = 1; + + /*set default value for output-class */ + if (in->configOptionVector[OUTPUT_CLASS] == 0) { + if (in->inputClass == 0 || in->inputClass == 4) + in->outputClass = 0; + if (in->inputClass == 1 || in->inputClass == 2 + || in->inputClass == 3) + in->outputClass = 1; + if (in->inputClass == 6 || in->inputClass == 7) + in->outputClass = 2; + } + break; + + case 2: /* INPUT-SIZE */ + if (in->configOptionVector[INPUT_SIZE] == 1) { + (void) HDfprintf(stderr, err5a, infile); + goto error; + } + if (fscanf(strm, "%d", (&ival)) != 1) { + (void) HDfprintf(stderr, "%s", err19); + goto error; + } + if (getInputSize(in, ival) == -1) { + (void) HDfprintf(stderr, err5b, infile); + goto error; + } + in->configOptionVector[INPUT_SIZE] = 1; + + /*set default value for output-size */ + if (in->configOptionVector[OUTPUT_SIZE] == 0) + in->outputSize = in->inputSize; + break; + + case 3: /* RANK */ + if (in->configOptionVector[RANK] == 1) { + (void) HDfprintf(stderr, err6a, infile); + goto error; + } + + if (getRank(in, strm) == -1) { + (void) HDfprintf(stderr, err6b, infile); + goto error; + } + in->configOptionVector[RANK] = 1; + break; + + case 4: /* DIMENSION-SIZES */ + if (in->configOptionVector[DIM] == 1) { + (void) HDfprintf(stderr, err7a, infile); + goto error; + } + + if (in->configOptionVector[RANK] == 0) { + (void) HDfprintf(stderr, err7b, infile); + goto error; + } + if (getDimensionSizes(in, strm) == -1) { + (void) HDfprintf(stderr, err7c, infile); + goto error; + } + in->configOptionVector[DIM] = 1; + break; + + case 5: /* OUTPUT-CLASS */ + if (in->configOptionVector[OUTPUT_CLASS] == 1) { + (void) HDfprintf(stderr, err8a, infile); + goto error; + } + + if (getOutputClass(in, strm) == -1) { + (void) HDfprintf(stderr, err8b, infile); + goto error; + } + in->configOptionVector[OUTPUT_CLASS] = 1; + break; + + case 6: /* OUTPUT-SIZE */ + if (in->configOptionVector[OUTPUT_SIZE] == 1) { + (void) HDfprintf(stderr, err9a, infile); + goto error; + } + + if (getOutputSize(in, strm) == -1) { + (void) HDfprintf(stderr, err9b, infile); + goto error; + } + in->configOptionVector[OUTPUT_SIZE] = 1; + break; + + case 7: /* OUTPUT-ARCHITECTURE */ + if (in->configOptionVector[OUTPUT_ARCH] == 1) { + (void) HDfprintf(stderr, err10a, infile); + goto error; + } + + if (getOutputArchitecture(in, strm) == -1) { + (void) HDfprintf(stderr, err10b, infile); + goto error; + } + in->configOptionVector[OUTPUT_ARCH] = 1; + break; + + case 8: /* OUTPUT-BYTE-ORDER */ + if (in->configOptionVector[OUTPUT_B_ORDER] == 1) { + (void) HDfprintf(stderr, err11a, infile); + goto error; + } + + if (getOutputByteOrder(in, strm) == -1) { + (void) HDfprintf(stderr, err11b, infile); + goto error; + } + in->configOptionVector[OUTPUT_B_ORDER] = 1; + break; + + case 9: /* CHUNKED-DIMENSION-SIZES */ + if (in->configOptionVector[CHUNK] == 1) { + (void) HDfprintf(stderr, err12a, infile); + goto error; + } + /* cant appear before dimension sizes have been provided */ + if (in->configOptionVector[DIM] == 0) { + (void) HDfprintf(stderr, err12b, infile); + goto error; + } + + if (getChunkedDimensionSizes(in, strm) == -1) { + (void) HDfprintf(stderr, err12c, infile); + goto error; + } + in->configOptionVector[CHUNK] = 1; + break; + + case 10: /* COMPRESSION-TYPE */ + if (in->configOptionVector[COMPRESS] == 1) { + (void) HDfprintf(stderr, err13a, infile); + goto error; + } + + if (getCompressionType(in, strm) == -1) { + (void) HDfprintf(stderr, err13b, infile); + goto error; + } + in->configOptionVector[COMPRESS] = 1; + + if (in->configOptionVector[COMPRESS_PARAM] == 0) { + if (in->compressionType == 0) + in->compressionParam = 6; /* default value if compressionType is GZIP */ + } + break; + + case 11: /* COMPRESSION-PARAM */ + if (in->configOptionVector[COMPRESS_PARAM] == 1) { + (void) HDfprintf(stderr, err14a, infile); + goto error; + } + + if (getCompressionParameter(in, strm) == -1) { + (void) HDfprintf(stderr, err14b, infile); + goto error; + } + + in->configOptionVector[COMPRESS_PARAM] = 1; + + if (in->configOptionVector[COMPRESS] == 0) + in->compressionType = 0; + + break; + + case 12: /* EXTERNAL-STORAGE */ + if (in->configOptionVector[EXTERNALSTORE] == 1) { + (void) HDfprintf(stderr, err15a, infile); + goto error; + } + + if (getExternalFilename(in, strm) == -1) { + (void) HDfprintf(stderr, err15b, infile); + goto error; + } + in->configOptionVector[EXTERNALSTORE] = 1; + break; + + case 13: /* MAXIMUM-DIMENSIONS */ + if (in->configOptionVector[EXTEND] == 1) { + (void) HDfprintf(stderr, err16a, infile); + goto error; + } + /* cant appear before dimension sizes have been provided */ + if (in->configOptionVector[DIM] == 0) { + (void) HDfprintf(stderr, err16b, infile); + goto error; + } + if (getMaximumDimensionSizes(in, strm) == -1) { + (void) HDfprintf(stderr, err16c, infile); + goto error; + } + in->configOptionVector[EXTEND] = 1; + break; + + default: + break; + } + scanret = fscanf(strm, "%s", key); + } + } + + /* + check if keywords obtained are valid + if yes, return 0 else error + */ + + if (validateConfigurationParameters(in) == -1) { + (void) HDfprintf(stderr, err17, infile); + goto error; + } + + /* Set success return value */ + retval = 0; + +error: + if(strm) + HDfclose(strm); + return(retval); +} + +static int validateConfigurationParameters(struct Input *in) +{ + const char *err1 = "One or more of the required fields (RANK, DIMENSION-SIZES) missing.\n"; + const char *err2 = "Cannot specify chunking or compression or extendible data sets with the external file option.\n"; + const char *err3 = "Cannot specify the compression or the extendible data sets without the chunking option.\n"; + const char *err4a = "OUTPUT-ARCHITECTURE cannot be STD if OUTPUT-CLASS is floating point (FP).\n"; + const char *err4b = "OUTPUT-ARCHITECTURE cannot be IEEE if OUTPUT-CLASS is integer (IN).\n"; + const char *err5 = "For OUTPUT-CLASS FP, valid values for OUTPUT-SIZE are (32, 64) .\n"; +#ifndef H5_SIZEOF_LONG_LONG + const char *err6 = "No support for reading 64-bit integer (INPUT-CLASS: IN, TEXTIN, UIN, TEXTUIN files\n"; +#endif + + /* for class STR other parameters are ignored */ + if (in->inputClass == 5) /* STR */ + return (0); + + if ((in->configOptionVector[DIM] != 1) || (in->configOptionVector[RANK] != 1)) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + + if (in->configOptionVector[EXTERNALSTORE] == 1) { + if ((in->configOptionVector[COMPRESS] == 1) || (in->configOptionVector[CHUNK] == 1) || (in->configOptionVector[EXTEND] == 1)) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + } + + if ((in->configOptionVector[COMPRESS] == 1) || (in->configOptionVector[EXTEND] == 1)) { + if (in->configOptionVector[CHUNK] != 1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + } + + /* Arch cant be STD if O/p class is FP */ + if (in->outputArchitecture == 1) + if (in->outputClass == 1) { + (void) HDfprintf(stderr, "%s", err4a); + return (-1); + } + + /* Arch cant be IEEE if O/p class is IN */ + if (in->outputArchitecture == 2) + if (in->outputClass == 0) { + (void) HDfprintf(stderr, "%s", err4b); + return (-1); + } + + if (in->outputClass == 1) + if (in->outputSize != 32 && in->outputSize != 64) { + (void) HDfprintf(stderr, "%s", err5); + return (-1); + } + +#ifndef H5_SIZEOF_LONG_LONG + if (in->inputSize == 64 && (in->inputClass == 0 || in->inputClass == 4 || in->inputClass == 6 || in->inputClass == 7) ) { + (void) HDfprintf(stderr, "%s", err6); + return -1; + } +#endif + return (0); +} + +static int mapKeywordToIndex(char *key) +{ + int i; + + for (i = 0; i < NUM_KEYS; i++) + if (!HDstrcmp(keytable[i], key)) + return i; + return -1; +} + +static int parsePathInfo(struct path_info *path, char *temp) +{ + const char delimiter[] = "/\""; + char *token; + int i = 0; + const char *err1 = "Path string larger than MAX_PATH_NAME_LENGTH.\n"; + + token = HDstrtok (temp, delimiter); + if (HDstrlen(token) >= MAX_PATH_NAME_LENGTH) { + (void) HDfprintf(stderr, err1); + return (-1); + } + HDstrcpy(path->group[i++],token); + + while (1) { + token = HDstrtok (NULL, delimiter); + if (token == NULL) + break; + if (HDstrlen(token) >= MAX_PATH_NAME_LENGTH) { + (void) HDfprintf(stderr, err1); + return (-1); + } + HDstrcpy(path->group[i++],token); + } + path->count = i; + return (0); +} + +static int parseDimensions(struct Input *in, char *strm) +{ + const char delimiter[] = ","; + char temp[255]; + char *token; + int i = 0; + const char *err1 = "Unable to allocate dynamic memory.\n"; + + HDstrncpy(temp, strm, sizeof(temp)); + temp[sizeof(temp) - 1] = '\0'; + HDstrtok (temp, delimiter); + + while (1) { + token = HDstrtok (NULL, delimiter); + if (token == NULL) + break; + i++; + } + in->rank = i + 1; + if ((in->sizeOfDimension = (hsize_t *) HDmalloc ((size_t) in->rank * sizeof(hsize_t))) == NULL) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + + i = 0; + HDstrncpy(temp, strm, sizeof(temp)); + temp[sizeof(temp) - 1] = '\0'; + in->sizeOfDimension[i++] + = HDstrtoull(HDstrtok (temp, delimiter), NULL, BASE_10); + + while (1) { + token = HDstrtok (NULL, delimiter); + if (token == NULL) + break; + in->sizeOfDimension[i++] = HDstrtoull(token, NULL, BASE_10); + } + return (0); +} + +static int getOutputClass(struct Input *in, FILE *strm) +{ + char temp[255]; + int kindex; + const char *err1 = "Unable to get 'string' value.\n"; + const char *err2 = "Invalid value for output class.\n"; + + if (fscanf(strm, "%s", temp) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + + if ((kindex = OutputClassStrToInt(temp)) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + + in->outputClass = kindex; + return (0); +} + +static int OutputClassStrToInt(char *temp) +{ + int i; + char classKeywordTable[3][15] = { "IN", "FP", "UIN" }; + for (i = 0; i < 3; i++) + if (!HDstrcmp(classKeywordTable[i], temp)) + return i; + + return -1; +} +/* same as getInputSize. But defined separately for extensibility */ +static int getOutputSize(struct Input *in, FILE *strm) +{ + int ival; + int i; + int outputSizeValidValues[4] = { 8, 16, 32, 64 }; + const char *err1 = "Unable to get integer value.\n"; + const char *err2 = "Invalid value for output size.\n"; + + if (fscanf(strm, "%d", (&ival)) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + + for (i = 0; i < 4; i++) + if (outputSizeValidValues[i] == ival) { + in->outputSize = ival; + return (0); + } + (void) HDfprintf(stderr, "%s", err2); + return (-1); +} + +static int getInputClass(struct Input *in, char * temp) +{ + int kindex; + const char *err1 = "Invalid value for input class.\n"; + + if ((kindex = InputClassStrToInt(temp)) == -1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + + in->inputClass = kindex; + return (0); +} + +static int getInputClassType(struct Input *in, char * buffer) +{ + int kindex = -1; + const char *err1 = "Invalid value for input class.\n"; + const char *err2 = "Invalid value for output architecture.\n"; + const char *err3 = "Invalid value for output byte-order.\n"; + + if (!HDstrcmp(buffer, "H5T_STD_I8BE")) { + in->inputSize = 8; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("BE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 4; + } + else if (!HDstrcmp(buffer, "H5T_STD_I8LE")) { + in->inputSize = 8; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("LE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 4; + } + else if (!HDstrcmp(buffer, "H5T_STD_I16BE")) { + in->inputSize = 16; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("BE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 4; + } + else if (!HDstrcmp(buffer, "H5T_STD_I16LE")) { + in->inputSize = 16; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("LE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 4; + } + else if (!HDstrcmp(buffer, "H5T_STD_I32BE")) { + in->inputSize = 32; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("BE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 4; + } + else if (!HDstrcmp(buffer, "H5T_STD_I32LE")) { + in->inputSize = 32; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("LE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 4; + } + else if (!HDstrcmp(buffer, "H5T_STD_I64BE")) { + in->inputSize = 64; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("BE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 4; + } + else if (!HDstrcmp(buffer, "H5T_STD_I64LE")) { + in->inputSize = 64; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("LE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 4; + } + else if (!HDstrcmp(buffer, "H5T_STD_U8BE")) { + in->inputSize = 8; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("BE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 7; + } + else if (!HDstrcmp(buffer, "H5T_STD_U8LE")) { + in->inputSize = 8; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("LE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 7; + } + else if (!HDstrcmp(buffer, "H5T_STD_U16BE")) { + in->inputSize = 16; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("BE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 7; + } + else if (!HDstrcmp(buffer, "H5T_STD_U16LE")) { + in->inputSize = 16; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("LE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 7; + } + else if (!HDstrcmp(buffer, "H5T_STD_U32BE")) { + in->inputSize = 32; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("BE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 7; + } + else if (!HDstrcmp(buffer, "H5T_STD_U32LE")) { + in->inputSize = 32; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("LE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 7; + } + else if (!HDstrcmp(buffer, "H5T_STD_U64BE")) { + in->inputSize = 64; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("BE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 7; + } + else if (!HDstrcmp(buffer, "H5T_STD_U64LE")) { + in->inputSize = 64; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("LE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 7; + } + else if (!HDstrcmp(buffer, "H5T_NATIVE_SCHAR")) { + in->inputSize = 8; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("NATIVE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + kindex = 4; + } + else if (!HDstrcmp(buffer, "H5T_NATIVE_UCHAR")) { + in->inputSize = 8; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("NATIVE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + kindex = 7; + } + else if (!HDstrcmp(buffer, "H5T_NATIVE_SHORT")) { + in->inputSize = 16; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("NATIVE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + kindex = 4; + } + else if (!HDstrcmp(buffer, "H5T_NATIVE_USHORT")) { + in->inputSize = 16; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("NATIVE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + kindex = 7; + } + else if (!HDstrcmp(buffer, "H5T_NATIVE_INT")) { + in->inputSize = 32; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("NATIVE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + kindex = 4; + } + else if (!HDstrcmp(buffer, "H5T_NATIVE_UINT")) { + in->inputSize = 32; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("NATIVE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + kindex = 7; + } + else if (!HDstrcmp(buffer, "H5T_NATIVE_LONG")) { + in->inputSize = 32; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("NATIVE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + kindex = 4; + } + else if (!HDstrcmp(buffer, "H5T_NATIVE_ULONG")) { + in->inputSize = 32; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("NATIVE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + kindex = 7; + } + else if (!HDstrcmp(buffer, "H5T_NATIVE_LLONG")) { + in->inputSize = 64; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("NATIVE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + kindex = 4; + } + else if (!HDstrcmp(buffer, "H5T_NATIVE_ULLONG")) { + in->inputSize = 64; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("NATIVE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + kindex = 7; + } + else if (!HDstrcmp(buffer, "H5T_IEEE_F32BE")) { + in->inputSize = 32; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("IEEE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("BE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 3; + } + else if (!HDstrcmp(buffer, "H5T_IEEE_F32LE")) { + in->inputSize = 32; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("IEEE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("LE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 3; + } + else if (!HDstrcmp(buffer, "H5T_IEEE_F64BE")) { + in->inputSize = 64; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("IEEE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("BE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 3; + } + else if (!HDstrcmp(buffer, "H5T_IEEE_F64LE")) { + in->inputSize = 64; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("IEEE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("LE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = 3; + } + else if (!HDstrcmp(buffer, "H5T_VAX_F32")) { + in->inputSize = 32; + in->configOptionVector[INPUT_SIZE] = 1; + + kindex = 3; + } + else if (!HDstrcmp(buffer, "H5T_VAX_F64")) { + in->inputSize = 64; + in->configOptionVector[INPUT_SIZE] = 1; + + kindex = 3; + } + else if (!HDstrcmp(buffer, "H5T_NATIVE_FLOAT")) { + in->inputSize = 32; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("NATIVE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + kindex = 3; + } + else if (!HDstrcmp(buffer, "H5T_NATIVE_DOUBLE")) { + in->inputSize = 64; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("NATIVE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + kindex = 3; + } +#if H5_SIZEOF_LONG_DOUBLE !=0 + else if (!HDstrcmp(buffer, "H5T_NATIVE_LDOUBLE")) { + in->inputSize = H5_SIZEOF_LONG_DOUBLE; + in->configOptionVector[INPUT_SIZE] = 1; + + if ((kindex = OutputArchStrToInt("NATIVE")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + kindex = 3; + } +#endif + else if(!HDstrcmp(buffer, "H5T_TIME: not yet implemented")) { + kindex = -1; + } + else if(!HDstrcmp(buffer, "H5T_STRING")) { + kindex = 5; + } + /* case H5T_BITFIELD: */ + else if (!HDstrcmp(buffer, "H5T_STD_B8BE")) { + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("BE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = -1; + } + else if (!HDstrcmp(buffer, "H5T_STD_B8LE")) { + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("LE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = -1; + } + else if (!HDstrcmp(buffer, "H5T_STD_B16BE")) { + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("BE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = -1; + } + else if (!HDstrcmp(buffer, "H5T_STD_B16LE")) { + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("LE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = -1; + } + else if (!HDstrcmp(buffer, "H5T_STD_B32BE")) { + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("BE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = -1; + } + else if (!HDstrcmp(buffer, "H5T_STD_B32LE")) { + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("LE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = -1; + } + else if (!HDstrcmp(buffer, "H5T_STD_B64BE")) { + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("BE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = -1; + } + else if (!HDstrcmp(buffer, "H5T_STD_B64LE")) { + + if ((kindex = OutputArchStrToInt("STD")) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->outputArchitecture = kindex; + + if ((kindex = OutputByteOrderStrToInt("LE")) == -1) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + in->outputByteOrder = kindex; + + kindex = -1; + } + /* case H5T_OPAQUE: */ + else if(!HDstrcmp(buffer, "H5T_OPAQUE")) { + kindex = -1; + } + /* case H5T_COMPOUND: */ + else if(!HDstrcmp(buffer, "H5T_COMPOUND")) { + kindex = -1; + } + /* case H5T_REFERENCE: */ + else if(!HDstrcmp(buffer, "H5T_REFERENCE")) { + kindex = -1; + } + /* case H5T_ENUM: */ + else if(!HDstrcmp(buffer, "H5T_ENUM")) { + kindex = -1; + } + /* case H5T_VLEN: */ + else if(!HDstrcmp(buffer, "H5T_VLEN")) { + kindex = -1; + } + /* case H5T_ARRAY: */ + else if(!HDstrcmp(buffer, "H5T_ARRAY")) { + kindex = -1; + } + + if (kindex == -1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + + /*set default value for output-size */ + if (in->configOptionVector[OUTPUT_SIZE] == 0) + in->outputSize = in->inputSize; +#ifdef H5DEBUGIMPORT + printf("h5dump DATATYPE STRING %d inputSize\n", in->inputSize); + printf("h5dump DATATYPE STRING %d outputSize\n", in->outputSize); +#endif + + in->inputClass = kindex; + return (0); +} + +static int InputClassStrToInt(char *temp) +{ + int i; + char classKeywordTable[8][15] = { "TEXTIN", "TEXTFP", "TEXTFPE", "FP", "IN", "STR", "TEXTUIN", "UIN" }; + for (i = 0; i < 8; i++) + if (!HDstrcmp(classKeywordTable[i], temp)) + return i; + return -1; +} + +/* same as getOutputSize. But defined separately for extensibility */ +static int getInputSize(struct Input *in, int ival) +{ + int i; + int inputSizeValidValues[4] = { 8, 16, 32, 64 }; + const char *err1 = "Invalid value for input size.\n"; + + for (i = 0; i < 4; i++) + if (inputSizeValidValues[i] == ival) { + in->inputSize = ival; + return (0); + } + (void) HDfprintf(stderr, "%s", err1); + return (-1); +} + +static int getRank(struct Input *in, FILE *strm) +{ + int ival; + + const char *err1 = "Unable to get integer value.\n"; + const char *err2 = "Invalid value for rank.\n"; + + if (fscanf(strm, "%d", (&ival)) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + if (ival >= MIN_NUM_DIMENSION && ival <= MAX_NUM_DIMENSION) { + in->rank = ival; + return (0); + } + + (void) HDfprintf(stderr, "%s", err2); + return (-1); +} + +/* same as getChunkedDimensionSizes. But defined separately for extensibility */ +static int getDimensionSizes(struct Input *in, FILE *strm) +{ + unsigned long long ullval; + int i = 0; + + const char *err1 = "Unable to allocate dynamic memory.\n"; + const char *err2 = "No. of dimensions for which dimension sizes provided is not equal to provided rank.\n"; + + if ((in->sizeOfDimension = (hsize_t *) HDmalloc ((size_t) in->rank * sizeof(hsize_t))) == NULL) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + + while (fscanf(strm, "%llu", (&ullval)) == 1) + in->sizeOfDimension[i++] = ullval; + + if (in->rank != i) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + return (0); +} +/* same as getDimensionSizes. But defined separately for extensibility */ +static int getChunkedDimensionSizes(struct Input *in, FILE *strm) +{ + unsigned long long ullval; + int i = 0; + + const char *err1 = "Unable to allocate dynamic memory.\n"; + const char *err2 = "No. of dimensions for which chunked dimension sizes provided is not equal to provided rank.\n"; + const char *err3 = "The CHUNKED-DIMENSION-SIZES cannot exceed the sizes of DIMENSION-SIZES\n"; + + if ((in->sizeOfChunk = (hsize_t *) HDmalloc ((size_t) in->rank * sizeof(hsize_t))) == NULL) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + + while (fscanf(strm, "%llu", (&ullval)) == 1) + in->sizeOfChunk[i++] = ullval; + + if (in->rank != i) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + + for (i = 0; i < in->rank; i++) + if (in->sizeOfChunk[i] > in->sizeOfDimension[i]) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + return (0); +} + +static int getMaximumDimensionSizes(struct Input *in, FILE *strm) +{ + long long llval; + int i = 0; + + const char *err1 = "Unable to allocate dynamic memory.\n"; + const char *err2 = "No. of dimensions for which maximum dimension sizes provided is not equal to provided rank.\n"; + const char *err3 = "The MAXIMUM-DIMENSIONS cannot be less than the sizes of DIMENSION-SIZES. Exception: can be -1 to indicate unlimited size\n"; + + if ((in->maxsizeOfDimension = (hsize_t *) HDmalloc ((size_t) in->rank * sizeof(hsize_t))) == NULL) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + + while (fscanf(strm, "%lld", (&llval)) == 1) { + if (llval == -1) + in->maxsizeOfDimension[i++] = H5S_UNLIMITED; + else + in->maxsizeOfDimension[i++] = (hsize_t)llval; + } + + if (in->rank != i) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + + for (i = 0; i < in->rank; i++) { + if (in->maxsizeOfDimension[i] != H5S_UNLIMITED) + if (in->maxsizeOfDimension[i] < in->sizeOfDimension[i]) { + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + } + return (0); +} + +static int getOutputArchitecture(struct Input *in, FILE *strm) +{ + char temp[255]; + int kindex; + const char *err1 = "Unable to get 'string' value.\n"; + const char *err2 = "Invalid value for output architecture.\n"; + + if (fscanf(strm, "%s", temp) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + + if ((kindex = OutputArchStrToInt(temp)) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + + in->outputArchitecture = kindex; + return (0); +} + +static int OutputArchStrToInt(const char *temp) +{ + int i; + char outputArchKeywordTable[8][15] = { "NATIVE", "STD", "IEEE", "INTEL", + "CRAY", "MIPS", "ALPHA", "UNIX" }; + for (i = 0; i < 8; i++) + if (!HDstrcmp(outputArchKeywordTable[i], temp)) + return i; + return -1; +} + +static int getOutputByteOrder(struct Input *in, FILE *strm) +{ + char temp[255]; + int kindex; + const char *err1 = "Unable to get 'string' value.\n"; + const char *err2 = "Invalid value for output byte-order.\n"; + + if (fscanf(strm, "%s", temp) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + + if ((kindex = OutputByteOrderStrToInt(temp)) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + + in->outputByteOrder = kindex; + return (0); +} + +static int OutputByteOrderStrToInt(const char *temp) +{ + int i; + char outputByteOrderKeywordTable[2][15] = { "BE", "LE" }; + for (i = 0; i < 2; i++) + if (!HDstrcmp(outputByteOrderKeywordTable[i], temp)) + return i; + return -1; +} + +static int getCompressionType(struct Input *in, FILE *strm) +{ + char temp[255]; + int kindex; + const char *err1 = "Unable to get 'string' value.\n"; + const char *err2 = "Invalid value for compression.\n"; + + if (fscanf(strm, "%s", temp) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + + if ((kindex = CompressionTypeStrToInt(temp)) == -1) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + + in->compressionType = kindex; + return (0); + +} + +static int CompressionTypeStrToInt(char *temp) +{ + /* currently supports only GZIP */ + /* can be extended by adding fields to the table */ + + int i; + char CompressionTypeKeywordTable[1][15] = { "GZIP" }; + for (i = 0; i < 1; i++) + if (!HDstrcmp(CompressionTypeKeywordTable[i], temp)) + return i; + return -1; +} + +static int getCompressionParameter(struct Input *in, FILE *strm) +{ + /* currently supports only GZIP */ + /* can be extended by adding more values to COMPRESSION-TYPE and */ + /* handling the paramters here by adding more cases */ + + int ival; + const char *err1 = "Unable to get integer value.\n"; + const char *err2 = "Invalid value for compression paramter.\n"; + const char *err3 = "Unsupported Compression Type.\n"; + + switch (in->compressionType) { + case 0: /* GZIP */ + if (fscanf(strm, "%d", (&ival)) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + + if (ival < 0 || ival > 9) { + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + in->compressionParam = ival; + return (0); + + default: + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } +} + +static int getExternalFilename(struct Input *in, FILE *strm) +{ + char temp[255]; + const char *err1 = "Unable to get 'string' value.\n"; + + if (fscanf(strm, "%s", temp) != 1) { + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + + in->externFilename = (char *) HDmalloc ((size_t) (HDstrlen(temp)) * sizeof(char)); + (void) HDstrcpy(in->externFilename, temp); + return (0); +} + +void setDefaultValues(struct Input *in, int count) +{ + int i; + char temp[255]; + char num[255]; + + in->h5dumpInput = 0; + in->inputClass = 3; /* FP */ + in->inputSize = 32; + in->outputClass = 1; /* FP */ + in->outputSize = 32; + in->rank = 0; + in->path.count = 1; + + HDstrcpy(temp, "dataset"); + sprintf(num, "%d", count); + HDstrcat(temp, num); + HDstrcpy(in->path.group[0], temp); + + in->outputArchitecture = 0; /* NATIVE */ + in->outputByteOrder = -1; /* use default */ + in->compressionType = 0; /* GZIP */ + for (i = 0; i < NUM_KEYS; i++) + in->configOptionVector[i] = 0; +} + +hid_t createOutputDataType(struct Input *in) +{ + hid_t new_type = (-1); + const char *err1 = "Invalid value for output class.\n"; + const char *err2 = "Invalid value for output size.\n"; + const char *err3 = "Invalid value for output byte order.\n"; + const char *err4 = "Invalid value for output architecture.\n"; + const char *err5 = "STD not supported for float.\n"; + const char *err6 = "IEEE not supported for INT.\n"; + + switch (in->outputClass) { + case 0: + switch (in->outputArchitecture) { + case 0: /* NATIVE */ + switch (in->outputSize) { + case 8: + new_type = H5Tcopy(H5T_NATIVE_CHAR); + break; + + case 16: + new_type = H5Tcopy(H5T_NATIVE_SHORT); + break; + + case 32: + new_type = H5Tcopy(H5T_NATIVE_INT); + break; + + case 64: + new_type = H5Tcopy(H5T_NATIVE_LLONG); + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + switch (in->outputByteOrder) { + case -1: /* default */ + break; + case 0: + H5Tset_order(new_type, H5T_ORDER_BE); + break; + + case 1: + H5Tset_order(new_type, H5T_ORDER_LE); + break; + + default: + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + break; + + case 1: /* STD */ + switch (in->outputSize) { + case 8: + switch (in->outputByteOrder) { + case -1: + case 0: + new_type = H5Tcopy(H5T_STD_I8BE); + break; + + case 1: + new_type = H5Tcopy(H5T_STD_I8LE); + break; + + default: + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + break; + + case 16: + switch (in->outputByteOrder) { + case -1: + case 0: + new_type = H5Tcopy(H5T_STD_I16BE); + break; + + case 1: + new_type = H5Tcopy(H5T_STD_I16LE); + break; + + default: + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + break; + + case 32: + switch (in->outputByteOrder) { + case -1: + case 0: + new_type = H5Tcopy(H5T_STD_I32BE); + break; + + case 1: + new_type = H5Tcopy(H5T_STD_I32LE); + break; + + default: + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + break; + + case 64: + switch (in->outputByteOrder) { + case -1: + case 0: + new_type = H5Tcopy(H5T_STD_I64BE); + break; + + case 1: + new_type = H5Tcopy(H5T_STD_I64LE); + break; + + default: + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; + + default: + (void) HDfprintf(stderr, "%s", err4); + return (-1); + } + break; + + case 1: + switch (in->outputArchitecture) { + case 0: + switch (in->outputSize) { + case 32: + new_type = H5Tcopy(H5T_NATIVE_FLOAT); + break; + + case 64: + new_type = H5Tcopy(H5T_NATIVE_DOUBLE); + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + switch (in->outputByteOrder) { + case -1: /* DEFAULT */ + break; + case 0: + H5Tset_order(new_type, H5T_ORDER_BE); + break; + + case 1: + H5Tset_order(new_type, H5T_ORDER_LE); + break; + + default: + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + break; + + case 1: + (void) HDfprintf(stderr, "%s", err5); + return (-1); + + case 2: + switch (in->outputSize) { + case 32: + switch (in->outputByteOrder) { + case -1: + case 0: + new_type = H5Tcopy(H5T_IEEE_F32BE); + break; + + case 1: + new_type = H5Tcopy(H5T_IEEE_F32LE); + break; + + default: + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + break; + + case 64: + switch (in->outputByteOrder) { + case -1: + case 0: + new_type = H5Tcopy(H5T_IEEE_F64BE); + break; + + case 1: + new_type = H5Tcopy(H5T_IEEE_F64LE); + break; + + default: + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; + + default: + (void) HDfprintf(stderr, "%s", err4); + return (-1); + } + break; + + case 2: + switch (in->outputArchitecture) { + case 0: + switch (in->outputSize) { + case 8: + new_type = H5Tcopy(H5T_NATIVE_UCHAR); + break; + + case 16: + new_type = H5Tcopy(H5T_NATIVE_USHORT); + break; + + case 32: + new_type = H5Tcopy(H5T_NATIVE_UINT); + break; + + case 64: + new_type = H5Tcopy(H5T_NATIVE_ULLONG); + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + switch (in->outputByteOrder) { + case -1: /* Default */ + break; + case 0: + H5Tset_order(new_type, H5T_ORDER_BE); + break; + + case 1: + H5Tset_order(new_type, H5T_ORDER_LE); + break; + + default: + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + break; + + case 1: + switch (in->outputSize) { + case 8: + switch (in->outputByteOrder) { + case -1: + case 0: + new_type = H5Tcopy(H5T_STD_U8BE); + break; + + case 1: + new_type = H5Tcopy(H5T_STD_U8LE); + break; + + default: + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + break; + + case 16: + switch (in->outputByteOrder) { + case -1: + case 0: + new_type = H5Tcopy(H5T_STD_U16BE); + break; + + case 1: + new_type = H5Tcopy(H5T_STD_U16LE); + break; + + default: + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + break; + + case 32: + switch (in->outputByteOrder) { + case -1: + case 0: + new_type = H5Tcopy(H5T_STD_U32BE); + break; + + case 1: + new_type = H5Tcopy(H5T_STD_U32LE); + break; + + default: + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + break; + + case 64: + switch (in->outputByteOrder) { + case -1: + case 0: + new_type = H5Tcopy(H5T_STD_U64BE); + break; + + case 1: + new_type = H5Tcopy(H5T_STD_U64LE); + break; + + default: + (void) HDfprintf(stderr, "%s", err3); + return (-1); + } + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; + + case 2: + (void) HDfprintf(stderr, "%s", err6); + return (-1); + + default: + (void) HDfprintf(stderr, "%s", err4); + return (-1); + } + break; + + default: + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + return new_type; +} + +hid_t createInputDataType(struct Input *in) +{ + hid_t new_type = (-1); + const char *err1 = "Invalid value for input class.\n"; + const char *err2 = "Invalid value for output size.\n"; + + switch (in->inputClass) { + case 0: + case 4: + switch (in->inputSize) { + case 8: + new_type = H5Tcopy(H5T_NATIVE_CHAR); + break; + + case 16: + new_type = H5Tcopy(H5T_NATIVE_SHORT); + break; + + case 32: + new_type = H5Tcopy(H5T_NATIVE_INT); + break; + + case 64: + new_type = H5Tcopy(H5T_NATIVE_LLONG); + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; + + case 1: + case 2: + case 3: + switch (in->inputSize) { + case 32: + new_type = H5Tcopy(H5T_NATIVE_FLOAT); + break; + + case 64: + new_type = H5Tcopy(H5T_NATIVE_DOUBLE); + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; + + case 5: + (void) HDfprintf(stderr, "%s", err1); + return (-1); + break; + + case 6: + case 7: + switch (in->inputSize) { + case 8: + new_type = H5Tcopy(H5T_NATIVE_UCHAR); + break; + + case 16: + new_type = H5Tcopy(H5T_NATIVE_USHORT); + break; + + case 32: + new_type = H5Tcopy(H5T_NATIVE_UINT); + break; + + case 64: + new_type = H5Tcopy(H5T_NATIVE_ULLONG); + break; + + default: + (void) HDfprintf(stderr, "%s", err2); + return (-1); + } + break; + + default: + (void) HDfprintf(stderr, "%s", err1); + return (-1); + } + return new_type; +} + +static int process(struct Options *opt) +{ + struct Input *in; + FILE *extfile; + hid_t file_id; + hid_t group_id; + hid_t handle; + hid_t dataset; + hid_t dataspace = (-1); + hid_t intype; + hid_t outtype; + hid_t proplist; + hsize_t numOfElements = 1; + int j; + int k; + + const char *err1 = "Error creating HDF output file: %s.\n"; + const char *err2 = "Error in processing the configuration file: %s.\n"; + const char *err3 = "Error in reading the input file: %s.\n"; + const char *err4 = "Error in creating or opening external file.\n"; + const char *err5 = "Error in creating the output data set. Dataset with the same name may exist at the specified path\n"; + const char *err6 = "Error in writing the output data set.\n"; + + H5E_BEGIN_TRY + { + if ((file_id = H5Fopen(opt->outfile, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) { + if ((file_id = H5Fcreate(opt->outfile, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) == FAIL) { + (void) HDfprintf(stderr, err1, opt->outfile); + return (-1); + } + } + } + H5E_END_TRY; + + for (k = 0; k < opt->fcount; k++) { + in = &(opt->infiles[k].in); + if (opt->infiles[k].config == 1) { + if (processConfigurationFile(opt->infiles[k].configfile, in) == -1) { + (void) HDfprintf(stderr, err2, opt->infiles[k].configfile); + return (-1); + } + } + + if (processDataFile(opt->infiles[k].datafile, in, file_id) == -1) { + (void) HDfprintf(stderr, err3, opt->infiles[k].datafile); + return (-1); + } + + if (in->inputClass != 5) { /* STR */ + for (j = 0; j < in->rank; j++) + numOfElements *= in->sizeOfDimension[j]; + + /* disable error reporting */ + H5E_BEGIN_TRY + { + /* create parent groups */ + if (in->path.count > 1) { + j = 0; + handle = file_id; + while (j < in->path.count - 1) { + if ((group_id = H5Gopen2(handle, in->path.group[j], H5P_DEFAULT)) < 0) { + group_id = H5Gcreate2(handle, in->path.group[j++], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + for (; j < in->path.count - 1; j++) + group_id = H5Gcreate2(group_id, in->path.group[j], H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + handle = group_id; + break; + } + handle = group_id; + j++; + } + } + else { + handle = file_id; + j = 0; + } + + /*enable error reporting */ + } + H5E_END_TRY; + + /*create data type */ + intype = createInputDataType(in); + outtype = createOutputDataType(in); +#ifdef H5DEBUGIMPORT + printf("process intype %d outtype %d\n", intype, outtype); +#endif + + /* create property list */ + proplist = H5Pcreate(H5P_DATASET_CREATE); + if (in->configOptionVector[CHUNK] == 1) { + H5Pset_layout(proplist, H5D_CHUNKED); + /* not reqd chunking is implied if set_chunk is used */ + H5Pset_chunk(proplist, in->rank, in->sizeOfChunk); + } + + if (in->configOptionVector[COMPRESS] == 1) { + H5Pset_deflate(proplist, (unsigned) in->compressionParam); + } + + if (in->configOptionVector[EXTERNALSTORE] == 1) { + /* creating the external file if it doesnt exist */ + if ((extfile = HDfopen(in->externFilename, "ab")) == NULL) { + (void) HDfprintf(stderr, "%s", err4); + H5Pclose(proplist); + H5Sclose(dataspace); + H5Fclose(file_id); + return (-1); + } + HDfclose(extfile); + H5Pset_external(proplist, in->externFilename, (off_t)0, numOfElements * (hsize_t)in->inputSize / 8); + } + + /* create dataspace */ + if (in->configOptionVector[EXTEND] == 1) + dataspace = H5Screate_simple(in->rank, in->sizeOfDimension, in->maxsizeOfDimension); + else + dataspace = H5Screate_simple(in->rank, in->sizeOfDimension, NULL); + + /* disable error reporting */ + H5E_BEGIN_TRY + { + /* create data set */ + if ((dataset = H5Dcreate2(handle, in->path.group[j], outtype, dataspace, H5P_DEFAULT, proplist, H5P_DEFAULT)) < 0) { + (void) HDfprintf(stderr, "%s", err5); + H5Pclose(proplist); + H5Sclose(dataspace); + H5Fclose(file_id); + return (-1); + } + + /*enable error reporting */ + } + H5E_END_TRY; + + /* write dataset */ + if (H5Dwrite(dataset, intype, H5S_ALL, H5S_ALL, H5P_DEFAULT, (VOIDP) in->data) < 0) { + (void) HDfprintf(stderr, "%s", err6); + H5Dclose(dataset); + H5Pclose(proplist); + H5Sclose(dataspace); + H5Fclose(file_id); + return (-1); + } + + H5Dclose(dataset); + H5Pclose(proplist); + H5Sclose(dataspace); + } + + } /* STR */ + + H5Fclose(file_id); + return (0); +} + +/* + * Name: + * help + * + * Purpose: + * Print a helpful summary of command usage and features. + */ + +void help(char *name) +{ + (void) HDfprintf(stdout, "Name:\n\n"); + (void) HDfprintf(stdout, "\t%s\n\n", name); + (void) HDfprintf(stdout, "\t TOOL NAME:\n"); + (void) HDfprintf(stdout, "\t %s\n", name); + (void) HDfprintf(stdout, "\t SYNTAX:\n"); + (void) HDfprintf(stdout, "\t %s -h[elp], OR\n", name); + (void) HDfprintf(stdout, + "\t %s <infile> -c[onfig] <configfile> [<infile> -c[config] <configfile>...]", name); + (void) HDfprintf(stdout, "\t\t\t\t -o[utfile] <outfile>\n\n"); + (void) HDfprintf(stdout, "\t PURPOSE:\n"); + (void) HDfprintf(stdout, + "\t To convert data stored in one or more ASCII or binary files\n"); + (void) HDfprintf(stdout, + "\t into one or more datasets (in accordance with the \n"); + (void) HDfprintf(stdout, + "\t user-specified type and storage properties) in an existing \n"); + (void) HDfprintf(stdout, "\t or new HDF5 file.\n\n"); + (void) HDfprintf(stdout, "\t DESCRIPTION:\n"); + (void) HDfprintf(stdout, + "\t The primary objective of the utility is to convert floating\n"); + (void) HDfprintf(stdout, + "\t point or integer data stored in ASCII text or binary form \n"); + (void) HDfprintf(stdout, + "\t into a data-set according to the type and storage properties\n"); + (void) HDfprintf(stdout, + "\t specified by the user. The utility can also accept ASCII\n"); + (void) HDfprintf(stdout, + "\t text files and store the contents in a compact form as an\n"); + (void) HDfprintf(stdout, "\t array of one-dimensional strings.\n\n"); + (void) HDfprintf(stdout, + "\t The input data to be written as a data-set can be provided\n"); + (void) HDfprintf(stdout, "\t to the utility in one of the following forms:\n"); + (void) HDfprintf(stdout, + "\t 1. ASCII text file with numeric data (floating point or \n"); + (void) HDfprintf(stdout, "\t integer data). \n"); + (void) HDfprintf(stdout, + "\t 2. Binary file with native floating point data (32-bit or \n"); + (void) HDfprintf(stdout, "\t 64-bit) \n"); + (void) HDfprintf(stdout, + "\t 3. Binary file with native integer (signed or unsigned)\n"); + (void) HDfprintf(stdout, "\t data (8-bit or 16-bit or 32-bit or 64-bit). \n"); + (void) HDfprintf(stdout, + "\t 4. ASCII text file containing strings (text data).\n"); + (void) HDfprintf(stdout, "\t \n"); + (void) HDfprintf(stdout, + "\t Every input file is associated with a configuration file \n"); + (void) HDfprintf(stdout, + "\t also provided as an input to the utility. (See Section \n"); + (void) HDfprintf(stdout, + "\t \"CONFIGURATION FILE\" to know how it is to be organized).\n"); + (void) HDfprintf(stdout, + "\t The class, size and dimensions of the input data is \n"); + (void) HDfprintf(stdout, + "\t specified in this configuration file. A point to note is\n"); + (void) HDfprintf(stdout, + "\t that the floating point data in the ASCII text file may be\n"); + (void) HDfprintf(stdout, + "\t organized in the fixed floating form (for example 323.56)\n"); + (void) HDfprintf(stdout, + "\t or in a scientific notation (for example 3.23E+02). A \n"); + (void) HDfprintf(stdout, + "\t different input-class specification is to be used for both\n"); + (void) HDfprintf(stdout, "\t forms.\n\n"); + (void) HDfprintf(stdout, + "\t The utility extracts the input data from the input file \n"); + (void) HDfprintf(stdout, + "\t according to the specified parameters and saves it into \n"); + (void) HDfprintf(stdout, "\t an H5 dataset. \n\n"); + (void) HDfprintf(stdout, + "\t The user can specify output type and storage properties in \n"); + (void) HDfprintf(stdout, + "\t the configuration file. The user is required to specify the \n"); + (void) HDfprintf(stdout, + "\t path of the dataset. If the groups in the path leading to \n"); + (void) HDfprintf(stdout, + "\t the data-set do not exist, the groups will be created by the\n"); + (void) HDfprintf(stdout, + "\t utility. If no group is specified, the dataset will be\n"); + (void) HDfprintf(stdout, "\t created under the root group.\n\n"); + (void) HDfprintf(stdout, + "\t In addition to the name, the user is also required to \n"); + (void) HDfprintf(stdout, + "\t provide the class and size of output data to be written to \n"); + (void) HDfprintf(stdout, + "\t the dataset and may optionally specify the output-architecture,\n"); + (void) HDfprintf(stdout, + "\t and the output-byte-order. If output-architecture is not \n"); + (void) HDfprintf(stdout, + "\t specified the default is NATIVE. Output-byte-orders are fixed\n"); + (void) HDfprintf(stdout, + "\t for some architectures and may be specified only if output-\n"); + (void) HDfprintf(stdout, "\t architecture is IEEE, UNIX or STD.\n\n"); + (void) HDfprintf(stdout, + "\t Also, layout and other storage properties such as \n"); + (void) HDfprintf(stdout, + "\t compression, external storage and extendible data-sets may be\n"); + (void) HDfprintf(stdout, + "\t optionally specified. The layout and storage properties \n"); + (void) HDfprintf(stdout, + "\t denote how raw data is to be organized on the disk. If these \n"); + (void) HDfprintf(stdout, + "\t options are not specified the default is Contiguous layout \n"); + (void) HDfprintf(stdout, "\t and storage.\n\n"); + (void) HDfprintf(stdout, + "\t The dataset can be organized in any of the following ways:\n"); + (void) HDfprintf(stdout, "\t 1. Contiguous.\n"); + (void) HDfprintf(stdout, "\t 2. Chunked.\n"); + (void) HDfprintf(stdout, + "\t 3. External Storage File (has to be contiguous)\n"); + (void) HDfprintf(stdout, + "\t 4. Extendible data sets (has to be chunked)\n"); + (void) HDfprintf(stdout, "\t 5. Compressed. (has to be chunked)\n"); + (void) HDfprintf(stdout, + "\t 6. Compressed & Extendible (has to be chunked)\n\n"); + (void) HDfprintf(stdout, + "\t If the user wants to store raw data in a non-HDF file then \n"); + (void) HDfprintf(stdout, + "\t the external storage file option is to be used and the name \n"); + (void) HDfprintf(stdout, "\t of the file is to be specified. \n\n"); + (void) HDfprintf(stdout, + "\t If the user wants the dimensions of the data-set to be\n"); + (void) HDfprintf(stdout, + "\t unlimited, the extendible data set option can be chosen. \n\n"); + (void) HDfprintf(stdout, + "\t The user may also specify the type of compression and the \n"); + (void) HDfprintf(stdout, + "\t level to which the data set must be compresses by setting \n"); + (void) HDfprintf(stdout, "\t the compressed option.\n\n"); + (void) HDfprintf(stdout, "\t SYNOPSIS:\n"); + (void) HDfprintf(stdout, "\t h5import -h[elp], OR\n"); + (void) HDfprintf( stdout, + "\t h5import <infile> -c[onfig] <configfile> \ + [<infile> -c[config] <confile2>...] -o[utfile] <outfile>\n\n"); + (void) HDfprintf(stdout, "\t -h[elp]:\n"); + (void) HDfprintf(stdout, + "\t Prints this summary of usage, and exits.\n\n"); + (void) HDfprintf(stdout, "\t <infile(s)>:\n"); + (void) HDfprintf(stdout, + "\t Name of the Input file(s), containing a \n"); + (void) HDfprintf(stdout, + "\t single n-dimensional floating point or integer array \n"); + (void) HDfprintf(stdout, + "\t in either ASCII text, native floating point(32-bit \n"); + (void) HDfprintf(stdout, + "\t or 64-bit) or native integer(8-bit or 16-bit or \n"); + (void) HDfprintf(stdout, + "\t 32-bit or 64-bit). Data to be specified in the order\n"); + (void) HDfprintf(stdout, "\t of fastest changing dimensions first.\n\n"); + (void) HDfprintf(stdout, "\t -c[config] <configfile>:\n"); + (void) HDfprintf(stdout, + "\t Every input file should be associated with a \n"); + (void) HDfprintf(stdout, + "\t configuration file and this is done by the -c option.\n"); + (void) HDfprintf(stdout, + "\t <configfile> is the name of the configuration file.\n"); + (void) HDfprintf(stdout, "\t (See Section \"CONFIGURATION FILE\")\n\n"); + (void) HDfprintf(stdout, "\t -o[utfile] <outfile>:\n"); + (void) HDfprintf(stdout, + "\t Name of the HDF5 output file. Data from one or more \n"); + (void) HDfprintf(stdout, + "\t input files are stored as one or more data sets in \n"); + (void) HDfprintf(stdout, + "\t <outfile>. The output file may be an existing file or \n"); + (void) HDfprintf(stdout, + "\t it maybe new in which case it will be created.\n\n\n"); + (void) HDfprintf(stdout, "\t CONFIGURATION FILE:\n"); + (void) HDfprintf(stdout, + "\t The configuration file is an ASCII text file and must be \n"); + (void) HDfprintf(stdout, + "\t the ddl formatted file (without data values) produced by h5dump \n"); + (void) HDfprintf(stdout, + "\t when used with the options '-o outfilename -b' of a single dataset (-d) \n"); + (void) HDfprintf(stdout, + "\t OR organized as \"CONFIG-KEYWORD VALUE\" pairs, one pair on each \n"); + (void) HDfprintf(stdout, "\t line.\n\n"); + (void) HDfprintf(stdout, + "\t The configuration file may have the following keywords each \n"); + (void) HDfprintf(stdout, "\t followed by an acceptable value.\n\n"); + (void) HDfprintf(stdout, "\t Required KEYWORDS:\n"); + (void) HDfprintf(stdout, "\t PATH\n"); + (void) HDfprintf(stdout, "\t INPUT-CLASS\n"); + (void) HDfprintf(stdout, "\t INPUT-SIZE\n"); + (void) HDfprintf(stdout, "\t RANK\n"); + (void) HDfprintf(stdout, "\t DIMENSION-SIZES\n"); + (void) HDfprintf(stdout, "\t OUTPUT-CLASS\n"); + (void) HDfprintf(stdout, "\t OUTPUT-SIZE\n\n"); + (void) HDfprintf(stdout, "\t Optional KEYWORDS:\n"); + (void) HDfprintf(stdout, "\t OUTPUT-ARCHITECTURE\n"); + (void) HDfprintf(stdout, "\t OUTPUT-BYTE-ORDER\n"); + (void) HDfprintf(stdout, "\t CHUNKED-DIMENSION-SIZES\n"); + (void) HDfprintf(stdout, "\t COMPRESSION-TYPE\n"); + (void) HDfprintf(stdout, "\t COMPRESSION-PARAM\n"); + (void) HDfprintf(stdout, "\t EXTERNAL-STORAGE\n"); + (void) HDfprintf(stdout, "\t MAXIMUM-DIMENSIONS\n\n\n"); + (void) HDfprintf(stdout, "\t Values for keywords:\n"); + (void) HDfprintf(stdout, "\t PATH:\n"); + (void) HDfprintf(stdout, "\t Strings separated by spaces to represent\n"); + (void) HDfprintf(stdout, "\t the path of the data-set. If the groups in\n"); + (void) HDfprintf(stdout, + "\t the path do not exist, they will be created. \n"); + (void) HDfprintf(stdout, "\t For example,\n"); + (void) HDfprintf(stdout, "\t PATH grp1/grp2/dataset1\n"); + (void) HDfprintf(stdout, "\t PATH: keyword\n"); + (void) HDfprintf(stdout, "\t grp1: group under the root. If\n"); + (void) HDfprintf(stdout, "\t non-existent will be created.\n"); + (void) HDfprintf(stdout, "\t grp2: group under grp1. If \n"); + (void) HDfprintf(stdout, "\t non-existent will be created \n"); + (void) HDfprintf(stdout, "\t under grp1.\n"); + (void) HDfprintf(stdout, "\t dataset1: the name of the data-set \n"); + (void) HDfprintf(stdout, "\t to be created.\n\n"); + (void) HDfprintf(stdout, "\t INPUT-CLASS:\n"); + (void) HDfprintf(stdout, "\t String denoting the type of input data.\n"); + (void) HDfprintf(stdout, "\t (\"TEXTIN\", \"TEXTFP\", \"FP\", \"IN\", \n"); + (void) HDfprintf(stdout, "\t \"STR\", \"TEXTUIN\", \"UIN\"). \n"); + (void) HDfprintf(stdout, + "\t INPUT-CLASS \"TEXTIN\" denotes an ASCII text \n"); + (void) HDfprintf(stdout, + "\t file with signed integer data in ASCII form,\n"); + (void) HDfprintf(stdout, + "\t INPUT-CLASS \"TEXTUIN\" denotes an ASCII text \n"); + (void) HDfprintf(stdout, + "\t file with unsigned integer data in ASCII form,\n"); + (void) HDfprintf(stdout, + "\t \"TEXTFP\" denotes an ASCII text file containing\n"); + (void) HDfprintf(stdout, "\t floating point data in the fixed notation\n"); + (void) HDfprintf(stdout, "\t (325.34),\n"); + (void) HDfprintf(stdout, + "\t \"FP\" denotes a floating point binary file,\n"); + (void) HDfprintf(stdout, + "\t \"IN\" denotes a signed integer binary file,\n"); + (void) HDfprintf(stdout, + "\t \"UIN\" denotes an unsigned integer binary file,\n"); + (void) HDfprintf(stdout, "\t & \"STR\" denotes an ASCII text file the \n"); + (void) HDfprintf(stdout, + "\t contents of which should be stored as an 1-D \n"); + (void) HDfprintf(stdout, "\t array of strings.\n"); + (void) HDfprintf(stdout, "\t If INPUT-CLASS is \"STR\", then RANK, \n"); + (void) HDfprintf(stdout, + "\t DIMENSION-SIZES, OUTPUT-CLASS, OUTPUT-SIZE, \n"); + (void) HDfprintf(stdout, "\t OUTPUT-ARCHITECTURE and OUTPUT-BYTE-ORDER \n"); + (void) HDfprintf(stdout, "\t will be ignored.\n\n\n"); + (void) HDfprintf(stdout, "\t INPUT-SIZE:\n"); + (void) HDfprintf(stdout, + "\t Integer denoting the size of the input data \n"); + (void) HDfprintf(stdout, "\t (8, 16, 32, 64). \n\n"); + (void) HDfprintf(stdout, "\t For floating point,\n"); + (void) HDfprintf(stdout, "\t INPUT-SIZE can be 32 or 64.\n"); + (void) HDfprintf(stdout, "\t For integers (signed and unsigned)\n"); + (void) HDfprintf(stdout, "\t INPUT-SIZE can be 8, 16, 32 or 64.\n\n"); + (void) HDfprintf(stdout, "\t RANK:\n"); + (void) HDfprintf(stdout, + "\t Integer denoting the number of dimensions.\n\n"); + (void) HDfprintf(stdout, "\t DIMENSION-SIZES:\n"); + (void) HDfprintf(stdout, + "\t Integers separated by spaces to denote the \n"); + (void) HDfprintf(stdout, "\t dimension sizes for the no. of dimensions \n"); + (void) HDfprintf(stdout, "\t determined by rank.\n\n"); + (void) HDfprintf(stdout, "\t OUTPUT-CLASS:\n"); + (void) HDfprintf(stdout, + "\t String dentoting data type of the dataset to \n"); + (void) HDfprintf(stdout, "\t be written (\"IN\",\"FP\", \"UIN\")\n\n"); + (void) HDfprintf(stdout, "\t OUTPUT-SIZE:\n"); + (void) HDfprintf(stdout, + "\t Integer denoting the size of the data in the \n"); + (void) HDfprintf(stdout, "\t output dataset to be written.\n"); + (void) HDfprintf(stdout, + "\t If OUTPUT-CLASS is \"FP\", OUTPUT-SIZE can be \n"); + (void) HDfprintf(stdout, "\t 32 or 64.\n"); + (void) HDfprintf(stdout, + "\t If OUTPUT-CLASS is \"IN\" or \"UIN\", OUTPUT-SIZE\n"); + (void) HDfprintf(stdout, "\t can be 8, 16, 32 or 64.\n\n"); + (void) HDfprintf(stdout, "\t OUTPUT-ARCHITECTURE:\n"); + (void) HDfprintf(stdout, "\t STRING denoting the type of output \n"); + (void) HDfprintf(stdout, + "\t architecture. Can accept the following values\n"); + (void) HDfprintf(stdout, "\t STD\n"); + (void) HDfprintf(stdout, "\t IEEE\n"); + (void) HDfprintf(stdout, "\t INTEL\n"); + (void) HDfprintf(stdout, "\t CRAY\n"); + (void) HDfprintf(stdout, "\t MIPS\n"); + (void) HDfprintf(stdout, "\t ALPHA\n"); + (void) HDfprintf(stdout, "\t NATIVE (default)\n"); + (void) HDfprintf(stdout, "\t UNIX\n\n"); + (void) HDfprintf(stdout, "\t OUTPUT-BYTE-ORDER:\n"); + (void) HDfprintf(stdout, + "\t String denoting the output-byte-order. Ignored\n"); + (void) HDfprintf(stdout, + "\t if the OUTPUT-ARCHITECTURE is not specified or\n"); + (void) HDfprintf(stdout, "\t if it is IEEE, UNIX or STD. Can accept the \n"); + (void) HDfprintf(stdout, "\t following values.\n"); + (void) HDfprintf(stdout, "\t BE (default)\n"); + (void) HDfprintf(stdout, "\t LE\n\n"); + (void) HDfprintf(stdout, "\t CHUNKED-DIMENSION-SIZES:\n"); + (void) HDfprintf(stdout, "\t Integers separated by spaces to denote the \n"); + (void) HDfprintf(stdout, + "\t dimension sizes of the chunk for the no. of \n"); + (void) HDfprintf(stdout, + "\t dimensions determined by rank. Required field\n"); + (void) HDfprintf(stdout, + "\t to denote that the dataset will be stored with\n"); + (void) HDfprintf(stdout, + "\t chunked storage. If this field is absent the\n"); + (void) HDfprintf(stdout, + "\t dataset will be stored with contiguous storage.\n\n"); + (void) HDfprintf(stdout, "\t COMPRESSION-TYPE:\n"); + (void) HDfprintf(stdout, + "\t String denoting the type of compression to be\n"); + (void) HDfprintf(stdout, "\t used with the chunked storage. Requires the\n"); + (void) HDfprintf(stdout, + "\t CHUNKED-DIMENSION-SIZES to be specified. The only \n"); + (void) HDfprintf(stdout, + "\t currently supported compression method is GZIP. \n"); + (void) HDfprintf(stdout, "\t Will accept the following value\n"); + (void) HDfprintf(stdout, "\t GZIP\n\n"); + (void) HDfprintf(stdout, "\t COMPRESSION-PARAM:\n"); + (void) HDfprintf(stdout, + "\t Integer used to denote compression level and \n"); + (void) HDfprintf(stdout, "\t this option is to be always specified when \n"); + (void) HDfprintf(stdout, + "\t the COMPRESSION-TYPE option is specified. The\n"); + (void) HDfprintf(stdout, "\t values are applicable only to GZIP \n"); + (void) HDfprintf(stdout, "\t compression.\n"); + (void) HDfprintf(stdout, "\t Value 1-9: The level of Compression. \n"); + (void) HDfprintf(stdout, "\t 1 will result in the fastest \n"); + (void) HDfprintf(stdout, "\t compression while 9 will result in \n"); + (void) HDfprintf(stdout, "\t the best compression ratio. The default\n"); + (void) HDfprintf(stdout, "\t level of compression is 6.\n\n"); + (void) HDfprintf(stdout, "\t EXTERNAL-STORAGE:\n"); + (void) HDfprintf(stdout, + "\t String to denote the name of the non-HDF5 file \n"); + (void) HDfprintf(stdout, + "\t to store data to. Cannot be used if CHUNKED-\n"); + (void) HDfprintf(stdout, + "\t DIMENSIONS or COMPRESSION-TYPE or EXTENDIBLE-\n"); + (void) HDfprintf(stdout, "\t DATASET is specified.\n"); + (void) HDfprintf(stdout, "\t Value <external-filename>: the name of the \n"); + (void) HDfprintf(stdout, "\t external file as a string to be used.\n\n"); + (void) HDfprintf(stdout, "\t MAXIMUM-DIMENSIONS:\n"); + (void) HDfprintf(stdout, "\t Integers separated by spaces to denote the \n"); + (void) HDfprintf(stdout, "\t maximum dimension sizes of all the \n"); + (void) HDfprintf(stdout, "\t dimensions determined by rank. Requires the\n"); + (void) HDfprintf(stdout, + "\t CHUNKED-DIMENSION-SIZES to be specified. A value of \n"); + (void) HDfprintf(stdout, "\t -1 for any dimension implies UNLIMITED \n"); + (void) HDfprintf(stdout, + "\t DIMENSION size for that particular dimension.\n\n"); + (void) HDfprintf(stdout, "\t EXAMPLES:\n"); + (void) HDfprintf(stdout, "\t 1. Configuration File may look like:\n\n"); + (void) HDfprintf(stdout, "\t PATH work h5 pkamat First-set\n"); + (void) HDfprintf(stdout, "\t INPUT-CLASS TEXTFP\n"); + (void) HDfprintf(stdout, "\t RANK 3\n"); + (void) HDfprintf(stdout, "\t DIMENSION-SIZES 5 2 4\n"); + (void) HDfprintf(stdout, "\t OUTPUT-CLASS FP\n"); + (void) HDfprintf(stdout, "\t OUTPUT-SIZE 64\n"); + (void) HDfprintf(stdout, "\t OUTPUT-ARCHITECTURE IEEE\n"); + (void) HDfprintf(stdout, "\t OUTPUT-BYTE-ORDER LE\n"); + (void) HDfprintf(stdout, "\t CHUNKED-DIMENSION-SIZES 2 2 2 \n\n"); + (void) HDfprintf(stdout, + "\t The above configuration will accept a floating point array \n"); + (void) HDfprintf(stdout, + "\t (5 x 2 x 4) in an ASCII file with the rank and dimension sizes \n"); + (void) HDfprintf(stdout, + "\t specified and will save it in a chunked data-set (of pattern \n"); + (void) HDfprintf(stdout, + "\t 2 X 2 X 2) of 64-bit floating point in the little-endian order \n"); + (void) HDfprintf(stdout, + "\t and IEEE architecture. The dataset will be stored at\n"); + (void) HDfprintf(stdout, "\t \"/work/h5/pkamat/First-set\"\n\n"); + (void) HDfprintf(stdout, "\t 2. Another configuration could be:\n\n"); + (void) HDfprintf(stdout, "\t PATH Second-set\n"); + (void) HDfprintf(stdout, "\t INPUT-CLASS IN \n"); + (void) HDfprintf(stdout, "\t RANK 5\n"); + (void) HDfprintf(stdout, "\t DIMENSION-SIZES 6 3 5 2 4\n"); + (void) HDfprintf(stdout, "\t OUTPUT-CLASS IN\n"); + (void) HDfprintf(stdout, "\t OUTPUT-SIZE 32\n"); + (void) HDfprintf(stdout, "\t CHUNKED-DIMENSION-SIZES 2 2 2 2 2\n"); + (void) HDfprintf(stdout, "\t EXTENDIBLE-DATASET 1 3 \n"); + (void) HDfprintf(stdout, "\t COMPRESSION-TYPE GZIP\n"); + (void) HDfprintf(stdout, "\t COMPRESSION-PARAM 7\n\n\n"); + (void) HDfprintf(stdout, + "\t The above configuration will accept an integer array \n"); + (void) HDfprintf(stdout, + "\t (6 X 3 X 5 x 2 x 4) in a binary file with the rank and \n"); + (void) HDfprintf(stdout, + "\t dimension sizes specified and will save it in a chunked data-set\n"); + (void) HDfprintf(stdout, + "\t (of pattern 2 X 2 X 2 X 2 X 2) of 32-bit floating point in \n"); + (void) HDfprintf(stdout, + "\t native format (as output-architecture is not specified). The \n"); + (void) HDfprintf(stdout, + "\t first and the third dimension will be defined as unlimited. The \n"); + (void) HDfprintf(stdout, + "\t data-set will be compressed using GZIP and a compression level \n"); + (void) HDfprintf(stdout, "\t of 7.\n"); + (void) HDfprintf(stdout, + "\t The dataset will be stored at \"/Second-set\"\n\n"); + return; +} + +void usage(char *name) +{ + (void) HDfprintf(stdout, "\nUsage:\t%s -h[elp], OR\n", name); + (void) HDfprintf(stdout, + "\t%s <infile> -c[onfig] <configfile> \ + [<infile> -c[config] <configfile>...] -o[utfile] <outfile> \n\n", name); + return; +} + diff --git a/tools/src/h5import/h5import.h b/tools/src/h5import/h5import.h new file mode 100644 index 0000000..c242483 --- /dev/null +++ b/tools/src/h5import/h5import.h @@ -0,0 +1,198 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * + * Data and structure definitions for h5import + * + */ + +#ifndef H5IMPORT_H__ +#define H5IMPORT_H__ + +/* + * state table tokens + */ +#define FILNAME 0 +/* filename */ +#define OPT_o 1 +/* output filename */ +#define OPT_c 2 /* configuration filename */ +#define OPT_h 3 /* request for explanation */ +#define OPT_d 4 /* dimensions */ +#define OPT_p 5 /* pathname */ +#define OPT_t 6 /* data type */ +#define OPT_s 7 /* data size */ +#define ERR 20 /* invalid token */ + +#define MAX_GROUPS_IN_PATH 20 +#define MAX_PATH_NAME_LENGTH 255 +#define NUM_KEYS 14 +#define MIN_NUM_DIMENSION 1 +#define MAX_NUM_DIMENSION 32 +#define BASE_10 10 + +#define PATH 0 +#define INPUT_CLASS 1 +#define INPUT_SIZE 2 +#define RANK 3 +#define DIM 4 +#define OUTPUT_CLASS 5 +#define OUTPUT_SIZE 6 +#define OUTPUT_ARCH 7 +#define OUTPUT_B_ORDER 8 +#define CHUNK 9 +#define COMPRESS 10 +#define COMPRESS_PARAM 11 +#define EXTERNALSTORE 12 +#define EXTEND 13 + +/* data types */ +#define H5DT_INT8 signed char +#define H5DT_INT16 short +#define H5DT_INT32 int +#define H5DT_FLOAT32 float +#define H5DT_FLOAT64 double +#define VOIDP void* +#define H5DT_UINT8 unsigned char +#define H5DT_UINT16 unsigned short +#define H5DT_UINT32 unsigned int +#define H5DT_INT64 long long +#define H5DT_UINT64 unsigned H5DT_INT64 + +struct path_info +{ + char group[MAX_GROUPS_IN_PATH][MAX_PATH_NAME_LENGTH]; + int count; +}; + +struct Input +{ + int h5dumpInput; + struct path_info path; + int inputClass; + int inputSize; + int rank; + hsize_t* sizeOfDimension; + int outputClass; + int outputSize; + int outputArchitecture; + int outputByteOrder; + hsize_t* sizeOfChunk; + hsize_t* maxsizeOfDimension; + int compressionType; + int compressionParam; + char *externFilename; + VOIDP data; + int configOptionVector[NUM_KEYS]; +}; + +struct infilesformat +{ + char datafile[255]; + char configfile[255]; + struct Input in; + int config; /* Configfile present? No - 0. Yes - 1 */ +}; + +struct Options +{ + struct infilesformat infiles[30]; /* structure to hold the list of input file names. Limited to 30*/ + char outfile[256]; /* output file name */ + int fcount; /* number of input files */ +}; + +char keytable[NUM_KEYS][30] = { + "PATH", + "INPUT-CLASS", + "INPUT-SIZE", + "RANK", + "DIMENSION-SIZES", + "OUTPUT-CLASS", + "OUTPUT-SIZE", + "OUTPUT-ARCHITECTURE", + "OUTPUT-BYTE-ORDER", + "CHUNKED-DIMENSION-SIZES", + "COMPRESSION-TYPE", + "COMPRESSION-PARAM", + "EXTERNAL-STORAGE", + "MAXIMUM-DIMENSIONS" +}; + +static int state_table[15][8] = +{ + /* token ordering: FILNAME OPT_o OPT_c OPT_h OPT_d OPT_p OPT_t OPT_s */ + + /* state 0: start */ + {1, ERR, ERR, 6, ERR, ERR, ERR, ERR}, + + /* state 1: input files */ + {ERR, ERR, 2, ERR, 7, ERR, ERR, ERR}, + + /* state 2: -c[onfigfile] */ + {3, ERR, ERR, ERR, ERR, ERR, ERR, ERR}, + + /* state 3: configfile */ + {1, 4, ERR, ERR, ERR, ERR, ERR, ERR}, + + /* state 4: -o[utfile] */ + {5, ERR, ERR, ERR, ERR, ERR, ERR, ERR}, + + /* state 5: outfile */ + {ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR}, + + /* state 6: -h[elp] */ + {ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR}, + + /* state 7: -d[ims] */ + {8, ERR, ERR, ERR, ERR, ERR, ERR, ERR}, + + /* state 8: dimensions */ + {1, 4, ERR, ERR, ERR, 9, 11, 13}, + + /* state 9: -p[ath] */ + {10, ERR, ERR, ERR, ERR, ERR, ERR, ERR}, + + /* state 10: path name */ + {1, 4, ERR, ERR, ERR, ERR, 11, 13}, + + /* state 11: -t[ype] */ + {12, ERR, ERR, ERR, ERR, ERR, ERR, ERR}, + + /* state 12: data type */ + {1, 4, ERR, ERR, ERR, ERR, ERR, 13}, + + /* state 13: -s[ize] */ + {14, ERR, ERR, ERR, ERR, ERR, ERR, ERR}, + + /* state 14: data size */ + {1, 4, ERR, ERR, ERR, ERR, ERR, ERR} + +}; + +/* + * + * Function declarations for h5import + * + */ +void usage(char *); +void setDefaultValues(struct Input *in, int count); +void help(char *); + +hid_t createOutputDataType(struct Input *in); +hid_t createInputDataType(struct Input *in); + +#endif /* H5IMPORT_H__ */ + diff --git a/tools/src/h5jam/CMakeLists.txt b/tools/src/h5jam/CMakeLists.txt new file mode 100644 index 0000000..cef54c2 --- /dev/null +++ b/tools/src/h5jam/CMakeLists.txt @@ -0,0 +1,49 @@ +cmake_minimum_required (VERSION 3.1.0) +PROJECT (HDF5_TOOLS_SRC_H5JAM) + +#----------------------------------------------------------------------------- +# Setup include Directories +#----------------------------------------------------------------------------- +INCLUDE_DIRECTORIES (${HDF5_TOOLS_DIR}/lib) + +# -------------------------------------------------------------------- +# Add the h5jam executables +# -------------------------------------------------------------------- +add_executable (h5jam ${HDF5_TOOLS_SRC_H5JAM_SOURCE_DIR}/h5jam.c) +TARGET_NAMING (h5jam STATIC) +TARGET_C_PROPERTIES (h5jam STATIC " " " ") +target_link_libraries (h5jam ${HDF5_TOOLS_LIB_TARGET} ${HDF5_LIB_TARGET}) +set_target_properties (h5jam PROPERTIES FOLDER tools) +set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};h5jam") + +add_executable (h5unjam ${HDF5_TOOLS_SRC_H5JAM_SOURCE_DIR}/h5unjam.c) +TARGET_NAMING (h5unjam STATIC) +TARGET_C_PROPERTIES (h5unjam STATIC " " " ") +target_link_libraries (h5unjam ${HDF5_TOOLS_LIB_TARGET} ${HDF5_LIB_TARGET}) +set_target_properties (h5unjam PROPERTIES FOLDER tools) +set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};h5unjam") + +set (H5_DEP_EXECUTABLES + h5jam + h5unjam +) + +############################################################################## +############################################################################## +### I N S T A L L A T I O N ### +############################################################################## +############################################################################## + +#----------------------------------------------------------------------------- +# Rules for Installation of tools using make Install target +#----------------------------------------------------------------------------- + +#INSTALL_PROGRAM_PDB (h5jam ${HDF5_INSTALL_BIN_DIR} toolsapplications) + +install ( + TARGETS + h5jam h5unjam + EXPORT + ${HDF5_EXPORTED_TARGETS} + RUNTIME DESTINATION ${HDF5_INSTALL_BIN_DIR} COMPONENT toolsapplications +) diff --git a/tools/src/h5jam/Makefile.am b/tools/src/h5jam/Makefile.am new file mode 100644 index 0000000..e244625 --- /dev/null +++ b/tools/src/h5jam/Makefile.am @@ -0,0 +1,35 @@ +# +# Copyright by The HDF Group. +# Copyright by the Board of Trustees of the University of Illinois. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the files COPYING and Copyright.html. COPYING can be found at the root +# of the source code distribution tree; Copyright.html can be found at the +# root level of an installed copy of the electronic HDF5 document set and +# is linked from the top-level documents page. It can also be found at +# http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have +# access to either file, you may request a copy from help@hdfgroup.org. +## +## Makefile.am +## Run automake to generate a Makefile.in from this file. +# +# HDF5 Library Makefile(.in) +# + +include $(top_srcdir)/config/commence.am + +# Include src and tools/lib directories +AM_CPPFLAGS+=-I$(top_srcdir)/src -I$(top_srcdir)/tools/lib + +bin_PROGRAMS=h5jam h5unjam + +# Add h5jam and h5unjam specific linker flags here +h5jam_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) +h5unjam_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) + +# Link against the main HDF5 library and tools library +LDADD=$(LIBH5TOOLS) $(LIBHDF5) + +include $(top_srcdir)/config/conclude.am diff --git a/tools/src/h5jam/h5jam.c b/tools/src/h5jam/h5jam.c new file mode 100644 index 0000000..ae45714 --- /dev/null +++ b/tools/src/h5jam/h5jam.c @@ -0,0 +1,571 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "hdf5.h" +#include "H5private.h" +#include "h5tools.h" +#include "h5tools_utils.h" + +/* Name of tool */ +#define PROGRAMNAME "h5jam" + +herr_t write_pad(int ofile, hsize_t old_where, hsize_t *new_where); +hsize_t compute_user_block_size (hsize_t); +hsize_t copy_some_to_file (int, int, hsize_t, hsize_t, ssize_t); +void parse_command_line (int, const char *[]); + +int do_clobber = FALSE; +char *output_file = NULL; +char *input_file = NULL; +char *ub_file = NULL; + +/* + * Command-line options: The user can specify short or long-named + * parameters. The long-named ones can be partially spelled. When + * adding more, make sure that they don't clash with each other. + */ +static const char *s_opts = "hi:u:o:c:V"; /* add more later ? */ +static struct long_options l_opts[] = { + {"help", no_arg, 'h'}, + {"hel", no_arg, 'h'}, + {"i", require_arg, 'i'}, /* input file */ + {"u", require_arg, 'u'}, /* user block file */ + {"o", require_arg, 'o'}, /* output file */ + {"clobber", no_arg, 'c'}, /* clobber existing UB */ + {"clobbe", no_arg, 'c'}, + {"clobb", no_arg, 'c'}, + {"clob", no_arg, 'c'}, + {"clo", no_arg, 'c'}, + {"cl", no_arg, 'c'}, + {NULL, 0, '\0'} +}; + +/*------------------------------------------------------------------------- + * Function: usage + * + * Purpose: Print the usage message + * + * Return: void + * + * Programmer: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +usage (const char *prog) +{ + HDfflush (stdout); + HDfprintf (stdout, + "usage: %s -i <in_file.h5> -u <in_user_file> [-o <out_file.h5>] [--clobber]\n", prog); + HDfprintf (stdout, "\n"); + HDfprintf (stdout, + "Adds user block to front of an HDF5 file and creates a new concatenated file.\n"); + HDfprintf (stdout, "\n"); + HDfprintf (stdout, + "OPTIONS\n"); + HDfprintf (stdout, + " -i in_file.h5 Specifies the input HDF5 file.\n"); + HDfprintf (stdout, + " -u in_user_file Specifies the file to be inserted into the user block.\n"); + HDfprintf (stdout, + " Can be any file format except an HDF5 format.\n"); + HDfprintf (stdout, + " -o out_file.h5 Specifies the output HDF5 file.\n"); + HDfprintf (stdout, + " If not specified, the user block will be concatenated in\n"); + HDfprintf (stdout, + " place to the input HDF5 file.\n"); + HDfprintf (stdout, + " --clobber Wipes out any existing user block before concatenating\n"); + HDfprintf (stdout, + " the given user block.\n"); + HDfprintf (stdout, + " The size of the new user block will be the larger of;\n"); + HDfprintf (stdout, + " - the size of existing user block in the input HDF5 file\n"); + HDfprintf (stdout, + " - the size of user block required by new input user file\n"); + HDfprintf (stdout, + " (size = 512 x 2N, N is positive integer.)\n"); + HDfprintf (stdout, "\n"); + HDfprintf (stdout, + " -h Prints a usage message and exits.\n"); + HDfprintf (stdout, + " -V Prints the HDF5 library version and exits.\n"); + HDfprintf (stdout, "\n"); + HDfprintf (stdout, + "Exit Status:\n"); + HDfprintf (stdout, + " 0 Succeeded.\n"); + HDfprintf (stdout, + " >0 An error occurred.\n"); +} + + +/*------------------------------------------------------------------------- + * Function: leave + * + * Purpose: Shutdown and call exit() + * + * Return: Does not return + * + *------------------------------------------------------------------------- + */ +static void +leave(int ret) +{ + if (ub_file) + HDfree (ub_file); + if (input_file) + HDfree (input_file); + if (output_file) + HDfree (output_file); + + h5tools_close(); + + HDexit(ret); +} + +/*------------------------------------------------------------------------- + * Function: parse_command_line + * + * Purpose: Parse the command line for the h5dumper. + * + * Return: Success: + * + * Failure: Exits program with EXIT_FAILURE value. + * + * Programmer: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +void +parse_command_line (int argc, const char *argv[]) +{ + int opt = FALSE; + + /* parse command line options */ + while ((opt = get_option (argc, argv, s_opts, l_opts)) != EOF) + { + switch ((char) opt) + { + case 'o': + output_file = HDstrdup (opt_arg); + break; + case 'i': + input_file = HDstrdup (opt_arg); + break; + case 'u': + ub_file = HDstrdup (opt_arg); + break; + case 'c': + do_clobber = TRUE; + break; + case 'h': + usage (h5tools_getprogname()); + leave (EXIT_SUCCESS); + case 'V': + print_version (h5tools_getprogname()); + leave (EXIT_SUCCESS); + case '?': + default: + usage (h5tools_getprogname()); + leave (EXIT_FAILURE); + } + } +} + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: HDF5 user block jammer + * + * Return: Success: 0 + * Failure: 1 + * + * Programmer: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +main (int argc, const char *argv[]) +{ + int ufid = -1; + int h5fid = -1; + int ofid = -1; + void *edata; + H5E_auto2_t func; + hid_t ifile = -1; + hid_t plist = -1; + herr_t status; + htri_t testval; + hsize_t usize; + hsize_t h5fsize; + hsize_t startub; + hsize_t where; + hsize_t newubsize; + off_t fsize; + h5_stat_t sbuf; + h5_stat_t sbuf2; + int res; + + h5tools_setprogname(PROGRAMNAME); + h5tools_setstatus(EXIT_SUCCESS); + + /* Disable error reporting */ + H5Eget_auto2(H5E_DEFAULT, &func, &edata); + H5Eset_auto2(H5E_DEFAULT, NULL, NULL); + + /* Initialize h5tools lib */ + h5tools_init(); + + parse_command_line (argc, argv); + + if (ub_file == NULL) { + /* no user block */ + error_msg("missing arguemnt for -u <user_file>.\n"); + help_ref_msg(stderr); + leave (EXIT_FAILURE); + } + + testval = H5Fis_hdf5 (ub_file); + + if (testval > 0) { + error_msg("-u <user_file> cannot be HDF5 file, but it appears to be an HDF5 file.\n"); + help_ref_msg(stderr); + leave (EXIT_FAILURE); + } + + if (input_file == NULL) { + error_msg("missing arguemnt for -i <HDF5 file>.\n"); + help_ref_msg(stderr); + leave (EXIT_FAILURE); + } + + testval = H5Fis_hdf5 (input_file); + + if (testval <= 0) { + error_msg("Input HDF5 file \"%s\" is not HDF5 format.\n", input_file); + help_ref_msg(stderr); + leave (EXIT_FAILURE); + } + + ifile = H5Fopen (input_file, H5F_ACC_RDONLY, H5P_DEFAULT); + + if (ifile < 0) { + error_msg("Can't open input HDF5 file \"%s\"\n", input_file); + leave (EXIT_FAILURE); + } + + plist = H5Fget_create_plist (ifile); + if (plist < 0) { + error_msg("Can't get file creation plist for file \"%s\"\n", input_file); + H5Fclose(ifile); + leave (EXIT_FAILURE); + } + + status = H5Pget_userblock (plist, &usize); + if (status < 0) { + error_msg("Can't get user block for file \"%s\"\n", input_file); + H5Pclose(plist); + H5Fclose(ifile); + leave (EXIT_FAILURE); + } + + H5Pclose(plist); + H5Fclose(ifile); + + ufid = HDopen(ub_file, O_RDONLY, 0); + if(ufid < 0) { + error_msg("unable to open user block file \"%s\"\n", ub_file); + leave (EXIT_FAILURE); + } + + res = HDfstat(ufid, &sbuf); + if(res < 0) { + error_msg("Can't stat file \"%s\"\n", ub_file); + HDclose (ufid); + leave (EXIT_FAILURE); + } + + fsize = (off_t)sbuf.st_size; + + h5fid = HDopen(input_file, O_RDONLY, 0); + if(h5fid < 0) { + error_msg("unable to open HDF5 file for read \"%s\"\n", input_file); + HDclose (ufid); + leave (EXIT_FAILURE); + } + + res = HDfstat(h5fid, &sbuf2); + if(res < 0) { + error_msg("Can't stat file \"%s\"\n", input_file); + HDclose (h5fid); + HDclose (ufid); + leave (EXIT_FAILURE); + } + + h5fsize = (hsize_t)sbuf2.st_size; + + if (output_file == NULL) { + ofid = HDopen (input_file, O_WRONLY, 0); + + if (ofid < 0) { + error_msg("unable to open output file \"%s\"\n", output_file); + HDclose (h5fid); + HDclose (ufid); + leave (EXIT_FAILURE); + } + } + else { + ofid = HDopen (output_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); + + if (ofid < 0) { + error_msg("unable to create output file \"%s\"\n", output_file); + HDclose (h5fid); + HDclose (ufid); + leave (EXIT_FAILURE); + } + } + + newubsize = compute_user_block_size ((hsize_t) fsize); + + startub = usize; + + if (usize > 0) { + if (do_clobber == TRUE) { + /* where is max of the current size or the new UB */ + if (usize > newubsize) { + newubsize = usize; + } + startub = 0; /*blast the old */ + } + else { + /* add new ub to current ublock, pad to new offset */ + newubsize += usize; + newubsize = compute_user_block_size ((hsize_t) newubsize); + } + } + + /* copy the HDF5 from starting at usize to starting at newubsize: + * makes room at 'from' for new ub */ + /* if no current ub, usize is 0 */ + copy_some_to_file (h5fid, ofid, usize, newubsize, (ssize_t) (h5fsize - usize)); + + /* copy the old ub to the beginning of the new file */ + if (!do_clobber) { + where = copy_some_to_file (h5fid, ofid, (hsize_t) 0, (hsize_t) 0, (ssize_t) usize); + } + + /* copy the new ub to the end of the ub */ + where = copy_some_to_file (ufid, ofid, (hsize_t) 0, startub, (ssize_t) - 1); + + /* pad the ub */ + if(write_pad(ofid, where, &where) < 0) { + error_msg("Can't pad file \"%s\"\n", output_file); + HDclose (h5fid); + HDclose (ufid); + HDclose (ofid); + leave (EXIT_FAILURE); + } /* end if */ + + if(ub_file) + HDfree (ub_file); + if(input_file) + HDfree (input_file); + if(output_file) + HDfree (output_file); + + if(ufid >= 0) + HDclose (ufid); + if(h5fid >= 0) + HDclose (h5fid); + if(ofid >= 0) + HDclose (ofid); + + return h5tools_getstatus(); +} + +/*------------------------------------------------------------------------- + * Function: copy_some_to_file + * + * Purpose: Copy part of the input file to output. + * infid: fd of file to read + * outfid: fd of file to write + * startin: offset of where to read from infid + * startout: offset of where to write to outfid + * limit: bytes to read/write + * + * If limit is < 0, the entire input file is copied. + * + * Note: this routine can be used to copy within + * the same file, i.e., infid and outfid can be the + * same file. + * + * Return: Success: last byte written in the output. + * Failure: Exits program with EXIT_FAILURE value. + * + *------------------------------------------------------------------------- + */ +hsize_t +copy_some_to_file(int infid, int outfid, hsize_t startin, hsize_t startout, + ssize_t limit) +{ + char buf[1024]; + h5_stat_t sbuf; + int res; + ssize_t tot = 0; + ssize_t howmuch = 0; + ssize_t nchars = -1; + ssize_t to; + ssize_t from; + ssize_t toend; + ssize_t fromend; + + if(startin > startout) { + /* this case is prohibited */ + error_msg("copy_some_to_file: panic: startin > startout?\n"); + exit (EXIT_FAILURE); + } /* end if */ + + if(limit < 0) { + res = HDfstat(infid, &sbuf); + if(res < 0) { + error_msg("Can't stat file \n"); + HDexit(EXIT_FAILURE); + } /* end if */ + + howmuch = (ssize_t)sbuf.st_size; + } else { + howmuch = limit; + } /* end if */ + + if(0 == howmuch) + return 0; + + toend = (ssize_t) startout + howmuch; + fromend = (ssize_t) startin + howmuch; + + if (howmuch > 512) { + to = toend - 512; + from = fromend - 512; + } else { + to = toend - howmuch; + from = fromend - howmuch; + } /* end if */ + + while (howmuch > 0) { + HDlseek(outfid, (off_t) to, SEEK_SET); + HDlseek(infid, (off_t) from, SEEK_SET); + + if (howmuch > 512) { + nchars = HDread(infid, buf, (unsigned) 512); + } else { + nchars = HDread(infid, buf, (unsigned)howmuch); + } /* end if */ + + if (nchars <= 0) { + error_msg("Read error \n"); + HDexit(EXIT_FAILURE); + } /* end if */ + + if(HDwrite (outfid, buf, (unsigned) nchars) < 0) { + error_msg("Write error \n"); + HDexit(EXIT_FAILURE); + } + + tot += nchars; + howmuch -= nchars; + if(howmuch > 512) { + to -= nchars; + from -= nchars; + } else { + to -= howmuch; + from -= howmuch; + } /* end if */ + } /* end while */ + + return (hsize_t)tot + (hsize_t)startout; +} /* end copy_some_to_file() */ + + +/*------------------------------------------------------------------------- + * Function: compute_user_block_size + * + * Purpose: Find the offset of the HDF5 header after the user block: + * align at 0, 512, 1024, etc. + * ublock_size: the size of the user block (bytes). + * + * Return: Success: the location of the header == the size of the + * padded user block. + * Failure: none + * + * Return: Success: last byte written in the output. + * Failure: Exits program with EXIT_FAILURE value. + *------------------------------------------------------------------------- + */ +H5_ATTR_CONST hsize_t +compute_user_block_size(hsize_t ublock_size) +{ + hsize_t where = 512; + + if(0 == ublock_size) + return 0; + + while(where < ublock_size) + where *= 2; + + return where; +} /* end compute_user_block_size() */ + +/* + * Write zeroes to fill the file from 'where' to 512, 1024, etc. bytes. + * + * Sets new_where to the size of the padded file and + * returns SUCCEED/FAIL. + */ +herr_t +write_pad(int ofile, hsize_t old_where, hsize_t *new_where) +{ + unsigned int i; + char buf[1]; + hsize_t psize; + + HDassert(new_where); + + buf[0] = '\0'; + + HDlseek(ofile, (off_t)old_where, SEEK_SET); + + psize = compute_user_block_size(old_where); + psize -= old_where; + + for(i = 0; i < psize; i++) + if(HDwrite(ofile, buf, 1) < 0) + return FAIL; + + /* Set the new size of the file. */ + *new_where = old_where + psize; + + return SUCCEED; +} /* end write_pad() */ + diff --git a/tools/src/h5jam/h5unjam.c b/tools/src/h5jam/h5unjam.c new file mode 100644 index 0000000..8f88398 --- /dev/null +++ b/tools/src/h5jam/h5unjam.c @@ -0,0 +1,411 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "hdf5.h" +#include "H5private.h" +#include "h5tools.h" +#include "h5tools_utils.h" + +/* Name of tool */ +#define PROGRAMNAME "h5unjam" + +#define COPY_BUF_SIZE 1024 + +hsize_t write_pad( int , hsize_t ); +hsize_t compute_pad( hsize_t ); +herr_t copy_to_file( FILE *, FILE * , ssize_t, ssize_t ); + +int do_delete = FALSE; +char *output_file = NULL; +char *input_file = NULL; +char *ub_file = NULL; + +/* + * Command-line options: The user can specify short or long-named + * parameters. The long-named ones can be partially spelled. When + * adding more, make sure that they don't clash with each other. + */ +static const char *s_opts = "hu:i:o:d:V"; +static struct long_options l_opts[] = { + { "help", no_arg, 'h' }, + { "hel", no_arg, 'h' }, + {"i", require_arg, 'i'}, /* input file */ + {"u", require_arg, 'u'}, /* user block file */ + {"o", require_arg, 'o'}, /* output file */ + {"delete", no_arg, 'd'}, /* delete ub */ + {"delet", no_arg, 'd'}, + {"dele", no_arg, 'd'}, + {"del", no_arg, 'd'}, + {"de", no_arg, 'd'}, + { NULL, 0, '\0' } +}; + +/*------------------------------------------------------------------------- + * Function: usage + * + * Purpose: Print the usage message + * + * Return: void + * + * Programmer: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +usage(const char *prog) +{ + HDfflush(stdout); + HDfprintf(stdout, + "usage: %s -i <in_file.h5> [-o <out_file.h5> ] [-u <out_user_file> | --delete]\n", prog); + HDfprintf(stdout, "\n"); + HDfprintf(stdout, + "Splits user file and HDF5 file into two files: user block data and HDF5 data.\n"); + HDfprintf(stdout, "\n"); + HDfprintf(stdout, + "OPTIONS\n"); + HDfprintf(stdout, + " -i in_file.h5 Specifies the HDF5 as input. If the input HDF5 file\n"); + HDfprintf(stdout, + " contains no user block, exit with an error message.\n"); + HDfprintf(stdout, + " -o out_file.h5 Specifies output HDF5 file without a user block.\n"); + HDfprintf(stdout, + " If not specified, the user block will be removed from the\n"); + HDfprintf(stdout, + " input HDF5 file.\n"); + HDfprintf(stdout, + " -u out_user_file\n"); + HDfprintf(stdout, + " Specifies the output file containing the data from the\n"); + HDfprintf(stdout, + " user block.\n"); + HDfprintf(stdout, + " Cannot be used with --delete option.\n"); + HDfprintf(stdout, + " --delete Remove the user block from the input HDF5 file. The content\n"); + HDfprintf(stdout, + " of the user block is discarded.\n"); + HDfprintf(stdout, + " Cannot be used with the -u option.\n"); + HDfprintf(stdout, "\n"); + HDfprintf(stdout, + " -h Prints a usage message and exits.\n"); + HDfprintf(stdout, + " -V Prints the HDF5 library version and exits.\n"); + HDfprintf(stdout, "\n"); + HDfprintf(stdout, + " If neither --delete nor -u is specified, the user block from the input file\n"); + HDfprintf(stdout, + " will be displayed to stdout.\n"); + HDfprintf(stdout, "\n"); + HDfprintf(stdout, + "Exit Status:\n"); + HDfprintf(stdout, + " 0 Succeeded.\n"); + HDfprintf(stdout, + " >0 An error occurred.\n"); +} + +/*------------------------------------------------------------------------- + * Function: parse_command_line + * + * Purpose: Parse the command line for the h5dumper. + * + * Return: Success: EXIT_SUCCESS; + * + * Failure: Exits function with EXIT_FAILURE value. + * + *------------------------------------------------------------------------- + */ +static int +parse_command_line(int argc, const char *argv[]) +{ + int opt = FALSE; + + /* parse command line options */ + while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { + switch((char)opt) { + case 'o': + output_file = HDstrdup(opt_arg); + if (output_file) + h5tools_set_data_output_file(output_file, 1); + break; + + case 'i': + input_file = HDstrdup(opt_arg); + if (input_file) + h5tools_set_input_file(input_file, 1); + break;; + + case 'u': + ub_file = HDstrdup(opt_arg); + if (ub_file) + h5tools_set_output_file(ub_file, 1); + else + rawoutstream = stdout; + break; + + case 'd': + do_delete = TRUE; + break; + + case 'h': + usage(h5tools_getprogname()); + h5tools_setstatus(EXIT_SUCCESS); + goto done; + + case 'V': + print_version (h5tools_getprogname()); + h5tools_setstatus(EXIT_SUCCESS); + goto done; + + case '?': + default: + usage(h5tools_getprogname()); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + } + + return EXIT_SUCCESS; + +done: + if(input_file) + HDfree(input_file); + if(output_file) + HDfree(output_file); + if(ub_file) + HDfree(ub_file); + + return EXIT_FAILURE; +} + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: HDF5 user block unjammer + * + * Return: Success: 0 + * Failure: 1 + * + * Programmer: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +main(int argc, const char *argv[]) +{ + void *edata; + H5E_auto2_t func; + hid_t ifile = -1; + hid_t plist = -1; + off_t fsize; + hsize_t usize; + htri_t testval; + herr_t status; + int res; + h5_stat_t sbuf; + + h5tools_setprogname(PROGRAMNAME); + h5tools_setstatus(EXIT_SUCCESS); + + /* Disable error reporting */ + H5Eget_auto2(H5E_DEFAULT, &func, &edata); + H5Eset_auto2(H5E_DEFAULT, NULL, NULL); + + /* Initialize h5tools lib */ + h5tools_init(); + + if(EXIT_FAILURE == parse_command_line(argc, argv)) + goto done; + + if (input_file == NULL) { + /* no user block */ + error_msg("missing arguemnt for HDF5 file input.\n"); + help_ref_msg(stderr); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + testval = H5Fis_hdf5(input_file); + + if (testval <= 0) { + error_msg("Input HDF5 file \"%s\" is not HDF\n", input_file); + help_ref_msg (stderr); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + ifile = H5Fopen(input_file, H5F_ACC_RDONLY , H5P_DEFAULT); + + if (ifile < 0) { + error_msg("Can't open input HDF5 file \"%s\"\n", input_file); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + plist = H5Fget_create_plist(ifile); + if (plist < 0) { + error_msg("Can't get file creation plist for file \"%s\"\n", input_file); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + status = H5Pget_userblock(plist, & usize); + if (status < 0) { + error_msg("Can't get user block for file \"%s\"\n", input_file); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + status = H5Pclose(plist); + HDassert(status >= 0); + status = H5Fclose(ifile); + HDassert(status >= 0); + + if (usize == 0) { + /* no user block to remove: message? */ + error_msg("\"%s\" has no user block: no change to file\n", input_file); + h5tools_setstatus(EXIT_SUCCESS); + goto done; + } + + res = HDfstat(HDfileno(rawinstream), &sbuf); + if(res < 0) { + error_msg("Can't stat file \"%s\"\n", input_file); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + fsize = sbuf.st_size; + + if (do_delete && (ub_file != NULL)) { + error_msg("??\"%s\"\n", ub_file); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + if (output_file == NULL) { + error_msg("unable to open output HDF5 file \"%s\"\n", input_file); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + /* copy from 0 to 'usize - 1' into ufid */ + if (!do_delete) { + if(copy_to_file(rawinstream, rawoutstream, 0, (ssize_t) usize) < 0) { + error_msg("unable to copy user block to output file \"%s\"\n", ub_file); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + } + + /* copy from usize to end of file into h5fid, + * starting at end of user block if present */ + if(copy_to_file(rawinstream, rawdatastream, (ssize_t) usize, (ssize_t)(fsize - (ssize_t)usize)) < 0) { + error_msg("unable to copy hdf5 data to output file \"%s\"\n", output_file); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + +done: + if(input_file) + HDfree(input_file); + + if(output_file) + HDfree(output_file); + + if(ub_file) { + HDfree(ub_file); + } + + h5tools_close(); + + return h5tools_getstatus(); +} + +/* + * Copy 'how_much' bytes from the input file to the output file, + * starting at byte 'where' in the input file. + * + * Returns 0 on success, -1 on failure. + */ +herr_t +copy_to_file( FILE *infid, FILE *ofid, ssize_t _where, ssize_t show_much ) +{ + static char buf[COPY_BUF_SIZE]; + size_t how_much; + off_t where = (off_t)_where; + off_t to; + off_t from; + herr_t ret_value = 0; + + /* nothing to copy */ + if(show_much <= 0) + goto done; + how_much = (size_t)show_much; + + /* rewind */ + HDfseek(infid, 0L, 0); + + from = where; + to = 0; + while(how_much > 0) { + size_t bytes_in = 0; /* # of bytes to read */ + size_t bytes_read = 0; /* # of bytes actually read */ + size_t bytes_wrote = 0; /* # of bytes written */ + + if (how_much > COPY_BUF_SIZE) + bytes_in = COPY_BUF_SIZE; + else + bytes_in = how_much; + + /* Seek to correct position in input file */ + HDfseek(infid, from, SEEK_SET); + + /* Read data to buffer */ + bytes_read = HDfread(buf, (size_t)1, bytes_in, infid); + if(0 == bytes_read && HDferror(infid)) { + ret_value = -1; + goto done; + } /* end if */ + if(0 == bytes_read && HDfeof(infid)) { + goto done; + } /* end if */ + + /* Seek to correct position in output file */ + HDfseek(ofid, to, SEEK_SET); + + /* Update positions/size */ + how_much -= bytes_read; + from += (off_t)bytes_read; + to += (off_t)bytes_read; + + /* Write nchars bytes to output file */ + bytes_wrote = HDfwrite(buf, (size_t)1, bytes_read, ofid); + if(bytes_wrote != bytes_read || (0 == bytes_wrote && HDferror(ofid))) { /* error */ + ret_value = -1; + goto done; + } /* end if */ + } /* end while */ + +done: + return ret_value; +} /* end copy_to_file */ + diff --git a/tools/src/h5ls/CMakeLists.txt b/tools/src/h5ls/CMakeLists.txt new file mode 100644 index 0000000..24e11cc --- /dev/null +++ b/tools/src/h5ls/CMakeLists.txt @@ -0,0 +1,41 @@ +cmake_minimum_required (VERSION 3.1.0) +PROJECT (HDF5_TOOLS_SRC_H5LS) + +#----------------------------------------------------------------------------- +# Setup include Directories +#----------------------------------------------------------------------------- +INCLUDE_DIRECTORIES (${HDF5_TOOLS_DIR}/lib) + +#----------------------------------------------------------------------------- +# Add the h5ls executable +#----------------------------------------------------------------------------- +add_executable (h5ls ${HDF5_TOOLS_SRC_H5LS_SOURCE_DIR}/h5ls.c) +TARGET_NAMING (h5ls STATIC) +TARGET_C_PROPERTIES (h5ls STATIC " " " ") +target_link_libraries (h5ls ${HDF5_TOOLS_LIB_TARGET} ${HDF5_LIB_TARGET}) +set_target_properties (h5ls PROPERTIES FOLDER tools) +set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};h5ls") + +set (H5_DEP_EXECUTABLES + h5ls +) + +############################################################################## +############################################################################## +### I N S T A L L A T I O N ### +############################################################################## +############################################################################## + +#----------------------------------------------------------------------------- +# Rules for Installation of tools using make Install target +#----------------------------------------------------------------------------- + +#INSTALL_PROGRAM_PDB (h5ls ${HDF5_INSTALL_BIN_DIR} toolsapplications) + +install ( + TARGETS + h5ls + EXPORT + ${HDF5_EXPORTED_TARGETS} + RUNTIME DESTINATION ${HDF5_INSTALL_BIN_DIR} COMPONENT toolsapplications +) diff --git a/tools/src/h5ls/Makefile.am b/tools/src/h5ls/Makefile.am new file mode 100644 index 0000000..dfa8bb6 --- /dev/null +++ b/tools/src/h5ls/Makefile.am @@ -0,0 +1,35 @@ +# +# Copyright by The HDF Group. +# Copyright by the Board of Trustees of the University of Illinois. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the files COPYING and Copyright.html. COPYING can be found at the root +# of the source code distribution tree; Copyright.html can be found at the +# root level of an installed copy of the electronic HDF5 document set and +# is linked from the top-level documents page. It can also be found at +# http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have +# access to either file, you may request a copy from help@hdfgroup.org. +## +## Makefile.am +## Run automake to generate a Makefile.in from this file. +# +# HDF5 Library Makefile(.in) +# + +include $(top_srcdir)/config/commence.am + +# Include src and tools/lib directories +AM_CPPFLAGS+=-I$(top_srcdir)/src -I$(top_srcdir)/tools/lib + +# This is our main target, the h5ls tool +bin_PROGRAMS=h5ls + +# Add h5ls specific linker flags here +h5ls_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) + +# All programs depend on the hdf5 and h5tools libraries +LDADD=$(LIBH5TOOLS) $(LIBHDF5) + +include $(top_srcdir)/config/conclude.am diff --git a/tools/src/h5ls/h5ls.c b/tools/src/h5ls/h5ls.c new file mode 100644 index 0000000..a032f08 --- /dev/null +++ b/tools/src/h5ls/h5ls.c @@ -0,0 +1,2939 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Robb Matzke <matzke@llnl.gov> + * Monday, March 23, 1998 + */ + + +/* + * We include the private header file so we can get to the uniform + * programming environment it declares. Other than that, h5ls only calls + * HDF5 API functions (except for H5G_basename()) + */ +#include "H5private.h" +#include "h5tools.h" +#include "h5tools_utils.h" +#include "h5tools_dump.h" +#include "h5trav.h" + +/* Name of tool */ +#define PROGRAMNAME "h5ls" + +#define NAME_BUF_SIZE 2048 +/* + * Alternative formating for data dumped by H5LS + * + * This table only affects H5LS output. + */ +static h5tool_format_t ls_dataformat = { + 0, /*raw */ + + "", /*fmt_raw */ + "%d", /*fmt_int */ + "%u", /*fmt_uint */ + "%hhd", /*fmt_schar */ + "%u", /*fmt_uchar */ + "%d", /*fmt_short */ + "%u", /*fmt_ushort */ + "%ld", /*fmt_long */ + "%lu", /*fmt_ulong */ + NULL, /*fmt_llong */ + NULL, /*fmt_ullong */ + "%g", /*fmt_double */ + "%g", /*fmt_float */ + + 0, /*ascii */ + 0, /*str_locale */ + 0, /*str_repeat */ + + "[", /*arr_pre */ + ",", /*arr_sep */ + "]", /*arr_suf */ + 1, /*arr_linebreak */ + + "", /*cmpd_name */ + ",", /*cmpd_sep */ + "{", /*cmpd_pre */ + "}", /*cmpd_suf */ + "", /*cmpd_end */ + + ",", /*vlen_sep */ + "(", /*vlen_pre */ + ")", /*vlen_suf */ + "", /*vlen_end */ + + "%s", /*elmt_fmt */ + ",", /*elmt_suf1 */ + " ", /*elmt_suf2 */ + + HSIZE_T_FORMAT, /*idx_n_fmt */ + ",", /*idx_sep */ + "(%s)", /*idx_fmt */ + + 65535, /*line_ncols *//*standard default columns */ + 0, /*line_per_line */ + "", /*line_pre */ + "%s", /*line_1st */ + "%s", /*line_cont */ + "", /*line_suf */ + "", /*line_sep */ + 1, /*line_multi_new */ + "", /*line_indent */ + + 0, /*skip_first */ + + 0, /*obj_hidefileno */ + "-%lu:"H5_PRINTF_HADDR_FMT, /*obj_format */ + + 0, /*dset_hidefileno */ + "DSET-%s ", /*dset_format */ + "%sBlk%lu: ", /*dset_blockformat_pre */ + "%sPt%lu: ", /*dset_ptformat_pre */ + "%s", /*dset_ptformat */ + 1, /*array indices */ + 1 /*escape non printable characters */ +}; + +/* Struct to pass through to visitors */ +typedef struct { + const char *fname; /* Filename */ + hid_t fid; /* File ID */ + hid_t gid; /* Group ID */ + hbool_t symlink_target; /* Whether this is the target of an symbolic link */ + symlink_trav_t *symlink_list; /* List of visited symbolic links */ + size_t base_len; /* Length of base path name, if not root */ + size_t name_start; /* # of leading characters to strip off path names on output */ +}iter_t; + +/* Command-line switches */ +static int verbose_g = 0; /* lots of extra output */ +static int width_g = 80; /* output width in characters */ +static hbool_t address_g = FALSE; /* print raw data addresses */ +static hbool_t data_g = FALSE; /* display dataset values? */ +static hbool_t label_g = FALSE; /* label compound values? */ +static hbool_t string_g = FALSE; /* print 1-byte numbers as ASCII? */ +static hbool_t fullname_g = FALSE; /* print full path names */ +static hbool_t recursive_g = FALSE; /* recursive descent listing */ +static hbool_t follow_symlink_g = FALSE; /* follow symbolic links */ +static hbool_t no_dangling_link_g = FALSE; /* treat dangling link is error */ +static hbool_t follow_elink_g = FALSE; /* follow external links */ +static hbool_t grp_literal_g = FALSE; /* list group, not contents */ +static hbool_t hexdump_g = FALSE; /* show data as raw hexadecimal */ +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 */ +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 { + const char *name; + hid_t (*open)(hid_t loc, const char *name, hid_t apl_id); + herr_t (*close)(hid_t obj); + herr_t (*list1)(hid_t obj); + herr_t (*list2)(hid_t obj, const char *name); +} dispatch_g[H5O_TYPE_NTYPES]; + +#define DISPATCH(TYPE, NAME, LIST1, LIST2) { \ + dispatch_g[TYPE].name = (NAME); \ + dispatch_g[TYPE].list1 = (LIST1); \ + dispatch_g[TYPE].list2 = (LIST2); \ +} + +static void print_type(h5tools_str_t *buffer, hid_t type, int ind); +static hbool_t print_int_type(h5tools_str_t *buffer, hid_t type, int ind); +static hbool_t print_float_type(h5tools_str_t *buffer, hid_t type, int ind); +static herr_t visit_obj(hid_t file, const char *oname, iter_t *iter); + + +/*------------------------------------------------------------------------- + * Function: usage + * + * Purpose: Prints a usage message on stderr and then returns. + * + * Return: void + * + * Programmer: Robb Matzke + * Thursday, July 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +usage (void) +{ + FLUSHSTREAM(rawoutstream); + PRINTVALSTREAM(rawoutstream, "usage: h5ls [OPTIONS] file[/OBJECT] [file[/[OBJECT]...]\n"); + PRINTVALSTREAM(rawoutstream, " OPTIONS\n"); + PRINTVALSTREAM(rawoutstream, " -h, -?, --help Print a usage message and exit\n"); + PRINTVALSTREAM(rawoutstream, " -a, --address Print raw data address. If dataset is contiguous, address\n"); + PRINTVALSTREAM(rawoutstream, " is offset in file of beginning of raw data. If chunked,\n"); + PRINTVALSTREAM(rawoutstream, " returned list of addresses indicates offset of each chunk.\n"); + PRINTVALSTREAM(rawoutstream, " Must be used with -v, --verbose option.\n"); + PRINTVALSTREAM(rawoutstream, " Provides no information for non-dataset objects.\n"); + PRINTVALSTREAM(rawoutstream, " -d, --data Print the values of datasets\n"); + PRINTVALSTREAM(rawoutstream, " --enable-error-stack\n"); + PRINTVALSTREAM(rawoutstream, " Prints messages from the HDF5 error stack as they occur.\n"); + PRINTVALSTREAM(rawoutstream, " --follow-symlinks\n"); + PRINTVALSTREAM(rawoutstream, " Follow symbolic links (soft links and external links)\n"); + PRINTVALSTREAM(rawoutstream, " to display target object information.\n"); + PRINTVALSTREAM(rawoutstream, " Without this option, h5ls identifies a symbolic link\n"); + PRINTVALSTREAM(rawoutstream, " as a soft link or external link and prints the value\n"); + PRINTVALSTREAM(rawoutstream, " assigned to the symbolic link; it does not provide any\n"); + PRINTVALSTREAM(rawoutstream, " information regarding the target object or determine\n"); + PRINTVALSTREAM(rawoutstream, " whether the link is a dangling link.\n"); + PRINTVALSTREAM(rawoutstream, " --no-dangling-links\n"); + PRINTVALSTREAM(rawoutstream, " Must be used with --follow-symlinks option;\n"); + PRINTVALSTREAM(rawoutstream, " otherwise, h5ls shows error message and returns an exit\n"); + PRINTVALSTREAM(rawoutstream, " code of 1. \n"); + PRINTVALSTREAM(rawoutstream, " Check for any symbolic links (soft links or external links)\n"); + PRINTVALSTREAM(rawoutstream, " that do not resolve to an existing object (dataset, group,\n"); + PRINTVALSTREAM(rawoutstream, " or named datatype).\n"); + PRINTVALSTREAM(rawoutstream, " If any dangling link is found, this situation is treated\n"); + PRINTVALSTREAM(rawoutstream, " as an error and h5ls returns an exit code of 1.\n"); + PRINTVALSTREAM(rawoutstream, " -f, --full Print full path names instead of base names\n"); + PRINTVALSTREAM(rawoutstream, " -g, --group Show information about a group, not its contents\n"); + PRINTVALSTREAM(rawoutstream, " -l, --label Label members of compound datasets\n"); + PRINTVALSTREAM(rawoutstream, " -r, --recursive List all groups recursively, avoiding cycles\n"); + PRINTVALSTREAM(rawoutstream, " -s, --string Print 1-byte integer datasets as ASCII\n"); + PRINTVALSTREAM(rawoutstream, " -S, --simple Use a machine-readable output format\n"); + PRINTVALSTREAM(rawoutstream, " -wN, --width=N Set the number of columns of output\n"); + PRINTVALSTREAM(rawoutstream, " -v, --verbose Generate more verbose output\n"); + PRINTVALSTREAM(rawoutstream, " -V, --version Print version number and exit\n"); + PRINTVALSTREAM(rawoutstream, " --vfd=DRIVER Use the specified virtual file driver\n"); + PRINTVALSTREAM(rawoutstream, " -x, --hexdump Show raw data in hexadecimal format\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " file/OBJECT\n"); + PRINTVALSTREAM(rawoutstream, " Each object consists of an HDF5 file name optionally followed by a\n"); + PRINTVALSTREAM(rawoutstream, " slash and an object name within the file (if no object is specified\n"); + PRINTVALSTREAM(rawoutstream, " within the file then the contents of the root group are displayed).\n"); + PRINTVALSTREAM(rawoutstream, " The file name may include a printf(3C) integer format such as\n"); + PRINTVALSTREAM(rawoutstream, " \"%%05d\" to open a file family.\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " Deprecated Options\n"); + PRINTVALSTREAM(rawoutstream, " The following options have been deprecated in HDF5. While they remain\n"); + PRINTVALSTREAM(rawoutstream, " available, they have been superseded as indicated and may be removed\n"); + PRINTVALSTREAM(rawoutstream, " from HDF5 in the future. Use the indicated replacement option in all\n"); + PRINTVALSTREAM(rawoutstream, " new work; where possible, existing scripts, et cetera, should also be\n"); + PRINTVALSTREAM(rawoutstream, " updated to use the replacement option.\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " -E or --external Follow external links.\n"); + PRINTVALSTREAM(rawoutstream, " Replaced by --follow-symlinks.\n"); + PRINTVALSTREAM(rawoutstream, " -e, --errors Show all HDF5 error reporting\n"); + PRINTVALSTREAM(rawoutstream, " Replaced by --enable-error-stack.\n"); +} + + + +/*------------------------------------------------------------------------- + * Function: print_string + * + * Purpose: Print a string value by escaping unusual characters. If + * STREAM is null then we only count how large the output would + * be. + * + * Return: Number of characters printed. + * + * Programmer: Robb Matzke + * Thursday, November 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +print_string(h5tools_str_t *buffer, const char *s, hbool_t escape_spaces) +{ + int nprint=0; + + for (/*void*/; s && *s; s++) { + switch (*s) { + case '"': + if (buffer) h5tools_str_append(buffer, "\\\""); + nprint += 2; + break; + case '\\': + if (buffer) h5tools_str_append(buffer, "\\\\"); + nprint += 2; + break; + case '\b': + if (buffer) h5tools_str_append(buffer, "\\b"); + nprint += 2; + break; + case '\f': + if (buffer) h5tools_str_append(buffer, "\\f"); + nprint += 2; + break; + case '\n': + if (buffer) h5tools_str_append(buffer, "\\n"); + nprint += 2; + break; + case '\r': + if (buffer) h5tools_str_append(buffer, "\\r"); + nprint += 2; + break; + case '\t': + if (buffer) h5tools_str_append(buffer, "\\t"); + nprint += 2; + break; + case ' ': + if (escape_spaces) { + if (buffer) h5tools_str_append(buffer, "\\ "); + nprint += 2; + } + else { + if (buffer) h5tools_str_append(buffer, " "); + nprint++; + } + break; + default: + if (isprint((int)*s)) { + if (buffer) h5tools_str_append(buffer, "%c", *s); + nprint++; + } + else { + if (buffer) h5tools_str_append(buffer, "\\%03o", *((const unsigned char*)s)); + nprint += 4; + } + break; + } + } + return nprint; +} + + +/*------------------------------------------------------------------------- + * Function: print_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 +print_obj_name(h5tools_str_t *buffer, 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) + HDsnprintf(fullname, sizeof(fullname), "%s/%s", iter->fname, oname + iter->name_start); + else + name = oname + iter->name_start; + + /* Print the object name, either full name or base name */ + if(fullname_g) + n = print_string(buffer, 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 = print_string(buffer, last_sep, TRUE); + } /* end else */ + h5tools_str_append(buffer, "%*s ", MAX(0, (24 - n)), s); + + return TRUE; +} + + +/*------------------------------------------------------------------------- + * Function: print_native_type + * + * Purpose: Prints the name of a native C data type. + * + * Return: Success: TRUE + * + * Failure: FALSE, nothing printed. + * + * Programmer: Robb Matzke + * Thursday, November 5, 1998 + * + * Modifications: + * Robb Matzke, 1999-06-11 + * Added the C9x types, but we still prefer to display the types + * from the C language itself (like `int' vs. `int32_t'). + * + *------------------------------------------------------------------------- + */ +static hbool_t +print_native_type(h5tools_str_t *buffer, hid_t type, int ind) +{ + if(!simple_output_g) { + if (H5Tequal(type, H5T_NATIVE_SCHAR)==TRUE) { + h5tools_str_append(buffer, "native signed char"); + } else if (H5Tequal(type, H5T_NATIVE_UCHAR)==TRUE) { + h5tools_str_append(buffer, "native unsigned char"); + } else if (H5Tequal(type, H5T_NATIVE_INT)==TRUE) { + h5tools_str_append(buffer, "native int"); + } else if (H5Tequal(type, H5T_NATIVE_UINT)==TRUE) { + h5tools_str_append(buffer, "native unsigned int"); + } else if (H5Tequal(type, H5T_NATIVE_SHORT)==TRUE) { + h5tools_str_append(buffer, "native short"); + } else if (H5Tequal(type, H5T_NATIVE_USHORT)==TRUE) { + h5tools_str_append(buffer, "native unsigned short"); + } else if (H5Tequal(type, H5T_NATIVE_LONG)==TRUE) { + h5tools_str_append(buffer, "native long"); + } else if (H5Tequal(type, H5T_NATIVE_ULONG)==TRUE) { + h5tools_str_append(buffer, "native unsigned long"); + } else if (H5Tequal(type, H5T_NATIVE_LLONG)==TRUE) { + h5tools_str_append(buffer, "native long long"); + } else if (H5Tequal(type, H5T_NATIVE_ULLONG)==TRUE) { + h5tools_str_append(buffer, "native unsigned long long"); + } else if (H5Tequal(type, H5T_NATIVE_FLOAT)==TRUE) { + h5tools_str_append(buffer, "native float"); + } else if (H5Tequal(type, H5T_NATIVE_DOUBLE)==TRUE) { + h5tools_str_append(buffer, "native double"); +#if H5_SIZEOF_LONG_DOUBLE !=0 + } else if (H5Tequal(type, H5T_NATIVE_LDOUBLE)==TRUE) { + h5tools_str_append(buffer, "native long double"); +#endif + } else if (H5Tequal(type, H5T_NATIVE_INT8)==TRUE) { + h5tools_str_append(buffer, "native int8_t"); + } else if (H5Tequal(type, H5T_NATIVE_UINT8)==TRUE) { + h5tools_str_append(buffer, "native uint8_t"); + } else if (H5Tequal(type, H5T_NATIVE_INT16)==TRUE) { + h5tools_str_append(buffer, "native int16_t"); + } else if (H5Tequal(type, H5T_NATIVE_UINT16)==TRUE) { + h5tools_str_append(buffer, "native uint16_t"); + } else if (H5Tequal(type, H5T_NATIVE_INT32)==TRUE) { + h5tools_str_append(buffer, "native int32_t"); + } else if (H5Tequal(type, H5T_NATIVE_UINT32)==TRUE) { + h5tools_str_append(buffer, "native uint32_t"); + } else if (H5Tequal(type, H5T_NATIVE_INT64)==TRUE) { + h5tools_str_append(buffer, "native int64_t"); + } else if (H5Tequal(type, H5T_NATIVE_UINT64)==TRUE) { + h5tools_str_append(buffer, "native uint64_t"); + } else if (H5Tequal(type, H5T_NATIVE_INT_LEAST8)==TRUE) { + h5tools_str_append(buffer, "native int_least8_t"); + } else if (H5Tequal(type, H5T_NATIVE_UINT_LEAST8)==TRUE) { + h5tools_str_append(buffer, "native uint_least8_t"); + } else if (H5Tequal(type, H5T_NATIVE_INT_LEAST16)==TRUE) { + h5tools_str_append(buffer, "native int_least16_t"); + } else if (H5Tequal(type, H5T_NATIVE_UINT_LEAST16)==TRUE) { + h5tools_str_append(buffer, "native uint_least16_t"); + } else if (H5Tequal(type, H5T_NATIVE_INT_LEAST32)==TRUE) { + h5tools_str_append(buffer, "native int_least32_t"); + } else if (H5Tequal(type, H5T_NATIVE_UINT_LEAST32)==TRUE) { + h5tools_str_append(buffer, "native uint_least32_t"); + } else if (H5Tequal(type, H5T_NATIVE_INT_LEAST64)==TRUE) { + h5tools_str_append(buffer, "native int_least64_t"); + } else if (H5Tequal(type, H5T_NATIVE_UINT_LEAST64)==TRUE) { + h5tools_str_append(buffer, "native uint_least64_t"); + } else if (H5Tequal(type, H5T_NATIVE_INT_FAST8)==TRUE) { + h5tools_str_append(buffer, "native int_fast8_t"); + } else if (H5Tequal(type, H5T_NATIVE_UINT_FAST8)==TRUE) { + h5tools_str_append(buffer, "native uint_fast8_t"); + } else if (H5Tequal(type, H5T_NATIVE_INT_FAST16)==TRUE) { + h5tools_str_append(buffer, "native int_fast16_t"); + } else if (H5Tequal(type, H5T_NATIVE_UINT_FAST16)==TRUE) { + h5tools_str_append(buffer, "native uint_fast16_t"); + } else if (H5Tequal(type, H5T_NATIVE_INT_FAST32)==TRUE) { + h5tools_str_append(buffer, "native int_fast32_t"); + } else if (H5Tequal(type, H5T_NATIVE_UINT_FAST32)==TRUE) { + h5tools_str_append(buffer, "native uint_fast32_t"); + } else if (H5Tequal(type, H5T_NATIVE_INT_FAST64)==TRUE) { + h5tools_str_append(buffer, "native int_fast64_t"); + } else if (H5Tequal(type, H5T_NATIVE_UINT_FAST64)==TRUE) { + h5tools_str_append(buffer, "native uint_fast64_t"); + } else if (H5Tequal(type, H5T_NATIVE_B8)==TRUE) { + h5tools_str_append(buffer, "native 8-bit field"); + } else if (H5Tequal(type, H5T_NATIVE_B16)==TRUE) { + h5tools_str_append(buffer, "native 16-bit field"); + } else if (H5Tequal(type, H5T_NATIVE_B32)==TRUE) { + h5tools_str_append(buffer, "native 32-bit field"); + } else if (H5Tequal(type, H5T_NATIVE_B64)==TRUE) { + h5tools_str_append(buffer, "native 64-bit field"); + } else if (H5Tequal(type, H5T_NATIVE_HSIZE)==TRUE) { + h5tools_str_append(buffer, "native hsize_t"); + } else if (H5Tequal(type, H5T_NATIVE_HSSIZE)==TRUE) { + h5tools_str_append(buffer, "native hssize_t"); + } else if (H5Tequal(type, H5T_NATIVE_HERR)==TRUE) { + h5tools_str_append(buffer, "native herr_t"); + } else if (H5Tequal(type, H5T_NATIVE_HBOOL)==TRUE) { + h5tools_str_append(buffer, "native hbool_t"); + } else { + return print_int_type(buffer, type, ind); + } + } else { + return print_int_type(buffer, type, ind); + } + return TRUE; +} + + +/*------------------------------------------------------------------------- + * Function: print_ieee_type + * + * Purpose: Print the name of an IEEE floating-point data type. + * + * Return: Success: TRUE + * + * Failure: FALSE, nothing printed + * + * Programmer: Robb Matzke + * Thursday, November 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static hbool_t +print_ieee_type(h5tools_str_t *buffer, hid_t type, int ind) +{ + if (H5Tequal(type, H5T_IEEE_F32BE)==TRUE) { + h5tools_str_append(buffer, "IEEE 32-bit big-endian float"); + } + else if (H5Tequal(type, H5T_IEEE_F32LE)==TRUE) { + h5tools_str_append(buffer, "IEEE 32-bit little-endian float"); + } + else if (H5Tequal(type, H5T_IEEE_F64BE)==TRUE) { + h5tools_str_append(buffer, "IEEE 64-bit big-endian float"); + } + else if (H5Tequal(type, H5T_IEEE_F64LE)==TRUE) { + h5tools_str_append(buffer, "IEEE 64-bit little-endian float"); + } + else { + return print_float_type(buffer, type, ind); + } + return TRUE; +} + + +/*------------------------------------------------------------------------- + * Function: print_precision + * + * Purpose: Prints information on the next line about precision and + * padding if the precision is less than the total data type + * size. + * + * Return: void + * + * Programmer: Robb Matzke + * Thursday, November 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +print_precision(h5tools_str_t *buffer, hid_t type, int ind) +{ + size_t prec; /* precision */ + H5T_pad_t plsb, pmsb; /* lsb and msb padding */ + const char *plsb_s=NULL; /* lsb padding string */ + const char *pmsb_s=NULL; /* msb padding string */ + size_t nbits; /* number of bits */ + + /* If the precision is less than the total size then show the precision + * and offset on the following line. Also display the padding + * information. */ + if(8 * H5Tget_size(type) != (prec = H5Tget_precision(type))) { + h5tools_str_append(buffer, "\n%*s(%lu bit%s of precision beginning at bit %lu)", + ind, "", (unsigned long)prec, 1 == prec ? "" : "s", + (unsigned long)H5Tget_offset(type)); + + H5Tget_pad(type, &plsb, &pmsb); + if(H5Tget_offset(type) > 0) { + switch(plsb) { + case H5T_PAD_ZERO: + plsb_s = "zero"; + break; + case H5T_PAD_ONE: + plsb_s = "one"; + break; + case H5T_PAD_BACKGROUND: + plsb_s = "bkg"; + break; + case H5T_PAD_ERROR: + case H5T_NPAD: + plsb_s = "unknown"; + break; + default: + break; + } + } + if((unsigned)H5Tget_offset(type) + prec < 8 * H5Tget_size(type)) { + switch(pmsb) { + case H5T_PAD_ZERO: + pmsb_s = "zero"; + break; + case H5T_PAD_ONE: + pmsb_s = "one"; + break; + case H5T_PAD_BACKGROUND: + pmsb_s = "bkg"; + break; + case H5T_PAD_ERROR: + case H5T_NPAD: + pmsb_s = "unknown"; + break; + default: + break; + } + } + if (plsb_s || pmsb_s) { + h5tools_str_append(buffer, "\n%*s(", ind, ""); + if (plsb_s) { + nbits = (unsigned)H5Tget_offset(type); + h5tools_str_append(buffer, "%lu %s bit%s at bit 0", + (unsigned long)nbits, plsb_s, 1 == nbits ? "" : "s"); + } + if (plsb_s && pmsb_s) h5tools_str_append(buffer, ", "); + if (pmsb_s) { + nbits = (8 * H5Tget_size(type)) - ((unsigned)H5Tget_offset(type) + prec); + h5tools_str_append(buffer, "%lu %s bit%s at bit %lu", + (unsigned long)nbits, pmsb_s, 1 == nbits ? "" : "s", + (unsigned long)(8 * H5Tget_size(type) - nbits)); + } + h5tools_str_append(buffer, ")"); + } + } +} + + +/*------------------------------------------------------------------------- + * Function: print_int_type + * + * Purpose: Print the name of an integer data type. Common information + * like number of bits, byte order, and sign scheme appear on + * the first line. Additional information might appear in + * parentheses on the following lines. + * + * Return: Success: TRUE + * + * Failure: FALSE, nothing printed + * + * Programmer: Robb Matzke + * Thursday, November 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static hbool_t +print_int_type(h5tools_str_t *buffer, hid_t type, int ind) +{ + H5T_order_t order; /* byte order value */ + const char *order_s=NULL; /* byte order string */ + H5T_sign_t sign; /* sign scheme value */ + const char *sign_s=NULL; /* sign scheme string */ + + if (H5T_INTEGER!=H5Tget_class(type)) return FALSE; + + /* Byte order */ + if (H5Tget_size(type)>1) { + order = H5Tget_order(type); + if (H5T_ORDER_LE==order) { + order_s = " little-endian"; + } + else if (H5T_ORDER_BE==order) { + order_s = " big-endian"; + } + else if (H5T_ORDER_VAX==order) { + order_s = " mixed-endian"; + } + else { + order_s = " unknown-byte-order"; + } + } + else { + order_s = ""; + } + + /* Sign */ + if ((sign=H5Tget_sign(type))>=0) { + if (H5T_SGN_NONE==sign) { + sign_s = " unsigned"; + } + else if (H5T_SGN_2==sign) { + sign_s = ""; + } + else { + sign_s = " unknown-sign"; + } + } + else { + sign_s = " unknown-sign"; + } + + /* Print size, order, and sign on first line, precision and padding + * information on the subsequent lines */ + h5tools_str_append(buffer, "%lu-bit%s%s integer", + (unsigned long)(8*H5Tget_size(type)), order_s, sign_s); + print_precision(buffer, type, ind); + return TRUE; +} + + +/*------------------------------------------------------------------------- + * Function: print_float_type + * + * Purpose: Print info about a floating point data type. + * + * Return: Success: TRUE + * + * Failure: FALSE, nothing printed + * + * Programmer: Robb Matzke + * Thursday, November 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static hbool_t +print_float_type(h5tools_str_t *buffer, hid_t type, int ind) +{ + H5T_order_t order; /* byte order value */ + const char *order_s=NULL; /* byte order string */ + size_t spos; /* sign bit position */ + size_t esize, epos; /* exponent size and position */ + size_t msize, mpos; /* significand size and position */ + size_t ebias; /* exponent bias */ + H5T_norm_t norm; /* significand normalization */ + const char *norm_s=NULL; /* normalization string */ + H5T_pad_t pad; /* internal padding value */ + const char *pad_s=NULL; /* internal padding string */ + + if (H5T_FLOAT!=H5Tget_class(type)) return FALSE; + + /* Byte order */ + if (H5Tget_size(type)>1) { + order = H5Tget_order(type); + if (H5T_ORDER_LE==order) { + order_s = " little-endian"; + } + else if (H5T_ORDER_BE==order) { + order_s = " big-endian"; + } + else if (H5T_ORDER_VAX==order) { + order_s = " mixed-endian"; + } + else { + order_s = " unknown-byte-order"; + } + } + else { + order_s = ""; + } + + /* Print size and byte order on first line, precision and padding on + * subsequent lines. */ + h5tools_str_append(buffer, "%lu-bit%s floating-point", + (unsigned long)(8*H5Tget_size(type)), order_s); + print_precision(buffer, type, ind); + + /* Print sizes, locations, and other information about each field */ + H5Tget_fields (type, &spos, &epos, &esize, &mpos, &msize); + ebias = H5Tget_ebias(type); + norm = H5Tget_norm(type); + switch (norm) { + case H5T_NORM_IMPLIED: + norm_s = ", msb implied"; + break; + case H5T_NORM_MSBSET: + norm_s = ", msb always set"; + break; + case H5T_NORM_NONE: + norm_s = ", no normalization"; + break; + case H5T_NORM_ERROR: + norm_s = ", unknown normalization"; + break; + default: + ; + break; + } + h5tools_str_append(buffer, "\n%*s(significant for %lu bit%s at bit %lu%s)", ind, "", + (unsigned long)msize, 1==msize?"":"s", (unsigned long)mpos, + norm_s); + h5tools_str_append(buffer, "\n%*s(exponent for %lu bit%s at bit %lu, bias is 0x%lx)", + ind, "", (unsigned long)esize, 1==esize?"":"s", + (unsigned long)epos, (unsigned long)ebias); + h5tools_str_append(buffer, "\n%*s(sign bit at %lu)", ind, "", (unsigned long)spos); + + /* Display internal padding */ + if (1+esize+msize<H5Tget_precision(type)) { + pad = H5Tget_inpad(type); + switch (pad) { + case H5T_PAD_ZERO: + pad_s = "zero"; + break; + case H5T_PAD_ONE: + pad_s = "one"; + break; + case H5T_PAD_BACKGROUND: + pad_s = "bkg"; + break; + case H5T_PAD_ERROR: + case H5T_NPAD: + pad_s = "unknown"; + break; + default: + ; + break; + } + h5tools_str_append(buffer, "\n%*s(internal padding bits are %s)", ind, "", pad_s); + } + return TRUE; +} + + +/*------------------------------------------------------------------------- + * Function: print_cmpd_type + * + * Purpose: Print info about a compound data type. + * + * Return: Success: TRUE + * + * Failure: FALSE, nothing printed + * + * Programmer: Robb Matzke + * Thursday, November 5, 1998 + * + *------------------------------------------------------------------------- + */ +static hbool_t +print_cmpd_type(h5tools_str_t *buffer, hid_t type, int ind) +{ + char *name=NULL; /* member name */ + size_t size; /* total size of type in bytes */ + hid_t subtype; /* member data type */ + int nmembs; /* number of members */ + int n; /* miscellaneous counters */ + unsigned i; /* miscellaneous counters */ + + if(H5T_COMPOUND != H5Tget_class(type)) + return FALSE; + if((nmembs = H5Tget_nmembers(type)) < 0) + return FALSE; + + h5tools_str_append(buffer, "struct {"); + for(i = 0; i < (unsigned)nmembs; i++) { + + /* Name and offset */ + name = H5Tget_member_name(type, i); + h5tools_str_append(buffer, "\n%*s\"", ind+4, ""); + n = print_string(buffer, name, FALSE); + h5tools_str_append(buffer, "\"%*s +%-4lu ", MAX(0, 16-n), "", + (unsigned long)H5Tget_member_offset(type, i)); + H5free_memory(name); + + /* Member's type */ + subtype = H5Tget_member_type(type, i); + print_type(buffer, subtype, ind+4); + H5Tclose(subtype); + } + size = H5Tget_size(type); + h5tools_str_append(buffer, "\n%*s} %lu byte%s", + ind, "", (unsigned long)size, 1==size?"":"s"); + + return TRUE; +} + + +/*------------------------------------------------------------------------- + * Function: print_enum_type + * + * Purpose: Print info about an enumeration data type. + * + * Return: Success: TRUE + * + * Failure: FALSE, nothing printed + * + * Programmer: Robb Matzke + * Wednesday, December 23, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static hbool_t +print_enum_type(h5tools_str_t *buffer, hid_t type, int ind) +{ + int nmembs; /* number of members */ + hid_t super; /* enum base integer type */ + + if(H5T_ENUM != H5Tget_class(type)) + return FALSE; + if((nmembs = H5Tget_nmembers(type)) < 0) + return FALSE; + + super = H5Tget_super(type); + h5tools_str_append(buffer, "enum "); + print_type(buffer, super, ind + 4); + h5tools_str_append(buffer, " {"); + + if(nmembs > 0) { + char **name; /* member names */ + unsigned char *value; /* value array */ + hid_t native = -1; /* native integer data type */ + size_t dst_size; /* destination value type size */ + unsigned i; /* miscellaneous counters */ + + /* Determine what data type to use for the native values. To simplify + * things we entertain three possibilities: + * 1. long long -- the largest native signed integer + * 2. unsigned long long -- the largest native unsigned integer + * 3. raw format */ + if(H5Tget_size(type) <= sizeof(long long)) { + dst_size = sizeof(long long); + if(H5T_SGN_NONE == H5Tget_sign(type)) + native = H5T_NATIVE_ULLONG; + else + native = H5T_NATIVE_LLONG; + } /* end if */ + else + dst_size = H5Tget_size(type); + + /* Get the names and raw values of all members */ + name = (char **)HDcalloc((size_t)nmembs, sizeof(char *)); + value = (unsigned char *)HDcalloc((size_t)nmembs, MAX(H5Tget_size(type), dst_size)); + for(i = 0; i < (unsigned)nmembs; i++) { + name[i] = H5Tget_member_name(type, i); + H5Tget_member_value(type, i, value + i * H5Tget_size(type)); + } + + /* Convert values to native data type */ + if(native > 0) + if(H5Tconvert(super, native, (size_t)nmembs, value, NULL, H5P_DEFAULT) < 0) { + /* Release resources */ + for(i = 0; i < (unsigned)nmembs; i++) + H5free_memory(name[i]); + HDfree(name); + HDfree(value); + + return FALSE; + } + + /* Sort members by increasing value */ + /*not implemented yet*/ + + /* Print members */ + for(i = 0; i < (unsigned)nmembs; i++) { + unsigned char *copy; /* a pointer to value array */ + int nchars; /* number of output characters */ + + h5tools_str_append(buffer, "\n%*s", ind+4, ""); + nchars = print_string(buffer, name[i], TRUE); + h5tools_str_append(buffer, "%*s = ", MAX(0, 16 - nchars), ""); + + if(native < 0) { + size_t j; + + h5tools_str_append(buffer, "0x"); + for(j = 0; j < dst_size; j++) + h5tools_str_append(buffer, "%02x", value[i*dst_size+j]); + } + else if(H5T_SGN_NONE == H5Tget_sign(native)) { + /*On SGI Altix(cobalt), wrong values were printed out with "value+i*dst_size" + *strangely, unless use another pointer "copy".*/ + copy = value + i * dst_size; + h5tools_str_append(buffer, HSIZE_T_FORMAT, *((unsigned long long*)((void*)copy))); + } + else { + /*On SGI Altix(cobalt), wrong values were printed out with "value+i*dst_size" + *strangely, unless use another pointer "copy".*/ + copy = value + i * dst_size; + h5tools_str_append(buffer, "%"H5_PRINTF_LL_WIDTH"d", + *((long long*)((void*)copy))); + } + } + + /* Release resources */ + for(i = 0; i < (unsigned)nmembs; i++) + H5free_memory(name[i]); + HDfree(name); + HDfree(value); + } + else + h5tools_str_append(buffer, "\n%*s <empty>", ind+4, ""); + + h5tools_str_append(buffer, "\n%*s}", ind, ""); + + H5Tclose(super); + + return TRUE; +} + + +/*------------------------------------------------------------------------- + * Function: print_string_type + * + * Purpose: Print information about a string data type. + * + * Return: Success: TRUE + * + * Failure: FALSE, nothing printed + * + * Programmer: Robb Matzke + * Thursday, November 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static hbool_t +print_string_type(h5tools_str_t *buffer, hid_t type, int H5_ATTR_UNUSED ind) +{ + H5T_str_t pad; + const char *pad_s=NULL; + H5T_cset_t cset; + const char *cset_s=NULL; + + if (H5T_STRING!=H5Tget_class(type)) return FALSE; + + /* Padding */ + pad = H5Tget_strpad(type); + switch (pad) { + case H5T_STR_NULLTERM: + pad_s = "null-terminated"; + break; + case H5T_STR_NULLPAD: + pad_s = "null-padded"; + break; + case H5T_STR_SPACEPAD: + pad_s = "space-padded"; + break; + case H5T_STR_RESERVED_3: + case H5T_STR_RESERVED_4: + case H5T_STR_RESERVED_5: + case H5T_STR_RESERVED_6: + case H5T_STR_RESERVED_7: + case H5T_STR_RESERVED_8: + case H5T_STR_RESERVED_9: + case H5T_STR_RESERVED_10: + case H5T_STR_RESERVED_11: + case H5T_STR_RESERVED_12: + case H5T_STR_RESERVED_13: + case H5T_STR_RESERVED_14: + case H5T_STR_RESERVED_15: + case H5T_STR_ERROR: + pad_s = "unknown-format"; + break; + default: + ; + break; + } + + /* Character set */ + cset = H5Tget_cset(type); + switch (cset) { + case H5T_CSET_ASCII: + cset_s = "ASCII"; + break; + case H5T_CSET_UTF8: + cset_s = "UTF-8"; + break; + case H5T_CSET_RESERVED_2: + case H5T_CSET_RESERVED_3: + case H5T_CSET_RESERVED_4: + case H5T_CSET_RESERVED_5: + case H5T_CSET_RESERVED_6: + case H5T_CSET_RESERVED_7: + case H5T_CSET_RESERVED_8: + case H5T_CSET_RESERVED_9: + case H5T_CSET_RESERVED_10: + case H5T_CSET_RESERVED_11: + case H5T_CSET_RESERVED_12: + case H5T_CSET_RESERVED_13: + case H5T_CSET_RESERVED_14: + case H5T_CSET_RESERVED_15: + case H5T_CSET_ERROR: + cset_s = "unknown-character-set"; + break; + default: + ; + break; + } + + if (H5Tis_variable_str(type)) { + h5tools_str_append(buffer, "variable-length"); + } + else { + h5tools_str_append(buffer, "%lu-byte", (unsigned long)H5Tget_size(type)); + } + h5tools_str_append(buffer, " %s %s string", pad_s, cset_s); + return TRUE; +} + + +/*------------------------------------------------------------------------- + * Function: print_reference_type + * + * Purpose: Prints information about a reference data type. + * + * Return: Success: TRUE + * + * Failure: FALSE, nothing printed + * + * Programmer: Robb Matzke + * Thursday, November 5, 1998 + * + * Modifications: + * Robb Matzke, 1999-06-04 + * Knows about object and dataset region references. + * + *------------------------------------------------------------------------- + */ +static hbool_t +print_reference_type(h5tools_str_t *buffer, hid_t type, int H5_ATTR_UNUSED ind) +{ + if (H5T_REFERENCE!=H5Tget_class(type)) return FALSE; + + if (H5Tequal(type, H5T_STD_REF_OBJ)==TRUE) { + h5tools_str_append(buffer, "object reference"); + } + else if (H5Tequal(type, H5T_STD_REF_DSETREG)==TRUE) { + h5tools_str_append(buffer, "dataset region reference"); + } + else { + h5tools_str_append(buffer, "%lu-byte unknown reference", + (unsigned long)H5Tget_size(type)); + } + + return TRUE; +} + + +/*------------------------------------------------------------------------- + * Function: print_opaque_type + * + * Purpose: Prints information about an opaque data type. + * + * Return: Success: TRUE + * + * Failure: FALSE, nothing printed + * + * Programmer: Robb Matzke + * Monday, June 7, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static hbool_t +print_opaque_type(h5tools_str_t *buffer, hid_t type, int ind) +{ + char *tag; + size_t size; + + if (H5T_OPAQUE!=H5Tget_class(type)) return FALSE; + + size = H5Tget_size(type); + h5tools_str_append(buffer, "%lu-byte opaque type", (unsigned long)size); + if ((tag=H5Tget_tag(type))) { + h5tools_str_append(buffer, "\n%*s(tag = \"", ind, ""); + print_string(buffer, tag, FALSE); + h5tools_str_append(buffer, "\")"); + H5free_memory(tag); + } + return TRUE; +} + + +/*------------------------------------------------------------------------- + * Function: print_vlen_type + * + * Purpose: Print information about a variable-length type + * + * Return: Success: TRUE + * + * Failure: FALSE + * + * Programmer: Robb Matzke + * Friday, December 1, 2000 + * + * Modifications: + *------------------------------------------------------------------------- + */ +static hbool_t +print_vlen_type(h5tools_str_t *buffer, hid_t type, int ind) +{ + hid_t super; + + if (H5T_VLEN!=H5Tget_class(type)) return FALSE; + + h5tools_str_append(buffer, "variable length of\n%*s", ind+4, ""); + super = H5Tget_super(type); + print_type(buffer, super, ind+4); + H5Tclose(super); + return TRUE; +} + + +/*--------------------------------------------------------------------------- + * Purpose: Print information about an array type + * + * Return: Success: TRUE + * + * Failure: FALSE + * + * Programmer: Robb Matzke + * Thursday, January 31, 2002 + * + * Modifications: + *--------------------------------------------------------------------------- + */ +static hbool_t +print_array_type(h5tools_str_t *buffer, hid_t type, int ind) +{ + hid_t super; + int ndims, i; + hsize_t *dims=NULL; + + if (H5T_ARRAY!=H5Tget_class(type)) + return FALSE; + ndims = H5Tget_array_ndims(type); + if (ndims) { + dims = (hsize_t *)HDmalloc((unsigned)ndims * sizeof(dims[0])); + H5Tget_array_dims2(type, dims); + + /* Print dimensions */ + for (i=0; i<ndims; i++) + h5tools_str_append(buffer, "%s" HSIZE_T_FORMAT , i?",":"[", dims[i]); + h5tools_str_append(buffer, "]"); + + HDfree(dims); + } + else + h5tools_str_append(buffer, " [SCALAR]\n", rawoutstream); + + + /* Print parent type */ + h5tools_str_append(buffer, " "); + super = H5Tget_super(type); + print_type(buffer, super, ind+4); + H5Tclose(super); + return TRUE; +} + + +/*------------------------------------------------------------------------- + * Function: print_bitfield_type + * + * Purpose: Print information about a bitfield type. + * + * Return: Success: TRUE + * + * Failure: FALSE, nothing printed + * + * Programmer: Pedro Vicente + * Tuesday, May 20, 2003 + * + * Modifications: + * Robb Matzke, LLNL 2003-06-05 + * Generalized Pedro's original if/then/else. Also display + * precision/offset information. + *------------------------------------------------------------------------- + */ +static hbool_t +print_bitfield_type(h5tools_str_t *buffer, hid_t type, int ind) +{ + H5T_order_t order; /* byte order value */ + const char *order_s=NULL; /* byte order string */ + + if (H5T_BITFIELD!=H5Tget_class(type)) return FALSE; + if (H5Tget_size(type)>1) { + order = H5Tget_order(type); + if (H5T_ORDER_LE==order) { + order_s = " little-endian"; + } else if (H5T_ORDER_BE==order) { + order_s = " big-endian"; + } else if (H5T_ORDER_VAX==order) { + order_s = " mixed-endian"; + } else { + order_s = "unknown-byte-order"; + } + } else { + order_s = ""; + } + + h5tools_str_append(buffer, "%lu-bit%s bitfield", + (unsigned long)(8*H5Tget_size(type)), order_s); + print_precision(buffer, type, ind); + return TRUE; +} + + +/*------------------------------------------------------------------------- + * Function: print_type + * + * Purpose: Prints a data type definition. The definition is printed + * without any leading space or trailing line-feed (although + * there might be line-feeds inside the type definition). The + * first line is assumed to have IND characters before it on + * the same line (printed by the caller). + * + * Return: void + * + * Programmer: Robb Matzke + * Thursday, November 5, 1998 + * + * Modifications: + * Robb Matzke, 1999-06-11 + * Prints the OID of shared data types. + * + *------------------------------------------------------------------------- + */ +static void +print_type(h5tools_str_t *buffer, hid_t type, int ind) +{ + H5T_class_t data_class = H5Tget_class(type); + + /* Bad data type */ + if (type<0) { + h5tools_str_append(buffer,"<ERROR>"); + return; + } + + /* Shared? If so then print the type's OID */ + if(H5Tcommitted(type)) { + H5O_info_t oi; + + if(H5Oget_info(type, &oi) >= 0) + h5tools_str_append(buffer,"shared-%lu:"H5_PRINTF_HADDR_FMT" ", + oi.fileno, oi.addr); + else + h5tools_str_append(buffer,"shared "); + } /* end if */ + + /* Print the type */ + if(print_native_type(buffer, type, ind) || + print_ieee_type(buffer, type, ind) || + print_cmpd_type(buffer, type, ind) || + print_enum_type(buffer, type, ind) || + print_string_type(buffer, type, ind) || + print_reference_type(buffer, type, ind) || + print_vlen_type(buffer, type, ind) || + print_array_type(buffer, type, ind) || + print_opaque_type(buffer, type, ind) || + print_bitfield_type(buffer, type, ind)) + return; + + /* Unknown type */ + h5tools_str_append(buffer,"%lu-byte class-%u unknown", + (unsigned long)H5Tget_size(type), (unsigned)data_class); +} + + +/*------------------------------------------------------------------------- + * Function: dump_dataset_values + * + * Purpose: Prints all values of a dataset. + * + * Return: void + * + * Programmer: Robb Matzke + * Tuesday, July 21, 1998 + * + * Modifications: + * Robb Matzke, 1999-09-27 + * Understands the simple_output_g switch which causes data to + * be displayed in a more machine-readable format. + *------------------------------------------------------------------------- + */ +static void +dump_dataset_values(hid_t dset) +{ + char string_prefix[64]; + static char fmt_double[16]; + static char fmt_float[16]; + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t outputformat; + h5tool_format_t *info = &ls_dataformat; + + hid_t f_type = H5Dget_type(dset); + size_t size = H5Tget_size(f_type); + + HDmemset(&ctx, 0, sizeof(ctx)); + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + outputformat = *info; + outputformat.line_1st = NULL; + if (simple_output_g) { + outputformat.idx_fmt = ""; + outputformat.line_per_line = 1; + outputformat.line_multi_new = 0; + outputformat.line_pre = " "; + outputformat.line_cont = " "; + + outputformat.arr_pre = ""; + outputformat.arr_suf = ""; + outputformat.arr_sep = " "; + + if (!label_g) { + outputformat.cmpd_pre = ""; + outputformat.cmpd_suf = ""; + } + outputformat.cmpd_sep = " "; + + if (label_g) outputformat.cmpd_name = "%s="; + + outputformat.elmt_suf1 = " "; + outputformat.str_locale = ESCAPE_HTML; + + } + else { + if (no_line_wrap_g) { + outputformat.line_per_line = 1; + } + else { + outputformat.line_ncols = (unsigned)width_g; + } + if (label_g) outputformat.cmpd_name = "%s="; + outputformat.line_pre = " %s "; + outputformat.line_cont = " %s "; + outputformat.str_repeat = 8; + + outputformat.arr_pre = NULL; + outputformat.arr_suf = NULL; + outputformat.arr_sep = NULL; + + outputformat.cmpd_pre = NULL; + outputformat.cmpd_suf = NULL; + outputformat.cmpd_sep = NULL; + + outputformat.vlen_sep = NULL; + outputformat.vlen_pre = NULL; + outputformat.vlen_suf = NULL; + outputformat.vlen_end = NULL; + } + outputformat.arr_linebreak = 0; + /* Floating point types should display full precision */ + HDsnprintf(fmt_float, sizeof(fmt_float), "%%1.%dg", FLT_DIG); + outputformat.fmt_float = fmt_float; + HDsnprintf(fmt_double, sizeof(fmt_double), "%%1.%dg", DBL_DIG); + outputformat.fmt_double = fmt_double; + + if (hexdump_g) { + /* Print all data in hexadecimal format if the `-x' or `--hexdump' + * command line switch was given. */ + outputformat.raw = TRUE; + } + else if (string_g && 1==size && H5T_INTEGER==H5Tget_class(f_type)) { + /* Print 1-byte integer data as an ASCI character string instead of + * integers if the `-s' or `--string' command-line option was given. */ + outputformat.ascii = TRUE; + outputformat.elmt_suf1 = ""; + outputformat.elmt_suf2 = ""; + HDsnprintf(string_prefix, sizeof(string_prefix), "%s\"", outputformat.line_pre); + outputformat.line_pre = string_prefix; + outputformat.line_suf = "\""; + } + info = &outputformat; + + ctx.indent_level = 2; + ctx.cur_column = (size_t)curr_pos; + /* Print all the values. */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, " Data:\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + ctx.need_prefix = TRUE; + ctx.cur_column = (size_t)curr_pos; + if (h5tools_dump_dset(rawoutstream, info, &ctx, dset, NULL) < 0) { + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, " Unable to print data."); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + } + + H5Tclose(f_type); + + h5tools_str_close(&buffer); + + PRINTVALSTREAM(rawoutstream, "\n"); +} + + +/*------------------------------------------------------------------------- + * Function: list_attr + * + * Purpose: Prints information about attributes. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * Friday, June 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +list_attr(hid_t obj, const char *attr_name, const H5A_info_t H5_ATTR_UNUSED *ainfo, + void H5_ATTR_UNUSED *op_data) +{ + hid_t attr = -1; + hid_t space = -1; + hid_t type = -1; + hid_t p_type = -1; + hsize_t size[H5S_MAX_RANK]; + hsize_t nelmts = 1; + hsize_t temp_need; + size_t need; + int ndims; + int i; + void *buf; + H5S_class_t space_type; + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *info = &ls_dataformat; + h5tool_format_t outputformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, " Attribute: "); + + print_string(&buffer, attr_name, TRUE); + + if((attr = H5Aopen(obj, attr_name, H5P_DEFAULT))) { + space = H5Aget_space(attr); + type = H5Aget_type(attr); + + /* Data space */ + ndims = H5Sget_simple_extent_dims(space, size, NULL); + space_type = H5Sget_simple_extent_type(space); + switch(space_type) { + case H5S_SCALAR: + /* scalar dataspace */ + h5tools_str_append(&buffer, " scalar\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5S_SIMPLE: + /* simple dataspace */ + h5tools_str_append(&buffer, " {"); + for (i=0; i<ndims; i++) { + h5tools_str_append(&buffer, "%s" HSIZE_T_FORMAT, i?", ":"", size[i]); + nelmts *= size[i]; + } + h5tools_str_append(&buffer, "}\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5S_NULL: + /* null dataspace */ + h5tools_str_append(&buffer, " null\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + break; + + case H5S_NO_CLASS: + default: + /* Unknown dataspace type */ + h5tools_str_append(&buffer, " unknown\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + break; + } /* end switch */ + + /* Data type */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, " Type: "); + print_type(&buffer, type, 15); + h5tools_str_append(&buffer, "\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + + /* Data */ + outputformat = *info; + + if(nelmts < 5) { + outputformat.idx_fmt = ""; + outputformat.line_1st = " Data: "; + outputformat.line_pre = " "; + outputformat.line_cont = " "; + outputformat.str_repeat = 8; + + } + else { + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, " Data:\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + outputformat.line_1st = NULL; + outputformat.line_pre = " %s "; + outputformat.line_cont = " %s "; + outputformat.str_repeat = 8; + } + + outputformat.line_ncols = (unsigned)width_g; + if(label_g) + outputformat.cmpd_name = "%s="; + if(string_g && 1==H5Tget_size(type) && + H5T_INTEGER==H5Tget_class(type)) { + outputformat.ascii = TRUE; + outputformat.elmt_suf1 = ""; + outputformat.elmt_suf2 = ""; + outputformat.line_pre = " %s \""; + outputformat.line_suf = "\""; + } /* end if */ + + + outputformat.arr_pre = NULL; + outputformat.arr_suf = NULL; + outputformat.arr_sep = NULL; + + outputformat.cmpd_pre = NULL; + outputformat.cmpd_suf = NULL; + outputformat.cmpd_sep = NULL; + + outputformat.vlen_sep = NULL; + outputformat.vlen_pre = NULL; + outputformat.vlen_suf = NULL; + outputformat.vlen_end = NULL; + + info = &outputformat; + + if(hexdump_g) + p_type = H5Tcopy(type); + else + p_type = h5tools_get_native_type(type); + + if(p_type >= 0) { + /* VL data special information */ + unsigned int vl_data = 0; /* contains VL datatypes */ + + /* Check if we have VL data in the dataset's datatype */ + if (h5tools_detect_vlen(p_type) == TRUE) + vl_data = TRUE; + + temp_need= nelmts * MAX(H5Tget_size(type), H5Tget_size(p_type)); + HDassert(temp_need == (hsize_t)((size_t)temp_need)); + need = (size_t)temp_need; + buf = HDmalloc(need); + HDassert(buf); + if(H5Aread(attr, p_type, buf) >= 0) { + ctx.need_prefix = TRUE; + ctx.indent_level = 2; + ctx.cur_column = (size_t)curr_pos; + h5tools_dump_mem(rawoutstream, info, &ctx, attr, p_type, space, buf); + } + + /* Reclaim any VL memory, if necessary */ + if (vl_data) + H5Dvlen_reclaim(p_type, space, H5P_DEFAULT, buf); + + HDfree(buf); + H5Tclose(p_type); + } /* end if */ + + H5Sclose(space); + H5Tclose(type); + H5Aclose(attr); + } + h5tools_str_close(&buffer); + + PRINTVALSTREAM(rawoutstream, "\n"); + + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: dataset_list1 + * + * Purpose: List information about a dataset which should appear on the + * same line as the dataset name. This information will precede + * information which is applicable to all objects which will be + * printed by the caller. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * Thursday, August 27, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +dataset_list1(hid_t dset) +{ + 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 */ + int i; + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *info = &ls_dataformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + h5tools_str_reset(&buffer); + + /* Information that goes on the same row as the name. The name has + * already been printed. */ + space = H5Dget_space(dset); + space_type = H5Sget_simple_extent_type(space); + ndims = H5Sget_simple_extent_dims(space, cur_size, max_size); + h5tools_str_append(&buffer, " {"); + for (i=0; i<ndims; i++) { + h5tools_str_append(&buffer, "%s"HSIZE_T_FORMAT, i?", ":"", cur_size[i]); + if (max_size[i]==H5S_UNLIMITED) { + h5tools_str_append(&buffer, "/%s", "Inf"); + } + else if (max_size[i]!=cur_size[i] || verbose_g>0) { + h5tools_str_append(&buffer, "/"HSIZE_T_FORMAT, max_size[i]); + } + } + if (space_type==H5S_SCALAR) h5tools_str_append(&buffer, "SCALAR"); + else if (space_type==H5S_NULL) h5tools_str_append(&buffer, "NULL"); + h5tools_str_append(&buffer, "}"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + H5Sclose (space); + + h5tools_str_close(&buffer); + + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: dataset_list2 + * + * Purpose: List information about a dataset which should appear after + * information which is general to all objects. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * Thursday, August 27, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +dataset_list2(hid_t dset, const char H5_ATTR_UNUSED *name) +{ + hid_t dcpl; /* dataset creation property list */ + hid_t type; /* data type of dataset */ + hid_t space; /* data space of dataset */ + int nf; /* number of filters */ + unsigned filt_flags; /* filter flags */ + H5Z_filter_t filt_id; /* filter identification number */ + unsigned cd_values[20]; /* filter client data values */ + size_t cd_nelmts; /* filter client number of values */ + size_t cd_num; /* filter client data counter */ + char f_name[256]; /* filter/file name */ + char s[64]; /* temporary string buffer */ + 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 */ + int ndims; /* dimensionality */ + int n, max_len; /* max extern file name length */ + double utilization; /* percent utilization of storage */ + H5T_class_t tclass; /* datatype class identifier */ + int i; + H5D_layout_t stl; + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *info = &ls_dataformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + h5tools_str_reset(&buffer); + + if(verbose_g > 0) { + dcpl = H5Dget_create_plist(dset); + space = H5Dget_space(dset); + type = H5Dget_type(dset); + + stl = H5Pget_layout(dcpl); + switch (stl) { + case H5D_CHUNKED: + { + hsize_t chsize[64]; /* chunk size in elements */ + + ndims = H5Pget_chunk(dcpl, (int)NELMTS(chsize), chsize/*out*/); + h5tools_str_append(&buffer, " %-10s {", "Chunks:"); + total = H5Tget_size(type); + for (i=0; i<ndims; i++) { + h5tools_str_append(&buffer, "%s"HSIZE_T_FORMAT, i?", ":"", chsize[i]); + total *= chsize[i]; + } + h5tools_str_append(&buffer, "} "HSIZE_T_FORMAT" bytes\n", total); + } + break; + case H5D_COMPACT: + break; + case H5D_CONTIGUOUS: + /* Print information about external storage */ + if((nf = H5Pget_external_count(dcpl)) > 0) { + for(i = 0, max_len = 0; i < nf; i++) { + if(H5Pget_external(dcpl, (unsigned)i, sizeof(f_name), f_name, NULL, NULL) < 0) + continue; + n = print_string(NULL, f_name, TRUE); + max_len = MAX(max_len, n); + } /* end for */ + h5tools_str_append(&buffer, " %-10s %d external file%s\n", + "Extern:", nf, 1==nf?"":"s"); + h5tools_str_append(&buffer, " %4s %10s %10s %10s %s\n", + "ID", "DSet-Addr", "File-Addr", "Bytes", "File"); + h5tools_str_append(&buffer, " %4s %10s %10s %10s ", + "----", "----------", "----------", "----------"); + for (i=0; i<max_len; i++) h5tools_str_append(&buffer, "-"); + h5tools_str_append(&buffer, "\n"); + for (i=0, total=0; i<nf; i++) { + if (H5Pget_external(dcpl, (unsigned)i, sizeof(f_name), f_name, &f_offset, &f_size)<0) { + h5tools_str_append(&buffer, + " #%03d %10"H5_PRINTF_LL_WIDTH"u %10s %10s ***ERROR*** %s\n", + i, total, "", "", + i+1<nf?"Following addresses are incorrect":""); + } + else if (H5S_UNLIMITED==f_size) { + h5tools_str_append(&buffer, " #%03d %10"H5_PRINTF_LL_WIDTH"u %10"H5_PRINTF_LL_WIDTH"u %10s ", + i, total, (hsize_t)f_offset, "INF"); + print_string(&buffer, f_name, TRUE); + } + else { + h5tools_str_append(&buffer, " #%03d %10"H5_PRINTF_LL_WIDTH"u %10"H5_PRINTF_LL_WIDTH"u %10"H5_PRINTF_LL_WIDTH"u ", + i, total, (hsize_t)f_offset, f_size); + print_string(&buffer, f_name, TRUE); + } + h5tools_str_append(&buffer, "\n"); + total += f_size; + } + h5tools_str_append(&buffer, " %4s %10s %10s %10s ", + "----", "----------", "----------", "----------"); + for (i=0; i<max_len; i++) + h5tools_str_append(&buffer, "-"); + h5tools_str_append(&buffer, "\n"); + } /* end if */ + break; + + case H5D_VIRTUAL: + { + char dset_name[256]; /* Dataset name */ + size_t vmaps; + + H5Pget_virtual_count(dcpl, &vmaps); + + if (vmaps) { + size_t next; + + h5tools_str_append(&buffer, " %-10s {%ld} Source {\n", "Maps:", vmaps); + for (next = 0; next < (unsigned) vmaps; next++) { + H5Pget_virtual_filename(dcpl, next, f_name, sizeof(f_name)); + H5Pget_virtual_dsetname(dcpl, next, dset_name, sizeof(dset_name)); + h5tools_str_append(&buffer, " %-10s ", " "); + print_string(&buffer, f_name, TRUE); + h5tools_str_append(&buffer, " "); + print_string(&buffer, dset_name, TRUE); + h5tools_str_append(&buffer, "\n"); + } + h5tools_str_append(&buffer, " %-10s}\n", " "); + } + } + break; + + case H5D_LAYOUT_ERROR: + case H5D_NLAYOUTS: + default: + HDassert(0); + break; + } + /* Print total raw storage size */ + total = (hsize_t)H5Sget_simple_extent_npoints(space) * H5Tget_size(type); + used = H5Dget_storage_size(dset); + tclass = H5Tget_class(type); + h5tools_str_append(&buffer, " %-10s ", "Storage:"); + switch (tclass) + { + + case H5T_VLEN: + h5tools_str_append(&buffer, "information not available"); + break; + + case H5T_REFERENCE: + if ( H5Tequal(type, H5T_STD_REF_DSETREG)) + { + h5tools_str_append(&buffer, "information not available"); + } + break; + + case H5T_NO_CLASS: + case H5T_INTEGER: + case H5T_FLOAT: + case H5T_TIME: + case H5T_STRING: + case H5T_BITFIELD: + case H5T_OPAQUE: + case H5T_COMPOUND: + case H5T_ENUM: + case H5T_ARRAY: + case H5T_NCLASSES: + default: + h5tools_str_append(&buffer, HSIZE_T_FORMAT" logical byte%s, "HSIZE_T_FORMAT" allocated byte%s", + total, 1==total?"":"s", + used, 1==used?"":"s"); + if (used>0) + { + utilization = ((double)total * (double)100.0f) / (double)used; + h5tools_str_append(&buffer, ", %1.2f%% utilization", utilization); + } + } + + h5tools_str_append(&buffer, "\n"); + + /* Print information about raw data filters */ + if((nf = H5Pget_nfilters(dcpl)) > 0) { + for(i = 0; i < nf; i++) { + cd_nelmts = NELMTS(cd_values); + filt_id = H5Pget_filter2(dcpl, (unsigned)i, &filt_flags, &cd_nelmts, + cd_values, sizeof(f_name), f_name, NULL); + f_name[sizeof(f_name) - 1] = '\0'; + HDsnprintf(s, sizeof(s), "Filter-%d:", i); + h5tools_str_append(&buffer, " %-10s %s-%u %s {", s, + (f_name[0] ? f_name : "method"), + (unsigned)filt_id, + ((filt_flags & H5Z_FLAG_OPTIONAL) ? "OPT" : "")); + for(cd_num = 0; cd_num < cd_nelmts; cd_num++) + h5tools_str_append(&buffer, "%s%u", (cd_num ? ", " : ""), cd_values[cd_num]); + h5tools_str_append(&buffer, "}\n"); + } /* end for */ + } /* end if */ + + /* Print data type */ + h5tools_str_append(&buffer, " %-10s ", "Type:"); + print_type(&buffer, type, 15); + h5tools_str_append(&buffer, "\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + + /* Print address information */ + if(address_g) + H5Ddebug(dset); + + /* Close stuff */ + H5Tclose(type); + H5Sclose(space); + H5Pclose(dcpl); + } /* end if */ + + h5tools_str_close(&buffer); + + if(data_g) + dump_dataset_values(dset); + + return 0; +} /* end dataset_list2() */ + + +/*------------------------------------------------------------------------- + * Function: datatype_list2 + * + * Purpose: List information about a datatype which should appear after + * information which is general to all objects. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * Thursday, November 5, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +datatype_list2(hid_t type, const char H5_ATTR_UNUSED *name) +{ + if (verbose_g>0) { + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *info = &ls_dataformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + h5tools_str_reset(&buffer); + + h5tools_str_append(&buffer, " %-10s ", "Type:"); + print_type(&buffer, type, 15); + h5tools_str_append(&buffer, "\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + + h5tools_str_close(&buffer); + } + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: list_obj + * + * Purpose: Prints information about an object + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Quincey Koziol + * Tuesday, November 6, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +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; + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *info = &ls_dataformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + h5tools_str_reset(&buffer); + + /* Print the link's name, either full name or base name */ + if(!iter->symlink_target) + print_obj_name(&buffer, iter, name, ""); + + /* Check object information */ + if(oinfo->type < 0 || oinfo->type >= H5O_TYPE_NTYPES) { + h5tools_str_append(&buffer, "Unknown type(%d)", (int)oinfo->type); + obj_type = H5O_TYPE_UNKNOWN; + } + if(iter->symlink_target) + h5tools_str_append(&buffer, "{"); + if(obj_type >= 0 && dispatch_g[obj_type].name) + h5tools_str_append(&buffer, "%s", dispatch_g[obj_type].name); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + + /* Check if we've seen this object before */ + if(first_seen) { + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, ", same as "); + print_string(&buffer, first_seen, TRUE); + if(!iter->symlink_target) { + h5tools_str_append(&buffer, "\n"); + } + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + } /* 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(obj_type >= 0 && (obj = H5Oopen(iter->fid, name, H5P_DEFAULT)) < 0) { + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, " *ERROR*\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + goto done; + } /* end if */ + + /* List the first line of information for the object. */ + if(obj_type >= 0 && dispatch_g[obj_type].list1) + (dispatch_g[obj_type].list1)(obj); + if(!iter->symlink_target || (verbose_g > 0)) { + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + } + + /* Show detailed information about the object, beginning with information + * which is common to all objects. */ + if(verbose_g > 0) { + size_t buf_size = 0; + char* comment = NULL; + ssize_t cmt_bufsize = -1; + + /* Display attributes */ + if(obj_type >= 0) + H5Aiterate2(obj, H5_INDEX_NAME, H5_ITER_INC, NULL, list_attr, NULL); + + /* Object location & reference count */ + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, " %-10s %lu:"H5_PRINTF_HADDR_FMT"\n", "Location:", oinfo->fileno, oinfo->addr); + h5tools_str_append(&buffer, " %-10s %u\n", "Links:", (unsigned)oinfo->rc); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + + /* Modification time */ + if(oinfo->mtime > 0) { + char buf[256]; + struct tm *tm; + + if(simple_output_g) + tm = HDgmtime(&(oinfo->mtime)); + else + tm = HDlocaltime(&(oinfo->mtime)); + if(tm) { + HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm); + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, " %-10s %s\n", "Modified:", buf); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + } /* end if */ + } /* end if */ + + /* Object comment */ + cmt_bufsize = H5Oget_comment(obj, comment, buf_size); + + /* if the actual length of the comment is longer than cmt_bufsize, then call + * H5Oget_comment again with the correct value. + * If the call to H5Oget_comment returned an error, skip this block */ + if (cmt_bufsize > 0) { + comment = (char *)HDmalloc((size_t)cmt_bufsize + 1); /* new_size including null terminator */ + if(comment) { + cmt_bufsize = H5Oget_comment(obj, comment, (size_t)cmt_bufsize); + if(cmt_bufsize > 0) { + comment[cmt_bufsize] = 0; + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, " %-10s \"", "Comment:"); + print_string(&buffer, comment, FALSE); + h5tools_str_append(&buffer, "\"\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + } /* end if */ + HDfree(comment); + } + } + } /* end if */ + + /* Detailed list for object */ + if(obj_type >= 0 && dispatch_g[obj_type].list2) + (dispatch_g[obj_type].list2)(obj, name); + + /* Close the object. */ + if(obj_type >= 0) + H5Oclose(obj); + } /* end else */ + +done: + if(iter->symlink_target) { + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "}\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + iter->symlink_target = FALSE; + } + h5tools_str_close(&buffer); + + return 0; +} /* end list_obj() */ + + + +/*------------------------------------------------------------------------- + * Function: list_lnk + * + * Purpose: Prints information about a link + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Quincey Koziol + * Thursday, November 8, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +list_lnk(const char *name, const H5L_info_t *linfo, void *_iter) +{ + char *buf=NULL; + iter_t *iter = (iter_t*)_iter; + int ret; + hsize_t curr_pos = 0; /* total data element position */ + h5tool_link_info_t lnk_info; + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *info = &ls_dataformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + h5tools_str_reset(&buffer); + + /* init linkinfo struct */ + HDmemset(&lnk_info, 0, sizeof(h5tool_link_info_t)); + + /* if verbose, make H5tools_get_symlink_info() display more */ + if (verbose_g) + lnk_info.opt.msg_mode=1; + + /* Print the link's name, either full name or base name */ + print_obj_name(&buffer, iter, name, ""); + + switch(linfo->type) { + case H5L_TYPE_SOFT: + ret = H5tools_get_symlink_info(iter->fid, name, &lnk_info, follow_symlink_g); + /* lnk_info.trg_path is malloced in H5tools_get_symlink_info() + * so it will be freed via buf later */ + buf = (char*)lnk_info.trg_path; + /* error */ + if (ret < 0) + goto done; + /* no dangling link option given and detect dangling link */ + else if (no_dangling_link_g && ret == 0) + iter->symlink_list->dangle_link = TRUE; + + h5tools_str_append(&buffer, "Soft Link {"); + h5tools_str_append(&buffer, buf); + h5tools_str_append(&buffer, "}"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + if(follow_symlink_g) + { + hbool_t orig_grp_literal = grp_literal_g; + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, " "); + + /* Check if we have already seen this softlink */ + if(symlink_is_visited(iter->symlink_list, linfo->type, NULL, buf)) + { + h5tools_str_append(&buffer, "{Already Visited}\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + goto done; + } + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + + /* Add this link to the list of seen softlinks */ + if(symlink_visit_add(iter->symlink_list, linfo->type, NULL, buf) < 0) + goto done; + + /* Adjust user data to specify that we are operating on the + * target of an soft link */ + iter->symlink_target = TRUE; + + /* Prevent recursive listing of soft link target if + * recursive_g is off */ + if(!recursive_g) + grp_literal_g = TRUE; + /* Recurse through the soft link */ + if(visit_obj(iter->fid, name, iter) < 0) + { + grp_literal_g = orig_grp_literal; + goto done; + } + + grp_literal_g = orig_grp_literal; + } + else { + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, "\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + } + + break; + + case H5L_TYPE_EXTERNAL: + { + const char *filename; + const char *path; + hbool_t follow_link = follow_symlink_g || follow_elink_g; + + ret = H5tools_get_symlink_info(iter->fid, name, &lnk_info, follow_link); + /* lnk_info.trg_path is malloced in H5tools_get_symlink_info() + * so it will be freed via buf later */ + buf = (char*)lnk_info.trg_path; + /* error */ + if (ret < 0) + goto done; + /* no dangling link option given and detect dangling link */ + else if (no_dangling_link_g && ret == 0) + iter->symlink_list->dangle_link = TRUE; + + if(H5Lunpack_elink_val(buf, linfo->u.val_size, NULL, &filename, &path) < 0) + goto done; + + h5tools_str_append(&buffer, "External Link {"); + h5tools_str_append(&buffer, filename); + h5tools_str_append(&buffer, "/"); + if(*path != '/') + h5tools_str_append(&buffer, "/"); + h5tools_str_append(&buffer, path); + h5tools_str_append(&buffer, "}"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + + /* Recurse through the external link */ + /* keep the follow_elink_g for backward compatibility with -E */ + if(follow_link) + { + hbool_t orig_grp_literal = grp_literal_g; + h5tools_str_reset(&buffer); + h5tools_str_append(&buffer, " "); + + /* Check if we have already seen this elink */ + if(symlink_is_visited(iter->symlink_list, linfo->type, filename, path)) + { + h5tools_str_append(&buffer, "{Already Visited}\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + goto done; + } + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + + /* Add this link to the list of seen elinks */ + if(symlink_visit_add(iter->symlink_list, linfo->type, filename, path) < 0) + { + goto done; + } + + /* Adjust user data to specify that we are operating on the + * target of an external link */ + iter->symlink_target = TRUE; + + /* Prevent recursive listing of external link target if + * recursive_g is off */ + if(!recursive_g) + grp_literal_g = TRUE; + + /* Recurse through the external link */ + if(visit_obj(iter->fid, name, iter) < 0) { + grp_literal_g = orig_grp_literal; + goto done; + } + + grp_literal_g = orig_grp_literal; + } + else + PRINTVALSTREAM(rawoutstream, "\n"); + } + break; + + case H5L_TYPE_ERROR: + case H5L_TYPE_HARD: + case H5L_TYPE_MAX: + default: + h5tools_str_append(&buffer, "UD Link {cannot follow UD links}\n"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + break; + } /* end switch */ + +done: + h5tools_str_close(&buffer); + + if (buf) + HDfree(buf); + return 0; +} /* end list_lnk() */ + + +/*------------------------------------------------------------------------- + * Function: visit_obj + * + * Purpose: Begins iteration on an object + * + * Return: + * Success: 0 + * Failure: -1 + * + * Programmer: Neil Fortner + * Wednesday, August 21, 2008 + * Mostly copied from main() + * + *------------------------------------------------------------------------- + */ +static herr_t +visit_obj(hid_t file, const char *oname, iter_t *iter) +{ + int retval = 0; + H5O_info_t oi; /* Information for object */ + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *info = &ls_dataformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + h5tools_str_reset(&buffer); + + /* Retrieve info for object to list */ + if(H5Oget_info_by_name(file, oname, &oi, H5P_DEFAULT) < 0) { + if(iter->symlink_target) { + h5tools_str_append(&buffer, "{**NOT FOUND**}\n"); + iter->symlink_target = FALSE; + } + else + print_obj_name(&buffer, iter, oname, "**NOT FOUND**"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + retval = -1; + goto done; + } /* end if */ + + /* Check for group iteration */ + if(H5O_TYPE_GROUP == oi.type && !grp_literal_g) { + /* Get ID for group */ + if(!iter->symlink_target && (iter->gid = H5Gopen2(file, oname, H5P_DEFAULT)) < 0) { + h5tools_str_append(&buffer, "%s: unable to open '%s' as group\n", iter->fname, oname); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + goto done; /* Previously "continue", when this code was in main(). + * We don't "continue" here in order to close the file + * and free the file name properly. */ + } /* end if */ + + /* Delay specifying the name start point so the original object name is + * displayed if it is a link or non-group object */ + iter->name_start = iter->base_len; + + /* Specified name is a group. List the complete contents of the group. */ + h5trav_visit(file, oname, (hbool_t) (display_root_g || iter->symlink_target), recursive_g, list_obj, list_lnk, iter); + + /* Close group */ + if(!iter->symlink_target) + H5Gclose(iter->gid); + } /* end if */ + else { + /* Use file ID for root group ID */ + iter->gid = file; + + /* Specified name is a non-group object -- list that object */ + list_obj(oname, &oi, NULL, iter); + } /* end else */ + +done: + h5tools_str_close(&buffer); + + return retval; +} + + +/*------------------------------------------------------------------------- + * Function: get_width + * + * Purpose: Figure out how wide the screen is. This is highly + * unportable, but the user can always override the width we + * detect by giving a command-line option. These code snippets + * were borrowed from the GNU less(1). + * + * Return: Success: Number of columns. + * + * Failure: Some default number of columms. + * + * Programmer: Robb Matzke + * Friday, November 6, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +get_width(void) +{ + int width = 80; /*the default */ + char *s; + + /* Try to get it from the COLUMNS environment variable first since it's + * value is sometimes wrong. */ + if ((s=HDgetenv("COLUMNS")) && *s && isdigit((int)*s)) + width = (int)HDstrtol(s, NULL, 0); + +#if defined(H5_HAVE_STRUCT_VIDEOCONFIG) && defined(H5_HAVE__GETVIDEOCONFIG) + { + /* Microsoft C */ + struct videoconfig w; + _getvideoconfig(&w); + width = w.numtextcols; + } +#elif defined(H5_HAVE_STRUCT_TEXT_INFO) && defined(H5_HAVE_GETTEXTINFO) + { + /* Borland C or DJGPPC */ + struct text_info w; + gettextinfo(&w); + width = w.screenwidth; + } +#elif defined(H5_HAVE_GETCONSOLESCREENBUFFERINFO) + { + /* Win32 C */ + CONSOLE_SCREEN_BUFFER_INFO scr; + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &scr); + width = scr.srWindow.Right - scr.srWindow.Left + 1; + } +#elif defined(H5_HAVE__SCRSIZE) + { + /* OS/2 */ + int w[2]; + _scrsize(w); + width = w[0]; + } +#elif defined(H5_HAVE_TIOCGWINSZ) && defined(H5_HAVE_IOCTL) + { + /* Unix with ioctl(TIOCGWINSZ) */ + struct winsize w; + if (ioctl(2, (int)TIOCGWINSZ, &w)>=0 && w.ws_col>0) + width = w.ws_col; + } +#elif defined(H5_HAVE_TIOCGETD) && defined(H5_HAVE_IOCTL) + { + /* Unix with ioctl(TIOCGETD) */ + struct uwdata w; + if (ioctl(2, WIOCGETD, &w)>=0 && w.uw_width>0) + width = w.uw_width / w.uw_hs; + } +#endif + + /* Set to at least 1 */ + if (width<1) width = 1; + return width; +} + +/*------------------------------------------------------------------------- + * Function: is_valid_args + * + * Purpose: check if command line arguments are valid + * + * Return: + * Success: TRUE (1) + * Failure: FALSE (0) + * + * Programmer: + * Jonathan Kim (06/15/2010) + * + *-------------------------------------------------------------------------*/ +static hbool_t +is_valid_args(void) +{ + hbool_t ret = TRUE; + + if(recursive_g && grp_literal_g) + { + HDfprintf(rawerrorstream, "Error: 'recursive' option not compatible with 'group info' option!\n\n"); + ret = FALSE; + goto out; + } + + if(no_dangling_link_g && !follow_symlink_g) + { + HDfprintf(rawerrorstream, "Error: --no-dangling-links must be used along with --follow-symlinks option!\n\n"); + ret = FALSE; + goto out; + } + +out: + return ret; +} + + +/*------------------------------------------------------------------------- + * Function: leave + * + * Purpose: Close HDF5 and MPI and call exit() + * + * Return: Does not return + * + * Programmer: Quincey Koziol + * Saturday, January 31, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +leave(int ret) +{ + h5tools_close(); + + HDexit(ret); +} + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: Opens a file and lists the specified group + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Robb Matzke + * Monday, March 23, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +main(int argc, const char *argv[]) +{ + hid_t file = -1; + char *fname = NULL, *oname = NULL, *x; + const char *s = NULL; + char *rest; + int argno; + static char root_name[] = "/"; + char drivername[50]; + const char *preferred_driver = NULL; + int err_exit = 0; + + h5tools_setprogname(PROGRAMNAME); + h5tools_setstatus(EXIT_SUCCESS); + + /* Initialize h5tools lib */ + h5tools_init(); + + /* Build object display table */ + 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(); + + /* Switches come before non-switch arguments */ + for(argno = 1; argno < argc && '-' == argv[argno][0]; argno++) { + if(!HDstrcmp(argv[argno], "--")) { + /* Last switch */ + argno++; + break; + } else if(!HDstrcmp(argv[argno], "--help")) { + usage(); + leave(EXIT_SUCCESS); + } else if(!HDstrcmp(argv[argno], "--address")) { + address_g = TRUE; + } else if(!HDstrcmp(argv[argno], "--data")) { + data_g = TRUE; + } else if(!HDstrcmp(argv[argno], "--enable-error-stack")) { + show_errors_g = TRUE; + /* deprecated --errors */ + } else if(!HDstrcmp(argv[argno], "--errors")) { + show_errors_g = TRUE; + } else if(!HDstrcmp(argv[argno], "--follow-symlinks")) { + follow_symlink_g = TRUE; + } else if(!HDstrcmp(argv[argno], "--no-dangling-links")) { + no_dangling_link_g = TRUE; + } else if(!HDstrcmp(argv[argno], "--external")) { + follow_elink_g = TRUE; + } else if(!HDstrcmp(argv[argno], "--full")) { + fullname_g = TRUE; + } else if(!HDstrcmp(argv[argno], "--group")) { + grp_literal_g = TRUE; + } else if(!HDstrcmp(argv[argno], "--label")) { + label_g = TRUE; + } else if(!HDstrcmp(argv[argno], "--recursive")) { + recursive_g = TRUE; + fullname_g = TRUE; + } else if(!HDstrcmp(argv[argno], "--simple")) { + simple_output_g = TRUE; + } else if(!HDstrcmp(argv[argno], "--string")) { + string_g = TRUE; + } else if(!HDstrncmp(argv[argno], "--vfd=", (size_t)6)) { + preferred_driver = argv[argno]+6; + } else if(!HDstrncmp(argv[argno], "--width=", (size_t)8)) { + width_g = (int)HDstrtol(argv[argno]+8, &rest, 0); + + if(0 == width_g) + no_line_wrap_g = TRUE; + else if(width_g < 0 || *rest) { + usage(); + leave(EXIT_FAILURE); + } + } else if(!HDstrcmp(argv[argno], "--width")) { + if((argno + 1) >= argc) { + usage(); + leave(EXIT_FAILURE); + } else { + s = argv[++argno]; + } + width_g = (int)HDstrtol(s, &rest, 0); + if(width_g <= 0 || *rest) { + usage(); + leave(EXIT_FAILURE); + } + } else if(!HDstrcmp(argv[argno], "--verbose")) { + verbose_g++; + } else if(!HDstrcmp(argv[argno], "--version")) { + print_version(h5tools_getprogname()); + leave(EXIT_SUCCESS); + } else if(!HDstrcmp(argv[argno], "--hexdump")) { + hexdump_g = TRUE; + } else if(!HDstrncmp(argv[argno], "-w", (size_t)2)) { + if(argv[argno][2]) { + s = argv[argno] + 2; + } else if((argno + 1) >= argc) { + usage(); + leave(EXIT_FAILURE); + } else { + s = argv[++argno]; + } + width_g = (int)HDstrtol(s, &rest, 0); + + if(0 == width_g) + no_line_wrap_g = TRUE; + else if(width_g < 0 || *rest) { + usage(); + leave(EXIT_FAILURE); + } + } else if('-'!=argv[argno][1]) { + /* Single-letter switches */ + for(s = argv[argno] + 1; *s; s++) { + switch(*s) { + case '?': + case 'h': /* --help */ + usage(); + leave(EXIT_SUCCESS); + + case 'a': /* --address */ + address_g = TRUE; + break; + + case 'd': /* --data */ + data_g = TRUE; + break; + + /* deprecated -e */ + case 'e': /* --errors */ + show_errors_g = TRUE; + break; + + case 'E': /* --external */ + follow_elink_g = TRUE; + break; + + case 'f': /* --full */ + fullname_g = TRUE; + break; + + case 'g': /* --group */ + grp_literal_g = TRUE; + break; + + case 'l': /* --label */ + label_g = TRUE; + break; + + case 'r': /* --recursive */ + recursive_g = TRUE; + fullname_g = TRUE; + break; + + case 'S': /* --simple */ + simple_output_g = TRUE; + break; + + case 's': /* --string */ + string_g = TRUE; + break; + + case 'v': /* --verbose */ + verbose_g++; + break; + + case 'V': /* --version */ + print_version(h5tools_getprogname()); + leave(EXIT_SUCCESS); + + case 'x': /* --hexdump */ + hexdump_g = TRUE; + break; + + default: + usage(); + leave(EXIT_FAILURE); + } /* end switch */ + } /* end for */ + } else { + usage(); + leave(EXIT_FAILURE); + } + } /* end for */ + + /* If no arguments remain then print a usage message (instead of doing + * absolutely nothing ;-) */ + if(argno >= argc) { + usage(); + leave(EXIT_FAILURE); + } /* end if */ + + /* Check for conflicting arguments */ + if (!is_valid_args()) + { + usage(); + leave(EXIT_FAILURE); + } + + /* Turn off HDF5's automatic error printing unless you're debugging h5ls */ + if(!show_errors_g) + H5Eset_auto2(H5E_DEFAULT, NULL, NULL); + + + /* Each remaining argument is an hdf5 file followed by an optional slash + * and object name. + * + * Example: ../dir1/foo/bar/baz + * \_________/\______/ + * file obj + * + * The dichotomy is determined by calling H5Fopen() repeatedly until it + * succeeds. The first call uses the entire name and each subsequent call + * chops off the last component. If we reach the beginning of the name + * then there must have been something wrong with the file (perhaps it + * doesn't exist). */ + show_file_name_g = (argc-argno > 1); /*show file names if more than one*/ + while(argno < argc) { + H5L_info_t li; + iter_t iter; + symlink_trav_t symlink_list; + size_t u; + + fname = HDstrdup(argv[argno++]); + oname = NULL; + file = -1; + + while(fname && *fname) { + file = h5tools_fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT, preferred_driver, drivername, sizeof drivername); + + if(file >= 0) { + if(verbose_g) + PRINTSTREAM(rawoutstream, "Opened \"%s\" with %s driver.\n", fname, drivername); + break; /*success*/ + } /* end if */ + + /* Shorten the file name; lengthen the object name */ + x = oname; + oname = HDstrrchr(fname, '/'); + if(x) + *x = '/'; + if(!oname) + break; + *oname = '\0'; + } /* end while */ + + if(file < 0) { + HDfprintf(rawerrorstream, "%s: unable to open file\n", argv[argno-1]); + HDfree(fname); + err_exit = 1; + continue; + } /* end if */ + if(oname) { + /* Always use absolute paths to avoid confusion, keep track of where + * to begin path name output */ + *oname = '/'; + iter.base_len = HDstrlen(oname); + iter.base_len -= oname[iter.base_len-1] == '/'; + x = oname; + if(NULL == (oname = HDstrdup(oname))) { + HDfprintf(rawerrorstream, "memory allocation failed\n"); + leave(EXIT_FAILURE); + } + *x = '\0'; + /* Delay specifying the name start point so the original object name + * is displayed if it is a link or non-group object */ + iter.name_start = 1; + } + if(!oname || !*oname) { + oname = root_name; + if(recursive_g) + display_root_g = TRUE; + iter.base_len = 0; + iter.name_start = 0; + /* Use x to remember if we have allocated space in oname */ + x = NULL; + } /* end if */ + + /* Remember the file information for later */ + iter.fname = fname; + iter.fid = file; + iter.gid = -1; + iter.symlink_target = FALSE; + iter.symlink_list = &symlink_list; + iter.symlink_list->dangle_link = FALSE; + + /* Initialize list of visited symbolic links */ + symlink_list.nused = symlink_list.nalloc = 0; + symlink_list.objs = NULL; + + /* 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) { + hsize_t curr_pos = 0; /* total data element position */ + h5tools_str_t buffer; /* string into which to render */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t *info = &ls_dataformat; + + HDmemset(&ctx, 0, sizeof(ctx)); + HDmemset(&buffer, 0, sizeof(h5tools_str_t)); + + h5tools_str_reset(&buffer); + print_obj_name(&buffer, &iter, oname, "**NOT FOUND**"); + h5tools_render_element(rawoutstream, info, &ctx, &buffer, &curr_pos, (size_t)info->line_ncols, (hsize_t)0, (hsize_t)0); + leave(EXIT_FAILURE); + } /* end if */ + } /* end if */ + else + li.type = H5L_TYPE_HARD; + + /* Open the object and display it's information */ + if(li.type == H5L_TYPE_HARD) { + if(visit_obj(file, oname, &iter) < 0) + leave(EXIT_FAILURE); + } /* end if(li.type == H5L_TYPE_HARD) */ + else { + /* Specified name is not for object -- list that link */ + /* Use file ID for root group ID */ + iter.gid = file; + list_lnk(oname, &li, &iter); + } + H5Fclose(file); + HDfree(fname); + if(x) + HDfree(oname); + + for(u=0; u < symlink_list.nused; u++) + { + if (symlink_list.objs[u].type == H5L_TYPE_EXTERNAL) + HDfree(symlink_list.objs[u].file); + + HDfree(symlink_list.objs[u].path); + } + HDfree(symlink_list.objs); + + /* if no-dangling-links option specified and dangling link found */ + if (no_dangling_link_g && iter.symlink_list->dangle_link) + err_exit = 1; + } /* end while */ + + if (err_exit) + leave(EXIT_FAILURE); + else + leave(EXIT_SUCCESS); +} /* end main() */ + diff --git a/tools/src/h5repack/CMakeLists.txt b/tools/src/h5repack/CMakeLists.txt new file mode 100644 index 0000000..cb7f5f6 --- /dev/null +++ b/tools/src/h5repack/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required (VERSION 3.1.0) +PROJECT (HDF5_TOOLS_SRC_H5REPACK) + +#----------------------------------------------------------------------------- +# Setup include Directories +#----------------------------------------------------------------------------- +INCLUDE_DIRECTORIES (${HDF5_TOOLS_DIR}/lib) +INCLUDE_DIRECTORIES (${HDF5_TEST_SRC_DIR}) + +# -------------------------------------------------------------------- +# Add h5Repack executables +# -------------------------------------------------------------------- +set (REPACK_COMMON_SOURCES + ${HDF5_TOOLS_SRC_H5REPACK_SOURCE_DIR}/h5repack_copy.c + ${HDF5_TOOLS_SRC_H5REPACK_SOURCE_DIR}/h5repack_filters.c + ${HDF5_TOOLS_SRC_H5REPACK_SOURCE_DIR}/h5repack_opttable.c + ${HDF5_TOOLS_SRC_H5REPACK_SOURCE_DIR}/h5repack_parse.c + ${HDF5_TOOLS_SRC_H5REPACK_SOURCE_DIR}/h5repack_refs.c + ${HDF5_TOOLS_SRC_H5REPACK_SOURCE_DIR}/h5repack_verify.c + ${HDF5_TOOLS_SRC_H5REPACK_SOURCE_DIR}/h5repack.c +) + +add_executable (h5repack ${REPACK_COMMON_SOURCES} ${HDF5_TOOLS_SRC_H5REPACK_SOURCE_DIR}/h5repack_main.c) +TARGET_NAMING (h5repack STATIC) +TARGET_C_PROPERTIES (h5repack STATIC " " " ") +target_link_libraries (h5repack ${HDF5_TOOLS_LIB_TARGET} ${HDF5_LIB_TARGET}) +set_target_properties (h5repack PROPERTIES FOLDER tools) +set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};h5repack") + +set (H5_DEP_EXECUTABLES h5repack) + +############################################################################## +############################################################################## +### I N S T A L L A T I O N ### +############################################################################## +############################################################################## + +#----------------------------------------------------------------------------- +# Rules for Installation of tools using make Install target +#----------------------------------------------------------------------------- + +#INSTALL_PROGRAM_PDB (h5repack ${HDF5_INSTALL_BIN_DIR} toolsapplications) + +install ( + TARGETS + h5repack + EXPORT + ${HDF5_EXPORTED_TARGETS} + RUNTIME DESTINATION ${HDF5_INSTALL_BIN_DIR} COMPONENT toolsapplications +) diff --git a/tools/src/h5repack/Makefile.am b/tools/src/h5repack/Makefile.am new file mode 100644 index 0000000..e6e5a56 --- /dev/null +++ b/tools/src/h5repack/Makefile.am @@ -0,0 +1,42 @@ +# +# Copyright by The HDF Group. +# Copyright by the Board of Trustees of the University of Illinois. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the files COPYING and Copyright.html. COPYING can be found at the root +# of the source code distribution tree; Copyright.html can be found at the +# root level of an installed copy of the electronic HDF5 document set and +# is linked from the top-level documents page. It can also be found at +# http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have +# access to either file, you may request a copy from help@hdfgroup.org. +## +## Makefile.am +## Run automake to generate a Makefile.in from this file. +# +# HDF5 Library Makefile(.in) +# + +include $(top_srcdir)/config/commence.am + +# Include src, test, and tools/lib directories +AM_CPPFLAGS+=-I$(top_srcdir)/src -I$(top_srcdir)/test -I$(top_srcdir)/tools/lib + +# Our main target, h5repack tool +bin_PROGRAMS=h5repack + +# Add h5repack specific linker flags here +h5repack_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) + +# Depend on the hdf5 library, the tools library, the test library +LDADD=$(LIBH5TOOLS) $(LIBH5TEST) $(LIBHDF5) + +# Source files +COMMON_SOURCES=h5repack.c h5repack_copy.c h5repack_filters.c \ + h5repack_opttable.c h5repack_parse.c h5repack_refs.c \ + h5repack_verify.c + +h5repack_SOURCES=$(COMMON_SOURCES) h5repack_main.c + +include $(top_srcdir)/config/conclude.am diff --git a/tools/src/h5repack/h5repack.c b/tools/src/h5repack/h5repack.c new file mode 100644 index 0000000..ef2085c --- /dev/null +++ b/tools/src/h5repack/h5repack.c @@ -0,0 +1,942 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "H5private.h" +#include "h5repack.h" +#include "h5tools.h" +#include "h5tools_utils.h" + +/*------------------------------------------------------------------------- + * File: h5repack.c + * Purpose: Public API functions + *------------------------------------------------------------------------- + */ + +static int check_options(pack_opt_t *options); +static int check_objects(const char* fname, pack_opt_t *options); +static const char* get_sfilter(H5Z_filter_t filtn); +static int have_request(pack_opt_t *options); + +/*------------------------------------------------------------------------- + * Function: h5repack + * + * Purpose: locate all high-level HDF5 objects in the file + * and compress/chunk them using options + * + * Algorithm: 2 traversals are made to the file; the 1st builds a list of + * the objects, the 2nd makes a copy of them, using the options; + * the reason for the 1st traversal is to check for invalid + * object name requests + * + * Return: 0, ok, -1, fail + * + * Programmer: pvn@ncsa.uiuc.edu + * + * Date: September, 22, 2003 + * + *------------------------------------------------------------------------- + */ +int h5repack(const char* infile, const char* outfile, pack_opt_t *options) { + /* check input */ + if (check_options(options) < 0) + return -1; + + /* check for objects in input that are in the file */ + if (check_objects(infile, options) < 0) + return -1; + + /* copy the objects */ + if (copy_objects(infile, outfile, options) < 0) + return -1; + + return 0; +} + +/*------------------------------------------------------------------------- + * Function: h5repack_init + * + * Purpose: initialize options + * + * Return: 0, ok, -1, fail + * + *------------------------------------------------------------------------- + */ +int h5repack_init(pack_opt_t *options, int verbose, hbool_t latest, + H5F_file_space_type_t strategy, hsize_t threshold) { + int k, n; + + HDmemset(options, 0, sizeof(pack_opt_t)); + options->min_comp = 0; + options->verbose = verbose; + options->latest = latest; + options->layout_g = H5D_LAYOUT_ERROR; + + for (n = 0; n < H5_REPACK_MAX_NFILTERS; n++) { + options->filter_g[n].filtn = -1; + options->filter_g[n].cd_nelmts = 0; + for (k = 0; k < CD_VALUES; k++) + options->filter_g[n].cd_values[k] = 0; + } + + options->fs_strategy = strategy; + options->fs_threshold = threshold; + + return (options_table_init(&(options->op_tbl))); +} + +/*------------------------------------------------------------------------- + * Function: h5repack_end + * + * Purpose: free options table + * + *------------------------------------------------------------------------- + */ + +int h5repack_end(pack_opt_t *options) { + return options_table_free(options->op_tbl); +} + +/*------------------------------------------------------------------------- + * Function: h5repack_addfilter + * + * Purpose: add a compression -f option to table + * Example: -f dset:GZIP=6 + * + * Return: 0, ok, -1, fail + * + *------------------------------------------------------------------------- + */ +int +h5repack_addfilter(const char* str, pack_opt_t *options) +{ + obj_list_t *obj_list = NULL; /* one object list for the -f and -l option entry */ + filter_info_t filter; /* filter info for the current -f option entry */ + unsigned n_objs; /* number of objects in the current -f or -l option entry */ + int is_glb; /* is the filter global */ + + /* parse the -f option */ + if (NULL == (obj_list = parse_filter(str, &n_objs, &filter, options, &is_glb))) + return -1; + + /* if it applies to all objects */ + if (is_glb) { + int n; + + n = options->n_filter_g++; /* increase # of global filters */ + if (options->n_filter_g > H5_REPACK_MAX_NFILTERS) { + error_msg("maximum number of filters exceeded for <%s>\n", str); + HDfree(obj_list); + return -1; + } + + options->filter_g[n] = filter; + } + else + options_add_filter(obj_list, n_objs, filter, options->op_tbl); + + HDfree(obj_list); + return 0; +} + +/*------------------------------------------------------------------------- + * Function: h5repack_addlayout + * + * Purpose: add a layout option + * + * Return: 0, ok, -1, fail + * + *------------------------------------------------------------------------- + */ +int +h5repack_addlayout(const char* str, pack_opt_t *options) +{ + obj_list_t *obj_list = NULL; /*one object list for the -t and -c option entry */ + unsigned n_objs; /*number of objects in the current -t or -c option entry */ + pack_info_t pack; /*info about layout to extract from parse */ + int j; + int ret_value = -1; + + init_packobject(&pack); + + if (options->all_layout == 1) { + error_msg( "invalid layout input: 'all' option is present with other objects <%s>\n", str); + return ret_value; + } + + /* parse the layout option */ + obj_list = parse_layout(str, &n_objs, &pack, options); + if (obj_list) { + /* set layout option */ + options->layout_g = pack.layout; + + /* no individual dataset specified */ + if (options->all_layout == 1) { + if (pack.layout == H5D_CHUNKED) { + /* -2 means the NONE option, remove chunking + and set the global layout to contiguous */ + if (pack.chunk.rank == -2) + options->layout_g = H5D_CONTIGUOUS; + /* otherwise set the global chunking type */ + else { + options->chunk_g.rank = pack.chunk.rank; + for (j = 0; j < pack.chunk.rank; j++) + options->chunk_g.chunk_lengths[j] = pack.chunk.chunk_lengths[j]; + } + } + } + + /* individual dataset specified */ + if (options->all_layout == 0) + ret_value = options_add_layout(obj_list, n_objs, &pack, options->op_tbl); + + HDfree(obj_list); + ret_value = 0; + } + + return ret_value; +} + +/* Note: The below copy_named_datatype(), named_datatype_free(), copy_attr() + * were located in h5repack_copy.c as static prior to bugfix1726. + * Made shared functions as copy_attr() was needed in h5repack_refs.c. + * However copy_attr() may be obsoleted when H5Acopy is available and put back + * others to static in h5repack_copy.c. + */ +/*------------------------------------------------------------------------- + * Function: copy_named_datatype + * + * Purpose: Copies the specified datatype anonymously, and returns an open + * id for that datatype in the output file. The first time this + * is called it scans every named datatype in travt into a + * private stack, afterwards it simply scans that stack. The id + * returned must be closed after it is no longer needed. + * named_datatype_free must be called before the program exits + * to free the stack. + * + * Programmer: Neil Fortner + * + * Date: April 14, 2009 + * + *------------------------------------------------------------------------- + */ +hid_t copy_named_datatype(hid_t type_in, hid_t fidout, + named_dt_t **named_dt_head_p, trav_table_t *travt, pack_opt_t *options) { + named_dt_t *dt = *named_dt_head_p; /* Stack pointer */ + named_dt_t *dt_ret = NULL; /* Datatype to return */ + H5O_info_t oinfo; /* Object info of input dtype */ + hid_t ret_value = -1; /* The identifier of the named dtype in the out file */ + + if (H5Oget_info(type_in, &oinfo) < 0) + goto done; + + if (*named_dt_head_p) { + /* Stack already exists, search for the datatype */ + while (dt && dt->addr_in != oinfo.addr) + dt = dt->next; + + dt_ret = dt; + } + else { + /* Create the stack */ + size_t i; + + for (i = 0; i < travt->nobjs; i++) { + if (travt->objs[i].type == H5TRAV_TYPE_NAMED_DATATYPE) { + /* Push onto the stack */ + if (NULL == (dt = (named_dt_t *) HDmalloc(sizeof(named_dt_t)))) { + goto done; + } + dt->next = *named_dt_head_p; + *named_dt_head_p = dt; + + /* Update the address and id */ + dt->addr_in = travt->objs[i].objno; + dt->id_out = -1; + + /* Check if this type is the one requested */ + if (oinfo.addr == dt->addr_in) { + HDassert(!dt_ret); + dt_ret = dt; + } /* end if */ + } /* end if */ + } /* end for */ + } /* end else */ + + /* Handle the case that the requested datatype was not found. This is + * possible if the datatype was committed anonymously in the input file. */ + if (!dt_ret) { + /* Push the new datatype onto the stack */ + if (NULL == (dt_ret = (named_dt_t *) HDmalloc(sizeof(named_dt_t)))) { + goto done; + } + dt_ret->next = *named_dt_head_p; + *named_dt_head_p = dt_ret; + + /* Update the address and id */ + dt_ret->addr_in = oinfo.addr; + dt_ret->id_out = -1; + } /* end if */ + + /* If the requested datatype does not yet exist in the output file, copy it + * anonymously */ + if (dt_ret->id_out < 0) { + if (options->use_native == 1) + dt_ret->id_out = h5tools_get_native_type(type_in); + else + dt_ret->id_out = H5Tcopy(type_in); + if (dt_ret->id_out < 0) + goto done; + if (H5Tcommit_anon(fidout, dt_ret->id_out, H5P_DEFAULT, H5P_DEFAULT) < 0) + goto done; + } /* end if */ + + /* Set return value */ + ret_value = dt_ret->id_out; + + /* Increment the ref count on id_out, because the calling function will try + * to close it */ + if(H5Iinc_ref(ret_value) < 0) { + ret_value = -1; + } + +done: + return (ret_value); +} /* end copy_named_datatype */ + +/*------------------------------------------------------------------------- + * Function: named_datatype_free + * + * Purpose: Frees the stack of named datatypes. + * + * Programmer: Neil Fortner + * + * Date: April 14, 2009 + * + *------------------------------------------------------------------------- + */ +int named_datatype_free(named_dt_t **named_dt_head_p, int ignore_err) { + named_dt_t *dt = *named_dt_head_p; + int ret_value = -1; + + while (dt) { + /* Pop the datatype off the stack and free it */ + if (H5Tclose(dt->id_out) < 0 && !ignore_err) + goto done; + dt = dt->next; + HDfree(*named_dt_head_p); + *named_dt_head_p = dt; + } /* end while */ + + ret_value = 0; + +done: + return (ret_value); +} /* end named_datatype_free */ + +/*------------------------------------------------------------------------- + * Function: copy_attr + * + * Purpose: copy attributes located in LOC_IN, which is obtained either from + * loc_id = H5Gopen2( fid, name); + * loc_id = H5Dopen2( fid, name); + * loc_id = H5Topen2( fid, name); + * + * Return: 0, ok, -1 no + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: October, 28, 2003 + * + *------------------------------------------------------------------------- + */ +int +copy_attr(hid_t loc_in, hid_t loc_out, named_dt_t **named_dt_head_p, + trav_table_t *travt, pack_opt_t *options) +{ + int ret_value = 0; /*no need to LEAVE() on ERROR: HERR_INIT(int, SUCCEED) */ + hid_t attr_id = -1; /* attr ID */ + hid_t attr_out = -1; /* attr ID */ + hid_t space_id = -1; /* space ID */ + hid_t ftype_id = -1; /* file type ID */ + hid_t wtype_id = -1; /* read/write type ID */ + size_t msize; /* size of type */ + void *buf = NULL; /* data buffer */ + hsize_t nelmts; /* number of elements in dataset */ + int rank; /* rank of dataset */ + htri_t is_named; /* Whether the datatype is named */ + hsize_t dims[H5S_MAX_RANK];/* dimensions of dataset */ + char name[255]; + H5O_info_t oinfo; /* object info */ + int j; + unsigned u; + hbool_t is_ref = 0; + H5T_class_t type_class = -1; + + if (H5Oget_info(loc_in, &oinfo) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Oget_info failed"); + + /*------------------------------------------------------------------------- + * copy all attributes + *------------------------------------------------------------------------- + */ + for (u = 0; u < (unsigned) oinfo.num_attrs; u++) { + /* open attribute */ + if ((attr_id = H5Aopen_by_idx(loc_in, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t) u, H5P_DEFAULT, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aopen_by_idx failed"); + + /* get name */ + if (H5Aget_name(attr_id, (size_t) 255, name) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + + /* get the file datatype */ + if ((ftype_id = H5Aget_type(attr_id)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aget_type failed"); + + /* Check if the datatype is committed */ + if ((is_named = H5Tcommitted(ftype_id)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tcommitted failed"); + if (is_named && travt) { + hid_t fidout; + + /* Create out file id */ + if ((fidout = H5Iget_file_id(loc_out)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Iget_file_id failed"); + + /* Copy named dt */ + if ((wtype_id = copy_named_datatype(ftype_id, fidout, named_dt_head_p, travt, options)) < 0) { + H5Fclose(fidout); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_named_datatype failed"); + } /* end if */ + + if (H5Fclose(fidout) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Fclose failed"); + } /* end if */ + else { + if (options->use_native == 1) + wtype_id = h5tools_get_native_type(ftype_id); + else + wtype_id = H5Tcopy(ftype_id); + } /* end else */ + + /* get the dataspace handle */ + if ((space_id = H5Aget_space(attr_id)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aget_space failed"); + + /* get dimensions */ + if ((rank = H5Sget_simple_extent_dims(space_id, dims, NULL)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sget_simple_extent_dims failed"); + + nelmts = 1; + for (j = 0; j < rank; j++) + nelmts *= dims[j]; + + if ((msize = H5Tget_size(wtype_id)) == 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tget_size failed"); + + /*------------------------------------------------------------------------- + * object references are a special case. We cannot just copy the buffers, + * but instead we recreate the reference. + * This is done on a second sweep of the file that just copies the referenced + * objects at copy_refs_attr() + *------------------------------------------------------------------------- + */ + type_class = H5Tget_class(wtype_id); + is_ref = (type_class == H5T_REFERENCE); + if (type_class == H5T_VLEN || type_class == H5T_ARRAY) { + hid_t base_type = -1; + + base_type = H5Tget_super(ftype_id); + is_ref = (is_ref || (H5Tget_class(base_type) == H5T_REFERENCE)); + H5Tclose(base_type); + } + + if (type_class == H5T_COMPOUND) { + int nmembers = H5Tget_nmembers(wtype_id); + + for (j = 0; j < nmembers; j++) { + hid_t mtid = H5Tget_member_type(wtype_id, (unsigned) j); + H5T_class_t mtclass = H5Tget_class(mtid); + H5Tclose(mtid); + + if (mtclass == H5T_REFERENCE) { + is_ref = 1; + break; + } + } /* for (j=0; i<nmembers; j++) */ + } /* if (type_class == H5T_COMPOUND) */ + + if (is_ref) { + ; /* handled by copy_refs_attr() */ + } + else { + /*------------------------------------------------------------------------- + * read to memory + *------------------------------------------------------------------------- + */ + + buf = (void *) HDmalloc((size_t)(nelmts * msize)); + if (buf == NULL) { + error_msg("h5repack", "cannot read into memory\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDmalloc failed"); + } /* end if */ + if (H5Aread(attr_id, wtype_id, buf) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aread failed"); + + /*------------------------------------------------------------------------- + * copy + *------------------------------------------------------------------------- + */ + + if ((attr_out = H5Acreate2(loc_out, name, wtype_id, space_id, H5P_DEFAULT, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Acreate2 failed"); + if (H5Awrite(attr_out, wtype_id, buf) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Awrite failed"); + + /*close*/ + if (H5Aclose(attr_out) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aclose failed"); + + /* Check if we have VL data and string in the attribute's datatype that must + * be reclaimed */ + if (TRUE == h5tools_detect_vlen(wtype_id)) + H5Dvlen_reclaim(wtype_id, space_id, H5P_DEFAULT, buf); + HDfree(buf); + buf = NULL; + } /*H5T_REFERENCE*/ + + if (options->verbose) + printf(FORMAT_OBJ_ATTR, "attr", name); + + /*------------------------------------------------------------------------- + * close + *------------------------------------------------------------------------- + */ + + if (H5Tclose(ftype_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); + if (H5Tclose(wtype_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); + if (H5Sclose(space_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sclose failed"); + if (H5Aclose(attr_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aclose failed"); + } /* u */ + + return 0; + +done: + H5E_BEGIN_TRY { + if (buf) { + /* Check if we have VL data and string in the attribute's datatype that must + * be reclaimed */ + if (TRUE == h5tools_detect_vlen(wtype_id)) + H5Dvlen_reclaim(wtype_id, space_id, H5P_DEFAULT, buf); + + /* Free buf */ + HDfree(buf); + } /* end if */ + + H5Tclose(ftype_id); + H5Tclose(wtype_id); + H5Sclose(space_id); + H5Aclose(attr_id); + H5Aclose(attr_out); + } H5E_END_TRY; + + return ret_value; +} /* end copy_attr() */ + +/*------------------------------------------------------------------------- + * Function: check_options + * + * Purpose: print options, checks for invalid options + * + * Return: void, return -1 on error + * + * Programmer: pvn@ncsa.uiuc.edu + * + * Date: September, 22, 2003 + * + * Modification: + * Peter Cao, July 9, 2007 + * Add "-L, --latest" and other options to pack a file with the latest file format + * + *------------------------------------------------------------------------- + */ +static int check_options(pack_opt_t *options) { + unsigned int i; + int k, j, has_cp = 0, has_ck = 0; + char slayout[30]; + + /*------------------------------------------------------------------------- + * objects to layout + *------------------------------------------------------------------------- + */ + if (options->verbose && have_request(options) /* only print if requested */) { + printf("Objects to modify layout are...\n"); + if (options->all_layout == 1) { + switch (options->layout_g) { + case H5D_COMPACT: + strcpy(slayout, "compact"); + break; + case H5D_CONTIGUOUS: + strcpy(slayout, "contiguous"); + break; + case H5D_CHUNKED: + strcpy(slayout, "chunked"); + break; + case H5D_VIRTUAL: + strcpy(slayout, "virtual"); + break; + case H5D_LAYOUT_ERROR: + case H5D_NLAYOUTS: + error_msg("invalid layout\n"); + return -1; + default: + strcpy(slayout, "invalid layout\n"); + return -1; + } + printf(" Apply %s layout to all\n", slayout); + if (H5D_CHUNKED == options->layout_g) { + printf("with dimension ["); + for (j = 0; j < options->chunk_g.rank; j++) + printf("%d ", (int) options->chunk_g.chunk_lengths[j]); + printf("]\n"); + } + } + }/* verbose */ + + for (i = 0; i < options->op_tbl->nelems; i++) { + char* name = options->op_tbl->objs[i].path; + + if (options->op_tbl->objs[i].chunk.rank > 0) { + if (options->verbose) { + printf(" <%s> with chunk size ", name); + for (k = 0; k < options->op_tbl->objs[i].chunk.rank; k++) + printf("%d ", + (int) options->op_tbl->objs[i].chunk.chunk_lengths[k]); + printf("\n"); + } + has_ck = 1; + } + else if (options->op_tbl->objs[i].chunk.rank == -2) { + if (options->verbose) + printf(" <%s> %s\n", name, "NONE (contigous)"); + has_ck = 1; + } + } + + if (options->all_layout == 1 && has_ck) { + error_msg( + "invalid chunking input: 'all' option\ + is present with other objects\n"); + return -1; + } + + /*------------------------------------------------------------------------- + * objects to filter + *------------------------------------------------------------------------- + */ + + if (options->verbose && have_request(options) /* only print if requested */) { + printf("Objects to apply filter are...\n"); + if (options->all_filter == 1) { + for (k = 0; k < options->n_filter_g; k++) { + H5Z_filter_t filtn = options->filter_g[k].filtn; + switch (filtn) { + case H5Z_FILTER_NONE: + printf(" Uncompress all\n"); + break; + case H5Z_FILTER_SHUFFLE: + case H5Z_FILTER_FLETCHER32: + printf(" All with %s\n", get_sfilter(filtn)); + break; + case H5Z_FILTER_SZIP: + case H5Z_FILTER_DEFLATE: + printf(" All with %s, parameter %d\n", get_sfilter(filtn), + options->filter_g[k].cd_values[0]); + break; + default: + printf(" User Defined %d\n", filtn); + break; + } /* k */ + }; + } + } /* verbose */ + + for (i = 0; i < options->op_tbl->nelems; i++) { + pack_info_t pack = options->op_tbl->objs[i]; + char* name = pack.path; + + for (j = 0; j < pack.nfilters; j++) { + if (options->verbose) { + printf(" <%s> with %s filter\n", name, + get_sfilter(pack.filter[j].filtn)); + } + + has_cp = 1; + + } /* j */ + } /* i */ + + if (options->all_filter == 1 && has_cp) { + error_msg( + "invalid compression input: 'all' option\ + is present with other objects\n"); + return -1; + } + + /*------------------------------------------------------------------------- + * check options for the latest format + *------------------------------------------------------------------------- + */ + + if (options->grp_compact < 0) { + error_msg( + "invalid maximum number of links to store as header messages\n"); + return -1; + } + if (options->grp_indexed < 0) { + error_msg( + "invalid minimum number of links to store in the indexed format\n"); + return -1; + } + if (options->grp_indexed > options->grp_compact) { + error_msg( + "minimum indexed size is greater than the maximum compact size\n"); + return -1; + } + for (i = 0; i < 8; i++) { + if (options->msg_size[i] < 0) { + error_msg("invalid shared message size\n"); + return -1; + } + } + + /*-------------------------------------------------------------------------------- + * verify new user userblock options; file name must be present + *--------------------------------------------------------------------------------- + */ + if (options->ublock_filename != NULL && options->ublock_size == 0) { + if (options->verbose) { + printf( + "Warning: user block size missing for file %s. Assigning a default size of 1024...\n", + options->ublock_filename); + options->ublock_size = 1024; + } + } + + if (options->ublock_filename == NULL && options->ublock_size != 0) { + error_msg("file name missing for user block\n", + options->ublock_filename); + return -1; + } + + /*-------------------------------------------------------------------------------- + * verify alignment options; threshold is zero default but alignment not + *--------------------------------------------------------------------------------- + */ + + if (options->alignment == 0 && options->threshold != 0) { + error_msg("alignment for H5Pset_alignment missing\n"); + return -1; + } + + return 0; +} + +/*------------------------------------------------------------------------- + * Function: check_objects + * + * Purpose: locate all HDF5 objects in the file and compare with user + * supplied list + * + * Return: 0, ok, -1 no + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: September, 23, 2003 + * + *------------------------------------------------------------------------- + */ +static int check_objects(const char* fname, pack_opt_t *options) { + hid_t fid; + unsigned int i; + trav_table_t *travt = NULL; + + /* nothing to do */ + if (options->op_tbl->nelems == 0) + return 0; + + /*------------------------------------------------------------------------- + * open the file + *------------------------------------------------------------------------- + */ + if ((fid = h5tools_fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT, NULL, NULL, 0)) + < 0) { + printf("<%s>: %s\n", fname, H5FOPENERROR); + return -1; + } + + /*------------------------------------------------------------------------- + * get the list of objects in the file + *------------------------------------------------------------------------- + */ + + /* init table */ + trav_table_init(&travt); + + /* get the list of objects in the file */ + if (h5trav_gettable(fid, travt) < 0) + goto out; + + /*------------------------------------------------------------------------- + * compare with user supplied list + *------------------------------------------------------------------------- + */ + + if (options->verbose) + printf("Opening file <%s>. Searching for objects to modify...\n", + fname); + + for (i = 0; i < options->op_tbl->nelems; i++) { + char* name = options->op_tbl->objs[i].path; + if (options->verbose) + printf(" <%s>", name); + + /* the input object names are present in the file and are valid */ + if (h5trav_getindext(name, travt) < 0) { + error_msg("%s Could not find <%s> in file <%s>. Exiting...\n", + (options->verbose ? "\n" : ""), name, fname); + goto out; + } + if (options->verbose) + printf("...Found\n"); + + /* check for extra filter conditions */ + switch (options->op_tbl->objs[i].filter->filtn) { + /* chunk size must be smaller than pixels per block */ + case H5Z_FILTER_SZIP: + { + int j; + hsize_t csize = 1; + unsigned ppb = options->op_tbl->objs[i].filter->cd_values[0]; + hsize_t dims[H5S_MAX_RANK]; + int rank; + hid_t did; + hid_t sid; + + if (options->op_tbl->objs[i].chunk.rank > 0) { + rank = options->op_tbl->objs[i].chunk.rank; + for (j = 0; j < rank; j++) + csize *= options->op_tbl->objs[i].chunk.chunk_lengths[j]; + } + else { + if ((did = H5Dopen2(fid, name, H5P_DEFAULT)) < 0) + goto out; + if ((sid = H5Dget_space(did)) < 0) + goto out; + if ((rank = H5Sget_simple_extent_ndims(sid)) < 0) + goto out; + HDmemset(dims, 0, sizeof dims); + if (H5Sget_simple_extent_dims(sid, dims, NULL) < 0) + goto out; + for (j = 0; j < rank; j++) + csize *= dims[j]; + if (H5Sclose(sid) < 0) + goto out; + if (H5Dclose(did) < 0) + goto out; + } + + if (csize < ppb) { + printf( + " <warning: SZIP settins, chunk size is smaller than pixels per block>\n"); + goto out; + } + } + break; + default: + break; + } + } /* i */ + + /*------------------------------------------------------------------------- + * close + *------------------------------------------------------------------------- + */ + H5Fclose(fid); + trav_table_free(travt); + return 0; + +out: + H5Fclose(fid); + trav_table_free(travt); + return -1; +} + +/*------------------------------------------------------------------------- + * Function: have_request + * + * Purpose: check if a filter or layout was requested + * + * Return: 1 yes, 0 no + * + * Date: May, 24, 2007 + * + *------------------------------------------------------------------------- + */ +static int have_request(pack_opt_t *options) { + + if (options->all_filter || options->all_layout || options->op_tbl->nelems) + return 1; + + return 0; + +} + +/*------------------------------------------------------------------------- + * Function: get_sfilter + * + * Purpose: return the filter as a string name + * + * Return: name of filter, exit on error + * + *------------------------------------------------------------------------- + */ + +static const char* get_sfilter(H5Z_filter_t filtn) { + if (filtn == H5Z_FILTER_NONE) + return "NONE"; + else if (filtn == H5Z_FILTER_DEFLATE) + return "GZIP"; + else if (filtn == H5Z_FILTER_SZIP) + return "SZIP"; + else if (filtn == H5Z_FILTER_SHUFFLE) + return "SHUFFLE"; + else if (filtn == H5Z_FILTER_FLETCHER32) + return "FLETCHER32"; + else if (filtn == H5Z_FILTER_NBIT) + return "NBIT"; + else if (filtn == H5Z_FILTER_SCALEOFFSET) + return "SOFF"; + else + return "UD"; +} + diff --git a/tools/src/h5repack/h5repack.h b/tools/src/h5repack/h5repack.h new file mode 100644 index 0000000..d2ab923 --- /dev/null +++ b/tools/src/h5repack/h5repack.h @@ -0,0 +1,243 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + +#ifndef H5REPACK_H__ +#define H5REPACK_H__ + +#include "H5private.h" +#include "hdf5.h" +#include "h5trav.h" + +#define H5FOPENERROR "unable to open file" +#define PFORMAT "%-7s %-7s %-7s\n" /* chunk info, compression info, name*/ +#define PFORMAT1 "%-7s %-7s %-7s" /* chunk info, compression info, name*/ +#define MAX_NC_NAME 256 /* max length of a name */ +#define MAX_VAR_DIMS 32 /* max per variable dimensions */ +#define FORMAT_OBJ " %-27s %s\n" /* obj type, name */ +#define FORMAT_OBJ_ATTR " %-27s %s\n" /* obj type, name */ +#define MAX_COMPACT_DSIZE 64512 /* max data size for compact layout. -1k for header size */ + +/*------------------------------------------------------------------------- + * data structures for command line options + *------------------------------------------------------------------------- + */ + +/* a list of names */ +typedef struct { + char obj[MAX_NC_NAME]; +} obj_list_t; + +/* + the type of filter and additional parameter + type can be one of the filters + H5Z_FILTER_NONE 0, uncompress if compressed + H5Z_FILTER_DEFLATE 1 , deflation like gzip + H5Z_FILTER_SHUFFLE 2 , shuffle the data + H5Z_FILTER_FLETCHER32 3 , letcher32 checksum of EDC + H5Z_FILTER_SZIP 4 , szip compression + H5Z_FILTER_NBIT 5 , nbit compression + H5Z_FILTER_SCALEOFFSET 6 , scaleoffset compression +*/ + +#define CD_VALUES 20 + +typedef struct { + H5Z_filter_t filtn; /* filter identification number */ + unsigned cd_values[CD_VALUES]; /* filter client data values */ + size_t cd_nelmts; /* filter client number of values */ +} filter_info_t; + +/* chunk lengths along each dimension and rank */ +typedef struct { + hsize_t chunk_lengths[MAX_VAR_DIMS]; + int rank; +} chunk_info_t; + +/* we currently define a maximum value for the filters array, + that corresponds to the current library filters */ +#define H5_REPACK_MAX_NFILTERS 6 + +/* information for one object, contains PATH, CHUNK info and FILTER info */ +typedef struct { + char path[MAX_NC_NAME]; /* name of object */ + filter_info_t filter[H5_REPACK_MAX_NFILTERS]; /* filter array */ + int nfilters; /* current number of filters */ + H5D_layout_t layout; /* layout information */ + chunk_info_t chunk; /* chunk information */ + hid_t refobj_id; /* object ID, references */ +} pack_info_t; + +/* store a table of all objects */ +typedef struct { + unsigned int size; + unsigned int nelems; + pack_info_t *objs; +} pack_opttbl_t; + + +/*------------------------------------------------------------------------- + * command line options + *------------------------------------------------------------------------- + */ + +/* all the above, ready to go to the hrepack call */ +typedef struct { + pack_opttbl_t *op_tbl; /*table with all -c and -f options */ + int all_layout; /*apply the layout to all objects */ + int all_filter; /*apply the filter to all objects */ + filter_info_t filter_g[H5_REPACK_MAX_NFILTERS]; /*global filter array for the ALL case */ + int n_filter_g; /*number of global filters */ + chunk_info_t chunk_g; /*global chunk INFO for the ALL case */ + H5D_layout_t layout_g; /*global layout information for the ALL case */ + int verbose; /*verbose mode */ + hsize_t min_comp; /*minimum size to compress, in bytes */ + int use_native; /*use a native type in write */ + hbool_t latest; /*pack file with the latest file format */ + int grp_compact; /* Set the maximum number of links to store as header messages in the group */ + int grp_indexed; /* Set the minimum number of links to store in the indexed format */ + int msg_size[8]; /* Minimum size of shared messages: dataspace, + datatype, fill value, filter pipleline, attribute */ + const char *ublock_filename; /* user block file name */ + hsize_t ublock_size; /* user block size */ + hsize_t meta_block_size; /* metadata aggregation block size (for H5Pset_meta_block_size) */ + hsize_t threshold; /* alignment threshold for H5Pset_alignment */ + hsize_t alignment; /* alignment for H5Pset_alignment */ + H5F_file_space_type_t fs_strategy; /* File space handling strategy */ + hsize_t fs_threshold; /* Free space section threshold */ +} pack_opt_t; + + +typedef struct named_dt_t { + haddr_t addr_in; /* Address of the named dtype in the in file */ + hid_t id_out; /* Open identifier for the dtype in the out file */ + struct named_dt_t *next; /* Next dtype */ +} named_dt_t; + +/*------------------------------------------------------------------------- + * public functions + *------------------------------------------------------------------------- + */ + +#ifdef __cplusplus +extern "C" { +#endif + +int h5repack(const char* infile, const char* outfile, pack_opt_t *options); +int h5repack_addfilter(const char* str, pack_opt_t *options); +int h5repack_addlayout(const char* str, pack_opt_t *options); +int h5repack_init(pack_opt_t *options, int verbose, hbool_t latest, + H5F_file_space_type_t strategy, hsize_t threshold); +int h5repack_end(pack_opt_t *options); +int h5repack_verify(const char *in_fname, const char *out_fname, pack_opt_t *options); +int h5repack_cmp_pl(const char *fname1, const char *fname2); + +/* Note: The below copy_named_datatype(), named_datatype_free(), copy_attr() + * and struct named_dt_t were located in h5repack_copy.c as static prior to + * bugfix1726. + * Made shared functions as copy_attr() was needed in h5repack_refs.c. + * However copy_attr() may be obsoleted when H5Acopy is available and put back + * others to static in h5repack_copy.c. + */ +hid_t copy_named_datatype(hid_t type_in, hid_t fidout, named_dt_t **named_dt_head_p, trav_table_t *travt, pack_opt_t *options); +int named_datatype_free(named_dt_t **named_dt_head_p, int ignore_err); +int copy_attr(hid_t loc_in, hid_t loc_out, named_dt_t **named_dt_head_p, + trav_table_t *travt, pack_opt_t *options); + +#ifdef __cplusplus +} +#endif + + + +/*------------------------------------------------------------------------- + * private functions + *------------------------------------------------------------------------- + */ + + +/*------------------------------------------------------------------------- + * copy module + *------------------------------------------------------------------------- + */ + +int copy_objects (const char* fnamein, + const char* fnameout, + pack_opt_t *options); + +int do_copy_refobjs(hid_t fidin, + hid_t fidout, + trav_table_t *travt, + pack_opt_t *options); + +/*------------------------------------------------------------------------- + * filters and verify module + *------------------------------------------------------------------------- + */ +void init_packobject(pack_info_t *obj); + + +/*------------------------------------------------------------------------- + * filters and copy module + *------------------------------------------------------------------------- + */ + +int apply_filters(const char* name, /* object name from traverse list */ + int rank, /* rank of dataset */ + hsize_t *dims, /* dimensions of dataset */ + size_t msize, /* size of type */ + hid_t dcpl_id, /* dataset creation property list */ + pack_opt_t *options, /* repack options */ + int *has_filter); /* (OUT) object NAME has a filter */ + + +/*------------------------------------------------------------------------- + * options table + *------------------------------------------------------------------------- + */ +int options_table_init( pack_opttbl_t **tbl ); +int options_table_free( pack_opttbl_t *table ); +int options_add_layout( obj_list_t *obj_list, + unsigned n_objs, + pack_info_t *pack, + pack_opttbl_t *table ); +int options_add_filter ( obj_list_t *obj_list, + unsigned n_objs, + filter_info_t filt, + pack_opttbl_t *table ); +pack_info_t* options_get_object( const char *path, + pack_opttbl_t *table); + +/*------------------------------------------------------------------------- + * parse functions + *------------------------------------------------------------------------- + */ + +obj_list_t* parse_filter(const char *str, + unsigned *n_objs, + filter_info_t *filt, + pack_opt_t *options, + int *is_glb); + +obj_list_t* parse_layout(const char *str, + unsigned *n_objs, + pack_info_t *pack, /* info about object */ + pack_opt_t *options); + + + + +#endif /* H5REPACK_H__ */ + diff --git a/tools/src/h5repack/h5repack_copy.c b/tools/src/h5repack/h5repack_copy.c new file mode 100644 index 0000000..547f61a --- /dev/null +++ b/tools/src/h5repack/h5repack_copy.c @@ -0,0 +1,1581 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "h5repack.h" +#include "h5tools.h" +#include "h5tools_utils.h" + +/*------------------------------------------------------------------------- + * typedefs + *------------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------- + * globals + *------------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------- + * macros + *------------------------------------------------------------------------- + */ + +/* size of buffer/# of bytes to xfer at a time when copying userblock */ +#define USERBLOCK_XFER_SIZE 512 + +/* check H5Dread()/H5Dwrite() error, e.g. memory allocation error inside the library. */ +#define CHECK_H5DRW_ERROR(_fun, _fail, _did, _mtid, _msid, _fsid, _pid, _buf) { \ + H5E_BEGIN_TRY { \ + if(_fun(_did, _mtid, _msid, _fsid, _pid, _buf) < 0) { \ + hid_t _err_num = 0; \ + char _msg[80]; \ + H5Ewalk2(H5E_DEFAULT, H5E_WALK_DOWNWARD, walk_error_callback, &_err_num); \ + H5Eget_msg(_err_num, NULL, _msg, (size_t)80); \ + error_msg("%s %s -- %s\n", #_fun, "failed", _msg); \ + HGOTO_DONE(_fail) \ + } \ + } H5E_END_TRY; \ +} + +/*------------------------------------------------------------------------- + * local functions + *------------------------------------------------------------------------- + */ +static int Get_hyperslab(hid_t dcpl_id, int rank_dset, hsize_t dims_dset[], + size_t size_datum, hsize_t dims_hslab[], hsize_t * hslab_nbytes_p); +static void print_dataset_info(hid_t dcpl_id, char *objname, double per, int pr); +static int do_copy_objects(hid_t fidin, hid_t fidout, trav_table_t *travt, + pack_opt_t *options); +static int copy_user_block(const char *infile, const char *outfile, + hsize_t size); +#if defined (H5REPACK_DEBUG_USER_BLOCK) +static void print_user_block(const char *filename, hid_t fid); +#endif +static herr_t walk_error_callback(unsigned n, const H5E_error2_t *err_desc, void *udata); + +/* get the major number from the error stack. */ +static herr_t walk_error_callback(H5_ATTR_UNUSED unsigned n, const H5E_error2_t *err_desc, void *udata) { + if (err_desc) + *((hid_t *) udata) = err_desc->maj_num; + + return 0; +} + +/*------------------------------------------------------------------------- + * Function: copy_objects + * + * Purpose: duplicate all HDF5 objects in the file + * + * Return: 0, ok, -1 no + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: October, 23, 2003 + * + * Modification: + * Peter Cao, June 13, 2007 + * Add "-L, --latest" and other options to pack a file with the latest file format + * + * Peter Cao, September 25, 2007 + * Copy user block when repacking a file + * + * Pedro Vicente, August 20, 2008 + * Add a user block to file if requested + * + *------------------------------------------------------------------------- + */ + +int copy_objects(const char* fnamein, const char* fnameout, pack_opt_t *options) +{ + int ret_value = 0; /*no need to LEAVE() on ERROR: HERR_INIT(int, SUCCEED) */ + hid_t fidin; + hid_t fidout = -1; + trav_table_t *travt = NULL; + hsize_t ub_size = 0; /* size of user block */ + hid_t fcpl = H5P_DEFAULT; /* file creation property list ID */ + hid_t fapl = H5P_DEFAULT; /* file access property list ID */ + + /*------------------------------------------------------------------------- + * open input file + *------------------------------------------------------------------------- + */ + if ((fidin = h5tools_fopen(fnamein, H5F_ACC_RDONLY, H5P_DEFAULT, NULL, NULL, (size_t) 0)) < 0) { + error_msg("<%s>: %s\n", fnamein, H5FOPENERROR); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + + /* get user block size and file space strategy/threshold */ + { + hid_t fcpl_in; /* file creation property list ID for input file */ + + if ((fcpl_in = H5Fget_create_plist(fidin)) < 0) { + error_msg("failed to retrieve file creation property list\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + + if (H5Pget_userblock(fcpl_in, &ub_size) < 0) { + error_msg("failed to retrieve userblock size\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + + if (!options->fs_strategy) { + if (H5Pget_file_space(fcpl_in, &options->fs_strategy, NULL) < 0) { + error_msg("failed to retrieve file space strategy\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + } + + if (!options->fs_threshold) { + if (H5Pget_file_space(fcpl_in, NULL, &options->fs_threshold) < 0) { + error_msg("failed to retrieve file space threshold\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + } + + if (H5Pclose(fcpl_in) < 0) { + error_msg("failed to close property list\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + } + + /* Check if we need to create a non-default file creation property list */ + if (options->latest || ub_size > 0) { + /* Create file creation property list */ + if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) { + error_msg("fail to create a file creation property list\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + + if (ub_size > 0) { + if (H5Pset_userblock(fcpl, ub_size) < 0) { + error_msg("failed to set non-default userblock size\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + } + + if (options->latest) { + unsigned i = 0, nindex = 0, mesg_type_flags[5], min_mesg_sizes[5]; + + /* Adjust group creation parameters for root group */ + /* (So that it is created in "dense storage" form) */ + if (H5Pset_link_phase_change(fcpl, (unsigned) options->grp_compact, + (unsigned) options->grp_indexed) < 0) { + error_msg("fail to adjust group creation parameters for root group\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + + for (i = 0; i < 5; i++) { + if (options->msg_size[i] > 0) { + switch (i) { + case 0: + mesg_type_flags[nindex] = H5O_SHMESG_SDSPACE_FLAG; + break; + + case 1: + mesg_type_flags[nindex] = H5O_SHMESG_DTYPE_FLAG; + break; + + case 2: + mesg_type_flags[nindex] = H5O_SHMESG_FILL_FLAG; + break; + + case 3: + mesg_type_flags[nindex] = H5O_SHMESG_PLINE_FLAG; + break; + + case 4: + mesg_type_flags[nindex] = H5O_SHMESG_ATTR_FLAG; + break; + + default: + break; + } /* end switch */ + min_mesg_sizes[nindex] = (unsigned) options->msg_size[i]; + + nindex++; + } /* end if */ + } /* end for */ + + if (nindex > 0) { + if (H5Pset_shared_mesg_nindexes(fcpl, nindex) < 0) { + error_msg("fail to set the number of shared object header message indexes\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + + /* msg_size[0]=dataspace, 1=datatype, 2=file value, 3=filter pipleline, 4=attribute */ + for (i = 0; i < (nindex - 1); i++) { + if (H5Pset_shared_mesg_index(fcpl, i, mesg_type_flags[i], min_mesg_sizes[i]) < 0) { + error_msg("fail to configure the specified shared object header message index\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } /* end if */ + } /* end for */ + } /* if (nindex>0) */ + + /* Create file access property list */ + if ((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) { + error_msg("Could not create file access property list\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } /* end if */ + + if (H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) { + error_msg("Could not set property for using latest version of the format\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } /* end if */ + } /* end if */ + } /* end if */ +#if defined (H5REPACK_DEBUG_USER_BLOCK) +print_user_block(fnamein, fidin); +#endif + + /*------------------------------------------------------------------------- + * set the new user userblock options in the FCPL (before H5Fcreate ) + *------------------------------------------------------------------------- + */ + if (options->ublock_size > 0) { + /* either use the FCPL already created or create a new one */ + if (fcpl == H5P_DEFAULT) { + /* create a file creation property list */ + if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) { + error_msg("fail to create a file creation property list\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + } + + /* set user block size */ + if (H5Pset_userblock(fcpl, options->ublock_size) < 0) { + error_msg("failed to set userblock size\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + } + + /*------------------------------------------------------------------------- + * set alignment options + *------------------------------------------------------------------------- + */ + if (options->alignment > 0) { + /* either use the FAPL already created or create a new one */ + if (fapl == H5P_DEFAULT) { + /* create a file access property list */ + if ((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) { + error_msg("Could not create file access property list\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + } + + if (H5Pset_alignment(fapl, options->threshold, options->alignment) < 0) { + error_msg("failed to set alignment\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + } + + /*------------------------------------------------------------------------- + * set metadata block size option + *------------------------------------------------------------------------- + */ + if (options->meta_block_size > 0) { + /* either use the FAPL already created or create a new one */ + if (fapl == H5P_DEFAULT) { + /* create a file access property list */ + if ((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) { + error_msg("Could not create file access property list\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + } + + if (H5Pset_meta_block_size(fapl, options->meta_block_size) < 0) { + error_msg("failed to set metadata block size\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + } + + /*------------------------------------------------------------------------- + * set free-space strategy options + *------------------------------------------------------------------------- + */ + + /* either use the FCPL already created or create a new one */ + if (fcpl == H5P_DEFAULT) { + /* create a file creation property list */ + if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) { + error_msg("fail to create a file creation property list\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + } + + /* set file space strategy and free space threshold */ + if (H5Pset_file_space(fcpl, options->fs_strategy, options->fs_threshold) < 0) { + error_msg("failed to set file space strategy & threshold \n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + + /*------------------------------------------------------------------------- + * create the output file + *------------------------------------------------------------------------- + */ + if (options->verbose) + printf("Making file <%s>...\n", fnameout); + + if ((fidout = H5Fcreate(fnameout, H5F_ACC_TRUNC, fcpl, fapl)) < 0) { + error_msg("<%s>: Could not create file\n", fnameout); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + + /*------------------------------------------------------------------------- + * write a new user block if requested + *------------------------------------------------------------------------- + */ + if (options->ublock_size > 0) { + if (copy_user_block(options->ublock_filename, fnameout, options->ublock_size) < 0) { + error_msg("Could not copy user block. Exiting...\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + } + + /*------------------------------------------------------------------------- + * get list of objects + *------------------------------------------------------------------------- + */ + + /* init table */ + trav_table_init(&travt); + + /* get the list of objects in the file */ + if (h5trav_gettable(fidin, travt) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + + /*------------------------------------------------------------------------- + * do the copy + *------------------------------------------------------------------------- + */ + if (do_copy_objects(fidin, fidout, travt, options) < 0) { + error_msg("<%s>: Could not copy data to: %s\n", fnamein, fnameout); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } /* end if */ + + /*------------------------------------------------------------------------- + * do the copy of referenced objects + * and create hard links + *------------------------------------------------------------------------- + */ + if (do_copy_refobjs(fidin, fidout, travt, options) < 0) { + printf("h5repack: <%s>: Could not copy data to: %s\n", fnamein, fnameout); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + + /*------------------------------------------------------------------------- + * close + *------------------------------------------------------------------------- + */ + + if (fapl > 0) + H5Pclose(fapl); + + if (fcpl > 0) + H5Pclose(fcpl); + + H5Fclose(fidin); + H5Fclose(fidout); + + /* free table */ + trav_table_free(travt); + travt = NULL; + + /*------------------------------------------------------------------------- + * write only the input file user block if there is no user block file input + *------------------------------------------------------------------------- + */ + + if (ub_size > 0 && options->ublock_size == 0) { + if (copy_user_block(fnamein, fnameout, ub_size) < 0) { + error_msg("Could not copy user block. Exiting...\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + } + + return 0; + + /*------------------------------------------------------------------------- + * out + *------------------------------------------------------------------------- + */ + +done: + H5E_BEGIN_TRY { + H5Pclose(fapl); + H5Pclose(fcpl); + H5Fclose(fidin); + H5Fclose(fidout); + } H5E_END_TRY; + if (travt) + trav_table_free(travt); + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: Get_hyperslab + * + * Purpose: Calulate a hyperslab from a dataset for higher performance. + * The size of hyperslab is limitted by H5TOOLS_BUFSIZE. + * Return the hyperslab dimentions and size in byte. + * + * Return: 0 - SUCCEED, -1 FAILED + * + * Parameters: + * dcpl_id : [IN] dataset creation property. + * rank_dset : [IN] dataset rank + * dims_dset[] : [IN] dataset dimentions + * size_datum : [IN] size of a data element in byte + * dims_hslab[] : [OUT] calculated hyperslab dimentions + * * hslab_nbytes_p : [OUT] total byte of the hyperslab + * + * Programmer: Jonathan Kim + * Date: Feburary, 2012 + * Update: + * The hyperslab calucation would be depend on if the dataset is chunked + * or not. + * + * There care 3 conditions to cover: + * 1. If chunked and a chunk fits in buffer, each chunk would be a unit of + * collection and the boundary would be dataset's dims. + * 2. If chunked but a chunk doesn't fit in buffer, each data element would + * be a unit of collection and the boundary would be the chunk itself. + * 3. If not chunked, each data element would be a unit of collection and + * the boundary would be dataset's dims. + * + * The calulation starts from the last dimention (h5dump dims output). + * + * Note: + * Added for JIRA HDFFV-7862. + *-----------------------------------------*/ + +int Get_hyperslab(hid_t dcpl_id, int rank_dset, hsize_t dims_dset[], + size_t size_datum, hsize_t dims_hslab[], hsize_t * hslab_nbytes_p) +{ + int ret_value = 0; /*no need to LEAVE() on ERROR: HERR_INIT(int, SUCCEED) */ + int k; + H5D_layout_t dset_layout; + int rank_chunk; + hsize_t dims_chunk[H5S_MAX_RANK]; + hsize_t size_chunk = 1; + hsize_t nchunk_fit; /* number of chunks that fits in hyperslab buffer (H5TOOLS_BUFSIZE) */ + hsize_t ndatum_fit; /* number of dataum that fits in hyperslab buffer (H5TOOLS_BUFSIZE) */ + hsize_t chunk_dims_map[H5S_MAX_RANK]; /* mapped chunk dimentions */ + hsize_t hs_dims_map[H5S_MAX_RANK]; /* mapped hyperslab dimentions */ + hsize_t hslab_nbytes; /* size of hyperslab in byte */ + + /* init to set as size of a data element */ + hslab_nbytes = size_datum; + + /* get layout of dataset */ + dset_layout = H5Pget_layout(dcpl_id); + + /* if dataset is chunked */ + if (dset_layout == H5D_CHUNKED) { + /* get chunk dims */ + rank_chunk = H5Pget_chunk(dcpl_id, rank_dset, dims_chunk); + if (rank_chunk < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + + for (k = rank_dset; k > 0; --k) + size_chunk *= dims_chunk[k - 1]; + + /* figure out how many chunks can fit in the hyperslab buffer */ + nchunk_fit = (H5TOOLS_BUFSIZE / size_datum) / size_chunk; + + /* 1. if a chunk fit in hyperslab buffer */ + if (nchunk_fit >= 1) { + /* Calulate a hyperslab that contains as many chunks that can fit + * in hyperslab buffer. Hyperslab will be increased starting from + * the last dimention of the dataset (see h5dump's dims output). + * The calculation boundary is dataset dims. + * In the loop, used mapping from a datum to a chunk to figure out + * chunk based hyperslab. + */ + for (k = rank_dset; k > 0; --k) { + /* map dataset dimentions with a chunk dims */ + chunk_dims_map[k - 1] = dims_dset[k - 1] / dims_chunk[k - 1]; + + /* if reminder exist, increse by 1 to cover partial edge chunks */ + if (dims_dset[k - 1] % dims_chunk[k - 1] > 0) + chunk_dims_map[k - 1]++; + + /* get mapped hyperslab dims */ + hs_dims_map[k - 1] = MIN (nchunk_fit, chunk_dims_map[k-1]); + + /* prepare next round */ + nchunk_fit = nchunk_fit / chunk_dims_map[k - 1]; + /* if a chunk is bigger than the rest of buffer */ + if (nchunk_fit == 0) + nchunk_fit = 1; + + /* get hyperslab dimentions as unmapping to actual size */ + dims_hslab[k - 1] = MIN( (hs_dims_map[k-1] * dims_chunk[k-1]), dims_dset[k-1]); + + /* calculate total size for the hyperslab */ + hslab_nbytes *= dims_hslab[k - 1]; + } + } + /* 2. if a chunk is bigger than hyperslab buffer */ + else { + /* Calulate a hyperslab that contains as many data elements that + * can fit in hyperslab buffer. Hyperslab will be increased + * starting from the last dimention of the chunk (see h5dump's dims + * output). + * The calculation boundary is a chunk dims. + */ + for (k = rank_dset; k > 0; --k) { + ndatum_fit = H5TOOLS_BUFSIZE / hslab_nbytes; + + /* if a datum is bigger than rest of buffer */ + if (ndatum_fit == 0) + ndatum_fit = 1; + /* get hyperslab dimentions within a chunk boundary */ + dims_hslab[k - 1] = MIN (dims_chunk[k-1], ndatum_fit); + + /* calculate total size for the hyperslab */ + hslab_nbytes *= dims_hslab[k - 1]; + + if (hslab_nbytes <= 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + } + } + /* 3. if dataset is not chunked */ + else { + /* Calulate a hyperslab that contains as many data elements that can + * fit in hyperslab buffer. Hyperslab will be increased starting from + * the last dimention of the dataset (see h5dump's dims output). + * The calculation boundary is dataset dims. + */ + for (k = rank_dset; k > 0; --k) { + ndatum_fit = H5TOOLS_BUFSIZE / hslab_nbytes; + + /* if a datum is bigger than rest of buffer */ + if (ndatum_fit == 0) + ndatum_fit = 1; + /* get hyperslab dimentions within dataset boundary */ + dims_hslab[k - 1] = MIN(dims_dset[k - 1], ndatum_fit); + + /* calculate total size for the hyperslab */ + hslab_nbytes *= dims_hslab[k - 1]; + + if (hslab_nbytes <= 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + } + } + + /* pass out the hyperslab size*/ + *hslab_nbytes_p = hslab_nbytes; + +done: + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: do_copy_objects + * + * Purpose: duplicate all HDF5 objects in the file + * + * Return: 0, ok, -1 no + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: October, 23, 2003 + * + * Modifications: + * + * July 2004: Introduced the extra EC or NN option for SZIP + * + * December 2004: Added a check for H5Dcreate; if the dataset cannot be created + * with the requested filter, use the input one + * + * October 2006: Read/write using the file type by default. + * + * October 2006: Read by hyperslabs for big datasets. + * + * A threshold of H5TOOLS_MALLOCSIZE (128 MB) is the limit upon which I/O hyperslab is done + * i.e., if the memory needed to read a dataset is greater than this limit, + * then hyperslab I/O is done instead of one operation I/O + * For each dataset, the memory needed is calculated according to + * + * memory needed = number of elements * size of each element + * + * if the memory needed is lower than H5TOOLS_MALLOCSIZE, then the following operations + * are done + * + * H5Dread( input_dataset1 ) + * H5Dread( input_dataset2 ) + * + * with all elements in the datasets selected. If the memory needed is greater than + * H5TOOLS_MALLOCSIZE, then the following operations are done instead: + * + * a strip mine is defined for each dimension k (a strip mine is defined as a + * hyperslab whose size is memory manageable) according to the formula + * + * (1) strip_mine_size[k ] = MIN(dimension[k ], H5TOOLS_BUFSIZE / size of memory type) + * + * where H5TOOLS_BUFSIZE is a constant currently defined as 1MB. This formula assures + * that for small datasets (small relative to the H5TOOLS_BUFSIZE constant), the strip + * mine size k is simply defined as its dimension k, but for larger datasets the + * hyperslab size is still memory manageable. + * a cycle is done until the number of elements in the dataset is reached. In each + * iteration, two parameters are defined for the function H5Sselect_hyperslab, + * the start and size of each hyperslab, according to + * + * (2) hyperslab_size [k] = MIN(dimension[k] - hyperslab_offset[k], strip_mine_size [k]) + * + * where hyperslab_offset [k] is initially set to zero, and later incremented in + * hyperslab_size[k] offsets. The reason for the operation + * + * dimension[k] - hyperslab_offset[k] + * + * in (2) is that, when using the strip mine size, it assures that the "remaining" part + * of the dataset that does not fill an entire strip mine is processed. + * + * November 2006: Use H5Ocopy in the copy of objects. The logic for using + * H5Ocopy or not is if a change of filters or layout is requested by the user + * then use read/write else use H5Ocopy. + * + * May, 1, 2008: Add a printing of the compression ratio of old size / new size + * + * Feburary 2012: improve Read/Write by hyperslabs for big datasets. + * Programmer: Jonathan Kim + * + * A threshold of H5TOOLS_MALLOCSIZE is the limit upon which I/O hyperslab is done + * i.e., if the memory needed to read a dataset is greater than this limit, + * then hyperslab I/O is done instead of one operation I/O + * For each dataset, the memory needed is calculated according to + * + * memory needed = number of elements * size of each element + * + * if the memory needed is lower than H5TOOLS_MALLOCSIZE, then the following operations + * are done + * + * H5Dread( input_dataset ) + * H5Dwrite( output_dataset ) + * + * with all elements in the datasets selected. If the memory needed is greater than + * H5TOOLS_MALLOCSIZE, then the following operations are done instead: + * + * 1. figure out a hyperslab (dimentions) and size (refer to Get_hyperslab()). + * 2. Calculate the hyperslab selections as the selection is moving forward. + * Selection would be same as the hyperslab except for the remaining edge portion + * of the dataset. The code take care of the remaining portion if exist. + * + *------------------------------------------------------------------------- + */ + +int do_copy_objects(hid_t fidin, hid_t fidout, trav_table_t *travt, + pack_opt_t *options) /* repack options */ +{ + int ret_value = 0; /*no need to LEAVE() on ERROR: HERR_INIT(int, SUCCEED) */ + hid_t grp_in = -1; /* group ID */ + hid_t grp_out = -1; /* group ID */ + hid_t dset_in = -1; /* read dataset ID */ + hid_t dset_out = -1; /* write dataset ID */ + hid_t gcpl_in = -1; /* group creation property list */ + hid_t gcpl_out = -1; /* group creation property list */ + hid_t type_in = -1; /* named type ID */ + hid_t type_out = -1; /* named type ID */ + hid_t dcpl_in = -1; /* dataset creation property list ID */ + hid_t dcpl_out = -1; /* dataset creation property list ID */ + hid_t f_space_id = -1; /* file space ID */ + hid_t ftype_id = -1; /* file type ID */ + hid_t wtype_id = -1; /* read/write type ID */ + named_dt_t *named_dt_head = NULL; /* Pointer to the stack of named datatypes copied */ + size_t msize; /* size of type */ + hsize_t nelmts; /* number of elements in dataset */ + H5D_space_status_t space_status; /* determines whether space has been allocated for the dataset */ + int rank; /* rank of dataset */ + hsize_t dims[H5S_MAX_RANK];/* dimensions of dataset */ + hsize_t dsize_in; /* input dataset size before filter */ + hsize_t dsize_out; /* output dataset size after filter */ + int apply_s; /* flag for apply filter to small dataset sizes */ + int apply_f; /* flag for apply filter to return error on H5Dcreate */ + void *buf = NULL; /* buffer for raw data */ + void *hslab_buf = NULL; /* hyperslab buffer for raw data */ + int has_filter; /* current object has a filter */ + int req_filter; /* there was a request for a filter */ + int req_obj_layout = 0; /* request layout to current object */ + unsigned crt_order_flags; /* group creation order flag */ + unsigned i; + unsigned u; + int is_ref = 0; + htri_t is_named; + hbool_t limit_maxdims; + hsize_t size_dset; + + /*------------------------------------------------------------------------- + * copy the suppplied object list + *------------------------------------------------------------------------- + */ + + if (options->verbose) { + printf("-----------------------------------------\n"); + printf(" Type Filter (Compression) Name\n"); + printf("-----------------------------------------\n"); + } + + for (i = 0; i < travt->nobjs; i++) { + /* init variables per obj */ + buf = NULL; + limit_maxdims = FALSE; + + switch (travt->objs[i].type) { + case H5TRAV_TYPE_UNKNOWN: + HDassert(0); + break; + + /*------------------------------------------------------------------------- + * H5TRAV_TYPE_GROUP + *------------------------------------------------------------------------- + */ + case H5TRAV_TYPE_GROUP: + if (options->verbose) + printf(FORMAT_OBJ, "group", travt->objs[i].name); + + /* open input group */ + if ((grp_in = H5Gopen2(fidin, travt->objs[i].name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gopen2 failed"); + + /* get input group creation property list */ + if ((gcpl_in = H5Gget_create_plist(grp_in)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gget_create_plist failed"); + + /* query and set the group creation properties */ + if (H5Pget_link_creation_order(gcpl_in, &crt_order_flags) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pget_link_creation_order failed"); + + /* set up group creation property list */ + if ((gcpl_out = H5Pcreate(H5P_GROUP_CREATE)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pcreate failed"); + + if (H5Pset_link_creation_order(gcpl_out, crt_order_flags) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pset_link_creation_order failed"); + + /*------------------------------------------------------------------------- + * the root is a special case, we get an ID for the root group + * and copy its attributes using that ID + *------------------------------------------------------------------------- + */ + if (HDstrcmp(travt->objs[i].name, "/") == 0) { + if ((grp_out = H5Gopen2(fidout, "/", H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gopen2 failed"); + } + else { + if (options->grp_compact > 0 || options->grp_indexed > 0) + if (H5Pset_link_phase_change(gcpl_out, (unsigned) options->grp_compact, (unsigned) options->grp_indexed) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pset_link_phase_change failed"); + + if ((grp_out = H5Gcreate2(fidout, travt->objs[i].name, H5P_DEFAULT, gcpl_out, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gcreate2 failed"); + } + + /*------------------------------------------------------------------------- + * copy attrs + *------------------------------------------------------------------------- + */ + if (copy_attr(grp_in, grp_out, &named_dt_head, travt, options) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_attr failed"); + + if (H5Pclose(gcpl_out) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + if (H5Pclose(gcpl_in) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + if (H5Gclose(grp_out) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gclose failed"); + if (H5Gclose(grp_in) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gclose failed"); + + break; + + /*------------------------------------------------------------------------- + * H5TRAV_TYPE_DATASET + *------------------------------------------------------------------------- + */ + case H5TRAV_TYPE_DATASET: + has_filter = 0; + req_filter = 0; + + /* check if global filters were requested */ + if (options->n_filter_g) + req_filter = 1; + + /* check if filters were requested for individual objects */ + for (u = 0; u < options->op_tbl->nelems; u++) + if (HDstrcmp(travt->objs[i].name, options->op_tbl->objs[u].path) == 0) + if (options->op_tbl->objs[u].filter->filtn > 0) + req_filter = 1; + + /* check if layout change requested individual object */ + if (options->layout_g != H5D_LAYOUT_ERROR) { + pack_info_t *pckinfo; + + /* any dataset is specified */ + if (options->op_tbl->nelems > 0) { + /* check if object exist */ + pckinfo = options_get_object(travt->objs[i].name, options->op_tbl); + if (pckinfo) + req_obj_layout = 1; + } + } + + /* early detection of references */ + if ((dset_in = H5Dopen2(fidin, travt->objs[i].name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dopen2 failed"); + if ((ftype_id = H5Dget_type(dset_in)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_type failed"); + if (H5T_REFERENCE == H5Tget_class(ftype_id)) + is_ref = 1; + + /* Check if the datatype is committed */ + if ((is_named = H5Tcommitted(ftype_id)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tcommitted failed"); + if (is_named) + if ((wtype_id = copy_named_datatype(ftype_id, fidout, &named_dt_head, travt, options)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_named_datatype failed"); + + if (H5Tclose(ftype_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); + if (H5Dclose(dset_in) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dclose failed"); + + /*------------------------------------------------------------------------- + * check if we should use H5Ocopy or not + * if there is a request for filters/layout, we read/write the object + * otherwise we do a copy using H5Ocopy + *------------------------------------------------------------------------- + */ + if (options->op_tbl->nelems || options->all_filter == 1 + || options->all_layout == 1 || is_ref || is_named) { + + int j; + + if ((dset_in = H5Dopen2(fidin, travt->objs[i].name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dopen2 failed"); + if ((f_space_id = H5Dget_space(dset_in)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_space failed"); + if ((ftype_id = H5Dget_type(dset_in)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_type failed"); + if ((dcpl_in = H5Dget_create_plist(dset_in)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_create_plist failed"); + if ((dcpl_out = H5Pcopy(dcpl_in)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pcopy failed"); + if ((rank = H5Sget_simple_extent_ndims(f_space_id)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sget_simple_extent_ndims failed"); + HDmemset(dims, 0, sizeof dims); + if (H5Sget_simple_extent_dims(f_space_id, dims, NULL) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sget_simple_extent_dims failed"); + if (H5Dget_space_status(dset_in, &space_status) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_space_status failed"); + + nelmts = 1; + for (j = 0; j < rank; j++) + nelmts *= dims[j]; + + /* wtype_id will have already been set if using a named dtype */ + if (!is_named) { + if (options->use_native == 1) + wtype_id = h5tools_get_native_type(ftype_id); + else + wtype_id = H5Tcopy(ftype_id); + } /* end if */ + + if ((msize = H5Tget_size(wtype_id)) == 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tget_size failed"); + + /* size of current dset */ + size_dset = nelmts * msize; + + /*------------------------------------------------------------------------- + * check if the dataset creation property list has filters that + * are not registered in the current configuration + * 1) the external filters GZIP and SZIP might not be available + * 2) the internal filters might be turned off + *------------------------------------------------------------------------- + */ + if (h5tools_canreadf((travt->objs[i].name), dcpl_in) == 1) { + apply_s = 1; + apply_f = 1; + + /*------------------------------------------------------------------------- + * references are a special case + * we cannot just copy the buffers, but instead we recreate the reference + * in a second traversal of the output file + *------------------------------------------------------------------------- + */ + if (H5T_REFERENCE != H5Tget_class(wtype_id)) { + /* get the storage size of the input dataset */ + dsize_in = H5Dget_storage_size(dset_in); + + /* check for small size datasets (less than 1k) except + * changing to COMPACT. For the reference, COMPACT is limited + * by size 64K by library. + */ + if (options->layout_g != H5D_COMPACT) + if (size_dset < options->min_comp) + apply_s = 0; + + /* apply the filter */ + if (apply_s) + if (apply_filters(travt->objs[i].name, rank, dims, msize, dcpl_out, options, &has_filter) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "apply_filters failed"); + + /* only if layout change requested for entire file or + * individual obj */ + if (options->all_layout > 0 || req_obj_layout == 1) + /*------------------------------------------------- + * Unset the unlimited max dims if convert to other + * than chunk layouts, because unlimited max dims + * only can be applied to chunk layout. + * Also perform only for targeted dataset + * Also check for size limit to convert to compact + *-------------------------------------------------*/ + if (options->layout_g != H5D_CHUNKED) { + /* any dataset is specified */ + if (options->op_tbl->nelems > 0) { + /* if current obj match specified obj */ + if (options_get_object(travt->objs[i].name, options->op_tbl)) + limit_maxdims = TRUE; + } + else /* no dataset is specified */ + limit_maxdims = TRUE; + + /* if convert to COMPACT */ + if (options->layout_g == H5D_COMPACT) + /* should be smaller than 64K */ + if (size_dset > MAX_COMPACT_DSIZE) + limit_maxdims = FALSE; + + /* unset unlimited max dims */ + if (limit_maxdims) + H5Sset_extent_simple(f_space_id, rank, dims, NULL); + } + + /*------------------------------------------------------------------------- + * create the output dataset; + * disable error checking in case the dataset cannot be created with the + * modified dcpl; in that case use the original instead + *------------------------------------------------------------------------- + */ + dset_out = H5Dcreate2(fidout, travt->objs[i].name, wtype_id, f_space_id, H5P_DEFAULT, dcpl_out, H5P_DEFAULT); + if (dset_out == FAIL) { + H5Epush2(H5tools_ERR_STACK_g, __FILE__, FUNC, __LINE__, H5tools_ERR_CLS_g, H5E_tools_g, H5E_tools_min_id_g, "H5Dcreate2 failed"); + if (options->verbose) + printf(" warning: could not create dataset <%s>. Applying original settings\n", travt->objs[i].name); + + if ((dset_out = H5Dcreate2(fidout, travt->objs[i].name, wtype_id, f_space_id, H5P_DEFAULT, dcpl_in, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dcreate2 failed"); + apply_f = 0; + } + + /*------------------------------------------------------------------------- + * read/write + *------------------------------------------------------------------------- + */ + if (nelmts > 0 && space_status != H5D_SPACE_STATUS_NOT_ALLOCATED) { + size_t need = (size_t)(nelmts * msize); /* bytes needed */ + + /* have to read the whole dataset if there is only one element in the dataset */ + if (need < H5TOOLS_MALLOCSIZE) + buf = HDmalloc(need); + + if (buf != NULL) { + /* read/write: use the macro to check error, e.g. memory allocation error inside the library. */ + CHECK_H5DRW_ERROR(H5Dread, FAIL, dset_in, wtype_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf); + CHECK_H5DRW_ERROR(H5Dwrite, FAIL, dset_out, wtype_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf); + + /* Check if we have VL data in the dataset's + * datatype that must be reclaimed */ + if (TRUE == H5Tdetect_class(wtype_id, H5T_VLEN)) + if (H5Dvlen_reclaim(wtype_id, f_space_id, H5P_DEFAULT, buf) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dvlen_reclaim failed"); + } + else { /* possibly not enough memory, read/write by hyperslabs */ + size_t p_type_nbytes = msize; /*size of memory type */ + hsize_t p_nelmts = nelmts; /*total elements */ + hsize_t elmtno; /*counter */ + int carry; /*counter carry value */ + unsigned int vl_data = 0; /*contains VL datatypes */ + + /* hyperslab info */ + hsize_t hslab_dims[H5S_MAX_RANK]; /*hyperslab dims */ + hsize_t hslab_nbytes; /*bytes per hyperslab */ + hsize_t hslab_nelmts; /*elements per hyperslab*/ + hid_t hslab_space; /*hyperslab data space */ + + /* hyperslab selection info */ + hsize_t hs_sel_offset[H5S_MAX_RANK];/* selection offset */ + hsize_t hs_sel_count[H5S_MAX_RANK]; /* selection count */ + hsize_t hs_select_nelmts; /* selected elements */ + hsize_t zero[8]; /*vector of zeros */ + int k; + H5D_layout_t dset_layout; + hid_t dcpl_tmp = -1; /* dataset creation property list ID */ + + /* check if we have VL data in the dataset's datatype */ + if (H5Tdetect_class(wtype_id, H5T_VLEN) == TRUE) + vl_data = TRUE; + + /* check first if writing dataset is chunked, + * if so use its chunk layout for better performance. */ + dset_layout = H5Pget_layout(dcpl_out); + if (dset_layout == H5D_CHUNKED) + dcpl_tmp = dcpl_out; /* writing dataset */ + else { /* if reading dataset is chunked */ + dset_layout = H5Pget_layout(dcpl_in); + if (dset_layout == H5D_CHUNKED) + dcpl_tmp = dcpl_in; /* reading dataset */ + } + + /* get hyperslab dims and size in byte */ + if (Get_hyperslab(dcpl_tmp, rank, dims, p_type_nbytes, hslab_dims, &hslab_nbytes) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "Get_hyperslab failed"); + + hslab_buf = HDmalloc((size_t)hslab_nbytes); + + hslab_nelmts = hslab_nbytes / p_type_nbytes; + hslab_space = H5Screate_simple(1, &hslab_nelmts, NULL); + + /* the hyperslab selection loop */ + HDmemset(hs_sel_offset, 0, sizeof hs_sel_offset); + HDmemset(zero, 0, sizeof zero); + + for (elmtno = 0; elmtno < p_nelmts; elmtno += hs_select_nelmts) { + if (rank > 0) { + /* calculate the hyperslab selections. + * The selection would be same as the hyperslab + * except for remaining edge portion of the dataset + * which is smaller then the hyperslab. + */ + for (k = 0, hs_select_nelmts = 1; k < rank; k++) { + /* MIN() is used to get the remaining edge portion if exist. + * "dims[k] - hs_sel_offset[k]" is remaining edge portion that is smaller then the hyperslab.*/ + hs_sel_count[k] = MIN(dims[k] - hs_sel_offset[k], hslab_dims[k]); + hs_select_nelmts *= hs_sel_count[k]; + } + + if (H5Sselect_hyperslab(f_space_id, H5S_SELECT_SET, hs_sel_offset, NULL, hs_sel_count, NULL) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sselect_hyperslab failed"); + if (H5Sselect_hyperslab(hslab_space, H5S_SELECT_SET, zero, NULL, &hs_select_nelmts, NULL) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sselect_hyperslab failed"); + } + else { + H5Sselect_all(f_space_id); + H5Sselect_all(hslab_space); + hs_select_nelmts = 1; + } /* rank */ + + /* read/write: use the macro to check error, e.g. memory allocation error inside the library. */ + CHECK_H5DRW_ERROR(H5Dread, FAIL, dset_in, wtype_id, hslab_space, f_space_id, H5P_DEFAULT, hslab_buf); + CHECK_H5DRW_ERROR(H5Dwrite, FAIL, dset_out, wtype_id, hslab_space, f_space_id, H5P_DEFAULT, hslab_buf); + + /* reclaim any VL memory, if necessary */ + if (vl_data) + H5Dvlen_reclaim(wtype_id, hslab_space, H5P_DEFAULT, hslab_buf); + + /* calculate the next hyperslab offset */ + for (k = rank, carry = 1; k > 0 && carry; --k) { + hs_sel_offset[k - 1] += hs_sel_count[k - 1]; + /* if reached the end of a dim */ + if (hs_sel_offset[k - 1] == dims[k - 1]) + hs_sel_offset[k - 1] = 0; + else + carry = 0; + } /* k */ + } /* elmtno */ + + H5Sclose(hslab_space); + /* free */ + if (hslab_buf != NULL) { + HDfree(hslab_buf); + hslab_buf = NULL; + } + } /* hyperslab read */ + } /* if (nelmts>0 && space_status==H5D_SPACE_STATUS_NOT_ALLOCATED) */ + + /*------------------------------------------------------------------------- + * amount of compression used + *------------------------------------------------------------------------- + */ + if (options->verbose) { + double ratio = 0; + + /* only print the compression ration if there was a filter request */ + if (apply_s && apply_f && req_filter) { + /* get the storage size of the output dataset */ + dsize_out = H5Dget_storage_size(dset_out); + + /* compression ratio = uncompressed size / compressed size */ + if (dsize_out != 0) + ratio = (double) dsize_in / (double) dsize_out; + print_dataset_info(dcpl_out, travt->objs[i].name, ratio, 1); + } + else + print_dataset_info(dcpl_in, travt->objs[i].name, ratio, 0); + + /* print a message that the filter was not applied + (in case there was a filter) + */ + if (has_filter && apply_s == 0) + printf(" <warning: filter not applied to %s. dataset smaller than %d bytes>\n", travt->objs[i].name, (int) options->min_comp); + + if (has_filter && apply_f == 0) + printf(" <warning: could not apply the filter to %s>\n", travt->objs[i].name); + } /* verbose */ + + /*------------------------------------------------------------------------- + * copy attrs + *------------------------------------------------------------------------- + */ + if (copy_attr(dset_in, dset_out, &named_dt_head, travt, options) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_attr failed"); + + /*close */ + if (H5Dclose(dset_out) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dclose failed"); + }/*!H5T_REFERENCE*/ + }/*h5tools_canreadf*/ + + /*------------------------------------------------------------------------- + * close + *------------------------------------------------------------------------- + */ + if (H5Tclose(ftype_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); + if (H5Tclose(wtype_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); + if (H5Pclose(dcpl_in) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + if (H5Pclose(dcpl_out) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + if (H5Sclose(f_space_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sclose failed"); + if (H5Dclose(dset_in) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dclose failed"); + } + /*------------------------------------------------------------------------- + * we do not have request for filter/chunking use H5Ocopy instead + *------------------------------------------------------------------------- + */ + else { + hid_t pid; + + /* create property to pass copy options */ + if ((pid = H5Pcreate(H5P_OBJECT_COPY)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pcreate failed"); + + /* set options for object copy */ + if (H5Pset_copy_object(pid, H5O_COPY_WITHOUT_ATTR_FLAG) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pset_copy_object failed"); + + /*------------------------------------------------------------------------- + * do the copy + *------------------------------------------------------------------------- + */ + + if (H5Ocopy(fidin, /* Source file or group identifier */ + travt->objs[i].name, /* Name of the source object to be copied */ + fidout, /* Destination file or group identifier */ + travt->objs[i].name, /* Name of the destination object */ + pid, /* Properties which apply to the copy */ + H5P_DEFAULT) < 0) /* Properties which apply to the new hard link */ + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Ocopy failed"); + + /* close property */ + if (H5Pclose(pid) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + + /*------------------------------------------------------------------------- + * copy attrs manually + *------------------------------------------------------------------------- + */ + if ((dset_in = H5Dopen2(fidin, travt->objs[i].name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dopen2 failed"); + if ((dset_out = H5Dopen2(fidout, travt->objs[i].name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dopen2 failed"); + if (copy_attr(dset_in, dset_out, &named_dt_head, travt, options) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_attr failed"); + if (H5Dclose(dset_in) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dclose failed"); + if (H5Dclose(dset_out) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dclose failed"); + + if (options->verbose) + printf(FORMAT_OBJ, "dset", travt->objs[i].name); + + } /* end do we have request for filter/chunking */ + break; + + /*------------------------------------------------------------------------- + * H5TRAV_TYPE_NAMED_DATATYPE + *------------------------------------------------------------------------- + */ + case H5TRAV_TYPE_NAMED_DATATYPE: + if (options->verbose) + printf(FORMAT_OBJ, "type", travt->objs[i].name); + + if ((type_in = H5Topen2(fidin, travt->objs[i].name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Topen2 failed"); + + /* Copy the datatype anonymously */ + if ((type_out = copy_named_datatype(type_in, fidout, &named_dt_head, travt, options)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_named_datatype failed"); + + /* Link in to group structure */ + if (H5Lcreate_hard(type_out, ".", fidout, travt->objs[i].name, H5P_DEFAULT, H5P_DEFAULT) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Lcreate_hard failed"); + + /*------------------------------------------------------------------------- + * copy attrs + *------------------------------------------------------------------------- + */ + if (copy_attr(type_in, type_out, &named_dt_head, travt, options) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_attr failed"); + + if (H5Tclose(type_in) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); + if (H5Tclose(type_out) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); + + break; + + /*------------------------------------------------------------------------- + * H5TRAV_TYPE_LINK + * H5TRAV_TYPE_UDLINK + * + * Only handles external links; H5Lcopy will fail for other UD link types + * since we don't have creation or copy callbacks for them. + *------------------------------------------------------------------------- + */ + case H5TRAV_TYPE_LINK: + case H5TRAV_TYPE_UDLINK: + if (options->verbose) + printf(FORMAT_OBJ, "link", travt->objs[i].name); + + if (H5Lcopy(fidin, travt->objs[i].name, fidout, travt->objs[i].name, H5P_DEFAULT, H5P_DEFAULT) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Lcopy failed"); + + if (options->verbose) + printf(FORMAT_OBJ, "link", travt->objs[i].name); + break; + + default: + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "Object type not found"); + } /* switch */ + + /* free */ + if (buf != NULL) { + HDfree(buf); + buf = NULL; + } + } /* i */ + + /* Finalize (link) the stack of named datatypes (if any) */ + named_datatype_free(&named_dt_head, 0); + + return ret_value; + +done: + H5E_BEGIN_TRY + { + H5Gclose(grp_in); + H5Gclose(grp_out); + H5Pclose(dcpl_in); + H5Pclose(gcpl_in); + H5Pclose(gcpl_out); + H5Sclose(f_space_id); + H5Dclose(dset_in); + H5Dclose(dset_out); + H5Tclose(ftype_id); + H5Tclose(wtype_id); + H5Tclose(type_in); + H5Tclose(type_out); + named_datatype_free(&named_dt_head, 1); + }H5E_END_TRY; + + /* free */ + if (buf != NULL) + HDfree(buf); + if (hslab_buf != NULL) + HDfree(hslab_buf); + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: print_dataset_info + * + * Purpose: print name, filters, percentage compression of a dataset + * + *------------------------------------------------------------------------- + */ +static void print_dataset_info(hid_t dcpl_id, char *objname, double ratio, + int pr) +{ + char strfilter[255]; +#if defined (PRINT_DEBUG ) + char temp[255]; +#endif + int nfilters; /* number of filters */ + unsigned filt_flags; /* filter flags */ + H5Z_filter_t filtn; /* filter identification number */ + unsigned cd_values[20]; /* filter client data values */ + size_t cd_nelmts; /* filter client number of values */ + char f_objname[256]; /* filter objname */ + int i; + + HDstrcpy(strfilter, "\0"); + + /* get information about input filters */ + if ((nfilters = H5Pget_nfilters(dcpl_id)) < 0) + return; + + for (i = 0; i < nfilters; i++) { + cd_nelmts = NELMTS(cd_values); + + filtn = H5Pget_filter2(dcpl_id, (unsigned) i, &filt_flags, &cd_nelmts, + cd_values, sizeof(f_objname), f_objname, NULL); + + switch (filtn) { + case H5Z_FILTER_NONE: + HDstrcat(strfilter, "NONE "); + break; + + case H5Z_FILTER_DEFLATE: + HDstrcat(strfilter, "GZIP "); + +#if defined (PRINT_DEBUG) + { + unsigned level = cd_values[0]; + + sprintf(temp,"(%d)", level); + HDstrcat(strfilter, temp); + } +#endif + break; + + case H5Z_FILTER_SZIP: + HDstrcat(strfilter, "SZIP "); + +#if defined (PRINT_DEBUG) + { + unsigned options_mask = cd_values[0]; /* from dcpl, not filt*/ + unsigned ppb = cd_values[1]; + + sprintf(temp,"(%d,", ppb); + HDstrcat(strfilter, temp); + if (options_mask & H5_SZIP_EC_OPTION_MASK) + HDstrcpy(temp, "EC) "); + else if (options_mask & H5_SZIP_NN_OPTION_MASK) + HDstrcpy(temp, "NN) "); + } + HDstrcat(strfilter, temp); +#endif + break; + + case H5Z_FILTER_SHUFFLE: + HDstrcat(strfilter, "SHUF "); + break; + + case H5Z_FILTER_FLETCHER32: + HDstrcat(strfilter, "FLET "); + break; + + case H5Z_FILTER_NBIT: + HDstrcat(strfilter, "NBIT "); + break; + + case H5Z_FILTER_SCALEOFFSET: + HDstrcat(strfilter, "SCALEOFFSET "); + break; + + default: + HDstrcat(strfilter, "UD "); + break; + } /* switch */ + }/*i*/ + + if (!pr) + printf(FORMAT_OBJ, "dset", objname); + else { + char str[255], temp[28]; + + HDstrcpy(str, "dset "); + HDstrcat(str, strfilter); + sprintf(temp, " (%.3f:1)", ratio); + HDstrcat(str, temp); + printf(FORMAT_OBJ, str, objname); + } +} + +/*------------------------------------------------------------------------- + * Function: copy_user_block + * + * Purpose: copy user block from one file to another + * + * Return: 0, ok, -1 no + * + * Programmer: Peter Cao + * + * Date: October, 25, 2007 + * + *------------------------------------------------------------------------- + */ +static int copy_user_block(const char *infile, const char *outfile, + hsize_t size) +{ + int ret_value = 0; /*no need to LEAVE() on ERROR: HERR_INIT(int, SUCCEED) */ + int infid = -1, outfid = -1; /* File descriptors */ + + /* User block must be any power of 2 equal to 512 or greater (512, 1024, 2048, etc.) */ + HDassert(size > 0); + + /* Open files */ + if ((infid = HDopen(infile, O_RDONLY, 0)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDopen failed"); + if ((outfid = HDopen(outfile, O_WRONLY, 0644)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDopen failed"); + + /* Copy the userblock from the input file to the output file */ + while (size > 0) { + ssize_t nread, nbytes; /* # of bytes transfered, etc. */ + char rbuf[USERBLOCK_XFER_SIZE]; /* Buffer for reading */ + const char *wbuf; /* Pointer into buffer, for writing */ + + /* Read buffer from source file */ + if (size > USERBLOCK_XFER_SIZE) + nread = HDread(infid, rbuf, (size_t)USERBLOCK_XFER_SIZE); + else + nread = HDread(infid, rbuf, (size_t)size); + if (nread < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDread failed"); + + /* Write buffer to destination file */ + /* (compensating for interrupted writes & checking for errors, etc.) */ + nbytes = nread; + wbuf = rbuf; + while (nbytes > 0) { + ssize_t nwritten; /* # of bytes written */ + + do { + nwritten = HDwrite(outfid, wbuf, (size_t)nbytes); + } while (-1 == nwritten && EINTR == errno); + if (-1 == nwritten) /* error */ + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDwrite failed"); + HDassert(nwritten > 0); + HDassert(nwritten <= nbytes); + + /* Update # of bytes left & offset in buffer */ + nbytes -= nwritten; + wbuf += nwritten; + HDassert(nbytes == 0 || wbuf < (rbuf + USERBLOCK_XFER_SIZE)); + } /* end while */ + + /* Update size of userblock left to transfer */ + size = size - (hsize_t) nread; + } /* end while */ + +done: + if (infid > 0) + HDclose(infid); + if (outfid > 0) + HDclose(outfid); + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: print_user_block + * + * Purpose: print user block + * + * Return: 0, ok, -1 no + * + * Programmer: Pedro Vicente + * + * Date: August, 20, 2008 + * + *------------------------------------------------------------------------- + */ +#if defined (H5REPACK_DEBUG_USER_BLOCK) +static +void print_user_block(const char *filename, hid_t fid) +{ + int ret_value = 0; /*no need to LEAVE() on ERROR: HERR_INIT(int, SUCCEED) */ + int fh; /* file handle */ + hsize_t ub_size; /* user block size */ + hsize_t size; /* size read */ + hid_t fcpl; /* file creation property list ID for HDF5 file */ + int i; + + /* get user block size */ + if(( fcpl = H5Fget_create_plist(fid)) < 0) { + error_msg("failed to retrieve file creation property list\n"); + HGOTO_ERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Fget_create_plist failed"); + } + + if(H5Pget_userblock(fcpl, &ub_size) < 0) { + error_msg("failed to retrieve userblock size\n"); + HGOTO_ERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Pget_userblock failed"); + } + + if(H5Pclose(fcpl) < 0) { + error_msg("failed to close property list\n"); + HGOTO_ERROR(H5E_tools_g, H5E_tools_min_id_g, "H5Pclose failed"); + } + + /* open file */ + if((fh = HDopen(filename, O_RDONLY, 0)) < 0) { + HGOTO_ERROR(H5E_tools_g, H5E_tools_min_id_g, "HDopen failed"); + } + + size = ub_size; + + /* read file */ + while(size > 0) { + ssize_t nread; /* # of bytes read */ + char rbuf[USERBLOCK_XFER_SIZE]; /* buffer for reading */ + + /* read buffer */ + if(size > USERBLOCK_XFER_SIZE) + nread = HDread(fh, rbuf, (size_t)USERBLOCK_XFER_SIZE); + else + nread = HDread(fh, rbuf, (size_t)size); + + for(i = 0; i < nread; i++) { + + printf("%c ", rbuf[i]); + + } + printf("\n"); + + if(nread < 0) { + HGOTO_ERROR(H5E_tools_g, H5E_tools_min_id_g, "nread < 0"); + } + + /* update size of userblock left to transfer */ + size -= nread; + } + +done: + if(fh > 0) + HDclose(fh); + + return; +} +#endif + diff --git a/tools/src/h5repack/h5repack_filters.c b/tools/src/h5repack/h5repack_filters.c new file mode 100644 index 0000000..e21b829 --- /dev/null +++ b/tools/src/h5repack/h5repack_filters.c @@ -0,0 +1,493 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "h5repack.h" +#include "h5tools.h" +#include "h5tools_utils.h" + +/* number of members in an array */ +#ifndef NELMTS +# define NELMTS(X) (sizeof(X)/sizeof(X[0])) +#endif + +/* minimum of two values */ +#undef MIN +#define MIN(a,b) (((a)<(b)) ? (a) : (b)) + +/*------------------------------------------------------------------------- + * Function: aux_find_obj + * + * Purpose: find the object name NAME (got from the traverse list) + * in the repack options list + * + *------------------------------------------------------------------------- + */ +static int +aux_find_obj(const char* name, /* object name from traverse list */ + pack_opt_t *options, /* repack options */ + pack_info_t *obj /*OUT*/) /* info about object to filter */ +{ + char *pdest; + int result; + unsigned int i; + + for ( i=0; i<options->op_tbl->nelems; i++) + { + if (HDstrcmp(options->op_tbl->objs[i].path,name)==0) + { + *obj = options->op_tbl->objs[i]; + return (int)i; + } + + pdest = HDstrstr(name,options->op_tbl->objs[i].path); + result = (int)(pdest - name); + + /* found at position 1, meaning without '/' */ + if( pdest != NULL && result==1 ) + { + *obj = options->op_tbl->objs[i]; + return (int)i; + } + }/*i*/ + + return -1; +} + + +/*------------------------------------------------------------------------- + * Function: aux_assign_obj + * + * Purpose: find the object name NAME (got from the traverse list) + * in the repack options list; assign the filter information OBJ + * + * Return: 0 not found, 1 found + * + *------------------------------------------------------------------------- + */ +static int +aux_assign_obj(const char* name, /* object name from traverse list */ + pack_opt_t *options, /* repack options */ + pack_info_t *obj /*OUT*/) /* info about object to filter */ +{ + + int idx, i; + pack_info_t tmp; + + init_packobject(&tmp); + + idx = aux_find_obj(name,options,&tmp); + + /* name was on input */ + if (idx>=0) + { + + + /* applying to all objects */ + if (options->all_layout) + { + /* assign the global layout info to the OBJ info */ + tmp.layout=options->layout_g; + switch (options->layout_g) + { + case H5D_CHUNKED: + tmp.chunk.rank=options->chunk_g.rank; + for ( i=0; i<tmp.chunk.rank; i++) + tmp.chunk.chunk_lengths[i]=options->chunk_g.chunk_lengths[i]; + break; + case H5D_LAYOUT_ERROR: + case H5D_COMPACT: + case H5D_CONTIGUOUS: + case H5D_VIRTUAL: + case H5D_NLAYOUTS: + break; + default: + break; + }/*switch*/ + } + else + { + tmp.layout = options->op_tbl->objs[idx].layout; + switch (tmp.layout) + { + case H5D_CHUNKED: + tmp.chunk.rank = options->op_tbl->objs[idx].chunk.rank; + for ( i=0; i<tmp.chunk.rank; i++) + tmp.chunk.chunk_lengths[i]=options->op_tbl->objs[idx].chunk.chunk_lengths[i]; + break; + case H5D_LAYOUT_ERROR: + case H5D_COMPACT: + case H5D_CONTIGUOUS: + case H5D_VIRTUAL: + case H5D_NLAYOUTS: + break; + default: + break; + }/*switch*/ + + } + + /* applying to all objects */ + if (options->all_filter) + { + /* assign the global filter */ + tmp.nfilters=1; + tmp.filter[0]=options->filter_g[0]; + } /* if all */ + else + { + tmp.nfilters=options->op_tbl->objs[idx].nfilters; + for ( i=0; i<tmp.nfilters; i++) + { + tmp.filter[i] = options->op_tbl->objs[idx].filter[i]; + } + } + + + } /* if idx */ + + + /* no input name */ + + else + { + + if (options->all_filter) + { + int k; + + /* assign the global filters */ + tmp.nfilters=options->n_filter_g; + for ( k = 0; k < options->n_filter_g; k++) + tmp.filter[k]=options->filter_g[k]; + } + if (options->all_layout) + { + /* assign the global layout info to the OBJ info */ + tmp.layout=options->layout_g; + switch (options->layout_g) + { + case H5D_CHUNKED: + tmp.chunk.rank=options->chunk_g.rank; + for ( i=0; i<tmp.chunk.rank; i++) + tmp.chunk.chunk_lengths[i]=options->chunk_g.chunk_lengths[i]; + break; + case H5D_LAYOUT_ERROR: + case H5D_COMPACT: + case H5D_CONTIGUOUS: + case H5D_VIRTUAL: + case H5D_NLAYOUTS: + break; + default: + break; + }/*switch*/ + } + } + + *obj = tmp; + return 1; + +} + + +/*------------------------------------------------------------------------- + * Function: apply_filters + * + * Purpose: apply the filters in the object to the property list; + * do extra checking in the case of SZIP; delete all filters in the case + * of H5Z_FILTER_NONE present in the PACK_INFO_T filter array + * + * Return: 0 success, -1 an error occured + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: December 19, 2003 + * + *------------------------------------------------------------------------- + */ + +int apply_filters(const char* name, /* object name from traverse list */ + int rank, /* rank of dataset */ + hsize_t *dims, /* dimensions of dataset */ + size_t msize, /* size of type */ + hid_t dcpl_id, /* dataset creation property list */ + pack_opt_t *options, /* repack options */ + int *has_filter) /* (OUT) object NAME has a filter */ + + +{ + int nfilters; /* number of filters in DCPL */ + hsize_t chsize[64]; /* chunk size in elements */ + H5D_layout_t layout; + int i; + pack_info_t obj; + + *has_filter = 0; + + if (rank==0) /* scalar dataset, do not apply */ + return 0; + + /*------------------------------------------------------------------------- + * initialize the assigment object + *------------------------------------------------------------------------- + */ + init_packobject(&obj); + + /*------------------------------------------------------------------------- + * find options + *------------------------------------------------------------------------- + */ + if (aux_assign_obj(name,options,&obj)==0) + return 0; + + /* get information about input filters */ + if ((nfilters = H5Pget_nfilters(dcpl_id))<0) + return -1; + + /*------------------------------------------------------------------------- + * check if we have filters in the pipeline + * we want to replace them with the input filters + * only remove if we are inserting new ones + *------------------------------------------------------------------------- + */ + if (nfilters && obj.nfilters ) + { + *has_filter = 1; + if (H5Premove_filter(dcpl_id,H5Z_FILTER_ALL)<0) + return -1; + } + + /*------------------------------------------------------------------------- + * check if there is an existent chunk + * read it only if there is not a requested layout + *------------------------------------------------------------------------- + */ + if (obj.layout == -1 ) + { + if ((layout = H5Pget_layout(dcpl_id))<0) + return -1; + + if (layout == H5D_CHUNKED) + { + if ((rank = H5Pget_chunk(dcpl_id,NELMTS(chsize),chsize/*out*/))<0) + return -1; + obj.layout = H5D_CHUNKED; + obj.chunk.rank = rank; + for ( i = 0; i < rank; i++) + obj.chunk.chunk_lengths[i] = chsize[i]; + } + } + + /*------------------------------------------------------------------------- + * the type of filter and additional parameter + * type can be one of the filters + * H5Z_FILTER_NONE 0 , uncompress if compressed + * H5Z_FILTER_DEFLATE 1 , deflation like gzip + * H5Z_FILTER_SHUFFLE 2 , shuffle the data + * H5Z_FILTER_FLETCHER32 3 , fletcher32 checksum of EDC + * H5Z_FILTER_SZIP 4 , szip compression + * H5Z_FILTER_NBIT 5 , nbit compression + * H5Z_FILTER_SCALEOFFSET 6 , scaleoffset compression + *------------------------------------------------------------------------- + */ + + if (obj.nfilters) + { + + /*------------------------------------------------------------------------- + * filters require CHUNK layout; if we do not have one define a default + *------------------------------------------------------------------------- + */ + if (obj.layout==-1) + { + + /* stripmine info */ + hsize_t sm_size[H5S_MAX_RANK]; /*stripmine size */ + hsize_t sm_nbytes; /*bytes per stripmine */ + + obj.chunk.rank = rank; + + /* + * determine the strip mine size. The strip mine is + * a hyperslab whose size is manageable. + */ + + + + sm_nbytes = msize; + for ( i = rank; i > 0; --i) + { + hsize_t size = H5TOOLS_BUFSIZE / sm_nbytes; + if ( size == 0) /* datum size > H5TOOLS_BUFSIZE */ + size = 1; + sm_size[i - 1] = MIN(dims[i - 1], size); + sm_nbytes *= sm_size[i - 1]; + HDassert(sm_nbytes > 0); + + } + + for ( i = 0; i < rank; i++) + { + obj.chunk.chunk_lengths[i] = sm_size[i]; + } + + } + + for ( i=0; i<obj.nfilters; i++) + { + switch (obj.filter[i].filtn) + { + + /*------------------------------------------------------------------------- + * H5Z_FILTER_NONE 0 , uncompress if compressed + *------------------------------------------------------------------------- + */ + case H5Z_FILTER_NONE: + break; + + /*------------------------------------------------------------------------- + * H5Z_FILTER_DEFLATE 1 , deflation like gzip + *------------------------------------------------------------------------- + */ + case H5Z_FILTER_DEFLATE: + { + unsigned aggression; /* the deflate level */ + + aggression = obj.filter[i].cd_values[0]; + /* set up for deflated data */ + if(H5Pset_chunk(dcpl_id, obj.chunk.rank, obj.chunk.chunk_lengths)<0) + return -1; + if(H5Pset_deflate(dcpl_id,aggression)<0) + return -1; + } + break; + + /*------------------------------------------------------------------------- + * H5Z_FILTER_SZIP 4 , szip compression + *------------------------------------------------------------------------- + */ + case H5Z_FILTER_SZIP: + { + unsigned options_mask; + unsigned pixels_per_block; + + options_mask = obj.filter[i].cd_values[0]; + pixels_per_block = obj.filter[i].cd_values[1]; + + /* set up for szip data */ + if(H5Pset_chunk(dcpl_id,obj.chunk.rank,obj.chunk.chunk_lengths)<0) + return -1; + if (H5Pset_szip(dcpl_id,options_mask,pixels_per_block)<0) + return -1; + + } + break; + + /*------------------------------------------------------------------------- + * H5Z_FILTER_SHUFFLE 2 , shuffle the data + *------------------------------------------------------------------------- + */ + case H5Z_FILTER_SHUFFLE: + if(H5Pset_chunk(dcpl_id, obj.chunk.rank, obj.chunk.chunk_lengths)<0) + return -1; + if (H5Pset_shuffle(dcpl_id)<0) + return -1; + break; + + /*------------------------------------------------------------------------- + * H5Z_FILTER_FLETCHER32 3 , fletcher32 checksum of EDC + *------------------------------------------------------------------------- + */ + case H5Z_FILTER_FLETCHER32: + if(H5Pset_chunk(dcpl_id, obj.chunk.rank, obj.chunk.chunk_lengths)<0) + return -1; + if (H5Pset_fletcher32(dcpl_id)<0) + return -1; + break; + /*----------- ------------------------------------------------------------- + * H5Z_FILTER_NBIT , NBIT compression + *------------------------------------------------------------------------- + */ + case H5Z_FILTER_NBIT: + if(H5Pset_chunk(dcpl_id, obj.chunk.rank, obj.chunk.chunk_lengths)<0) + return -1; + if (H5Pset_nbit(dcpl_id)<0) + return -1; + break; + /*----------- ------------------------------------------------------------- + * H5Z_FILTER_SCALEOFFSET , scale+offset compression + *------------------------------------------------------------------------- + */ + + case H5Z_FILTER_SCALEOFFSET: + { + H5Z_SO_scale_type_t scale_type; + int scale_factor; + + scale_type = (H5Z_SO_scale_type_t)obj.filter[i].cd_values[0]; + scale_factor = (int)obj.filter[i].cd_values[1]; + + if(H5Pset_chunk(dcpl_id, obj.chunk.rank, obj.chunk.chunk_lengths)<0) + return -1; + if (H5Pset_scaleoffset(dcpl_id,scale_type,scale_factor)<0) + return -1; + } + break; + default: + { + if (H5Pset_filter (dcpl_id, obj.filter[i].filtn, H5Z_FLAG_MANDATORY, obj.filter[i].cd_nelmts, obj.filter[i].cd_values)<0) + return -1; + if(H5Pset_chunk(dcpl_id, obj.chunk.rank, obj.chunk.chunk_lengths)<0) + return -1; + } + break; + } /* switch */ + }/*i*/ + + } + /*obj.nfilters*/ + + /*------------------------------------------------------------------------- + * layout + *------------------------------------------------------------------------- + */ + + if (obj.layout>=0) + { + /* a layout was defined */ + if (H5Pset_layout(dcpl_id, obj.layout)<0) + return -1; + + if (H5D_CHUNKED == obj.layout) + { + if(H5Pset_chunk(dcpl_id, obj.chunk.rank, obj.chunk.chunk_lengths)<0) + return -1; + } + else if (H5D_COMPACT == obj.layout) + { + if (H5Pset_alloc_time(dcpl_id, H5D_ALLOC_TIME_EARLY)<0) + return -1; + } + /* remove filters for the H5D_CONTIGUOUS case */ + else if (H5D_CONTIGUOUS == obj.layout) + { + if (H5Premove_filter(dcpl_id,H5Z_FILTER_ALL)<0) + return -1; + } + + } + + return 0; +} + diff --git a/tools/src/h5repack/h5repack_main.c b/tools/src/h5repack/h5repack_main.c new file mode 100644 index 0000000..2d48a04 --- /dev/null +++ b/tools/src/h5repack/h5repack_main.c @@ -0,0 +1,664 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "h5tools.h" +#include "h5tools_utils.h" +#include "h5repack.h" + +/* Name of tool */ +#define PROGRAMNAME "h5repack" + +static int parse_command_line(int argc, const char **argv, pack_opt_t* options); +static void leave(int ret) H5_ATTR_NORETURN; + + +/* module-scoped variables */ +static int has_i_o = 0; +const char *infile = NULL; +const char *outfile = NULL; + +/* + * Command-line options: The user can specify short or long-named + * parameters. + */ +static const char *s_opts = "hVvf:l:m:e:nLc:d:s:u:b:M:t:a:i:o:S:T:E"; +static struct long_options l_opts[] = { + { "help", no_arg, 'h' }, + { "version", no_arg, 'V' }, + { "verbose", no_arg, 'v' }, + { "filter", require_arg, 'f' }, + { "layout", require_arg, 'l' }, + { "minimum", require_arg, 'm' }, + { "file", require_arg, 'e' }, + { "native", no_arg, 'n' }, + { "latest", no_arg, 'L' }, + { "compact", require_arg, 'c' }, + { "indexed", require_arg, 'd' }, + { "ssize", require_arg, 's' }, + { "ublock", require_arg, 'u' }, + { "block", require_arg, 'b' }, + { "metadata_block_size", require_arg, 'M' }, + { "threshold", require_arg, 't' }, + { "alignment", require_arg, 'a' }, + { "infile", require_arg, 'i' }, /* -i for backward compability */ + { "outfile", require_arg, 'o' }, /* -o for backward compability */ + { "fs_strategy", require_arg, 'S' }, + { "fs_threshold", require_arg, 'T' }, + { "enable-error-stack", no_arg, 'E' }, + { NULL, 0, '\0' } +}; + +/*------------------------------------------------------------------------- + * Function: usage + * + * Purpose: print usage + * + * Return: void + * + *------------------------------------------------------------------------- + */ +static void usage(const char *prog) { + FLUSHSTREAM(rawoutstream); + PRINTSTREAM(rawoutstream, "usage: %s [OPTIONS] file1 file2\n", prog); + PRINTVALSTREAM(rawoutstream, " file1 Input HDF5 File\n"); + PRINTVALSTREAM(rawoutstream, " file2 Output HDF5 File\n"); + PRINTVALSTREAM(rawoutstream, " OPTIONS\n"); + PRINTVALSTREAM(rawoutstream, " -h, --help Print a usage message and exit\n"); + PRINTVALSTREAM(rawoutstream, " -v, --verbose Verbose mode, print object information\n"); + PRINTVALSTREAM(rawoutstream, " -V, --version Print version number and exit\n"); + PRINTVALSTREAM(rawoutstream, " -n, --native Use a native HDF5 type when repacking\n"); + PRINTVALSTREAM(rawoutstream, " -L, --latest Use latest version of file format\n"); + PRINTVALSTREAM(rawoutstream, " -c L1, --compact=L1 Maximum number of links in header messages\n"); + PRINTVALSTREAM(rawoutstream, " -d L2, --indexed=L2 Minimum number of links in the indexed format\n"); + PRINTVALSTREAM(rawoutstream, " -s S[:F], --ssize=S[:F] Shared object header message minimum size\n"); + PRINTVALSTREAM(rawoutstream, " -m M, --minimum=M Do not apply the filter to datasets smaller than M\n"); + PRINTVALSTREAM(rawoutstream, " -e E, --file=E Name of file E with the -f and -l options\n"); + PRINTVALSTREAM(rawoutstream, " -u U, --ublock=U Name of file U with user block data to be added\n"); + PRINTVALSTREAM(rawoutstream, " -b B, --block=B Size of user block to be added\n"); + PRINTVALSTREAM(rawoutstream, " -M A, --metadata_block_size=A Metadata block size for H5Pset_meta_block_size\n"); + PRINTVALSTREAM(rawoutstream, " -t T, --threshold=T Threshold value for H5Pset_alignment\n"); + PRINTVALSTREAM(rawoutstream, " -a A, --alignment=A Alignment value for H5Pset_alignment\n"); + PRINTVALSTREAM(rawoutstream, " -f FILT, --filter=FILT Filter type\n"); + PRINTVALSTREAM(rawoutstream, " -l LAYT, --layout=LAYT Layout type\n"); + PRINTVALSTREAM(rawoutstream, " -S FS_STRGY, --fs_strategy=FS_STRGY File space management strategy\n"); + PRINTVALSTREAM(rawoutstream, " -T FS_THRD, --fs_threshold=FS_THRD Free-space section threshold\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " M - is an integer greater than 1, size of dataset in bytes (default is 0) \n"); + PRINTVALSTREAM(rawoutstream, " E - is a filename.\n"); + PRINTVALSTREAM(rawoutstream, " S - is an integer\n"); + PRINTVALSTREAM(rawoutstream, " U - is a filename.\n"); + PRINTVALSTREAM(rawoutstream, " T - is an integer\n"); + PRINTVALSTREAM(rawoutstream, " A - is an integer greater than zero\n"); + PRINTVALSTREAM(rawoutstream, " B - is the user block size, any value that is 512 or greater and is\n"); + PRINTVALSTREAM(rawoutstream, " a power of 2 (1024 default)\n"); + PRINTVALSTREAM(rawoutstream, " F - is the shared object header message type, any of <dspace|dtype|fill|\n"); + PRINTVALSTREAM(rawoutstream, " pline|attr>. If F is not specified, S applies to all messages\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " --enable-error-stack Prints messages from the HDF5 error stack as they\n"); + PRINTVALSTREAM(rawoutstream, " occur.\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " FS_STRGY is the file space management strategy to use for the output file.\n"); + PRINTVALSTREAM(rawoutstream, " It is a string as listed below:\n"); + PRINTVALSTREAM(rawoutstream, " ALL_PERSIST - Use persistent free-space managers, aggregators and virtual file driver\n"); + PRINTVALSTREAM(rawoutstream, " for file space allocation\n"); + PRINTVALSTREAM(rawoutstream, " ALL - Use non-persistent free-space managers, aggregators and virtual file driver\n"); + PRINTVALSTREAM(rawoutstream, " for file space allocation\n"); + PRINTVALSTREAM(rawoutstream, " AGGR_VFD - Use aggregators and virtual file driver for file space allocation\n"); + PRINTVALSTREAM(rawoutstream, " VFD - Use virtual file driver for file space allocation\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " FS_THRD is the free-space section threshold to use for the output file.\n"); + PRINTVALSTREAM(rawoutstream, " It is the minimum size (in bytes) of free-space sections to be tracked\n"); + PRINTVALSTREAM(rawoutstream, " by the the library's free-space managers.\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " FILT - is a string with the format:\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " <list of objects>:<name of filter>=<filter parameters>\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " <list of objects> is a comma separated list of object names, meaning apply\n"); + PRINTVALSTREAM(rawoutstream, " compression only to those objects. If no names are specified, the filter\n"); + PRINTVALSTREAM(rawoutstream, " is applied to all objects\n"); + PRINTVALSTREAM(rawoutstream, " <name of filter> can be:\n"); + PRINTVALSTREAM(rawoutstream, " GZIP, to apply the HDF5 GZIP filter (GZIP compression)\n"); + PRINTVALSTREAM(rawoutstream, " SZIP, to apply the HDF5 SZIP filter (SZIP compression)\n"); + PRINTVALSTREAM(rawoutstream, " SHUF, to apply the HDF5 shuffle filter\n"); + PRINTVALSTREAM(rawoutstream, " FLET, to apply the HDF5 checksum filter\n"); + PRINTVALSTREAM(rawoutstream, " NBIT, to apply the HDF5 NBIT filter (NBIT compression)\n"); + PRINTVALSTREAM(rawoutstream, " SOFF, to apply the HDF5 Scale/Offset filter\n"); + PRINTVALSTREAM(rawoutstream, " UD, to apply a user defined filter\n"); + PRINTVALSTREAM(rawoutstream, " NONE, to remove all filters\n"); + PRINTVALSTREAM(rawoutstream, " <filter parameters> is optional filter parameter information\n"); + PRINTVALSTREAM(rawoutstream, " GZIP=<deflation level> from 1-9\n"); + PRINTVALSTREAM(rawoutstream, " SZIP=<pixels per block,coding> pixels per block is a even number in\n"); + PRINTVALSTREAM(rawoutstream, " 2-32 and coding method is either EC or NN\n"); + PRINTVALSTREAM(rawoutstream, " SHUF (no parameter)\n"); + PRINTVALSTREAM(rawoutstream, " FLET (no parameter)\n"); + PRINTVALSTREAM(rawoutstream, " NBIT (no parameter)\n"); + PRINTVALSTREAM(rawoutstream, " SOFF=<scale_factor,scale_type> scale_factor is an integer and scale_type\n"); + PRINTVALSTREAM(rawoutstream, " is either IN or DS\n"); + PRINTVALSTREAM(rawoutstream, " UD=<filter_number,cd_value_count,value_1[,value_2,...,value_N]>\n"); + PRINTVALSTREAM(rawoutstream, " required values for filter_number,cd_value_count,value_1\n"); + PRINTVALSTREAM(rawoutstream, " optional values for value_2 to value_N\n"); + PRINTVALSTREAM(rawoutstream, " NONE (no parameter)\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " LAYT - is a string with the format:\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " <list of objects>:<layout type>=<layout parameters>\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " <list of objects> is a comma separated list of object names, meaning that\n"); + PRINTVALSTREAM(rawoutstream, " layout information is supplied for those objects. If no names are\n"); + PRINTVALSTREAM(rawoutstream, " specified, the layout type is applied to all objects\n"); + PRINTVALSTREAM(rawoutstream, " <layout type> can be:\n"); + PRINTVALSTREAM(rawoutstream, " CHUNK, to apply chunking layout\n"); + PRINTVALSTREAM(rawoutstream, " COMPA, to apply compact layout\n"); + PRINTVALSTREAM(rawoutstream, " CONTI, to apply contiguous layout\n"); + PRINTVALSTREAM(rawoutstream, " <layout parameters> is optional layout information\n"); + PRINTVALSTREAM(rawoutstream, " CHUNK=DIM[xDIM...xDIM], the chunk size of each dimension\n"); + PRINTVALSTREAM(rawoutstream, " COMPA (no parameter)\n"); + PRINTVALSTREAM(rawoutstream, " CONTI (no parameter)\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, "Examples of use:\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, "1) h5repack -v -f GZIP=1 file1 file2\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " GZIP compression with level 1 to all objects\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, "2) h5repack -v -f dset1:SZIP=8,NN file1 file2\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " SZIP compression with 8 pixels per block and NN coding method to object dset1\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, "3) h5repack -v -l dset1,dset2:CHUNK=20x10 -f dset3,dset4,dset5:NONE file1 file2\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " Chunked layout, with a layout size of 20x10, to objects dset1 and dset2\n"); + PRINTVALSTREAM(rawoutstream, " and remove filters to objects dset3, dset4, dset5\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, "4) h5repack -L -c 10 -s 20:dtype file1 file2 \n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " Using latest file format with maximum compact group size of 10 and\n"); + PRINTVALSTREAM(rawoutstream, " and minimum shared datatype size of 20\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, "5) h5repack -f SHUF -f GZIP=1 file1 file2 \n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " Add both filters SHUF and GZIP in this order to all datasets\n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, "6) h5repack -f UD=307,1,9 file1 file2 \n"); + PRINTVALSTREAM(rawoutstream, "\n"); + PRINTVALSTREAM(rawoutstream, " Add bzip2 filter to all datasets\n"); + PRINTVALSTREAM(rawoutstream, "\n"); +} + +/*------------------------------------------------------------------------- + * Function: leave + * + * Purpose: Shutdown MPI & HDF5 and call exit() + * + * Return: Does not return + * + * Programmer: Quincey Koziol + * Saturday, 31. January 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void leave(int ret) { + h5tools_close(); + + HDexit(ret); +} + +/*------------------------------------------------------------------------- + * Function: read_info + * + * Purpose: read comp and chunk options from a file + * + * Return: void, exit on error + * + * Programmer: pvn@ncsa.uiuc.edu + * + * Date: September, 22, 2003 + * + *------------------------------------------------------------------------- + */ + +static +int read_info(const char *filename, pack_opt_t *options) { + + char stype[10]; + char comp_info[1024]; + FILE *fp = NULL; + char c; + int i, rc = 1; + int ret_value = EXIT_SUCCESS; + + if ((fp = HDfopen(filename, "r")) == (FILE *) NULL) { + error_msg("cannot open options file %s\n", filename); + h5tools_setstatus(EXIT_FAILURE); + ret_value = EXIT_FAILURE; + goto done; + } + + /* cycle until end of file reached */ + while (1) { + rc = fscanf(fp, "%s", stype); + if (rc == -1) + break; + + /*------------------------------------------------------------------------- + * filter + *------------------------------------------------------------------------- + */ + if (HDstrcmp(stype,"-f") == 0) { + /* find begining of info */ + i = 0; + c = '0'; + while (c != ' ') { + if(fscanf(fp, "%c", &c) < 0 && HDferror(fp)) { + error_msg("fscanf error\n"); + h5tools_setstatus(EXIT_FAILURE); + ret_value = EXIT_FAILURE; + goto done; + } /* end if */ + if (HDfeof(fp)) + break; + } + c = '0'; + /* go until end */ + while (c != ' ') { + if(fscanf(fp, "%c", &c) < 0 && HDferror(fp)) { + error_msg("fscanf error\n"); + h5tools_setstatus(EXIT_FAILURE); + ret_value = EXIT_FAILURE; + goto done; + } /* end if */ + comp_info[i] = c; + i++; + if (HDfeof(fp)) + break; + if (c == 10 /*eol*/) + break; + } + comp_info[i - 1] = '\0'; /*cut the last " */ + + if (h5repack_addfilter(comp_info, options) == -1) { + error_msg("could not add compression option\n"); + h5tools_setstatus(EXIT_FAILURE); + ret_value = EXIT_FAILURE; + goto done; + } + } + /*------------------------------------------------------------------------- + * layout + *------------------------------------------------------------------------- + */ + else if (HDstrcmp(stype,"-l") == 0) { + + /* find begining of info */ + i = 0; + c = '0'; + while (c != ' ') { + if(fscanf(fp, "%c", &c) < 0 && HDferror(fp)) { + error_msg("fscanf error\n"); + h5tools_setstatus(EXIT_FAILURE); + ret_value = EXIT_FAILURE; + goto done; + } /* end if */ + if (HDfeof(fp)) + break; + } + c = '0'; + /* go until end */ + while (c != ' ') { + if(fscanf(fp, "%c", &c) < 0 && HDferror(fp)) { + error_msg("fscanf error\n"); + h5tools_setstatus(EXIT_FAILURE); + ret_value = EXIT_FAILURE; + goto done; + } /* end if */ + comp_info[i] = c; + i++; + if (HDfeof(fp)) + break; + if (c == 10 /*eol*/) + break; + } + comp_info[i - 1] = '\0'; /*cut the last " */ + + if (h5repack_addlayout(comp_info, options) == -1) { + error_msg("could not add chunck option\n"); + h5tools_setstatus(EXIT_FAILURE); + ret_value = EXIT_FAILURE; + goto done; + } + } + /*------------------------------------------------------------------------- + * not valid + *------------------------------------------------------------------------- + */ + else { + error_msg("bad file format for %s", filename); + h5tools_setstatus(EXIT_FAILURE); + ret_value = EXIT_FAILURE; + goto done; + } + } + +done: + if (fp) + HDfclose(fp); + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: parse_command_line + * + * Purpose: parse command line input + * + *------------------------------------------------------------------------- + */ + +static +int parse_command_line(int argc, const char **argv, pack_opt_t* options) { + + int opt; + int ret_value = 0; + + /* parse command line options */ + while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { + switch ((char) opt) { + + /* -i for backward compability */ + case 'i': + infile = opt_arg; + has_i_o = 1; + break; + + /* -o for backward compability */ + case 'o': + outfile = opt_arg; + has_i_o = 1; + break; + + case 'h': + usage(h5tools_getprogname()); + h5tools_setstatus(EXIT_SUCCESS); + ret_value = -1; + goto done; + + case 'V': + print_version(h5tools_getprogname()); + h5tools_setstatus(EXIT_SUCCESS); + ret_value = -1; + goto done; + + case 'v': + options->verbose = 1; + break; + + case 'f': + /* parse the -f filter option */ + if (h5repack_addfilter(opt_arg, options) < 0) { + error_msg("in parsing filter\n"); + h5tools_setstatus(EXIT_FAILURE); + ret_value = -1; + goto done; + } + break; + + case 'l': + /* parse the -l layout option */ + if (h5repack_addlayout(opt_arg, options) < 0) { + error_msg("in parsing layout\n"); + h5tools_setstatus(EXIT_FAILURE); + ret_value = -1; + goto done; + } + break; + + case 'm': + options->min_comp = HDstrtoull(opt_arg , NULL, 0); + if ((int) options->min_comp <= 0) { + error_msg("invalid minimum compress size <%s>\n", opt_arg); + h5tools_setstatus(EXIT_FAILURE); + ret_value = -1; + goto done; + } + break; + + case 'e': + ret_value = read_info(opt_arg, options); + if (ret_value < 0) + goto done; + break; + + case 'n': + options->use_native = 1; + break; + + case 'L': + options->latest = TRUE; + break; + + case 'c': + options->grp_compact = HDatoi( opt_arg ); + if (options->grp_compact > 0) + options->latest = TRUE; /* must use latest format */ + break; + + case 'd': + options->grp_indexed = HDatoi( opt_arg ); + if (options->grp_indexed > 0) + options->latest = TRUE; /* must use latest format */ + break; + + case 's': + { + int idx = 0; + int ssize = 0; + char *msgPtr = HDstrchr( opt_arg, ':'); + options->latest = TRUE; /* must use latest format */ + if (msgPtr == NULL) { + ssize = HDatoi( opt_arg ); + for (idx = 0; idx < 5; idx++) + options->msg_size[idx] = ssize; + } + else { + char msgType[10]; + HDstrcpy(msgType, msgPtr + 1); + msgPtr[0] = '\0'; + ssize = HDatoi( opt_arg ); + if (HDstrncmp(msgType, "dspace",6) == 0) { + options->msg_size[0] = ssize; + } + else if (HDstrncmp(msgType, "dtype", 5) == 0) { + options->msg_size[1] = ssize; + } + else if (HDstrncmp(msgType, "fill", 4) == 0) { + options->msg_size[2] = ssize; + } + else if (HDstrncmp(msgType, "pline", 5) == 0) { + options->msg_size[3] = ssize; + } + else if (HDstrncmp(msgType, "attr", 4) == 0) { + options->msg_size[4] = ssize; + } + } + } + break; + + case 'u': + options->ublock_filename = opt_arg; + break; + + case 'b': + options->ublock_size = (hsize_t) HDatol( opt_arg ); + break; + + case 'M': + options->meta_block_size = (hsize_t) HDatol( opt_arg ); + break; + + case 't': + options->threshold = (hsize_t) HDatol( opt_arg ); + break; + + case 'a': + options->alignment = HDstrtoull(opt_arg , NULL, 0); + if (options->alignment < 1) { + error_msg("invalid alignment size\n", opt_arg); + h5tools_setstatus(EXIT_FAILURE); + ret_value = -1; + goto done; + } + break; + + case 'S': + { + char strategy[MAX_NC_NAME]; + + HDstrcpy(strategy, opt_arg); + if (!HDstrcmp(strategy, "ALL_PERSIST")) + options->fs_strategy = H5F_FILE_SPACE_ALL_PERSIST; + else if (!HDstrcmp(strategy, "ALL")) + options->fs_strategy = H5F_FILE_SPACE_ALL; + else if (!HDstrcmp(strategy, "AGGR_VFD")) + options->fs_strategy = H5F_FILE_SPACE_AGGR_VFD; + else if (!HDstrcmp(strategy, "VFD")) + options->fs_strategy = H5F_FILE_SPACE_VFD; + else { + error_msg("invalid file space management strategy\n", opt_arg); + h5tools_setstatus(EXIT_FAILURE); + ret_value = -1; + goto done; + } + } + break; + + case 'T': + options->fs_threshold = (hsize_t) HDatol( opt_arg ); + break; + + case 'E': + enable_error_stack = TRUE; + break; + + default: + break; + } /* switch */ + + } /* while */ + + if (has_i_o == 0) { + /* check for file names to be processed */ + if (argc <= opt_ind || argv[opt_ind + 1] == NULL) { + error_msg("missing file names\n"); + usage(h5tools_getprogname()); + h5tools_setstatus(EXIT_FAILURE); + ret_value = -1; + } + } + +done: + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: h5repack main program + * + * Return: Success: EXIT_SUCCESS(0) + * + * Failure: EXIT_FAILURE(1) + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: May 9, 2003 + * + * Comments: + * + *------------------------------------------------------------------------- + */ +int main(int argc, const char **argv) { + H5E_auto2_t func; + H5E_auto2_t tools_func; + void *edata; + void *tools_edata; + + pack_opt_t options; /*the global options */ + + h5tools_setprogname(PROGRAMNAME); + h5tools_setstatus(EXIT_SUCCESS); + + /* Disable error reporting */ + H5Eget_auto2(H5E_DEFAULT, &func, &edata); + H5Eset_auto2(H5E_DEFAULT, NULL, NULL); + + /* Initialize h5tools lib */ + h5tools_init(); + + /* Disable tools error reporting */ + H5Eget_auto2(H5tools_ERR_STACK_g, &tools_func, &tools_edata); + H5Eset_auto2(H5tools_ERR_STACK_g, NULL, NULL); + + /* update hyperslab buffer size from H5TOOLS_BUFSIZE env if exist */ + if (h5tools_getenv_update_hyperslab_bufsize() < 0) { + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + /* initialize options */ + h5repack_init(&options, 0, FALSE, H5F_FILE_SPACE_DEFAULT, (hsize_t) 0); + + if (parse_command_line(argc, argv, &options) < 0) + goto done; + + /* get file names if they were not yet got */ + if (has_i_o == 0) { + + if (argv[opt_ind] != NULL && argv[opt_ind + 1] != NULL) { + infile = argv[opt_ind]; + outfile = argv[opt_ind + 1]; + + if ( HDstrcmp( infile, outfile ) == 0) { + error_msg("file names cannot be the same\n"); + usage(h5tools_getprogname()); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + } + else { + error_msg("file names missing\n"); + usage(h5tools_getprogname()); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + } + + if (enable_error_stack) { + H5Eset_auto2(H5E_DEFAULT, func, edata); + H5Eset_auto2(H5tools_ERR_STACK_g, tools_func, tools_edata); + } + + /* pack it */ + h5tools_setstatus(h5repack(infile, outfile, &options)); + +done: + /* free tables */ + h5repack_end(&options); + + leave(h5tools_getstatus()); +} + diff --git a/tools/src/h5repack/h5repack_opttable.c b/tools/src/h5repack/h5repack_opttable.c new file mode 100644 index 0000000..8c98b76 --- /dev/null +++ b/tools/src/h5repack/h5repack_opttable.c @@ -0,0 +1,367 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "h5repack.h" +#include "h5tools.h" +#include "h5tools_utils.h" + +/*------------------------------------------------------------------------- + * Function: init_packobject + * + * Purpose: initialize a pack_info_t structure + * + * Return: void + * + *------------------------------------------------------------------------- + */ + +void init_packobject(pack_info_t *obj) { + int j, k; + + HDstrcpy(obj->path, "\0"); + for (j = 0; j < H5_REPACK_MAX_NFILTERS; j++) { + obj->filter[j].filtn = -1; + for (k = 0; k < CD_VALUES; k++) + obj->filter[j].cd_values[k] = 0; + } + obj->chunk.rank = -1; + obj->refobj_id = -1; + obj->layout = H5D_LAYOUT_ERROR; + obj->nfilters = 0; +} + +/*------------------------------------------------------------------------- + * Function: aux_tblinsert_filter + * + * Purpose: auxiliary function, inserts the filter in object OBJS[ I ] + * + * Return: void + * + *------------------------------------------------------------------------- + */ + +static void aux_tblinsert_filter(pack_opttbl_t *table, unsigned int I, + filter_info_t filt) { + if (table->objs[I].nfilters < H5_REPACK_MAX_NFILTERS) { + table->objs[I].filter[table->objs[I].nfilters++] = filt; + } + else { + error_msg( + "cannot insert the filter in this object.\ + Maximum capacity exceeded\n"); + } +} + +/*------------------------------------------------------------------------- + * Function: aux_tblinsert_layout + * + * Purpose: auxiliary function, inserts the layout in object OBJS[ I ] + * + * Return: void + * + *------------------------------------------------------------------------- + */ + +static void aux_tblinsert_layout(pack_opttbl_t *table, unsigned int I, + pack_info_t *pack) { + int k; + + table->objs[I].layout = pack->layout; + if (H5D_CHUNKED == pack->layout) { + /* -2 means the NONE option, remove chunking + and set the layout to contiguous */ + if (pack->chunk.rank == -2) { + table->objs[I].layout = H5D_CONTIGUOUS; + table->objs[I].chunk.rank = -2; + } + /* otherwise set the chunking type */ + else { + table->objs[I].chunk.rank = pack->chunk.rank; + for (k = 0; k < pack->chunk.rank; k++) + table->objs[I].chunk.chunk_lengths[k] = + pack->chunk.chunk_lengths[k]; + } + } +} + +/*------------------------------------------------------------------------- + * Function: aux_inctable + * + * Purpose: auxiliary function, increases the size of the collection by N_OBJS + * + * Return: 0, ok, -1, fail + * + *------------------------------------------------------------------------- + */ +static int +aux_inctable(pack_opttbl_t *table, unsigned n_objs) +{ + unsigned u; + + table->size += n_objs; + table->objs = (pack_info_t*) HDrealloc(table->objs, table->size * sizeof(pack_info_t)); + if (table->objs == NULL) { + error_msg("not enough memory for options table\n"); + return -1; + } + + for (u = table->nelems; u < table->size; u++) + init_packobject(&table->objs[u]); + + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: options_table_init + * + * Purpose: init options table + * + * Return: 0, ok, -1, fail + * + *------------------------------------------------------------------------- + */ +int options_table_init(pack_opttbl_t **tbl) { + unsigned int i; + pack_opttbl_t *table; + + if (NULL == (table = (pack_opttbl_t *) HDmalloc(sizeof(pack_opttbl_t)))) { + error_msg("not enough memory for options table\n"); + return -1; + } + + table->size = 30; + table->nelems = 0; + if (NULL == (table->objs = + (pack_info_t*) HDmalloc(table->size * sizeof(pack_info_t)))) { + error_msg("not enough memory for options table\n"); + HDfree(table); + return -1; + } + + for (i = 0; i < table->size; i++) + init_packobject(&table->objs[i]); + + *tbl = table; + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: options_table_free + * + * Purpose: free table memory + * + * Return: 0 + * + *------------------------------------------------------------------------- + */ + +int options_table_free(pack_opttbl_t *table) { + HDfree(table->objs); + HDfree(table); + return 0; +} + +/*------------------------------------------------------------------------- + * Function: options_add_layout + * + * Purpose: add a layout option to the option list + * + * Return: 0, ok, -1, fail + * + *------------------------------------------------------------------------- + */ +int +options_add_layout(obj_list_t *obj_list, unsigned n_objs, pack_info_t *pack, + pack_opttbl_t *table) +{ + unsigned i, j, I; + unsigned added = 0; + hbool_t found = FALSE; + + /* increase the size of the collection by N_OBJS if necessary */ + if (table->nelems + n_objs >= table->size) + if (aux_inctable(table, n_objs) < 0) + return -1; + + /* search if this object is already in the table; "path" is the key */ + if (table->nelems > 0) { + /* go tru the supplied list of names */ + for (j = 0; j < n_objs; j++) { + /* linear table search */ + for (i = 0; i < table->nelems; i++) { + /*already on the table */ + if (HDstrcmp(obj_list[j].obj,table->objs[i].path) == 0) { + /* already chunk info inserted for this one; exit */ + if (table->objs[i].chunk.rank > 0) { + error_msg("chunk information already inserted for <%s>\n", obj_list[j].obj); + HDexit(EXIT_FAILURE); + } + /* insert the layout info */ + else { + aux_tblinsert_layout(table, i, pack); + found = TRUE; + break; + } + } /* if */ + } /* i */ + + if (!found) { + /* keep the grow in a temp var */ + I = table->nelems + added; + added++; + HDstrcpy(table->objs[I].path, obj_list[j].obj); + aux_tblinsert_layout(table, I, pack); + } + /* cases where we have an already inserted name but there is a new name also + example: + -f dset1:GZIP=1 -l dset1,dset2:CHUNK=20x20 + dset1 is already inserted, but dset2 must also be + */ + else + if(found && HDstrcmp(obj_list[j].obj,table->objs[i].path) != 0) { + /* keep the grow in a temp var */ + I = table->nelems + added; + added++; + HDstrcpy(table->objs[I].path, obj_list[j].obj); + aux_tblinsert_layout(table, I, pack); + } + } /* j */ + } + /* first time insertion */ + else { + /* go tru the supplied list of names */ + for (j = 0; j < n_objs; j++) { + I = table->nelems + added; + added++; + HDstrcpy(table->objs[I].path, obj_list[j].obj); + aux_tblinsert_layout(table, I, pack); + } + } + + table->nelems += added; + + return 0; +} + +/*------------------------------------------------------------------------- + * Function: options_add_filter + * + * Purpose: add a compression -f option to the option list + * + * Return: 0, ok, -1, fail + * + *------------------------------------------------------------------------- + */ +int +options_add_filter(obj_list_t *obj_list, unsigned n_objs, filter_info_t filt, + pack_opttbl_t *table) +{ + unsigned int i, j, I; + unsigned added = 0; + hbool_t found = FALSE; + + /* increase the size of the collection by N_OBJS if necessary */ + if (table->nelems + n_objs >= table->size) + if (aux_inctable(table, n_objs) < 0) + return -1; + + /* search if this object is already in the table; "path" is the key */ + if (table->nelems > 0) { + /* go tru the supplied list of names */ + for (j = 0; j < n_objs; j++) { + /* linear table search */ + for (i = 0; i < table->nelems; i++) { + /*already on the table */ + if (HDstrcmp(obj_list[j].obj, table->objs[i].path) == 0) { + /* insert */ + aux_tblinsert_filter(table, i, filt); + found = TRUE; + break; + } /* if */ + } /* i */ + + if (!found) { + /* keep the grow in a temp var */ + I = table->nelems + added; + added++; + HDstrcpy(table->objs[I].path, obj_list[j].obj); + aux_tblinsert_filter(table, I, filt); + } + /* cases where we have an already inserted name but there is a new name also + example: + -l dset1:CHUNK=20x20 -f dset1,dset2:GZIP=1 + dset1 is already inserted, but dset2 must also be + */ + else + if(found && HDstrcmp(obj_list[j].obj,table->objs[i].path) != 0) { + /* keep the grow in a temp var */ + I = table->nelems + added; + added++; + HDstrcpy(table->objs[I].path, obj_list[j].obj); + aux_tblinsert_filter(table, I, filt); + } + } /* j */ + } + + /* first time insertion */ + else { + /* go tru the supplied list of names */ + for (j = 0; j < n_objs; j++) { + I = table->nelems + added; + added++; + HDstrcpy(table->objs[I].path, obj_list[j].obj); + aux_tblinsert_filter(table, I, filt); + } + } + + table->nelems += added; + + return 0; +} + +/*------------------------------------------------------------------------- + * Function: options_get_object + * + * Purpose: get object from table; "path" is the key + * + * Return: pack_info_t* OBJECT or NULL if not found; PATH is the key + * + *------------------------------------------------------------------------- + */ + +pack_info_t* options_get_object(const char *path, pack_opttbl_t *table) { + unsigned int i; + char tbl_path[MAX_NC_NAME + 1]; /* +1 for start with "/" case */ + + for (i = 0; i < table->nelems; i++) { + /* make full path (start with "/") to compare correctly */ + if (HDstrncmp(table->objs[i].path, "/", 1)) { + HDstrcpy(tbl_path, "/"); + HDstrcat(tbl_path, table->objs[i].path); + } + else + HDstrcpy(tbl_path, table->objs[i].path); + + /* found it */ + if (HDstrcmp(tbl_path, path) == 0) { + return (&table->objs[i]); + } + } + + return NULL; +} + diff --git a/tools/src/h5repack/h5repack_parse.c b/tools/src/h5repack/h5repack_parse.c new file mode 100644 index 0000000..004b9e4 --- /dev/null +++ b/tools/src/h5repack/h5repack_parse.c @@ -0,0 +1,616 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "h5repack.h" +#include "h5tools.h" +#include "h5tools_utils.h" + +/*------------------------------------------------------------------------- + * Function: parse_filter + * + * Purpose: read filter information + * + * Return: a list of names, the number of names and its compression type + * + * <name of filter> can be: + * GZIP, to apply the HDF5 GZIP filter (GZIP compression) + * SZIP, to apply the HDF5 SZIP filter (SZIP compression) + * SHUF, to apply the HDF5 shuffle filter + * FLET, to apply the HDF5 checksum filter + * NBIT, to apply the HDF5 NBIT filter (NBIT compression) + * SOFF, to apply the HDF5 scale+offset filter (compression) + * UD, to apply a User Defined filter k,m,n1[,…,nm] + * NONE, to remove the filter + * + * Examples: + * "GZIP=6" + * "A,B:NONE" + *------------------------------------------------------------------------- + */ +obj_list_t* parse_filter(const char *str, unsigned *n_objs, filter_info_t *filt, + pack_opt_t *options, int *is_glb) { + size_t i, m, u; + char c; + size_t len = HDstrlen(str); + int k, l, p, q, end_obj = -1, no_param = 0; + unsigned j, n; + char sobj[MAX_NC_NAME]; + char scomp[10]; + char stype[6]; + char smask[3]; + obj_list_t* obj_list = NULL; + unsigned pixels_per_block; + + /* initialize compression info */ + HDmemset(filt, 0, sizeof(filter_info_t)); + *is_glb = 0; + + /* check for the end of object list and number of objects */ + for (i = 0, n = 0; i < len; i++) { + c = str[i]; + if (c == ':') + end_obj = (int) i; + if (c == ',') + n++; + } + + /* Check for missing : */ + if (end_obj == -1) { + /* apply to all objects */ + options->all_filter = 1; + *is_glb = 1; + } + + n++; + obj_list = (obj_list_t *) HDmalloc(n * sizeof(obj_list_t)); + if (obj_list == NULL) { + error_msg("could not allocate object list\n"); + return NULL; + } + *n_objs = n; + + /* get object list */ + if (end_obj > 0) + for (j = 0, k = 0, n = 0; j < (unsigned) end_obj; j++, k++) { + c = str[j]; + sobj[k] = c; + if (c == ',' || j == (unsigned) (end_obj - 1)) { + if (c == ',') + sobj[k] = '\0'; + else + sobj[k + 1] = '\0'; + HDstrcpy(obj_list[n].obj, sobj); + HDmemset(sobj, 0, sizeof(sobj)); + n++; + k = -1; + } + } + /* nothing after : */ + if (end_obj + 1 == (int) len) { + if (obj_list) + HDfree(obj_list); + error_msg("input Error: Invalid compression type in <%s>\n", str); + HDexit(EXIT_FAILURE); + } + + /* get filter additional parameters */ + m = 0; + for (i = (size_t)(end_obj + 1), k = 0, j = 0; i < len; i++, k++) { + c = str[i]; + scomp[k] = c; + if (c == '=' || i == len - 1) { + if (c == '=') { /*one more parameter */ + scomp[k] = '\0'; /*cut space */ + + /*------------------------------------------------------------------------- + * H5Z_FILTER_SZIP + * szip has the format SZIP=<pixels per block,coding> + * pixels per block is a even number in 2-32 and coding method is 'EC' or 'NN' + * example SZIP=8,NN + *------------------------------------------------------------------------- + */ + if (HDstrcmp(scomp, "SZIP") == 0) { + l = -1; /* mask index check */ + for (m = 0, u = i + 1; u < len; u++, m++) { + if (str[u] == ',') { + stype[m] = '\0'; /* end digit of szip */ + l = 0; /* start EC or NN search */ + u++; /* skip ',' */ + } + c = str[u]; + if (!HDisdigit(c) && l == -1) { + if (obj_list) + HDfree(obj_list); + error_msg("compression parameter not digit in <%s>\n", str); + HDexit(EXIT_FAILURE); + } + if (l == -1) + stype[m] = c; + else { + smask[l] = c; + l++; + if (l == 2) { + smask[l] = '\0'; + i = len - 1; /* end */ + (*n_objs)--; /* we counted an extra ',' */ + if (HDstrcmp(smask,"NN") == 0) + filt->cd_values[j++] = H5_SZIP_NN_OPTION_MASK; + else if (HDstrcmp(smask,"EC") == 0) + filt->cd_values[j++] = H5_SZIP_EC_OPTION_MASK; + else { + error_msg("szip mask must be 'NN' or 'EC' \n"); + HDexit(EXIT_FAILURE); + } + } + } + } /* u */ + } /*if */ + + /*------------------------------------------------------------------------- + * H5Z_FILTER_SCALEOFFSET + * scaleoffset has the format SOFF=<scale_factor,scale_type> + * scale_type can be + * integer datatype, H5Z_SO_INT (IN) + * float datatype using D-scaling method, H5Z_SO_FLOAT_DSCALE (DS) + * float datatype using E-scaling method, H5Z_SO_FLOAT_ESCALE (ES) , not yet implemented + * for integer datatypes, scale_factor denotes Minimum Bits + * for float datatypes, scale_factor denotes decimal scale factor + * examples + * SOFF=31,IN + * SOFF=3,DF + *------------------------------------------------------------------------- + */ + else if (HDstrcmp(scomp, "SOFF") == 0) { + l = -1; /* mask index check */ + for (m = 0, u = i + 1; u < len; u++, m++) { + if (str[u] == ',') { + stype[m] = '\0'; /* end digit */ + l = 0; /* start 'IN' , 'DS', or 'ES' search */ + u++; /* skip ',' */ + } + c = str[u]; + if (!HDisdigit(c) && l == -1) { + if (obj_list) + HDfree(obj_list); + error_msg("compression parameter is not a digit in <%s>\n", str); + HDexit(EXIT_FAILURE); + } + if (l == -1) + stype[m] = c; + else { + smask[l] = c; + l++; + if (l == 2) { + smask[l] = '\0'; + i = len - 1; /* end */ + (*n_objs)--; /* we counted an extra ',' */ + if (HDstrcmp(smask,"IN") == 0) + filt->cd_values[j++] = H5Z_SO_INT; + else if (HDstrcmp(smask, "DS") == H5Z_SO_FLOAT_DSCALE) + filt->cd_values[j++] = H5Z_SO_FLOAT_DSCALE; + else { + error_msg("scale type must be 'IN' or 'DS' \n"); + HDexit(EXIT_FAILURE); + } + } + } + } /* u */ + } /*if */ + + /*------------------------------------------------------------------------- + * User Defined + * has the format UD=<filter_number,cd_value_count,value_1[,value_2,...,value_N]> + * BZIP2 example + * UD=307,1,9 + *------------------------------------------------------------------------- + */ + else if (HDstrcmp(scomp, "UD") == 0) { + l = -1; /* filter number index check */ + p = -1; /* CD_VAL count check */ + for (m = 0, q = 0, u = i + 1; u < len; u++, m++, q++) { + if (str[u] == ',') { + stype[q] = '\0'; /* end digit */ + if (l == -1) { + filt->filtn = HDatoi(stype); + l = 0; + } + else if (p == -1) { + filt->cd_nelmts = HDstrtoull(stype, NULL, 0); + p = 0; + } + else + filt->cd_values[j++] = (unsigned)HDstrtoul(stype, NULL, 0); + q = 0; + u++; /* skip ',' */ + } + c = str[u]; + if (!HDisdigit(c) && l == -1) { + if (obj_list) + HDfree(obj_list); + error_msg("filter number parameter is not a digit in <%s>\n", str); + HDexit(EXIT_FAILURE); + } + stype[q] = c; + } /* for u */ + stype[q] = '\0'; + } /*if */ + + /*------------------------------------------------------------------------- + * all other filters + *------------------------------------------------------------------------- + */ + else { + /* here we could have 1 or 2 digits */ + for (m = 0, u = i + 1; u < len; u++, m++) { + c = str[u]; + if (!HDisdigit(c)) { + if (obj_list) + HDfree(obj_list); + error_msg("compression parameter is not a digit in <%s>\n", str); + HDexit(EXIT_FAILURE); + } + stype[m] = c; + } /* u */ + + stype[m] = '\0'; + } /*if */ + + filt->cd_values[j++] = (unsigned) HDstrtoul(stype, NULL, 0); + if(filt->cd_nelmts == 0) + j = 0; + i += m; /* jump */ + } + else if (i == len - 1) { /*no more parameters */ + scomp[k + 1] = '\0'; + no_param = 1; + } + + /*------------------------------------------------------------------------- + * translate from string to filter symbol + *------------------------------------------------------------------------- + */ + + /*------------------------------------------------------------------------- + * H5Z_FILTER_NONE + *------------------------------------------------------------------------- + */ + if (HDstrcmp(scomp, "NONE") == 0) { + filt->filtn = H5Z_FILTER_NONE; + filt->cd_nelmts = 0; + } + + /*------------------------------------------------------------------------- + * H5Z_FILTER_DEFLATE + *------------------------------------------------------------------------- + */ + else if (HDstrcmp(scomp, "GZIP") == 0) { + filt->filtn = H5Z_FILTER_DEFLATE; + filt->cd_nelmts = 1; + if (no_param) { /*no more parameters, GZIP must have parameter */ + if (obj_list) + HDfree(obj_list); + error_msg("missing compression parameter in <%s>\n", str); + HDexit(EXIT_FAILURE); + } + } + + /*------------------------------------------------------------------------- + * H5Z_FILTER_SZIP + *------------------------------------------------------------------------- + */ + else if (HDstrcmp(scomp, "SZIP") == 0) { + filt->filtn = H5Z_FILTER_SZIP; + filt->cd_nelmts = 2; + if (no_param) { /*no more parameters, SZIP must have parameter */ + if (obj_list) + HDfree(obj_list); + error_msg("missing compression parameter in <%s>\n", str); + HDexit(EXIT_FAILURE); + } + } + + /*------------------------------------------------------------------------- + * H5Z_FILTER_SHUFFLE + *------------------------------------------------------------------------- + */ + else if (HDstrcmp(scomp, "SHUF") == 0) { + filt->filtn = H5Z_FILTER_SHUFFLE; + filt->cd_nelmts = 0; + if (m > 0) { /*shuffle does not have parameter */ + if (obj_list) + HDfree(obj_list); + error_msg("extra parameter in SHUF <%s>\n", str); + HDexit(EXIT_FAILURE); + } + } + /*------------------------------------------------------------------------- + * H5Z_FILTER_FLETCHER32 + *------------------------------------------------------------------------- + */ + else if (HDstrcmp(scomp, "FLET") == 0) { + filt->filtn = H5Z_FILTER_FLETCHER32; + filt->cd_nelmts = 0; + if (m > 0) { /*shuffle does not have parameter */ + if (obj_list) + HDfree(obj_list); + error_msg("extra parameter in FLET <%s>\n", str); + HDexit(EXIT_FAILURE); + } + } + /*------------------------------------------------------------------------- + * H5Z_FILTER_NBIT + *------------------------------------------------------------------------- + */ + else if (HDstrcmp(scomp, "NBIT") == 0) { + filt->filtn = H5Z_FILTER_NBIT; + filt->cd_nelmts = 0; + if (m > 0) { /*nbit does not have parameter */ + if (obj_list) + HDfree(obj_list); + error_msg("extra parameter in NBIT <%s>\n", str); + HDexit(EXIT_FAILURE); + } + } + /*------------------------------------------------------------------------- + * H5Z_FILTER_SCALEOFFSET + *------------------------------------------------------------------------- + */ + else if (HDstrcmp(scomp, "SOFF") == 0) { + filt->filtn = H5Z_FILTER_SCALEOFFSET; + filt->cd_nelmts = 2; + if (no_param) { /*no more parameters, SOFF must have parameter */ + if (obj_list) + HDfree(obj_list); + error_msg("missing compression parameter in <%s>\n", str); + HDexit(EXIT_FAILURE); + } + } + /*------------------------------------------------------------------------- + * User Defined Filter + *------------------------------------------------------------------------- + */ + else if (HDstrcmp(scomp, "UD") == 0) { + /* parameters does not match count */ + if (filt->cd_nelmts != j) { + if (obj_list) + HDfree(obj_list); + error_msg("incorrect number of compression parameters in <%s>\n", str); + HDexit(EXIT_FAILURE); + } + } + else { + if (obj_list) + HDfree(obj_list); + error_msg("invalid filter type in <%s>\n", str); + HDexit(EXIT_FAILURE); + } + } + } /*i*/ + + /*------------------------------------------------------------------------- + * check valid parameters + *------------------------------------------------------------------------- + */ + + switch (filt->filtn) { + /*------------------------------------------------------------------------- + * H5Z_FILTER_DEFLATE + *------------------------------------------------------------------------- + */ + case H5Z_FILTER_DEFLATE: + if (filt->cd_values[0] > 9) { + if (obj_list) + HDfree(obj_list); + error_msg("invalid compression parameter in <%s>\n", str); + HDexit(EXIT_FAILURE); + } + break; + /*------------------------------------------------------------------------- + * H5Z_FILTER_SZIP + *------------------------------------------------------------------------- + */ + case H5Z_FILTER_SZIP: + pixels_per_block = filt->cd_values[0]; + if ((pixels_per_block % 2) == 1) { + if (obj_list) + HDfree(obj_list); + error_msg("pixels_per_block is not even in <%s>\n", str); + HDexit(EXIT_FAILURE); + } + if (pixels_per_block > H5_SZIP_MAX_PIXELS_PER_BLOCK) { + if (obj_list) + HDfree(obj_list); + error_msg("pixels_per_block is too large in <%s>\n", str); + HDexit(EXIT_FAILURE); + } + if ((HDstrcmp(smask,"NN") != 0) && (HDstrcmp(smask,"EC") != 0)) { + if (obj_list) + HDfree(obj_list); + error_msg("szip mask must be 'NN' or 'EC' \n"); + HDexit(EXIT_FAILURE); + } + break; + default: + break; + }; + + return obj_list; +} + + +/*------------------------------------------------------------------------- + * Function: parse_layout + * + * Purpose: read layout info + * + * Return: a list of names, the number of names and its chunking info for + * chunked. NULL, on error + * the layout type can be: + * CHUNK, to apply chunking layout + * CONTI, to apply contiguous layout + * COMPA, to apply compact layout + * + * Example: + * "AA,B,CDE:CHUNK=10X10" + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: December 30, 2003 + * + *------------------------------------------------------------------------- + */ +obj_list_t* parse_layout(const char *str, unsigned *n_objs, pack_info_t *pack, /* info about layout needed */ +pack_opt_t *options) { + obj_list_t* obj_list = NULL; + unsigned i, j, n; + char c; + size_t len = HDstrlen(str); + int k, end_obj = -1, c_index; + char sobj[MAX_NC_NAME]; + char sdim[10]; + char slayout[10]; + + HDmemset(sdim, '\0', sizeof(sdim)); + HDmemset(sobj, '\0', sizeof(sobj)); + HDmemset(slayout, '\0', sizeof(slayout)); + + /* check for the end of object list and number of objects */ + for (i = 0, n = 0; i < len; i++) { + c = str[i]; + if (c == ':') + end_obj = (int) i; + if (c == ',') + n++; + } + + if (end_obj == -1) { /* missing : chunk all */ + options->all_layout = 1; + } + + n++; + obj_list = (obj_list_t*) HDmalloc(n * sizeof(obj_list_t)); + if (obj_list == NULL) { + error_msg("could not allocate object list\n"); + return NULL; + } + *n_objs = n; + + /* get object list */ + if (end_obj > 0) + for (j = 0, k = 0, n = 0; j < (unsigned) end_obj; j++, k++) { + c = str[j]; + sobj[k] = c; + if (c == ',' || j == (unsigned) (end_obj - 1)) { + if (c == ',') + sobj[k] = '\0'; + else + sobj[k + 1] = '\0'; + HDstrcpy(obj_list[n].obj, sobj); + HDmemset(sobj, 0, sizeof(sobj)); + n++; + k = -1; + } + } + + /* nothing after : */ + if (end_obj + 1 == (int) len) { + if (obj_list) + HDfree(obj_list); + error_msg("in parse layout, no characters after : in <%s>\n", str); + HDexit(EXIT_FAILURE); + } + + /* get layout info */ + for (j = (unsigned) (end_obj + 1), n = 0; n <= 5; j++, n++) { + if (n == 5) { + slayout[n] = '\0'; /*cut string */ + if (HDstrcmp(slayout, "COMPA") == 0) + pack->layout = H5D_COMPACT; + else if (HDstrcmp(slayout, "CONTI") == 0) + pack->layout = H5D_CONTIGUOUS; + else if (HDstrcmp(slayout, "CHUNK") == 0) + pack->layout = H5D_CHUNKED; + else { + error_msg("in parse layout, not a valid layout in <%s>\n", str); + HDexit(EXIT_FAILURE); + } + } + else { + c = str[j]; + slayout[n] = c; + } + } /* j */ + + if (pack->layout == H5D_CHUNKED) { + /*------------------------------------------------------------------------- + * get chunk info + *------------------------------------------------------------------------- + */ + k = 0; + if (j > len) { + if (obj_list) + HDfree(obj_list); + error_msg("in parse layout, <%s> Chunk dimensions missing\n", str); + HDexit(EXIT_FAILURE); + } + + for (i = j, c_index = 0; i < len; i++) { + c = str[i]; + sdim[k] = c; + k++; /*increment sdim index */ + + if (!HDisdigit(c) && c != 'x' && c != 'N' && c != 'O' && c != 'N' && c != 'E') { + if (obj_list) + HDfree(obj_list); + error_msg("in parse layout, <%s> Not a valid character in <%s>\n", sdim, str); + HDexit(EXIT_FAILURE); + } + + if (c == 'x' || i == len - 1) { + if (c == 'x') { + sdim[k - 1] = '\0'; + k = 0; + pack->chunk.chunk_lengths[c_index] = HDstrtoull(sdim, NULL, 0); + if (pack->chunk.chunk_lengths[c_index] == 0) { + if (obj_list) + HDfree(obj_list); + error_msg("in parse layout, <%s> conversion to number in <%s>\n", sdim, str); + HDexit(EXIT_FAILURE); + } + c_index++; + } + else if (i == len - 1) { /*no more parameters */ + sdim[k] = '\0'; + k = 0; + if (HDstrcmp(sdim,"NONE") == 0) { + pack->chunk.rank = -2; + } + else { + pack->chunk.chunk_lengths[c_index] = HDstrtoull(sdim, NULL, 0); + if (pack->chunk.chunk_lengths[c_index] == 0) { + if (obj_list) + HDfree(obj_list); + error_msg("in parse layout, <%s> conversion to number in <%s>\n", sdim, str); + HDexit(EXIT_FAILURE); + } + pack->chunk.rank = c_index + 1; + } + } /*if */ + } /*if c=='x' || i==len-1 */ + } /*i*/ + } /*H5D_CHUNKED*/ + + return obj_list; +} diff --git a/tools/src/h5repack/h5repack_refs.c b/tools/src/h5repack/h5repack_refs.c new file mode 100644 index 0000000..f0f32c3 --- /dev/null +++ b/tools/src/h5repack/h5repack_refs.c @@ -0,0 +1,877 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "h5repack.h" +#include "h5diff.h" +#include "h5tools.h" + + +/*------------------------------------------------------------------------- + * local functions + *------------------------------------------------------------------------- + */ + +static const char* MapIdToName(hid_t refobj_id,trav_table_t *travt); +static int copy_refs_attr(hid_t loc_in, hid_t loc_out, pack_opt_t *options, + trav_table_t *travt, hid_t fidout); +static herr_t update_ref_value(hid_t obj_id, H5R_type_t ref_type, void *ref_in, + hid_t fid_out, void *ref_out, trav_table_t *travt); + +/*------------------------------------------------------------------------- + * Function: do_copy_refobjs + * + * Purpose: duplicate all referenced HDF5 objects in the file + * and create hard links + * + * Return: 0, ok, -1 no + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: December, 10, 2003 + * + *------------------------------------------------------------------------- + */ + +int do_copy_refobjs(hid_t fidin, + hid_t fidout, + trav_table_t *travt, + pack_opt_t *options) /* repack options */ +{ + int ret_value = 0; /*no need to LEAVE() on ERROR: HERR_INIT(int, SUCCEED) */ + hid_t grp_in = (-1); /* read group ID */ + hid_t grp_out = (-1); /* write group ID */ + hid_t dset_in = (-1); /* read dataset ID */ + hid_t dset_out = (-1); /* write dataset ID */ + hid_t type_in = (-1); /* named type ID */ + hid_t dcpl_id = (-1); /* dataset creation property list ID */ + hid_t space_id = (-1); /* space ID */ + hid_t ftype_id = (-1); /* file data type ID */ + hid_t mtype_id = (-1); /* memory data type ID */ + size_t msize; /* memory size of memory type */ + hsize_t nelmts; /* number of elements in dataset */ + int rank; /* rank of dataset */ + hsize_t dims[H5S_MAX_RANK]; /* dimensions of dataset */ + unsigned int i, j; + int k; + named_dt_t *named_dt_head=NULL; /* Pointer to the stack of named datatypes + copied */ + + /*------------------------------------------------------------------------- + * browse + *------------------------------------------------------------------------- + */ + for(i = 0; i < travt->nobjs; i++) { + switch(travt->objs[i].type) + { + /*------------------------------------------------------------------------- + * H5TRAV_TYPE_GROUP + *------------------------------------------------------------------------- + */ + case H5TRAV_TYPE_GROUP: + /*------------------------------------------------------------------------- + * copy referenced objects in attributes + *------------------------------------------------------------------------- + */ + if((grp_out = H5Gopen2(fidout, travt->objs[i].name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gopen2 failed"); + + if((grp_in = H5Gopen2(fidin, travt->objs[i].name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gopen2 failed"); + + if(copy_refs_attr(grp_in, grp_out, options, travt, fidout) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_refs_attr failed"); + + if(H5Gclose(grp_out) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gclose failed"); + if(H5Gclose(grp_in) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gclose failed"); + + /*------------------------------------------------------------------------- + * check for hard links + *------------------------------------------------------------------------- + */ + if(travt->objs[i].nlinks) + for(j = 0; j < travt->objs[i].nlinks; j++) + H5Lcreate_hard(fidout, travt->objs[i].name, H5L_SAME_LOC, travt->objs[i].links[j].new_name, H5P_DEFAULT, H5P_DEFAULT); + break; + + /*------------------------------------------------------------------------- + * H5TRAV_TYPE_DATASET + *------------------------------------------------------------------------- + */ + case H5TRAV_TYPE_DATASET: + if((dset_in = H5Dopen2(fidin, travt->objs[i].name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dopen2 failed"); + if((space_id = H5Dget_space(dset_in)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_space failed"); + if((ftype_id = H5Dget_type(dset_in)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_type failed"); + if((dcpl_id = H5Dget_create_plist(dset_in)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_create_plist failed"); + if((rank = H5Sget_simple_extent_ndims(space_id)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sget_simple_extent_ndims failed"); + if(H5Sget_simple_extent_dims(space_id, dims, NULL) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sget_simple_extent_dims failed"); + nelmts = 1; + for(k = 0; k < rank; k++) + nelmts *= dims[k]; + + if((mtype_id = h5tools_get_native_type(ftype_id)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "h5tools_get_native_type failed"); + + if((msize = H5Tget_size(mtype_id)) == 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tget_size failed"); + + /*------------------------------------------------------------------------- + * check if the dataset creation property list has filters that + * are not registered in the current configuration + * 1) the external filters GZIP and SZIP might not be available + * 2) the internal filters might be turned off + *------------------------------------------------------------------------- + */ + if(h5tools_canreadf(NULL, dcpl_id) == 1) { + /*------------------------------------------------------------------------- + * test for a valid output dataset + *------------------------------------------------------------------------- + */ + dset_out = FAIL; + + /*------------------------------------------------------------------------- + * object references are a special case + * we cannot just copy the buffers, but instead we recreate the reference + *------------------------------------------------------------------------- + */ + if(H5Tequal(mtype_id, H5T_STD_REF_OBJ)) { + hid_t refobj_id; + hobj_ref_t *refbuf = NULL; /* buffer for object references */ + hobj_ref_t *buf = NULL; + const char* refname; + unsigned u; + + /*------------------------------------------------------------------------- + * read to memory + *------------------------------------------------------------------------- + */ + if(nelmts) { + buf = (hobj_ref_t *)HDmalloc((unsigned)(nelmts * msize)); + if(buf==NULL) { + printf("cannot read into memory\n" ); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDmalloc failed"); + } /* end if */ + if(H5Dread(dset_in, mtype_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dread failed"); + + refbuf = (hobj_ref_t*) HDcalloc((unsigned)nelmts, msize); + if(refbuf == NULL){ + printf("cannot allocate memory\n" ); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDcalloc failed"); + } /* end if */ + for(u = 0; u < nelmts; u++) { + H5E_BEGIN_TRY { + if((refobj_id = H5Rdereference2(dset_in, H5P_DEFAULT, H5R_OBJECT, &buf[u])) < 0) + continue; + } H5E_END_TRY; + + /* get the name. a valid name could only occur + * in the second traversal of the file + */ + if((refname = MapIdToName(refobj_id, travt)) != NULL) { + /* create the reference, -1 parameter for objects */ + if(H5Rcreate(&refbuf[u], fidout, refname, H5R_OBJECT, (hid_t)-1) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Rcreate failed"); + if(options->verbose) + { + printf(FORMAT_OBJ,"dset",travt->objs[i].name ); + printf("object <%s> object reference created to <%s>\n", + travt->objs[i].name, + refname); + } + } /*refname*/ + H5Oclose(refobj_id); + } /* u */ + } /*nelmts*/ + + /*------------------------------------------------------------------------- + * create/write dataset/close + *------------------------------------------------------------------------- + */ + if((dset_out = H5Dcreate2(fidout, travt->objs[i].name, mtype_id, space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dcreate2 failed"); + if(nelmts) + if(H5Dwrite(dset_out, mtype_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, refbuf) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dwrite failed"); + + if(buf) + HDfree(buf); + if(refbuf) + HDfree(refbuf); + + /*------------------------------------------------------ + * copy attrs + *----------------------------------------------------*/ + if(copy_attr(dset_in, dset_out, &named_dt_head, travt, options) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_attr failed"); + } /*H5T_STD_REF_OBJ*/ + + /*------------------------------------------------------------------------- + * dataset region references + *------------------------------------------------------------------------- + */ + else if(H5Tequal(mtype_id, H5T_STD_REF_DSETREG)) + { + hid_t refobj_id; + hdset_reg_ref_t *refbuf = NULL; /* input buffer for region references */ + hdset_reg_ref_t *buf = NULL; /* output buffer */ + const char* refname; + unsigned u; + + /*------------------------------------------------------------------------- + * read input to memory + *------------------------------------------------------------------------- + */ + if(nelmts) { + buf = (hdset_reg_ref_t *)HDmalloc((unsigned)(nelmts * msize)); + if(buf == NULL) { + printf("cannot read into memory\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDmalloc failed"); + } /* end if */ + if(H5Dread(dset_in, mtype_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dread failed"); + + /*------------------------------------------------------------------------- + * create output + *------------------------------------------------------------------------- + */ + refbuf = (hdset_reg_ref_t *)HDcalloc(sizeof(hdset_reg_ref_t), (size_t)nelmts); /*init to zero */ + if(refbuf == NULL) { + printf("cannot allocate memory\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDcalloc failed"); + } /* end if */ + + for(u = 0; u < nelmts; u++) { + H5E_BEGIN_TRY { + if((refobj_id = H5Rdereference2(dset_in, H5P_DEFAULT, H5R_DATASET_REGION, &buf[u])) < 0) + continue; + } H5E_END_TRY; + + /* get the name. a valid name could only occur + * in the second traversal of the file + */ + if((refname = MapIdToName(refobj_id, travt)) != NULL) { + hid_t region_id; /* region id of the referenced dataset */ + + if((region_id = H5Rget_region(dset_in, H5R_DATASET_REGION, &buf[u])) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Rget_region failed"); + + /* create the reference, we need the space_id */ + if(H5Rcreate(&refbuf[u], fidout, refname, H5R_DATASET_REGION, region_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Rcreate failed"); + if(H5Sclose(region_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sclose failed"); + if(options->verbose) + { + printf(FORMAT_OBJ,"dset",travt->objs[i].name ); + printf("object <%s> region reference created to <%s>\n", + travt->objs[i].name, + refname); + } + } /*refname*/ + H5Oclose(refobj_id); + } /* u */ + } /*nelmts*/ + + /*------------------------------------------------------------------------- + * create/write dataset/close + *------------------------------------------------------------------------- + */ + if((dset_out = H5Dcreate2(fidout, travt->objs[i].name, mtype_id, space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dcreate2 failed"); + if(nelmts) + if(H5Dwrite(dset_out, mtype_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, refbuf) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dwrite failed"); + + if(buf) + HDfree(buf); + if(refbuf) + HDfree(refbuf); + + /*----------------------------------------------------- + * copy attrs + *----------------------------------------------------*/ + if(copy_attr(dset_in, dset_out, &named_dt_head, travt, options) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_attr failed"); + } /* H5T_STD_REF_DSETREG */ + /*------------------------------------------------------------------------- + * not references, open previously created object in 1st traversal + *------------------------------------------------------------------------- + */ + else { + if((dset_out = H5Dopen2(fidout, travt->objs[i].name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dopen2 failed"); + } /* end else */ + + HDassert(dset_out != FAIL); + + /*------------------------------------------------------------------------- + * copy referenced objects in attributes + *------------------------------------------------------------------------- + */ + if(copy_refs_attr(dset_in, dset_out, options, travt, fidout) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "copy_refs_attr failed"); + + /*------------------------------------------------------------------------- + * check for hard links + *------------------------------------------------------------------------- + */ + if(travt->objs[i].nlinks) + for(j = 0; j < travt->objs[i].nlinks; j++) + H5Lcreate_hard(fidout, travt->objs[i].name, H5L_SAME_LOC, travt->objs[i].links[j].new_name, H5P_DEFAULT, H5P_DEFAULT); + + if(H5Dclose(dset_out) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dclose failed"); + } /*can_read*/ + + /*------------------------------------------------------------------------- + * close + *------------------------------------------------------------------------- + */ + if(H5Tclose(ftype_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); + if(H5Tclose(mtype_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); + if(H5Pclose(dcpl_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + if(H5Sclose(space_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sclose failed"); + if(H5Dclose(dset_in) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dclose failed"); + break; + + /*------------------------------------------------------------------------- + * H5TRAV_TYPE_NAMED_DATATYPE + *------------------------------------------------------------------------- + */ + case H5TRAV_TYPE_NAMED_DATATYPE: + if((type_in = H5Topen2(fidin, travt->objs[i].name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Topen2 failed"); + if(H5Tclose(type_in) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); + break; + + /*------------------------------------------------------------------------- + * H5TRAV_TYPE_LINK + *------------------------------------------------------------------------- + */ + case H5TRAV_TYPE_LINK: + /*nothing to do */ + break; + + case H5TRAV_TYPE_UNKNOWN: + case H5TRAV_TYPE_UDLINK: + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5TRAV invalid type"); + + default: + break; + } /* end switch */ + } /* end for */ + + /* Finalize (link) the stack of named datatypes (if any) + * This function is paired with copy_named_datatype() which is called + * in copy_attr(), so need to free. + */ + named_datatype_free(&named_dt_head, 0); + + return ret_value; + +done: + H5E_BEGIN_TRY { + H5Gclose(grp_in); + H5Gclose(grp_out); + H5Pclose(dcpl_id); + H5Sclose(space_id); + H5Dclose(dset_in); + H5Dclose(dset_out); + H5Tclose(ftype_id); + H5Tclose(mtype_id); + H5Tclose(type_in); + named_datatype_free(&named_dt_head, 0); + } H5E_END_TRY; + + return ret_value; +} + + +/*------------------------------------------------------------------------- + * Function: copy_refs_attr + * + * Purpose: duplicate all referenced HDF5 located in attributes + * relative to LOC_IN, which is obtained either from + * loc_id = H5Gopen2(fid, name, H5P_DEFAULT); + * loc_id = H5Dopen2(fid, name, H5P_DEFAULT); + * loc_id = H5Topen2(fid, name, H5P_DEFAULT); + * + * Return: 0, ok, -1 no + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Modifier: xcao@hdfgroup.org, 9/12/2011 + * Update values of references(object and region) for the following types: + * 1) References, + * 2) ARRAY of reference, + * 3) VLEN of references. + * 4) COMPOUND of references. + * This function does not handle references in other complicated structures, + * such as references in nested compound datatypes. + * + * Date: October, 28, 2003 + * + *------------------------------------------------------------------------- + */ + +static int copy_refs_attr(hid_t loc_in, + hid_t loc_out, + pack_opt_t *options, + trav_table_t *travt, + hid_t fidout /* for saving references */ + ) +{ + int ret_value = 0; /*no need to LEAVE() on ERROR: HERR_INIT(int, SUCCEED) */ + hid_t attr_id = -1; /* attr ID */ + hid_t attr_out = -1; /* attr ID */ + hid_t space_id = -1; /* space ID */ + hid_t ftype_id = -1; /* file data type ID */ + hid_t mtype_id = -1; /* memory data type ID */ + size_t msize; /* memory size of type */ + hsize_t nelmts; /* number of elements in dataset */ + hsize_t dims[H5S_MAX_RANK];/* dimensions of dataset */ + char name[255]; + H5O_info_t oinfo; /* Object info */ + unsigned u, i, j; + int rank; + H5T_class_t type_class = -1; + hbool_t is_ref=0, is_ref_vlen=0, is_ref_array=0, is_ref_comp=0; + void *refbuf = NULL; + void *buf = NULL; + const char* refname = NULL; + unsigned *ref_comp_index = NULL; + size_t *ref_comp_size = NULL; + int ref_comp_field_n = 0; + + + if(H5Oget_info(loc_in, &oinfo) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Oget_info failed"); + + for(u = 0; u < (unsigned)oinfo.num_attrs; u++) { + is_ref = is_ref_vlen = is_ref_array = is_ref_comp = 0; + + /* open attribute */ + if((attr_id = H5Aopen_by_idx(loc_in, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)u, H5P_DEFAULT, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aopen_by_idx failed"); + + /* get the file datatype */ + if((ftype_id = H5Aget_type(attr_id)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aget_type failed"); + + type_class = H5Tget_class(ftype_id); + + if((mtype_id = h5tools_get_native_type(ftype_id)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "h5tools_get_native_type failed"); + + if((msize = H5Tget_size(mtype_id)) == 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tget_size failed"); + + is_ref = (type_class == H5T_REFERENCE); + + if(type_class == H5T_VLEN ) { + hid_t base_type; + + base_type = H5Tget_super(ftype_id); + is_ref_vlen = (H5Tget_class(base_type)==H5T_REFERENCE); + msize = H5Tget_size(base_type); + H5Tclose(base_type); + } + else if(type_class == H5T_ARRAY ) { + hid_t base_type; + + base_type = H5Tget_super(ftype_id); + is_ref_array = (H5Tget_class(base_type)==H5T_REFERENCE); + msize = H5Tget_size(base_type); + H5Tclose(base_type); + } + else if(type_class == H5T_COMPOUND) { + int nmembers = H5Tget_nmembers(ftype_id) ; + + if (nmembers < 1) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tget_nmembers failed"); + + ref_comp_index = (unsigned *)HDmalloc((size_t)nmembers*sizeof(unsigned)); + ref_comp_size = (size_t *)HDmalloc((size_t)nmembers*sizeof(ref_comp_size)); + ref_comp_field_n = 0; + + for (i=0; i<(unsigned)nmembers; i++) { + hid_t mtid = H5Tget_member_type( ftype_id, i ); + + if ((H5Tget_class(mtid)==H5T_REFERENCE)) { + ref_comp_index[ref_comp_field_n] = i; + ref_comp_size[ref_comp_field_n] = H5Tget_size(mtid); + ref_comp_field_n++; + } + H5Tclose(mtid); + } + + /* if compound don't contain reference type member, free the above + * mallocs. Otherwise there can be memory leaks by the 'continue' + * statement below. */ + if (!ref_comp_field_n) { + if (ref_comp_index) { + HDfree(ref_comp_index); + ref_comp_index = NULL; + } + + if (ref_comp_size) { + HDfree(ref_comp_size); + ref_comp_size = NULL; + } + } + } + + is_ref_comp = (ref_comp_field_n > 0); + + if (!(is_ref || is_ref_vlen || is_ref_array || is_ref_comp)) { + H5Tclose(mtype_id); + H5Tclose(ftype_id); + H5Aclose(attr_id); + continue; + } + + /* get name */ + if(H5Aget_name(attr_id, 255, name) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aget_name failed"); + + /* get the dataspace handle */ + if((space_id = H5Aget_space(attr_id)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aget_space failed"); + + /* get dimensions */ + if((rank = H5Sget_simple_extent_dims(space_id, dims, NULL)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sget_simple_extent_dims failed"); + + + /*------------------------------------------------------------------------- + * elements + *------------------------------------------------------------------------- + */ + nelmts = 1; + for(j = 0; j < (unsigned)rank; j++) + nelmts *= dims[j]; + + if (is_ref_array) { + unsigned array_rank = 0; + hsize_t array_size = 1; + hsize_t array_dims[H5S_MAX_RANK]; + hid_t base_type; + + base_type = H5Tget_super(ftype_id); + msize = H5Tget_size(base_type); + H5Tclose(base_type); + + array_rank = (unsigned)H5Tget_array_ndims(mtype_id); + H5Tget_array_dims2(mtype_id, array_dims); + for(j = 0; j <array_rank; j++) + array_size *= array_dims[j]; + nelmts *= array_size; + } + + if((attr_out = H5Acreate2(loc_out, name, ftype_id, space_id, H5P_DEFAULT, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Acreate2 failed"); + + if (nelmts>0) { + /* handle object references */ + if((is_ref || is_ref_array) && (H5R_OBJ_REF_BUF_SIZE==msize)) { + buf = (hobj_ref_t *)HDmalloc((unsigned)(nelmts * msize)); + if(buf == NULL) { + printf("cannot read into memory\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDmalloc failed"); + } /* end if */ + if(H5Aread(attr_id, mtype_id, buf) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aread failed"); + + refbuf = (hobj_ref_t *)HDcalloc((unsigned)nelmts, msize); + if(refbuf == NULL) { + printf("cannot allocate memory\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDcalloc failed"); + } /* end if */ + + for(i = 0; i < (unsigned)nelmts; i++) { + if (update_ref_value(attr_id, H5R_OBJECT, &((hobj_ref_t *)buf)[i], fidout, &((hobj_ref_t *)refbuf)[i], travt)<0) + continue; + if(options->verbose) + printf("object <%s> reference created to <%s>\n", name, refname); + } /* i */ + } /* H5T_STD_REF_OBJ */ + /* handle region references */ + else if((is_ref || is_ref_array) && (H5R_DSET_REG_REF_BUF_SIZE == msize)) { + buf = (hdset_reg_ref_t *)HDmalloc((unsigned)(nelmts * msize)); + + if(buf == NULL) { + printf( "cannot read into memory\n" ); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDmalloc failed"); + } /* end if */ + if(H5Aread(attr_id, mtype_id, buf) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aread failed"); + + /*------------------------------------------------------------------------- + * create output + *------------------------------------------------------------------------- + */ + refbuf = (hdset_reg_ref_t *)HDcalloc(sizeof(hdset_reg_ref_t), (size_t)nelmts); /*init to zero */ + if(refbuf == NULL) { + printf( "cannot allocate memory\n" ); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDcalloc failed"); + } /* end if */ + + for(i = 0; i < (unsigned)nelmts; i++) { + if (update_ref_value(attr_id, H5R_DATASET_REGION, &((hdset_reg_ref_t *)buf)[i], fidout, &((hdset_reg_ref_t *)refbuf)[i], travt)<0) + continue; + if(options->verbose) + printf("object <%s> region reference created to <%s>\n", name, refname); + } + } /* H5T_STD_REF_DSETREG */ + else if (is_ref_vlen) { + /* handle VLEN of references */ + + buf = (hvl_t *)HDmalloc((unsigned)(nelmts * sizeof(hvl_t))); + refbuf = buf; /* reuse the read buffer for write */ + + if(buf == NULL) { + printf( "cannot read into memory\n" ); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDmalloc failed"); + } /* end if */ + + if(H5Aread(attr_id, mtype_id, buf) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aread failed"); + + if (H5R_OBJ_REF_BUF_SIZE==msize) { + hobj_ref_t ref_out; + + for (i=0; i<(unsigned)nelmts; i++) { + hobj_ref_t *ptr = (hobj_ref_t *)((hvl_t *)buf)[i].p; + + for (j=0; j<((hvl_t *)buf)[i].len; j++ ) { + if (update_ref_value(attr_id, H5R_OBJECT, &(ptr[j]), fidout, &ref_out, travt)<0) + continue; + HDmemcpy(&(ptr[j]), &ref_out, msize); + } + } /* for (i=0; i<nelems; i++) */ + } else if (H5R_DSET_REG_REF_BUF_SIZE == msize) { + hdset_reg_ref_t ref_out; + + for (i=0; i<(unsigned)nelmts; i++) { + hdset_reg_ref_t *ptr = (hdset_reg_ref_t *)((hvl_t *)buf)[i].p; + + for (j=0; j<((hvl_t *)buf)[i].len; j++ ) { + if (update_ref_value(attr_id, H5R_DATASET_REGION, &(ptr[j]), fidout, &ref_out, travt)<0) + continue; + HDmemcpy(&(ptr[j]), &ref_out, msize); + } + } /* for (i=0; i<nelems; i++) */ + } + } /* else if (is_ref_vlen) */ + else if (is_ref_comp) { + /* handle ref fields in a compound */ + + buf = HDmalloc((unsigned)(nelmts * msize)); + refbuf = buf; /* reuse the read buffer for write */ + + if(buf == NULL) + { + printf( "cannot read into memory\n" ); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "HDmalloc failed"); + } /* end if */ + + if(H5Aread(attr_id, mtype_id, buf) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aread failed"); + + for (i=0; i<(unsigned)nelmts; i++) { + for (j=0; j<(unsigned)ref_comp_field_n; j++) { + if (ref_comp_size[j] == H5R_OBJ_REF_BUF_SIZE) { + size_t idx = (i * msize) + H5Tget_member_offset(mtype_id, ref_comp_index[j]); + hobj_ref_t ref_out; + + if (update_ref_value(attr_id, H5R_OBJECT, (hobj_ref_t *)(((char *)buf)+idx), fidout, &ref_out, travt)<0) + continue; + HDmemcpy(((char *)buf)+idx, &ref_out, ref_comp_size[j]); + } /* if */ + else if (ref_comp_size[j] == H5R_DSET_REG_REF_BUF_SIZE) { + size_t idx = i * msize + H5Tget_member_offset(mtype_id, ref_comp_index[j]); + hdset_reg_ref_t ref_out; + + if (update_ref_value(attr_id, H5R_DATASET_REGION, (hdset_reg_ref_t *)(((char *)buf)+idx), fidout, &ref_out, travt)<0) + continue; + HDmemcpy(((char *)buf)+idx, &ref_out, ref_comp_size[j]); + } /* else if */ + } /* j */ + } /* i */ + } /* else if (is_ref_comp) */ + + if(H5Awrite(attr_out, mtype_id, refbuf) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Awrite failed"); + + if (is_ref_vlen && buf) + H5Dvlen_reclaim (mtype_id, space_id, H5P_DEFAULT, buf); + } /* if (nelmts) */ + + if (refbuf == buf) + refbuf = NULL; /* set it to NULL to avoid double free since buf and refbuf are the same. */ + + if(buf) { + HDfree(buf); + buf = NULL; + } + + if(refbuf) { + HDfree(refbuf); + refbuf = NULL; + } + + if (ref_comp_index) { + HDfree(ref_comp_index); + ref_comp_index = NULL; + } + + if (ref_comp_size) { + HDfree(ref_comp_size); + ref_comp_size = NULL; + } + + if(H5Aclose(attr_out) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aclose failed"); + + /*------------------------------------------------------------------------- + * close + *------------------------------------------------------------------------- + */ + if(H5Tclose(ftype_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); + if(H5Tclose(mtype_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); + if(H5Sclose(space_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sclose failed"); + if(H5Aclose(attr_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Aclose failed"); + } /* for(u = 0; u < (unsigned)oinfo.num_attrs; u++) */ + + return ret_value; + +done: + if(refbuf) + HDfree(refbuf); + if(buf) + HDfree(buf); + + if (ref_comp_index) + HDfree(ref_comp_index); + + if (ref_comp_size) + HDfree(ref_comp_size); + + H5E_BEGIN_TRY { + H5Tclose(ftype_id); + H5Tclose(mtype_id); + H5Sclose(space_id); + H5Aclose(attr_id); + H5Aclose(attr_out); + } H5E_END_TRY; + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: MapIdToName + * + * Purpose: map a ID from a reference to a dataset name + * + *------------------------------------------------------------------------- + */ +static const char* +MapIdToName(hid_t refobj_id, trav_table_t *travt) +{ + unsigned int u; + const char* ret = NULL; + + /* linear search */ + for(u = 0; u < travt->nobjs; u++) { + if(travt->objs[u].type == (h5trav_type_t)H5O_TYPE_DATASET || + travt->objs[u].type == (h5trav_type_t)H5O_TYPE_GROUP || + travt->objs[u].type == (h5trav_type_t)H5O_TYPE_NAMED_DATATYPE) { + H5O_info_t ref_oinfo; /* Stat for the refobj id */ + + /* obtain information to identify the referenced object uniquely */ + if(H5Oget_info(refobj_id, &ref_oinfo) < 0) + goto out; + + if(ref_oinfo.addr == travt->objs[u].objno) { + ret = travt->objs[u].name; + goto out; + } /* end if */ + } /* end if */ + } /* u */ + +out: + return ret; +} + +/*------------------------------------------------------------------------- + * Function: Update_Ref_value + * + * Purpose: Update a reference value + * + * Programmer: xcao@hdfgroup.org 9/12/2011 + * + *------------------------------------------------------------------------- + */ +static herr_t update_ref_value(hid_t obj_id, H5R_type_t ref_type, void *ref_in, + hid_t fid_out, void *ref_out, trav_table_t *travt) +{ + int ret_value = 0; /*no need to LEAVE() on ERROR: HERR_INIT(int, SUCCEED) */ + const char* ref_obj_name; + hid_t space_id=-1, ref_obj_id=-1; + + ref_obj_id = H5Rdereference2(obj_id, H5P_DEFAULT, ref_type, ref_in); + if (ref_obj_id < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Rdereference2 failed"); + + ref_obj_name = MapIdToName(ref_obj_id, travt); + if (ref_obj_name == NULL) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "MapIdToName failed"); + + if (ref_type == H5R_DATASET_REGION) { + space_id = H5Rget_region(obj_id, H5R_DATASET_REGION, ref_in); + if (space_id < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Rget_region failed"); + } + + if(H5Rcreate(ref_out, fid_out, ref_obj_name, ref_type, space_id) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Rcreate failed"); + +done: + H5E_BEGIN_TRY { + H5Sclose(space_id); + H5Oclose(ref_obj_id); + } H5E_END_TRY; + + return ret_value; +} + diff --git a/tools/src/h5repack/h5repack_verify.c b/tools/src/h5repack/h5repack_verify.c new file mode 100644 index 0000000..6765c49 --- /dev/null +++ b/tools/src/h5repack/h5repack_verify.c @@ -0,0 +1,675 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "h5repack.h" +#include "h5tools.h" +#include "h5tools_utils.h" + +/* number of members in an array */ +#ifndef NELMTS +# define NELMTS(X) (sizeof(X)/sizeof(X[0])) +#endif + +static int verify_layout(hid_t pid, pack_info_t *obj); +static int verify_filters(hid_t pid, hid_t tid, int nfilters, filter_info_t *filter); + + +/*------------------------------------------------------------------------- + * Function: h5repack_verify + * + * Purpose: verify if filters and layout in the input file match the output file + * + * Return: + * 1 match + * 0 do not match + * -1 error + * + * Programmer: Pedro Vicente, pvn@hdfgroup.org + * + * Date: December 19, 2003 + * Modified: December, 19, 2007 (exactly 4 years later :-) ) + * Separate into 3 cases + * 1) no filter input, get all datasets and compare DCPLs. TO DO + * 2) filter input on selected datasets, get each one trough OBJ and match + * 3) filter input on all datasets, get all objects and match + * + *------------------------------------------------------------------------- + */ + +int +h5repack_verify(const char *in_fname, const char *out_fname, pack_opt_t *options) +{ + int ret_value = 0; /*no need to LEAVE() on ERROR: HERR_INIT(int, SUCCEED) */ + hid_t fidin = -1; /* file ID for input file*/ + hid_t fidout = -1; /* file ID for output file*/ + hid_t did = -1; /* dataset ID */ + hid_t pid = -1; /* dataset creation property list ID */ + hid_t sid = -1; /* space ID */ + hid_t tid = -1; /* type ID */ + unsigned int i; + trav_table_t *travt = NULL; + int ok = 1; + hid_t fcpl_in = -1; /* file creation property for input file */ + hid_t fcpl_out = -1; /* file creation property for output file */ + H5F_file_space_type_t in_strat, out_strat; /* file space handling strategy for in/output file */ + hsize_t in_thresh, out_thresh; /* free space section threshold for in/output file */ + + /* open the output file */ + if((fidout = H5Fopen(out_fname, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0 ) + return -1; + + for(i = 0; i < options->op_tbl->nelems; i++) + { + char* name = options->op_tbl->objs[i].path; + pack_info_t *obj = &options->op_tbl->objs[i]; + + /*------------------------------------------------------------------------- + * open + *------------------------------------------------------------------------- + */ + if((did = H5Dopen2(fidout, name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dopen2 failed"); + if((sid = H5Dget_space(did)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_space failed"); + if((pid = H5Dget_create_plist(did)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_create_plist failed"); + if((tid = H5Dget_type(did)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_type failed"); + + /*------------------------------------------------------------------------- + * filter check + *------------------------------------------------------------------------- + */ + if(verify_filters(pid, tid, obj->nfilters, obj->filter) <= 0) + ok = 0; + + + /*------------------------------------------------------------------------- + * layout check + *------------------------------------------------------------------------- + */ + if((obj->layout != -1) && (verify_layout(pid, obj) == 0)) + ok = 0; + + /*------------------------------------------------------------------------- + * close + *------------------------------------------------------------------------- + */ + if(H5Pclose(pid) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + if (H5Sclose(sid) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sclose failed"); + if (H5Dclose(did) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dclose failed"); + if (H5Tclose(tid) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); + + } + + + /*------------------------------------------------------------------------- + * check for the "all" objects option + *------------------------------------------------------------------------- + */ + + if(options->all_filter == 1 || options->all_layout == 1) + { + + /* init table */ + trav_table_init(&travt); + + /* get the list of objects in the file */ + if(h5trav_gettable(fidout, travt) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "h5trav_gettable failed"); + + for(i = 0; i < travt->nobjs; i++) + { + char *name = travt->objs[i].name; + + if(travt->objs[i].type == H5TRAV_TYPE_DATASET) + { + + /*------------------------------------------------------------------------- + * open + *------------------------------------------------------------------------- + */ + if((did = H5Dopen2(fidout, name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dopen2 failed"); + if((sid = H5Dget_space(did)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_space failed"); + if((pid = H5Dget_create_plist(did)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_create_plist failed"); + if((tid = H5Dget_type(did)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_type failed"); + + /*------------------------------------------------------------------------- + * filter check + *------------------------------------------------------------------------- + */ + if(options->all_filter == 1) + { + if(verify_filters(pid, tid, options->n_filter_g, options->filter_g) <= 0) + ok = 0; + } + + /*------------------------------------------------------------------------- + * layout check + *------------------------------------------------------------------------- + */ + if(options->all_layout == 1) + { + pack_info_t pack; + + init_packobject(&pack); + pack.layout = options->layout_g; + pack.chunk = options->chunk_g; + if(verify_layout(pid, &pack) == 0) + ok = 0; + } + + + /*------------------------------------------------------------------------- + * close + *------------------------------------------------------------------------- + */ + if (H5Pclose(pid) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + if (H5Sclose(sid) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Sclose failed"); + if (H5Dclose(did) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dclose failed"); + if (H5Tclose(tid) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Tclose failed"); + } /* if */ + + } /* i */ + + /* free table */ + trav_table_free(travt); + } + + /*------------------------------------------------------------------------- + * Verify that file space strategy and free space threshold + * are set as expected + *------------------------------------------------------------------------- + */ + + /* open the input file */ + if((fidin = H5Fopen(in_fname, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0 ) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Fopen failed"); + + /* Get file creation property list for input file */ + if((fcpl_in = H5Fget_create_plist(fidin)) < 0) { + error_msg("failed to retrieve file creation property list\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Fget_create_plist failed"); + } + + /* Get file space management info for input file */ + if(H5Pget_file_space(fcpl_in, &in_strat, &in_thresh) < 0) { + error_msg("failed to retrieve file space strategy & threshold\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pget_file_space failed"); + } + + /* Output file is already opened */ + /* Get file creation property list for output file */ + if((fcpl_out = H5Fget_create_plist(fidout)) < 0) { + error_msg("failed to retrieve file creation property list\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Fget_create_plist failed"); + } + + /* Get file space management info for output file */ + if(H5Pget_file_space(fcpl_out, &out_strat, &out_thresh) < 0) { + error_msg("failed to retrieve file space strategy & threshold\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pget_file_space failed"); + } + + /* + * If the strategy option is not set, + * file space handling strategy should be the same for both + * input & output files. + * If the strategy option is set, + * the output file's file space handling strategy should be the same + * as what is set via the strategy option + */ + if(!options->fs_strategy && out_strat != in_strat) { + error_msg("file space strategy not set as unexpected\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "file space strategy not set as unexpected"); + + } + else if(options->fs_strategy && out_strat!= options->fs_strategy) { + error_msg("file space strategy not set as unexpected\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "file space strategy not set as unexpected"); + } + + /* + * If the threshold option is not set, + * the free space section threshold should be the same for both + * input & output files. + * If the threshold option is set, + * the output file's free space section threshold should be the same + * as what is set via the threshold option. + */ + if(!options->fs_threshold && out_thresh != in_thresh) { + error_msg("free space threshold not set as unexpected\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "free space threshold not set as unexpected"); + } + else if(options->fs_threshold && out_thresh != options->fs_threshold) { + error_msg("free space threshold not set as unexpected\n"); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "free space threshold not set as unexpected"); + } + + /* Closing */ + if (H5Pclose(fcpl_in) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + if (H5Pclose(fcpl_out) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + if (H5Fclose(fidin) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Fclose failed"); + if (H5Fclose(fidout) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Fclose failed"); + + return ok; + +done: + H5E_BEGIN_TRY { + H5Pclose(fcpl_in); + H5Pclose(fcpl_out); + H5Pclose(pid); + H5Sclose(sid); + H5Dclose(did); + H5Fclose(fidin); + H5Fclose(fidout); + if (travt) + trav_table_free(travt); + } H5E_END_TRY; + + return ret_value; +} /* h5repack_verify() */ + + + +/*------------------------------------------------------------------------- + * Function: verify_layout + * + * Purpose: verify which layout is present in the property list DCPL_ID + * + * H5D_COMPACT = 0 + * H5D_CONTIGUOUS = 1 + * H5D_CHUNKED = 2 + * + * Return: 1 has, 0 does not, -1 error + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: December 30, 2003 + * + *------------------------------------------------------------------------- + */ + +int verify_layout(hid_t pid, + pack_info_t *obj) +{ + hsize_t chsize[64]; /* chunk size in elements */ + H5D_layout_t layout; /* layout */ + int nfilters; /* number of filters */ + int rank; /* rank */ + int i; /* index */ + + /* check if we have filters in the input object */ + if ((nfilters = H5Pget_nfilters(pid)) < 0) + return -1; + + /* a non chunked layout was requested on a filtered object */ + if (nfilters && obj->layout!=H5D_CHUNKED) + return 0; + + /* get layout */ + if ((layout = H5Pget_layout(pid)) < 0) + return -1; + + if (obj->layout != layout) + return 0; + + if (layout==H5D_CHUNKED) + { + if ((rank = H5Pget_chunk(pid,NELMTS(chsize),chsize/*out*/)) < 0) + return -1; + if (obj->chunk.rank != rank) + return 0; + for ( i=0; i<rank; i++) + if (chsize[i] != obj->chunk.chunk_lengths[i]) + return 0; + } + + return 1; +} + +/*------------------------------------------------------------------------- + * Function: h5repack_cmp_pl + * + * Purpose: compare 2 files for identical property lists of all objects + * + * Return: 1=identical, 0=not identical, -1=error + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: December 31, 2003 + * + *------------------------------------------------------------------------- + */ + +int h5repack_cmp_pl(const char *fname1, + const char *fname2) +{ + int ret_value = 0; /*no need to LEAVE() on ERROR: HERR_INIT(int, SUCCEED) */ + hid_t fid1=-1; /* file ID */ + hid_t fid2=-1; /* file ID */ + hid_t dset1=-1; /* dataset ID */ + hid_t dset2=-1; /* dataset ID */ + hid_t gid=-1; /* group ID */ + hid_t dcpl1=-1; /* dataset creation property list ID */ + hid_t dcpl2=-1; /* dataset creation property list ID */ + hid_t gcplid=-1; /* group creation property list */ + unsigned crt_order_flag1; /* group creation order flag */ + unsigned crt_order_flag2; /* group creation order flag */ + trav_table_t *trav=NULL; + int ret=1; + unsigned int i; + + /*------------------------------------------------------------------------- + * open the files + *------------------------------------------------------------------------- + */ + + /* disable error reporting */ + H5E_BEGIN_TRY + { + + /* Open the files */ + if ((fid1 = H5Fopen(fname1,H5F_ACC_RDONLY,H5P_DEFAULT)) < 0 ) + { + error_msg("<%s>: %s\n", fname1, H5FOPENERROR ); + return -1; + } + if ((fid2 = H5Fopen(fname2,H5F_ACC_RDONLY,H5P_DEFAULT)) < 0 ) + { + error_msg("<%s>: %s\n", fname2, H5FOPENERROR ); + H5Fclose(fid1); + return -1; + } + /* enable error reporting */ + } H5E_END_TRY; + + /*------------------------------------------------------------------------- + * get file table list of objects + *------------------------------------------------------------------------- + */ + trav_table_init(&trav); + if(h5trav_gettable(fid1, trav) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "h5trav_gettable failed"); + + /*------------------------------------------------------------------------- + * traverse the suppplied object list + *------------------------------------------------------------------------- + */ + for(i = 0; i < trav->nobjs; i++) + { + + if(trav->objs[i].type == H5TRAV_TYPE_GROUP) + { + + if ((gid = H5Gopen2(fid1, trav->objs[i].name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gopen2 failed"); + if ((gcplid = H5Gget_create_plist(gid)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gget_create_plist failed"); + if (H5Pget_link_creation_order(gcplid, &crt_order_flag1) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pget_link_creation_order failed"); + if (H5Pclose(gcplid) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + if (H5Gclose(gid) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gclose failed"); + + if ((gid = H5Gopen2(fid2, trav->objs[i].name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gopen2 failed"); + if ((gcplid = H5Gget_create_plist(gid)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gget_create_plist failed"); + if (H5Pget_link_creation_order(gcplid, &crt_order_flag2) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pget_link_creation_order failed"); + if (H5Pclose(gcplid) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + if (H5Gclose(gid) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Gclose failed"); + + if (crt_order_flag1 != crt_order_flag2) { + error_msg("property lists for <%s> are different\n",trav->objs[i].name); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "property lists failed"); + } + + } + + + + else if(trav->objs[i].type == H5TRAV_TYPE_DATASET) + { + if((dset1 = H5Dopen2(fid1, trav->objs[i].name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dopen2 failed"); + if((dset2 = H5Dopen2(fid2, trav->objs[i].name, H5P_DEFAULT)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dopen2 failed"); + if((dcpl1 = H5Dget_create_plist(dset1)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_create_plist failed"); + if((dcpl2 = H5Dget_create_plist(dset2)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dget_create_plist failed"); + + /*------------------------------------------------------------------------- + * compare the property lists + *------------------------------------------------------------------------- + */ + if((ret = H5Pequal(dcpl1, dcpl2)) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pequal failed"); + + if(ret == 0) { + error_msg("property lists for <%s> are different\n",trav->objs[i].name); + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "property lists failed"); + } + + /*------------------------------------------------------------------------- + * close + *------------------------------------------------------------------------- + */ + if(H5Pclose(dcpl1) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + if(H5Pclose(dcpl2) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Pclose failed"); + if(H5Dclose(dset1) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dclose failed"); + if(H5Dclose(dset2) < 0) + HGOTO_ERROR(FAIL, H5E_tools_min_id_g, "H5Dclose failed"); + } /*if*/ + } /*i*/ + + /*------------------------------------------------------------------------- + * free + *------------------------------------------------------------------------- + */ + + trav_table_free(trav); + + /*------------------------------------------------------------------------- + * close + *------------------------------------------------------------------------- + */ + + H5Fclose(fid1); + H5Fclose(fid2); + + return ret; + +/*------------------------------------------------------------------------- +* error +*------------------------------------------------------------------------- +*/ +done: + H5E_BEGIN_TRY + { + H5Pclose(dcpl1); + H5Pclose(dcpl2); + H5Dclose(dset1); + H5Dclose(dset2); + H5Fclose(fid1); + H5Fclose(fid2); + H5Pclose(gcplid); + H5Gclose(gid); + trav_table_free(trav); + } H5E_END_TRY; + + return ret_value; +} + + +/*------------------------------------------------------------------------- + * Function: verify_filters + * + * Purpose: verify if all requested filters in the array FILTER obtained + * from user input are present in the property list PID obtained from + * the output file + * + * Return: + * 1 match + * 0 do not match + * -1 error + * + * Programmer: Pedro Vicente, pvn@hdfgroup.org + * + * Date: December 21, 2007 + * + *------------------------------------------------------------------------- + */ + +static +int verify_filters(hid_t pid, hid_t tid, int nfilters, filter_info_t *filter) +{ + int nfilters_dcpl; /* number of filters in DCPL*/ + unsigned filt_flags; /* filter flags */ + H5Z_filter_t filtn; /* filter identification number */ + unsigned cd_values[20]; /* filter client data values */ + size_t cd_nelmts; /* filter client number of values */ + char f_name[256]; /* filter name */ + size_t size; /* type size */ + int i; /* index */ + unsigned j; /* index */ + + /* get information about filters */ + if((nfilters_dcpl = H5Pget_nfilters(pid)) < 0) + return -1; + + /* if we do not have filters and the requested filter is NONE, return 1 */ + if(!nfilters_dcpl && + nfilters == 1 && + filter[0].filtn == H5Z_FILTER_NONE ) + return 1; + + /* else the numbers of filters must match */ + if (nfilters_dcpl != nfilters ) + return 0; + + /*------------------------------------------------------------------------- + * build a list with DCPL filters + *------------------------------------------------------------------------- + */ + + for( i = 0; i < nfilters_dcpl; i++) + { + cd_nelmts = NELMTS(cd_values); + filtn = H5Pget_filter2(pid, (unsigned)i, &filt_flags, &cd_nelmts, + cd_values, sizeof(f_name), f_name, NULL); + + /* filter ID */ + if (filtn != filter[i].filtn) + return 0; + + /* compare client data values. some filters do return local values */ + switch (filtn) + { + + case H5Z_FILTER_NONE: + break; + + case H5Z_FILTER_SHUFFLE: + /* 1 private client value is returned by DCPL */ + if ( cd_nelmts != H5Z_SHUFFLE_TOTAL_NPARMS && filter[i].cd_nelmts != H5Z_SHUFFLE_USER_NPARMS ) + return 0; + + /* get dataset's type size */ + if((size = H5Tget_size(tid)) <= 0) + return -1; + + /* the private client value holds the dataset's type size */ + if ( size != cd_values[0] ) + return 0; + + break; + + case H5Z_FILTER_SZIP: + /* 4 private client values are returned by DCPL */ + if ( cd_nelmts != H5Z_SZIP_TOTAL_NPARMS && filter[i].cd_nelmts != H5Z_SZIP_USER_NPARMS ) + return 0; + + /* "User" parameter for pixels-per-block (index 1) */ + if ( cd_values[H5Z_SZIP_PARM_PPB] != filter[i].cd_values[H5Z_SZIP_PARM_PPB] ) + return 0; + + break; + + case H5Z_FILTER_NBIT: + /* only client data values number of values checked */ + if ( H5Z_NBIT_USER_NPARMS != filter[i].cd_nelmts) + return 0; + break; + + case H5Z_FILTER_SCALEOFFSET: + /* only client data values checked */ + for( j = 0; j < H5Z_SCALEOFFSET_USER_NPARMS; j++) + if (cd_values[j] != filter[i].cd_values[j]) + return 0; + break; + + /* for these filters values must match, no local values set in DCPL */ + case H5Z_FILTER_FLETCHER32: + case H5Z_FILTER_DEFLATE: + + if ( cd_nelmts != filter[i].cd_nelmts) + return 0; + + for( j = 0; j < cd_nelmts; j++) + if (cd_values[j] != filter[i].cd_values[j]) + return 0; + + break; + + default: + if ( cd_nelmts != filter[i].cd_nelmts) + return 0; + + for( j = 0; j < cd_nelmts; j++) + if (cd_values[j] != filter[i].cd_values[j]) + return 0; + break; + + } /* switch */ + } + + return 1; +} + diff --git a/tools/src/h5stat/CMakeLists.txt b/tools/src/h5stat/CMakeLists.txt new file mode 100644 index 0000000..d4e14cb --- /dev/null +++ b/tools/src/h5stat/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required (VERSION 3.1.0) +PROJECT (HDF5_TOOLS_SRC_H5STAT) + +#----------------------------------------------------------------------------- +# Setup include Directories +#----------------------------------------------------------------------------- +INCLUDE_DIRECTORIES (${HDF5_TOOLS_DIR}/lib) + +# -------------------------------------------------------------------- +# Add the h5stat executables +# -------------------------------------------------------------------- +add_executable (h5stat ${HDF5_TOOLS_SRC_H5STAT_SOURCE_DIR}/h5stat.c) +TARGET_NAMING (h5stat STATIC) +TARGET_C_PROPERTIES (h5stat STATIC " " " ") +target_link_libraries (h5stat ${HDF5_TOOLS_LIB_TARGET} ${HDF5_LIB_TARGET}) +set_target_properties (h5stat PROPERTIES FOLDER tools) +set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};h5stat") + +set (H5_DEP_EXECUTABLES h5stat) + +############################################################################## +############################################################################## +### I N S T A L L A T I O N ### +############################################################################## +############################################################################## + +#----------------------------------------------------------------------------- +# Rules for Installation of tools using make Install target +#----------------------------------------------------------------------------- + +#INSTALL_PROGRAM_PDB (h5stat ${HDF5_INSTALL_BIN_DIR} toolsapplications) + +install ( + TARGETS + h5stat + EXPORT + ${HDF5_EXPORTED_TARGETS} + RUNTIME DESTINATION ${HDF5_INSTALL_BIN_DIR} COMPONENT toolsapplications +) diff --git a/tools/src/h5stat/Makefile.am b/tools/src/h5stat/Makefile.am new file mode 100644 index 0000000..b4d81de --- /dev/null +++ b/tools/src/h5stat/Makefile.am @@ -0,0 +1,39 @@ +# +# Copyright by The HDF Group. +# Copyright by the Board of Trustees of the University of Illinois. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the files COPYING and Copyright.html. COPYING can be found at the root +# of the source code distribution tree; Copyright.html can be found at the +# root level of an installed copy of the electronic HDF5 document set and +# is linked from the top-level documents page. It can also be found at +# http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have +# access to either file, you may request a copy from help@hdfgroup.org. +## +## Makefile.am +## Run automake to generate a Makefile.in from this file. +# +# HDF5 Library Makefile(.in) +# + +include $(top_srcdir)/config/commence.am + +# Include src directory +AM_CPPFLAGS+=-I$(top_srcdir)/src -I$(top_srcdir)/tools/lib + +# These are our main targets, the tools +bin_PROGRAMS=h5stat +bin_SCRIPTS= + +# Add h5stat specific linker flags here +h5stat_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) + +# Tell automake to clean h5redeploy script +CLEANFILES= + +# All programs rely on hdf5 library and h5tools library +LDADD=$(LIBH5TOOLS) $(LIBHDF5) + +include $(top_srcdir)/config/conclude.am diff --git a/tools/src/h5stat/h5stat.c b/tools/src/h5stat/h5stat.c new file mode 100644 index 0000000..a331014 --- /dev/null +++ b/tools/src/h5stat/h5stat.c @@ -0,0 +1,1815 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include <stdlib.h> +#include <string.h> +#include "H5private.h" /* Generic Functions */ +#include "h5tools.h" +#include "h5tools_utils.h" +#include "h5tools_ref.h" +#include "h5trav.h" +#include "hdf5.h" + +/* Name of tool */ +#define PROGRAMNAME "h5stat" + +/* Parameters to control statistics gathered */ + +/* Default threshold for small groups/datasets/attributes */ +#define DEF_SIZE_SMALL_GROUPS 10 +#define DEF_SIZE_SMALL_DSETS 10 +#define DEF_SIZE_SMALL_ATTRS 10 + +#define SIZE_SMALL_SECTS 10 + +#define H5_NFILTERS_IMPL 8 /* Number of currently implemented filters + one to + accommodate for user-define filters + one + to accomodate datasets whithout any filters */ + +/* File space management strategies: see H5Fpublic.h for declarations */ +const char *FS_STRATEGY_NAME[] = { + "unknown", + "H5F_FILE_SPACE_ALL_PERSIST", + "H5F_FILE_SPACE_ALL", + "H5F_FILE_SPACE_AGGR_VFD", + "H5F_FILE_SPACE_VFD", + NULL +}; + +/* Datatype statistics for datasets */ +typedef struct dtype_info_t { + hid_t tid; /* ID of datatype */ + unsigned long count; /* Number of types found */ + unsigned long named; /* Number of types that are named */ +} dtype_info_t; + +typedef struct ohdr_info_t { + hsize_t total_size; /* Total size of object headers */ + hsize_t free_size; /* Total free space in object headers */ +} ohdr_info_t; + +/* Info to pass to the iteration functions */ +typedef struct iter_t { + hid_t fid; /* File ID */ + hsize_t filesize; /* Size of the file */ + unsigned long uniq_groups; /* Number of unique groups */ + unsigned long uniq_dsets; /* Number of unique datasets */ + unsigned long uniq_dtypes; /* Number of unique named datatypes */ + unsigned long uniq_links; /* Number of unique links */ + unsigned long uniq_others; /* Number of other unique objects */ + + 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 of small groups tracked */ + unsigned group_nbins; /* Number of bins for group counts */ + unsigned long *group_bins; /* Pointer to array of bins for group counts */ + ohdr_info_t group_ohdr_info; /* Object header information for groups */ + + hsize_t max_attrs; /* Maximum attributes from a group */ + unsigned long *num_small_attrs; /* Size of small attributes tracked */ + unsigned attr_nbins; /* Number of bins for attribute counts */ + unsigned long *attr_bins; /* Pointer to array of bins for attribute counts */ + + unsigned max_dset_rank; /* Maximum rank of dataset */ + unsigned long dset_rank_count[H5S_MAX_RANK]; /* Number of datasets of each rank */ + hsize_t max_dset_dims; /* Maximum dimension size of dataset */ + unsigned long *small_dset_dims; /* Size of dimensions of small datasets tracked */ + unsigned long dset_layouts[H5D_NLAYOUTS]; /* Type of storage for each dataset */ + unsigned long dset_comptype[H5_NFILTERS_IMPL]; /* Number of currently implemented filters */ + unsigned long dset_ntypes; /* Number of diff. dataset datatypes found */ + dtype_info_t *dset_type_info; /* Pointer to dataset datatype information found */ + unsigned dset_dim_nbins; /* Number of bins for dataset dimensions */ + unsigned long *dset_dim_bins; /* Pointer to array of bins for dataset dimensions */ + ohdr_info_t dset_ohdr_info; /* Object header information for datasets */ + hsize_t dset_storage_size; /* Size of raw data for datasets */ + hsize_t dset_external_storage_size; /* Size of raw data for datasets with external storage */ + ohdr_info_t dtype_ohdr_info; /* Object header information for datatypes */ + hsize_t groups_btree_storage_size; /* btree size for group */ + hsize_t groups_heap_storage_size; /* heap size for group */ + hsize_t attrs_btree_storage_size; /* btree size for attributes (1.8) */ + hsize_t attrs_heap_storage_size; /* fractal heap size for attributes (1.8) */ + hsize_t SM_hdr_storage_size; /* header size for SOHM table (1.8) */ + hsize_t SM_index_storage_size; /* index (btree & list) size for SOHM table (1.8) */ + hsize_t SM_heap_storage_size; /* fractal heap size for SOHM table (1.8) */ + hsize_t super_size; /* superblock size */ + hsize_t super_ext_size; /* superblock extension size */ + hsize_t ublk_size; /* user block size (if exists) */ + H5F_file_space_type_t fs_strategy; /* File space management strategy */ + hsize_t fs_threshold; /* Free-space section threshold */ + hsize_t free_space; /* amount of freespace in the file */ + hsize_t free_hdr; /* size of free space manager metadata in the file */ + unsigned long num_small_sects[SIZE_SMALL_SECTS]; /* Size of small free-space sections */ + unsigned sect_nbins; /* Number of bins for free-space section sizes */ + unsigned long *sect_bins; /* Pointer to array of bins for free-space section sizes */ + hsize_t datasets_index_storage_size;/* meta size for chunked dataset's indexing type */ + hsize_t datasets_heap_storage_size; /* heap size for dataset with external storage */ + unsigned long nexternal; /* Number of external files for a dataset */ + int local; /* Flag to indicate iteration over the object*/ +} iter_t; + + +static int display_all = TRUE; + +/* Enable the printing of selected statistics */ +static int display_file = FALSE; /* display file information */ +static int display_group = FALSE; /* display groups information */ +static int display_dset = FALSE; /* display datasets information */ +static int display_dset_dtype_meta = FALSE; /* display datasets' datatype information */ +static int display_attr = FALSE; /* display attributes information */ +static int display_free_sections = FALSE; /* display free space information */ +static int display_summary = FALSE; /* display summary of file space information */ + +static int display_file_metadata = FALSE; /* display file space info for file's metadata */ +static int display_group_metadata = FALSE; /* display file space info for groups' metadata */ +static int display_dset_metadata = FALSE; /* display file space info for datasets' metadata */ + +static int display_object = FALSE; /* not implemented yet */ + +/* Initialize threshold for small groups/datasets/attributes */ +static int sgroups_threshold = DEF_SIZE_SMALL_GROUPS; +static int sdsets_threshold = DEF_SIZE_SMALL_DSETS; +static int sattrs_threshold = DEF_SIZE_SMALL_ATTRS; + +/* a structure for handling the order command-line parameters come in */ +struct handler_t { + size_t obj_count; + char **obj; +}; + +static const char *s_opts ="Aa:Ddm:FfhGgl:sSTO:V"; +/* e.g. "filemetadata" has to precede "file"; "groupmetadata" has to precede "group" etc. */ +static struct long_options l_opts[] = { + {"help", no_arg, 'h'}, + {"hel", no_arg, 'h'}, + {"he", no_arg, 'h'}, + {"filemetadata", no_arg, 'F'}, + {"filemetadat", no_arg, 'F'}, + {"filemetada", no_arg, 'F'}, + {"filemetad", no_arg, 'F'}, + {"filemeta", no_arg, 'F'}, + {"filemet", no_arg, 'F'}, + {"fileme", no_arg, 'F'}, + {"filem", no_arg, 'F'}, + {"file", no_arg, 'f'}, + {"fil", no_arg, 'f'}, + {"fi", no_arg, 'f'}, + {"groupmetadata", no_arg, 'G'}, + {"groupmetadat", no_arg, 'G'}, + {"groupmetada", no_arg, 'G'}, + {"groupmetad", no_arg, 'G'}, + {"groupmeta", no_arg, 'G'}, + {"groupmet", no_arg, 'G'}, + {"groupme", no_arg, 'G'}, + {"groupm", no_arg, 'G'}, + {"group", no_arg, 'g'}, + {"grou", no_arg, 'g'}, + {"gro", no_arg, 'g'}, + {"gr", no_arg, 'g'}, + { "links", require_arg, 'l' }, + { "link", require_arg, 'l' }, + { "lin", require_arg, 'l' }, + { "li", require_arg, 'l' }, + {"dsetmetadata", no_arg, 'D'}, + {"dsetmetadat", no_arg, 'D'}, + {"dsetmetada", no_arg, 'D'}, + {"dsetmetad", no_arg, 'D'}, + {"dsetmeta", no_arg, 'D'}, + {"dsetmet", no_arg, 'D'}, + {"dsetme", no_arg, 'D'}, + {"dsetm", no_arg, 'D'}, + {"dset", no_arg, 'd'}, + {"dse", no_arg, 'd'}, + {"ds", no_arg, 'd'}, + {"dims", require_arg, 'm'}, + {"dim", require_arg, 'm'}, + {"di", require_arg, 'm'}, + {"dtypemetadata", no_arg, 'T'}, + {"dtypemetadat", no_arg, 'T'}, + {"dtypemetada", no_arg, 'T'}, + {"dtypemetad", no_arg, 'T'}, + {"dtypemeta", no_arg, 'T'}, + {"dtypemet", no_arg, 'T'}, + {"dtypeme", no_arg, 'T'}, + {"dtypem", no_arg, 'T'}, + {"dtype", no_arg, 'T'}, + {"dtyp", no_arg, 'T'}, + {"dty", no_arg, 'T'}, + {"dt", no_arg, 'T'}, + { "object", require_arg, 'O' }, + { "objec", require_arg, 'O' }, + { "obje", require_arg, 'O' }, + { "obj", require_arg, 'O' }, + { "ob", require_arg, 'O' }, + { "version", no_arg, 'V' }, + { "versio", no_arg, 'V' }, + { "versi", no_arg, 'V' }, + { "vers", no_arg, 'V' }, + { "ver", no_arg, 'V' }, + { "ve", no_arg, 'V' }, + { "attribute", no_arg, 'A' }, + { "attribut", no_arg, 'A' }, + { "attribu", no_arg, 'A' }, + { "attrib", no_arg, 'A' }, + { "attri", no_arg, 'A' }, + { "attr", no_arg, 'A' }, + { "att", no_arg, 'A' }, + { "at", no_arg, 'A' }, + { "numattrs", require_arg, 'a' }, + { "numattr", require_arg, 'a' }, + { "numatt", require_arg, 'a' }, + { "numat", require_arg, 'a' }, + { "numa", require_arg, 'a' }, + { "num", require_arg, 'a' }, + { "nu", require_arg, 'a' }, + { "freespace", no_arg, 's' }, + { "freespac", no_arg, 's' }, + { "freespa", no_arg, 's' }, + { "freesp", no_arg, 's' }, + { "frees", no_arg, 's' }, + { "free", no_arg, 's' }, + { "fre", no_arg, 's' }, + { "fr", no_arg, 's' }, + { "summary", no_arg, 'S' }, + { "summar", no_arg, 'S' }, + { "summa", no_arg, 'S' }, + { "summ", no_arg, 'S' }, + { "sum", no_arg, 'S' }, + { "su", no_arg, 'S' }, + { NULL, 0, '\0' } +}; + +static void +leave(int ret) +{ + h5tools_close(); + HDexit(ret); +} + + + +/*------------------------------------------------------------------------- + * Function: usage + * + * Purpose: Compute the ceiling of log_10(x) + * + * Return: >0 on success, 0 on failure + * + *------------------------------------------------------------------------- + */ +static void usage(const char *prog) +{ + HDfflush(stdout); + HDfprintf(stdout, "Usage: %s [OPTIONS] file\n", prog); + HDfprintf(stdout, "\n"); + HDfprintf(stdout, " OPTIONS\n"); + HDfprintf(stdout, " -h, --help Print a usage message and exit\n"); + HDfprintf(stdout, " -V, --version Print version number and exit\n"); + HDfprintf(stdout, " -f, --file Print file information\n"); + HDfprintf(stdout, " -F, --filemetadata Print file space information for file's metadata\n"); + HDfprintf(stdout, " -g, --group Print group information\n"); + HDfprintf(stdout, " -l N, --links=N Set the threshold for the # of links when printing\n"); + HDfprintf(stdout, " information for small groups. N is an integer greater\n"); + HDfprintf(stdout, " than 0. The default threshold is 10.\n"); + HDfprintf(stdout, " -G, --groupmetadata Print file space information for groups' metadata\n"); + HDfprintf(stdout, " -d, --dset Print dataset information\n"); + HDfprintf(stdout, " -m N, --dims=N Set the threshold for the dimension sizes when printing\n"); + HDfprintf(stdout, " information for small datasets. N is an integer greater\n"); + HDfprintf(stdout, " than 0. The default threshold is 10.\n"); + HDfprintf(stdout, " -D, --dsetmetadata Print file space information for datasets' metadata\n"); + HDfprintf(stdout, " -T, --dtypemetadata Print datasets' datatype information\n"); + HDfprintf(stdout, " -A, --attribute Print attribute information\n"); + HDfprintf(stdout, " -a N, --numattrs=N Set the threshold for the # of attributes when printing\n"); + HDfprintf(stdout, " information for small # of attributes. N is an integer greater\n"); + HDfprintf(stdout, " than 0. The default threshold is 10.\n"); + HDfprintf(stdout, " -s, --freespace Print free space information\n"); + HDfprintf(stdout, " -S, --summary Print summary of file space information\n"); +} + + +/*------------------------------------------------------------------------- + * Function: ceil_log10 + * + * Purpose: Compute the ceiling of log_10(x) + * + * Return: >0 on success, 0 on failure + * + * Programmer: Quincey Koziol + * Monday, August 22, 2005 + * + *------------------------------------------------------------------------- + */ +H5_ATTR_CONST static unsigned +ceil_log10(unsigned long x) +{ + unsigned long pow10 = 1; + unsigned ret = 0; + + while(x >= pow10) { + pow10 *= 10; + ret++; + } /* end while */ + + return ret; +} /* ceil_log10() */ + + +/*------------------------------------------------------------------------- + * Function: attribute_stats + * + * Purpose: Gather statistics about attributes on an object + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Quincey Koziol + * Tuesday, July 17, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +attribute_stats(iter_t *iter, const H5O_info_t *oi) +{ + unsigned bin; /* "bin" the number of objects falls in */ + + /* Update dataset & attribute metadata info */ + iter->attrs_btree_storage_size += oi->meta_size.attr.index_size; + iter->attrs_heap_storage_size += oi->meta_size.attr.heap_size; + + /* Update small # of attribute count & limits */ + if(oi->num_attrs <= (hsize_t)sattrs_threshold) + (iter->num_small_attrs[(size_t)oi->num_attrs])++; + if(oi->num_attrs > iter->max_attrs) + iter->max_attrs = oi->num_attrs; + + /* Add attribute count to proper bin */ + bin = ceil_log10((unsigned long)oi->num_attrs); + if((bin + 1) > iter->attr_nbins) { + iter->attr_bins = (unsigned long *)HDrealloc(iter->attr_bins, (bin + 1) * sizeof(unsigned long)); + HDassert(iter->attr_bins); + + /* Initialize counts for intermediate bins */ + while(iter->attr_nbins < bin) + iter->attr_bins[iter->attr_nbins++] = 0; + iter->attr_nbins++; + + /* Initialize count for new bin */ + iter->attr_bins[bin] = 1; + } /* end if */ + else + (iter->attr_bins[bin])++; + + return 0; +} /* end attribute_stats() */ + + +/*------------------------------------------------------------------------- + * Function: group_stats + * + * Purpose: Gather statistics about the group + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Quincey Koziol + * Tuesday, August 16, 2005 + * + * Modifications: Refactored code from the walk_function + * EIP, Wednesday, August 16, 2006 + * + * Vailin Choi 12 July 2007 + * 1. Gathered storage info for btree and heap + * (groups and attributes) + * 2. Gathered info for attributes + * + * Vailin Choi 14 July 2007 + * Cast "num_objs" and "num_attrs" to size_t + * Due to the -Mbounds problem for the pgi-32 bit compiler on indexing + * + *------------------------------------------------------------------------- + */ +static herr_t +group_stats(iter_t *iter, const char *name, const H5O_info_t *oi) +{ + 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++; + + /* 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(iter->fid, name, &ginfo, H5P_DEFAULT); + HDassert(ret >= 0); + + /* Update link stats */ + /* Collect statistics for small groups */ + if(ginfo.nlinks < (hsize_t)sgroups_threshold) + (iter->num_small_groups[(size_t)ginfo.nlinks])++; + /* Determine maximum link count */ + if(ginfo.nlinks > iter->max_fanout) + iter->max_fanout = ginfo.nlinks; + + /* Add group count to proper bin */ + bin = ceil_log10((unsigned long)ginfo.nlinks); + if((bin + 1) > iter->group_nbins) { + /* Allocate more storage for info about dataset's datatype */ + iter->group_bins = (unsigned long *)HDrealloc(iter->group_bins, (bin + 1) * sizeof(unsigned long)); + HDassert(iter->group_bins); + + /* Initialize counts for intermediate bins */ + while(iter->group_nbins < bin) + iter->group_bins[iter->group_nbins++] = 0; + iter->group_nbins++; + + /* Initialize count for new bin */ + iter->group_bins[bin] = 1; + } /* end if */ + else + (iter->group_bins[bin])++; + + /* Update group metadata info */ + iter->groups_btree_storage_size += oi->meta_size.obj.index_size; + iter->groups_heap_storage_size += oi->meta_size.obj.heap_size; + + /* Update attribute metadata info */ + ret = attribute_stats(iter, oi); + HDassert(ret >= 0); + + return 0; +} /* end group_stats() */ + + +/*------------------------------------------------------------------------- + * Function: dataset_stats + * + * Purpose: Gather statistics about the dataset + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Quincey Koziol + * Tuesday, August 16, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +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 */ + hid_t sid; /* Dataspace ID */ + hid_t tid; /* Datatype ID */ + hid_t dcpl; /* Dataset creation property list ID */ + hsize_t dims[H5S_MAX_RANK];/* Dimensions of dataset */ + H5D_layout_t lout; /* Layout of dataset */ + unsigned type_found; /* Whether the dataset's datatype was */ + /* already found */ + int ndims; /* Number of dimensions of dataset */ + hsize_t storage; /* Size of dataset storage */ + unsigned u; /* Local index variable */ + int num_ext; /* Number of external files for a dataset */ + int nfltr; /* Number of filters for a dataset */ + H5Z_filter_t fltr; /* Filter identifier */ + herr_t ret; + + /* Gather statistics about this type of object */ + iter->uniq_dsets++; + + /* Get object header information */ + iter->dset_ohdr_info.total_size += oi->hdr.space.total; + iter->dset_ohdr_info.free_size += oi->hdr.space.free; + + did = H5Dopen2(iter->fid, name, H5P_DEFAULT); + HDassert(did > 0); + + /* Update dataset metadata info */ + iter->datasets_index_storage_size += oi->meta_size.obj.index_size; + iter->datasets_heap_storage_size += oi->meta_size.obj.heap_size; + + /* Update attribute metadata info */ + ret = attribute_stats(iter, oi); + HDassert(ret >= 0); + + /* Get storage info */ + storage = H5Dget_storage_size(did); + + /* Gather layout statistics */ + dcpl = H5Dget_create_plist(did); + HDassert(dcpl > 0); + + lout = H5Pget_layout(dcpl); + HDassert(lout >= 0); + + /* Object header's total size for H5D_COMPACT layout includes raw data size */ + /* "storage" also includes H5D_COMPACT raw data size */ + if(lout == H5D_COMPACT) + iter->dset_ohdr_info.total_size -= storage; + + /* Track the layout type for dataset */ + (iter->dset_layouts[lout])++; + + /* Get the number of external files for the dataset */ + num_ext = H5Pget_external_count(dcpl); + assert (num_ext >= 0); + + /* Accumulate raw data size accordingly */ + if(num_ext) { + iter->nexternal += (unsigned long)num_ext; + iter->dset_external_storage_size += (unsigned long)storage; + } else + iter->dset_storage_size += storage; + + /* Gather dataspace statistics */ + sid = H5Dget_space(did); + HDassert(sid > 0); + + ndims = H5Sget_simple_extent_dims(sid, dims, NULL); + HDassert(ndims >= 0); + + /* Check for larger rank of dataset */ + if((unsigned)ndims > iter->max_dset_rank) + iter->max_dset_rank = (unsigned)ndims; + + /* Track the number of datasets with each rank */ + (iter->dset_rank_count[ndims])++; + + /* Only gather dim size statistics on 1-D datasets */ + if(ndims == 1) { + /* Determine maximum dimension size */ + if(dims[0] > iter->max_dset_dims) + iter->max_dset_dims = dims[0]; + /* Collect statistics for small datasets */ + if(dims[0] < (hsize_t)sdsets_threshold) + (iter->small_dset_dims[(size_t)dims[0]])++; + + /* Add dim count to proper bin */ + bin = ceil_log10((unsigned long)dims[0]); + if((bin + 1) > iter->dset_dim_nbins) { + /* Allocate more storage for info about dataset's datatype */ + iter->dset_dim_bins = (unsigned long *)HDrealloc(iter->dset_dim_bins, (bin + 1) * sizeof(unsigned long)); + HDassert(iter->dset_dim_bins); + + /* Initialize counts for intermediate bins */ + while(iter->dset_dim_nbins < bin) + iter->dset_dim_bins[iter->dset_dim_nbins++] = 0; + iter->dset_dim_nbins++; + + /* Initialize count for this bin */ + iter->dset_dim_bins[bin] = 1; + } /* end if */ + else + (iter->dset_dim_bins[bin])++; + } /* end if */ + + ret = H5Sclose(sid); + HDassert(ret >= 0); + + /* Gather datatype statistics */ + tid = H5Dget_type(did); + HDassert(tid > 0); + + type_found = FALSE; + for(u = 0; u < iter->dset_ntypes; u++) + if(H5Tequal(iter->dset_type_info[u].tid, tid) > 0) { + type_found = TRUE; + break; + } /* end for */ + if(type_found) + (iter->dset_type_info[u].count)++; + else { + unsigned curr_ntype = (unsigned)iter->dset_ntypes; + + /* Increment # of datatypes seen for datasets */ + iter->dset_ntypes++; + + /* Allocate more storage for info about dataset's datatype */ + iter->dset_type_info = (dtype_info_t *)HDrealloc(iter->dset_type_info, iter->dset_ntypes * sizeof(dtype_info_t)); + HDassert(iter->dset_type_info); + + /* Initialize information about datatype */ + iter->dset_type_info[curr_ntype].tid = H5Tcopy(tid); + HDassert(iter->dset_type_info[curr_ntype].tid > 0); + iter->dset_type_info[curr_ntype].count = 1; + iter->dset_type_info[curr_ntype].named = 0; + + /* Set index for later */ + u = curr_ntype; + } /* end else */ + + /* Check if the datatype is a named datatype */ + if(H5Tcommitted(tid) > 0) + (iter->dset_type_info[u].named)++; + + ret = H5Tclose(tid); + HDassert(ret >= 0); + + /* Track different filters */ + if((nfltr = H5Pget_nfilters(dcpl)) >= 0) { + if(nfltr == 0) + iter->dset_comptype[0]++; + for(u = 0; u < (unsigned)nfltr; u++) { + fltr = H5Pget_filter2(dcpl, u, 0, 0, 0, 0, 0, NULL); + if(fltr >= 0) { + if(fltr < (H5_NFILTERS_IMPL - 1)) + iter->dset_comptype[fltr]++; + else + iter->dset_comptype[H5_NFILTERS_IMPL - 1]++; /*other filters*/ + } /* end if */ + } /* end for */ + } /* endif nfltr */ + + ret = H5Pclose(dcpl); + HDassert(ret >= 0); + + ret = H5Dclose(did); + HDassert(ret >= 0); + + return 0; +} /* end dataset_stats() */ + + +/*------------------------------------------------------------------------- + * Function: datatype_stats + * + * Purpose: Gather statistics about the datatype + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Vailin Choi; July 7th, 2009 + * + *------------------------------------------------------------------------- + */ +static herr_t +datatype_stats(iter_t *iter, const H5O_info_t *oi) +{ + herr_t ret; + + /* Gather statistics about this type of object */ + iter->uniq_dtypes++; + + /* Get object header information */ + iter->dtype_ohdr_info.total_size += oi->hdr.space.total; + iter->dtype_ohdr_info.free_size += oi->hdr.space.free; + + /* Update attribute metadata info */ + ret = attribute_stats(iter, oi); + HDassert(ret >= 0); + + return 0; +} /* end datatype_stats() */ + + +/*------------------------------------------------------------------------- + * Function: obj_stats + * + * Purpose: Gather statistics about an object + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Quincey Koziol + * Tuesday, November 6, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +obj_stats(const char *path, const H5O_info_t *oi, const char *already_visited, + void *_iter) +{ + iter_t *iter = (iter_t *)_iter; + + /* 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: + datatype_stats(iter, oi); + break; + + case H5O_TYPE_UNKNOWN: + case H5O_TYPE_NTYPES: + default: + /* Gather statistics about this type of object */ + iter->uniq_others++; + break; + } /* end switch */ + } /* end if */ + + 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 H5_ATTR_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; + + case H5L_TYPE_HARD: + case H5L_TYPE_MAX: + case H5L_TYPE_ERROR: + default: + /* Gather statistics about this type of object */ + iter->uniq_others++; + break; + } /* end switch() */ + + return 0; +} /* end lnk_stats() */ + +/*------------------------------------------------------------------------- + * Function: freespace_stats + * + * Purpose: Gather statistics for free space sections in the file + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Vailin Choi; July 7th, 2009 + * + *------------------------------------------------------------------------- + */ +static herr_t +freespace_stats(hid_t fid, iter_t *iter) +{ + H5F_sect_info_t *sect_info = NULL; /* Free space sections */ + ssize_t nsects; /* Number of free space sections */ + size_t u; /* Local index variable */ + + /* Query section information */ + if((nsects = H5Fget_free_sections(fid, H5FD_MEM_DEFAULT, 0, NULL)) < 0) + return(FAIL); + else if(nsects) { + if(NULL == (sect_info = (H5F_sect_info_t *)HDcalloc((size_t)nsects, sizeof(H5F_sect_info_t)))) + return(FAIL); + nsects = H5Fget_free_sections(fid, H5FD_MEM_DEFAULT, (size_t)nsects, sect_info); + HDassert(nsects); + } /* end else-if */ + + for(u = 0; u < (size_t)nsects; u++) { + unsigned bin; /* "bin" the number of objects falls in */ + + if(sect_info[u].size < SIZE_SMALL_SECTS) + (iter->num_small_sects[(size_t)sect_info[u].size])++; + + /* Add section size to proper bin */ + bin = ceil_log10((unsigned long)sect_info[u].size); + if(bin >= iter->sect_nbins) { + /* Allocate more storage for section info */ + iter->sect_bins = (unsigned long *)HDrealloc(iter->sect_bins, (bin + 1) * sizeof(unsigned long)); + HDassert(iter->sect_bins); + + /* Initialize counts for intermediate bins */ + while(iter->sect_nbins < bin) + iter->sect_bins[iter->sect_nbins++] = 0; + iter->sect_nbins++; + + /* Initialize count for this bin */ + iter->sect_bins[bin] = 1; + } /* end if */ + else + (iter->sect_bins[bin])++; + } /* end for */ + + if(sect_info) + HDfree(sect_info); + + return 0; +} /* end freespace_stats() */ + + +/*------------------------------------------------------------------------- + * Function: hand_free + * + * Purpose: Free handler structure + * + * Return: Success: 0 + * + * Failure: Never fails + * + *------------------------------------------------------------------------- + */ +static void +hand_free(struct handler_t *hand) +{ + if(hand) { + unsigned u; + + for(u = 0; u < hand->obj_count; u++) + if(hand->obj[u]) { + HDfree(hand->obj[u]); + hand->obj[u] = NULL; + } /* end if */ + hand->obj_count = 0; + HDfree(hand->obj); + HDfree(hand); + } /* end if */ +} /* end hand_free() */ + + +/*------------------------------------------------------------------------- + * Function: parse_command_line + * + * Purpose: Parses command line and sets up global variable to control output + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Elena Pourmal + * Saturday, August 12, 2006 + * + *------------------------------------------------------------------------- + */ +static int +parse_command_line(int argc, const char *argv[], struct handler_t **hand_ret) +{ + int opt; + unsigned u; + struct handler_t *hand = NULL; + + /* parse command line options */ + while((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { + switch((char)opt) { + case 'h': + usage(h5tools_getprogname()); + h5tools_setstatus(EXIT_SUCCESS); + goto done; + break; + + case 'V': + print_version(h5tools_getprogname()); + h5tools_setstatus(EXIT_SUCCESS); + goto done; + break; + + case 'F': + display_all = FALSE; + display_file_metadata = TRUE; + break; + + case 'f': + display_all = FALSE; + display_file = TRUE; + break; + + case 'G': + display_all = FALSE; + display_group_metadata = TRUE; + break; + + case 'g': + display_all = FALSE; + display_group = TRUE; + break; + + case 'l': + if(opt_arg) { + sgroups_threshold = HDatoi(opt_arg); + if(sgroups_threshold < 1) { + error_msg("Invalid threshold for small groups\n"); + goto error; + } + } else + error_msg("Missing threshold for small groups\n"); + + break; + + case 'D': + display_all = FALSE; + display_dset_metadata = TRUE; + break; + + case 'd': + display_all = FALSE; + display_dset = TRUE; + break; + + case 'm': + if(opt_arg) { + sdsets_threshold = HDatoi(opt_arg); + if(sdsets_threshold < 1) { + error_msg("Invalid threshold for small datasets\n"); + goto error; + } + } else + error_msg("Missing threshold for small datasets\n"); + + break; + + case 'T': + display_all = FALSE; + display_dset_dtype_meta = TRUE; + break; + + case 'A': + display_all = FALSE; + display_attr = TRUE; + break; + + case 'a': + if(opt_arg) { + sattrs_threshold = HDatoi(opt_arg); + if(sattrs_threshold < 1) { + error_msg("Invalid threshold for small # of attributes\n"); + goto error; + } + } else + error_msg("Missing threshold for small # of attributes\n"); + + break; + + case 's': + display_all = FALSE; + display_free_sections = TRUE; + break; + + case 'S': + display_all = FALSE; + display_summary = TRUE; + break; + + case 'O': + display_all = FALSE; + display_object = TRUE; + + /* Allocate space to hold the command line info */ + if(NULL == (hand = (struct handler_t *)HDcalloc((size_t)1, sizeof(struct handler_t)))) { + error_msg("unable to allocate memory for object struct\n"); + goto error; + } /* end if */ + + /* Allocate space to hold the object strings */ + hand->obj_count = (size_t)argc; + if(NULL == (hand->obj = (char **)HDcalloc((size_t)argc, sizeof(char *)))) { + error_msg("unable to allocate memory for object array\n"); + goto error; + } /* end if */ + + /* Store object names */ + for(u = 0; u < hand->obj_count; u++) + if(NULL == (hand->obj[u] = HDstrdup(opt_arg))) { + error_msg("unable to allocate memory for object name\n"); + goto error; + } /* end if */ + break; + + default: + usage(h5tools_getprogname()); + goto error; + } /* end switch */ + } /* end while */ + + /* check for file name to be processed */ + if(argc <= opt_ind) { + error_msg("missing file name\n"); + usage(h5tools_getprogname()); + goto error; + } /* end if */ + + /* Set handler structure */ + *hand_ret = hand; + +done: + return 0; + +error: + hand_free(hand); + h5tools_setstatus(EXIT_FAILURE); + + return -1; +} + + +/*------------------------------------------------------------------------- + * Function: iter_free + * + * Purpose: Free iter structure + * + * Return: Success: 0 + * + * Failure: Never fails + * + *------------------------------------------------------------------------- + */ +static void +iter_free(iter_t *iter) +{ + + /* Clear array of bins for group counts */ + if(iter->group_bins) { + HDfree(iter->group_bins); + iter->group_bins = NULL; + } /* end if */ + + /* Clear array for tracking small groups */ + if(iter->num_small_groups) { + HDfree(iter->num_small_groups); + iter->num_small_groups = NULL; + } /* end if */ + + /* Clear array of bins for attribute counts */ + if(iter->attr_bins) { + HDfree(iter->attr_bins); + iter->attr_bins = NULL; + } /* end if */ + + /* Clear array for tracking small attributes */ + if(iter->num_small_attrs) { + HDfree(iter->num_small_attrs); + iter->num_small_attrs= NULL; + } /* end if */ + + /* Clear dataset datatype information found */ + if(iter->dset_type_info) { + HDfree(iter->dset_type_info); + iter->dset_type_info = NULL; + } /* end if */ + + /* Clear array of bins for dataset dimensions */ + if(iter->dset_dim_bins) { + HDfree(iter->dset_dim_bins); + iter->dset_dim_bins = NULL; + } /* end if */ + + /* Clear array of tracking 1-D small datasets */ + if(iter->small_dset_dims) { + HDfree(iter->small_dset_dims); + iter->small_dset_dims = NULL; + } /* end if */ + + /* Clear array of bins for free-space section sizes */ + if(iter->sect_bins) { + HDfree(iter->sect_bins); + iter->sect_bins = NULL; + } /* end if */ +} /* end iter_free() */ + + +/*------------------------------------------------------------------------- + * Function: print_file_info + * + * Purpose: Prints information about file + * + * Return: Success: 0 + * + * Failure: Never fails + * + * Programmer: Elena Pourmal + * Saturday, August 12, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +print_file_info(const iter_t *iter) +{ + printf("File information\n"); + printf("\t# of unique groups: %lu\n", iter->uniq_groups); + printf("\t# of unique datasets: %lu\n", iter->uniq_dsets); + printf("\t# of unique named datatypes: %lu\n", iter->uniq_dtypes); + 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); + HDfprintf(stdout, "\tMax. # of objects in group: %Hu\n", iter->max_fanout); + + return 0; +} /* print_file_info() */ + + +/*------------------------------------------------------------------------- + * Function: print_file_metadata + * + * Purpose: Prints file space information for file's metadata + * + * Return: Success: 0 + * + * Failure: Never fails + * + * Programmer: Elena Pourmal + * Saturday, August 12, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +print_file_metadata(const iter_t *iter) +{ + HDfprintf(stdout, "File space information for file metadata (in bytes):\n"); + HDfprintf(stdout, "\tSuperblock: %Hu\n", iter->super_size); + HDfprintf(stdout, "\tSuperblock extension: %Hu\n", iter->super_ext_size); + HDfprintf(stdout, "\tUser block: %Hu\n", iter->ublk_size); + + HDfprintf(stdout, "\tObject headers: (total/unused)\n"); + HDfprintf(stdout, "\t\tGroups: %Hu/%Hu\n", + iter->group_ohdr_info.total_size, + iter->group_ohdr_info.free_size); + HDfprintf(stdout, "\t\tDatasets(exclude compact data): %Hu/%Hu\n", + iter->dset_ohdr_info.total_size, + iter->dset_ohdr_info.free_size); + HDfprintf(stdout, "\t\tDatatypes: %Hu/%Hu\n", + iter->dtype_ohdr_info.total_size, + iter->dtype_ohdr_info.free_size); + + HDfprintf(stdout, "\tGroups:\n"); + HDfprintf(stdout, "\t\tB-tree/List: %Hu\n", iter->groups_btree_storage_size); + HDfprintf(stdout, "\t\tHeap: %Hu\n", iter->groups_heap_storage_size); + + HDfprintf(stdout, "\tAttributes:\n"); + HDfprintf(stdout, "\t\tB-tree/List: %Hu\n", iter->attrs_btree_storage_size); + HDfprintf(stdout, "\t\tHeap: %Hu\n", iter->attrs_heap_storage_size); + + HDfprintf(stdout, "\tChunked datasets:\n"); + HDfprintf(stdout, "\t\tIndex: %Hu\n", iter->datasets_index_storage_size); + + HDfprintf(stdout, "\tDatasets:\n"); + HDfprintf(stdout, "\t\tHeap: %Hu\n", iter->datasets_heap_storage_size); + + HDfprintf(stdout, "\tShared Messages:\n"); + HDfprintf(stdout, "\t\tHeader: %Hu\n", iter->SM_hdr_storage_size); + HDfprintf(stdout, "\t\tB-tree/List: %Hu\n", iter->SM_index_storage_size); + HDfprintf(stdout, "\t\tHeap: %Hu\n", iter->SM_heap_storage_size); + + HDfprintf(stdout, "\tFree-space managers:\n"); + HDfprintf(stdout, "\t\tHeader: %Hu\n", iter->free_hdr); + HDfprintf(stdout, "\t\tAmount of free space: %Hu\n", iter->free_space); + + return 0; +} /* print_file_metadata() */ + + +/*------------------------------------------------------------------------- + * Function: print_group_info + * + * Purpose: Prints information about groups in the file + * + * Return: Success: 0 + * + * Failure: Never fails + * + * Programmer: Elena Pourmal + * Saturday, August 12, 2006 + * + * Modifications: + * bug #1253; Oct 6th 2008; Vailin Choi + * Fixed segmentation fault: print iter->group_bins[0] when + * there is iter->group_nbins + * + *------------------------------------------------------------------------- + */ +static herr_t +print_group_info(const iter_t *iter) +{ + unsigned long power; /* Temporary "power" for bins */ + unsigned long total; /* Total count for various statistics */ + unsigned u; /* Local index variable */ + + printf("Small groups (with 0 to %u links):\n", sgroups_threshold-1); + total = 0; + for(u = 0; u < (unsigned)sgroups_threshold; u++) { + if(iter->num_small_groups[u] > 0) { + printf("\t# of groups with %u link(s): %lu\n", u, iter->num_small_groups[u]); + total += iter->num_small_groups[u]; + } /* end if */ + } /* end for */ + printf("\tTotal # of small groups: %lu\n", total); + + printf("Group bins:\n"); + total = 0; + if((iter->group_nbins > 0) && (iter->group_bins[0] > 0)) { + printf("\t# of groups with 0 link: %lu\n", iter->group_bins[0]); + total = iter->group_bins[0]; + } /* end if */ + power = 1; + for(u = 1; u < iter->group_nbins; u++) { + if(iter->group_bins[u] > 0) { + printf("\t# of groups with %lu - %lu links: %lu\n", power, (power * 10) - 1, + iter->group_bins[u]); + total += iter->group_bins[u]; + } /* end if */ + power *= 10; + } /* end for */ + printf("\tTotal # of groups: %lu\n", total); + + return 0; +} /* print_group_info() */ + + +/*------------------------------------------------------------------------- + * Function: print_group_metadata + * + * Purpose: Prints file space information for groups' metadata + * + * Return: Success: 0 + * + * Failure: Never fails + * + * Programmer: Vailin Choi; October 2009 + * + *------------------------------------------------------------------------- + */ +static herr_t +print_group_metadata(const iter_t *iter) +{ + printf("File space information for groups' metadata (in bytes):\n"); + + HDfprintf(stdout, "\tObject headers (total/unused): %Hu/%Hu\n", + iter->group_ohdr_info.total_size, iter->group_ohdr_info.free_size); + + HDfprintf(stdout, "\tB-tree/List: %Hu\n", iter->groups_btree_storage_size); + HDfprintf(stdout, "\tHeap: %Hu\n", iter->groups_heap_storage_size); + + return 0; +} /* print_group_metadata() */ + + +/*------------------------------------------------------------------------- + * Function: print_dataset_info + * + * Purpose: Prints information about datasets in the file + * + * Return: Success: 0 + * + * Failure: Never fails + * + * Programmer: Elena Pourmal + * Saturday, August 12, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +print_dataset_info(const iter_t *iter) +{ + unsigned long power; /* Temporary "power" for bins */ + unsigned long total; /* Total count for various statistics */ + unsigned u; /* Local index variable */ + + if(iter->uniq_dsets > 0) { + printf("Dataset dimension information:\n"); + printf("\tMax. rank of datasets: %u\n", iter->max_dset_rank); + printf("\tDataset ranks:\n"); + for(u = 0; u < H5S_MAX_RANK; u++) + if(iter->dset_rank_count[u] > 0) + printf("\t\t# of dataset with rank %u: %lu\n", u, iter->dset_rank_count[u]); + + printf("1-D Dataset information:\n"); + HDfprintf(stdout, "\tMax. dimension size of 1-D datasets: %Hu\n", iter->max_dset_dims); + printf("\tSmall 1-D datasets (with dimension sizes 0 to %u):\n", sdsets_threshold - 1); + total = 0; + for(u = 0; u < (unsigned)sdsets_threshold; u++) { + if(iter->small_dset_dims[u] > 0) { + printf("\t\t# of datasets with dimension sizes %u: %lu\n", u, + iter->small_dset_dims[u]); + total += iter->small_dset_dims[u]; + } /* end if */ + } /* end for */ + printf("\t\tTotal # of small datasets: %lu\n", total); + + /* Protect against no datasets in file */ + if(iter->dset_dim_nbins > 0) { + printf("\t1-D Dataset dimension bins:\n"); + total = 0; + if(iter->dset_dim_bins[0] > 0) { + printf("\t\t# of datasets with dimension size 0: %lu\n", iter->dset_dim_bins[0]); + total = iter->dset_dim_bins[0]; + } /* end if */ + power = 1; + for(u = 1; u < iter->dset_dim_nbins; u++) { + if(iter->dset_dim_bins[u] > 0) { + printf("\t\t# of datasets with dimension size %lu - %lu: %lu\n", power, (power * 10) - 1, + iter->dset_dim_bins[u]); + total += iter->dset_dim_bins[u]; + } /* end if */ + power *= 10; + } /* end for */ + printf("\t\tTotal # of datasets: %lu\n", total); + } /* end if */ + + printf("Dataset storage information:\n"); + HDfprintf(stdout, "\tTotal raw data size: %Hu\n", iter->dset_storage_size); + HDfprintf(stdout, "\tTotal external raw data size: %Hu\n", iter->dset_external_storage_size); + + printf("Dataset layout information:\n"); + for(u = 0; u < H5D_NLAYOUTS; u++) + printf("\tDataset layout counts[%s]: %lu\n", (u == H5D_COMPACT ? "COMPACT" : + (u == H5D_CONTIGUOUS ? "CONTIG" : (u == H5D_CHUNKED ? "CHUNKED" : "VIRTUAL"))), iter->dset_layouts[u]); + printf("\tNumber of external files : %lu\n", iter->nexternal); + + printf("Dataset filters information:\n"); + printf("\tNumber of datasets with:\n"); + printf("\t\tNO filter: %lu\n", iter->dset_comptype[H5Z_FILTER_ERROR+1]); + printf("\t\tGZIP filter: %lu\n", iter->dset_comptype[H5Z_FILTER_DEFLATE]); + printf("\t\tSHUFFLE filter: %lu\n", iter->dset_comptype[H5Z_FILTER_SHUFFLE]); + printf("\t\tFLETCHER32 filter: %lu\n", iter->dset_comptype[H5Z_FILTER_FLETCHER32]); + printf("\t\tSZIP filter: %lu\n", iter->dset_comptype[H5Z_FILTER_SZIP]); + printf("\t\tNBIT filter: %lu\n", iter->dset_comptype[H5Z_FILTER_NBIT]); + printf("\t\tSCALEOFFSET filter: %lu\n", iter->dset_comptype[H5Z_FILTER_SCALEOFFSET]); + printf("\t\tUSER-DEFINED filter: %lu\n", iter->dset_comptype[H5_NFILTERS_IMPL-1]); + } /* end if */ + + return 0; +} /* print_dataset_info() */ + + +/*------------------------------------------------------------------------- + * Function: print_dataset_metadata + * + * Purpose: Prints file space information for datasets' metadata + * + * Return: Success: 0 + * + * Failure: Never fails + * + * Programmer: Vailin Choi; October 2009 + * + *------------------------------------------------------------------------- + */ +static herr_t +print_dset_metadata(const iter_t *iter) +{ + printf("File space information for datasets' metadata (in bytes):\n"); + + HDfprintf(stdout, "\tObject headers (total/unused): %Hu/%Hu\n", + iter->dset_ohdr_info.total_size, iter->dset_ohdr_info.free_size); + + HDfprintf(stdout, "\tIndex for Chunked datasets: %Hu\n", + iter->datasets_index_storage_size); + HDfprintf(stdout, "\tHeap: %Hu\n", iter->datasets_heap_storage_size); + + return 0; +} /* print_dset_metadata() */ + + +/*------------------------------------------------------------------------- + * Function: print_dset_dtype_meta + * + * Purpose: Prints datasets' datatype information + * + * Return: Success: 0 + * + * Failure: Never fails + * + * Programmer: Vailin Choi; October 2009 + * + *------------------------------------------------------------------------- + */ +static herr_t +print_dset_dtype_meta(const iter_t *iter) +{ + unsigned long total; /* Total count for various statistics */ + size_t dtype_size; /* Size of encoded datatype */ + unsigned u; /* Local index variable */ + + if(iter->dset_ntypes) { + printf("Dataset datatype information:\n"); + printf("\t# of unique datatypes used by datasets: %lu\n", iter->dset_ntypes); + total = 0; + for(u = 0; u < iter->dset_ntypes; u++) { + H5Tencode(iter->dset_type_info[u].tid, NULL, &dtype_size); + printf("\tDataset datatype #%u:\n", u); + printf("\t\tCount (total/named) = (%lu/%lu)\n", + iter->dset_type_info[u].count, iter->dset_type_info[u].named); + printf("\t\tSize (desc./elmt) = (%lu/%lu)\n", (unsigned long)dtype_size, + (unsigned long)H5Tget_size(iter->dset_type_info[u].tid)); + H5Tclose(iter->dset_type_info[u].tid); + total += iter->dset_type_info[u].count; + } /* end for */ + printf("\tTotal dataset datatype count: %lu\n", total); + } /* end if */ + + return 0; +} /* print_dset_dtype_meta() */ + + +/*------------------------------------------------------------------------- + * Function: print_attr_info + * + * Purpose: Prints information about attributes in the file + * + * Return: Success: 0 + * + * Failure: Never fails + * + * Programmer: Vailin Choi + * July 12, 2007 + * + *------------------------------------------------------------------------- + */ +static herr_t +print_attr_info(const iter_t *iter) +{ + unsigned long power; /* Temporary "power" for bins */ + unsigned long total; /* Total count for various statistics */ + unsigned u; /* Local index variable */ + + printf("Small # of attributes (objects with 1 to %u attributes):\n", sattrs_threshold); + total = 0; + for(u = 1; u <= (unsigned)sattrs_threshold; u++) { + if(iter->num_small_attrs[u] > 0) { + printf("\t# of objects with %u attributes: %lu\n", u, iter->num_small_attrs[u]); + total += iter->num_small_attrs[u]; + } /* end if */ + } /* end for */ + printf("\tTotal # of objects with small # of attributes: %lu\n", total); + + printf("Attribute bins:\n"); + total = 0; + power = 1; + for(u = 1; u < iter->attr_nbins; u++) { + if(iter->attr_bins[u] > 0) { + printf("\t# of objects with %lu - %lu attributes: %lu\n", power, (power * 10) - 1, + iter->attr_bins[u]); + total += iter->attr_bins[u]; + } /* end if */ + power *= 10; + } /* end for */ + printf("\tTotal # of objects with attributes: %lu\n", total); + printf("\tMax. # of attributes to objects: %lu\n", (unsigned long)iter->max_attrs); + + return 0; +} /* print_attr_info() */ + + +/*------------------------------------------------------------------------- + * Function: print_freespace_info + * + * Purpose: Prints information about free space in the file + * + * Return: Success: 0 + * + * Failure: Never fails + * + * Programmer: Vailin Choi; July 7th, 2009 + * + *------------------------------------------------------------------------- + */ +static herr_t +print_freespace_info(const iter_t *iter) +{ + unsigned long power; /* Temporary "power" for bins */ + unsigned long total; /* Total count for various statistics */ + unsigned u; /* Local index variable */ + + HDfprintf(stdout, "Free-space section threshold: %Hu bytes\n", iter->fs_threshold); + printf("Small size free-space sections (< %u bytes):\n", (unsigned)SIZE_SMALL_SECTS); + total = 0; + for(u = 0; u < SIZE_SMALL_SECTS; u++) { + if(iter->num_small_sects[u] > 0) { + printf("\t# of sections of size %u: %lu\n", u, iter->num_small_sects[u]); + total += iter->num_small_sects[u]; + } /* end if */ + } /* end for */ + printf("\tTotal # of small size sections: %lu\n", total); + + printf("Free-space section bins:\n"); + + total = 0; + power = 1; + for(u = 1; u < iter->sect_nbins; u++) { + if(iter->sect_bins[u] > 0) { + printf("\t# of sections of size %lu - %lu: %lu\n", power, (power * 10) - 1, + iter->sect_bins[u]); + total += iter->sect_bins[u]; + } /* end if */ + power *= 10; + } /* end for */ + printf("\tTotal # of sections: %lu\n", total); + + return 0; +} /* print_freespace_info() */ + + +/*------------------------------------------------------------------------- + * Function: print_storage_summary + * + * Purpose: Prints file space information for the file + * + * Return: Success: 0 + * + * Failure: Never fails + * + * Programmer: Vailin Choi; August 2009 + * + *------------------------------------------------------------------------- + */ +static herr_t +print_storage_summary(const iter_t *iter) +{ + hsize_t total_meta = 0; + hsize_t unaccount = 0; + double percent = 0.0f; + + HDfprintf(stdout, "File space management strategy: %s\n", FS_STRATEGY_NAME[iter->fs_strategy]); + printf("Summary of file space information:\n"); + total_meta = + iter->super_size + iter->super_ext_size + iter->ublk_size + + iter->group_ohdr_info.total_size + + iter->dset_ohdr_info.total_size + + iter->dtype_ohdr_info.total_size + + iter->groups_btree_storage_size + + iter->groups_heap_storage_size + + iter->attrs_btree_storage_size + + iter->attrs_heap_storage_size + + iter->datasets_index_storage_size + + iter->datasets_heap_storage_size + + iter->SM_hdr_storage_size + + iter->SM_index_storage_size + + iter->SM_heap_storage_size + + iter->free_hdr; + + HDfprintf(stdout, " File metadata: %Hu bytes\n", total_meta); + HDfprintf(stdout, " Raw data: %Hu bytes\n", iter->dset_storage_size); + + percent = ((double)iter->free_space / (double)iter->filesize) * (double)100.0f; + HDfprintf(stdout, " Amount/Percent of tracked free space: %Hu bytes/%3.1f%\n", + iter->free_space, percent); + + if(iter->filesize < (total_meta + iter->dset_storage_size + iter->free_space)) { + unaccount = (total_meta + iter->dset_storage_size + iter->free_space) - iter->filesize; + HDfprintf(stdout, " ??? File has %Hu more bytes accounted for than its size! ???\n", unaccount); + } + else { + unaccount = iter->filesize - (total_meta + iter->dset_storage_size + iter->free_space); + HDfprintf(stdout, " Unaccounted space: %Hu bytes\n", unaccount); + } + + HDfprintf(stdout, "Total space: %Hu bytes\n", total_meta + iter->dset_storage_size + iter->free_space + unaccount); + + if(iter->nexternal) + HDfprintf(stdout, "External raw data: %Hu bytes\n", iter->dset_external_storage_size); + + return 0; +} /* print_storage_summary() */ + + +/*------------------------------------------------------------------------- + * Function: print_file_statistics + * + * Purpose: Prints file statistics + * + * Return: Success: 0 + * + * Failure: Never fails + * + * Programmer: Elena Pourmal + * Saturday, August 12, 2006 + * + *------------------------------------------------------------------------- + */ +static void +print_file_statistics(const iter_t *iter) +{ + if(display_all) { + display_file = TRUE; + display_group = TRUE; + display_dset = TRUE; + display_dset_dtype_meta = TRUE; + display_attr = TRUE; + display_free_sections = TRUE; + display_summary = TRUE; + + display_file_metadata = TRUE; + display_group_metadata = TRUE; + display_dset_metadata = TRUE; + } + + if(display_file) print_file_info(iter); + if(display_file_metadata) print_file_metadata(iter); + + if(display_group) print_group_info(iter); + if(!display_all && display_group_metadata) print_group_metadata(iter); + + if(display_dset) print_dataset_info(iter); + if(display_dset_dtype_meta) print_dset_dtype_meta(iter); + if(!display_all && display_dset_metadata) print_dset_metadata(iter); + + if(display_attr) print_attr_info(iter); + if(display_free_sections) print_freespace_info(iter); + if(display_summary) print_storage_summary(iter); +} /* print_file_statistics() */ + + +/*------------------------------------------------------------------------- + * Function: print_object_statistics + * + * Purpose: Prints object statistics + * + * Return: Success: 0 + * + * Failure: Never fails + * + * Programmer: Elena Pourmal + * Thursday, August 17, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +print_object_statistics(const char *name) +{ + printf("Object name %s\n", name); +} /* print_object_statistics() */ + + +/*------------------------------------------------------------------------- + * Function: print_statistics + * + * Purpose: Prints statistics + * + * Return: Success: 0 + * + * Failure: Never fails + * + * Programmer: Elena Pourmal + * Thursday, August 17, 2006 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +print_statistics(const char *name, const iter_t *iter) +{ + if(display_object) + print_object_statistics(name); + else + print_file_statistics(iter); +} /* print_statistics() */ + + +/*------------------------------------------------------------------------- + * Function: main + * + * Modifications: + * 2/2010; Vailin Choi + * Get the size of user block + * + *------------------------------------------------------------------------- + */ +int +main(int argc, const char *argv[]) +{ + iter_t iter; + const char *fname = NULL; + hid_t fid = -1; + struct handler_t *hand = NULL; + + h5tools_setprogname(PROGRAMNAME); + h5tools_setstatus(EXIT_SUCCESS); + + /* Disable error reporting */ + H5Eset_auto2(H5E_DEFAULT, NULL, NULL); + + /* Initialize h5tools lib */ + h5tools_init(); + + HDmemset(&iter, 0, sizeof(iter)); + + if(parse_command_line(argc, argv, &hand) < 0) + goto done; + + fname = argv[opt_ind]; + + /* Check for filename given */ + if(fname) { + hid_t fcpl; + H5F_info2_t finfo; + + printf("Filename: %s\n", fname); + + fid = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT); + if(fid < 0) { + error_msg("unable to open file \"%s\"\n", fname); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } /* end if */ + + /* Initialize iter structure */ + iter.fid = fid; + + if(H5Fget_filesize(fid, &iter.filesize) < 0) + warn_msg("Unable to retrieve file size\n"); + HDassert(iter.filesize != 0); + + /* Get storge info for file-level structures */ + if(H5Fget_info2(fid, &finfo) < 0) + warn_msg("Unable to retrieve file info\n"); + else { + iter.super_size = finfo.super.super_size; + iter.super_ext_size = finfo.super.super_ext_size; + 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; + iter.free_space = finfo.free.tot_space; + iter.free_hdr = finfo.free.meta_size; + } /* end else */ + + iter.num_small_groups = (unsigned long *)HDcalloc((size_t)sgroups_threshold, sizeof(unsigned long)); + iter.num_small_attrs = (unsigned long *)HDcalloc((size_t)(sattrs_threshold+1), sizeof(unsigned long)); + iter.small_dset_dims = (unsigned long *)HDcalloc((size_t)sdsets_threshold, sizeof(unsigned long)); + + if(iter.num_small_groups == NULL || iter.num_small_attrs == NULL || iter.small_dset_dims == NULL) { + error_msg("Unable to allocate memory for tracking small groups/datasets/attributes\n"); + h5tools_setstatus(EXIT_FAILURE); + goto done; + } + + if((fcpl = H5Fget_create_plist(fid)) < 0) + warn_msg("Unable to retrieve file creation property\n"); + + if(H5Pget_userblock(fcpl, &iter.ublk_size) < 0) + warn_msg("Unable to retrieve userblock size\n"); + + if(H5Pget_file_space(fcpl, &iter.fs_strategy, &iter.fs_threshold) < 0) + warn_msg("Unable to retrieve file space information\n"); + HDassert(iter.fs_strategy != 0 && iter.fs_strategy < H5F_FILE_SPACE_NTYPES); + + /* get information for free-space sections */ + if(freespace_stats(fid, &iter) < 0) + warn_msg("Unable to retrieve freespace info\n"); + + /* Walk the objects or all file */ + if(display_object) { + unsigned u; + + for(u = 0; u < hand->obj_count; u++) { + if(h5trav_visit(fid, hand->obj[u], TRUE, TRUE, obj_stats, lnk_stats, &iter) < 0) + warn_msg("Unable to traverse object \"%s\"\n", hand->obj[u]); + else + print_statistics(hand->obj[u], &iter); + } /* end for */ + } /* end if */ + else { + if(h5trav_visit(fid, "/", TRUE, TRUE, obj_stats, lnk_stats, &iter) < 0) + warn_msg("Unable to traverse objects/links in file \"%s\"\n", fname); + else + print_statistics("/", &iter); + } /* end else */ + } /* end if */ + +done: + hand_free(hand); + + /* Free iter structure */ + iter_free(&iter); + + if(fid >= 0 && H5Fclose(fid) < 0) { + error_msg("unable to close file \"%s\"\n", fname); + h5tools_setstatus(EXIT_FAILURE); + } /* end if */ + + leave(h5tools_getstatus()); +} /* end main() */ + diff --git a/tools/src/h5stat/testh5stat.sh.in b/tools/src/h5stat/testh5stat.sh.in new file mode 100644 index 0000000..cbb732c --- /dev/null +++ b/tools/src/h5stat/testh5stat.sh.in @@ -0,0 +1,318 @@ +#! /bin/sh +# +# Copyright by The HDF Group. +# Copyright by the Board of Trustees of the University of Illinois. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the files COPYING and Copyright.html. COPYING can be found at the root +# of the source code distribution tree; Copyright.html can be found at the +# root level of an installed copy of the electronic HDF5 document set and +# is linked from the top-level documents page. It can also be found at +# http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have +# access to either file, you may request a copy from help@hdfgroup.org. +# +# Tests for the h5stat tool +# +# Modifcations: +# Vailin Choi; July 2013 +# Add tests for -l, -m, -a options +# + +srcdir=@srcdir@ + +# Determine which filters are available +USE_FILTER_SZIP="@USE_FILTER_SZIP@" +USE_FILTER_DEFLATE="@USE_FILTER_DEFLATE@" + +TESTNAME=h5stat +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +STAT=h5stat # The tool name +STAT_BIN=`pwd`/$STAT # The path of the tool binary + +RM='rm -rf' +CMP='cmp -s' +DIFF='diff -c' +CP='cp' +DIRNAME='dirname' +LS='ls' +AWK='awk' + +nerrors=0 +verbose=yes + +# source dirs +SRC_TOOLS="$srcdir/.." +SRC_TOOLS_TESTFILES="$SRC_TOOLS/testfiles" + +# testfiles source dirs for tools +SRC_H5LS_TESTFILES="$SRC_TOOLS_TESTFILES" +SRC_H5DUMP_TESTFILES="$SRC_TOOLS_TESTFILES" +SRC_H5DIFF_TESTFILES="$SRC_TOOLS/h5diff/testfiles" +SRC_H5COPY_TESTFILES="$SRC_TOOLS/h5copy/testfiles" +SRC_H5REPACK_TESTFILES="$SRC_TOOLS/h5repack/testfiles" +SRC_H5JAM_TESTFILES="$SRC_TOOLS/h5jam/testfiles" +SRC_H5STAT_TESTFILES="$SRC_TOOLS/h5stat/testfiles" +SRC_H5IMPORT_TESTFILES="$SRC_TOOLS/h5import/testfiles" + +TESTDIR=./testfiles +test -d $TESTDIR || mkdir $TESTDIR + +###################################################################### +# test files +# -------------------------------------------------------------------- +# All the test files copy from source directory to test directory +# NOTE: Keep this framework to add/remove test files. +# Any test files from other tools can be used in this framework. +# This list are also used for checking exist. +# Comment '#' without space can be used. +# -------------------------------------------------------------------- +LIST_HDF5_TEST_FILES=" +$SRC_H5STAT_TESTFILES/h5stat_filters.h5 +$SRC_H5STAT_TESTFILES/h5stat_tsohm.h5 +$SRC_H5STAT_TESTFILES/h5stat_newgrat.h5 +$SRC_H5STAT_TESTFILES/h5stat_idx.h5 +$SRC_H5STAT_TESTFILES/h5stat_threshold.h5 +" + +LIST_OTHER_TEST_FILES=" +$SRC_H5STAT_TESTFILES/h5stat_help1.ddl +$SRC_H5STAT_TESTFILES/h5stat_help2.ddl +$SRC_H5STAT_TESTFILES/h5stat_notexist.ddl +$SRC_H5STAT_TESTFILES/h5stat_nofile.ddl +$SRC_H5STAT_TESTFILES/h5stat_filters.ddl +$SRC_H5STAT_TESTFILES/h5stat_filters-file.ddl +$SRC_H5STAT_TESTFILES/h5stat_filters-F.ddl +$SRC_H5STAT_TESTFILES/h5stat_filters-d.ddl +$SRC_H5STAT_TESTFILES/h5stat_filters-g.ddl +$SRC_H5STAT_TESTFILES/h5stat_filters-dT.ddl +$SRC_H5STAT_TESTFILES/h5stat_filters-UD.ddl +$SRC_H5STAT_TESTFILES/h5stat_filters-UT.ddl +$SRC_H5STAT_TESTFILES/h5stat_tsohm.ddl +$SRC_H5STAT_TESTFILES/h5stat_newgrat.ddl +$SRC_H5STAT_TESTFILES/h5stat_newgrat-UG.ddl +$SRC_H5STAT_TESTFILES/h5stat_newgrat-UA.ddl +$SRC_H5STAT_TESTFILES/h5stat_idx.ddl +$SRC_H5STAT_TESTFILES/h5stat_err1_links.ddl +$SRC_H5STAT_TESTFILES/h5stat_links1.ddl +$SRC_H5STAT_TESTFILES/h5stat_links2.ddl +$SRC_H5STAT_TESTFILES/h5stat_links3.ddl +$SRC_H5STAT_TESTFILES/h5stat_links4.ddl +$SRC_H5STAT_TESTFILES/h5stat_links5.ddl +$SRC_H5STAT_TESTFILES/h5stat_err1_dims.ddl +$SRC_H5STAT_TESTFILES/h5stat_dims1.ddl +$SRC_H5STAT_TESTFILES/h5stat_dims2.ddl +$SRC_H5STAT_TESTFILES/h5stat_err1_numattrs.ddl +$SRC_H5STAT_TESTFILES/h5stat_err2_numattrs.ddl +$SRC_H5STAT_TESTFILES/h5stat_numattrs1.ddl +$SRC_H5STAT_TESTFILES/h5stat_numattrs2.ddl +$SRC_H5STAT_TESTFILES/h5stat_numattrs3.ddl +$SRC_H5STAT_TESTFILES/h5stat_numattrs4.ddl +" + +# +# copy test files and expected output files from source dirs to test dir +# +COPY_TESTFILES="$LIST_HDF5_TEST_FILES $LIST_OTHER_TEST_FILES" + +COPY_TESTFILES_TO_TESTDIR() +{ + # copy test files. Used -f to make sure get a new copy + for tstfile in $COPY_TESTFILES + do + # ignore '#' comment + echo $tstfile | tr -d ' ' | grep '^#' > /dev/null + RET=$? + if [ $RET -eq 1 ]; then + # skip cp if srcdir is same as destdir + # this occurs when build/test performed in source dir and + # make cp fail + SDIR=`$DIRNAME $tstfile` + INODE_SDIR=`$LS -i -d $SDIR | $AWK -F' ' '{print $1}'` + INODE_DDIR=`$LS -i -d $TESTDIR | $AWK -F' ' '{print $1}'` + if [ "$INODE_SDIR" != "$INODE_DDIR" ]; then + $CP -f $tstfile $TESTDIR + if [ $? -ne 0 ]; then + echo "Error: FAILED to copy $tstfile ." + + # Comment out this to CREATE expected file + exit $EXIT_FAILURE + fi + fi + fi + done +} + +CLEAN_TESTFILES_AND_TESTDIR() +{ + # skip rm if srcdir is same as destdir + # this occurs when build/test performed in source dir and + # make cp fail + SDIR=$SRC_H5STAT_TESTFILES + INODE_SDIR=`$LS -i -d $SDIR | $AWK -F' ' '{print $1}'` + INODE_DDIR=`$LS -i -d $TESTDIR | $AWK -F' ' '{print $1}'` + if [ "$INODE_SDIR" != "$INODE_DDIR" ]; then + $RM $TESTDIR + fi +} + +# Print a line-line message left justified in a field of 70 characters +# beginning with the word "Testing". +# +TESTING() { + SPACES=" " + echo "Testing $* $SPACES" | cut -c1-70 | tr -d '\012' +} + +# Source in the output filter function definitions. +. $srcdir/../../bin/output_filter.sh + +# Run a test and print PASS or *FAIL*. If a test fails then increment +# the `nerrors' global variable and (if $verbose is set) display the +# difference between the actual output and the expected output. The +# expected output is given as the first argument to this function and +# the actual output file is calculated by replacing the `.ddl' with +# `.out'. The actual output is not removed if $HDF5_NOCLEANUP has a +# non-zero value. +# +TOOLTEST() { + expect="$TESTDIR/$1" + actual="$TESTDIR/`basename $1 .ddl`.out" + actual_err="$TESTDIR/`basename $1 .ddl`.err" + actual_sav=${actual}-sav + actual_err_sav=${actual_err}-sav + shift + + # Run test. + TESTING $STAT $@ + ( + cd $TESTDIR + $RUNSERIAL $STAT_BIN $@ + ) >$actual 2>$actual_err + + # save actual and actual_err in case they are needed later. + cp $actual $actual_sav + STDOUT_FILTER $actual + cp $actual_err $actual_err_sav + STDERR_FILTER $actual_err + cat $actual_err >> $actual + + if [ ! -f $expect ]; then + # Create the expect file if it doesn't yet exist. + echo " CREATED" + cp $actual $expect + elif $CMP $expect $actual; then + echo " PASSED" + else + echo "*FAILED*" + echo " Expected result (*.ddl) differs from actual result (*.out)" + nerrors="`expr $nerrors + 1`" + test yes = "$verbose" && $DIFF $expect $actual |sed 's/^/ /' + fi + + # Clean up output file + if test -z "$HDF5_NOCLEANUP"; then + rm -f $actual $actual_err $actual_sav $actual_err_sav + fi +} + + +# Print a "SKIP" message +SKIP() { + TESTING $STAT $@ + echo " -SKIP-" +} + + + +############################################################################## +############################################################################## +### T H E T E S T S ### +############################################################################## +############################################################################## +# prepare for test +COPY_TESTFILES_TO_TESTDIR + +# Test for help flag +TOOLTEST h5stat_help1.ddl -h +TOOLTEST h5stat_help2.ddl --help +# Test when h5stat a file that does not exist +TOOLTEST h5stat_notexist.ddl notexist.h5 +TOOLTEST h5stat_nofile.ddl '' + +# Test file with groups, compressed datasets, user-applied fileters, etc. +# h5stat_filters.h5 is a copy of ../../testfiles/tfilters.h5 as of release 1.8.0-alpha4 +TOOLTEST h5stat_filters.ddl h5stat_filters.h5 +TOOLTEST h5stat_filters-file.ddl -f h5stat_filters.h5 +TOOLTEST h5stat_filters-F.ddl -F h5stat_filters.h5 +TOOLTEST h5stat_filters-d.ddl -d h5stat_filters.h5 +TOOLTEST h5stat_filters-g.ddl -g h5stat_filters.h5 +TOOLTEST h5stat_filters-dT.ddl -dT h5stat_filters.h5 +TOOLTEST h5stat_filters-UD.ddl -D h5stat_filters.h5 +TOOLTEST h5stat_filters-UT.ddl -T h5stat_filters.h5 +# +# h5stat_tsohm.h5 is a copy of ../../../test/tsohm.h5 generated by tsohm.c +# as of release 1.8.7-snap0 (on a 64-bit machine) +TOOLTEST h5stat_tsohm.ddl h5stat_tsohm.h5 +# h5stat_newgrat.h5 is generated by h5stat_gentest.c +TOOLTEST h5stat_newgrat.ddl h5stat_newgrat.h5 +TOOLTEST h5stat_newgrat-UG.ddl -G h5stat_newgrat.h5 +TOOLTEST h5stat_newgrat-UA.ddl -A h5stat_newgrat.h5 +# h5stat_idx.h5 is generated by h5stat_gentest.c +TOOLTEST h5stat_idx.ddl h5stat_idx.h5 +# +# Tests for -l (--links) option on h5stat_threshold.h5: +# -l 0 (incorrect threshold value) +# -g -l 8 +# --links=8 +# --links=20 -g +TOOLTEST h5stat_err1_links.ddl -l 0 h5stat_threshold.h5 +TOOLTEST h5stat_links1.ddl -g -l 8 h5stat_threshold.h5 +TOOLTEST h5stat_links2.ddl --links=8 h5stat_threshold.h5 +TOOLTEST h5stat_links3.ddl --links=20 -g h5stat_threshold.h5 +# +# Tests for -l (--links) option on h5stat_newgrat.h5: +# -g +# -g -l 40000 +TOOLTEST h5stat_links4.ddl -g h5stat_newgrat.h5 +TOOLTEST h5stat_links5.ddl -g -l 40000 h5stat_newgrat.h5 +# +# Tests for -m (--dims) option on h5stat_threshold.h5 +# -d --dims=-1 (incorrect threshold value) +# -gd -m 5 +# -d --di=15 +TOOLTEST h5stat_err1_dims.ddl -d --dims=-1 h5stat_threshold.h5 +TOOLTEST h5stat_dims1.ddl -gd -m 5 h5stat_threshold.h5 +TOOLTEST h5stat_dims2.ddl -d --di=15 h5stat_threshold.h5 +# +# Tests for -a option on h5stat_threshold.h5 +# -a -2 (incorrect threshold value) +# --numattrs (without threshold value) +# -AS -a 10 +# -a 1 +# -A --numattrs=25 +TOOLTEST h5stat_err1_numattrs.ddl -a -2 h5stat_threshold.h5 +TOOLTEST h5stat_err2_numattrs.ddl --numattrs h5stat_threshold.h5 +TOOLTEST h5stat_numattrs1.ddl -AS -a 10 h5stat_threshold.h5 +TOOLTEST h5stat_numattrs2.ddl -a 1 h5stat_threshold.h5 +TOOLTEST h5stat_numattrs3.ddl -A --numattrs=25 h5stat_threshold.h5 +# +# Tests for -a option on h5stat_newgrat.h5 +# -A -a 100 +TOOLTEST h5stat_numattrs4.ddl -A -a 100 h5stat_newgrat.h5 +# + +# Clean up temporary files/directories +CLEAN_TESTFILES_AND_TESTDIR + +if test $nerrors -eq 0 ; then + echo "All $TESTNAME tests passed." + exit $EXIT_SUCCESS +else + echo "$TESTNAME tests failed with $nerrors errors." + exit $EXIT_FAILURE +fi + diff --git a/tools/src/misc/CMakeLists.txt b/tools/src/misc/CMakeLists.txt new file mode 100644 index 0000000..6fcff9c --- /dev/null +++ b/tools/src/misc/CMakeLists.txt @@ -0,0 +1,67 @@ +cmake_minimum_required (VERSION 3.1.0) +PROJECT (HDF5_TOOLS_SRC_MISC) + +#----------------------------------------------------------------------------- +# Setup include Directories +#----------------------------------------------------------------------------- +INCLUDE_DIRECTORIES (${HDF5_TOOLS_DIR}/lib) + +# -------------------------------------------------------------------- +# Add the misc executables +# -------------------------------------------------------------------- +#-- Misc Executables +add_executable (h5debug ${HDF5_TOOLS_SRC_MISC_SOURCE_DIR}/h5debug.c) +TARGET_NAMING (h5debug STATIC) +TARGET_C_PROPERTIES (h5debug STATIC " " " ") +target_link_libraries (h5debug ${HDF5_LIB_TARGET} ${HDF5_TOOLS_LIB_TARGET}) +set_target_properties (h5debug PROPERTIES FOLDER tools) +set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};h5debug") + +add_executable (h5repart ${HDF5_TOOLS_SRC_MISC_SOURCE_DIR}/h5repart.c) +TARGET_NAMING (h5repart STATIC) +TARGET_C_PROPERTIES (h5repart STATIC " " " ") +target_link_libraries (h5repart ${HDF5_LIB_TARGET} ${HDF5_TOOLS_LIB_TARGET}) +set_target_properties (h5repart PROPERTIES FOLDER tools) +set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};h5repart") + +add_executable (h5mkgrp ${HDF5_TOOLS_SRC_MISC_SOURCE_DIR}/h5mkgrp.c) +TARGET_NAMING (h5mkgrp STATIC) +TARGET_C_PROPERTIES (h5mkgrp STATIC " " " ") +target_link_libraries (h5mkgrp ${HDF5_TOOLS_LIB_TARGET} ${HDF5_LIB_TARGET}) +set_target_properties (h5mkgrp PROPERTIES FOLDER tools) +set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};h5mkgrp") + +set (H5_DEP_EXECUTABLES + h5debug + h5repart + h5mkgrp +) + +#----------------------------------------------------------------------------- +# Generate the h5cc file containing settings needed to compile programs +#----------------------------------------------------------------------------- +#if (NOT WIN32) +# configure_file (${HDF5_TOOLS_SRC_MISC_SOURCE_DIR}/h5cc.in ${HDF5_BINARY_DIR}/h5cc @ONLY) +#endif (NOT WIN32) + +############################################################################## +############################################################################## +### I N S T A L L A T I O N ### +############################################################################## +############################################################################## + +#----------------------------------------------------------------------------- +# Rules for Installation of tools using make Install target +#----------------------------------------------------------------------------- + +#INSTALL_PROGRAM_PDB (h5debug ${HDF5_INSTALL_BIN_DIR} toolsapplications) +#INSTALL_PROGRAM_PDB (h5repart ${HDF5_INSTALL_BIN_DIR} toolsapplications) +#INSTALL_PROGRAM_PDB (h5mkgrp ${HDF5_INSTALL_BIN_DIR} toolsapplications) + +install ( + TARGETS + h5debug h5repart h5mkgrp + EXPORT + ${HDF5_EXPORTED_TARGETS} + RUNTIME DESTINATION ${HDF5_INSTALL_BIN_DIR} COMPONENT toolsapplications +) diff --git a/tools/src/misc/Makefile.am b/tools/src/misc/Makefile.am new file mode 100644 index 0000000..c069e9a --- /dev/null +++ b/tools/src/misc/Makefile.am @@ -0,0 +1,61 @@ +# +# Copyright by The HDF Group. +# Copyright by the Board of Trustees of the University of Illinois. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the files COPYING and Copyright.html. COPYING can be found at the root +# of the source code distribution tree; Copyright.html can be found at the +# root level of an installed copy of the electronic HDF5 document set and +# is linked from the top-level documents page. It can also be found at +# http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have +# access to either file, you may request a copy from help@hdfgroup.org. +## +## Makefile.am +## Run automake to generate a Makefile.in from this file. +# +# HDF5 Library Makefile(.in) +# + +include $(top_srcdir)/config/commence.am + +# Include src directory +AM_CPPFLAGS+=-I$(top_srcdir)/src -I$(top_srcdir)/tools/lib + +# These are our main targets, the tools +bin_PROGRAMS=h5debug h5repart h5mkgrp +bin_SCRIPTS=h5redeploy + +# Add h5debug, h5repart, and h5mkgrp specific linker flags here +h5debug_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) +h5repart_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) +h5mkgrp_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) + +# Tell automake to clean h5redeploy script +CLEANFILES=h5redeploy + +# These were generated by configure. Remove them only when distclean. +DISTCLEANFILES=h5cc + +# All programs rely on hdf5 library and h5tools library +LDADD=$(LIBH5TOOLS) $(LIBHDF5) + +# h5cc needs custom install and uninstall rules, since it may be +# named h5pcc if hdf5 is being built in parallel mode. +if BUILD_PARALLEL_CONDITIONAL + H5CC_NAME=h5pcc +else + H5CC_NAME=h5cc +endif + +install-exec-local: + @$(INSTALL) h5cc $(DESTDIR)$(bindir)/$(H5CC_NAME) +uninstall-local: + @$(RM) $(DESTDIR)$(bindir)/$(H5CC_NAME) + +# How to build h5redeploy script +h5redeploy: h5redeploy.in + @cp $(srcdir)/$@.in $@ + +include $(top_srcdir)/config/conclude.am diff --git a/tools/src/misc/h5cc.in b/tools/src/misc/h5cc.in new file mode 100644 index 0000000..1645855 --- /dev/null +++ b/tools/src/misc/h5cc.in @@ -0,0 +1,401 @@ +#! /bin/sh +## +# Copyright by The HDF Group. +# Copyright by the Board of Trustees of the University of Illinois. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the files COPYING and Copyright.html. COPYING can be found at the root +# of the source code distribution tree; Copyright.html can be found at the +# root level of an installed copy of the electronic HDF5 document set and +# is linked from the top-level documents page. It can also be found at +# http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have +# access to either file, you may request a copy from help@hdfgroup.org. +## + +# This tool is adapted from the mpicc command of the MPICH Software. + +############################################################################ +## ## +## Things You May Have to Modify: ## +## ## +## If the following paths don't point to the place were HDF5 is installed ## +## on your system (i.e., you received a binary distribution or moved the ## +## files from the originally installed directory to another directory) ## +## then modify them accordingly to represent the new paths. ## +## ## +############################################################################ +prefix="@prefix@" +exec_prefix="@exec_prefix@" +libdir="@libdir@" +includedir="@includedir@" +HL="@HL@" + +############################################################################ +## ## +## Things You Can Modify to Override HDF5 Library Build Components: ## +## ## +## (Advanced usage - know what you're doing - you're on your own here.) ## +## The four variables below can be used to insert paths and flags in ## +## CPPFLAGS, CFLAGS, LDFLAGS, or LIBS in the h5cc compile line: ## +## $CLINKER $H5BLD_CPPFLAGS $CPPFLAGS $H5BLD_CFLAGS $CFLAGS $LDFLAGS ## +## $LIBS $clibpath $link_objs $link_args $shared_link ## +## ## +## These settings can be overriden by setting HDF5_CFLAGS, ## +## HDF5_CPPFLAGS, HDF5_LDFLAGS, or HDF5_LIBS in the environment. ## +## ## +############################################################################ +CFLAGSBASE="" +CPPFLAGSBASE="" +LDFLAGSBASE="" +LIBSBASE="" + +############################################################################ +## ## +## You shouldn't have to modify anything below this line. ## +## ## +############################################################################ + +# Constants definitions +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +host_os="@host_os@" + +prog_name="`basename $0`" + +allargs="" +compile_args="" +libraries="" +link_args="" +link_objs="" +clibpath="" + +do_link="yes" +do_compile="no" +dash_o="no" +dash_c="no" +get_output_file="no" + +SHOW="eval" +CCBASE="@CC@" +CLINKERBASE="@CC@" + +# CFLAGS, CPPFLAGS and LDFLAGS are reserved for use by the script user. +# FLAGS brought from the hdf5 build are put in H5BLD_*FLAGS. + +# User's CPPFLAGS and CFLAGS come after their H5BLD counterparts. User's +# LDFLAGS come just before clibpath, user's LIBS come after $link_objs and +# before the hdf5 libraries in $link_args, followed by any external library +# paths and libraries from AM_LDFLAGS, LDFLAGS, AM_LIBS or LIBS carried in +# from the hdf5 build. The order of the flags is intended to give precedence +# to the user's flags. +H5BLD_CFLAGS="@AM_CFLAGS@ @CFLAGS@" +H5BLD_CPPFLAGS="@AM_CPPFLAGS@ @CPPFLAGS@" +H5BLD_LDFLAGS="@AM_LDFLAGS@ @LDFLAGS@" +H5BLD_LIBS="@LIBS@" + +CC="${HDF5_CC:-$CCBASE}" +CLINKER="${HDF5_CLINKER:-$CLINKERBASE}" +CFLAGS="${HDF5_CFLAGS:-$CFLAGSBASE}" +CPPFLAGS="${HDF5_CPPFLAGS:-$CPPFLAGSBASE}" +LDFLAGS="${HDF5_LDFLAGS:-$LDFLAGSBASE}" +LIBS="${HDF5_LIBS:-$LIBSBASE}" + +# If a static library is available, the default will be to use it. If the only +# available library is shared, it will be used by default. The user can +# override either default, although choosing an unavailable library will result +# in link errors. +STATIC_AVAILABLE="@enable_static@" +if test "${STATIC_AVAILABLE}" = "yes"; then + USE_SHARED_LIB="${HDF5_USE_SHLIB:-no}" +else + USE_SHARED_LIB="${HDF5_USE_SHLIB:-yes}" +fi + + +usage() { + # A wonderfully informative "usage" message. + echo "usage: $prog_name [OPTIONS] <compile line>" + echo " OPTIONS:" + echo " -help This help message." + echo " -echo Show all the shell commands executed" + echo " -prefix=DIR Prefix directory to find HDF5 lib/ and include/" + echo " subdirectories [default: $prefix]" + # A wonderfully informative "usage" message. + echo "usage: $prog_name [OPTIONS] <compile line>" + echo " OPTIONS:" + echo " -help This help message." + echo " -echo Show all the shell commands executed" + echo " -prefix=DIR Prefix directory to find HDF5 lib/ and include/" + echo " subdirectories [default: $prefix]" + echo " -show Show the commands without executing them" + echo " -showconfig Show the HDF5 library configuration summary" + echo " -shlib Compile with shared HDF5 libraries [default for hdf5 built" + echo " without static libraries]" + echo " -noshlib Compile with static HDF5 libraries [default for hdf5 built" + echo " with static libraries]" + echo " " + echo " <compile line> - the normal compile line options for your compiler." + echo " $prog_name uses the same compiler you used to compile" + echo " HDF5. Check with your compiler's man pages for more" + echo " information on which options are needed." + echo " " + echo " You can override the compiler, linker, and whether or not to use static" + echo " or shared libraries to compile your program by setting the following" + echo " environment variables accordingly:" + echo " " + echo " HDF5_CC - use a different C compiler" + echo " HDF5_CLINKER - use a different linker" + echo " HDF5_USE_SHLIB=[yes|no] - use shared or static version of the HDF5 library" + echo " [default: no except when built with only" + echo " shared libraries]" + echo " " + echo " You can also add or change paths and flags to the compile line using" + echo " the following environment varibles or by assigning them to their counterparts" + echo " in the 'Things You Can Modify to Override...'" section of $prog_name + echo " " + echo " Variable Current value to be replaced" + echo " HDF5_CPPFLAGS \"$CPPFLAGSBASE\"" + echo " HDF5_CFLAGS \"$CFLAGSBASE\"" + echo " HDF5_LDFLAGS \"$LDFLAGSBASE\"" + echo " HDF5_LIBS \"$LIBSBASE\"" + echo " " + echo " Note that adding library paths to HDF5_LDFLAGS where another hdf5 version" + echo " is located may link your program with that other hdf5 library version." + echo " " + exit $EXIT_FAILURE +} + +# Show the configuration summary of the library recorded in the +# libhdf5.settings file reside in the lib directory. +showconfigure() +{ + cat ${libdir}/libhdf5.settings + status=$? +} + +# Main +status=$EXIT_SUCCESS + +if test "$#" = "0"; then + # No parameters specified, issue usage statement and exit. + usage +fi + +case "$CC" in + gcc) + kind="gcc" + ;; + mpicc|mpcc|mpicc_r) + # Is this gcc masquarading as an MPI compiler? + if test "`${CC} -v 2>&1 | sed -n 2p | cut -c1-3`" = "gcc"; then + kind="gcc" + else + # Nope + kind="$host_os" + fi + ;; + *) + kind="$host_os" + ;; +esac + +for arg in $@ ; do + if test "x$get_output_file" = "xyes"; then + link_args="$link_args $arg" + output_file="$arg" + get_output_file="no" + continue + fi + + case "$arg" in + -c) + allargs="$allargs $arg" + compile_args="$compile_args $arg" + + if test "x$do_link" = "xyes" -a -n "$output_file"; then + compile_args="$compile_args -o $output_file" + fi + + do_link="no" + dash_c="yes" + ;; + -o) + allargs="$allargs $arg" + dash_o="yes" + + if test "x$dash_c" = "xyes"; then + compile_args="$compile_args $arg" + else + link_args="$link_args $arg" + do_link="yes" + get_output_file="yes" + fi + ;; + -E|-M|-MT) + allargs="$allargs $arg" + compile_args="$compile_args $arg" + dash_c="yes" + do_link="no" + ;; + -l*) + libraries=" $libraries $arg " + allargs="$allargs $arg" + ;; + -prefix=*) + prefix="`expr "$arg" : '-prefix=\(.*\)'`" + ;; + -echo) + set -x + ;; + -show) + SHOW="echo" + ;; + -showconfig) + showconfigure + exit $status + ;; + -shlib) + USE_SHARED_LIB="yes" + ;; + -noshlib) + USE_SHARED_LIB="no" + ;; + -help) + usage + ;; + *\"*) + qarg="'"$arg"'" + allargs="$allargs $qarg" + ;; + *\'*) + qarg='\"'"$arg"'\"' + allargs="$allargs $qarg" + ;; + *) + allargs="$allargs $qarg" + + if test -s "$arg"; then + ext=`expr "$arg" : '.*\(\..*\)'` + + if test "x$ext" = "x.c"; then + do_compile="yes" + compile_args="$compile_args $arg" + fname=`basename $arg .c` + link_objs="$link_objs $fname.o" + elif test "x$ext" = "x.o"; then + if test "x$dash_c" = "xyes"; then + compile_args="$compile_args $arg" + else + do_link="yes" + link_objs="$link_objs $arg" + fi + elif test "x$ext" = "x.a"; then + # This is an archive that we're linking in + libraries=" $libraries $arg " + else + compile_args="$compile_args $arg" + link_args="$link_args $arg" + fi + else + compile_args="$compile_args $arg" + link_args="$link_args $arg" + fi + ;; + esac +done + +if test "$dash_c" = "yes" -a "$do_compile" = no -a "$do_link" = no ; then + # -c was specified. Force do_compile on. + do_compile=yes +fi + +if test "x$do_compile" = "xyes"; then + if test "x$dash_c" != "xyes"; then + compile_args="-c $compile_args" + fi + + $SHOW $CC -I$includedir $H5BLD_CPPFLAGS $CPPFLAGS $H5BLD_CFLAGS $CFLAGS $compile_args + status=$? + + if test "$status" != "0"; then + exit $status + fi +fi + +if test "x$do_link" = "xyes"; then + shared_link="" +# conditionnaly link with the hl library + if test "X$HL" = "Xhl"; then + libraries=" $libraries -lhdf5_hl -lhdf5 " + else + libraries=" $libraries -lhdf5 " + fi + link_args="$link_args -L${libdir}" + + case "$kind" in + gcc|linux*) + # MacOS X doesn't support the "-Wl,-rpath -Wl," style of linker flags. + # It appears to want none of them specified. + case "$host_os" in + darwin*) flag="" ;; + *) flag="-Wl,-rpath -Wl," ;; + esac + ;; + hpux*) flag="-Wl,+b -Wl," ;; + freebsd*|solaris*) flag="-R" ;; + rs6000*|aix*) flag="-L" ;; + sgi) flag="-rpath " ;; + *) flag="" ;; + esac + + if test -n "$flag"; then + shared_link="${flag}${libdir}" + fi + + if test "x$USE_SHARED_LIB" != "xyes"; then + # The "-lhdf5" & "-lhdf5_hl" flags are in here already...This is a static + # compile though, so change it to the static version (.a) of the library. + new_libraries="" + for lib in $libraries; do + case "$lib" in + -lhdf5) + new_libraries="$new_libraries ${libdir}/libhdf5.a" + ;; + -lhdf5_hl) + new_libraries="$new_libraries ${libdir}/libhdf5_hl.a" + ;; + *) + new_libraries="$new_libraries $lib" + ;; + esac + done + libraries="$new_libraries" + fi + + for lib in $libraries; do + if echo $link_args | grep " $lib " > /dev/null || + echo $link_args | grep " $lib$" > /dev/null; then + : + else + link_args="$link_args $lib " + fi + done + + # The LIBS are just a bunch of -l* libraries necessary for the HDF5 + # module. It's okay if they're included twice in the compile line. + link_args="$link_args $H5BLD_LDFLAGS $H5BLD_LIBS" + + # User's CPPFLAGS and CFLAGS come after their H5BLD counterparts. User's + # LDFLAGS come just before clibpath, user's LIBS come after $link_objs and + # before the hdf5 libraries in $link_args, followed by any external library + # paths and libraries from AM_LDFLAGS, LDFLAGS, AM_LIBS or LIBS carried in + # from the hdf5 build. The order of the flags is intended to give precedence + # to the user's flags. + $SHOW $CLINKER $H5BLD_CPPFLAGS $CPPFLAGS $H5BLD_CFLAGS $CFLAGS $LDFLAGS $clibpath $link_objs $LIBS $link_args $shared_link + status=$? +fi + +exit $status diff --git a/tools/src/misc/h5debug.c b/tools/src/misc/h5debug.c new file mode 100644 index 0000000..ae64952 --- /dev/null +++ b/tools/src/misc/h5debug.c @@ -0,0 +1,723 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: debug.c + * Jul 18 1997 + * Robb Matzke <matzke@llnl.gov> + * + * Purpose: Debugs an existing HDF5 file at a low level. + * + *------------------------------------------------------------------------- + */ +#define H5A_FRIEND /*suppress error about including H5Apkg */ +#define H5B2_FRIEND /*suppress error about including H5B2pkg */ +#define H5B2_TESTING /*suppress warning about H5B2 testing funcs*/ +#define H5D_FRIEND /*suppress error about including H5Dpkg */ +#define H5EA_FRIEND /*suppress error about including H5EApkg */ +#define H5EA_TESTING /*suppress warning about H5EA testing funcs*/ +#define H5FA_FRIEND /*suppress error about including H5FApkg */ +#define H5FA_TESTING /*suppress warning about H5FA testing funcs*/ +#define H5F_FRIEND /*suppress error about including H5Fpkg */ +#define H5G_FRIEND /*suppress error about including H5Gpkg */ +#define H5HF_FRIEND /*suppress error about including H5HFpkg */ +#define H5O_FRIEND /*suppress error about including H5Opkg */ +#define H5SM_FRIEND /*suppress error about including H5SMpkg */ + +#include "H5private.h" /* Generic Functions */ +#include "H5Apkg.h" /* Attributes */ +#include "H5B2pkg.h" /* v2 B-trees */ +#include "H5Dpkg.h" /* Datasets */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5EApkg.h" /* Extensible Arrays */ +#include "H5FApkg.h" /* Fixed Arrays */ +#include "H5Fpkg.h" /* File access */ +#include "H5FSprivate.h" /* Free space manager */ +#include "H5Gpkg.h" /* Groups */ +#include "H5HFpkg.h" /* Fractal heaps */ +#include "H5HGprivate.h" /* Global Heaps */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Opkg.h" /* Object headers */ +#include "H5SMpkg.h" /* Implicitly shared messages */ + +/* File drivers */ +#include "H5FDfamily.h" + +#define VCOL 50 + + +/*------------------------------------------------------------------------- + * Function: get_H5B2_class + * + * Purpose: Determine the v2 B-tree class from the buffer read in. + * B-trees are debugged through the B-tree subclass. The subclass + * identifier is two bytes after the B-tree signature. + * + * Return: Non-NULL on success/NULL on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 11 2008 + * + *------------------------------------------------------------------------- + */ +static const H5B2_class_t * +get_H5B2_class(const uint8_t *sig) +{ + H5B2_subid_t subtype = (H5B2_subid_t)sig[H5_SIZEOF_MAGIC + 1]; + const H5B2_class_t *cls; + + switch(subtype) { + case H5B2_TEST_ID: + cls = H5B2_TEST; + break; + + case H5B2_FHEAP_HUGE_INDIR_ID: + cls = H5HF_HUGE_BT2_INDIR; + break; + + case H5B2_FHEAP_HUGE_FILT_INDIR_ID: + cls = H5HF_HUGE_BT2_FILT_INDIR; + break; + + case H5B2_FHEAP_HUGE_DIR_ID: + cls = H5HF_HUGE_BT2_DIR; + break; + + case H5B2_FHEAP_HUGE_FILT_DIR_ID: + cls = H5HF_HUGE_BT2_FILT_DIR; + break; + + case H5B2_GRP_DENSE_NAME_ID: + cls = H5G_BT2_NAME; + break; + + case H5B2_GRP_DENSE_CORDER_ID: + cls = H5G_BT2_CORDER; + break; + + case H5B2_SOHM_INDEX_ID: + cls = H5SM_INDEX; + break; + + case H5B2_ATTR_DENSE_NAME_ID: + cls = H5A_BT2_NAME; + break; + + case H5B2_ATTR_DENSE_CORDER_ID: + cls = H5A_BT2_CORDER; + break; + + case H5B2_CDSET_ID: + cls = H5D_BT2; + break; + + case H5B2_CDSET_FILT_ID: + cls = H5D_BT2_FILT; + break; + + case H5B2_TEST2_ID: + cls = H5B2_TEST2; + break; + + case H5B2_NUM_BTREE_ID: + default: + HDfprintf(stderr, "Unknown v2 B-tree subtype %u\n", (unsigned)(subtype)); + HDexit(4); + } /* end switch */ + + return(cls); +} /* end get_H5B2_class() */ + + +/*------------------------------------------------------------------------- + * Function: get_H5EA_class + * + * Purpose: Determine the extensible array class from the buffer read in. + * Extensible arrays are debugged through the array subclass. + * The subclass identifier is two bytes after the signature. + * + * Return: Non-NULL on success/NULL on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 11 2008 + * + *------------------------------------------------------------------------- + */ +static const H5EA_class_t * +get_H5EA_class(const uint8_t *sig) +{ + H5EA_cls_id_t clsid = (H5EA_cls_id_t)sig[H5_SIZEOF_MAGIC + 1]; + const H5EA_class_t *cls; + + switch(clsid) { + case H5EA_CLS_TEST_ID: + cls = H5EA_CLS_TEST; + break; + + case H5EA_CLS_CHUNK_ID: + cls = H5EA_CLS_CHUNK; + break; + + case H5EA_CLS_FILT_CHUNK_ID: + cls = H5EA_CLS_FILT_CHUNK; + break; + + case H5EA_NUM_CLS_ID: + default: + HDfprintf(stderr, "Unknown extensible array class %u\n", (unsigned)(clsid)); + HDexit(4); + } /* end switch */ + + return(cls); +} /* end get_H5EA_class() */ + + +/*------------------------------------------------------------------------- + * Function: get_H5FA_class + * + * Purpose: Determine the fixed array class from the buffer read in. + * Extensible arrays are debugged through the array subclass. + * The subclass identifier is two bytes after the signature. + * + * Return: Non-NULL on success/NULL on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Sep 11 2008 + * + *------------------------------------------------------------------------- + */ +static const H5FA_class_t * +get_H5FA_class(const uint8_t *sig) +{ + H5FA_cls_id_t clsid = (H5FA_cls_id_t)sig[H5_SIZEOF_MAGIC + 1]; + const H5FA_class_t *cls; + + switch(clsid) { + case H5FA_CLS_TEST_ID: + cls = H5FA_CLS_TEST; + break; + + case H5FA_CLS_CHUNK_ID: + cls = H5FA_CLS_CHUNK; + break; + + case H5FA_CLS_FILT_CHUNK_ID: + cls = H5FA_CLS_FILT_CHUNK; + break; + + case H5FA_NUM_CLS_ID: + default: + HDfprintf(stderr, "Unknown fixed array class %u\n", (unsigned)(clsid)); + HDexit(4); + } /* end switch */ + + return(cls); +} /* end get_H5FA_class() */ + + +/*------------------------------------------------------------------------- + * Function: main + * + * Usage: debug FILENAME [OFFSET] + * + * Return: Success: exit (0) + * + * Failure: exit (non-zero) + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 18 1997 + * + *------------------------------------------------------------------------- + */ +int +main(int argc, char *argv[]) +{ + hid_t fid, fapl, dxpl; + H5F_t *f; + haddr_t addr = 0, extra = 0, extra2 = 0, extra3 = 0, extra4 = 0; + uint8_t sig[H5F_SIGNATURE_LEN]; + size_t u; + H5E_auto2_t func; + void *edata; + herr_t status = SUCCEED; + + if(argc == 1) { + HDfprintf(stderr, "Usage: %s filename [signature-addr [extra]]\n", argv[0]); + HDexit(1); + } /* end if */ + + /* Initialize the library */ + if(H5open() < 0) { + HDfprintf(stderr, "cannot initialize the library\n"); + HDexit(1); + } /* end if */ + + /* Disable error reporting */ + H5Eget_auto2(H5E_DEFAULT, &func, &edata); + H5Eset_auto2(H5E_DEFAULT, NULL, NULL); + + /* + * Open the file and get the file descriptor. + */ + dxpl = H5AC_ind_read_dxpl_id; + if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) { + HDfprintf(stderr, "cannot create file access property list\n"); + HDexit(1); + } /* end if */ + if(HDstrchr(argv[1], '%')) + if(H5Pset_fapl_family (fapl, (hsize_t)0, H5P_DEFAULT) < 0) { + fprintf(stderr, "cannot set file access property list\n"); + HDexit(1); + } + if((fid = H5Fopen(argv[1], H5F_ACC_RDONLY, fapl)) < 0) { + HDfprintf(stderr, "cannot open file\n"); + HDexit(1); + } /* end if */ + if(NULL == (f = (H5F_t *)H5I_object(fid))) { + HDfprintf(stderr, "cannot obtain H5F_t pointer\n"); + HDexit(2); + } /* end if */ + + /* Ignore metadata tags while using h5debug */ + if(H5AC_ignore_tags(f) < 0) { + HDfprintf(stderr, "cannot ignore metadata tags\n"); + HDexit(1); + } + + /* + * Parse command arguments. + */ + if(argc > 2) + addr = (haddr_t)HDstrtoll(argv[2], NULL, 0); + if(argc > 3) + extra = (haddr_t)HDstrtoll(argv[3], NULL, 0); + if(argc > 4) + extra2 = (haddr_t)HDstrtoll(argv[4], NULL, 0); + if(argc > 5) + extra3 = (haddr_t)HDstrtoll(argv[5], NULL, 0); + if(argc > 6) + extra4 = (haddr_t)HDstrtoll(argv[6], NULL, 0); + + /* + * Read the signature at the specified file position. + */ + HDfprintf(stdout, "Reading signature at address %a (rel)\n", addr); + if(H5F_block_read(f, H5FD_MEM_SUPER, addr, sizeof(sig), dxpl, sig) < 0) { + HDfprintf(stderr, "cannot read signature\n"); + HDexit(3); + } + if(!HDmemcmp(sig, H5F_SIGNATURE, (size_t)H5F_SIGNATURE_LEN)) { + /* + * Debug the file's super block. + */ + status = H5F_debug(f, stdout, 0, VCOL); + + } else if(!HDmemcmp(sig, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug a local heap. + */ + status = H5HL_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL); + + } else if(!HDmemcmp (sig, H5HG_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug a global heap collection. + */ + status = H5HG_debug (f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL); + + } else if(!HDmemcmp(sig, H5G_NODE_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug a symbol table node. + */ + + /* Check for extra parameters */ + if(extra == 0) { + HDfprintf(stderr, "\nWarning: Providing the group's local heap address will give more information\n"); + HDfprintf(stderr, "Symbol table node usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <Symbol table node address> <address of local heap>\n\n"); + } /* end if */ + + status = H5G_node_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, extra); + + } else if(!HDmemcmp(sig, H5B_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug a B-tree. B-trees are debugged through the B-tree + * subclass. The subclass identifier is the byte immediately + * after the B-tree signature. + */ + H5B_subid_t subtype = (H5B_subid_t)sig[H5_SIZEOF_MAGIC]; + unsigned ndims; + uint32_t dim[H5O_LAYOUT_NDIMS]; + + switch(subtype) { + case H5B_SNODE_ID: + /* Check for extra parameters */ + if(extra == 0) { + HDfprintf(stderr, "\nWarning: Providing the group's local heap address will give more information\n"); + HDfprintf(stderr, "B-tree symbol table node usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <B-tree node address> <address of local heap>\n\n"); + HDexit(4); + } /* end if */ + + status = H5G_node_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, extra); + break; + + case H5B_CHUNK_ID: + /* Check for extra parameters */ + if(extra == 0) { + HDfprintf(stderr, "ERROR: Need number of dimensions of chunk in order to dump chunk B-tree node\n"); + HDfprintf(stderr, "B-tree chunked storage node usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <B-tree node address> <# of dimensions> <slowest chunk dim>...<fastest chunk dim>\n"); + HDexit(4); + } /* end if */ + + /* Build array of chunk dimensions */ + ndims = (unsigned)extra; + dim[0] = (uint32_t)extra2; + if(ndims > 1) + dim[1] = (uint32_t)extra3; + if(ndims > 2) + dim[2] = (uint32_t)extra4; + + /* Check for dimension error */ + if(ndims > 3) { + HDfprintf(stderr, "ERROR: Only 3 dimensions support currently (fix h5debug)\n"); + HDfprintf(stderr, "B-tree chunked storage node usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <B-tree node address> <# of dimensions> <slowest chunk dim>...<fastest chunk dim>\n"); + HDexit(4); + } /* end for */ + for(u = 0; u < ndims; u++) + if(0 == dim[u]) { + HDfprintf(stderr, "ERROR: Chunk dimensions should be >0\n"); + HDfprintf(stderr, "B-tree chunked storage node usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <B-tree node address> <# of dimensions> <slowest chunk dim>...<fastest chunk dim>\n"); + HDexit(4); + } /* end if */ + + /* Set the last dimension (the element size) to zero */ + dim[ndims] = 0; + + status = H5D_btree_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, ndims, dim); + break; + + case H5B_NUM_BTREE_ID: + default: + HDfprintf(stderr, "Unknown v1 B-tree subtype %u\n", (unsigned)(subtype)); + HDexit(4); + } + + } else if(!HDmemcmp(sig, H5B2_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug a v2 B-tree header. + */ + const H5B2_class_t *cls = get_H5B2_class(sig); + HDassert(cls); + + if((cls == H5D_BT2 || cls == H5D_BT2_FILT) && extra == 0) { + HDfprintf(stderr, "ERROR: Need v2 B-tree header address and object header address containing the layout message in order to dump header\n"); + HDfprintf(stderr, "v2 B-tree hdr usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <v2 B-tree header address> <object header address>\n"); + HDexit(4); + } /* end if */ + + status = H5B2__hdr_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, cls, (haddr_t)extra); + + } else if(!HDmemcmp(sig, H5B2_INT_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug a v2 B-tree internal node. + */ + const H5B2_class_t *cls = get_H5B2_class(sig); + HDassert(cls); + + /* Check for enough valid parameters */ + if((cls == H5D_BT2 || cls == H5D_BT2_FILT) && + (extra == 0 || extra2 == 0 || extra3 == 0 || extra4 == 0)) { + + fprintf(stderr, "ERROR: Need v2 B-tree header address, the node's number of records, depth, and object header address containing the layout message in order to dump internal node\n"); + fprintf(stderr, "NOTE: Leaf nodes are depth 0, the internal nodes above them are depth 1, etc.\n"); + fprintf(stderr, "v2 B-tree internal node usage:\n"); + fprintf(stderr, "\th5debug <filename> <internal node address> <v2 B-tree header address> <number of records> <depth> <object header address>\n"); + HDexit(4); + + } else if(extra == 0 || extra2 == 0 || extra3 == 0) { + HDfprintf(stderr, "ERROR: Need v2 B-tree header address and the node's number of records and depth in order to dump internal node\n"); + HDfprintf(stderr, "NOTE: Leaf nodes are depth 0, the internal nodes above them are depth 1, etc.\n"); + HDfprintf(stderr, "v2 B-tree internal node usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <internal node address> <v2 B-tree header address> <number of records> <depth>\n"); + HDexit(4); + } /* end if */ + + status = H5B2__int_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, cls, extra, (unsigned)extra2, (unsigned)extra3, (haddr_t)extra4); + + } else if(!HDmemcmp(sig, H5B2_LEAF_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug a v2 B-tree leaf node. + */ + const H5B2_class_t *cls = get_H5B2_class(sig); + HDassert(cls); + + /* Check for enough valid parameters */ + if((cls == H5D_BT2 || cls == H5D_BT2_FILT) && + (extra == 0 || extra2 == 0 || extra3 == 0 )) { + + fprintf(stderr, "ERROR: Need v2 B-tree header address, number of records, and object header address containing the layout message in order to dump leaf node\n"); + fprintf(stderr, "v2 B-tree leaf node usage:\n"); + fprintf(stderr, "\th5debug <filename> <leaf node address> <v2 B-tree header address> <number of records> <object header address>\n"); + HDexit(4); + + } else if(extra == 0 || extra2 == 0) { + HDfprintf(stderr, "ERROR: Need v2 B-tree header address and number of records in order to dump leaf node\n"); + HDfprintf(stderr, "v2 B-tree leaf node usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <leaf node address> <v2 B-tree header address> <number of records>\n"); + HDexit(4); + } /* end if */ + + status = H5B2__leaf_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, cls, extra, (unsigned)extra2, (haddr_t)extra3); + + } else if(!HDmemcmp(sig, H5HF_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug a fractal heap header. + */ + status = H5HF_hdr_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL); + + } else if(!HDmemcmp(sig, H5HF_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug a fractal heap direct block. + */ + + /* Check for enough valid parameters */ + if(extra == 0 || extra2 == 0) { + HDfprintf(stderr, "ERROR: Need fractal heap header address and size of direct block in order to dump direct block\n"); + HDfprintf(stderr, "Fractal heap direct block usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <direct block address> <heap header address> <size of direct block>\n"); + HDexit(4); + } /* end if */ + + status = H5HF_dblock_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, extra, (size_t)extra2); + + } else if(!HDmemcmp(sig, H5HF_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug a fractal heap indirect block. + */ + + /* Check for enough valid parameters */ + if(extra == 0 || extra2 == 0) { + HDfprintf(stderr, "ERROR: Need fractal heap header address and number of rows in order to dump indirect block\n"); + HDfprintf(stderr, "Fractal heap indirect block usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <indirect block address> <heap header address> <number of rows>\n"); + HDexit(4); + } /* end if */ + + status = H5HF_iblock_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, extra, (unsigned)extra2); + + } else if(!HDmemcmp(sig, H5FS_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug a free space header. + */ + + status = H5FS_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL); + + } else if(!HDmemcmp(sig, H5FS_SINFO_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug free space serialized sections. + */ + + /* Check for enough valid parameters */ + if(extra == 0 || extra2 == 0) { + HDfprintf(stderr, "ERROR: Need free space header address and client address in order to dump serialized sections\n"); + HDfprintf(stderr, "Free space serialized sections usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <serialized sections address> <free space header address> <client address>\n"); + HDexit(4); + } /* end if */ + + status = H5FS_sects_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, extra, extra2); + + } else if(!HDmemcmp(sig, H5SM_TABLE_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug shared message master table. + */ + + status = H5SM_table_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, (unsigned) UFAIL, (unsigned) UFAIL); + + } else if(!HDmemcmp(sig, H5SM_LIST_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug shared message list index. + */ + + /* Check for enough valid parameters */ + if(extra == 0) { + HDfprintf(stderr, "ERROR: Need shared message header address in order to shared message list\n"); + HDfprintf(stderr, "Shared message list usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <shared message list address> <shared message header address>\n"); + HDexit(4); + } /* end if */ + + status = H5SM_list_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, (haddr_t)extra); + + } else if(!HDmemcmp(sig, H5EA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug an extensible aray header. + */ + const H5EA_class_t *cls = get_H5EA_class(sig); + HDassert(cls); + + /* Check for enough valid parameters */ + if(extra == 0) { + HDfprintf(stderr, "ERROR: Need object header address containing the layout message in order to dump header\n"); + HDfprintf(stderr, "Extensible array header block usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <Extensible Array header address> <object header address>\n"); + HDexit(4); + } /* end if */ + + status = H5EA__hdr_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, cls, extra); + + } else if(!HDmemcmp(sig, H5EA_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug an extensible aray index block. + */ + const H5EA_class_t *cls = get_H5EA_class(sig); + HDassert(cls); + + /* Check for enough valid parameters */ + if(extra == 0 || extra2 == 0) { + HDfprintf(stderr, "ERROR: Need extensible array header address and object header address containing the layout message in order to dump index block\n"); + HDfprintf(stderr, "Extensible array index block usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <index block address> <array header address> <object header address\n"); + HDexit(4); + } /* end if */ + + status = H5EA__iblock_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, cls, extra, extra2); + + } else if(!HDmemcmp(sig, H5EA_SBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug an extensible aray super block. + */ + const H5EA_class_t *cls = get_H5EA_class(sig); + HDassert(cls); + + /* Check for enough valid parameters */ + if(extra == 0 || extra2 == 0 || extra3 == 0) { + HDfprintf(stderr, "ERROR: Need extensible array header address, super block index and object header address containing the layout message in order to dump super block\n"); + HDfprintf(stderr, "Extensible array super block usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <super block address> <array header address> <super block index> <object header address>\n"); + HDexit(4); + } /* end if */ + + status = H5EA__sblock_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, cls, extra, (unsigned)extra2, extra3); + + } else if(!HDmemcmp(sig, H5EA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug an extensible aray data block. + */ + const H5EA_class_t *cls = get_H5EA_class(sig); + HDassert(cls); + + /* Check for enough valid parameters */ + if(extra == 0 || extra2 == 0 || extra3 == 0) { + HDfprintf(stderr, "ERROR: Need extensible array header address, # of elements in data block and object header address containing the layout message in order to dump data block\n"); + HDfprintf(stderr, "Extensible array data block usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <data block address> <array header address> <# of elements in data block> <object header address\n"); + HDexit(4); + } /* end if */ + + status = H5EA__dblock_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, cls, extra, (size_t)extra2, extra3); + + } else if(!HDmemcmp(sig, H5FA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug a fixed array header. + */ + const H5FA_class_t *cls = get_H5FA_class(sig); + HDassert(cls); + + /* Check for enough valid parameters */ + if(extra == 0) { + HDfprintf(stderr, "ERROR: Need object header address containing the layout message in order to dump header\n"); + HDfprintf(stderr, "Fixed array header block usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <Fixed Array header address> <object header address>\n"); + HDexit(4); + } /* end if */ + + status = H5FA__hdr_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, cls, extra); + + } else if(!HDmemcmp(sig, H5FA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug a fixed array data block. + */ + const H5FA_class_t *cls = get_H5FA_class(sig); + HDassert(cls); + + /* Check for enough valid parameters */ + if(extra == 0 || extra2 == 0) { + HDfprintf(stderr, "ERROR: Need fixed array header address and object header address containing the layout message in order to dump data block\n"); + HDfprintf(stderr, "fixed array data block usage:\n"); + HDfprintf(stderr, "\th5debug <filename> <data block address> <array header address> <object header address>\n"); + HDexit(4); + } /* end if */ + + status = H5FA__dblock_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL, cls, extra, extra2); + + } else if(!HDmemcmp(sig, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { + /* + * Debug v2 object header (which have signatures). + */ + + status = H5O_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL); + + } else if(sig[0] == H5O_VERSION_1) { + /* + * This could be a v1 object header. Since they don't have a signature + * it's a somewhat "ify" detection. + */ + status = H5O_debug(f, H5AC_ind_read_dxpl_id, addr, stdout, 0, VCOL); + + } else { + /* + * Got some other unrecognized signature. + */ + printf("%-*s ", VCOL, "Signature:"); + for (u = 0; u < sizeof(sig); u++) { + if (sig[u] > ' ' && sig[u] <= '~' && '\\' != sig[u]) + HDputchar(sig[u]); + else if ('\\' == sig[u]) { + HDputchar('\\'); + HDputchar('\\'); + } else + printf("\\%03o", sig[u]); + } + HDputchar('\n'); + + HDfprintf(stderr, "unknown signature\n"); + HDexit(4); + } /* end else */ + + /* Check for an error when dumping information */ + if(status < 0) { + HDfprintf(stderr, "An error occurred!\n"); + H5Eprint2(H5E_DEFAULT, stderr); + HDexit(5); + } /* end if */ + + H5Pclose(fapl); + H5Fclose(fid); + + H5Eset_auto2(H5E_DEFAULT, func, edata); + + return 0; +} /* main() */ + diff --git a/tools/src/misc/h5mkgrp.c b/tools/src/misc/h5mkgrp.c new file mode 100644 index 0000000..ad2d306 --- /dev/null +++ b/tools/src/misc/h5mkgrp.c @@ -0,0 +1,336 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + +#include "H5private.h" +#include "h5tools.h" +#include "h5tools_utils.h" +#include <string.h> +#include <stdlib.h> + +/* Name of tool */ +#define PROGRAMNAME "h5mkgrp" + +/* Exit status for tools library routines */ +int d_status = EXIT_SUCCESS; + +/* command-line options: short and long-named parameters */ +static const char *s_opts = "hlpvV"; +static struct long_options l_opts[] = { + { "help", no_arg, 'h' }, + { "latest", no_arg, 'l' }, + { "parents", no_arg, 'p' }, + { "verbose", no_arg, 'v' }, + { "version", no_arg, 'V' }, + { NULL, 0, '\0' } +}; + +/* Command line parameter settings */ +typedef struct { + char *fname; /* File name to operate on */ + hbool_t latest; /* Whether file should use latest format versions */ + hbool_t verbose; /* Whether output should be verbose */ + hbool_t parents; /* Whether to create intermediate groups */ + size_t ngroups; /* Number of groups to create */ + char **groups; /* Pointer to array of group names */ +} param_t; +param_t params; /* Command line parameter settings */ + + +/*------------------------------------------------------------------------- + * Function: leave + * + * Purpose: Shutdown MPI and/or HDF5 and call exit() + * + * Return: Does not return + * + * Programmer: Quincey Koziol, 2/13/2007 + * + *------------------------------------------------------------------------- + */ +static void +leave(int ret) +{ + size_t curr_group; + + if (params.fname) + HDfree (params.fname); + if (params.ngroups) { + for(curr_group = 0; curr_group < params.ngroups; curr_group++) + HDfree (params.groups[curr_group]); + HDfree (params.groups); + } + h5tools_close(); + HDexit(ret); +} /* end leave() */ + + +/*------------------------------------------------------------------------- + * Function: usage + * + * Purpose: Prints a usage message on stderr and then returns. + * + * Return: void + * + * Programmer: Quincey Koziol, 2/13/2007 + * + *------------------------------------------------------------------------- + */ +static void +usage(void) +{ + HDfprintf(stdout, "\ +usage: h5mkgrp [OPTIONS] FILE GROUP...\n\ + OPTIONS\n\ + -h, --help Print a usage message and exit\n\ + -l, --latest Use latest version of file format to create groups\n\ + -p, --parents No error if existing, make parent groups as needed\n\ + -v, --verbose Print information about OBJECTS and OPTIONS\n\ + -V, --version Print version number and exit\n"); +} /* end usage() */ + + +/*------------------------------------------------------------------------- + * Function: parse_command_line + * + * Purpose: Parses command line and sets up global variable to control output + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Quincey Koziol, 2/13/2007 + * + *------------------------------------------------------------------------- + */ +static int +parse_command_line(int argc, const char *argv[], param_t *parms) +{ + int opt; /* Option from command line */ + size_t curr_group; /* Current group name to copy */ + + /* Check for empty command line */ + if(argc == 1) { + usage(); + leave(EXIT_SUCCESS); + } /* end if */ + + /* Parse command line options */ + while((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { + switch((char)opt) { + /* Display 'help' */ + case 'h': + usage(); + leave(EXIT_SUCCESS); + + /* Create objects with the latest version of the format */ + case 'l': + parms->latest = TRUE; + break; + + /* Create parent groups */ + case 'p': + parms->parents = TRUE; + break; + + /* Verbose output */ + case 'v': + parms->verbose = TRUE; + break; + + /* Display version */ + case 'V': + print_version(h5tools_getprogname()); + leave(EXIT_SUCCESS); + + /* Bad command line argument */ + default: + usage(); + leave(EXIT_FAILURE); + } /* end switch */ + } /* end while */ + + /* Check for file name to be processed */ + if(argc <= opt_ind) { + error_msg("missing file name\n"); + usage(); + leave(EXIT_FAILURE); + } /* end if */ + + /* Retrieve file name */ + parms->fname = HDstrdup(argv[opt_ind]); + opt_ind++; + + /* Check for group(s) to be created */ + if(argc <= opt_ind) { + error_msg("missing group name(s)\n"); + usage(); + leave(EXIT_FAILURE); + } /* end if */ + + /* Allocate space for the group name pointers */ + parms->ngroups = (size_t)(argc - opt_ind); + parms->groups = (char **)HDmalloc(parms->ngroups * sizeof(char *)); + + /* Retrieve the group names */ + curr_group = 0; + while(opt_ind < argc) { + parms->groups[curr_group] = HDstrdup(argv[opt_ind]); + curr_group++; + opt_ind++; + } /* end while */ + +#ifdef QAK +HDfprintf(stderr, "parms->parents = %t\n", parms->parents); +HDfprintf(stderr, "parms->verbose = %t\n", parms->verbose); +HDfprintf(stderr, "parms->fname = '%s'\n", parms->fname); +HDfprintf(stderr, "parms->ngroups = %Zu\n", parms->ngroups); +for(curr_group = 0; curr_group < parms->ngroups; curr_group++) + HDfprintf(stderr, "parms->group[%Zu] = '%s'\n", curr_group, parms->groups[curr_group]); +#endif /* QAK */ + + return(0); +} /* parse_command_line() */ + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: Create group(s) in an HDF5 file + * + * Programmer: Quincey Koziol, 2/13/2007 + * + *------------------------------------------------------------------------- + */ +int +main(int argc, const char *argv[]) +{ + hid_t fid; /* HDF5 file ID */ + hid_t fapl_id; /* File access property list ID */ + hid_t lcpl_id; /* Link creation property list ID */ + size_t curr_group; /* Current group to create */ + + h5tools_setprogname(PROGRAMNAME); + h5tools_setstatus(EXIT_SUCCESS); + + /* Disable the HDF5 library's error reporting */ + H5Eset_auto2(H5E_DEFAULT, NULL, NULL); + + /* Initialize h5tools lib */ + h5tools_init(); + + /* Parse command line */ + HDmemset(¶ms, 0, sizeof(params)); + if(parse_command_line(argc, argv, ¶ms) < 0) { + error_msg("unable to parse command line arguments\n"); + leave(EXIT_FAILURE); + } /* end if */ + + /* Create file access property list */ + if((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) { + error_msg("Could not create file access property list\n"); + leave(EXIT_FAILURE); + } /* end if */ + + /* Check for creating groups with new format version */ + if(params.latest) { + /* Set the "use the latest version of the format" bounds */ + if(H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) { + error_msg("Could not set property for using latest version of the format\n"); + leave(EXIT_FAILURE); + } /* end if */ + + /* Display some output if requested */ + if(params.verbose) + printf("%s: Creating groups with latest version of the format\n", h5tools_getprogname()); + } /* end if */ + + /* Attempt to open an existing HDF5 file first */ + fid = h5tools_fopen(params.fname, H5F_ACC_RDWR, fapl_id, NULL, NULL, 0); + + /* If we couldn't open an existing file, try creating file */ + /* (use "EXCL" instead of "TRUNC", so we don't blow away existing non-HDF5 file) */ + if(fid < 0) + fid = H5Fcreate(params.fname, H5F_ACC_EXCL, H5P_DEFAULT, fapl_id); + + /* Test for error in opening file */ + if(fid < 0) { + error_msg("Could not open output file '%s'\n", params.fname); + leave(EXIT_FAILURE); + } /* end if */ + + /* Create link creation property list */ + if((lcpl_id = H5Pcreate(H5P_LINK_CREATE)) < 0) { + error_msg("Could not create link creation property list\n"); + leave(EXIT_FAILURE); + } /* end if */ + + /* Check for creating intermediate groups */ + if(params.parents) { + /* Set the intermediate group creation property */ + if(H5Pset_create_intermediate_group(lcpl_id, TRUE) < 0) { + error_msg("Could not set property for creating parent groups\n"); + leave(EXIT_FAILURE); + } /* end if */ + + /* Display some output if requested */ + if(params.verbose) + printf("%s: Creating parent groups\n", h5tools_getprogname()); + } /* end if */ + + /* Loop over creating requested groups */ + for(curr_group = 0; curr_group < params.ngroups; curr_group++) { + hid_t gid; /* Group ID */ + + /* Attempt to create a group */ + if((gid = H5Gcreate2(fid, params.groups[curr_group], lcpl_id, H5P_DEFAULT, H5P_DEFAULT)) < 0) { + error_msg("Could not create group '%s'\n", params.groups[curr_group]); + leave(EXIT_FAILURE); + } /* end if */ + + /* Close the group */ + if(H5Gclose(gid) < 0) { + error_msg("Could not close group '%s'??\n", params.groups[curr_group]); + leave(EXIT_FAILURE); + } /* end if */ + + /* Display some output if requested */ + if(params.verbose) + printf("%s: created group '%s'\n", h5tools_getprogname(), params.groups[curr_group]); + } /* end for */ + + /* Close link creation property list */ + if(H5Pclose(lcpl_id) < 0) { + error_msg("Could not close link creation property list\n"); + leave(EXIT_FAILURE); + } /* end if */ + + /* Close file */ + if(H5Fclose(fid) < 0) { + error_msg("Could not close output file '%s'??\n", params.fname); + leave(EXIT_FAILURE); + } /* end if */ + + /* Close file access property list */ + if(H5Pclose(fapl_id) < 0) { + error_msg("Could not close file access property list\n"); + leave(EXIT_FAILURE); + } /* end if */ + + /* Shut down h5tools lib */ + h5tools_close(); + + leave(EXIT_SUCCESS); +} /* end main() */ + diff --git a/tools/src/misc/h5redeploy.in b/tools/src/misc/h5redeploy.in new file mode 100644 index 0000000..6b6ef87 --- /dev/null +++ b/tools/src/misc/h5redeploy.in @@ -0,0 +1,218 @@ +#! /bin/sh +# +# Copyright by The HDF Group. +# Copyright by the Board of Trustees of the University of Illinois. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the files COPYING and Copyright.html. COPYING can be found at the root +# of the source code distribution tree; Copyright.html can be found at the +# root level of an installed copy of the electronic HDF5 document set and +# is linked from the top-level documents page. It can also be found at +# http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have +# access to either file, you may request a copy from help@hdfgroup.org. +# + +## Update HDF5 compiler tools after the HDF5 software has been installed ## +## in a new location. ## +## For help page, use "h5redeploy -help" ## +## ## + +# Constants definitions +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +# Function definitions + +# show help page +usage() { + # A wonderfully informative "usage" message. + echo "usage: $prog_name [OPTIONS]" + echo " OPTIONS:" + echo " -help|help This help message" + echo " -echo Show all the shell commands executed" + echo " -force No prompt, just do it" + echo " -prefix=DIR New directory to find HDF5 lib/ and include/" + echo " subdirectories [default: current directory]" + echo " -exec-prefix=DIR New directory to find HDF5 lib/" + echo " subdirectory [default: <prefix>]" + echo " -libdir=DIR New directory for the HDF5 lib directory" + echo " [default: <exec-prefix>/lib]" + echo " -includedir=DIR New directory for the HDF5 header files" + echo " [default: <prefix>/include]" + echo " -tool=TOOL Tool to update. TOOL must be in the current" + echo " directory and writable. [default: $h5tools]" + echo " -show Show the commands without executing them" + echo " " + exit $EXIT_FAILURE +} + +# display variable values +dump_vars(){ + echo "====Showing all variable values=====" + echo prefix=$prefix + echo h5tools=$h5tools + echo "====End Showing=====" +} + +# show actions to be taken +show_action() +{ + echo "Update the following tools because they are now installed at a new directory" + for t in $foundtools; do + echo "${t}:" + echo " current setting=`sed -e '/^prefix=/s/prefix=//p' -e d $t`" + echo " new setting="\""$prefix"\" + done +} + + +# Report Error message +ERROR() +{ + echo "***ERROR***" + echo "$1" +} + +# Main +# +############################################################################ +## Installation directories: ## +## prefix architecture-independent files. ## +## exec_prefix architecture-dependent files, default is <prefix>. ## +## libdir libraries, default is <exec_prefix>/lib. ## +## includedir header files, default is <prefix/include>. ## +## Not used here: ## +## bindir executables, <exec_prefix/bin>. ## +############################################################################ +# Initialization +h5tools="h5cc h5pcc h5fc h5pfc h5c++" # possible hdf5 tools +foundtools= # tools found and will be modified +fmode= # force mode, default is off +prefix= +exec_prefix= +libdir= +includedir= + +# Parse options +for arg in $@ ; do + case "$arg" in + -prefix=*) + prefix="`echo $arg | cut -f2 -d=`" + ;; + -exec-prefix=*) + exec_prefix="`echo $arg | cut -f2 -d=`" + ;; + -libdir=*) + libdir="`echo $arg | cut -f2 -d=`" + ;; + -includedir=*) + includedir="`echo $arg | cut -f2 -d=`" + ;; + -echo) + set -x + ;; + -show) + SHOW="echo" + ;; + -tool=*) + h5tools="`echo $arg | cut -f2 -d=`" + ;; + -help|help) + usage + ;; + -force) + fmode=yes + ;; + *) + ERROR "Unknown Option($arg)" + usage + exit $EXIT_FAILURE + ;; + esac +done + +# Set to default value, one above where i am, if not given by user +if [ -z "$prefix" ]; then + prefix=`(cd ..;pwd)` +fi +if [ -z "$exec_prefix" ]; then + exec_prefix='${prefix}' # use single quotes to prevent expansion of $ +fi +if [ -z "$libdir" ]; then + libdir='${exec_prefix}'/lib # use single quotes to prevent expansion of $ +fi +if [ -z "$includedir" ]; then + includedir='${prefix}'/include # use single quotes to prevent expansion of $ +fi + +for x in $h5tools; do + if [ -f $x ]; then + foundtools="$foundtools $x" + if [ ! -w $x ]; then + ERROR "h5tool($x) is not writable" + exit $EXIT_FAILURE + fi + fi +done + +if [ -z "$foundtools" ]; then + ERROR "found no tools to modify" + exit $EXIT_FAILURE +fi + +# Show actions to be taken and get consent +show_action +# Ask confirmation unless fmode is on +if [ x-$fmode = x- ]; then + echo "Continue? (yes/no)" + read ansx + ans=`echo $ansx | tr "[A-Z]" "[a-z]"` + if [ x-$ans != x-yes ]; then + echo ABORT. No tools changed. + exit $EXIT_FAILURE + fi +fi + + +# Create the update commands +CMDFILE=/tmp/h5redeploy.$$ +touch $CMDFILE +chmod 0600 $CMDFILE +echo "/^prefix=/c" >> $CMDFILE +echo prefix=\""$prefix"\" >> $CMDFILE +echo . >> $CMDFILE +echo "/^exec_prefix=/c" >> $CMDFILE +echo exec_prefix=\""$exec_prefix"\" >> $CMDFILE +echo . >> $CMDFILE +echo "/^libdir=/c" >> $CMDFILE +echo libdir=\""$libdir"\" >> $CMDFILE +echo . >> $CMDFILE +echo "/^includedir=/c" >> $CMDFILE +echo includedir=\""$includedir"\" >> $CMDFILE +echo . >> $CMDFILE +(echo w; echo q) >> $CMDFILE + + +# Update them +if [ "$SHOW" = "echo" ]; then + echo "===Update commands are:====" + cat $CMDFILE + echo "===End Update commands=====" +fi + +for t in $foundtools; do + echo Update $t ... + COMMAND="ed - $t" + if [ "$SHOW" = "echo" ]; then + echo $COMMAND + else + $COMMAND < $CMDFILE + fi +done + + +# Cleanup +rm -f $CMDFILE +exit $EXIT_SUCCESS diff --git a/tools/src/misc/h5repart.c b/tools/src/misc/h5repart.c new file mode 100644 index 0000000..e44c957 --- /dev/null +++ b/tools/src/misc/h5repart.c @@ -0,0 +1,510 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Robb Matzke <matzke@llnl.gov> + * Wednesday, May 13, 1998 + * + * Purpose: Repartitions a file family. This program can be used to + * split a single file into a family of files, join a family of + * files into a single file, or copy one family to another while + * changing the size of the family members. It can also be used + * to copy a single file to a single file with holes. + */ + +/* See H5private.h for how to include system headers */ +#include "hdf5.h" +#include "H5private.h" +#ifdef H5_STDC_HEADERS +# include <ctype.h> +# include <errno.h> +# include <fcntl.h> +# include <stdio.h> +# include <stdlib.h> +# include <string.h> +#endif + +#ifdef H5_HAVE_UNISTD_H +# include <sys/types.h> +# include <unistd.h> +#endif + +#ifdef H5_HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif + +#ifndef FALSE +# define FALSE 0 +#endif +#ifndef TRUE +# define TRUE 1 +#endif +# define NAMELEN 4096 +#define GB *1024*1024*1024 + +#ifndef MIN +# define MIN(X,Y) ((X)<(Y)?(X):(Y)) +#endif +#ifndef MIN3 +# define MIN3(X,Y,Z) MIN(MIN(X,Y),Z) +#endif + +/*Make these 2 private properties(defined in H5Fprivate.h) available to h5repart. + *The first one updates the member file size in the superblock. The second one + *change file driver from family to sec2. */ +#define H5F_ACS_FAMILY_NEWSIZE_NAME "family_newsize" +#define H5F_ACS_FAMILY_TO_SEC2_NAME "family_to_sec2" + + +/*------------------------------------------------------------------------- + * Function: usage + * + * Purpose: Prints a usage message. + * + * Return: void + * + * Programmer: Robb Matzke + * Wednesday, May 13, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +usage (const char *progname) +{ + fprintf(stderr, "usage: %s [-v] [-V] [-[b|m] N[g|m|k]] [-family_to_sec2] SRC DST\n", + progname); + fprintf(stderr, " -v Produce verbose output\n"); + fprintf(stderr, " -V Print a version number and exit\n"); + fprintf(stderr, " -b N The I/O block size, defaults to 1kB\n"); + fprintf(stderr, " -m N The destination member size or 1GB\n"); + fprintf(stderr, " -family_to_sec2 Change file driver from family to sec2\n"); + fprintf(stderr, " SRC The name of the source file\n"); + fprintf(stderr, " DST The name of the destination files\n"); + fprintf(stderr, "Sizes may be suffixed with `g' for GB, `m' for MB or " + "`k' for kB.\n"); + fprintf(stderr, "File family names include an integer printf " + "format such as `%%d'\n"); + exit (EXIT_FAILURE); +} + + +/*------------------------------------------------------------------------- + * Function: get_size + * + * Purpose: Reads a size option of the form `-XNS' where `X' is any + * letter, `N' is a multi-character positive decimal number, and + * `S' is an optional suffix letter in the set [GgMmk]. The + * option may also be split among two arguments as: `-X NS'. + * The input value of ARGNO is the argument number for the + * switch in the ARGV vector and ARGC is the number of entries + * in that vector. + * + * Return: Success: The value N multiplied according to the + * suffix S. On return ARGNO will be the number + * of the next argument to process. + * + * Failure: Calls usage() which exits with a non-zero + * status. + * + * Programmer: Robb Matzke + * Wednesday, May 13, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static off_t +get_size (const char *progname, int *argno, int argc, char *argv[]) +{ + off_t retval=-1; + char *suffix; + + if (isdigit ((int)(argv[*argno][2]))) { + retval = strtol (argv[*argno]+2, &suffix, 10); + (*argno)++; + } else if (argv[*argno][2] || *argno+1>=argc) { + usage (progname); + } else { + retval = strtol (argv[*argno+1], &suffix, 0); + if (suffix==argv[*argno+1]) usage (progname); + *argno += 2; + } + if (suffix && suffix[0] && !suffix[1]) { + switch (*suffix) { + case 'G': + case 'g': + retval *= 1024 * 1024 * 1024; + break; + case 'M': + case 'm': + retval *= 1024 * 1024; + break; + case 'k': + retval *= 1024; + break; + default: + usage (progname); + } + } else if (suffix && suffix[0]) { + usage (progname); + } + return retval; +} + + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: Split an hdf5 file + * + * Return: Success: + * + * Failure: + * + * Programmer: Robb Matzke + * Wednesday, May 13, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +main (int argc, char *argv[]) +{ + const char *prog_name; /*program name */ + size_t blk_size=1024; /*size of each I/O block */ + char *buf=NULL; /*I/O block buffer */ + size_t n, i; /*counters */ + ssize_t nio; /*I/O return value */ + int argno=1; /*program argument number */ + int src, dst=-1; /*source & destination files */ + int need_seek=FALSE; /*destination needs to seek? */ + int need_write; /*data needs to be written? */ + h5_stat_t sb; /*temporary file stat buffer */ + + int verbose=FALSE; /*display file names? */ + + const char *src_gen_name; /*general source name */ + char *src_name=NULL; /*source member name */ + + int src_is_family; /*is source name a family name? */ + int src_membno=0; /*source member number */ + + const char *dst_gen_name; /*general destination name */ + char *dst_name=NULL; /*destination member name */ + int dst_is_family; /*is dst name a family name? */ + int dst_membno=0; /*destination member number */ + + off_t left_overs=0; /*amount of zeros left over */ + off_t src_offset=0; /*offset in source member */ + off_t dst_offset=0; /*offset in destination member */ + off_t src_size; /*source logical member size */ + off_t src_act_size; /*source actual member size */ + off_t dst_size=1 GB; /*destination logical memb size */ + hid_t fapl; /*file access property list */ + hid_t file; + hsize_t hdsize; /*destination logical memb size */ + hbool_t family_to_sec2=FALSE; /*change family to sec2 driver? */ + + /* + * Get the program name from argv[0]. Use only the last component. + */ + if ((prog_name=strrchr (argv[0], '/'))) prog_name++; + else prog_name = argv[0]; + + /* + * Parse switches. + */ + while (argno<argc && '-'==argv[argno][0]) { + if (!strcmp (argv[argno], "-v")) { + verbose = TRUE; + argno++; + } else if (!strcmp(argv[argno], "-V")) { + printf("This is %s version %u.%u release %u\n", + prog_name, H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE); + exit(EXIT_SUCCESS); + } else if (!strcmp (argv[argno], "-family_to_sec2")) { + family_to_sec2 = TRUE; + argno++; + } else if ('b'==argv[argno][1]) { + blk_size = (size_t)get_size (prog_name, &argno, argc, argv); + } else if ('m'==argv[argno][1]) { + dst_size = get_size (prog_name, &argno, argc, argv); + } else { + usage (prog_name); + } /* end if */ + } /* end while */ + + /* allocate names */ + if(NULL == (src_name = (char *)HDcalloc((size_t)NAMELEN, sizeof(char)))) + exit(EXIT_FAILURE); + if(NULL == (dst_name = (char *)HDcalloc((size_t)NAMELEN, sizeof(char)))) + exit(EXIT_FAILURE); + + /* + * Get the name for the source file and open the first member. The size + * of the first member determines the logical size of all the members. + */ + if (argno>=argc) usage (prog_name); + src_gen_name = argv[argno++]; + sprintf (src_name, src_gen_name, src_membno); + src_is_family = strcmp (src_name, src_gen_name); + + if ((src=HDopen(src_name, O_RDONLY,0))<0) { + perror (src_name); + exit (EXIT_FAILURE); + } + + if (HDfstat(src, &sb)<0) { + perror ("fstat"); + exit (EXIT_FAILURE); + } + src_size = src_act_size = sb.st_size; + if (verbose) fprintf (stderr, "< %s\n", src_name); + + /* + * Get the name for the destination file and open the first member. + */ + if (argno>=argc) usage (prog_name); + dst_gen_name = argv[argno++]; + sprintf (dst_name, dst_gen_name, dst_membno); + dst_is_family = strcmp (dst_name, dst_gen_name); + + if ((dst=HDopen (dst_name, O_RDWR|O_CREAT|O_TRUNC, 0666))<0) { + perror (dst_name); + exit (EXIT_FAILURE); + } + if (verbose) fprintf (stderr, "> %s\n", dst_name); + + /* No more arguments */ + if (argno<argc) usage (prog_name); + + /* Now the real work, split the file */ + buf = (char *)HDmalloc(blk_size); + while (src_offset<src_size) { + + /* Read a block. The amount to read is the minimum of: + * 1. The I/O block size + * 2. What's left to write in the destination member + * 3. Left over zeros or what's left in the source member. + */ + n = blk_size; + if (dst_is_family) n = (size_t)MIN((off_t)n, dst_size-dst_offset); + if (left_overs) { + n = (size_t)MIN ((off_t)n, left_overs); + left_overs = left_overs - (off_t)n; + need_write = FALSE; + } else if (src_offset<src_act_size) { + n = (size_t)MIN ((off_t)n, src_act_size-src_offset); + if ((nio=HDread (src, buf, n))<0) { + perror ("read"); + exit (EXIT_FAILURE); + } else if ((size_t)nio!=n) { + fprintf (stderr, "%s: short read\n", src_name); + exit (EXIT_FAILURE); + } + for (i=0; i<n; i++) { + if (buf[i]) break; + } + need_write = (i<n); + } else { + n = 0; + left_overs = src_size - src_act_size; + need_write = FALSE; + } + + /* + * If the block contains non-zero data then write it to the + * destination, otherwise just remember that we'll have to do a seek + * later in the destination when we finally get non-zero data. + */ + if (need_write) { + if (need_seek && HDlseek (dst, dst_offset, SEEK_SET)<0) { + perror ("HDlseek"); + exit (EXIT_FAILURE); + } + if ((nio=HDwrite (dst, buf, n))<0) { + perror ("write"); + exit (EXIT_FAILURE); + } else if ((size_t)nio!=n) { + fprintf (stderr, "%s: short write\n", dst_name); + exit (EXIT_FAILURE); + } + need_seek = FALSE; + } else { + need_seek = TRUE; + } + + /* + * Update the source offset and open the next source family member if + * necessary. The source stream ends at the first member which + * cannot be opened because it doesn't exist. At the end of the + * source stream, update the destination offset and break out of the + * loop. The destination offset must be updated so we can fix + * trailing holes. + */ + src_offset = src_offset + (off_t)n; + if (src_offset==src_act_size) { + HDclose (src); + if (!src_is_family) { + dst_offset = dst_offset + (off_t)n; + break; + } + sprintf (src_name, src_gen_name, ++src_membno); + if ((src=HDopen (src_name, O_RDONLY,0))<0 && ENOENT==errno) { + dst_offset = dst_offset + (off_t)n; + break; + } else if (src<0) { + perror (src_name); + exit (EXIT_FAILURE); + } + if (HDfstat (src, &sb)<0) { + perror ("fstat"); + exit (EXIT_FAILURE); + } + src_act_size = sb.st_size; + if (src_act_size>src_size) { + fprintf (stderr, "%s: member truncated to %lu bytes\n", + src_name, (unsigned long)src_size); + } + src_offset = 0; + if (verbose) fprintf (stderr, "< %s\n", src_name); + } + + /* + * Update the destination offset, opening a new member if one will be + * needed. The first member is extended to the logical member size + * but other members might be smaller if they end with a hole. + */ + dst_offset = dst_offset + (off_t)n; + if (dst_is_family && dst_offset==dst_size) { + if (0==dst_membno) { + if (HDlseek (dst, dst_size-1, SEEK_SET)<0) { + perror ("HDHDlseek"); + exit (EXIT_FAILURE); + } + if (HDread (dst, buf, 1)<0) { + perror ("read"); + exit (EXIT_FAILURE); + } + if (HDlseek (dst, dst_size-1, SEEK_SET)<0) { + perror ("HDlseek"); + exit (EXIT_FAILURE); + } + if (HDwrite (dst, buf, 1)<0) { + perror ("write"); + exit (EXIT_FAILURE); + } + } + HDclose (dst); + sprintf (dst_name, dst_gen_name, ++dst_membno); + if ((dst=HDopen (dst_name, O_RDWR|O_CREAT|O_TRUNC, 0666))<0) { + perror (dst_name); + exit (EXIT_FAILURE); + } + dst_offset = 0; + need_seek = FALSE; + if (verbose) fprintf (stderr, "> %s\n", dst_name); + } + } + + /* + * Make sure the last family member is the right size and then close it. + * The last member can't end with a hole or hdf5 will think that the + * family has been truncated. + */ + if (need_seek) { + if (HDlseek (dst, dst_offset-1, SEEK_SET)<0) { + perror ("HDlseek"); + exit (EXIT_FAILURE); + } + if (HDread (dst, buf, 1)<0) { + perror ("read"); + exit (EXIT_FAILURE); + } + if (HDlseek (dst, dst_offset-1, SEEK_SET)<0) { + perror ("HDlseek"); + exit (EXIT_FAILURE); + } + if (HDwrite (dst, buf, 1)<0) { + perror ("write"); + exit (EXIT_FAILURE); + } + } + HDclose (dst); + + /* Modify family driver information saved in superblock through private property. + * These private properties are for this tool only. */ + if ((fapl=H5Pcreate(H5P_FILE_ACCESS))<0) { + perror ("H5Pcreate"); + exit (EXIT_FAILURE); + } + + if(family_to_sec2) { + /* The user wants to change file driver from family to sec2. Open the file + * with sec2 driver. This property signals the library to ignore the family + * driver information saved in the superblock. */ + if(H5Pset(fapl, H5F_ACS_FAMILY_TO_SEC2_NAME, &family_to_sec2) < 0) { + perror ("H5Pset"); + exit (EXIT_FAILURE); + } + } else { + /* Modify family size saved in superblock through private property. It signals + * library to save the new member size(specified in command line) in superblock. + * This private property is for this tool only. */ + if(H5Pset_fapl_family(fapl, H5F_FAMILY_DEFAULT, H5P_DEFAULT) < 0) { + perror ("H5Pset_fapl_family"); + exit (EXIT_FAILURE); + } + + /* Set the property of the new member size as hsize_t */ + hdsize = (hsize_t)dst_size; + if(H5Pset(fapl, H5F_ACS_FAMILY_NEWSIZE_NAME, &hdsize) < 0) { + perror ("H5Pset"); + exit (EXIT_FAILURE); + } + } + + /* If the new file is a family file, try to open file for "read and write" to + * flush metadata. Flushing metadata will update the superblock to the new + * member size. If the original file is a family file and the new file is a sec2 + * file, the property FAMILY_TO_SEC2 will signal the library to switch to sec2 + * driver when the new file is opened. If the original file is a sec2 file and the + * new file can only be a sec2 file, reopen the new file should fail. There's + * nothing to do in this case. */ + H5E_BEGIN_TRY { + file=H5Fopen(dst_gen_name, H5F_ACC_RDWR, fapl); + } H5E_END_TRY; + + if(file>=0) { + if(H5Fclose(file)<0) { + perror ("H5Fclose"); + exit (EXIT_FAILURE); + } /* end if */ + } /* end if */ + + if(H5Pclose(fapl)<0) { + perror ("H5Pclose"); + exit (EXIT_FAILURE); + } /* end if */ + + /* Free resources and return */ + HDfree(src_name); + HDfree(dst_name); + HDfree(buf); + return EXIT_SUCCESS; +} /* end main */ |