fixed SEGFAULT for NULL parameter for nc_inq_format(), added testing, improved documentation

This commit is contained in:
Ed Hartnett 2017-11-22 06:53:23 -07:00
parent 64b500cf24
commit 70c739858b
3 changed files with 229 additions and 109 deletions

View File

@ -1575,88 +1575,111 @@ NC3_inq_base_pe(int ncid, int *pe)
return NC_NOERR;
}
/**
* Return the file format.
*
* \param ncid the ID of the open file.
* \param formatp a pointer that gets the format. Ignored if NULL.
*
* \returns NC_NOERR No error.
* \returns NC_EBADID Bad ncid.
* \internal
* \author Ed Hartnett, Dennis Heimbigner
*/
int
NC3_inq_format(int ncid, int *formatp)
{
int status;
NC *nc;
NC3_INFO* nc3;
int status;
NC *nc;
NC3_INFO* nc3;
status = NC_check_id(ncid, &nc);
if(status != NC_NOERR)
return status;
nc3 = NC3_DATA(nc);
status = NC_check_id(ncid, &nc);
if(status != NC_NOERR)
return status;
nc3 = NC3_DATA(nc);
/* only need to check for netCDF-3 variants, since this is never called for netCDF-4 files */
/* Why even call this function with no format pointer? */
if (!formatp)
return NC_NOERR;
/* only need to check for netCDF-3 variants, since this is never called for netCDF-4 files */
#ifdef USE_CDF5
if (fIsSet(nc3->flags, NC_64BIT_DATA))
*formatp = NC_FORMAT_CDF5;
else
if (fIsSet(nc3->flags, NC_64BIT_DATA))
*formatp = NC_FORMAT_CDF5;
else
#endif
if (fIsSet(nc3->flags, NC_64BIT_OFFSET))
*formatp = NC_FORMAT_64BIT_OFFSET;
else
*formatp = NC_FORMAT_CLASSIC;
return NC_NOERR;
*formatp = NC_FORMAT_64BIT_OFFSET;
else
*formatp = NC_FORMAT_CLASSIC;
return NC_NOERR;
}
/**
* Return the extended format (i.e. the dispatch model), plus the mode
* associated with an open file.
*
* \param ncid the ID of the open file.
* \param formatp a pointer that gets the extended format. Note that
* this is not the same as the format provided by nc_inq_format(). The
* extended foramt indicates the dispatch layer model. Classic, 64-bit
* offset, and CDF5 files all have an extended format of
* ::NC_FORMATX_NC3. Ignored if NULL.
*
* \modep a pointer that gets the open/create mode associated with
* this file. Ignored if NULL.
*
* \returns NC_NOERR No error.
* \returns NC_EBADID Bad ncid.
* \internal
* \author Dennis Heimbigner
*/
int
NC3_inq_format_extended(int ncid, int *formatp, int *modep)
{
int status;
NC *nc;
int status;
NC *nc;
status = NC_check_id(ncid, &nc);
if(status != NC_NOERR)
return status;
if(formatp) *formatp = NC_FORMATX_NC3;
if(modep) *modep = nc->mode;
return NC_NOERR;
status = NC_check_id(ncid, &nc);
if(status != NC_NOERR)
return status;
if(formatp) *formatp = NC_FORMATX_NC3;
if(modep) *modep = nc->mode;
return NC_NOERR;
}
/* The sizes of types may vary from platform to platform, but within
* netCDF files, type sizes are fixed. */
#define NC_BYTE_LEN 1
#define NC_CHAR_LEN 1
#define NC_SHORT_LEN 2
#define NC_INT_LEN 4
#define NC_FLOAT_LEN 4
#define NC_DOUBLE_LEN 8
#define NUM_ATOMIC_TYPES 6
/* This netCDF-4 function proved so popular that a netCDF-classic
* version is provided. You're welcome. */
/**
* Determine name and size of netCDF type. This netCDF-4 function
* proved so popular that a netCDF-classic version is provided. You're
* welcome.
*
* \param ncid The ID of an open file.
* \param typeid The ID of a netCDF type.
* \param name Pointer that will get the name of the type. Maximum
* size will be NC_MAX_NAME. Ignored if NULL.
* \param size Pointer that will get size of type in bytes. Ignored if
* null.
*
* \returns NC_NOERR No error.
* \returns NC_EBADID Bad ncid.
* \returns NC_EBADTYPE Bad typeid.
* \internal
* \author Ed Hartnett
*/
int
NC3_inq_type(int ncid, nc_type typeid, char *name, size_t *size)
{
#if 0
int atomic_size[NUM_ATOMIC_TYPES] = {NC_BYTE_LEN, NC_CHAR_LEN, NC_SHORT_LEN,
NC_INT_LEN, NC_FLOAT_LEN, NC_DOUBLE_LEN};
char atomic_name[NUM_ATOMIC_TYPES][NC_MAX_NAME + 1] = {"byte", "char", "short",
"int", "float", "double"};
#endif
NC *ncp;
int stat = NC_check_id(ncid, &ncp);
if (stat != NC_NOERR)
return stat;
return stat;
/* Only netCDF classic model and CDF-5 need to be handled. */
/* After discussion, this seems like an artificial limitation.
See https://github.com/Unidata/netcdf-c/issues/240 for more
discussion. */
/*
if((ncp->mode & NC_CDF5) != 0) {
if (typeid < NC_BYTE || typeid > NC_STRING)
return NC_EBADTYPE;
} else if (typeid < NC_BYTE || typeid > NC_DOUBLE)
return NC_EBADTYPE;
*/
if(typeid < NC_BYTE || typeid > NC_STRING)
return NC_EBADTYPE;
return NC_EBADTYPE;
/* Give the user the values they want. Subtract one because types
* are numbered starting at 1, not 0. */
/* Give the user the values they want. */
if (name)
strcpy(name, NC_atomictypename(typeid));
if (size)
@ -1666,36 +1689,6 @@ NC3_inq_type(int ncid, nc_type typeid, char *name, size_t *size)
}
/**************************************************/
#if 0
int
NC3_set_content(int ncid, size_t size, void* memory)
{
int status = NC_NOERR;
NC *nc;
NC3_INFO* nc3;
status = NC_check_id(ncid, &nc);
if(status != NC_NOERR)
return status;
nc3 = NC3_DATA(nc);
#ifdef USE_DISKLESS
fClr(nc3->flags, NC_CREAT);
status = memio_set_content(nc3->nciop, size, memory);
if(status != NC_NOERR) goto done;
status = nc_get_NC(nc3);
if(status != NC_NOERR) goto done;
#else
status = NC_EDISKLESS;
#endif
done:
return status;
}
#endif
/**************************************************/
int
nc_delete_mp(const char * path, int basepe)
{

View File

@ -9,23 +9,23 @@ include $(top_srcdir)/lib_flags.am
AM_CPPFLAGS += -I$(top_srcdir)/libsrc
AM_CPPFLAGS += -DTOPSRCDIR=${abs_top_srcdir}
AM_CPPFLAGS += -DTOPBINDIR=${abs_top_bindir}
LDADD = ${top_builddir}/liblib/libnetcdf.la
AM_CPPFLAGS += -I$(top_builddir)/liblib -I$(top_builddir)/include -I$(top_srcdir)/libsrc
# These files are created by the tests.
CLEANFILES = nc_test_classic.nc nc_test_64bit.nc nc_test_netcdf4.nc \
tst_*.nc t_nc.nc large_files.nc quick_large_files.nc \
tst_diskless.nc tst_diskless2.nc \
tst_diskless3.nc tst_diskless3_file.cdl tst_diskless3_memory.cdl \
tst_diskless4.cdl tst_diskless4.nc tst_formatx.nc nc_test_cdf5.nc \
unlim.nc tst_inq_type.nc tst_elatefill.nc tst_global_fillval.nc \
tst_large_cdf5.nc tst_max_var_dims.nc
check_PROGRAMS =
tst_*.nc t_nc.nc large_files.nc quick_large_files.nc tst_diskless.nc \
tst_diskless2.nc tst_diskless3.nc tst_diskless3_file.cdl \
tst_diskless3_memory.cdl tst_diskless4.cdl tst_diskless4.nc \
tst_formatx.nc nc_test_cdf5.nc unlim.nc tst_inq_type.nc \
tst_elatefill.nc tst_global_fillval.nc tst_large_cdf5.nc \
tst_max_var_dims.nc
# These are the tests which are always run.
TESTPROGRAMS = t_nc tst_small nc_test tst_misc tst_norm \
tst_names tst_nofill tst_nofill2 tst_nofill3 tst_atts3 \
tst_meta tst_inq_type tst_utf8_validate tst_utf8_phrases \
tst_global_fillval tst_max_var_dims
TESTPROGRAMS = t_nc tst_small nc_test tst_misc tst_norm tst_names \
tst_nofill tst_nofill2 tst_nofill3 tst_atts3 tst_meta tst_inq_type \
tst_utf8_validate tst_utf8_phrases tst_global_fillval \
tst_max_var_dims tst_formats
if USE_NETCDF4
TESTPROGRAMS += tst_atts tst_put_vars tst_elatefill
@ -45,11 +45,8 @@ endif
# These are the source files for the main workhorse test program,
# nc_test. If you pass nc_test, you are doing well.
nc_test_SOURCES = nc_test.c error.c test_get.c test_put.c \
test_read.c test_write.c util.c error.h tests.h
LDADD = ${top_builddir}/liblib/libnetcdf.la
AM_CPPFLAGS += -I$(top_builddir)/liblib -I$(top_builddir)/include -I$(top_srcdir)/libsrc
nc_test_SOURCES = nc_test.c error.c test_get.c test_put.c test_read.c \
test_write.c util.c error.h tests.h
# If the user asked for large file tests, then add them.
if LARGE_FILE_TESTS
@ -64,7 +61,7 @@ CLEANFILES += benchmark.nc
endif
# Set up the tests.
check_PROGRAMS += $(TESTPROGRAMS)
check_PROGRAMS = $(TESTPROGRAMS)
# Build Diskless test helpers
if BUILD_DISKLESS
@ -105,10 +102,9 @@ endif # USE_VALGRIND_TESTS
# Distribute the .c files so that m4 isn't required on the users
# machine.
EXTRA_DIST = test_get.m4 test_put.m4 run_valgrind_tests.sh \
run_diskless.sh run_diskless2.sh run_diskless5.sh \
run_mmap.sh run_pnetcdf_test.sh \
test_read.m4 test_write.m4
EXTRA_DIST = test_get.m4 test_put.m4 run_valgrind_tests.sh \
run_diskless.sh run_diskless2.sh run_diskless5.sh run_mmap.sh \
run_pnetcdf_test.sh test_read.m4 test_write.m4
# ref_tst_diskless2.cdl is for diff comparison and to produce tst_diskless2.c
EXTRA_DIST += ref_tst_diskless2.cdl tst_diskless5.cdl CMakeLists.txt

131
nc_test/tst_formats.c Normal file
View File

@ -0,0 +1,131 @@
/* This is part of the netCDF package. Copyright 2005-2007 University
Corporation for Atmospheric Research/Unidata. See COPYRIGHT file
for conditions of use.
Test handling of formats.
Ed Hartnett, 11/22/17
*/
#include "config.h"
#include <nc_tests.h>
#include "err_macros.h"
#define FILE_NAME_BASE "tst_formats"
/* Determine how many formats are available, and what they are. */
void
determine_test_formats(int *num_formats, int *format)
{
int ind = 0;
int num;
/* Check inputs. */
assert(num_formats && format);
/* We always have classic and 64-bit offset */
num = 2;
format[ind++] = NC_FORMAT_CLASSIC;
format[ind++] = NC_FORMAT_64BIT_OFFSET;
/* Do we have netCDF-4 and netCDF-4 classic? */
#ifdef USE_NETCDF4
num += 2;
format[ind++] = NC_FORMAT_NETCDF4;
format[ind++] = NC_FORMAT_NETCDF4_CLASSIC;
#endif /* USE_NETCDF4 */
/* Do we have CDF5? */
#ifdef ENABLE_CDF5
num++;
format[ind++] = NC_FORMAT_CDF5;
#endif /* ENABLE_CDF5 */
*num_formats = num;
}
/* Function to test nc_inq_format(). */
int
check_inq_format(int ncid, int expected_format, int expected_extended_format, int expected_mode)
{
int format;
int extended_format;
int mode;
if (nc_inq_format(ncid + 66000, NULL) != NC_EBADID) ERR;
if (nc_inq_format(ncid, NULL)) ERR;
if (nc_inq_format(ncid, &format)) ERR;
if (format != expected_format) ERR;
if (nc_inq_format_extended(ncid + 66000, &extended_format, &mode) != NC_EBADID) ERR;
{
int mode;
if (nc_inq_format_extended(ncid, NULL, &mode)) ERR;
if (mode != expected_mode) ERR;
}
{
int extended_format;
if (nc_inq_format_extended(ncid, &extended_format, NULL)) ERR;
if (extended_format != expected_extended_format) ERR;
}
if (nc_inq_format_extended(ncid, &extended_format, &mode)) ERR;
if (mode != expected_mode) ERR;
if (extended_format != expected_extended_format) ERR;
return 0;
}
int
main(int argc, char **argv)
{
int format[MAX_NUM_FORMATS];
int num_formats;
char file_name[NC_MAX_NAME + 1];
int f;
/* How many formats to be tested? */
determine_test_formats(&num_formats, format);
printf("\n*** Testing netcdf format functions.\n");
{
int ncid;
int expected_mode;
int expected_extended_format;
for (f = 0; f < num_formats; f++)
{
printf("*** testing nc_inq_format() and nc_inq_format_extended() with format %d...", format[f]);
sprintf(file_name, "%s_%d.nc", FILE_NAME_BASE, format[f]);
/* Create a file with some global atts. */
if (nc_set_default_format(format[f], NULL)) ERR;
if (nc_create(file_name, 0, &ncid)) ERR;
switch (format[f]) {
case NC_FORMAT_CLASSIC:
expected_extended_format = NC_FORMATX_NC3;
expected_mode = 0;
break;
case NC_FORMAT_64BIT_OFFSET:
expected_extended_format = NC_FORMATX_NC3;
expected_mode = NC_64BIT_OFFSET;
break;
case NC_FORMAT_CDF5:
expected_extended_format = NC_FORMATX_NC3;
expected_mode = NC_CDF5;
break;
case NC_FORMAT_NETCDF4:
expected_extended_format = NC_FORMATX_NC4;
expected_mode = NC_NETCDF4;
break;
case NC_FORMAT_NETCDF4_CLASSIC:
expected_extended_format = NC_FORMATX_NC4;
expected_mode = NC_NETCDF4|NC_CLASSIC_MODEL;
break;
}
if (check_inq_format(ncid, format[f], expected_extended_format, expected_mode)) ERR;
if (nc_close(ncid)) ERR;
SUMMARIZE_ERR;
} /* next format */
}
FINAL_RESULTS;
}