mirror of
https://github.com/Unidata/netcdf-c.git
synced 2025-04-06 18:00:24 +08:00
Classic Format Specification says: Header padding uses null (\x00) bytes
This commit is contained in:
parent
3889617a2a
commit
340f0d2a91
@ -301,11 +301,11 @@ static int
|
||||
v1h_get_NC_string(v1hs *gsp, NC_string **ncstrpp)
|
||||
{
|
||||
int status;
|
||||
size_t nchars = 0;
|
||||
size_t padding, nchars = 0;
|
||||
NC_string *ncstrp;
|
||||
|
||||
status = v1h_get_size_t(gsp, &nchars);
|
||||
if(status != NC_NOERR)
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
|
||||
ncstrp = new_NC_string(nchars, NULL);
|
||||
@ -314,7 +314,6 @@ v1h_get_NC_string(v1hs *gsp, NC_string **ncstrpp)
|
||||
return NC_ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* assert(ncstrp->nchars == nchars || ncstrp->nchars - nchars < X_ALIGN); */
|
||||
assert(ncstrp->nchars % X_ALIGN == 0);
|
||||
@ -323,22 +322,33 @@ v1h_get_NC_string(v1hs *gsp, NC_string **ncstrpp)
|
||||
|
||||
status = check_v1hs(gsp, _RNDUP(ncstrp->nchars, X_ALIGN));
|
||||
#endif
|
||||
if(status != NC_NOERR)
|
||||
if(status != NC_NOERR)
|
||||
goto unwind_alloc;
|
||||
|
||||
status = ncx_pad_getn_text((const void **)(&gsp->pos),
|
||||
nchars, ncstrp->cp);
|
||||
if(status != NC_NOERR)
|
||||
if(status != NC_NOERR)
|
||||
goto unwind_alloc;
|
||||
|
||||
padding = _RNDUP(X_SIZEOF_CHAR * ncstrp->nchars, X_ALIGN)
|
||||
- X_SIZEOF_CHAR * ncstrp->nchars;
|
||||
if (padding > 0) {
|
||||
/* CDF specification: Header padding uses null (\x00) bytes. */
|
||||
char pad[X_ALIGN-1];
|
||||
memset(pad, 0, X_ALIGN-1);
|
||||
if (memcmp((char*)gsp->pos-padding, pad, padding) != 0) {
|
||||
free_NC_string(ncstrp);
|
||||
return NC_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
*ncstrpp = ncstrp;
|
||||
|
||||
return NC_NOERR;
|
||||
return NC_NOERR;
|
||||
|
||||
unwind_alloc:
|
||||
free_NC_string(ncstrp);
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
/* End NC_string */
|
||||
@ -575,6 +585,28 @@ ncx_len_NC_attr(const NC_attr *attrp, int version)
|
||||
#undef MIN
|
||||
#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn))
|
||||
|
||||
/*----< ncmpix_len_nctype() >------------------------------------------------*/
|
||||
/* return the length of external data type */
|
||||
static int
|
||||
ncmpix_len_nctype(nc_type type) {
|
||||
switch(type) {
|
||||
case NC_BYTE:
|
||||
case NC_CHAR:
|
||||
case NC_UBYTE: return X_SIZEOF_CHAR;
|
||||
case NC_SHORT: return X_SIZEOF_SHORT;
|
||||
case NC_USHORT: return X_SIZEOF_USHORT;
|
||||
case NC_INT: return X_SIZEOF_INT;
|
||||
case NC_UINT: return X_SIZEOF_UINT;
|
||||
case NC_FLOAT: return X_SIZEOF_FLOAT;
|
||||
case NC_DOUBLE: return X_SIZEOF_DOUBLE;
|
||||
case NC_INT64: return X_SIZEOF_INT64;
|
||||
case NC_UINT64: return X_SIZEOF_UINT64;
|
||||
default: fprintf(stderr,"ncmpix_len_nctype bad type %d\n",type);
|
||||
assert(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put the values of an attribute
|
||||
* The loop is necessary since attrp->nelems
|
||||
@ -587,7 +619,7 @@ v1h_put_NC_attrV(v1hs *psp, const NC_attr *attrp)
|
||||
const size_t perchunk = psp->extent;
|
||||
size_t remaining = attrp->xsz;
|
||||
void *value = attrp->xvalue;
|
||||
size_t nbytes;
|
||||
size_t nbytes, padding;
|
||||
|
||||
assert(psp->extent % X_ALIGN == 0);
|
||||
|
||||
@ -595,18 +627,24 @@ v1h_put_NC_attrV(v1hs *psp, const NC_attr *attrp)
|
||||
nbytes = MIN(perchunk, remaining);
|
||||
|
||||
status = check_v1hs(psp, nbytes);
|
||||
if(status != NC_NOERR)
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
|
||||
(void) memcpy(psp->pos, value, nbytes);
|
||||
|
||||
psp->pos = (void *)((signed char *)psp->pos + nbytes);
|
||||
value = (void *)((signed char *)value + nbytes);
|
||||
remaining -= nbytes;
|
||||
remaining -= nbytes;
|
||||
|
||||
} while(remaining != 0);
|
||||
|
||||
return NC_NOERR;
|
||||
padding = attrp->xsz - ncmpix_len_nctype(attrp->type) * attrp->nelems;
|
||||
if (padding > 0) {
|
||||
/* CDF specification: Header padding uses null (\x00) bytes. */
|
||||
memset((char*)psp->pos-padding, 0, padding);
|
||||
}
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
/* Write a NC_attr to the header */
|
||||
@ -647,24 +685,33 @@ v1h_get_NC_attrV(v1hs *gsp, NC_attr *attrp)
|
||||
const size_t perchunk = gsp->extent;
|
||||
size_t remaining = attrp->xsz;
|
||||
void *value = attrp->xvalue;
|
||||
size_t nget;
|
||||
size_t nget, padding;
|
||||
|
||||
do {
|
||||
nget = MIN(perchunk, remaining);
|
||||
|
||||
status = check_v1hs(gsp, nget);
|
||||
if(status != NC_NOERR)
|
||||
if(status != NC_NOERR)
|
||||
return status;
|
||||
|
||||
(void) memcpy(value, gsp->pos, nget);
|
||||
gsp->pos = (void *)((signed char *)gsp->pos + nget);
|
||||
value = (void *)((signed char *)value + nget);
|
||||
|
||||
remaining -= nget;
|
||||
remaining -= nget;
|
||||
|
||||
} while(remaining != 0);
|
||||
|
||||
return NC_NOERR;
|
||||
padding = attrp->xsz - ncmpix_len_nctype(attrp->type) * attrp->nelems;
|
||||
if (padding > 0) {
|
||||
/* CDF specification: Header padding uses null (\x00) bytes. */
|
||||
char pad[X_ALIGN-1];
|
||||
memset(pad, 0, X_ALIGN-1);
|
||||
if (memcmp((char*)gsp->pos-padding, pad, (size_t)padding) != 0)
|
||||
return NC_EINVAL;
|
||||
}
|
||||
|
||||
return NC_NOERR;
|
||||
}
|
||||
|
||||
|
||||
|
@ -156,7 +156,7 @@ main(int argc, char *argv[])
|
||||
/* Initialize global variables defining test file */
|
||||
init_gvars();
|
||||
|
||||
/* Write the test file, needed for the read-only tests below. */
|
||||
/* Write the test file, needed for the read-only tests below. */
|
||||
write_file(testfile);
|
||||
|
||||
/* delete any existing scratch netCDF file */
|
||||
@ -355,6 +355,8 @@ main(int argc, char *argv[])
|
||||
NC_TEST(nc_copy_att);
|
||||
NC_TEST(nc_rename_att);
|
||||
NC_TEST(nc_del_att);
|
||||
NC_TEST(nc_against_pnetcdf);
|
||||
/* keep below the last test, as it changes the default file format */
|
||||
NC_TEST(nc_set_default_format);
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ dnl
|
||||
* Copyright (C) 2003, Northwestern University and Argonne National Laboratory
|
||||
* See COPYRIGHT notice in top-level directory.
|
||||
*/
|
||||
/* $Id: test_put.m4 2630 2016-11-17 06:35:10Z wkliao $ */
|
||||
/* $Id: test_put.m4 2655 2016-11-25 21:03:48Z wkliao $ */
|
||||
|
||||
dnl
|
||||
dnl The command-line m4 macro "PNETCDF" is to differentiate PnetCDF and netCDF
|
||||
@ -112,11 +112,11 @@ define(`HASH',dnl
|
||||
* ensure hash value within range for internal TYPE
|
||||
*/
|
||||
$1
|
||||
hash_$1(const int cdf_format,
|
||||
const nc_type type,
|
||||
const int rank,
|
||||
const IntType *index,
|
||||
const nct_itype itype)
|
||||
hash_$1(const int cdf_format,
|
||||
const nc_type type,
|
||||
const int rank,
|
||||
const IntType *index,
|
||||
const nct_itype itype)
|
||||
{
|
||||
double value;
|
||||
|
||||
|
@ -10,7 +10,7 @@ dnl
|
||||
* Copyright (C) 2003, Northwestern University and Argonne National Laboratory
|
||||
* See COPYRIGHT notice in top-level directory.
|
||||
*/
|
||||
/* $Id: test_read.m4 2616 2016-11-14 09:19:14Z wkliao $ */
|
||||
/* $Id: test_read.m4 2640 2016-11-18 21:08:08Z wkliao $ */
|
||||
|
||||
dnl
|
||||
dnl The command-line m4 macro "PNETCDF" is to differentiate PnetCDF and netCDF
|
||||
@ -20,9 +20,11 @@ dnl types.
|
||||
dnl
|
||||
|
||||
#include <sys/types.h> /* open() */
|
||||
#include <sys/stat.h> /* open() */
|
||||
#include <fcntl.h> /* open() */
|
||||
#include <unistd.h> /* unlink(), write() */
|
||||
#include <sys/stat.h> /* open() */
|
||||
#include <fcntl.h> /* open() */
|
||||
#include <unistd.h> /* unlink(), write() */
|
||||
#include <errno.h> /* errno, strerror() */
|
||||
|
||||
#include "tests.h"
|
||||
|
||||
define(`EXPECT_ERR',`error("expecting $1 but got %s",nc_err_code_name($2));')dnl
|
||||
@ -168,9 +170,14 @@ ifdef(`PNETCDF',
|
||||
ifdef(`PNETCDF', ``#'if 1', ``#'if 0')
|
||||
/* create a not-nc file */
|
||||
fd = open(NOT_NC_FILE, O_CREAT|O_WRONLY, 0600);
|
||||
w_len = write(fd, "0123456789abcdefghijklmnopqrstuvwxyz", 36);
|
||||
assert(w_len >= 0);
|
||||
close(fd);
|
||||
IF (fd == -1) {
|
||||
error("Error: creating a non-CDF file (%s)", strerror(errno));
|
||||
}
|
||||
else {
|
||||
w_len = write(fd, "0123456789abcdefghijklmnopqrstuvwxyz", 36);
|
||||
assert(w_len >= 0);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* Open a file that is not a netCDF file. */
|
||||
err = FileOpen(NOT_NC_FILE, NC_NOWRITE, &ncid); /* should fail */
|
||||
|
@ -10,7 +10,7 @@ dnl
|
||||
* Copyright (C) 2003, Northwestern University and Argonne National Laboratory
|
||||
* See COPYRIGHT notice in top-level directory.
|
||||
*/
|
||||
/* $Id: test_write.m4 2633 2016-11-17 22:06:42Z wkliao $ */
|
||||
/* $Id: test_write.m4 2655 2016-11-25 21:03:48Z wkliao $ */
|
||||
|
||||
dnl
|
||||
dnl The command-line m4 macro "PNETCDF" is to differentiate PnetCDF and netCDF
|
||||
@ -179,14 +179,16 @@ TestFunc(redef)(AttVarArgs)
|
||||
error("close: %s", APIFunc(strerror)(err));
|
||||
|
||||
/* tests using scratch file */
|
||||
err = FileCreate(scratch, NC_NOCLOBBER, &ncid);
|
||||
ifdef(`PNETCDF',`dnl
|
||||
err = FileCreate(scratch, NC_NOCLOBBER, &ncid);',`dnl
|
||||
err = file__create(scratch, NC_NOCLOBBER, 0, &sizehint, &ncid);')
|
||||
IF (err != NC_NOERR) {
|
||||
error("create: %s", APIFunc(strerror)(err));
|
||||
return nok;
|
||||
}
|
||||
ifdef(`PNETCDF',,`dnl
|
||||
/* limit for ncio implementations which have infinite chunksize */
|
||||
if(sizehint > 32768)
|
||||
sizehint = 16384;
|
||||
if(sizehint > 32768) sizehint = 16384;')
|
||||
def_dims(ncid);
|
||||
Def_Vars(ncid, numVars);
|
||||
Put_Atts(ncid, numGatts, numVars);
|
||||
@ -2380,18 +2382,17 @@ APIFunc(get_file_version)(char *path, int *version)
|
||||
if (fd == -1) return errno;
|
||||
|
||||
read_len = read(fd, magic, MAGIC_NUM_LEN);
|
||||
if (read_len == -1) {
|
||||
close(fd);
|
||||
if (-1 == close(fd)) return errno;
|
||||
|
||||
if (read_len == -1)
|
||||
return errno;
|
||||
}
|
||||
|
||||
if (read_len != MAGIC_NUM_LEN) {
|
||||
printf("Error: reading NC magic string unexpected short read\n");
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strncmp(magic, "CDF", MAGIC_NUM_LEN-1)==0)
|
||||
{
|
||||
if (strncmp(magic, "CDF", MAGIC_NUM_LEN-1)==0) {
|
||||
if (magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CLASSIC ||
|
||||
magic[MAGIC_NUM_LEN-1] == NC_FORMAT_64BIT_OFFSET ||
|
||||
magic[MAGIC_NUM_LEN-1] == NC_FORMAT_CDF5)
|
||||
@ -2457,11 +2458,13 @@ TestFunc(set_default_format)(void)
|
||||
if (err != NC_NOERR)
|
||||
error("bad file version = %d", err);
|
||||
if (version != i) {
|
||||
#if 0
|
||||
if (i == 4) {
|
||||
if (version == 3) continue;
|
||||
printf("expect version 3 but got %d (file=%s)",version,scratch);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
printf("expect version %d but got %d (file=%s)",i,version,scratch);
|
||||
error("bad file version = %d", version);
|
||||
}
|
||||
|
@ -480,6 +480,7 @@ extern int test_nc_rename_att(void);
|
||||
extern int test_nc_del_att(void);
|
||||
extern int test_nc_set_fill(void);
|
||||
extern int test_nc_set_default_format(void);
|
||||
extern int test_nc_against_pnetcdf(void);
|
||||
|
||||
void print_nok(int nok);
|
||||
|
||||
@ -565,6 +566,8 @@ void check_file(char *filename);
|
||||
|
||||
int file_create(const char *filename, int cmode, int *ncid);
|
||||
|
||||
int file__create(const char *filename, int cmode, size_t initialsz, size_t *bufrsizehintp, int *ncid);
|
||||
|
||||
int file_open(const char *filename, int omode, int *ncid);
|
||||
|
||||
char* nc_err_code_name(int err);
|
||||
|
@ -1016,9 +1016,9 @@ check_vars(int ncid)
|
||||
IF (err)
|
||||
error("nc_get_var1_text: %s", nc_strerror(err));
|
||||
IF (text != (char)expect) {
|
||||
error("Var %s value read 0x%02x not that expected 0x%02x ",
|
||||
var_name[i], text, (char)expect);
|
||||
print_n_size_t(var_rank[i], index);
|
||||
error("Var %s [%lu] value read %hhd not that expected %g ",
|
||||
var_name[i], j, text, expect);
|
||||
print_n_size_t(var_rank[i], index);
|
||||
} else {
|
||||
nok++;
|
||||
}
|
||||
@ -1029,10 +1029,8 @@ check_vars(int ncid)
|
||||
error("nc_get_var1_double: %s", nc_strerror(err));
|
||||
} else {
|
||||
IF (!equal(value,expect,var_type[i], NCT_DOUBLE)) {
|
||||
value = 0;
|
||||
err = nc_get_var1_double(ncid, i, index, &value);
|
||||
error("Var %s value read % 12.5e not that expected % 12.7e ",
|
||||
var_name[i], value, expect);
|
||||
error("Var %s [%lu] value read %g not that expected %g ",
|
||||
var_name[i], j, value, expect);
|
||||
print_n_size_t(var_rank[i], index);
|
||||
} else {
|
||||
nok++;
|
||||
@ -1156,13 +1154,13 @@ int file_create(const char *filename, int cmode, int *ncid)
|
||||
{
|
||||
int err;
|
||||
|
||||
#ifdef USE_PNETCDF
|
||||
/* get the default file format */
|
||||
int default_format;
|
||||
nc_set_default_format(NC_FORMAT_CLASSIC, &default_format);
|
||||
/* set it back to the default */
|
||||
nc_set_default_format(default_format, NULL);
|
||||
|
||||
#ifdef USE_PNETCDF
|
||||
if (default_format == NC_FORMAT_CLASSIC ||
|
||||
default_format == NC_FORMAT_64BIT_OFFSET ||
|
||||
default_format == NC_FORMAT_64BIT_DATA)
|
||||
@ -1174,17 +1172,43 @@ int file_create(const char *filename, int cmode, int *ncid)
|
||||
return err;
|
||||
}
|
||||
|
||||
int file_open(const char *filename, int omode, int *ncid)
|
||||
int file__create(const char *filename,
|
||||
int cmode,
|
||||
size_t initialsz,
|
||||
size_t *bufrsizehintp,
|
||||
int *ncid)
|
||||
{
|
||||
int err;
|
||||
|
||||
#ifdef USE_PNETCDF
|
||||
/* get the default file format */
|
||||
int default_format;
|
||||
err = nc_set_default_format(NC_FORMAT_CLASSIC, &default_format);
|
||||
/* set it back to the default */
|
||||
err = nc_set_default_format(default_format, NULL);
|
||||
|
||||
if (default_format == NC_FORMAT_CLASSIC ||
|
||||
default_format == NC_FORMAT_64BIT_OFFSET ||
|
||||
default_format == NC_FORMAT_64BIT_DATA)
|
||||
err = nc_create_par(filename, cmode|NC_PNETCDF, MPI_COMM_WORLD, MPI_INFO_NULL, ncid);
|
||||
else
|
||||
#endif
|
||||
err = nc__create(filename, cmode, initialsz, bufrsizehintp, ncid);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int file_open(const char *filename, int omode, int *ncid)
|
||||
{
|
||||
int err;
|
||||
|
||||
#ifdef USE_PNETCDF
|
||||
/* get the default file format */
|
||||
int default_format;
|
||||
err = nc_set_default_format(NC_FORMAT_CLASSIC, &default_format);
|
||||
/* set it back to the default */
|
||||
err = nc_set_default_format(default_format, NULL);
|
||||
|
||||
if (default_format == NC_FORMAT_CLASSIC ||
|
||||
default_format == NC_FORMAT_64BIT_OFFSET ||
|
||||
default_format == NC_FORMAT_64BIT_DATA)
|
||||
@ -1379,3 +1403,57 @@ char* nc_err_code_name(int err)
|
||||
return unknown_str;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
test_nc_against_pnetcdf(void)
|
||||
{
|
||||
#ifdef USE_PNETCDF
|
||||
int ncid; /* netCDF id */
|
||||
int err; /* status */
|
||||
|
||||
/* Using netCDF library to create file */
|
||||
err = nc_create(scratch, NC_CLOBBER, &ncid);
|
||||
IF (err != NC_NOERR) error("nc_create: %s", nc_strerror(err));
|
||||
def_dims(ncid);
|
||||
def_vars(ncid);
|
||||
put_atts(ncid);
|
||||
err = nc_enddef(ncid);
|
||||
IF (err != NC_NOERR) error("nc_enddef: %s", nc_strerror(err));
|
||||
put_vars(ncid);
|
||||
err = nc_close (ncid);
|
||||
IF (err != NC_NOERR) error("nc_close: %s", nc_strerror(err));
|
||||
|
||||
/* Using PnetCDF library to check file */
|
||||
err = nc_open_par(scratch, NC_NOWRITE|NC_PNETCDF, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid);
|
||||
IF (err != NC_NOERR) error("nc_open_par: %s", nc_strerror(err));
|
||||
check_dims(ncid);
|
||||
check_vars(ncid);
|
||||
check_atts(ncid);
|
||||
err = nc_close (ncid);
|
||||
IF (err != NC_NOERR) error("nc_close: %s", nc_strerror(err));
|
||||
|
||||
/* Using PnetCDF library to create file */
|
||||
err = nc_create_par(scratch, NC_PNETCDF, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid);
|
||||
IF (err != NC_NOERR) error("nc_create_par: %s", nc_strerror(err));
|
||||
def_dims(ncid);
|
||||
def_vars(ncid);
|
||||
put_atts(ncid);
|
||||
err = nc_enddef(ncid);
|
||||
IF (err != NC_NOERR) error("nc_enddef: %s", nc_strerror(err));
|
||||
put_vars(ncid);
|
||||
err = nc_close (ncid);
|
||||
IF (err != NC_NOERR) error("nc_close: %s", nc_strerror(err));
|
||||
|
||||
/* Using NetCDF library to check file */
|
||||
err = nc_open(scratch, NC_NOWRITE, &ncid);
|
||||
IF (err != NC_NOERR) error("nc_open: %s", nc_strerror(err));
|
||||
check_dims(ncid);
|
||||
check_vars(ncid);
|
||||
check_atts(ncid);
|
||||
err = nc_close (ncid);
|
||||
IF (err != NC_NOERR) error("nc_close: %s", nc_strerror(err));
|
||||
err = nc_delete(scratch);
|
||||
IF (err != NC_NOERR) error("remove of %s failed", scratch);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user