mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-11-27 07:30:33 +08:00
fixed SEGFAULT for NULL parameter for nc_inq_format(), added testing, improved documentation
This commit is contained in:
parent
64b500cf24
commit
70c739858b
@ -1575,6 +1575,18 @@ 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)
|
||||
{
|
||||
@ -1587,6 +1599,10 @@ NC3_inq_format(int ncid, int *formatp)
|
||||
return status;
|
||||
nc3 = NC3_DATA(nc);
|
||||
|
||||
/* 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))
|
||||
@ -1600,6 +1616,26 @@ NC3_inq_format(int ncid, int *formatp)
|
||||
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)
|
||||
{
|
||||
@ -1614,49 +1650,36 @@ NC3_inq_format_extended(int ncid, int *formatp, int *modep)
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
|
@ -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
|
||||
@ -106,9 +103,8 @@ 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
|
||||
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
131
nc_test/tst_formats.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user