2
0
mirror of https://github.com/Unidata/netcdf-c.git synced 2025-03-07 17:08:02 +08:00

Add provenance info for netcdf-4 files.

This consists of a persistent attribute named
_NCProperties plus two computed attributes
_IsNetcdf4 and _SuperblockVersion.
See the 'Provenance Attributes' section
of docs/attribute_conventions.md for details.
This commit is contained in:
Dennis Heimbigner 2016-05-03 21:17:06 -06:00
parent e1a75d5257
commit 2e55a233eb
55 changed files with 3646 additions and 2498 deletions

View File

@ -191,7 +191,6 @@ OPTION(NC_FIND_SHARED_LIBS "Find dynamically-built versions of dependent librari
##
OPTION(ENABLE_SHARED_LIBRARY_VERSION "Encode the library SO version in the file name of the generated library file." ON)
# Set some default linux gcc & apple compiler options for
# debug builds.
IF(CMAKE_COMPILER_IS_GNUCC OR APPLE)
@ -752,6 +751,12 @@ IF(NOT WIN32)
ENDIF()
ENDIF()
OPTION(ENABLE_PROPERTIES_ATTRIBUTE "Enable properties attribute." ON)
IF(ENABLE_PROPERTIES_ATTRIBUTE)
SET(ENABLE_PROPATTR ON CACHE BOOL "")
ENDIF()
# Option to Enable DAP long tests, remote tests.
OPTION(ENABLE_DAP_LONG_TESTS "Enable DAP long tests." OFF)
OPTION(ENABLE_DAP_REMOTE_TESTS "Enable DAP remote tests." ON)
@ -1064,6 +1069,11 @@ MARK_AS_ADVANCED(ENABLE_INTERNAL_DOCS VALGRIND_TESTS ENABLE_COVERAGE_TESTS )
MARK_AS_ADVANCED(ENABLE_DAP_REMOTE_TESTS ENABLE_DAP_LONG_TESTS USE_REMOTE_CDASH)
MARK_AS_ADVANCED(ENABLE_DOXYGEN_BUILD_RELEASE_DOCS DOXYGEN_ENABLE_TASKS ENABLE_DOXYGEN_SERVER_SIDE_SEARCH)
MARK_AS_ADVANCED(ENABLE_SHARED_LIBRARY_VERSION)
# This option is temporary and should always be on
OPTION(ENABLE_FILEINFO "Enable FILEINFO." ON)
MARK_AS_ADVANCED(ENABLE_FILEINFO)
################################
# Option checks
################################

10
cf
View File

@ -24,7 +24,7 @@ fi
CFLAGS=""
#CFLAGS="-Wall -Wno-unused-but-set-variable -Wno-unused-variable -Wno-unused-parameter -Wconversion ${CFLAGS}"
CFLAGS="-Wall -Wno-unused-but-set-variable -Wno-unused-variable -Wno-unused-parameter ${CFLAGS}"
CFLAGS="-Wall -Wno-unused-but-set-variable -Wno-unused-variable -Wno-unused-parameter -Wno-char-subscripts -Wno-pointer-sign -Wno-format ${CFLAGS}"
#CFLAGS="-Wall ${CFLAGS}"
#CFLAGS="-Wconversion"
@ -116,21 +116,23 @@ FLAGS="$FLAGS --disable-examples"
#FLAGS="$FLAGS --disable-dap-remote-tests"
FLAGS="$FLAGS --enable-dap-auth-tests"
#FLAGS="$FLAGS --enable-doxygen"
FLAGS="$FLAGS --enable-logging"
#FLAGS="$FLAGS --enable-logging"
#FLAGS="$FLAGS --disable-diskless"
#FLAGS="$FLAGS --enable-mmap"
#FLAGS="$FLAGS --with-udunits"
#FLAGS="$FLAGS --with-libcf"
#valgrind => not shared
#FLAGS="$FLAGS --enable-valgrind-tests"
FLAGS="$FLAGS --enable-jna"
#FLAGS="$FLAGS --enable-jna"
#FLAGS="$FLAGS --disable-properties-attribute"
#FLAGS="$FLAGS --disable-silent-rules"
if test "x$PAR4" != x1 ; then
FLAGS="$FLAGS --disable-parallel4"
fi
if test "x${DB}" = x1 ; then
FLAGS="$FLAGS --disable-shared"
FLAGS="$FLAGS --disable-shared --enable-static"
else
FLAGS="$FLAGS --enable-shared"
fi

View File

@ -42,7 +42,7 @@ ZLIB="-DZLIB_LIBRARY=${ZP}/$ZLIB -DZLIB_INCLUDE_DIR=${ZP}/include -DZLIB_INCLUDE
HDF5="-DHDF5_LIB=${HP}/$H5LIB -DHDF5_HL_LIB=${HP}/$H5LIB_HL -DHDF5_INCLUDE_DIR=${HP}/include"
CURL="-DCURL_LIBRARY=${CP}/$CURLLIB -DCURL_INCLUDE_DIR=${CP}/include -DCURL_INCLUDE_DIRS=${CP}/include"
FLAGS="$FLAGS -DCMAKE_C_FLAGS='-Wall -Wno-unused-but-set-variable -Wno-unused-variable -Wno-unused-parameter'"x2
#FLAGS="$FLAGS -DCMAKE_C_FLAGS='-Wall -Wno-unused-but-set-variable -Wno-unused-variable -Wno-unused-parameter'"x2
#FLAGS="$FLAGS -DENABLE_DAP=false"
#FLAGS="$FLAGS -DENABLE_NETCDF_4=false"

View File

@ -87,6 +87,7 @@ are set when opening a binary file on Windows. */
#cmakedefine ENABLE_DAP 1
#cmakedefine ENABLE_DAP_GROUPS 1
#cmakedefine ENABLE_DAP_REMOTE_TESTS 1
#cmakedefine ENABLE_FILEINFO 1
#cmakedefine EXTRA_TESTS
#cmakedefine USE_NETCDF4 1
#cmakedefine USE_LIBDL 1
@ -102,6 +103,7 @@ are set when opening a binary file on Windows. */
#cmakedefine USE_PARALLEL4 1
#cmakedefine USE_PNETCDF 1
#cmakedefine USE_MMAP 1
#cmakedefine ENABLE_FILEINFO 1
#cmakedefine TEST_PARALLEL ${TEST_PARALLEL}
#cmakedefine BUILD_RPC 1
#cmakedefine USE_DISKLESS 1

View File

@ -68,7 +68,7 @@ AC_CONFIG_LINKS([nc_test4/ref_hdf5_compat2.nc:nc_test4/ref_hdf5_compat2.nc])
AC_CONFIG_LINKS([nc_test4/ref_hdf5_compat3.nc:nc_test4/ref_hdf5_compat3.nc])
# This call is required by automake.
AM_INIT_AUTOMAKE([foreign dist-zip subdir-objects])
AM_INIT_AUTOMAKE([foreign dist-zip subdir-objects serial-tests])
# Check for the existence of this file before proceeding.
AC_CONFIG_SRCDIR([include/netcdf.h])
@ -200,6 +200,21 @@ enable_netcdf_4=no
fi
AC_MSG_RESULT([$enable_netcdf_4])
####
# Is Netcdf4 file info capture enabled; includes properties attribute
# We do not actually provide a direct flag for disabling this
if test "x$enable_netcdf_4" = xyes ; then
enable_fileinfo=yes
else
enable_fileinfo=no
fi
AC_MSG_CHECKING([If file info capture is enabled])
AC_MSG_RESULT([$enable_fileinfo])
if test "x$enable_fileinfo" = xyes ; then
AC_DEFINE([ENABLE_FILEINFO], [1], [file info])
fi
AM_CONDITIONAL(ENABLE_FILEINFO, [test x$enable_fileinfo = xyes])
# Does the user require dynamic loading?
# This is only for those hdf5 installs that support it.
AC_MSG_CHECKING([do we require hdf5 dynamic-loading support])

View File

@ -126,3 +126,42 @@ It is strongly recommended that applicable conventions be followed unless there
<p>
> Typical conventions web sites will include references to documents in some form agreed upon by the community that supports the conventions and examples of netCDF file structures that follow the conventions.
# Provenance Attributes
These attributes can occur in netCDF enhanced (netcdf-4) files beginning
with version 4.4.1. They all are associated with the root group as
global attributes. They are hidden in the sense that they can only be
accessed thru the netcdf-C api calls via the name. They have no
attribute number and will not be counted in the number of global
attributes in the root group. The simplest way to view these attributes
is to use the -s flag to the ncdump command.
`_NCProperties`
> This attribute is persistent in the file, but hidden. It is inserted in the file at creation time and is never modified after that point. It specifies the following.
> - The version for the netcdf library used at creation time.
> - The version for the HDF5 library used at creation time.
> Its format is: `name=value|name=value ...`<br>
> Occurrences of '|' in the name or value are disallowed.
> The current set of known names is as follows.
> - version=... The current format version for the _NCProperties file, currently 1.
> - netcdflibversion=... The version of the netcdf library used to create the file. The value is, for example, 4.4.1-rc1-development or 4.4.1.
> - hdf5libversion=... The version of the HDF5 library used to create the file. The value is, for example, 1.8.16 or 1.10.0.
`_SuperblockVersion`
> This attribute is ephemeral in that it is computed by looking at the file's HDF5 superblock.
> It has this form: `_SuperBlockVersion = 0|1|2|3|...`
`_IsNetcdf4`
> This attribute is ephemeral in that it is computed by walking the metadata of the file looking for attributes specific to netCDF-4 files.
> The _IsNetcdf4 attribute has the form: `_IsNetcdf4 = 0|1`
> where 1 means the file has various tags indicating it was produced thru the netcdf-4 API.
> This attribute is computed by using the HDF5 API to walk the file to look for attributes specific to netcdf-4. False negatives are possible for a small subset of netcdf-4 files, especially those not containing dimensions. False positives are only possible by deliberate modifications to an existing HDF5 file thru the HDF5 API. For files with the _NCProperties attribute, this attribute is redundant. For files created prior to the introduction of the _NCProperties attribute, this may be a useful indicator of the provenance of the file.

View File

@ -653,7 +653,7 @@ stripped from the name for the netCDF API.
Attributes in HDF5 and netCDF-4 correspond very closely. Each
attribute in an HDF5 file is represented as an attribute in the
netCDF-4 file, with the exception of the attributes below, which are
ignored by the netCDF-4 API.
hidden by the netCDF-4 API.
- _Netcdf4Coordinates An integer array containing the dimension IDs of
a variable which is a multi-dimensional coordinate variable.
- _nc3_strict When this (scalar, H5T_NATIVE_INT) attribute exists in
@ -670,6 +670,9 @@ ignored by the netCDF-4 API.
- _Netcdf4Dimid Holds a scalar H5T_NATIVE_INT that is the (zero-based)
dimension ID for this dimension, needed when dimensions and
coordinate variables are defined in different orders.
- _NCProperties Holds provenance information about a file at the time
it was created. It specifies the versions of the netCDF and HDF5
libraries used to create the file.
\subsection user_defined_spec User-Defined Data Types

View File

@ -2233,17 +2233,20 @@ one of 'classic'. '64-bit offset', 'netCDF-4', or 'netCDF-4 classic
model'.
@par -s
Specifies that \e special virtual attributes should be output for the
file format variant and for variable properties such as
Specifies that \e special virtual and hidden attributes should be output
for the file format variant and for variable properties such as
compression, chunking, and other properties specific to the format
implementation that are primarily related to performance rather
than the logical schema of the data. All the special virtual
attributes begin with '_' followed by an upper-case
letter. Currently they include the global attribute '_Format' and
letter. Currently they include the global attributes '_Format',
'_NCProperties', '_IsNetcdf4', '_SuperblockVersion' and
the variable attributes '_ChunkSizes', '_DeflateLevel',
'_Endianness', '_Fletcher32', '_NoFill', '_Shuffle', and '_Storage'.
The \b ncgen utility recognizes these attributes and
supports them appropriately.
supports them appropriately. For '_NCProperties',
'_IsNetcdf4', and '_SuperblockVersion', the term 'appropriately'
means that they are ignored.
@par -t
Controls display of time data, if stored in a variable that uses a

View File

@ -87,12 +87,14 @@ extern int nc_set_default_format(int format, int *old_formatp);
/* This function gets a current default create flag */
extern int nc_get_default_format(void);
extern int add_to_NCList(NC*);
extern void del_from_NCList(NC*);/* does not free object */
extern NC* find_in_NCList(int ext_ncid);
extern NC* find_in_NCList_by_name(const char*);
extern void free_NCList(void);/* reclaim whole list */
extern int count_NCList(void); /* return # of entries in NClist */
extern int iterate_NCList(int i,NC**); /* Walk from 0 ...; ERANGE return => stop */
/* Defined in nc.c */
extern void free_NC(NC*);

View File

@ -9,21 +9,21 @@
#ifndef _NC4INTERNAL_
#define _NC4INTERNAL_
#include <config.h>
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdarg.h>
#include <string.h>
#include <hdf5.h>
#include <ncdimscale.h>
#include <nc_logging.h>
#include "ncdimscale.h"
#include "nc_logging.h"
#ifdef USE_PARALLEL
#include <netcdf_par.h>
#include "netcdf_par.h"
#endif /* USE_PARALLEL */
#include <netcdf.h>
#include <netcdf_f.h>
#include "netcdf.h"
#include "netcdf_f.h"
/* Always needed */
#include "nc.h"
@ -100,6 +100,11 @@ typedef enum {VAR, DIM, ATT} NC_OBJ_T;
/* Boolean type, to make the code easier to read */
typedef enum {NC_FALSE = 0, NC_TRUE = 1} nc_bool_t;
#ifdef ENABLE_FILEINFO
/*Forward*/
struct NCFILEINFO;
#endif
/* Generic doubly-linked list node */
typedef struct NC_LIST_NODE
{
@ -286,6 +291,7 @@ typedef struct NC_GRP_INFO
#define NC_NDIRTY 0x40 /* numrecs has changed */
#define NC_HDIRTY 0x80 /* header info has changed */
/* This is the metadata we need to keep track of for each
netcdf-4/HDF5 file. */
typedef struct NC_HDF5_FILE_INFO
@ -314,6 +320,9 @@ typedef struct NC_HDF5_FILE_INFO
nc_bool_t hdf4; /* True for HDF4 file */
int sdid;
#endif /* USE_HDF4 */
#ifdef ENABLE_FILEINFO
struct NCFILEINFO* fileinfo;
#endif
} NC_HDF5_FILE_INFO_T;
@ -407,8 +416,8 @@ int nc4_normalize_name(const char *name, char *norm_name);
int nc4_check_dup_name(NC_GRP_INFO_T *grp, char *norm_name);
/* HDF5 initialization */
static int nc4_hdf5_initialized;
void nc4_hdf5_initialize(void);
extern int nc4_hdf5_initialized;
extern void nc4_hdf5_initialize(void);
/* This is only included if --enable-logging is used for configure; it
prints info about the metadata to stderr. */
@ -420,4 +429,64 @@ int log_metadata_nc(NC *nc);
#define NC4_DATA(nc) ((NC_HDF5_FILE_INFO_T*)(nc)->dispatchdata)
#define NC4_DATA_SET(nc,data) ((nc)->dispatchdata = (void*)(data))
/* Reserved Attributes */
extern const char* NC_RESERVED_VARATT_LIST[];
extern const char* NC_RESERVED_ATT_LIST[];
extern const char* NC_RESERVED_SPECIAL_LIST[];
#define NC_ATT_REFERENCE_LIST "REFERENCE_LIST"
#define NC_ATT_CLASS "CLASS"
#define NC_ATT_DIMENSION_LIST "DIMENSION_LIST"
#define NC_ATT_NAME "NAME"
#define NC_ATT_COORDINATES COORDINATES /*defined above*/
#define NC_ATT_FORMAT "_Format"
/**************************************************/
/**
For netcdf4 files, capture state information about the following:
1. Global: netcdf library version
2. Global: hdf5 library version
3. Per file: superblock version
4. Per File: was it created by netcdf-4?
5. Per file: _NCProperties attribute
*/
#ifdef ENABLE_FILEINFO
#define NCPROPS "_NCProperties"
#define NCPROPS_VERSION (1)
#define NCPROPSSEP '|'
#define NCPROPS_LENGTH (8192)
/* Currently used properties */
#define NCPVERSION "version" /* Of the properties format */
#define NCPHDF5LIBVERSION "hdf5libversion"
#define NCPNCLIBVERSION "netcdflibversion"
/* Other hidden attributes */
#define ISNETCDF4ATT "_IsNetcdf4"
#define SUPERBLOCKATT "_SuperblockVersion"
struct NCFILEINFO {
int superblockversion;
/* Following is filled from NCPROPS attribute or from global version */
struct NCPROPINFO {
int version; /* 0 => not defined */
char hdf5ver[NC_MAX_NAME+1];
char netcdfver[NC_MAX_NAME+1];
char text[NCPROPS_LENGTH+1]; /* Value of the NCPROPS attribute */
} propattr;
};
extern struct NCPROPINFO globalpropinfo;
extern int NC4_fileinfo_init(void); /*libsrc4/ncinfo.c*/
extern int NC4_get_fileinfo(struct NC_HDF5_FILE_INFO* info, struct NCPROPINFO*); /*libsrc4/ncinfo.c*/
extern int NC4_put_propattr(struct NC_HDF5_FILE_INFO* info); /*libsrc4/ncinfo.c*/
/* ENABLE_FILEINFO => ENABLE_NETCDF4 */
extern int NC4_hdf5get_libversion(unsigned*,unsigned*,unsigned*);/*libsrc4/nc4hdf.c*/
extern int NC4_hdf5get_superblock(struct NC_HDF5_FILE_INFO*, int*);/*libsrc4/nc4hdf.c*/
extern int NC4_isnetcdf4(struct NC_HDF5_FILE_INFO*); /*libsrc4/nc4hdf.c*/
#endif /*ENABLE_FILEINFO*/
#endif /* _NETCDF4_ */

View File

@ -161,7 +161,8 @@ nc_del_att(int ncid, int varid, const char *name)
int stat = NC_check_id(ncid, &ncp);
if(stat != NC_NOERR) return stat;
TRACE(nc_del_att);
return ncp->dispatch->del_att(ncid, varid, name);
stat = ncp->dispatch->del_att(ncid, varid, name);
return stat;
}
/*! \} */ /* End of named group ...*/

View File

@ -11,6 +11,7 @@
#define ID_SHIFT (16)
#define NCFILELISTLENGTH 0x10000
/* Version one just allocates the max space (sizeof(NC*)*2^16)*/
static NC** nc_filelist = NULL;
@ -111,4 +112,13 @@ find_in_NCList_by_name(const char* path)
return f;
}
int
iterate_NCList(int index, NC** ncp)
{
/* Walk from 0 ...; 0 return => stop */
if(index < 0 || index >= NCFILELISTLENGTH)
return NC_ERANGE;
if(ncp) *ncp = nc_filelist[index];
return NC_NOERR;
}

View File

@ -10,6 +10,7 @@
#endif
#include "ncdispatch.h"
#include "nc4internal.h"
extern int NC3_initialize(void);
extern int NC3_finalize(void);
@ -54,25 +55,26 @@ nc_initialize()
NC_finalized = 0;
/* Do general initialization */
if((stat = NCDISPATCH_initialize())) return stat;
if((stat = NCDISPATCH_initialize())) goto done;
/* Initialize each active protocol */
if((stat = NC3_initialize())) return stat;
if((stat = NC3_initialize())) goto done;
#ifdef USE_DAP
if((stat = NCD2_initialize())) return stat;
if((stat = NCD2_initialize())) goto done;
#endif
#ifdef USE_PNETCDF
if((stat = NCP_initialize())) return stat;
if((stat = NCP_initialize())) goto done;
#endif
#ifdef USE_NETCDF4
if((stat = NC4_initialize())) return stat;
if((stat = NC4_initialize())) goto done;
#endif /* USE_NETCDF4 */
return NC_NOERR;
#ifdef ENABLE_FILEINFO
stat = NC4_fileinfo_init();
#endif
done:
return stat;
}
/**
@ -114,5 +116,3 @@ nc_finalize(void)
return NC_NOERR;
}

View File

@ -1,6 +1,6 @@
# Process these files with m4.
SET(libsrc4_SOURCES nc4dispatch.c nc4attr.c nc4dim.c nc4file.c nc4grp.c nc4type.c nc4var.c ncfunc.c nc4internal.c nc4hdf.c)
SET(libsrc4_SOURCES nc4dispatch.c nc4attr.c nc4dim.c nc4file.c nc4grp.c nc4type.c nc4var.c ncfunc.c nc4internal.c nc4hdf.c nc4info.c)
IF(LOGGING)
SET(libsrc4_SOURCES ${libsrc4_SOURCES} error4.c)

View File

@ -16,6 +16,9 @@ endif
noinst_LTLIBRARIES = libnetcdf4.la
libnetcdf4_la_SOURCES = nc4dispatch.c nc4dispatch.h nc4attr.c nc4dim.c \
nc4file.c nc4grp.c nc4hdf.c nc4internal.c nc4type.c nc4var.c ncfunc.c error4.c
if ENABLE_FILEINFO
libnetcdf4_la_SOURCES += nc4info.c
endif
EXTRA_DIST=CMakeLists.txt

View File

@ -21,6 +21,10 @@ conditions.
#include <pnetcdf.h>
#endif
#ifdef ENABLE_FILEINFO
static int nc4_get_att_special(NC_HDF5_FILE_INFO_T*, const char*, nc_type, int, void*, size_t*, int*);
#endif
int nc4typelen(nc_type type);
/* Get or put attribute metadata from our linked list of file
@ -43,10 +47,11 @@ nc4_get_att(int ncid, NC *nc, int varid, const char *name,
char norm_name[NC_MAX_NAME + 1];
int i;
int retval = NC_NOERR;
const char** sp;
if (attnum)
if (attnum) {
my_attnum = *attnum;
assert(nc && NC4_DATA(nc));
}
LOG((3, "%s: ncid 0x%x varid %d name %s attnum %d mem_type %d",
__func__, ncid, varid, name, my_attnum, mem_type));
@ -60,6 +65,17 @@ nc4_get_att(int ncid, NC *nc, int varid, const char *name,
if ((retval = nc4_normalize_name(name, norm_name)))
BAIL(retval);
#ifdef ENABLE_FILEINFO
if(nc->ext_ncid == ncid && varid == NC_GLOBAL) {
const char** sp;
for(sp = NC_RESERVED_SPECIAL_LIST;*sp;sp++) {
if(strcmp(name,*sp)==0) {
return nc4_get_att_special(h5, norm_name, mem_type, is_long, data, lenp, attnum);
}
}
}
#endif
/* Find the attribute, if it exists. If we don't find it, we are
major failures. */
if ((retval = nc4_find_grp_att(grp, varid, norm_name, my_attnum, &att)))
@ -84,8 +100,9 @@ nc4_get_att(int ncid, NC *nc, int varid, const char *name,
*lenp = att->len;
if (xtype)
*xtype = att->nc_typeid;
if (attnum)
if (attnum) {
*attnum = att->attnum;
}
/* Zero len attributes are easy to read! */
if (!att->len)
@ -232,6 +249,17 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
if ((retval = nc4_check_name(name, norm_name)))
return retval;
#ifdef ENABLE_FILEINFO
if(nc->ext_ncid == ncid && varid == NC_GLOBAL) {
const char** sp;
for(sp = NC_RESERVED_SPECIAL_LIST;*sp;sp++) {
if(strcmp(name,*sp)==0) {
return NC_ENOTATT; /* Not settable */
}
}
}
#endif
/* Find att, if it exists. */
if (varid == NC_GLOBAL)
attlist = &grp->att;
@ -246,6 +274,7 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
if (!var)
return NC_ENOTVAR;
}
for (att = *attlist; att; att = att->l.next)
if (!strcmp(att->name, norm_name))
break;
@ -860,6 +889,22 @@ nc4_put_att_tc(int ncid, int varid, const char *name, nc_type file_type,
h5 = NC4_DATA(nc);
assert(h5);
if(nc->ext_ncid == ncid && varid == NC_GLOBAL) {
const char** reserved = NC_RESERVED_ATT_LIST;
for(;*reserved;reserved++) {
if(strcmp(name,*reserved)==0)
return NC_ENAMEINUSE;
}
}
if(varid != NC_GLOBAL) {
const char** reserved = NC_RESERVED_VARATT_LIST;
for(;*reserved;reserved++) {
if(strcmp(name,*reserved)==0)
return NC_ENAMEINUSE;
}
}
#if 0 /*def USE_PNETCDF*/
/* Take care of files created/opened with parallel-netcdf library. */
if (h5->pnetcdf_file)
@ -903,6 +948,44 @@ nc4_put_att_tc(int ncid, int varid, const char *name, nc_type file_type,
mem_type_is_long, op);
}
#ifdef ENABLE_FILEINFO
static int
nc4_get_att_special(NC_HDF5_FILE_INFO_T *h5, const char* name, nc_type mem_type, int islong, void* data, size_t* lenp, int* idp)
{
/* Always make the attr id be -1 */
if(idp) *idp = -1;
if(strcmp(name,NCPROPS)==0) {
if(h5->fileinfo->propattr.version == 0)
return NC_ENOTATT;
if(lenp) *lenp = strlen(h5->fileinfo->propattr.text);
if(data) strcpy((char*)data,h5->fileinfo->propattr.text);
} else if(strcmp(name,ISNETCDF4ATT)==0
|| strcmp(name,SUPERBLOCKATT)==0) {
unsigned long long iv = 0;
if(strcmp(name,SUPERBLOCKATT)==0)
iv = (unsigned long long)h5->fileinfo->superblockversion;
else /* strcmp(name,ISNETCDF4ATT)==0 */
iv = NC4_isnetcdf4(h5);
if(lenp) *lenp = 1;
if(data)
switch (mem_type) {
case NC_BYTE: *((char*)data) = (char)iv; break;
case NC_SHORT: *((short*)data) = (short)iv; break;
case NC_INT: *((int*)data) = (int)iv; break;
case NC_UBYTE: *((unsigned char*)data) = (unsigned char)iv; break;
case NC_USHORT: *((unsigned short*)data) = (unsigned short)iv; break;
case NC_UINT: *((unsigned int*)data) = (unsigned int)iv; break;
case NC_INT64: *((long long*)data) = (long long)iv; break;
case NC_UINT64: *((unsigned long long*)data) = (unsigned long long)iv; break;
default:
return NC_ERANGE;
}
}
return NC_NOERR;
}
#endif
/* Read an attribute of any type, with type conversion. This may be
* called by any of the nc_get_att_* functions. */
int
@ -953,8 +1036,7 @@ nc4_get_att_tc(int ncid, int varid, const char *name, nc_type mem_type,
}
}
#endif /* USE_PNETCDF */
return nc4_get_att(ncid, nc, varid, name, NULL, mem_type,
return nc4_get_att(ncid, nc, varid, name, NULL, mem_type,
NULL, NULL, mem_type_is_long, ip);
}

View File

@ -12,7 +12,6 @@ COPYRIGHT file for copying and redistribution conditions.
#include "config.h"
#include <errno.h> /* netcdf functions sometimes return system errors */
#include "nc.h"
#include "nc4internal.h"
#include "nc4dispatch.h"
@ -28,6 +27,11 @@ COPYRIGHT file for copying and redistribution conditions.
#include <hdf5_hl.h>
#endif
/* When we have open objects at file close, should
we log them or print to stdout. Default is to log
*/
#define LOGOPEN 1
/* This is to track opened HDF5 objects to make sure they are
* closed. */
#ifdef EXTRA_TESTS
@ -38,18 +42,13 @@ extern int num_spaces;
#define MIN_DEFLATE_LEVEL 0
#define MAX_DEFLATE_LEVEL 9
/* These are the special attributes added by the HDF5 dimension scale
* API. They will be ignored by netCDF-4. */
#define REFERENCE_LIST "REFERENCE_LIST"
#define CLASS "CLASS"
#define DIMENSION_LIST "DIMENSION_LIST"
#define NAME "NAME"
/* Define the illegal mode flags */
static const int ILLEGAL_OPEN_FLAGS = (NC_MMAP|NC_64BIT_OFFSET);
static const int ILLEGAL_CREATE_FLAGS = (NC_NOWRITE|NC_MMAP|NC_INMEMORY|NC_64BIT_OFFSET|NC_CDF5);
extern void reportopenobjects(int log, hid_t);
/*! Struct to track information about objects in a group, for nc4_rec_read_metadata()
\internal
@ -80,6 +79,46 @@ static int NC4_enddef(int ncid);
static int nc4_rec_read_metadata(NC_GRP_INFO_T *grp);
static int close_netcdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort);
/* Define the names of attributes to ignore
* added by the HDF5 dimension scale; these
* attached to variables.
* They cannot be modified thru the netcdf-4 API.
*/
const char* NC_RESERVED_VARATT_LIST[] = {
NC_ATT_REFERENCE_LIST,
NC_ATT_CLASS,
NC_ATT_DIMENSION_LIST,
NC_ATT_NAME,
NC_ATT_COORDINATES,
NC_DIMID_ATT_NAME,
NULL
};
/* Define the names of attributes to ignore
* because they are "hidden" global attributes.
* They can be read, but not modified thru the netcdf-4 API.
*/
const char* NC_RESERVED_ATT_LIST[] = {
NC_ATT_FORMAT,
NC3_STRICT_ATT_NAME,
#ifdef ENABLE_FILEINFO
NCPROPS,
ISNETCDF4ATT,
SUPERBLOCKATT,
#endif
NULL
};
#ifdef ENABLE_FILEINFO
/* Define the subset of the reserved list that is readable by name only */
const char* NC_RESERVED_SPECIAL_LIST[] = {
ISNETCDF4ATT,
SUPERBLOCKATT,
NCPROPS,
NULL
};
#endif
/* These are the default chunk cache sizes for HDF5 files created or
* opened with netCDF-4. */
size_t nc4_chunk_cache_size = CHUNK_CACHE_SIZE;
@ -314,7 +353,7 @@ nc4_create_file(const char *path, int cmode, MPI_Comm comm, MPI_Info info,
return NC_NOERR;
#endif
/* Need this access plist to control how HDF5 handles open onjects
/* Need this access plist to control how HDF5 handles open objects
* on file close. (Setting H5F_CLOSE_SEMI will cause H5Fclose to
* fail if there are any open objects in the file. */
if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0)
@ -424,8 +463,7 @@ nc4_create_file(const char *path, int cmode, MPI_Comm comm, MPI_Info info,
BAIL(NC_EFILEMETA);
/* Release the property lists. */
if (H5Pclose(fapl_id) < 0 ||
H5Pclose(fcpl_id) < 0)
if (H5Pclose(fapl_id) < 0 || H5Pclose(fcpl_id) < 0)
BAIL(NC_EHDFERR);
#ifdef EXTRA_TESTS
num_plists--;
@ -435,6 +473,11 @@ nc4_create_file(const char *path, int cmode, MPI_Comm comm, MPI_Info info,
/* Define mode gets turned on automatically on create. */
nc4_info->flags |= NC_INDEF;
#ifdef ENABLE_FILEINFO
NC4_get_fileinfo(nc4_info,&globalpropinfo);
NC4_put_propattr(nc4_info);
#endif
return NC_NOERR;
exit: /*failure exit*/
@ -474,6 +517,7 @@ NC4_create(const char* path, int cmode, size_t initialsz, int basepe,
MPI_Comm comm = MPI_COMM_WORLD;
MPI_Info info = MPI_INFO_NULL;
int res;
NC* nc;
assert(nc_file && path);
@ -1490,6 +1534,7 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
hid_t access_pid = 0;
int incr_id_rc = 0; /* Whether the dataset ID's ref count has been incremented */
int natts, a, d;
const char** reserved;
NC_ATT_INFO_T *att;
hid_t attid = 0;
@ -1758,13 +1803,10 @@ read_var(NC_GRP_INFO_T *grp, hid_t datasetid, const char *obj_name,
LOG((4, "%s:: a %d att_name %s", __func__, a, att_name));
/* Should we ignore this attribute? */
if (strcmp(att_name, REFERENCE_LIST) &&
strcmp(att_name, CLASS) &&
strcmp(att_name, DIMENSION_LIST) &&
strcmp(att_name, NAME) &&
strcmp(att_name, COORDINATES) &&
strcmp(att_name, NC_DIMID_ATT_NAME))
{
for(reserved=NC_RESERVED_VARATT_LIST;*reserved;reserved++) {
if (strcmp(att_name, *reserved)==0) break;
}
if(*reserved == NULL) {
/* Add to the end of the list of atts for this var. */
if ((retval = nc4_att_list_add(&var->att, &att)))
BAIL(retval);
@ -1825,36 +1867,43 @@ exit:
static int
read_grp_atts(NC_GRP_INFO_T *grp)
{
hid_t attid = 0;
hid_t attid = -1;
hsize_t num_obj, i;
NC_ATT_INFO_T *att;
NC_TYPE_INFO_T *type;
char obj_name[NC_MAX_HDF5_NAME + 1];
int max_len;
int retval = NC_NOERR;
int hidden = 0;
num_obj = H5Aget_num_attrs(grp->hdf_grpid);
for (i = 0; i < num_obj; i++)
{
/* Close an attribute from previous loop iteration */
/* (Should be from 'continue' statement, below) */
if (attid && H5Aclose(attid) < 0)
BAIL(NC_EHDFERR);
if ((attid = H5Aopen_idx(grp->hdf_grpid, (unsigned int)i)) < 0)
BAIL(NC_EATTMETA);
if (H5Aget_name(attid, NC_MAX_NAME + 1, obj_name) < 0)
BAIL(NC_EATTMETA);
LOG((3, "reading attribute of _netCDF group, named %s", obj_name));
/* See if this a hidden, global attribute */
if(grp->nc4_info->root_grp == grp) {
const char** reserved = NC_RESERVED_ATT_LIST;
hidden = 0;
for(;*reserved;reserved++) {
if(strcmp(*reserved,obj_name)==0) {
hidden = 1;
break;
}
}
}
/* This may be an attribute telling us that strict netcdf-3
* rules are in effect. If so, we will make note of the fact,
* but not add this attribute to the metadata. It's not a user
* attribute, but an internal netcdf-4 one. */
if (!strcmp(obj_name, NC3_STRICT_ATT_NAME))
grp->nc4_info->cmode |= NC_CLASSIC_MODEL;
else
{
if(strcmp(obj_name, NC3_STRICT_ATT_NAME)==0)
grp->nc4_info->cmode |= NC_CLASSIC_MODEL;
else if(!hidden) {
/* Add an att struct at the end of the list, and then go to it. */
if ((retval = nc4_att_list_add(&grp->att, &att)))
BAIL(retval);
@ -1866,26 +1915,28 @@ read_grp_atts(NC_GRP_INFO_T *grp)
strncpy(att->name, obj_name, max_len);
att->name[max_len] = 0;
att->attnum = grp->natts++;
if ((retval = read_hdf5_att(grp, attid, att)))
{
if (NC_EBADTYPID == retval)
{
if ((retval = nc4_att_list_del(&grp->att, att)))
retval = read_hdf5_att(grp, attid, att);
if(retval == NC_EBADTYPID) {
if((retval = nc4_att_list_del(&grp->att, att)))
BAIL(retval);
continue;
}
else
} else if(retval) {
BAIL(retval);
}
att->created = NC_TRUE;
if ((retval = nc4_find_type(grp->nc4_info, att->nc_typeid, &type)))
BAIL(retval);
} else {
att->created = NC_TRUE;
if ((retval = nc4_find_type(grp->nc4_info, att->nc_typeid, &type)))
BAIL(retval);
}
}
/* Unconditionally close the open attribute */
H5Aclose(attid);
attid = -1;
}
exit:
if (attid > 0 && H5Aclose(attid) < 0)
BAIL2(NC_EHDFERR);
exit:
if (attid > 0) {
if(H5Aclose(attid) < 0)
BAIL2(NC_EHDFERR);
}
return retval;
}
@ -2229,7 +2280,6 @@ nc4_open_file(const char *path, int mode, void* parameters, NC *nc)
BAIL(NC_EHDFERR);
#endif
#ifdef USE_PARALLEL4
/* If this is a parallel file create, set up the file creation
property list. */
@ -2323,6 +2373,10 @@ nc4_open_file(const char *path, int mode, void* parameters, NC *nc)
num_plists--;
#endif
#ifdef ENABLE_FILEINFO
NC4_get_fileinfo(nc4_info,NULL);
#endif
return NC_NOERR;
exit:
@ -2834,7 +2888,6 @@ NC4_open(const char *path, int mode, int basepe, size_t *chunksizehintp,
#endif /* USE_HDF4 */
else
assert(0); /* should never happen */
return res;
}
@ -3087,6 +3140,11 @@ close_netcdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort)
MPI_Info_free(&h5->info);
}
#endif
#ifdef ENABLE_FILEINFO
if(h5->fileinfo) free(h5->fileinfo);
#endif
if (H5Fclose(h5->hdfid) < 0)
{
int nobjs;
@ -3097,23 +3155,29 @@ close_netcdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort)
BAIL_QUIET(NC_EHDFERR);
} else if(nobjs > 0) {
#ifdef LOGGING
char msg[1024];
int logit = 1;
/* If the close doesn't work, probably there are still some HDF5
* objects open, which means there's a bug in the library. So
* print out some info on to help the poor programmer figure it
* out. */
LOG((0, "There are %d HDF5 objects open!", nobjs));
snprintf(msg,sizeof(msg),"There are %d HDF5 objects open!", nobjs);
#ifdef LOGOPEN
LOG((0, msg));
#else
fprintf(stdout,msg);
logit = 0;
#endif
reportopenobjects(logit,h5->hdfid);
#endif
BAIL_QUIET(NC_EHDFERR);
}
}
}
}
exit:
/* Free the nc4_info struct; above code should have reclaimed
everything else */
if(h5 != NULL)
free(h5);
return retval;
}

View File

@ -25,6 +25,8 @@
#define NC3_STRICT_ATT_NAME "_nc3_strict"
#define NC_HDF5_MAX_NAME 1024
/* This is to track opened HDF5 objects to make sure they are
* closed. */
#ifdef EXTRA_TESTS
@ -1901,10 +1903,10 @@ write_nc3_strict_att(hid_t hdf_grpid)
BAIL(NC_EHDFERR);
if (H5Aget_name(attid, NC_MAX_HDF5_NAME, att_name) < 0)
BAIL(NC_EHDFERR);
if (!strcmp(att_name, NC3_STRICT_ATT_NAME))
{
if (H5Aclose(attid) < 0)
if (H5Aclose(attid) < 0)
return NC_EFILEMETA;
if (strcmp(att_name, NC3_STRICT_ATT_NAME)==0)
{
return NC_NOERR;
}
}
@ -2488,14 +2490,12 @@ nc4_rec_write_metadata(NC_GRP_INFO_T *grp, nc_bool_t bad_coord_order)
int coord_varid = -1;
int retval;
assert(grp && grp->name && grp->hdf_grpid);
LOG((3, "%s: grp->name %s, bad_coord_order %d", __func__, grp->name, bad_coord_order));
/* Write global attributes for this group. */
if ((retval = write_attlist(grp->att, NC_GLOBAL, grp)))
return retval;
/* Set the pointers to the beginning of the list of dims & vars in this
* group. */
dim = grp->dim;
@ -3848,3 +3848,228 @@ nc4_get_typeclass(const NC_HDF5_FILE_INFO_T *h5, nc_type xtype, int *type_class)
exit:
return retval;
}
int
NC4_test_netcdf4(void)
{
return NC_NOERR;
}
void
reportobject(int log, hid_t id, unsigned int type)
{
# define MAXNAME 1024
char name[MAXNAME];
ssize_t len;
const char* typename = NULL;
len = H5Iget_name(id, name, MAXNAME);
if(len < 0) return;
name[len] = '\0';
switch (type) {
case H5F_OBJ_FILE: typename = "File"; break;
case H5F_OBJ_DATASET: typename = "Dataset"; break;
case H5F_OBJ_GROUP: typename = "Group"; break;
case H5F_OBJ_DATATYPE: typename = "Datatype"; break;
case H5F_OBJ_ATTR:
typename = "Attribute";
len = H5Aget_name(id, MAXNAME, name);
if(len < 0) len = 0;
name[len] = '\0';
break;
default: typename = "<unknown>"; break;
}
if(log) {
#ifdef LOGGING
LOG((0,"Type = %s(%8u) name='%s'",typename,id,name));
#endif
} else {
fprintf(stderr,"Type = %s(%8u) name='%s'",typename,id,name);
}
}
static unsigned int OTYPES[5] = {H5F_OBJ_FILE, H5F_OBJ_DATASET, H5F_OBJ_GROUP, H5F_OBJ_DATATYPE, H5F_OBJ_ATTR};
static void
reportopenobjectsT(int log, hid_t fid, int ntypes, unsigned int* otypes)
{
int t,i;
ssize_t ocount;
size_t maxobjs = -1;
hid_t* idlist = NULL;
if(log) {
#ifdef LOGGING
LOG((0,"\nReport: open objects on %d\n",fid));
#endif
} else {
fprintf(stdout,"\nReport: open objects on %d\n",fid);
}
maxobjs = H5Fget_obj_count(fid,H5F_OBJ_ALL);
if(idlist != NULL) free(idlist);
idlist = (hid_t*)malloc(sizeof(hid_t)*maxobjs);
for(t=0;t<ntypes;t++) {
unsigned int ot = otypes[t];
if(ot < 0) break;
ocount = H5Fget_obj_ids(fid,ot,maxobjs,idlist);
for(i=0;i<ocount;i++) {
hid_t o = idlist[i];
reportobject(log,o,ot);
}
}
if(idlist != NULL) free(idlist);
}
void
reportopenobjects(int log, hid_t fid)
{
reportopenobjectsT(log, fid,5,OTYPES);
}
#ifdef ENABLE_FILEINFO
int
NC4_hdf5get_libversion(unsigned* major,unsigned* minor,unsigned* release)
{
if(H5get_libversion(major,minor,release) < 0)
return NC_EHDFERR;
return NC_NOERR;
}
int
NC4_hdf5get_superblock(struct NC_HDF5_FILE_INFO* h5, int* idp)
{
int stat = NC_NOERR;
unsigned super;
hid_t plist = -1;
if((plist = H5Fget_create_plist(h5->hdfid)) < 0)
{stat = NC_EHDFERR; goto done;}
if(H5Pget_version(plist, &super, NULL, NULL, NULL) < 0)
{stat = NC_EHDFERR; goto done;}
if(idp) *idp = (int)super;
done:
if(plist >= 0) H5Pclose(plist);
return stat;
}
/* We define a file as being from netcdf-4 if any of the following
are true:
1. NCPROPS attribute exists in root group
2. NC3_STRICT_ATT_NAME exists in root group
3. any of NC_ATT_REFERENCE_LIST, NC_ATT_CLASS,
NC_ATT_DIMENSION_LIST, NC_ATT_NAME,
NC_ATT_COORDINATES, NC_DIMID_ATT_NAME
exist anywhere in the file; note that this
requires walking the file.
WARNINGS:
1. False negatives are possible for a small subset of netcdf-4
created files.
2. Deliberate falsification in the file can be used to cause
a false positive.
*/
static int NC4_get_strict_att(NC_HDF5_FILE_INFO_T*);
static int NC4_walk(hid_t, int*);
int
NC4_isnetcdf4(struct NC_HDF5_FILE_INFO* h5)
{
int stat;
int isnc4 = 0;
int count;
#if 0
if(h5->fileinfo->propattr.version > 0) {
isnc4 = 1;
goto done;
}
#endif
/* Look for NC3_STRICT_ATT_NAME */
isnc4 = NC4_get_strict_att(h5);
if(isnc4 > 0)
goto done;
/* attribute did not exist */
/* => last resort: walk the HDF5 file looking for markers */
count = 0;
stat = NC4_walk(h5->root_grp->hdf_grpid, &count);
if(stat != NC_NOERR)
isnc4 = 0;
else /* Threshold is at least two matches */
isnc4 = (count >= 2);
done:
return isnc4;
}
static int
NC4_get_strict_att(NC_HDF5_FILE_INFO_T* h5)
{
int ncstat = NC_NOERR;
size_t size;
char text[NCPROPS_LENGTH+1];
hid_t grp = -1;
hid_t attid = -1;
herr_t herr = 0;
/* Get root group */
grp = h5->root_grp->hdf_grpid; /* get root group */
/* Try to extract the NC3_STRICT_ATT_NAME attribute */
attid = H5Aopen_name(grp, NC3_STRICT_ATT_NAME);
H5Aclose(attid);
return attid;
}
static int
NC4_walk(hid_t gid, int* countp)
{
int ncstat = NC_NOERR;
int i,j,na;
ssize_t len;
hsize_t nobj;
herr_t err;
int otype;
hid_t grpid, dsid;
char name[NC_HDF5_MAX_NAME];
/* walk group members of interest */
err = H5Gget_num_objs(gid, &nobj);
for(i = 0; i < nobj; i++) {
/* Get name & kind of object in the group */
len = H5Gget_objname_by_idx(gid,(hsize_t)i,name,(size_t)NC_HDF5_MAX_NAME);
otype = H5Gget_objtype_by_idx(gid,(size_t)i);
switch(otype) {
case H5G_GROUP:
grpid = H5Gopen(gid,name);
NC4_walk(grpid,countp);
H5Gclose(grpid);
break;
case H5G_DATASET: /* variables */
/* Check for phony_dim */
if(strcmp(name,"phony_dim")==0)
*countp = *countp + 1;
dsid = H5Dopen(gid,name);
na = H5Aget_num_attrs(dsid);
for(j = 0; j < na; j++) {
hid_t aid = H5Aopen_idx(dsid,(unsigned int) j);
if(aid >= 0) {
const char** p;
ssize_t len = H5Aget_name(aid, NC_HDF5_MAX_NAME, name);
/* Is this a netcdf-4 marker attribute */
for(p=NC_RESERVED_VARATT_LIST;*p;p++) {
if(strcmp(name,*p) == 0) {
*countp = *countp + 1;
}
}
}
H5Aclose(aid);
}
H5Dclose(dsid);
break;
default:/* ignore */
break;
}
}
return ncstat;
}
#endif

216
libsrc4/nc4info.c Normal file
View File

@ -0,0 +1,216 @@
/*********************************************************************
* Copyright 2010, UCAR/Unidata
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
* ********************************************************************/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <hdf5.h>
#include "netcdf.h"
#include "nc4internal.h"
#define IGNORE 0
#define HDF5_MAX_NAME 1024
#define NCHECK(expr) {if((expr)!=NC_NOERR) {goto done;}}
#define HCHECK(expr) {if((expr)<0) {ncstat = NC_EHDFERR; goto done;}}
/* Global */
struct NCPROPINFO globalpropinfo;
struct NCdata {
};
int
NC4_fileinfo_init(void)
{
int stat = NC_NOERR;
unsigned major,minor,release;
int super;
size_t total = 0;
/* Build nc properties */
memset((void*)&globalpropinfo,0,sizeof(globalpropinfo));
globalpropinfo.version = NCPROPS_VERSION;
globalpropinfo.netcdfver[0] = '\0';
globalpropinfo.hdf5ver[0] = '\0';
stat = NC4_hdf5get_libversion(&major,&minor,&release);
if(stat) goto done;
snprintf(globalpropinfo.hdf5ver,sizeof(globalpropinfo.hdf5ver),
"%1u.%1u.%1u",major,minor,release);
strncpy(globalpropinfo.netcdfver,PACKAGE_VERSION,sizeof(globalpropinfo.netcdfver));
/* Now build actual attribute text */
total = 0;
total += strlen(NCPVERSION);
total += strlen("=00000000|");
total += strlen(NCPNCLIBVERSION);
total += strlen(globalpropinfo.netcdfver);
total += strlen("=|");
total += strlen(NCPHDF5LIBVERSION);
total += strlen(globalpropinfo.hdf5ver);
total += strlen("="); /* Last pair has no trailing '|' */
if(total >= sizeof(globalpropinfo.text)) {
fprintf(stderr,"%s size is too small\n",NCPROPS);
goto done;
}
globalpropinfo.text[0] = '\0';
snprintf(globalpropinfo.text,sizeof(globalpropinfo.text),
"%s=%d|%s=%s|%s=%s",
NCPVERSION,globalpropinfo.version,
NCPNCLIBVERSION,globalpropinfo.netcdfver,
NCPHDF5LIBVERSION,globalpropinfo.hdf5ver);
done:
return stat;
}
static int
NC4_properties_parse(struct NCPROPINFO* ncprops)
{
size_t len;
char propdata[NCPROPS_LENGTH]; /* match nc.h struct NCProperties */
char* p;
ncprops->version = 0;
ncprops->hdf5ver[0] = '\0';
ncprops->netcdfver[0] = '\0';
strncpy(propdata,ncprops->text,sizeof(propdata)-1);
propdata[sizeof(propdata)-1] = '\0';
len = strlen(propdata);
if(len == 0) return NC_NOERR;
/* Walk and fill in ncinfo */
p = propdata;
while(*p) {
char* name = p;
char* value = NULL;
char* q = strchr(p,'=');
if(q == NULL)
return NC_EINVAL;
*q++ = '\0';
value = p = q;
q = strchr(p,NCPROPSSEP);
if(q == NULL) q = (p+strlen(p)); else* q++ = '\0';
p = q;
if(name != NULL && value != NULL) {
if(strcmp(name,NCPVERSION) == 0) {
int v = atoi(value);
if(v < 0) v = 0;
ncprops->version = v;
} else if(strcmp(name,NCPNCLIBVERSION) == 0)
strncpy(ncprops->netcdfver,value,sizeof(ncprops->netcdfver)-1);
else if(strcmp(name,NCPHDF5LIBVERSION) == 0)
strncpy(ncprops->hdf5ver,value,sizeof(ncprops->hdf5ver)-1);
/* else ignore */
}
}
/* Guarantee null term */
ncprops->netcdfver[sizeof(ncprops->netcdfver)-1] = '\0';
ncprops->hdf5ver[sizeof(ncprops->hdf5ver)-1] = '\0';
return NC_NOERR;
}
static int
NC4_get_propattr(NC_HDF5_FILE_INFO_T* h5)
{
int ncstat = NC_NOERR;
size_t size;
H5T_class_t t_class;
char text[NCPROPS_LENGTH+1];
hid_t grp = -1;
hid_t attid = -1;
hid_t aspace = -1;
hid_t atype = -1;
hid_t ntype = -1;
herr_t herr = 0;
/* Get root group */
grp = h5->root_grp->hdf_grpid; /* get root group */
/* Try to extract the NCPROPS attribute */
attid = H5Aopen_name(grp, NCPROPS);
if(attid >= 0) {
herr = -1;
aspace = H5Aget_space(attid); /* dimensions of attribute data */
atype = H5Aget_type(attid);
/* Verify that atype and size */
t_class = H5Tget_class(atype);
if(t_class != H5T_STRING) {ncstat = NC_EATTMETA; goto done;}
size = H5Tget_size(atype);
if(size != NCPROPS_LENGTH) {ncstat = NC_EATTMETA; goto done;}
HCHECK((ntype = H5Tget_native_type(atype, H5T_DIR_ASCEND)));
HCHECK((H5Aread(attid, ntype, text)));
/* Try to parse text */
strncpy(h5->fileinfo->propattr.text,text,NCPROPS_LENGTH);
h5->fileinfo->propattr.text[NCPROPS_LENGTH-1] = '\0';
ncstat = NC4_properties_parse(&h5->fileinfo->propattr);
herr = 0;
}
done:
if(attid >= 0) HCHECK((H5Aclose(attid)));
if(aspace >= 0) HCHECK((H5Sclose(aspace)));
if(ntype >= 0) HCHECK((H5Tclose(ntype)));
if(atype >= 0) HCHECK((H5Tclose(atype)));
return ncstat;
}
int
NC4_put_propattr(NC_HDF5_FILE_INFO_T* h5)
{
int ncstat = NC_NOERR;
char text[NCPROPS_LENGTH+1];
H5T_class_t t_class;
size_t size;
hid_t grp = -1;
hid_t exists = -1;
hid_t attid = -1;
hid_t aspace = -1;
hid_t atype = -1;
herr_t herr = 0;
/* Get root group */
grp = h5->root_grp->hdf_grpid; /* get root group */
/* See if the NCPROPS attribute exists */
exists = H5Aopen_name(grp, NCPROPS);
if(exists < 0) {/* Does not exist */
herr = -1;
/* Create a datatype to refer to. */
HCHECK((atype = H5Tcopy(H5T_C_S1)));
HCHECK((H5Tset_cset(atype, H5T_CSET_UTF8)));
HCHECK((H5Tset_size(atype, NCPROPS_LENGTH)));
HCHECK((aspace = H5Screate(H5S_SCALAR)));
HCHECK((attid = H5Acreate(grp, NCPROPS, atype, aspace, H5P_DEFAULT)));
HCHECK((H5Awrite(attid, atype, h5->fileinfo->propattr.text)));
herr = 0;
}
done:
if(exists >= 0) HCHECK((H5Aclose(exists)));
if(attid >= 0) HCHECK((H5Aclose(attid)));
if(aspace >= 0) HCHECK((H5Sclose(aspace)));
if(atype >= 0) HCHECK((H5Tclose(atype)));
return ncstat;
}
int
NC4_get_fileinfo(NC_HDF5_FILE_INFO_T* h5, struct NCPROPINFO* init)
{
int ncstat = NC_NOERR;
/* Allocate the fileinfo in h5 */
h5->fileinfo = (struct NCFILEINFO*)calloc(1,sizeof(struct NCFILEINFO));
if(h5->fileinfo == NULL)
{ncstat = NC_ENOMEM; goto done;}
/* Get superblock version */
NCHECK((ncstat = NC4_hdf5get_superblock(h5,&h5->fileinfo->superblockversion)));
/* Get properties attribute if not already defined */
if(init == NULL) {
NCHECK((ncstat = NC4_get_propattr(h5)));
} else { /*init != NULL*/
h5->fileinfo->propattr = *init; /* Initialize */
}
done:
return ncstat;
}

View File

@ -45,7 +45,7 @@ int nc_log_level = -1;
#endif /* LOGGING */
static int nc4_hdf5_initialized = 0;
int nc4_hdf5_initialized = 0;
/*
Provide a function to do any necessary initialization
@ -544,12 +544,13 @@ nc4_find_grp_att(NC_GRP_INFO_T *grp, int varid, const char *name, int attnum,
/* Now find the attribute by name or number. If a name is provided,
* ignore the attnum. */
for (*att = attlist; *att; *att = (*att)->l.next) {
if (name && (*att)->name && !strcmp((*att)->name, name))
return NC_NOERR;
if (!name && (*att)->attnum == attnum)
return NC_NOERR;
}
if(attlist)
for (*att = attlist; *att; *att = (*att)->l.next) {
if (name && (*att)->name && !strcmp((*att)->name, name))
return NC_NOERR;
if (!name && (*att)->attnum == attnum)
return NC_NOERR;
}
/* If we get here, we couldn't find the attribute. */
return NC_ENOTATT;

View File

@ -1474,10 +1474,7 @@ nc4_get_hdf4_vara(NC *nc, int ncid, int varid, const size_t *startp,
NC_VAR_INFO_T *var;
int32 start32[NC_MAX_VAR_DIMS], edge32[NC_MAX_VAR_DIMS];
int retval, d;
#if 0
NC_GRP_INFO_T *g;
NC_DIM_INFO_T *dim;
#endif
/* Find our metadata for this file, group, and var. */
assert(nc);
if ((retval = nc4_find_g_var_nc(nc, ncid, varid, &grp, &var)))

View File

@ -1,34 +1,33 @@
# Test c output
T=t
T=tst_small
#CMD=valgrind --leak-check=full
CMD=gdb --args
#CMD=gdb --args
#PAR=1
CFLAGS=-Wall -Wno-unused-variable -Wno-unused-function -g -O0 -I.. -I../include
ifdef PAR
CC=mpicc
CFLAGS=-g -O0 -I.. -I../include
#CC=/usr/local/bin/mpicc
LDFLAGS=../liblib/.libs/libnetcdf.a -L/usr/local/lib -lhdf5_hl -lhdf5 -lz -ldl -lcurl -lpnetcdf -lmpich -lm
else
CC=gcc
#LDFLAGS=../liblib/.libs/libnetcdf.a -L/usr/local/lib -lhdf5_hl -lhdf5 -lz -lm -lcurl
LDFLAGS=-L/usr/local/lib -lhdf5_hl -lhdf5 -lz ../liblib/.libs/libnetcdf.a -ldl -lm -lcurl
CC=/usr/local/bin/mpicc
LDFLAGS=-L/usr/local/lib -lhdf5_hl -lhdf5 -lz ../liblib/.libs/libnetcdf.a -ldl -lcurl -lpnetcdf -lmpich -lm
LDFLAGS=../liblib/.libs/libnetcdf.a -L/usr/local/lib -lhdf5_hl -lhdf5 -lz -ldl -lm -lcurl
endif
# cd .. ; ${MAKE} all
LLP=/usr/local/lib:${LD_LIBRARY_PATH}
all::
echo ${LD_RUN_PATH}
all:: cmp
export LD_LIBRARY_PATH=${LLP}; export CFLAGS; export LDFLAGS; \
${CC} -o t ${CFLAGS} ${T}.c ${LDFLAGS}; \
${CMD} ./t
cmp::
export LD_LIBRARY_PATH=${LLP}; export CFLAGS; export LDFLAGS; \
${CC} -o t ${CFLAGS} ${T}.c ${SRC} ${LDFLAGS}; \
cpp::
${CC} -E ${CFLAGS} ${T}.c > ${T}.txt
all::
echo ${LD_RUN_PATH}
export LD_LIBRARY_PATH=${LLP}; export CFLAGS; export LDFLAGS; \
gcc -o t ${CFLAGS} ${T}.c ${LDFLAGS}; \
${CMD} ./t

View File

@ -1,31 +1,33 @@
# Test c output
T=tst_mode
T=tst_chunk_hdf4
#CMD=valgrind --leak-check=full
CMD=gdb --args
PAR=1
#PAR=1
CFLAGS=-g -O0 -I.. -I../include
CFLAGS=-Wall -Wno-unused-variable -Wno-unused-function -g -O0 -I.. -I../include
ifdef PAR
CC=mpicc
#CC=/usr/local/bin/mpicc
LDFLAGS=-L/usr/local/lib -lhdf5_hl -lhdf5 -lz ../liblib/.libs/libnetcdf.a -ldl -lcurl -lpnetcdf -lmpich -lm
LDFLAGS=../liblib/.libs/libnetcdf.a -L/usr/local/lib -lhdf5_hl -lhdf5 -lz -ldl -lcurl -lpnetcdf -lmpich -lm
else
CC=gcc
#LDFLAGS=../liblib/.libs/libnetcdf.a -L/usr/local/lib -lhdf5_hl -lhdf5 -lz -lm -lcurl
LDFLAGS=-L/usr/local/lib -lhdf5_hl -lhdf5 -lz ../liblib/.libs/libnetcdf.a -ldl -lm -lcurl
LDFLAGS=../liblib/.libs/libnetcdf.a -L/usr/local/lib -lhdf5_hl -lhdf5 -lz -ldl -lm -lcurl
endif
# cd .. ; ${MAKE} all
LLP=/usr/local/lib:${LD_LIBRARY_PATH}
all::
echo ${LD_RUN_PATH}
all:: cmp
export LD_LIBRARY_PATH=${LLP}; export CFLAGS; export LDFLAGS; \
${CC} -o t ${CFLAGS} ${T}.c ${LDFLAGS}; \
${CMD} ./t
cmp::
export LD_LIBRARY_PATH=${LLP}; export CFLAGS; export LDFLAGS; \
${CC} -o t ${CFLAGS} ${T}.c ${SRC} ${LDFLAGS}; \
cpp::
${CC} -E ${CFLAGS} ${T}.c > ${T}.txt

View File

@ -23,12 +23,15 @@ echo "* Testing Empty Ragged Arrays (VLEN)"
echo "Generating test netcdf files."
./tst_empty_vlen_unlim
echo "Validating Files with ncdump."
echo "======================================"
../ncdump/ncdump -s tst_empty_vlen_unlim.nc
echo "---------------------------------------"
../ncdump/ncdump -s tst_empty_vlen_lim.nc
echo "======================================"
# Since no comparison is made, I am not sure
# if this is useful.
#echo "Validating Files with ncdump."
#echo "======================================"
#../ncdump/ncdump -s tst_empty_vlen_unlim.nc
#echo "---------------------------------------"
#../ncdump/ncdump -s tst_empty_vlen_lim.nc
#echo "======================================"
echo "* Tests Passed."
exit 0

View File

@ -59,6 +59,12 @@ IF(ENABLE_TESTS)
TARGET_LINK_LIBRARIES(bom netcdf)
TARGET_LINK_LIBRARIES(tst_dimsizes netcdf)
IF(ENABLE_PROPERTIES_ATTRIBUTE)
ADD_EXECUTABLE(tst_fileinfo tst_fileinfo.c)
TARGET_LINK_LIBRARIES(tst_fileinfo netcdf)
add_sh_test(ncdump tst_fileinfo)
ENDIF()
IF(MSVC)
SET_TARGET_PROPERTIES(rewrite-scalar PROPERTIES RUNTIME_OUTPUT_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR})
@ -80,6 +86,8 @@ IF(MSVC)
${CMAKE_CURRENT_BINARY_DIR})
SET_TARGET_PROPERTIES(tst_dimsizes PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE
${CMAKE_CURRENT_BINARY_DIR})
SET_TARGET_PROPERTIES(tst_fileinfo PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE
${CMAKE_CURRENT_BINARY_DIR})
ENDIF()
# Base tests
@ -96,7 +104,6 @@ ENDIF()
add_sh_test(ncdump tst_lengths)
add_sh_test(ncdump tst_calendars)
add_bin_test(ncdump tst_utf8)
add_sh_test(ncdump run_utf8_tests)
IF(USE_NETCDF4)
add_sh_test(ncdump run_utf8_nc4_tests)

View File

@ -1,24 +1,33 @@
# Test c output
T=tst_dimsizes
T=tst_fileinfo
#CMD=valgrind --leak-check=full
#CMD=gdb --args
CMD=gdb --args
#MPI=1
LLP="LD_LIBRARY_PATH=/usr/local/lib"
#PAR=1
ifndef MPI
CC=gcc
CFLAGS=-g -O0 -I.. -I../include
LDFLAGS=../liblib/.libs/libnetcdf.a -L/usr/local/lib -lhdf5_hl -lhdf5 -lz -lm -lcurl
CFLAGS=-Wall -g -O0 -I.. -I../include
ifdef PAR
CC=mpicc
#CC=/usr/local/bin/mpicc
LDFLAGS=../liblib/.libs/libnetcdf.a -L/usr/local/lib -lhdf5_hl -lhdf5 -lz -ldl -lcurl -lpnetcdf -lmpich -lm
else
CC=/usr/local/bin/mpicc
LDFLAGS=../liblib/.libs/libnetcdf.a -L/usr/local/lib -lhdf5_hl -lhdf5 -lz ../liblib/.libs/libnetcdf.a -ldl -lcurl -lpnetcdf -lmpich -lm
CC=gcc
#LDFLAGS=../liblib/.libs/libnetcdf.a -L/usr/local/lib -lhdf5_hl -lhdf5 -lz -lm -lcurl
LDFLAGS=../liblib/.libs/libnetcdf.a -L/usr/local/lib -lhdf5_hl -lhdf5 -lz -ldl -lm -lcurl
endif
all::
export ${LLP}; export CFLAGS; export LDFLAGS; \
${CC} -o $T.exe ${CFLAGS} ${T}.c ${LDFLAGS}; \
${CMD} ./$T.exe
# cd .. ; ${MAKE} all
LLP=/usr/local/lib:${LD_LIBRARY_PATH}
all:: cmp
export LD_LIBRARY_PATH=${LLP}; export CFLAGS; export LDFLAGS; \
${CMD} ./t
cmp::
export LD_LIBRARY_PATH=${LLP}; export CFLAGS; export LDFLAGS; \
${CC} -o t ${CFLAGS} ${T}.c ${SRC} ${LDFLAGS}; \
cpp::
${CC} -E ${CFLAGS} ${T}.c > ${T}.txt

View File

@ -29,11 +29,17 @@ if BUILD_TESTSETS
#if !BUILD_DLL
# These tests are run for both netCDF-4 and non-netCDF-4 builds.
check_PROGRAMS = rewrite-scalar ctest ctest64 ncdump tst_utf8 bom tst_dimsizes
TESTS = tst_inttags.sh run_tests.sh tst_64bit.sh ctest ctest64 tst_output.sh \
tst_lengths.sh tst_calendars.sh tst_utf8 run_utf8_tests.sh \
tst_nccopy3.sh tst_charfill.sh tst_iter.sh tst_formatx3.sh tst_bom.sh \
tst_dimsizes.sh
if ENABLE_FILEINFO
check_PROGRAMS += tst_fileinfo
TESTS += tst_fileinfo.sh
endif
if LARGE_FILE_TESTS
TESTS += tst_iter.sh
endif
@ -114,7 +120,8 @@ tst_nc_test_netcdf4_4_0.cdl tst_mud4.nc tst_mud4.cdl tst_mud4-bc.cdl \
tst_ncf213.cdl tst_ncf213.nc tst_h_scalar.cdl tst_h_scalar.nc \
tst_mud4_chars.cdl tst_mud4_chars.nc \
inttags.nc inttags4.nc tst_inttags.cdl tst_inttags4.cdl \
tst_dimsize_classic.nc tst_dimsize_64offset.nc tst_dimsize_64data.nc
tst_dimsize_classic.nc tst_dimsize_64offset.nc tst_dimsize_64data.nc \
nc4_fileinfo.nc hdf5_fileinfo.hdf
# These files all have to be included with the distribution.
EXTRA_DIST = run_tests.sh tst_64bit.sh tst_output.sh test0.cdl \
@ -142,7 +149,7 @@ run_utf8_nc4_tests.sh \
tst_formatx3.sh tst_formatx4.sh ref_tst_utf8_4.cdl \
tst_inttags.sh tst_inttags4.sh \
CMakeLists.txt XGetopt.c tst_bom.sh tst_inmemory_nc3.sh \
tst_dimsizes.sh tst_inmemory_nc4.sh
tst_dimsizes.sh tst_inmemory_nc4.sh tst_fileinfo.sh
# CDL files and Expected results
SUBDIRS=cdl expected

View File

@ -17,5 +17,6 @@
#define NC_ATT_SHUFFLE "_Shuffle"
#define NC_ATT_STORAGE "_Storage"
#define NC_ATT_NOFILL "_NoFill"
#define NC_ATT_NETCDF4 "_NetCDF4"
#endif /*_CDL_H_ */

View File

@ -37,8 +37,8 @@ typedef int ssize_t;
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif /* HAVE_LOCALE_H */
#include <netcdf.h>
#include <netcdf_mem.h>
#include "netcdf.h"
#include "netcdf_mem.h"
#include "utils.h"
#include "nccomps.h"
#include "nctime0.h" /* new iso time and calendar stuff */
@ -48,6 +48,7 @@ typedef int ssize_t;
#include "indent.h"
#include "isnan.h"
#include "cdl.h"
#include "nc4internal.h" /* to get name of the special properties file */
#define XML_VERSION "1.0"
@ -116,6 +117,7 @@ usage(void)
[-g grp1[,...]] Data and metadata for group(s) <grp1>,... only\n\
[-w] With client-side caching of variables for DAP URLs\n\
[-x] Output XML (NcML) instead of CDL\n\
[-Xp] Unconditionally suppress output of the properties attribute\n\
file Name of netCDF file (or URL if DAP access enabled)\n"
(void) fprintf(stderr,
@ -757,6 +759,10 @@ pr_att(
ncatt_t att; /* attribute */
NC_CHECK( nc_inq_attname(ncid, varid, ia, att.name) );
if (ncid == getrootid(ncid)
&& varid == NC_GLOBAL
&& strcmp(att.name,NCPROPS)==0)
return; /* will be printed elsewere */
NC_CHECK( nc_inq_att(ncid, varid, att.name, &att.type, &att.len) );
att.tinfo = get_typeinfo(att.type);
@ -952,7 +958,6 @@ pr_att_global_format(
printf (" ;\n");
}
#ifdef USE_NETCDF4
/*
* Print special reserved variable attributes, such as _Chunking,
@ -1054,6 +1059,7 @@ pr_att_specials(
printf(" = \"true\" ;\n");
}
}
/* TODO: handle _Nbit when inquire function is available */
/* TODO: handle _ScaleOffset when inquire is available */
@ -1062,6 +1068,54 @@ pr_att_specials(
}
#endif /* USE_NETCDF4 */
#ifdef ENABLE_FILEINFO /*=>NETCDF4*/
static void
pr_att_hidden(
int ncid,
int kind
)
{
int stat;
size_t len;
char propdata[NCPROPS_LENGTH];
/* No special variable attributes for classic or 64-bit offset data */
if(kind == 1 || kind == 2)
return;
/* Print out Selected hidden attributes */
/* NCPROPS */
stat = nc_inq_att(ncid,NC_GLOBAL,NCPROPS,NULL,&len);
if(stat == NC_NOERR && len < sizeof(propdata)) {
stat = nc_get_att_text(ncid,NC_GLOBAL,NCPROPS,propdata);
if(stat == NC_NOERR) {
pr_att_name(ncid, "", NCPROPS);
/* make sure its null terminated */
propdata[NCPROPS_LENGTH-1] = '\0';
printf(" = \"%s\" ;\n",propdata);
}
}
/* _SuperblockVersion */
stat = nc_inq_att(ncid,NC_GLOBAL,SUPERBLOCKATT,NULL,&len);
if(stat == NC_NOERR && len == 1) {
int sbversion;
stat = nc_get_att_int(ncid,NC_GLOBAL,SUPERBLOCKATT,&sbversion);
if(stat == NC_NOERR) {
pr_att_name(ncid, "", SUPERBLOCKATT);
printf(" = %d ;\n",sbversion);
}
}
/* _IsNetcdf4 */
stat = nc_inq_att(ncid,NC_GLOBAL,ISNETCDF4ATT,NULL,&len);
if(stat == NC_NOERR && len == 1) {
int isnc4;
stat = nc_get_att_int(ncid,NC_GLOBAL,ISNETCDF4ATT,&isnc4);
if(stat == NC_NOERR) {
pr_att_name(ncid, "", ISNETCDF4ATT);
printf(" = %d ;\n",isnc4?1:0);
}
}
}
#endif /* ENABLE_FILEINFO */
/*
* Print a variable attribute for NcML
@ -1078,6 +1132,13 @@ pr_attx(
int attvalslen = 0;
NC_CHECK( nc_inq_attname(ncid, varid, ia, att.name) );
if (ncid == getrootid(ncid)
&& varid == NC_GLOBAL
&& strcmp(att.name,NCPROPS)==0
&& (!formatting_specs.special_atts
|| !formatting_specs.xopt_props)
)
return;
NC_CHECK( nc_inq_att(ncid, varid, att.name, &att.type, &att.len) );
/* Put attribute values into a single string, with blanks in between */
@ -1325,8 +1386,11 @@ print_ud_type(int ncid, nc_type typeid) {
printf(" ;\n");
}
indent_out();
/* printf("}; // %s\n", type_name); */
#if 0
printf("}; // %s\n", type_name);
#else
printf("}; // ");
#endif
print_type_name(ncid, typeid);
printf("\n");
}
@ -1666,7 +1730,6 @@ do_ncdump_rec(int ncid, const char *path)
#endif /* USE_NETCDF4 */
}
/* get global attributes */
if (ngatts > 0 || formatting_specs.special_atts) {
printf ("\n");
indent_out();
@ -1680,9 +1743,12 @@ do_ncdump_rec(int ncid, const char *path)
}
if (is_root && formatting_specs.special_atts) { /* output special attribute
* for format variant */
pr_att_hidden(ncid, kind);
pr_att_global_format(ncid, kind);
}
fflush(stdout);
/* output variable data, unless "-h" option specified header only
* or this group is not in list of groups specified by "-g"
* option */
@ -2019,6 +2085,7 @@ main(int argc, char *argv[])
bool_t xml_out = false; /* if true, output NcML instead of CDL */
bool_t kind_out = false; /* if true, just output kind of netCDF file */
bool_t kind_out_extended = false; /* output inq_format vs inq_format_extended */
int Xp_flag = 0; /* indicate that -Xp flag was set */
#if defined(WIN32) || defined(msdos) || defined(WIN64)
putenv("PRINTF_EXPONENT_DIGITS=2"); /* Enforce unix/linux style exponent formatting. */
@ -2132,6 +2199,9 @@ main(int argc, char *argv[])
case 'm':
formatting_specs.xopt_inmemory = 1;
break;
case 'p': /* suppress the properties attribute */
Xp_flag = 1; /* record that this flag was set */
break;
default:
error("invalid value for -X option: %s", optarg);
break;
@ -2142,6 +2212,16 @@ main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
/* Decide xopt_props */
if(formatting_specs.special_atts && Xp_flag == 1)
formatting_specs.xopt_props = 0;
else if(formatting_specs.special_atts && Xp_flag == 0)
formatting_specs.xopt_props = 1;
else if(!formatting_specs.special_atts)
formatting_specs.xopt_props = 0;
else
formatting_specs.xopt_props = 0;
set_max_len(max_len);
argc -= optind;

View File

@ -43,7 +43,7 @@ typedef struct { /* specification for how to format dump */
* for optimization characteristics:
* _Compression, _Chunking,
* _Endianness, _Format, _Checksum,
* _NoFill */
* _NoFill, _NetCDF4 */
Nclang data_lang; /* Specifies index conventions used in data
* comments, either LANG_C (C, 0-based,
@ -78,6 +78,7 @@ typedef struct { /* specification for how to format dump */
int nc_mode; /* mode as reported by inq_format_extended */
int xopt_inmemory; /* Use in-memory option; testing only */
int xopt_props ; /* 1=>Unconditionally Suppress properties attribute */
} fspec_t;
#endif /*_NCDUMP_H_ */

View File

@ -44,5 +44,8 @@ variables:
var5:_NoFill = "true" ;
// global attributes:
:_NCProperties = "version=1|netcdflibversion=0.0.0|hdf5libversion=0.0.0" ;
:_SuperblockVersion = 0 ;
:_IsNetcdf4 = 1 ;
:_Format = "netCDF-4" ;
}

View File

@ -45,6 +45,9 @@ variables:
var5:_NoFill = "true" ;
// global attributes:
:_NCProperties = "version=1|netcdflibversion=0.0.0|hdf5libversion=0.0.0" ;
:_SuperblockVersion = 0 ;
:_IsNetcdf4 = 1 ;
:_Format = "netCDF-4" ;
data:
}

157
ncdump/tst_fileinfo.c Normal file
View File

@ -0,0 +1,157 @@
/* This is part of the netCDF package. Copyright 2008 University
Corporation for Atmospheric Research/Unidata See COPYRIGHT file for
conditions of use. See www.unidata.ucar.edu for more info.
*/
/*
Test _NCProperties and other special attributes
*/
#include "config.h"
#ifdef HAVE_UNISTD_H
#include "unistd.h"
#endif
#include <hdf5.h>
#include "nc_tests.h"
#include "netcdf.h"
#include "nc4internal.h"
#define NC4FILE "nc4_fileinfo.nc"
#define HDFFILE "hdf5_fileinfo.hdf"
#define INT_ATT_NAME "int_attr"
#define INT_VAR_NAME "int_var"
#define GROUPNAME "subgroup"
#define DIMNAME "time"
int
main(int argc, char **argv)
{
printf("\n*** Testing 'Fileinfo attributes.\n");
{
hid_t fileid;
hid_t fcplid;
hid_t scalar_spaceid;
printf("*** creating test file using HDF5 directly %s...", HDFFILE);
/* Create scalar dataspace */
if((scalar_spaceid = H5Screate(H5S_SCALAR)) < 0) ERR;
/* Set creation ordering for file, so we can revise its contents later */
if((fcplid = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR;
if(H5Pset_link_creation_order(fcplid, H5P_CRT_ORDER_TRACKED) < 0) ERR;
if(H5Pset_attr_creation_order(fcplid, H5P_CRT_ORDER_TRACKED) < 0) ERR;
/* Create new file, using default properties */
if((fileid = H5Fcreate(HDFFILE, H5F_ACC_TRUNC, fcplid, H5P_DEFAULT)) < 0) ERR;
/* Close file creation property list */
if(H5Pclose(fcplid) < 0) ERR;
/* Add attributes to root group */
{
hid_t scalar_spaceid = -1;
hid_t attid = -1;
/* Create scalar dataspace */
if((scalar_spaceid = H5Screate(H5S_SCALAR)) < 0) ERR;
/* Create attribute with native integer datatype on object */
if((attid = H5Acreate2(fileid, INT_ATT_NAME, H5T_NATIVE_INT, scalar_spaceid, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR;
if(H5Aclose(attid) < 0) ERR;
/* Clean up objects created */
if(H5Sclose(scalar_spaceid) < 0) ERR;
}
/* Close rest */
if(H5Sclose(scalar_spaceid) < 0) ERR;
if(H5Fclose(fileid) < 0) ERR;
}
{
int root, grpid, varid, stat, natts;
int data = 17;
const char* sdata = "text";
char ncprops[8192];
size_t len;
int dimid;
printf("*** creating netcdf-4 test file using netCDF %s...", NC4FILE);
if(nc_create(NC4FILE,NC_WRITE|NC_CLOBBER|NC_NETCDF4,&root)!=0) ERR;
/* Create global attribute */
if(nc_put_att_int(root,NC_GLOBAL,INT_ATT_NAME,NC_INT,1,&data)!=0) ERR;
/* Create global variable */
if(nc_def_var(root,INT_VAR_NAME,NC_INT,0,NULL,&varid)!=0) ERR;
/* Create attribute on var */
if(nc_put_att_int(root,varid,INT_ATT_NAME,NC_INT,1,&data)!=0) ERR;
/* Create global subgroup */
if(nc_def_grp(root,GROUPNAME,&grpid)!=0) ERR;
/* Create global attribute in the group */
if(nc_put_att_int(grpid,NC_GLOBAL,INT_ATT_NAME,NC_INT,1,&data)!=0) ERR;
/* Create _NCProperties as var attr and as subgroup attribute */
if(nc_put_att_text(grpid,NC_GLOBAL,NCPROPS,strlen(sdata),sdata)!=0) ERR;
if(nc_put_att_text(root,varid,NCPROPS,strlen(sdata),sdata)!=0) ERR;
/* Create var + dimension to cause e.g. dimscales to appear */
if(nc_def_dim(root,DIMNAME,(size_t)4,&dimid)!=0) ERR;
if(nc_def_var(root,DIMNAME,NC_INT,1,&dimid,&varid)!=0) ERR; /* same name */
/* Close, then re-open */
if(nc_close(root)) ERR;
if(nc_open(NC4FILE,NC_WRITE|NC_NETCDF4,&root)!=0) ERR;
/* Is all invisible attributes actually invisible vis-a-vis nc_inq? */
if(nc_inq(root,NULL,NULL,&natts,NULL)!=0) ERR;
if(natts != 1) ERR;
/* Now, fiddle with the NCPROPS attribute */
/* Get its value */
if(nc_inq_att(root,NC_GLOBAL,NCPROPS,NULL,&len)!=0) ERR;
if(nc_get_att_text(root,NC_GLOBAL,NCPROPS,ncprops)!=0) ERR;
/*Overwrite _NCProperties root attribute; should fail */
stat = nc_put_att_text(root,NC_GLOBAL,NCPROPS,strlen(sdata),sdata);
if(stat == NC_NOERR) ERR;
/* Delete; should fail */
stat = nc_del_att(root,NC_GLOBAL,NCPROPS);
if(stat != NC_ENOTATT) ERR;
/* Ditto _SuperblockVersion */
/* Get its value */
if(nc_inq_att(root,NC_GLOBAL,SUPERBLOCKATT,NULL,&len)!=0) ERR;
if(len != 1) ERR;
if(nc_get_att_int(root,NC_GLOBAL,SUPERBLOCKATT,&data)!=0) ERR;
/*Overwrite; should fail */
stat = nc_put_att_int(root,NC_GLOBAL,NCPROPS,NC_INT,1,&data);
if(stat == NC_NOERR) ERR;
/* Delete; should fail */
stat = nc_del_att(root,NC_GLOBAL,SUPERBLOCKATT);
if(stat == NC_NOERR) ERR;
/* Ditto _IsNetcdf4 */
/* Get its value */
if(nc_inq_att(root,NC_GLOBAL,ISNETCDF4ATT,NULL,&len)!=0) ERR;
if(len != 1) ERR;
if(nc_get_att_int(root,NC_GLOBAL,ISNETCDF4ATT,&data)!=0) ERR;
/*Overwrite; should fail */
stat = nc_put_att_int(root,NC_GLOBAL,ISNETCDF4ATT,NC_INT,1,&data);
if(stat == NC_NOERR) ERR;
/* Delete; should fail */
stat = nc_del_att(root,NC_GLOBAL,ISNETCDF4ATT);
if(stat == NC_NOERR) ERR;
if(nc_close(root)!=0) ERR;
}
SUMMARIZE_ERR;
FINAL_RESULTS;
}

59
ncdump/tst_fileinfo.sh Executable file
View File

@ -0,0 +1,59 @@
#!/bin/sh
if test "x$SETX" = x1 ; then echo "file=$0"; set -x ; fi
set -e
echo ""
if test "x$builddir" = "x"; then builddir=`pwd`; fi
if test "x$srcdir" = "x"; then srcdir=`dirname $0`; fi
# Make buildir absolute
cd $builddir
builddir=`pwd`
# Make srcdir be absolute
cd $srcdir
srcdir=`pwd`
cd $builddir
export verbose
export srcdir
export builddir
EXIT=0
NCF=$srcdir/nc4_fileinfo.nc
HDF=$srcdir/hdf5_fileinfo.hdf
NF=ref_tst_compounds4.nc
# Do a false negative test
rm -f ./tmp
if $builddir/ncdump -s $builddir/$NF | fgrep '_IsNetcdf4 = 0' > ./tmp ; then
echo "Pass: False negative for file: $NF"
else
echo "FAIL: False negative for file: $NF"
fi
rm -f ./tmp
if ./tst_fileinfo > /dev/null ; then
# look at the _IsNetcdf4 flag
N_IS=`${builddir}/ncdump -s $NCF | fgrep '_IsNetcdf4' | tr -d ' ;'`
N_IS=`echo $N_IS | cut -d= -f2`
H_IS=`${builddir}/ncdump -s $HDF | fgrep '_IsNetcdf4' | tr -d ' ;'`
H_IS=`echo $H_IS | cut -d= -f2`
if test "x$N_IS" = 'x0' ;then
echo "FAIL: $NCF is marked as not netcdf-4"
fi
if test "x$H_IS" = 'x1' ;then
echo "FAIL: $HDF is marked as netcdf-4"
fi
else
echo "FAIL: tst_fileinfo"
EXIT=1
fi
rm -f $NCF
rm -f $HDF
exit $EXIT

View File

@ -1,5 +1,21 @@
#!/bin/sh
if test "x$SETX" = x1 ; then echo "file=$0"; set -x ; fi
if test "x$srcdir" = x ; then
srcdir=`pwd`
fi
# It is unreasonable to test actual lengths of files
# (even netcdf-3 files).
#However, the files created in this script are used in later ones
../ncgen/ncgen -b ${srcdir}/small.cdl
../ncgen/ncgen -b ${srcdir}/small2.cdl
exit
# This shell script tests lengths of small netcdf files and tests
# that rewriting a numeric value doesn't change file length
# $Id: tst_lengths.sh,v 1.10 2008/08/07 00:07:52 ed Exp $
@ -34,9 +50,6 @@ if test "x$SETX" = x1 ; then echo "file=$0"; set -x ; fi
# echo "netcdf small {variables: byte t; data: t = 1;}" > small.cdl
set -e
if test "x$srcdir" = x ; then
srcdir=`pwd`
fi
echo ""
echo "*** testing length of classic file"

View File

@ -82,7 +82,12 @@ if test -f ./tst_unicode -o -f ./tst_unicode.exe ; then
#diff -b tst_unicode.cdl $srcdir/ref_tst_unicode.cdl
fi
./tst_special_atts
./ncdump -c -s tst_special_atts.nc | sed 's/e+0/e+/g' > tst_special_atts.cdl
./ncdump -c -s tst_special_atts.nc \
| sed 's/e+0/e+/g' \
| sed -e 's/netcdflibversion=.*[|]/netcdflibversion=0.0.0|/' \
| sed -e 's/hdf5libversion=.*"/hdf5libversion=0.0.0"/' \
| sed -e 's|_SuperblockVersion = [0-9]|_SuperblockVersion = 0|' \
| cat > tst_special_atts.cdl
echo "*** comparing tst_special_atts.cdl with ref_tst_special_atts.cdl..."
diff -b tst_special_atts.cdl $srcdir/ref_tst_special_atts.cdl

View File

@ -84,7 +84,11 @@ else # Non-MINGW Platforms
# Exercise Jira NCF-213 bug fix
# rm -f tst_ncf213.cdl tst_ncf213.nc
../ncgen/ncgen -b -o tst_ncf213.nc $srcdir/ref_tst_ncf213.cdl
./ncdump -s -h tst_ncf213.nc >tst_ncf213.cdl
./ncdump -s -h tst_ncf213.nc \
| sed -e 's/netcdflibversion=.*[|]/netcdflibversion=0.0.0|/' \
| sed -e 's/hdf5libversion=.*"/hdf5libversion=0.0.0"/' \
| sed -e 's|_SuperblockVersion = [0-9]|_SuperblockVersion = 0|' \
| cat >tst_ncf213.cdl
# Now compare
ok=1;
if diff -b $srcdir/ref_tst_ncf213.cdl tst_ncf213.cdl ; then ok=1; else ok=0; fi

View File

@ -745,3 +745,18 @@ nc_inq_grps_full(int rootid, int *numgrps, int *grpids)
nc_free_giter(giter);
return stat;
}
int
getrootid(int grpid)
{
int current = grpid;
int parent = current;
/* see if root id */
for(;;) {
int stat = nc_inq_grp_parent(current,&parent);
if(stat) break;
current = parent;
}
return current;
}

View File

@ -150,6 +150,7 @@ extern int nc_next_giter(ncgiter_t *iterp, int *grpid);
* Release memory allocated for group iterator.
*/
extern void nc_free_giter(ncgiter_t *iterp);
extern int getrootid(int grpid);
#ifdef __cplusplus
}

View File

@ -43,7 +43,7 @@ CLEANFILES = c0.nc c0_64.nc c0_4.nc c0_4c.nc ref_camrun.c \
# autoconf will forcibly delete files of the name *.tab.*
makeparser::
flex -L -Pncg -8 ncgen.l
flex -Pncg -8 ncgen.l
rm -f ncgenl.c
sed -e s/lex.ncg.c/ncgenl.c/g <lex.ncg.c >ncgenl.c
bison -pncg -t -d ncgen.y

View File

@ -177,9 +177,6 @@ void gen_charattr(Datalist*, Bytebuffer*);
void gen_charvlen(Datalist*, Bytebuffer*);
void gen_chararray(struct Dimset*, int, Datalist*, Bytebuffer*, Datalist* fillsrc);
/* Mnemonic */
#define UNKNOWN ((size_t)0)
typedef enum ListClass {
LISTDATA, LISTATTR, LISTVLEN, LISTCOMPOUND, LISTFIELDARRAY
} ListClass;

View File

@ -414,7 +414,7 @@ genc_defineglobalspecials(void)
if(usingclassic) return;
if(!/*Main.*/format_attribute) return;
/* Watch out, this is a global Attribute */
format = kind_string(/*Main.*/format_flag);
format = kind_string(globalspecials._Format);
bbprintf0(stmt,"%sstat = nc_put_att_text(ncid, NC_GLOBAL, \"_Format\", 1, \"%s\");\n",
indented(1),
format);

View File

@ -152,7 +152,6 @@ extern void jflush(void);
/* from: main.c */
extern int k_flag; /* -k value from command line*/
extern int format_flag; /* _Format attribute value (same range as -k flag) */
extern int format_attribute; /* 1 if format came from _FORMAT attribute */
extern int enhanced_flag; /* 1 => netcdf-4 constructs appear in the parse */
extern int cdf5_flag; /* 1 => cdf-5 unsigned types in the parse */
@ -160,6 +159,7 @@ extern int specials_flag; /* 1 => special attributes are present */
extern int usingclassic; /* 1 => k_flag == 1|2|5 */
extern int k_flag;
extern int ncloglevel;
extern GlobalSpecialData globalspecials;
/* Global data */
@ -199,6 +199,6 @@ extern void* emalloc (size_t);
extern void* ecalloc (size_t);
extern void* erealloc(void*,size_t);
extern char* specialname(int flag);
extern const char* specialname(int tag);
#endif /*!NC_GENLIB_H*/

View File

@ -46,6 +46,8 @@
#include "genlib.h"
#include "util.h"
#include "debug.h"
#include "nc.h"
#include "nc4internal.h"
extern int specialconstants;

View File

@ -38,7 +38,6 @@ int header_only;
/* flags for tracking what output format to use */
int k_flag; /* > 0 => -k was specified on command line*/
int format_flag; /* _Format attribute value (same range as -k flag) */
int format_attribute; /* 1=>format came from format attribute */
int enhanced_flag; /* 1 => netcdf-4 */
int cdf5_flag; /* 1 => cdf5 | maybe netcdf-4 */
@ -48,6 +47,8 @@ int cmode_modifier;
int diskless;
int ncloglevel;
GlobalSpecialData globalspecials;
char* binary_ext = ".nc";
size_t nciterbuffersize;
@ -231,7 +232,6 @@ main(
nciterbuffersize = 0;
k_flag = 0;
format_flag = 0;
format_attribute = 0;
enhanced_flag = 0;
cdf5_flag = 0;
@ -242,6 +242,7 @@ main(
#else
ncloglevel = -1;
#endif
memset(&globalspecials,0,sizeof(GlobalSpecialData));
#if _CRAYMPP && 0
/* initialize CRAY MPP parallel-I/O library */
@ -512,7 +513,7 @@ main(
}
if(k_flag == 0)
k_flag = format_flag;
k_flag = globalspecials._Format;
if(cdf5_flag && !enhanced_flag && k_flag == 0)
k_flag = 5;

View File

@ -4,7 +4,7 @@
* Copyright 1993, UCAR/Unidata
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
* $Header: /upc/share/CVS/netcdf-3/ncgen/ncgen.h,v 1.18 2010/06/01 15:34:53 ed Exp $
*********************************************************************/
*********************************************************************/
#ifdef _MSC_VER
#include <float.h>
@ -71,7 +71,7 @@ typedef nc_type nc_subclass;
/*
Define data structure
to hold special attribute values
xto hold special attribute values
for a given variable.
Global values are kept as
various C global variables
@ -79,6 +79,7 @@ various C global variables
/* Define a bit set for indicating which*/
/* specials were explicitly specified*/
/* See also: ncgen.y.tag2name */
#define _STORAGE_FLAG 0x001
#define _CHUNKSIZES_FLAG 0x002
#define _FLETCHER32_FLAG 0x004
@ -87,7 +88,16 @@ various C global variables
#define _ENDIAN_FLAG 0x020
#define _NOFILL_FLAG 0x040
#define _FILLVALUE_FLAG 0x080
#define _FORMAT_FLAG 0x100
#define _NCPROPS_FLAG 0x100
#define _ISNETCDF4_FLAG 0x200
#define _SUPERBLOCK_FLAG 0x400
#define _FORMAT_FLAG 0x800
extern struct Specialtoken {
char* name;
int token;
int tag;
} specials[];
/* Define an enumeration of supported languages */
typedef enum Language {
@ -120,6 +130,13 @@ typedef struct Specialdata {
int _Fill ; /* 0 => false, 1 => true WATCHOUT: this is inverse of NOFILL*/
} Specialdata;
typedef struct GlobalSpecialdata {
int _Format ; /* kflag */
const char* _NCProperties ;
int _IsNetcdf4 ; /* 0 => false, 1 => true */
int _Superblock ; /* HDF5 file superblock version */
} GlobalSpecialData;
/* Track a set of dimensions*/
/* (Note: the netcdf type system is deficient here)*/
typedef struct Dimset {
@ -143,7 +160,7 @@ typedef struct Typeinfo {
nc_type typecode;
unsigned long offset; /* fields in struct*/
unsigned long alignment;/* fields in struct*/
NCConstant econst; /* for enum values*/
NCConstant econst; /* for enum values*/
Dimset dimset; /* for NC_VAR/NC_FIELD/NC_ATT*/
size_t size; /* for opaque, compound, etc.*/
size_t nelems; /* size in terms of # of datalist constants

View File

@ -115,19 +115,19 @@ static int tagmatch(nc_type nct, int tag);
static int nct2lexeme(nc_type nct);
static int collecttag(char* text, char** stagp);
static struct Specialtoken {
char* name;
int token;
} specials[] = {
{"_FillValue",_FILLVALUE},
{"_Format",_FORMAT},
{"_Storage",_STORAGE},
{"_ChunkSizes",_CHUNKSIZES},
{"_Fletcher32",_FLETCHER32},
{"_DeflateLevel",_DEFLATELEVEL},
{"_Shuffle",_SHUFFLE},
{"_Endianness",_ENDIANNESS},
{"_NoFill",_NOFILL},
struct Specialtoken specials[] = {
{"_FillValue",_FILLVALUE,_FILLVALUE_FLAG},
{"_Format",_FORMAT,_FORMAT_FLAG},
{"_Storage",_STORAGE,_STORAGE_FLAG},
{"_ChunkSizes",_CHUNKSIZES,_CHUNKSIZES_FLAG},
{"_Fletcher32",_FLETCHER32,_FLETCHER32_FLAG},
{"_DeflateLevel",_DEFLATELEVEL,_DEFLATE_FLAG},
{"_Shuffle",_SHUFFLE,_SHUFFLE_FLAG},
{"_Endianness",_ENDIANNESS,_ENDIAN_FLAG},
{"_NoFill",_NOFILL,_NOFILL_FLAG},
{"_NCProperties",_NCPROPS,_NCPROPS_FLAG},
{"_IsNetcdf4",_ISNETCDF4,_ISNETCDF4_FLAG},
{"_SuperblockVersion",_SUPERBLOCK,_SUPERBLOCK_FLAG},
{NULL,0} /* null terminate */
};
@ -206,7 +206,7 @@ NUMBER [+-]?[0-9][0-9]*[Uu]?([BbSs]|[Ll]|[Ll][Ll])?
DBLNUMBER [+-]?[0-9]*\.[0-9]*{exp}?[LlDd]?|[+-]?[0-9]*{exp}[LlDd]?
FLTNUMBER [+-]?[0-9]*\.[0-9]*{exp}?[Ff]|[+-]?[0-9]*{exp}[Ff]
SPECIAL "_FillValue"|"_Format"|"_Storage"|"_ChunkSizes"|"_Fletcher32"|"_DeflateLevel"|"_Shuffle"|"_Endianness"|"_NoFill"
SPECIAL "_FillValue"|"_Format"|"_Storage"|"_ChunkSizes"|"_Fletcher32"|"_DeflateLevel"|"_Shuffle"|"_Endianness"|"_NoFill"|"_NCProperties"|"_IsNetcdf4"|"_SuperblockVersion"
USASCII [\x01-\x7F]

View File

@ -69,6 +69,8 @@ char* primtypenames[PRIMNO] = {
"string"
};
static int GLOBAL_SPECIAL = _NCPROPS_FLAG | _ISNETCDF4_FLAG | _SUPERBLOCK_FLAG | _FORMAT_FLAG ;
/*Defined in ncgen.l*/
extern int lineno; /* line number for error messages */
extern Bytebuffer* lextext; /* name or string with escapes removed */
@ -112,6 +114,7 @@ static Symbol* makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int
static int containsfills(Datalist* list);
static void datalistextend(Datalist* dl, NCConstant* con);
static void vercheck(int ncid);
static long long extractint(NCConstant con);
int yylex(void);
@ -185,6 +188,9 @@ NCConstant constant;
_ENDIANNESS
_NOFILL
_FLETCHER32
_NCPROPS
_ISNETCDF4
_SUPERBLOCK
DATASETID
%type <sym> ident typename primtype dimd varspec
@ -438,9 +444,9 @@ dimdeclist: dimdecl
;
dimdecl:
dimd '=' UINT64_CONST
dimd '=' constint
{
$1->dim.declsize = (size_t)uint64_val;
$1->dim.declsize = (size_t)extractint($3);
#ifdef GENDEBUG1
fprintf(stderr,"dimension: %s = %llu\n",$1->name,(unsigned long long)$1->dim.declsize);
#endif
@ -690,6 +696,12 @@ attrdecllist: /*empty*/ {} | attrdecl ';' attrdecllist {} ;
attrdecl:
':' ident '=' datalist
{ $$=makeattribute($2,NULL,NULL,$4,ATTRGLOBAL);}
| ':' _NCPROPS '=' conststring
{$$ = makespecial(_NCPROPS_FLAG,NULL,NULL,(void*)&$4,ATTRGLOBAL);}
| ':' _ISNETCDF4 '=' constbool
{$$ = makespecial(_ISNETCDF4_FLAG,NULL,NULL,(void*)&$4,ATTRGLOBAL);}
| ':' _SUPERBLOCK '=' constint
{$$ = makespecial(_SUPERBLOCK_FLAG,NULL,NULL,(void*)&$4,ATTRGLOBAL);}
| typeref type_var_ref ':' ident '=' datalist
{Symbol* tsym = $1; Symbol* vsym = $2; Symbol* asym = $4;
if(vsym->objectclass == NC_VAR) {
@ -1099,24 +1111,6 @@ basetypefor(nc_type nctype)
return primsymbols[nctype];
}
char*
specialname(int flag)
{
switch (flag) {
case _FILLVALUE_FLAG: return "_FillValue";
case _FORMAT_FLAG: return "_Format";
case _STORAGE_FLAG: return "_Storage";
case _CHUNKSIZES_FLAG: return "_ChunkSizes";
case _FLETCHER32_FLAG: return "_Fletcher32";
case _DEFLATE_FLAG: return "_DeflateLevel";
case _SHUFFLE_FLAG: return "_Shuffle";
case _ENDIAN_FLAG: return "_Endianness";
case _NOFILL_FLAG: return "_NoFill";
default: break;
}
return "<unknown>";
}
static int
truefalse(NCConstant* con, int tag)
{
@ -1153,7 +1147,7 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst)
char* sdata = NULL;
int idata = -1;
if(tag == _FORMAT_FLAG) {
if((GLOBAL_SPECIAL & tag) != 0) {
if(vsym != NULL) {
derror("_Format: must be global attribute");
vsym = NULL;
@ -1180,6 +1174,7 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst)
switch (tag) {
case _FLETCHER32_FLAG:
case _SHUFFLE_FLAG:
case _ISNETCDF4_FLAG:
case _NOFILL_FLAG:
iconst.nctype = (con->nctype == NC_STRING?NC_STRING:NC_INT);
convert1(con,&iconst);
@ -1187,6 +1182,7 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst)
break;
case _FORMAT_FLAG:
case _STORAGE_FLAG:
case _NCPROPS_FLAG:
case _ENDIAN_FLAG:
iconst.nctype = NC_STRING;
convert1(con,&iconst);
@ -1195,6 +1191,7 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst)
else
derror("%s: illegal value",specialname(tag));
break;
case _SUPERBLOCK_FLAG:
case _DEFLATE_FLAG:
iconst.nctype = NC_INT;
convert1(con,&iconst);
@ -1214,12 +1211,12 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst)
/* Watch out: this is a global attribute */
struct Kvalues* kvalue;
int found = 0;
/* Use the table in main.c */
for(kvalue = legalkinds; kvalue->name; kvalue++) {
if(sdata) {
if(strcmp(sdata, kvalue->name) == 0) {
/*Main.*/format_flag = kvalue->k_flag;
globalspecials._Format = kvalue->k_flag;
/*Main.*/format_attribute = 1;
found = 1;
break;
}
@ -1227,13 +1224,17 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst)
}
if(!found)
derror("_Format: illegal value: %s",sdata);
/*Main.*/format_attribute = 1;
} else if((GLOBAL_SPECIAL & tag) != 0) {
if(tag == _ISNETCDF4_FLAG)
globalspecials._IsNetcdf4 = tf;
else if(tag == _SUPERBLOCK_FLAG)
globalspecials._Superblock = idata;
else if(tag == _NCPROPS_FLAG)
globalspecials._NCProperties = strdup(sdata);
} else {
Specialdata* special;
/* Set up special info */
special = &vsym->var.special;
if(tag == _FILLVALUE_FLAG) {
special->_Fillvalue = list;
/* fillvalue must be a single value*/
@ -1293,7 +1294,7 @@ makespecial(int tag, Symbol* vsym, Symbol* tsym, void* data, int isconst)
special->_Fill = (1 - tf); /* negate */
special->flags |= _NOFILL_FLAG;
break;
case _CHUNKSIZES_FLAG: {
case _CHUNKSIZES_FLAG: {
int i;
special->nchunks = list->length;
special->_ChunkSizes = (size_t*)emalloc(sizeof(size_t)*special->nchunks);
@ -1327,17 +1328,21 @@ makeattribute(Symbol* asym,
{
asym->objectclass = NC_ATT;
asym->data = data;
addtogroup(asym);
switch (kind) {
case ATTRVAR:
asym->att.var = vsym;
asym->typ.basetype = tsym;
listpush(attdefs,(void*)asym);
addtogroup(asym);
break;
case ATTRGLOBAL:
asym->att.var = NULL; /* NULL => NC_GLOBAL*/
asym->typ.basetype = tsym;
listpush(gattdefs,(void*)asym);
// If we are adding NCPROPS to root group, then don't.
if(strcmp(NCPROPS,asym->name)!=0 || !currentgroup()->grp.is_root) {
addtogroup(asym);
listpush(gattdefs,(void*)asym);
}
break;
default: PANIC1("unexpected attribute type: %d",kind);
}
@ -1348,6 +1353,24 @@ makeattribute(Symbol* asym,
return asym;
}
static long long
extractint(NCConstant con)
{
switch (con.nctype) {
case NC_BYTE: return (long long)(con.value.int8v);
case NC_SHORT: return (long long)(con.value.int16v);
case NC_INT: return (long long)(con.value.int32v);
case NC_UBYTE: return (long long)(con.value.uint8v);
case NC_USHORT: return (long long)(con.value.uint16v);
case NC_UINT: return (long long)(con.value.uint32v);
case NC_INT64: return (long long)(con.value.int64v);
default:
derror("Not a signed integer type: %d",con.nctype);
break;
}
return 0;
}
static int
containsfills(Datalist* list)
{
@ -1387,6 +1410,17 @@ vercheck(int tid)
}
}
const char*
specialname(int tag)
{
struct Specialtoken* spp = specials;
for(;spp->name;spp++) {
if(spp->tag == tag)
return spp->name;
}
return "<unknown>";
}
/*
Since the arguments are all simple constants,
we can evaluate the function immediately

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,13 @@
/* A Bison parser, made by GNU Bison 2.3. */
/* A Bison parser, made by GNU Bison 3.0.4. */
/* Skeleton interface for Bison's Yacc-like parsers in C
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -16,9 +15,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
@ -33,133 +30,100 @@
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* Tokens. */
#ifndef YY_NCG_NCGEN_TAB_H_INCLUDED
# define YY_NCG_NCGEN_TAB_H_INCLUDED
/* Debug traces. */
#ifndef YYDEBUG
# define YYDEBUG 1
#endif
#if YYDEBUG
extern int ncgdebug;
#endif
/* Token type. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
NC_UNLIMITED_K = 258,
CHAR_K = 259,
BYTE_K = 260,
SHORT_K = 261,
INT_K = 262,
FLOAT_K = 263,
DOUBLE_K = 264,
UBYTE_K = 265,
USHORT_K = 266,
UINT_K = 267,
INT64_K = 268,
UINT64_K = 269,
IDENT = 270,
TERMSTRING = 271,
CHAR_CONST = 272,
BYTE_CONST = 273,
SHORT_CONST = 274,
INT_CONST = 275,
INT64_CONST = 276,
UBYTE_CONST = 277,
USHORT_CONST = 278,
UINT_CONST = 279,
UINT64_CONST = 280,
FLOAT_CONST = 281,
DOUBLE_CONST = 282,
DIMENSIONS = 283,
VARIABLES = 284,
NETCDF = 285,
DATA = 286,
TYPES = 287,
COMPOUND = 288,
ENUM = 289,
OPAQUE = 290,
OPAQUESTRING = 291,
GROUP = 292,
PATH = 293,
FILLMARKER = 294,
NIL = 295,
_FILLVALUE = 296,
_FORMAT = 297,
_STORAGE = 298,
_CHUNKSIZES = 299,
_DEFLATELEVEL = 300,
_SHUFFLE = 301,
_ENDIANNESS = 302,
_NOFILL = 303,
_FLETCHER32 = 304,
DATASETID = 305
};
enum yytokentype
{
NC_UNLIMITED_K = 258,
CHAR_K = 259,
BYTE_K = 260,
SHORT_K = 261,
INT_K = 262,
FLOAT_K = 263,
DOUBLE_K = 264,
UBYTE_K = 265,
USHORT_K = 266,
UINT_K = 267,
INT64_K = 268,
UINT64_K = 269,
IDENT = 270,
TERMSTRING = 271,
CHAR_CONST = 272,
BYTE_CONST = 273,
SHORT_CONST = 274,
INT_CONST = 275,
INT64_CONST = 276,
UBYTE_CONST = 277,
USHORT_CONST = 278,
UINT_CONST = 279,
UINT64_CONST = 280,
FLOAT_CONST = 281,
DOUBLE_CONST = 282,
DIMENSIONS = 283,
VARIABLES = 284,
NETCDF = 285,
DATA = 286,
TYPES = 287,
COMPOUND = 288,
ENUM = 289,
OPAQUE = 290,
OPAQUESTRING = 291,
GROUP = 292,
PATH = 293,
FILLMARKER = 294,
NIL = 295,
_FILLVALUE = 296,
_FORMAT = 297,
_STORAGE = 298,
_CHUNKSIZES = 299,
_DEFLATELEVEL = 300,
_SHUFFLE = 301,
_ENDIANNESS = 302,
_NOFILL = 303,
_FLETCHER32 = 304,
_NCPROPS = 305,
_ISNETCDF4 = 306,
_SUPERBLOCK = 307,
DATASETID = 308
};
#endif
/* Tokens. */
#define NC_UNLIMITED_K 258
#define CHAR_K 259
#define BYTE_K 260
#define SHORT_K 261
#define INT_K 262
#define FLOAT_K 263
#define DOUBLE_K 264
#define UBYTE_K 265
#define USHORT_K 266
#define UINT_K 267
#define INT64_K 268
#define UINT64_K 269
#define IDENT 270
#define TERMSTRING 271
#define CHAR_CONST 272
#define BYTE_CONST 273
#define SHORT_CONST 274
#define INT_CONST 275
#define INT64_CONST 276
#define UBYTE_CONST 277
#define USHORT_CONST 278
#define UINT_CONST 279
#define UINT64_CONST 280
#define FLOAT_CONST 281
#define DOUBLE_CONST 282
#define DIMENSIONS 283
#define VARIABLES 284
#define NETCDF 285
#define DATA 286
#define TYPES 287
#define COMPOUND 288
#define ENUM 289
#define OPAQUE 290
#define OPAQUESTRING 291
#define GROUP 292
#define PATH 293
#define FILLMARKER 294
#define NIL 295
#define _FILLVALUE 296
#define _FORMAT 297
#define _STORAGE 298
#define _CHUNKSIZES 299
#define _DEFLATELEVEL 300
#define _SHUFFLE 301
#define _ENDIANNESS 302
#define _NOFILL 303
#define _FLETCHER32 304
#define DATASETID 305
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 131 "ncgen.y"
union YYSTYPE
{
#line 134 "ncgen.y" /* yacc.c:1909 */
Symbol* sym;
unsigned long size; /* allow for zero size to indicate e.g. UNLIMITED*/
long mark; /* track indices into the sequence*/
int nctype; /* for tracking attribute list type*/
Datalist* datalist;
NCConstant constant;
}
/* Line 1529 of yacc.c. */
#line 158 "ncgen.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#line 117 "ncgeny.h" /* yacc.c:1909 */
};
typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
#endif
extern YYSTYPE ncglval;
int ncgparse (void);
#endif /* !YY_NCG_NCGEN_TAB_H_INCLUDED */

View File

@ -2,14 +2,17 @@
# This shell script runs the ncgen tests.
# $Id: run_tests.sh,v 1.10 2010/04/04 22:06:03 dmh Exp $
set -x
if test "x$srcdir" = x ; then
srcdir="."
srcdir=`pwd`
fi
echo "*** Testing ncgen."
set -e
echo "*** creating classic file c0.nc from c0.cdl..."
ls -l "$srcdir/c0.cdl"
ls -l ./ncgen*
./ncgen -b -o c0.nc $srcdir/c0.cdl
if [ ! -f c0.nc ]; then
echo "Failure."

View File

@ -695,3 +695,17 @@ kind_string(int kind)
}
return NULL;
}
int
getrootid(int grpid)
{
int current = grpid;
int parent = current;
/* see if root id */
for(;;) {
int stat = nc_inq_grp_parent(current,&parent);
if(stat) break;
current = parent;
}
return current;
}

View File

@ -61,6 +61,7 @@ extern int getpadding(int offset, int alignment);
extern void check_err(const int stat, const int line, const char* file);
extern void check_err2(const int stat, const int cdlline, const int line, const char* file);
extern const char* kind_string(int kind);
extern int getrootid(int grpid);
/* Inline functions */
#define isunlimited(dimset,i) ((dimset)->dimsyms[i]->dim.isunlimited)

View File

@ -19,7 +19,8 @@ EXTRA_DIST = ref_nctest_classic.nc ref_nctest_64bit_offset.nc \
compare_test_files.sh run_valgrind_tests.sh CMakeLists.txt
CLEANFILES = nctest_classic.nc nctest_64bit_offset.nc \
nctest_netcdf4.nc test2.nc temp.tmp tst_*.nc
nctest_netcdf4.nc test2.nc temp.tmp tst_*.nc \
nctest_classic.cdl ref_nctest_classic.cdl
# Run nctest and the script that compares the output with the
# reference file.