re: Github issue netcdf-c 300

Modified provenance code to allocate the minimal space
needed for _NCProperties attribute in file.  Basically
required using malloc in the provenance code and in ncdump.
Otherwise should cause no externally visible effects.
Also removed the ENABLE_FILEINFO from configure.ac since
the provenance code is no longer optional.
This commit is contained in:
Dennis Heimbigner 2016-08-08 09:24:19 -06:00
parent ec879abca6
commit 0cf1e2c49f
15 changed files with 99 additions and 119 deletions

View File

@ -1074,14 +1074,6 @@ 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 except if netcdf-4 is off.
IF(ENABLE_NETCDF_4)
OPTION(ENABLE_FILEINFO "Enable FILEINFO." ON)
ELSE()
OPTION(ENABLE_FILEINFO "Enable FILEINFO." OFF)
ENDIF()
MARK_AS_ADVANCED(ENABLE_FILEINFO)
################################
# Option checks
################################

View File

@ -87,7 +87,6 @@ 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

View File

@ -204,21 +204,6 @@ 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

@ -131,10 +131,11 @@ It is strongly recommended that applicable conventions be followed unless there
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 have no
attribute number, so they can only be accessed thru the netcdf-C api
calls via the name. Additionally, these attributes will not be counted
in the number of global attributes in the root group.
global attributes, although only _NCProperties is actually stored in the
file; the others are computed. They are hidden in the sense that they
have no attribute number, so they can only be accessed thru the netcdf-C
API calls via the name. Additionally, these attributes 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. Alternatively, one can use the following API calls to
@ -152,7 +153,6 @@ Using the following API calls will fail.
- nc_del_att
- nc_put_att (and derivatives)
`_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.

View File

@ -102,10 +102,8 @@ 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
@ -322,9 +320,7 @@ 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;
@ -452,12 +448,9 @@ For netcdf4 files, capture state information about the following:
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 */
@ -475,7 +468,6 @@ struct NCFILEINFO {
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;
};
@ -484,11 +476,10 @@ 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*/
extern int NC4_buildpropinfo(struct NCPROPINFO* info,char** propdatap);
/* 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

@ -67,11 +67,8 @@ nc_initialize()
#endif
#ifdef USE_NETCDF4
if((stat = NC4_initialize())) goto done;
#endif /* USE_NETCDF4 */
#ifdef ENABLE_FILEINFO
stat = NC4_fileinfo_init();
#endif
#endif /* USE_NETCDF4 */
done:
return stat;

View File

@ -15,10 +15,8 @@ endif
# This is our output. The netCDF-4 convenience library.
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
nc4file.c nc4grp.c nc4hdf.c nc4internal.c nc4type.c nc4var.c ncfunc.c error4.c \
nc4info.c
EXTRA_DIST=CMakeLists.txt

View File

@ -17,10 +17,8 @@ conditions.
#include "nc4dispatch.h"
#include "ncdispatch.h"
#ifdef ENABLE_FILEINFO
static int nc4_get_att_special(NC_HDF5_FILE_INFO_T*, const char*,
nc_type*, nc_type, size_t*, int*, int, void*);
#endif
int nc4typelen(nc_type type);
@ -62,7 +60,6 @@ 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++) {
@ -71,7 +68,6 @@ nc4_get_att(int ncid, NC *nc, int varid, const char *name,
}
}
}
#endif
/* Find the attribute, if it exists.
<strike>If we don't find it, we are major failures.</strike>
@ -251,7 +247,6 @@ 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++) {
@ -260,7 +255,6 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
}
}
}
#endif
/* Find att, if it exists. */
if (varid == NC_GLOBAL)
@ -877,7 +871,6 @@ 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* filetypep, nc_type mem_type, size_t* lenp,
@ -888,14 +881,21 @@ nc4_get_att_special(NC_HDF5_FILE_INFO_T* h5, const char* name,
return NC_EATTMETA;
if(strcmp(name,NCPROPS)==0) {
char* propdata = NULL;
int stat = NC_NOERR;
int len;
if(h5->fileinfo->propattr.version == 0)
return NC_ENOTATT;
if(mem_type == NC_NAT) mem_type = NC_CHAR;
if(mem_type != NC_CHAR)
return NC_ECHAR;
if(filetypep) *filetypep = NC_CHAR;
if(lenp) *lenp = strlen(h5->fileinfo->propattr.text);
if(data) strcpy((char*)data,h5->fileinfo->propattr.text);
stat = NC4_buildpropinfo(&h5->fileinfo->propattr, &propdata);
if(stat != NC_NOERR) return stat;
len = strlen(propdata);
if(lenp) *lenp = len;
if(data) strncpy((char*)data,propdata,len+1);
free(propdata);
} else if(strcmp(name,ISNETCDF4ATT)==0
|| strcmp(name,SUPERBLOCKATT)==0) {
unsigned long long iv = 0;
@ -922,7 +922,6 @@ nc4_get_att_special(NC_HDF5_FILE_INFO_T* h5, const char* name,
}
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. */

View File

@ -101,15 +101,12 @@ NULL
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,
@ -117,7 +114,6 @@ SUPERBLOCKATT,
NCPROPS,
NULL
};
#endif
/* These are the default chunk cache sizes for HDF5 files created or
* opened with netCDF-4. */
@ -468,10 +464,8 @@ 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;
@ -2355,9 +2349,7 @@ 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;
@ -3094,9 +3086,7 @@ close_netcdf4_file(NC_HDF5_FILE_INFO_T *h5, int abort)
}
#endif
#ifdef ENABLE_FILEINFO
if(h5->fileinfo) free(h5->fileinfo);
#endif
if (H5Fclose(h5->hdfid) < 0)
{

View File

@ -4003,7 +4003,6 @@ reportopenobjects(int log, hid_t fid)
}
#ifdef ENABLE_FILEINFO
int
NC4_hdf5get_libversion(unsigned* major,unsigned* minor,unsigned* release)
{
@ -4076,7 +4075,6 @@ 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;
@ -4147,4 +4145,4 @@ NC4_walk(hid_t gid, int* countp)
return ncstat;
}
#endif

View File

@ -26,7 +26,6 @@ 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));
@ -39,45 +38,28 @@ NC4_fileinfo_init(void)
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)
NC4_properties_parse(struct NCPROPINFO* ncprops, const char* text)
{
int ret = NC_NOERR;
size_t len;
char propdata[NCPROPS_LENGTH]; /* match nc.h struct NCProperties */
char* p;
char* propdata = NULL;
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);
len = strlen(text);
if(len == 0) return NC_NOERR;
propdata = (char*)malloc(len+1);
if(propdata == NULL) return NC_ENOMEM;
memcpy(propdata,text,len+1);
propdata[len] = '\0'; /* guarantee */
/* Walk and fill in ncinfo */
p = propdata;
@ -86,7 +68,7 @@ NC4_properties_parse(struct NCPROPINFO* ncprops)
char* value = NULL;
char* q = strchr(p,'=');
if(q == NULL)
return NC_EINVAL;
{ret = NC_EINVAL; goto done;}
*q++ = '\0';
value = p = q;
q = strchr(p,NCPROPSSEP);
@ -107,7 +89,9 @@ NC4_properties_parse(struct NCPROPINFO* ncprops)
/* Guarantee null term */
ncprops->netcdfver[sizeof(ncprops->netcdfver)-1] = '\0';
ncprops->hdf5ver[sizeof(ncprops->hdf5ver)-1] = '\0';
return NC_NOERR;
done:
if(propdata != NULL) free(propdata);
return ret;
}
static int
@ -116,13 +100,13 @@ 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;
char* text = NULL;
/* Get root group */
grp = h5->root_grp->hdf_grpid; /* get root group */
@ -136,13 +120,14 @@ NC4_get_propattr(NC_HDF5_FILE_INFO_T* h5)
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;}
if(size == 0) goto done;
text = (char*)malloc(size+1);
if(text == NULL)
{ncstat = NC_ENOMEM; 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);
ncstat = NC4_properties_parse(&h5->fileinfo->propattr,text);
herr = 0;
}
done:
@ -150,6 +135,7 @@ done:
if(aspace >= 0) HCHECK((H5Sclose(aspace)));
if(ntype >= 0) HCHECK((H5Tclose(ntype)));
if(atype >= 0) HCHECK((H5Tclose(atype)));
if(text != NULL) free(text);
return ncstat;
}
@ -157,7 +143,6 @@ 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;
@ -171,14 +156,20 @@ NC4_put_propattr(NC_HDF5_FILE_INFO_T* h5)
grp = h5->root_grp->hdf_grpid; /* get root group */
/* See if the NCPROPS attribute exists */
if(H5Aexists(grp,NCPROPS) == 0) { /* Does not exist */
char* text = NULL;
ncstat = NC4_buildpropinfo(&h5->fileinfo->propattr,&text);
if(text == NULL || ncstat != NC_NOERR) {
if(text != NULL) free(text);
goto done;
}
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((H5Tset_cset(atype, H5T_CSET_ASCII)));
HCHECK((H5Tset_size(atype, strlen(text))));
HCHECK((aspace = H5Screate(H5S_SCALAR)));
HCHECK((attid = H5Acreate(grp, NCPROPS, atype, aspace, H5P_DEFAULT)));
HCHECK((H5Awrite(attid, atype, h5->fileinfo->propattr.text)));
HCHECK((H5Awrite(attid, atype, text)));
herr = 0;
}
done:
@ -209,3 +200,40 @@ NC4_get_fileinfo(NC_HDF5_FILE_INFO_T* h5, struct NCPROPINFO* init)
done:
return ncstat;
}
int
NC4_buildpropinfo(struct NCPROPINFO* info,char** propdatap)
{
size_t total;
if(info == NULL || info->version == 0) return NC_EINVAL;
if(propdatap == NULL)
return NC_NOERR;
*propdatap = NULL;
/* compute attribute length */
total = 0;
total += strlen(NCPVERSION);
total += strlen("=00000000");
if(strlen(info->netcdfver) > 0) {
total += 1; /*|NCPROPSEP|*/
total += strlen(NCPNCLIBVERSION);
total += strlen("=");
total += strlen(info->netcdfver);
}
if(strlen(info->hdf5ver) > 0) {
total += 1; /*|NCPROPSEP|*/
total += strlen(NCPHDF5LIBVERSION);
total += strlen("=");
total += strlen(info->hdf5ver);
}
*propdatap = (char*)malloc(total+1);
if(*propdatap == NULL)
return NC_ENOMEM;
snprintf(*propdatap,total+1,
"%s=%d|%s=%s|%s=%s",
NCPVERSION,info->version,
NCPNCLIBVERSION,info->netcdfver,
NCPHDF5LIBVERSION,info->hdf5ver);
return NC_NOERR;
}

View File

@ -59,7 +59,7 @@ IF(ENABLE_TESTS)
TARGET_LINK_LIBRARIES(bom netcdf)
TARGET_LINK_LIBRARIES(tst_dimsizes netcdf)
IF(ENABLE_FILEINFO)
IF(USE_NETCDF4)
ADD_EXECUTABLE(tst_fileinfo tst_fileinfo.c)
TARGET_LINK_LIBRARIES(tst_fileinfo netcdf)
add_sh_test(ncdump tst_fileinfo)

View File

@ -35,7 +35,7 @@ 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
if USE_NETCDF4
check_PROGRAMS += tst_fileinfo
TESTS += tst_fileinfo.sh
endif

View File

@ -763,7 +763,7 @@ pr_att(
ncatt_t att; /* attribute */
NC_CHECK( nc_inq_attname(ncid, varid, ia, att.name) );
#ifdef ENABLE_FILEINFO
#ifdef USE_NETCDF4
if (ncid == getrootid(ncid)
&& varid == NC_GLOBAL
&& strcmp(att.name,NCPROPS)==0)
@ -1074,7 +1074,7 @@ pr_att_specials(
}
#endif /* USE_NETCDF4 */
#ifdef ENABLE_FILEINFO /*=>NETCDF4*/
#ifdef USE_NETCDF4
static void
pr_att_hidden(
int ncid,
@ -1083,7 +1083,6 @@ pr_att_hidden(
{
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)
@ -1091,14 +1090,18 @@ pr_att_hidden(
/* Print out Selected hidden attributes */
/* NCPROPS */
stat = nc_inq_att(ncid,NC_GLOBAL,NCPROPS,NULL,&len);
if(stat == NC_NOERR && len < sizeof(propdata)) {
if(stat == NC_NOERR) {
char* propdata = (char*)malloc(len+1);
if(propdata == NULL)
return;
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';
propdata[len+1] = '\0';
printf(" = \"%s\" ;\n",propdata);
}
free(propdata);
}
/* _SuperblockVersion */
stat = nc_inq_att(ncid,NC_GLOBAL,SUPERBLOCKATT,NULL,&len);
@ -1121,7 +1124,7 @@ pr_att_hidden(
}
}
}
#endif /* ENABLE_FILEINFO */
#endif /* USE_NETCDF4 */
/*
* Print a variable attribute for NcML
@ -1138,7 +1141,7 @@ pr_attx(
int attvalslen = 0;
NC_CHECK( nc_inq_attname(ncid, varid, ia, att.name) );
#ifdef ENABLE_FILEINFO
#ifdef USE_NETCDF4
if (ncid == getrootid(ncid)
&& varid == NC_GLOBAL
&& strcmp(att.name,NCPROPS)==0
@ -1751,7 +1754,7 @@ do_ncdump_rec(int ncid, const char *path)
}
if (is_root && formatting_specs.special_atts) { /* output special attribute
* for format variant */
#ifdef ENABLE_FILEINFO
#ifdef USE_NETCDF4
pr_att_hidden(ncid, kind);
#endif
pr_att_global_format(ncid, kind);

View File

@ -746,11 +746,11 @@ nc_inq_grps_full(int rootid, int *numgrps, int *grpids)
return stat;
}
#ifdef ENABLE_FILEINFO
int
getrootid(int grpid)
{
int current = grpid;
#ifdef USE_NETCDF4
int parent = current;
/* see if root id */
for(;;) {
@ -758,7 +758,7 @@ getrootid(int grpid)
if(stat) break;
current = parent;
}
#endif
return current;
}
#endif