Tentatively fixed https://github.com/Unidata/netcdf-c/issues/239 but the test needs to be extended.

This commit is contained in:
Ward Fisher 2016-06-10 17:03:08 -06:00
parent f248ef7714
commit 1ebb104f74
3 changed files with 89 additions and 75 deletions

View File

@ -63,7 +63,7 @@ nc4_get_att(int ncid, NC *nc, int varid, const char *name,
BAIL(retval);
#ifdef ENABLE_FILEINFO
if(nc->ext_ncid == ncid && varid == NC_GLOBAL) {
if(nc->ext_ncid == ncid && varid == NC_GLOBAL) {
const char** sp;
for(sp = NC_RESERVED_SPECIAL_LIST;*sp;sp++) {
if(strcmp(name,*sp)==0) {
@ -252,7 +252,7 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
return retval;
#ifdef ENABLE_FILEINFO
if(nc->ext_ncid == ncid && varid == NC_GLOBAL) {
if(nc->ext_ncid == ncid && varid == NC_GLOBAL) {
const char** sp;
for(sp = NC_RESERVED_SPECIAL_LIST;*sp;sp++) {
if(strcmp(name,*sp)==0) {
@ -267,19 +267,19 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
attlist = &grp->att;
else
{
for (var = grp->var; var; var = var->l.next)
if (var->varid == varid)
{
attlist = &var->att;
break;
}
if (!var)
return NC_ENOTVAR;
for (var = grp->var; var; var = var->l.next)
if (var->varid == varid)
{
attlist = &var->att;
break;
}
if (!var)
return NC_ENOTVAR;
}
for (att = *attlist; att; att = att->l.next)
if (!strcmp(att->name, norm_name))
break;
if (!strcmp(att->name, norm_name))
break;
if (!att)
{
@ -297,14 +297,14 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
{
/* For an existing att, if we're not in define mode, the len
must not be greater than the existing len for classic model. */
if (!(h5->flags & NC_INDEF) &&
len * nc4typelen(file_type) > (size_t)att->len * nc4typelen(att->nc_typeid))
{
if (h5->cmode & NC_CLASSIC_MODEL)
return NC_EINDEFINE;
if ((retval = NC4_redef(ncid)))
BAIL(retval);
}
if (!(h5->flags & NC_INDEF) &&
len * nc4typelen(file_type) > (size_t)att->len * nc4typelen(att->nc_typeid))
{
if (h5->cmode & NC_CLASSIC_MODEL)
return NC_EINDEFINE;
if ((retval = NC4_redef(ncid)))
BAIL(retval);
}
}
/* We must have two valid types to continue. */
@ -332,9 +332,9 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
{
LOG((3, "adding attribute %s to the list...", norm_name));
if ((res = nc4_att_list_add(attlist, &att)))
BAIL (res);
BAIL (res);
if (!(att->name = strdup(norm_name)))
return NC_ENOMEM;
return NC_ENOMEM;
}
/* Now fill in the metadata. */
@ -375,72 +375,72 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
/* Fill value must be same type and have exactly one value */
if (att->nc_typeid != var->type_info->nc_typeid)
return NC_EBADTYPE;
return NC_EBADTYPE;
if (att->len != 1)
return NC_EINVAL;
return NC_EINVAL;
/* If we already wrote to the dataset, then return an error. */
if (var->written_to)
return NC_ELATEFILL;
return NC_ELATEFILL;
/* If fill value hasn't been set, allocate space. Of course,
* vlens have to be different... */
if ((retval = nc4_get_typelen_mem(grp->nc4_info, var->type_info->nc_typeid, 0,
&type_size)))
return retval;
&type_size)))
return retval;
/* Already set a fill value? Now I'll have to free the old
* one. Make up your damn mind, would you? */
if (var->fill_value)
{
if (var->type_info->nc_type_class == NC_VLEN)
{
if ((retval = nc_free_vlen(var->fill_value)))
return retval;
}
else if (var->type_info->nc_type_class == NC_STRING)
{
if (*(char **)var->fill_value)
free(*(char **)var->fill_value);
}
free(var->fill_value);
}
{
if (var->type_info->nc_type_class == NC_VLEN)
{
if ((retval = nc_free_vlen(var->fill_value)))
return retval;
}
else if (var->type_info->nc_type_class == NC_STRING)
{
if (*(char **)var->fill_value)
free(*(char **)var->fill_value);
}
free(var->fill_value);
}
/* Allocate space for the fill value. */
if (var->type_info->nc_type_class == NC_VLEN)
size = sizeof(hvl_t);
size = sizeof(hvl_t);
else if (var->type_info->nc_type_class == NC_STRING)
size = sizeof(char *);
size = sizeof(char *);
else
size = type_size;
size = type_size;
if (!(var->fill_value = calloc(1, size)))
return NC_ENOMEM;
return NC_ENOMEM;
/* Copy the fill_value. */
LOG((4, "Copying fill value into metadata for variable %s", var->name));
if (var->type_info->nc_type_class == NC_VLEN)
{
nc_vlen_t *in_vlen = (nc_vlen_t *)data, *fv_vlen = (nc_vlen_t *)(var->fill_value);
{
nc_vlen_t *in_vlen = (nc_vlen_t *)data, *fv_vlen = (nc_vlen_t *)(var->fill_value);
fv_vlen->len = in_vlen->len;
if (!(fv_vlen->p = malloc(size * in_vlen->len)))
return NC_ENOMEM;
memcpy(fv_vlen->p, in_vlen->p, in_vlen->len * size);
}
fv_vlen->len = in_vlen->len;
if (!(fv_vlen->p = malloc(size * in_vlen->len)))
return NC_ENOMEM;
memcpy(fv_vlen->p, in_vlen->p, in_vlen->len * size);
}
else if (var->type_info->nc_type_class == NC_STRING)
{
if(NULL != (*(char **)data))
{
if (!(*(char **)(var->fill_value) = malloc(strlen(*(char **)data) + 1)))
return NC_ENOMEM;
strcpy(*(char **)var->fill_value, *(char **)data);
}
else
{
if(NULL != (*(char **)data))
{
if (!(*(char **)(var->fill_value) = malloc(strlen(*(char **)data) + 1)))
return NC_ENOMEM;
strcpy(*(char **)var->fill_value, *(char **)data);
}
else
*(char **)var->fill_value = NULL;
}
}
else
memcpy(var->fill_value, data, type_size);
memcpy(var->fill_value, data, type_size);
/* Indicate that the fill value was changed, if the variable has already
* been created in the file, so the dataset gets deleted and re-created. */
@ -548,7 +548,7 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name,
return NC_NOERR;
}
/* Learn about an att. All the nc4 nc_inq_ functions just call
/* Learn about an att. All the nc4 nc_inq_ functions just call
* nc4_get_att to get the metadata on an attribute. */
int
NC4_inq_att(int ncid, int varid, const char *name, nc_type *xtypep, size_t *lenp)

View File

@ -607,7 +607,7 @@ nc4_put_vara(NC *nc, int ncid, int varid, const size_t *startp,
BAIL_QUIET(NC_EEDGE);
}
}
/* Now you would think that no one would be crazy enough to write
a scalar dataspace with one of the array function calls, but you
would be wrong. So let's check to see if the dataset is
@ -1119,7 +1119,7 @@ nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp,
else {
#ifdef USE_PARALLEL4 /* Start block contributed by HDF group. */
/* For collective IO read, some processes may not have any element for reading.
Collective requires all processes to participate, so we use H5Sselect_none
Collective requires all processes to participate, so we use H5Sselect_none
for these processes. */
if(var->parallel_access == NC_COLLECTIVE) {
@ -1135,14 +1135,14 @@ nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp,
if (H5Sselect_none(file_spaceid)<0)
BAIL(NC_EHDFERR);
/* Since no element will be selected, we just get the memory space the same as the file space.
*/
if((mem_spaceid = H5Dget_space(var->hdf_datasetid))<0)
BAIL(NC_EHDFERR);
if (H5Sselect_none(mem_spaceid)<0)
BAIL(NC_EHDFERR);
#ifdef EXTRA_TESTS
num_spaces++;
#endif
@ -2139,6 +2139,20 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, nc_bool_t write_dimid)
{
replace_existing_var = NC_TRUE;
var->fill_val_changed = NC_FALSE;
/* If the variable is going to be replaced,
we need to flag any other attributes associated
with the variable as 'dirty', or else
*only* the fill value attribute will be copied over
and the rest will be lost. See:
* https://github.com/Unidata/netcdf-c/issues/239 */
{
NC_ATT_INFO_T *att, **attlist = NULL;
attlist = &var->att;
for(att = *attlist; att; att = att->l.next) {
att->dirty = NC_TRUE;
}
}
}
/* Is this a coordinate var that has already been created in
@ -3899,7 +3913,7 @@ reportobject(int log, hid_t id, unsigned int type)
# define MAXNAME 1024
char name[MAXNAME];
ssize_t len;
const char* typename = NULL;
const char* typename = NULL;
len = H5Iget_name(id, name, MAXNAME);
if(len < 0) return;
@ -3922,7 +3936,7 @@ reportobject(int log, hid_t id, unsigned int type)
#ifdef LOGGING
LOG((0,"Type = %s(%8u) name='%s'",typename,id,name));
#endif
} else {
} else {
fprintf(stderr,"Type = %s(%8u) name='%s'",typename,id,name);
}
}
@ -3947,7 +3961,7 @@ reportopenobjectsT(int log, hid_t fid, int ntypes, unsigned int* otypes)
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++) {
for(t=0;t<ntypes;t++) {
unsigned int ot = otypes[t];
if(ot < 0) break;
ocount = H5Fget_obj_ids(fid,ot,maxobjs,idlist);
@ -3983,7 +3997,7 @@ NC4_hdf5get_superblock(struct NC_HDF5_FILE_INFO* h5, int* idp)
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)
if(H5Pget_version(plist, &super, NULL, NULL, NULL) < 0)
{stat = NC_EHDFERR; goto done;}
if(idp) *idp = (int)super;
done:
@ -4092,7 +4106,7 @@ NC4_walk(hid_t gid, int* countp)
if(strcmp(name,*p) == 0) {
*countp = *countp + 1;
}
}
}
}
H5Aclose(aid);
}

View File

@ -27,14 +27,14 @@
#define ATTVAL "This is a text attribute used for testing."
int
main()
/*! Main function for tst_fill_attr_vanish.c
*
*/
int main()
{
int ncid, dimids[RANK_P], time_id, p_id, test_id;
int ndims, dimids_in[RANK_P];
int test_data[1] = {1};
size_t test_start[1] = {0}, test_count[1] = {1};
int test_fill_val[] = {5};