NetCDF  4.6.1
nc4info.c
Go to the documentation of this file.
1 
9 #include "config.h"
10 #include <stdlib.h>
11 #include <string.h>
12 #include <hdf5.h>
13 #include "netcdf.h"
14 #include "nc4internal.h"
15 
16 #define HDF5_MAX_NAME 1024
19 #define NCHECK(expr) {if((expr)!=NC_NOERR) {goto done;}}
20 
22 #define HCHECK(expr) {if((expr)<0) {ncstat = NC_EHDFERR; goto done;}}
23 
24 struct NCPROPINFO globalpropinfo;
32 int
33 NC4_fileinfo_init(void)
34 {
35  int stat = NC_NOERR;
36  unsigned major,minor,release;
37 
38  /* Build nc properties */
39  memset((void*)&globalpropinfo,0,sizeof(globalpropinfo));
40  globalpropinfo.version = NCPROPS_VERSION;
41  globalpropinfo.netcdfver[0] = '\0';
42  globalpropinfo.hdf5ver[0] = '\0';
43 
44  stat = NC4_hdf5get_libversion(&major,&minor,&release);
45  if(stat) goto done;
46  snprintf(globalpropinfo.hdf5ver,sizeof(globalpropinfo.hdf5ver),
47  "%1u.%1u.%1u",major,minor,release);
48  strncpy(globalpropinfo.netcdfver,PACKAGE_VERSION,sizeof(globalpropinfo.netcdfver));
49 done:
50  return stat;
51 }
52 
62 static int
63 NC4_properties_parse(struct NCPROPINFO* ncprops, const char* text)
64 {
65  int ret = NC_NOERR;
66  size_t len;
67  char* p;
68  char* propdata = NULL;
69 
70  ncprops->version = 0;
71  ncprops->hdf5ver[0] = '\0';
72  ncprops->netcdfver[0] = '\0';
73 
74  len = strlen(text);
75  if(len == 0) return NC_NOERR;
76  propdata = (char*)malloc(len+1);
77  if(propdata == NULL) return NC_ENOMEM;
78  memcpy(propdata,text,len+1);
79  propdata[len] = '\0'; /* guarantee */
80 
81  /* Walk and fill in ncinfo */
82  p = propdata;
83  while(*p) {
84  char* name = p;
85  char* value = NULL;
86  char* q = strchr(p,'=');
87  if(q == NULL)
88  {ret = NC_EINVAL; goto done;}
89  *q++ = '\0';
90  value = p = q;
91  q = strchr(p,NCPROPSSEP);
92  if(q == NULL) q = (p+strlen(p)); else* q++ = '\0';
93  p = q;
94  if(value != NULL) {
95  if(strcmp(name,NCPVERSION) == 0) {
96  int v = atoi(value);
97  if(v < 0) v = 0;
98  ncprops->version = v;
99  } else if(strcmp(name,NCPNCLIBVERSION) == 0)
100  strncpy(ncprops->netcdfver,value,sizeof(ncprops->netcdfver)-1);
101  else if(strcmp(name,NCPHDF5LIBVERSION) == 0)
102  strncpy(ncprops->hdf5ver,value,sizeof(ncprops->hdf5ver)-1);
103  /* else ignore */
104  }
105  }
106  /* Guarantee null term */
107  ncprops->netcdfver[sizeof(ncprops->netcdfver)-1] = '\0';
108  ncprops->hdf5ver[sizeof(ncprops->hdf5ver)-1] = '\0';
109 done:
110  if(propdata != NULL) free(propdata);
111  return ret;
112 }
113 
122 static int
123 NC4_get_propattr(NC_HDF5_FILE_INFO_T* h5)
124 {
125  int ncstat = NC_NOERR;
126  size_t size;
127  H5T_class_t t_class;
128  hid_t grp = -1;
129  hid_t attid = -1;
130  hid_t aspace = -1;
131  hid_t atype = -1;
132  hid_t ntype = -1;
133  char* text = NULL;
134 
135  /* Get root group */
136  grp = h5->root_grp->hdf_grpid; /* get root group */
137  /* Try to extract the NCPROPS attribute */
138  if(H5Aexists(grp,NCPROPS) > 0) { /* Does exist */
139  attid = H5Aopen_name(grp, NCPROPS);
140  aspace = H5Aget_space(attid); /* dimensions of attribute data */
141  atype = H5Aget_type(attid);
142  /* Verify that atype and size */
143  t_class = H5Tget_class(atype);
144  if(t_class != H5T_STRING) {ncstat = NC_EATTMETA; goto done;}
145  size = H5Tget_size(atype);
146  if(size == 0) goto done;
147  text = (char*)malloc(size+1);
148  if(text == NULL)
149  {ncstat = NC_ENOMEM; goto done;}
150  HCHECK((ntype = H5Tget_native_type(atype, H5T_DIR_ASCEND)));
151  HCHECK((H5Aread(attid, ntype, text)));
152  /* Make sure its null terminated */
153  text[size] = '\0';
154  /* Try to parse text */
155  ncstat = NC4_properties_parse(&h5->fileinfo->propattr,text);
156  }
157 done:
158  if(attid >= 0) HCHECK((H5Aclose(attid)));
159  if(aspace >= 0) HCHECK((H5Sclose(aspace)));
160  if(ntype >= 0) HCHECK((H5Tclose(ntype)));
161  if(atype >= 0) HCHECK((H5Tclose(atype)));
162  if(text != NULL) free(text);
163  return ncstat;
164 }
165 
174 int
175 NC4_put_propattr(NC_HDF5_FILE_INFO_T* h5)
176 {
177  int ncstat = NC_NOERR;
178  hid_t grp = -1;
179  hid_t attid = -1;
180  hid_t aspace = -1;
181  hid_t atype = -1;
182  char* text = NULL;
183 
184  /* Get root group */
185  grp = h5->root_grp->hdf_grpid; /* get root group */
186  /* See if the NCPROPS attribute exists */
187  if(H5Aexists(grp,NCPROPS) == 0) { /* Does not exist */
188  ncstat = NC4_buildpropinfo(&h5->fileinfo->propattr,&text);
189  if(text == NULL || ncstat != NC_NOERR) {
190  goto done;
191  }
192  /* Create a datatype to refer to. */
193  HCHECK((atype = H5Tcopy(H5T_C_S1)));
194  HCHECK((H5Tset_cset(atype, H5T_CSET_ASCII)));
195  HCHECK((H5Tset_size(atype, strlen(text)+1))); /*keep nul term */
196  HCHECK((aspace = H5Screate(H5S_SCALAR)));
197  HCHECK((attid = H5Acreate(grp, NCPROPS, atype, aspace, H5P_DEFAULT)));
198  HCHECK((H5Awrite(attid, atype, text)));
199  }
200  done:
201  if(text != NULL) {
202  free(text);
203  text = NULL;
204  }
205 
206  if(attid >= 0) HCHECK((H5Aclose(attid)));
207  if(aspace >= 0) HCHECK((H5Sclose(aspace)));
208  if(atype >= 0) HCHECK((H5Tclose(atype)));
209  return ncstat;
210 }
211 
221 int
222 NC4_get_fileinfo(NC_HDF5_FILE_INFO_T* h5, struct NCPROPINFO* init)
223 {
224  int ncstat = NC_NOERR;
225 
226  /* Allocate the fileinfo in h5 */
227  h5->fileinfo = (struct NCFILEINFO*)calloc(1,sizeof(struct NCFILEINFO));
228  if(h5->fileinfo == NULL)
229  {ncstat = NC_ENOMEM; goto done;}
230 
231  /* Get superblock version */
232  NCHECK((ncstat = NC4_hdf5get_superblock(h5,&h5->fileinfo->superblockversion)));
233  /* Get properties attribute if not already defined */
234  if(init == NULL) {
235  NCHECK((ncstat = NC4_get_propattr(h5)));
236  } else { /*init != NULL*/
237  h5->fileinfo->propattr = *init; /* Initialize */
238  }
239 done:
240  return ncstat;
241 }
242 
252 int
253 NC4_buildpropinfo(struct NCPROPINFO* info,char** propdatap)
254 {
255  size_t total;
256  char* propdata = NULL;
257 
258  if(info == NULL || info->version == 0) return NC_EINVAL;
259  if(propdatap == NULL)
260  return NC_NOERR;
261  *propdatap = NULL;
262 
263  /* compute attribute length */
264  total = 0;
265  total += strlen(NCPVERSION);
266  total += strlen("=00000000");
267  if(strlen(info->netcdfver) > 0) {
268  total += 1; /*|NCPROPSEP|*/
269  total += strlen(NCPNCLIBVERSION);
270  total += strlen("=");
271  total += strlen(info->netcdfver);
272  }
273  if(strlen(info->hdf5ver) > 0) {
274  total += 1; /*|NCPROPSEP|*/
275  total += strlen(NCPHDF5LIBVERSION);
276  total += strlen("=");
277  total += strlen(info->hdf5ver);
278  }
279  propdata = (char*)malloc(total+1);
280  if(propdata == NULL)
281  return NC_ENOMEM;
282  snprintf(propdata,total+1,
283  "%s=%d|%s=%s|%s=%s",
284  NCPVERSION,info->version,
285  NCPNCLIBVERSION,info->netcdfver,
286  NCPHDF5LIBVERSION,info->hdf5ver);
287  /* Force null termination */
288  propdata[total] = '\0';
289  *propdatap = propdata;
290 
291  return NC_NOERR;
292 }
struct NCPROPINFO globalpropinfo
Global property info.
Definition: nc4info.c:24
#define NC_ENOMEM
Memory allocation (malloc) failure.
Definition: netcdf.h:395
Main header file for the C API.
#define NC_EATTMETA
Problem with attribute metadata.
Definition: netcdf.h:433
#define NC_EINVAL
Invalid Argument.
Definition: netcdf.h:325
#define NC_NOERR
No Error.
Definition: netcdf.h:315

Return to the Main Unidata NetCDF page.
Generated on Thu Jul 19 2018 13:18:57 for NetCDF. NetCDF is a Unidata library.