/** * @internal I think all atts should be named the exact same thing, to * avoid confusion! * * @param ncid File and group ID. * @param varid Variable ID. * @param name Name of attribute. * @param newname New name for attribute. * * @return ::NC_NOERR No error. * @return ::NC_EBADID Bad ncid. * @return ::NC_EMAXNAME New name too long. * @return ::NC_EPERM File is read-only. * @return ::NC_ENAMEINUSE New name already in use. * @return ::NC_ENOTINDEFINE Classic model file not in define mode. * @return ::NC_EHDFERR HDF error. * @return ::NC_ENOMEM Out of memory. * @return ::NC_EINTERNAL Could not rebuild list. * @author Ed Hartnett */ int NC4_rename_att(int ncid, int varid, const char *name, const char *newname) { NC *nc; NC_GRP_INFO_T *grp; NC_FILE_INFO_T *h5; NC_VAR_INFO_T *var = NULL; NC_ATT_INFO_T *att; NCindex *list; char norm_newname[NC_MAX_NAME + 1], norm_name[NC_MAX_NAME + 1]; hid_t datasetid = 0; int retval = NC_NOERR; if (!name || !newname) return NC_EINVAL; LOG((2, "nc_rename_att: ncid 0x%x varid %d name %s newname %s", ncid, varid, name, newname)); /* If the new name is too long, that's an error. */ if (strlen(newname) > NC_MAX_NAME) return NC_EMAXNAME; /* Find info for this file, group, and h5 info. */ if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5))) return retval; assert(h5 && grp && h5); /* If the file is read-only, return an error. */ if (h5->no_write) return NC_EPERM; /* Check and normalize the name. */ if ((retval = nc4_check_name(newname, norm_newname))) return retval; /* Get the list of attributes. */ if ((retval = getattlist(grp, varid, &var, &list))) return retval; /* Is new name in use? */ att = (NC_ATT_INFO_T*)ncindexlookup(list,norm_newname); if(att != NULL) return NC_ENAMEINUSE; /* Normalize name and find the attribute. */ if ((retval = nc4_normalize_name(name, norm_name))) return retval; att = (NC_ATT_INFO_T*)ncindexlookup(list,norm_name); if (!att) return NC_ENOTATT; /* If we're not in define mode, new name must be of equal or less size, if complying with strict NC3 rules. */ if (!(h5->flags & NC_INDEF) && strlen(norm_newname) > strlen(att->hdr.name) && (h5->cmode & NC_CLASSIC_MODEL)) return NC_ENOTINDEFINE; /* Delete the original attribute, if it exists in the HDF5 file. */ if (att->created) { if (varid == NC_GLOBAL) { if (H5Adelete(((NC_HDF5_GRP_INFO_T *)(grp->format_grp_info))->hdf_grpid, att->hdr.name) < 0) return NC_EHDFERR; } else { if ((retval = nc4_open_var_grp2(grp, varid, &datasetid))) return retval; if (H5Adelete(datasetid, att->hdr.name) < 0) return NC_EHDFERR; } att->created = NC_FALSE; } /* Copy the new name into our metadata. */ if(att->hdr.name) free(att->hdr.name); if (!(att->hdr.name = strdup(norm_newname))) return NC_ENOMEM; att->hdr.hashkey = NC_hashmapkey(att->hdr.name,strlen(att->hdr.name)); /* Fix hash key */ att->dirty = NC_TRUE; /* Rehash the attribute list so that the new name is used */ if(!ncindexrebuild(list)) return NC_EINTERNAL; /* Mark attributes on variable dirty, so they get written */ if(var) var->attr_dirty = NC_TRUE; return retval; }
static int find_var_dim_max_length(NC_GRP_INFO_T *grp, int varid, int dimid, size_t *maxlen) { hid_t datasetid = 0, spaceid = 0; NC_VAR_INFO_T *var; hsize_t *h5dimlen = NULL, *h5dimlenmax = NULL; int d, dataset_ndims = 0; int retval = NC_NOERR; *maxlen = 0; /* Find this var. */ for (var = grp->var; var; var = var->l.next) if (var->varid == varid) break; if (!var) return NC_ENOTVAR; /* If the var hasn't been created yet, its size is 0. */ if (!var->created) { *maxlen = 0; } else { /* Get the number of records in the dataset. */ if ((retval = nc4_open_var_grp2(grp, var->varid, &datasetid))) BAIL(retval); if ((spaceid = H5Dget_space(datasetid)) < 0) BAIL(NC_EHDFERR); #ifdef EXTRA_TESTS num_spaces++; #endif /* If it's a scalar dataset, it has length one. */ if (H5Sget_simple_extent_type(spaceid) == H5S_SCALAR) { *maxlen = (var->dimids && var->dimids[0] == dimid) ? 1 : 0; } else { /* Check to make sure ndims is right, then get the len of each dim in the space. */ if ((dataset_ndims = H5Sget_simple_extent_ndims(spaceid)) < 0) BAIL(NC_EHDFERR); if (dataset_ndims != var->ndims) BAIL(NC_EHDFERR); if (!(h5dimlen = malloc(dataset_ndims * sizeof(hsize_t)))) BAIL(NC_ENOMEM); if (!(h5dimlenmax = malloc(dataset_ndims * sizeof(hsize_t)))) BAIL(NC_ENOMEM); if ((dataset_ndims = H5Sget_simple_extent_dims(spaceid, h5dimlen, h5dimlenmax)) < 0) BAIL(NC_EHDFERR); LOG((5, "find_var_dim_max_length: varid %d len %d max: %d", varid, (int)h5dimlen[0], (int)h5dimlenmax[0])); for (d=0; d<dataset_ndims; d++) { if (var->dimids[d] == dimid) { *maxlen = *maxlen > h5dimlen[d] ? *maxlen : h5dimlen[d]; } } } } exit: if (spaceid > 0 && H5Sclose(spaceid) < 0) BAIL2(NC_EHDFERR); #ifdef EXTRA_TESTS num_spaces--; #endif if (h5dimlen) free(h5dimlen); if (h5dimlenmax) free(h5dimlenmax); return retval; }
/* I think all atts should be named the exact same thing, to avoid confusion! */ int NC4_rename_att(int ncid, int varid, const char *name, const char *newname) { NC *nc; NC_GRP_INFO_T *grp; NC_HDF5_FILE_INFO_T *h5; NC_VAR_INFO_T *var; NC_ATT_INFO_T *att, *list; char norm_newname[NC_MAX_NAME + 1], norm_name[NC_MAX_NAME + 1]; hid_t datasetid = 0; int retval = NC_NOERR; if (!name || !newname) return NC_EINVAL; LOG((2, "nc_rename_att: ncid 0x%x varid %d name %s newname %s", ncid, varid, name, newname)); /* If the new name is too long, that's an error. */ if (strlen(newname) > NC_MAX_NAME) return NC_EMAXNAME; /* Find metadata for this file. */ if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5))) return retval; assert(h5 && grp); /* If the file is read-only, return an error. */ if (h5->no_write) return NC_EPERM; #if 0 /*def USE_PNETCDF*/ /* Take care of files created/opened with parallel-netcdf library. */ if (h5->pnetcdf_file) return ncmpi_rename_att(nc->int_ncid, varid, name, newname); #endif /* USE_PNETCDF */ /* Check and normalize the name. */ if ((retval = nc4_check_name(newname, norm_newname))) return retval; /* Is norm_newname in use? */ if (varid == NC_GLOBAL) { list = grp->att; } else { for (var = grp->var; var; var = var->l.next) if (var->varid == varid) { list = var->att; break; } if (!var) return NC_ENOTVAR; } for (att = list; att; att = att->l.next) if (!strncmp(att->name, norm_newname, NC_MAX_NAME)) return NC_ENAMEINUSE; /* Normalize name and find the attribute. */ if ((retval = nc4_normalize_name(name, norm_name))) return retval; for (att = list; att; att = att->l.next) if (!strncmp(att->name, norm_name, NC_MAX_NAME)) break; if (!att) return NC_ENOTATT; /* If we're not in define mode, new name must be of equal or less size, if complying with strict NC3 rules. */ if (!(h5->flags & NC_INDEF) && strlen(norm_newname) > strlen(att->name) && (h5->cmode & NC_CLASSIC_MODEL)) return NC_ENOTINDEFINE; /* Delete the original attribute, if it exists in the HDF5 file. */ if (att->created) { if (varid == NC_GLOBAL) { if (H5Adelete(grp->hdf_grpid, att->name) < 0) return NC_EHDFERR; } else { if ((retval = nc4_open_var_grp2(grp, varid, &datasetid))) return retval; if (H5Adelete(datasetid, att->name) < 0) return NC_EHDFERR; } att->created = NC_FALSE; } /* Copy the new name into our metadata. */ free(att->name); if (!(att->name = malloc((strlen(norm_newname) + 1) * sizeof(char)))) return NC_ENOMEM; strcpy(att->name, norm_newname); att->dirty = NC_TRUE; return retval; }