/* Copyright 2005-2018, University Corporation for Atmospheric * Research. See COPYRIGHT file for copying and redistribution * conditions. */ /** * @file @internal This file is part of netcdf-4, a netCDF-like * interface for HDF5, or a HDF5 backend for netCDF, depending on your * point of view. * * This file handles HDF5 groups. * * @author Ed Hartnett */ #include "config.h" #include "hdf5internal.h" /** * @internal Create a group. Its ncid is returned in the new_ncid * pointer. * * @param parent_ncid Parent group. * @param name Name of new group. * @param new_ncid Pointer that gets ncid for new group. * * @return ::NC_NOERR No error. * @return ::NC_EBADID Bad ncid. * @return ::NC_ESTRICTNC3 Classic model in use for this file. * @return ::NC_ENOTNC4 Not a netCDF-4 file. * @author Ed Hartnett */ int NC4_def_grp(int parent_ncid, const char *name, int *new_ncid) { NC_GRP_INFO_T *grp, *g; NC_FILE_INFO_T *h5; char norm_name[NC_MAX_NAME + 1]; int retval; LOG((2, "%s: parent_ncid 0x%x name %s", __func__, parent_ncid, name)); /* Find info for this file and group, and set pointer to each. */ if ((retval = nc4_find_grp_h5(parent_ncid, &grp, &h5))) return retval; assert(h5); /* Check and normalize the name. */ if ((retval = nc4_check_name(name, norm_name))) return retval; /* Check that this name is not in use as a var, grp, or type. */ if ((retval = nc4_check_dup_name(grp, norm_name))) return retval; /* No groups in netcdf-3! */ if (h5->cmode & NC_CLASSIC_MODEL) return NC_ESTRICTNC3; /* If it's not in define mode, switch to define mode. */ if (!(h5->flags & NC_INDEF)) if ((retval = NC4_redef(parent_ncid))) return retval; /* Update internal lists to reflect new group. The actual HDF5 * group creation will be done when metadata is written by a * sync. */ if ((retval = nc4_grp_list_add(h5, grp, norm_name, &g))) return retval; if (!(g->format_grp_info = calloc(1, sizeof(NC_HDF5_GRP_INFO_T)))) return NC_ENOMEM; /* For new groups, there are no atts to read from file. */ g->atts_read = 1; /* Return the ncid to the user. */ if (new_ncid) *new_ncid = grp->nc4_info->controller->ext_ncid | g->hdr.id; return NC_NOERR; } /** * @internal Rename a group. * * @param grpid Group ID. * @param name New name for group. * * @return ::NC_NOERR No error. * @return ::NC_EBADID Bad ncid. * @return ::NC_ENOTNC4 Not a netCDF-4 file. * @return ::NC_EPERM File opened read-only. * @return ::NC_EBADGRPID Renaming root forbidden. * @return ::NC_EHDFERR HDF5 function returned error. * @return ::NC_ENOMEM Out of memory. * @author Ed Hartnett */ int NC4_rename_grp(int grpid, const char *name) { NC_GRP_INFO_T *grp; NC_HDF5_GRP_INFO_T *hdf5_grp; NC_FILE_INFO_T *h5; char norm_name[NC_MAX_NAME + 1]; int retval; LOG((2, "nc_rename_grp: grpid 0x%x name %s", grpid, name)); /* Find info for this file and group, and set pointer to each. */ if ((retval = nc4_find_grp_h5(grpid, &grp, &h5))) return retval; assert(h5 && grp && grp->format_grp_info); /* Get HDF5-specific group info. */ hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->format_grp_info; if (h5->no_write) return NC_EPERM; /* attempt to write to a read-only file */ /* Do not allow renaming the root group */ if (grp->parent == NULL) return NC_EBADGRPID; /* Check and normalize the name. */ if ((retval = nc4_check_name(name, norm_name))) return retval; /* Check that this name is not in use as a var, grp, or type in the * parent group (i.e. the group that grp is in). */ if ((retval = nc4_check_dup_name(grp->parent, norm_name))) return retval; /* If it's not in define mode, switch to define mode. */ if (!(h5->flags & NC_INDEF)) if ((retval = NC4_redef(grpid))) return retval; /* Rename the group, if it exists in the file */ if (hdf5_grp->hdf_grpid) { NC_HDF5_GRP_INFO_T *parent_hdf5_grp; parent_hdf5_grp = (NC_HDF5_GRP_INFO_T *)grp->parent->format_grp_info; /* Close the group */ if (H5Gclose(hdf5_grp->hdf_grpid) < 0) return NC_EHDFERR; hdf5_grp->hdf_grpid = 0; /* Attempt to rename & re-open the group, if the parent group is open */ if (parent_hdf5_grp->hdf_grpid) { /* Rename the group. */ if (H5Lmove(parent_hdf5_grp->hdf_grpid, grp->hdr.name, parent_hdf5_grp->hdf_grpid, name, H5P_DEFAULT, H5P_DEFAULT) < 0) return NC_EHDFERR; /* Reopen the group, with the new name. */ if ((hdf5_grp->hdf_grpid = H5Gopen2(parent_hdf5_grp->hdf_grpid, name, H5P_DEFAULT)) < 0) return NC_EHDFERR; } } /* Give the group its new name in metadata. UTF8 normalization * has been done. */ free(grp->hdr.name); if (!(grp->hdr.name = strdup(norm_name))) return NC_ENOMEM; /* Update the hash and rebuild index. */ grp->hdr.hashkey = NC_hashmapkey(grp->hdr.name,strlen(grp->hdr.name)); if(!ncindexrebuild(grp->parent->children)) return NC_EINTERNAL; return NC_NOERR; }