Corrected an issue with netcdf3 files that would prevent the -v and -V flags from working properly when using nccopy. See https://github.com/Unidata/netcdf-c/issues/425 and https://github.com/Unidata/netcdf-c/issues/463 for more information.

This commit is contained in:
Ward Fisher 2017-08-31 16:16:21 -06:00
parent 2bf1f68cf7
commit a95a7c18bb

View File

@ -1,7 +1,7 @@
/*********************************************************************
* Copyright 2010, University Corporation for Atmospheric Research
* See netcdf/README file for copying and redistribution conditions.
* Thanks to Philippe Poilbarbe and Antonio S. Cofiño for
* Thanks to Philippe Poilbarbe and Antonio S. Cofiño for
* compression additions.
* $Id: nccopy.c 400 2010-08-27 21:02:52Z russ $
*********************************************************************/
@ -241,14 +241,14 @@ inq_var_chunking_params(int igrp, int ivarid, int ogrp, int ovarid,
/* Forward declaration, because copy_type, copy_vlen_type call each other */
static int copy_type(int igrp, nc_type typeid, int ogrp);
/*
/*
* copy a user-defined variable length type in the group igrp to the
* group ogrp
*/
static int
copy_vlen_type(int igrp, nc_type itype, int ogrp)
{
int stat = NC_NOERR;
int stat = NC_NOERR;
nc_type ibasetype;
nc_type obasetype; /* base type in target group */
char name[NC_MAX_NAME];
@ -275,13 +275,13 @@ copy_vlen_type(int igrp, nc_type itype, int ogrp)
return stat;
}
/*
/*
* copy a user-defined opaque type in the group igrp to the group ogrp
*/
static int
copy_opaque_type(int igrp, nc_type itype, int ogrp)
{
int stat = NC_NOERR;
int stat = NC_NOERR;
nc_type otype;
char name[NC_MAX_NAME];
size_t size;
@ -292,13 +292,13 @@ copy_opaque_type(int igrp, nc_type itype, int ogrp)
return stat;
}
/*
/*
* copy a user-defined enum type in the group igrp to the group ogrp
*/
static int
copy_enum_type(int igrp, nc_type itype, int ogrp)
{
int stat = NC_NOERR;
int stat = NC_NOERR;
nc_type otype;
nc_type basetype;
size_t basesize;
@ -317,13 +317,13 @@ copy_enum_type(int igrp, nc_type itype, int ogrp)
return stat;
}
/*
/*
* copy a user-defined compound type in the group igrp to the group ogrp
*/
static int
copy_compound_type(int igrp, nc_type itype, int ogrp)
{
int stat = NC_NOERR;
int stat = NC_NOERR;
char name[NC_MAX_NAME];
size_t size;
size_t nfields;
@ -351,7 +351,7 @@ copy_compound_type(int igrp, nc_type itype, int ogrp)
} else { /* field is array type */
int *fdimsizes;
fdimsizes = (int *) emalloc((fndims + 1) * sizeof(int));
stat = nc_inq_compound_field(igrp, itype, fid, NULL, NULL, NULL,
stat = nc_inq_compound_field(igrp, itype, fid, NULL, NULL, NULL,
NULL, fdimsizes);
NC_CHECK(nc_insert_array_compound(ogrp, otype, fname, foff, oftype, fndims, fdimsizes));
free(fdimsizes);
@ -361,13 +361,13 @@ copy_compound_type(int igrp, nc_type itype, int ogrp)
}
/*
/*
* copy a user-defined type in the group igrp to the group ogrp
*/
static int
copy_type(int igrp, nc_type typeid, int ogrp)
{
int stat = NC_NOERR;
int stat = NC_NOERR;
nc_type type_class;
NC_CHECK(nc_inq_user_type(igrp, typeid, NULL, NULL, NULL, NULL, &type_class));
@ -422,7 +422,7 @@ copy_groups(int iroot, int oroot)
NC_CHECK(nc_inq_grpname_full(grpids[i], &len_name, grpname_full));
/* Make sure, the parent group is also wanted (root group is always wanted) */
NC_CHECK(nc_inq_parid(iroot, grpname_full, &iparid));
if (!option_grpstruct && !group_wanted(iparid, option_nlgrps, option_grpids)
if (!option_grpstruct && !group_wanted(iparid, option_nlgrps, option_grpids)
&& iparid != iroot) {
error("ERROR: trying to copy a group but not the parent: %s", grpname_full);
}
@ -439,17 +439,17 @@ copy_groups(int iroot, int oroot)
}
free(grpids);
}
return stat;
return stat;
}
/*
/*
* Copy the user-defined types in this group (igrp) and all its
* subgroups, recursively, to corresponding group in output (ogrp)
*/
static int
copy_types(int igrp, int ogrp)
{
int stat = NC_NOERR;
int stat = NC_NOERR;
int ntypes;
nc_type *types = NULL;
int numgrps;
@ -501,7 +501,7 @@ copy_var_specials(int igrp, int varid, int ogrp, int o_varid)
size_t *chunkp = (size_t *) emalloc(ndims * sizeof(size_t));
int *dimids = (int *) emalloc(ndims * sizeof(int));
int idim;
/* size of a chunk: product of dimension chunksizes and size of value */
/* size of a chunk: product of dimension chunksizes and size of value */
size_t csprod = val_size(ogrp, o_varid);
int is_unlimited = 0;
NC_CHECK(nc_inq_var_chunking(igrp, varid, &contig, chunkp));
@ -610,7 +610,7 @@ set_var_chunked(int ogrp, int o_varid)
size_t dimlen;
NC_CHECK(nc_inq_dimlen(ogrp, odimid, &dimlen));
if( (chunksize > 0) || dimmap_ounlim(odimid)) {
chunked = 1;
chunked = 1;
}
if(dimlen > 0) { /* dimlen for unlimited dims is still 0 before copying data */
varsize *= dimlen;
@ -702,7 +702,7 @@ copy_dims(int igrp, int ogrp)
int *unlimids;
#else
int unlimid;
#endif /* USE_NETCDF4 */
#endif /* USE_NETCDF4 */
NC_CHECK(nc_inq_ndims(igrp, &ndims));
@ -739,7 +739,7 @@ copy_dims(int igrp, int ogrp)
if(idimid == unlimids[uld]) {
i_is_unlim = 1;
break;
}
}
}
#else
idimid = dgrp;
@ -751,7 +751,7 @@ copy_dims(int igrp, int ogrp)
stat = nc_inq_dim(igrp, idimid, name, &length);
if (stat == NC_EDIMSIZE && sizeof(size_t) < 8) {
error("dimension \"%s\" requires 64-bit platform", name);
}
}
NC_CHECK(stat);
o_is_unlim = i_is_unlim;
if(i_is_unlim && !option_fix_unlimdims) {
@ -766,7 +766,7 @@ copy_dims(int igrp, int ogrp)
#ifdef USE_NETCDF4
free(dimids);
free(unlimids);
#endif /* USE_NETCDF4 */
#endif /* USE_NETCDF4 */
return stat;
}
@ -781,7 +781,7 @@ copy_atts(int igrp, int ivar, int ogrp, int ovar)
int stat = NC_NOERR;
NC_CHECK(nc_inq_varnatts(igrp, ivar, &natts));
for(iatt = 0; iatt < natts; iatt++) {
char name[NC_MAX_NAME];
NC_CHECK(nc_inq_attname(igrp, ivar, iatt, name));
@ -832,7 +832,7 @@ copy_var(int igrp, int varid, int ogrp)
NC_CHECK(nc_def_var(ogrp, name, o_typeid, ndims, odimids, &o_varid));
/* attach the variable attributes to the output variable */
NC_CHECK(copy_atts(igrp, varid, ogrp, o_varid));
#ifdef USE_NETCDF4
#ifdef USE_NETCDF4
{
int inkind;
int outkind;
@ -879,7 +879,7 @@ copy_vars(int igrp, int ogrp)
if(nc_inq_gvarid(igrp, option_lvars[iv], &varid) == NC_NOERR)
idadd(vlist, varid);
}
NC_CHECK(nc_inq_nvars(igrp, &nvars));
for (varid = 0; varid < nvars; varid++) {
if (!option_varstruct && option_nlvars > 0 && ! idmember(vlist, varid))
@ -894,7 +894,7 @@ copy_vars(int igrp, int ogrp)
* group igrp in input to parent group ogrp in destination. Use
* dimmap array to map input dimids to output dimids. */
static int
copy_schema(int igrp, int ogrp)
copy_schema(int igrp, int ogrp)
{
int stat = NC_NOERR;
int ogid; /* like igrp but in output file */
@ -906,7 +906,7 @@ copy_schema(int igrp, int ogrp)
NC_CHECK(copy_dims(igrp, ogid));
NC_CHECK(copy_atts(igrp, NC_GLOBAL, ogid, NC_GLOBAL));
NC_CHECK(copy_vars(igrp, ogid));
#ifdef USE_NETCDF4
#ifdef USE_NETCDF4
{
int numgrps;
int *grpids;
@ -915,7 +915,7 @@ copy_schema(int igrp, int ogrp)
stat = nc_inq_grps(igrp, &numgrps, NULL);
grpids = (int *)emalloc((numgrps + 1) * sizeof(int));
NC_CHECK(nc_inq_grps(igrp, &numgrps, grpids));
for(i = 0; i < numgrps; i++) {
if (option_grpstruct || group_wanted(grpids[i], option_nlgrps, option_grpids)) {
NC_CHECK(copy_schema(grpids[i], ogid));
@ -924,7 +924,7 @@ copy_schema(int igrp, int ogrp)
free(grpids);
}
#endif /* USE_NETCDF4 */
return stat;
return stat;
}
/* Return number of values for a variable varid in a group igrp */
@ -966,7 +966,7 @@ copy_var_data(int igrp, int varid, int ogrp) {
size_t *count;
nciter_t *iterp; /* opaque structure for iteration status */
int do_realloc = 0;
#ifdef USE_NETCDF4
#ifdef USE_NETCDF4
int okind;
size_t chunksize;
#endif
@ -983,10 +983,10 @@ copy_var_data(int igrp, int varid, int ogrp) {
option_copy_buffer_size = value_size;
do_realloc = 1;
}
#ifdef USE_NETCDF4
#ifdef USE_NETCDF4
NC_CHECK(nc_inq_format(ogrp, &okind));
if(okind == NC_FORMAT_NETCDF4 || okind == NC_FORMAT_NETCDF4_CLASSIC) {
/* if this variable chunked, set variable chunk cache size */
/* if this variable chunked, set variable chunk cache size */
int contig = 1;
NC_CHECK(nc_inq_var_chunking(ogrp, ovarid, &contig, NULL));
if(contig == 0) { /* chunked */
@ -997,16 +997,16 @@ copy_var_data(int igrp, int varid, int ogrp) {
size_t chunkcache_size, chunkcache_nelems;
float chunkcache_preemption;
NC_CHECK(inq_var_chunking_params(igrp, varid, ogrp, ovarid,
&chunkcache_size,
&chunkcache_nelems,
&chunkcache_size,
&chunkcache_nelems,
&chunkcache_preemption));
NC_CHECK(nc_set_var_chunk_cache(ogrp, ovarid,
chunkcache_size,
chunkcache_nelems,
chunkcache_preemption));
} else {
NC_CHECK(nc_set_var_chunk_cache(ogrp, ovarid,
chunkcache_size,
chunkcache_nelems,
chunkcache_preemption));
} else {
/* by default, use same chunk cache for all chunked variables */
NC_CHECK(nc_set_var_chunk_cache(ogrp, ovarid,
NC_CHECK(nc_set_var_chunk_cache(ogrp, ovarid,
option_chunk_cache_size,
option_chunk_cache_nelems,
COPY_CHUNKCACHE_PREEMPTION));
@ -1098,11 +1098,11 @@ copy_data(int igrp, int ogrp)
if(nc_inq_gvarid(igrp, option_lvars[iv], &varid) == NC_NOERR)
idadd(vlist, varid);
}
/* get groupid in output corresponding to group igrp in input,
* given parent group (or root group) ogrp in output */
NC_CHECK(get_grpid(igrp, ogrp, &ogid));
/* Copy data from this group */
NC_CHECK(nc_inq_nvars(igrp, &nvars));
@ -1145,7 +1145,7 @@ count_dims(int ncid) {
for(igrp = 0; igrp < numgrps; igrp++) {
ndims += count_dims(grpids[igrp]);
}
free(grpids);
free(grpids);
}
#endif /* USE_NETCDF4 */
return ndims;
@ -1200,20 +1200,36 @@ classify_vars(
int **rvars) /* the array of record variable IDs, caller should free */
{
int varid;
int varindex = 0;
int nvars;
NC_CHECK(nc_inq_nvars(ncid, &nvars));
*nf = 0;
*fvars = (int *) emalloc(nvars * sizeof(int));
*nr = 0;
*rvars = (int *) emalloc(nvars * sizeof(int));
for (varid = 0; varid < nvars; varid++) {
if (isrecvar(ncid, varid)) {
(*rvars)[*nr] = varid;
(*nr)++;
} else {
(*fvars)[*nf] = varid;
(*nf)++;
}
if(option_nlvars > 0) {
for (varindex = 0; varindex < option_nlvars; varindex++) {
nc_inq_varid(ncid,option_lvars[varindex],&varid);
if (isrecvar(ncid, varid)) {
(*rvars)[*nr] = varid;
(*nr)++;
} else {
(*fvars)[*nf] = varid;
(*nf)++;
}
}
} else {
for (varid = 0; varid < nvars; varid++) {
if (isrecvar(ncid, varid)) {
(*rvars)[*nr] = varid;
(*nr)++;
} else {
(*fvars)[*nf] = varid;
(*nf)++;
}
}
}
return NC_NOERR;
}
@ -1242,7 +1258,7 @@ copy_rec_var_data(int ncid, /* input */
size_t *start, /* start indices for record data */
size_t *count, /* edge lengths for record data */
void *buf /* buffer large enough to hold data */
)
)
{
NC_CHECK(nc_get_vara(ncid, varid, start, count, buf));
NC_CHECK(nc_put_vara(ogrp, ovarid, start, count, buf));
@ -1292,7 +1308,7 @@ copy_record_data(int ncid, int ogrp, size_t nrec_vars, int *rec_varids) {
start[ivar][ii] = 0;
count[ivar][ii] = dimlen;
}
start[ivar][0] = 0;
start[ivar][0] = 0;
count[ivar][0] = 1; /* 1 record */
buf[ivar] = (void *) emalloc(nvals * value_size);
NC_CHECK(nc_inq_varname(ncid, varid, varname));
@ -1308,7 +1324,7 @@ copy_record_data(int ncid, int ogrp, size_t nrec_vars, int *rec_varids) {
varid = rec_varids[ivar];
ovarid = rec_ovarids[ivar];
start[ivar][0] = irec;
NC_CHECK(copy_rec_var_data(ncid, ogrp, irec, varid, ovarid,
NC_CHECK(copy_rec_var_data(ncid, ogrp, irec, varid, ovarid,
start[ivar], count[ivar], buf[ivar]));
}
}
@ -1358,11 +1374,11 @@ copy(char* infile, char* outfile)
/* option_kind specifies which netCDF format for output, one of
*
* SAME_AS_INPUT, NC_FORMAT_CLASSIC, NC_FORMAT_64BIT,
* NC_FORMAT_NETCDF4, NC_FORMAT_NETCDF4_CLASSIC
* SAME_AS_INPUT, NC_FORMAT_CLASSIC, NC_FORMAT_64BIT,
* NC_FORMAT_NETCDF4, NC_FORMAT_NETCDF4_CLASSIC
*
* However, if compression or shuffling was specified and kind was SAME_AS_INPUT,
* option_kind is changed to NC_FORMAT_NETCDF4_CLASSIC, if input format is
* option_kind is changed to NC_FORMAT_NETCDF4_CLASSIC, if input format is
* NC_FORMAT_CLASSIC or NC_FORMAT_64BIT .
*/
outkind = option_kind;
@ -1370,11 +1386,11 @@ copy(char* infile, char* outfile)
outkind = inkind;
/* Deduce output kind if netCDF-4 features requested */
if (inkind == NC_FORMAT_CLASSIC || inkind == NC_FORMAT_64BIT_OFFSET
|| inkind == NC_FORMAT_CDF5) {
if (option_deflate_level > 0 ||
option_shuffle_vars == NC_SHUFFLE ||
option_chunkspec)
{
|| inkind == NC_FORMAT_CDF5) {
if (option_deflate_level > 0 ||
option_shuffle_vars == NC_SHUFFLE ||
option_chunkspec)
{
outkind = NC_FORMAT_NETCDF4_CLASSIC;
}
}
@ -1467,7 +1483,7 @@ copy(char* infile, char* outfile)
NC_CHECK(classify_vars(ogrp, &nfixed_vars, &fixed_varids, &nrec_vars, &rec_varids));
NC_CHECK(copy_fixed_size_data(igrp, ogrp, nfixed_vars, fixed_varids));
NC_CHECK(copy_record_data(igrp, ogrp, nrec_vars, rec_varids));
} else {
} else {
NC_CHECK(copy_data(igrp, ogrp)); /* recursive, to handle nested groups */
}
@ -1476,7 +1492,7 @@ copy(char* infile, char* outfile)
return stat;
}
/*
/*
* For non-negative numeric string with multiplier suffix K, M, G, T,
* or P (or lower-case equivalent), return corresponding value
* incorporating multiplier 1000, 1000000, 1.0d9, ... 1.0d15, or -1.0
@ -1509,7 +1525,7 @@ double_with_suffix(char *str) {
break;
default:
dval = -1.0; /* error, suffix multiplier must be K, M, G, or T */
}
}
}
return dval;
}
@ -1565,13 +1581,13 @@ main(int argc, char**argv)
{"classic", NC_FORMAT_CLASSIC}, /* canonical format name */
{"nc3", NC_FORMAT_CLASSIC}, /* short format name */
{"1", NC_FORMAT_CLASSIC}, /* deprecated, use "-3" or "-k nc3" instead */
/* NetCDF-3 64-bit offset format */
{"64-bit offset", NC_FORMAT_64BIT_OFFSET}, /* canonical format name */
{"nc6", NC_FORMAT_64BIT_OFFSET}, /* short format name */
{"2", NC_FORMAT_64BIT_OFFSET}, /* deprecated, use "-6" or "-k nc6" instead */
{"64-bit-offset", NC_FORMAT_64BIT_OFFSET}, /* deprecated alias */
/* NetCDF-4 HDF5-based format */
{"netCDF-4", NC_FORMAT_NETCDF4}, /* canonical format name */
{"nc4", NC_FORMAT_NETCDF4}, /* short format name */
@ -1611,7 +1627,7 @@ main(int argc, char**argv)
while ((c = getopt(argc, argv, "k:3467d:sum:c:h:e:rwxg:G:v:V:")) != -1) {
switch(c) {
case 'k': /* for specifying variant of netCDF format to be generated
case 'k': /* for specifying variant of netCDF format to be generated
Format names:
"classic" or "nc3"
"64-bit offset" or "nc6"
@ -1724,7 +1740,7 @@ main(int argc, char**argv)
make_lvars (optarg, &option_nlvars, &option_lvars);
option_varstruct = false;
break;
default:
default:
usage();
}
}