NetCDF  4.6.0
nc4grp.c
Go to the documentation of this file.
1 /* Copyright 2005-2018, University Corporation for Atmospheric
2  * Research. See COPYRIGHT file for copying and redistribution
3  * conditions. */
14 #include "nc4internal.h"
15 #include "nc4dispatch.h"
16 
31 int
32 NC4_def_grp(int parent_ncid, const char *name, int *new_ncid)
33 {
34  NC_GRP_INFO_T *grp;
35  NC_HDF5_FILE_INFO_T *h5;
36  char norm_name[NC_MAX_NAME + 1];
37  int retval;
38 
39  LOG((2, "%s: parent_ncid 0x%x name %s", __func__, parent_ncid, name));
40 
41  /* Find info for this file and group, and set pointer to each. */
42  if ((retval = nc4_find_grp_h5(parent_ncid, &grp, &h5)))
43  return retval;
44  assert(h5);
45 
46  /* Check and normalize the name. */
47  if ((retval = nc4_check_name(name, norm_name)))
48  return retval;
49 
50  /* Check that this name is not in use as a var, grp, or type. */
51  if ((retval = nc4_check_dup_name(grp, norm_name)))
52  return retval;
53 
54  /* No groups in netcdf-3! */
55  if (h5->cmode & NC_CLASSIC_MODEL)
56  return NC_ESTRICTNC3;
57 
58  /* If it's not in define mode, switch to define mode. */
59  if (!(h5->flags & NC_INDEF))
60  if ((retval = NC4_redef(parent_ncid)))
61  return retval;
62 
63  /* Update internal lists to reflect new group. The actual HDF5
64  * group creation will be done when metadata is written by a
65  * sync. */
66  if ((retval = nc4_grp_list_add(&(grp->children), h5->next_nc_grpid,
67  grp, grp->nc4_info->controller, norm_name, NULL)))
68  return retval;
69  if (new_ncid)
70  *new_ncid = grp->nc4_info->controller->ext_ncid | h5->next_nc_grpid;
71  h5->next_nc_grpid++;
72 
73  return NC_NOERR;
74 }
75 
91 int
92 NC4_rename_grp(int grpid, const char *name)
93 {
94  NC_GRP_INFO_T *grp;
95  NC_HDF5_FILE_INFO_T *h5;
96  char norm_name[NC_MAX_NAME + 1];
97  int retval;
98 
99  LOG((2, "nc_rename_grp: grpid 0x%x name %s", grpid, name));
100 
101  /* Find info for this file and group, and set pointer to each. */
102  if ((retval = nc4_find_grp_h5(grpid, &grp, &h5)))
103  return retval;
104  assert(h5);
105 
106  if (h5->no_write)
107  return NC_EPERM; /* attempt to write to a read-only file */
108 
109  /* Do not allow renaming the root group */
110  if (grp->parent == NULL)
111  return NC_EBADGRPID;
112 
113  /* Check and normalize the name. */
114  if ((retval = nc4_check_name(name, norm_name)))
115  return retval;
116 
117  /* Check that this name is not in use as a var, grp, or type in the
118  * parent group (i.e. the group that grp is in). */
119  if ((retval = nc4_check_dup_name(grp->parent, norm_name)))
120  return retval;
121 
122  /* If it's not in define mode, switch to define mode. */
123  if (!(h5->flags & NC_INDEF))
124  if ((retval = NC4_redef(grpid)))
125  return retval;
126 
127  /* Rename the group, if it exists in the file */
128  if (grp->hdf_grpid)
129  {
130  /* Close the group */
131  if (H5Gclose(grp->hdf_grpid) < 0)
132  return NC_EHDFERR;
133  grp->hdf_grpid = 0;
134 
135  /* Attempt to rename & re-open the group, if the parent group is open */
136  if (grp->parent->hdf_grpid)
137  {
138  /* Rename the group */
139  if (H5Gmove(grp->parent->hdf_grpid, grp->name, name) < 0)
140  return NC_EHDFERR;
141 
142  /* Reopen the group, with the new name */
143  if ((grp->hdf_grpid = H5Gopen2(grp->parent->hdf_grpid, name, H5P_DEFAULT)) < 0)
144  return NC_EHDFERR;
145  }
146  }
147 
148  /* Give the group its new name in metadata. UTF8 normalization
149  * has been done. */
150  free(grp->name);
151  if (!(grp->name = malloc((strlen(norm_name) + 1) * sizeof(char))))
152  return NC_ENOMEM;
153  strcpy(grp->name, norm_name);
154 
155  return NC_NOERR;
156 }
157 
172 int
173 NC4_inq_ncid(int ncid, const char *name, int *grp_ncid)
174 {
175  NC_GRP_INFO_T *grp, *g;
176  NC_HDF5_FILE_INFO_T *h5;
177  char norm_name[NC_MAX_NAME + 1];
178  int retval;
179 
180  LOG((2, "nc_inq_ncid: ncid 0x%x name %s", ncid, name));
181 
182  /* Find info for this file and group, and set pointer to each. */
183  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
184  return retval;
185  assert(h5);
186 
187  /* Normalize name. */
188  if ((retval = nc4_normalize_name(name, norm_name)))
189  return retval;
190 
191  /* Look through groups for one of this name. */
192  for (g = grp->children; g; g = g->l.next)
193  if (!strcmp(norm_name, g->name)) /* found it! */
194  {
195  if (grp_ncid)
196  *grp_ncid = grp->nc4_info->controller->ext_ncid | g->nc_grpid;
197  return NC_NOERR;
198  }
199 
200  /* If we got here, we didn't find the named group. */
201  return NC_ENOGRP;
202 }
203 
216 int
217 NC4_inq_grps(int ncid, int *numgrps, int *ncids)
218 {
219  NC_GRP_INFO_T *grp, *g;
220  NC_HDF5_FILE_INFO_T *h5;
221  int num = 0;
222  int retval;
223 
224  LOG((2, "nc_inq_grps: ncid 0x%x", ncid));
225 
226  /* Find info for this file and group, and set pointer to each. */
227  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
228  return retval;
229  assert(h5);
230 
231  /* Count the number of groups in this group. */
232  for (g = grp->children; g; g = g->l.next)
233  {
234  if (ncids)
235  {
236  /* Combine the nc_grpid in a bitwise or with the ext_ncid,
237  * which allows the returned ncid to carry both file and
238  * group information. */
239  *ncids = g->nc_grpid | g->nc4_info->controller->ext_ncid;
240  ncids++;
241  }
242  num++;
243  }
244 
245  if (numgrps)
246  *numgrps = num;
247 
248  return NC_NOERR;
249 }
250 
262 int
263 NC4_inq_grpname(int ncid, char *name)
264 {
265  NC_GRP_INFO_T *grp;
266  NC_HDF5_FILE_INFO_T *h5;
267  int retval;
268 
269  LOG((2, "nc_inq_grpname: ncid 0x%x", ncid));
270 
271  /* Find info for this file and group, and set pointer to each. */
272  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
273  return retval;
274  assert(h5);
275 
276  /* Copy the name. */
277  if (name)
278  strcpy(name, grp->name);
279 
280  return NC_NOERR;
281 }
282 
298 int
299 NC4_inq_grpname_full(int ncid, size_t *lenp, char *full_name)
300 {
301  char *name, grp_name[NC_MAX_NAME + 1];
302  int g, id = ncid, parent_id, *gid;
303  int i, ret = NC_NOERR;
304 
305  /* How many generations? */
306  for (g = 0; !NC4_inq_grp_parent(id, &parent_id); g++, id = parent_id)
307  ;
308 
309  /* Allocate storage. */
310  if (!(name = malloc((g + 1) * (NC_MAX_NAME + 1) + 1)))
311  return NC_ENOMEM;
312  if (!(gid = malloc((g + 1) * sizeof(int))))
313  {
314  free(name);
315  return NC_ENOMEM;
316  }
317  assert(name && gid);
318 
319  /* Always start with a "/" for the root group. */
320  strcpy(name, "/");
321 
322  /* Get the ncids for all generations. */
323  gid[0] = ncid;
324  for (i = 1; i < g && !ret; i++)
325  ret = NC4_inq_grp_parent(gid[i - 1], &gid[i]);
326 
327  /* Assemble the full name. */
328  for (i = g - 1; !ret && i >= 0 && !ret; i--)
329  {
330  if ((ret = NC4_inq_grpname(gid[i], grp_name)))
331  break;
332  strcat(name, grp_name);
333  if (i)
334  strcat(name, "/");
335  }
336 
337  /* Give the user the length of the name, if he wants it. */
338  if (!ret && lenp)
339  *lenp = strlen(name);
340 
341  /* Give the user the name, if he wants it. */
342  if (!ret && full_name)
343  strcpy(full_name, name);
344 
345  free(gid);
346  free(name);
347 
348  return ret;
349 }
350 
365 int
366 NC4_inq_grp_parent(int ncid, int *parent_ncid)
367 {
368  NC_GRP_INFO_T *grp;
369  NC_HDF5_FILE_INFO_T *h5;
370  int retval;
371 
372  LOG((2, "nc_inq_grp_parent: ncid 0x%x", ncid));
373 
374  /* Find info for this file and group. */
375  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
376  return retval;
377  assert(h5);
378 
379  /* Set the parent ncid, if there is one. */
380  if (grp->parent)
381  {
382  if (parent_ncid)
383  *parent_ncid = grp->nc4_info->controller->ext_ncid | grp->parent->nc_grpid;
384  }
385  else
386  return NC_ENOGRP;
387 
388  return NC_NOERR;
389 }
390 
405 int
406 NC4_inq_grp_full_ncid(int ncid, const char *full_name, int *grp_ncid)
407 {
408  NC_GRP_INFO_T *grp;
409  NC_HDF5_FILE_INFO_T *h5;
410  int id1 = ncid, id2;
411  char *cp, *full_name_cpy;
412  int ret;
413 
414  if (!full_name)
415  return NC_EINVAL;
416 
417  /* Find info for this file and group, and set pointer to each. */
418  if ((ret = nc4_find_grp_h5(ncid, &grp, &h5)))
419  return ret;
420  assert(h5);
421 
422  /* Copy full_name because strtok messes with the value it works
423  * with, and we don't want to mess up full_name. */
424  if (!(full_name_cpy = malloc(strlen(full_name) + 1)))
425  return NC_ENOMEM;
426  strcpy(full_name_cpy, full_name);
427 
428  /* Get the first part of the name. */
429  if (!(cp = strtok(full_name_cpy, "/")))
430  {
431  /* If "/" is passed, and this is the root group, return the root
432  * group id. */
433  if (!grp->parent)
434  id2 = ncid;
435  else
436  {
437  free(full_name_cpy);
438  return NC_ENOGRP;
439  }
440  }
441  else
442  {
443  /* Keep parsing the string. */
444  for (; cp; id1 = id2)
445  {
446  if ((ret = NC4_inq_ncid(id1, cp, &id2)))
447  {
448  free(full_name_cpy);
449  return ret;
450  }
451  cp = strtok(NULL, "/");
452  }
453  }
454 
455  /* Give the user the requested value. */
456  if (grp_ncid)
457  *grp_ncid = id2;
458 
459  free(full_name_cpy);
460 
461  return NC_NOERR;
462 }
463 
475 int
476 NC4_inq_varids(int ncid, int *nvars, int *varids)
477 {
478  NC_GRP_INFO_T *grp;
479  NC_HDF5_FILE_INFO_T *h5;
480  NC_VAR_INFO_T *var;
481  int v, num_vars = 0;
482  int retval;
483  int i;
484 
485  LOG((2, "nc_inq_varids: ncid 0x%x", ncid));
486 
487  /* Find info for this file and group, and set pointer to each. */
488  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
489  return retval;
490  assert(h5);
491 
492  /* This is a netCDF-4 group. Round up them doggies and count
493  * 'em. The list is in correct (i.e. creation) order. */
494  for (i=0; i < grp->vars.nelems; i++)
495  {
496  var = grp->vars.value[i];
497  if (!var) continue;
498  if (varids)
499  varids[num_vars] = var->varid;
500  num_vars++;
501  }
502 
503  /* If the user wants to know how many vars in the group, tell
504  * him. */
505  if (nvars)
506  *nvars = num_vars;
507 
508  return NC_NOERR;
509 }
510 
522 int int_cmp(const void *a, const void *b)
523 {
524  const int *ia = (const int *)a;
525  const int *ib = (const int *)b;
526  return *ia - *ib;
527 }
528 
544 int
545 NC4_inq_dimids(int ncid, int *ndims, int *dimids, int include_parents)
546 {
547  NC_GRP_INFO_T *grp, *g;
548  NC_HDF5_FILE_INFO_T *h5;
549  NC_DIM_INFO_T *dim;
550  int d, num = 0;
551  int retval;
552 
553  LOG((2, "nc_inq_dimids: ncid 0x%x include_parents: %d", ncid,
554  include_parents));
555 
556  /* Find info for this file and group, and set pointer to each. */
557  if ((retval = nc4_find_grp_h5(ncid, &grp, &h5)))
558  return retval;
559  assert(h5);
560 
561  /* First count them. */
562  for (dim = grp->dim; dim; dim = dim->l.next)
563  num++;
564  if (include_parents)
565  for (g = grp->parent; g; g = g->parent)
566  for (dim = g->dim; dim; dim = dim->l.next)
567  num++;
568 
569  /* If the user wants the dimension ids, get them. */
570  if (dimids)
571  {
572  int n = 0;
573 
574  /* Get dimension ids from this group. */
575  for (dim = grp->dim; dim; dim = dim->l.next)
576  dimids[n++] = dim->dimid;
577 
578  /* Get dimension ids from parent groups. */
579  if (include_parents)
580  for (g = grp->parent; g; g = g->parent)
581  for (dim = g->dim; dim; dim = dim->l.next)
582  dimids[n++] = dim->dimid;
583 
584  qsort(dimids, num, sizeof(int), int_cmp);
585  }
586 
587  /* If the user wants the number of dims, give it. */
588  if (ndims)
589  *ndims = num;
590 
591  return NC_NOERR;
592 }
593 
#define NC_ENOMEM
Memory allocation (malloc) failure.
Definition: netcdf.h:395
#define NC_CLASSIC_MODEL
Enforce classic model on netCDF-4.
Definition: netcdf.h:135
#define NC_EHDFERR
Error at HDF5 layer.
Definition: netcdf.h:426
#define NC_ENOGRP
No group found.
Definition: netcdf.h:450
#define NC_EINVAL
Invalid Argument.
Definition: netcdf.h:325
#define NC_ESTRICTNC3
Attempting netcdf-4 operation on strict nc3 netcdf-4 file.
Definition: netcdf.h:437
#define NC_EBADGRPID
Bad group ID.
Definition: netcdf.h:441
#define NC_MAX_NAME
Maximum for classic library.
Definition: netcdf.h:265
#define NC_EPERM
Write to read only.
Definition: netcdf.h:326
#define NC_NOERR
No Error.
Definition: netcdf.h:315

Return to the Main Unidata NetCDF page.
Generated on Thu Jan 25 2018 21:06:33 for NetCDF. NetCDF is a Unidata library.