diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 79c0c2a66f..4afb742f47 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -7,6 +7,8 @@ This file contains a high-level description of this package's evolution. Release ## 4.8.1 - TBD + +* [Bug Fix] Fix ncdump bug when printing VLENs with basetype char. See [Github #1986](https://github.com/Unidata/netcdf-c/issues/1986). * [Bug Fixes] The netcdf-c library was incorrectly determining the scope of types referred to by nc_inq_type_equal. See [Github #1959](https://github.com/Unidata/netcdf-c/pull/1959) for more information. * [Bug Fix] Fix bug in use of XGetopt when building under Mingw. See [Github #2009](https://github.com/Unidata/netcdf-c/issues/2009). * [Enhancement] Improve the error reporting when attempting to use a filter for which no implementation can be found in HDF5_PLUGIN_PATH. See [Github #2000](https://github.com/Unidata/netcdf-c/pull/2000) for more information. diff --git a/nc_test4/CMakeLists.txt b/nc_test4/CMakeLists.txt index 980dab7fab..d4f97bfd7b 100644 --- a/nc_test4/CMakeLists.txt +++ b/nc_test4/CMakeLists.txt @@ -28,6 +28,7 @@ IF(BUILD_UTILITIES) SET(NC4_TESTS ${NC4_TESTS} tst_xplatform) build_bin_test(renamegroup) add_sh_test(nc_test4 run_grp_rename) + build_bin_test(tst_charvlenbug) ADD_SH_TEST(nc_test4 tst_misc) build_bin_test(tst_fillonly) ADD_SH_TEST(nc_test4 test_fillonly) diff --git a/nc_test4/Makefile.am b/nc_test4/Makefile.am index 6c0142c7b7..8075b7373b 100644 --- a/nc_test4/Makefile.am +++ b/nc_test4/Makefile.am @@ -35,7 +35,7 @@ tst_h_scalar tst_rename tst_rename2 tst_rename3 tst_h5_endians \ tst_atts_string_rewrite tst_hdf5_file_compat tst_fill_attr_vanish \ tst_rehash tst_filterparser tst_bug324 tst_types tst_atts3 \ tst_put_vars tst_elatefill tst_udf tst_put_vars_two_unlim_dim \ -tst_bug1442 +tst_bug1442 tst_charvlenbug # Temporary I hoped, but hoped in vain. if !ISCYGWIN diff --git a/nc_test4/tst_charvlenbug.c b/nc_test4/tst_charvlenbug.c new file mode 100755 index 0000000000..8a407bbd39 --- /dev/null +++ b/nc_test4/tst_charvlenbug.c @@ -0,0 +1,111 @@ +#define AFIRST + +#include +#include +#include +#include "netcdf.h" + +#define FILE "tst_charvlenbug.nc" + +void checkErrorCode(int status, const char* message){ + if (status != NC_NOERR){ + fprintf(stderr,"Error code: %d: %s\n",status,message); + } +} + +int +main(int argc, const char * argv[]) +{ + int ncid; + int retval; + int dimid_a; + int dimid_b; + int dimids[2]; + int varid; + int typeid; + int ndims, dimids_read[NC_MAX_VAR_DIMS]; + size_t dimlen; + size_t num_items; + ptrdiff_t stride[2] = {1, 1}; + nc_vlen_t vlenPointers[4]; + nc_vlen_t* readVlenPointers; + +#ifdef AFIRST + size_t start[2] = {1, 0}; + size_t count[2] = {2, 2}; +#else + size_t start[2] = {0, 1}; + size_t count[2] = {2, 2}; +#endif + + // set up data + + vlenPointers[0].len = 1; vlenPointers[0].p = "a"; + vlenPointers[1].len = 2; vlenPointers[1].p = "aa"; + vlenPointers[2].len = 1; vlenPointers[2].p = "b"; + vlenPointers[3].len = 2; vlenPointers[3].p = "bb"; + + // -- WRITE -- + + retval = nc_create(FILE, NC_NETCDF4, &ncid); + checkErrorCode(retval, "nc_create"); + + // Define dimensions + retval = nc_def_dim(ncid, "a", NC_UNLIMITED, &dimid_a); + checkErrorCode(retval, "nc_def_dim for 'a'"); + + retval = nc_def_dim(ncid, "b", 4, &dimid_b); + checkErrorCode(retval, "nc_def_dim for 'b'"); + + /* Define VLEN type */ + retval = nc_def_vlen(ncid,"str",NC_CHAR,&typeid); + checkErrorCode(retval, "nc_def_vlen"); + + // Define variable +#ifdef AFIRST + dimids[0] = dimid_a; + dimids[1] = dimid_b; +#else + dimids[0] = dimid_b; + dimids[1] = dimid_a; +#endif + retval = nc_def_var(ncid, "var", typeid, 2, dimids, &varid); + checkErrorCode(retval, "nc_def_var"); + + // Put variable + + retval = nc_put_vars(ncid, varid, start, count, stride, vlenPointers); +// retval = nc_put_vara_string(ncid, varid, start, count, vlenPointers); + checkErrorCode(retval, "nc_put_vars_string"); + + retval = nc_close(ncid); + checkErrorCode(retval, "nc_close(1)"); + + // -- READ -- + retval = nc_open(FILE, NC_NOWRITE, &ncid); + checkErrorCode(retval, "nc_open"); + + // get dimensions + retval = nc_inq_var(ncid, varid, NULL, NULL, &ndims, dimids_read, NULL); + checkErrorCode(retval, "nc_inq_var"); + + // calculate num elements to read + dimlen = 0; + num_items = 1; + for ( int j = 0; j < ndims; ++j ) { + retval = nc_inq_dimlen(ncid, dimids_read[j], &dimlen); + checkErrorCode(retval, "nc_inq_dimlen"); + num_items *= dimlen; + } + + // get var + readVlenPointers = (nc_vlen_t*)malloc(sizeof(nc_vlen_t)*num_items); + retval = nc_get_var(ncid, varid, readVlenPointers); + checkErrorCode(retval, "nc_get_var"); + + retval = nc_close(ncid); + checkErrorCode(retval, "nc_close(2)"); + + free(readVlenPointers); + return retval; +} diff --git a/nc_test4/tst_misc.sh b/nc_test4/tst_misc.sh index 1642f5b99f..1e594d3fdf 100755 --- a/nc_test4/tst_misc.sh +++ b/nc_test4/tst_misc.sh @@ -5,16 +5,27 @@ if test "x$srcdir" = x ; then srcdir=`pwd`; fi set -e +ECODE=0 + echo "*** Testing phony dimension creation on pure h5 file" rm -f ./tmp if $NCDUMP -L0 -K ${srcdir}/tdset.h5 >./tmp ; then echo "*** Pass: phony dimension creation" -ECODE=0 else echo "*** Fail: phony dimension creation" ECODE=1 fi +echo "*** Testing char(*) type printout error in ncdump" +rm -f ./tst_charvlenbug.nc ./tmp +${execdir}/tst_charvlenbug +if $NCDUMP ./tst_charvlenbug.nc 2>1 >./tmp ; then + echo "*** Pass: char(*) ncdump printout" +else + echo "*** Fail: char(*) ncdump printout" + ECODE=1 +fi + rm -f tmp exit $ECODE diff --git a/ncdump/dumplib.c b/ncdump/dumplib.c index 95e20023e6..03fe3b278e 100644 --- a/ncdump/dumplib.c +++ b/ncdump/dumplib.c @@ -696,8 +696,11 @@ ncbyte_typ_tostring(const nctype_t *typ, safebuf_t *sfbf, const void *valp) { int ncchar_typ_tostring(const nctype_t *typ, safebuf_t *sfbf, const void *valp) { char sout[PRIM_LEN]; + char cstr[2]; int res; - res = snprintf(sout, PRIM_LEN, typ->fmt, *(char *)valp); +cstr[0] = *(char*)valp; +cstr[1] = '\0'; + res = snprintf(sout, PRIM_LEN, typ->fmt, cstr); assert(res < PRIM_LEN); sbuf_cpy(sfbf, sout); return sbuf_len(sfbf);