mirror of
https://github.com/Unidata/netcdf-c.git
synced 2025-01-30 16:10:44 +08:00
Tentatively fixed https://github.com/Unidata/netcdf-c/issues/239 but the test needs to be extended.
This commit is contained in:
parent
f248ef7714
commit
1ebb104f74
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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};
|
||||
|
Loading…
Reference in New Issue
Block a user