mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-11-27 07:30:33 +08:00
176 lines
5.3 KiB
C
176 lines
5.3 KiB
C
/* 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;
|
|
}
|