1 /* This is part of the netCDF package.
2    Copyright 2005 University Corporation for Atmospheric Research/Unidata
3    See COPYRIGHT file for conditions of use.
4 
5    Test HDF5 file code. These are not intended to be exhaustive tests,
6    but they use HDF5 the same way that netCDF-4 does, so if these
7    tests don't work, than netCDF-4 won't work either.
8 */
9 #include "h5_err_macros.h"
10 #include <hdf5.h>
11 #include <H5DSpublic.h>
12 #include <ncdimscale.h>
13 
14 #define FILE_NAME "tst_h_dimscales2.h5"
15 #define DIMSCALE_NAME "dimscale"
16 #define VAR1_NAME "var1"
17 #define NDIMS 1
18 #define DIM1_LEN 3
19 #define NAME_ATTRIBUTE "dimscale_name_attribute"
20 #define DIMSCALE_LABEL "dimscale_label"
21 #define STR_LEN 255
22 
alien_visitor(hid_t did,unsigned dim,hid_t dsid,void * visitor_data)23 herr_t alien_visitor(hid_t did, unsigned dim, hid_t dsid,
24 		     void *visitor_data)
25 {
26    char name1[STR_LEN];
27    H5G_stat_t statbuf;
28    HDF5_OBJID_T *objid = visitor_data;
29 
30    /* This should get "/var1", the name of the dataset that the scale
31     * is attached to. */
32    if (H5Iget_name(did, name1, STR_LEN) < 0) ERR;
33    if (strcmp(&name1[1], VAR1_NAME)) ERR;
34 
35    /* Get more info on the dimscale object.*/
36    if (H5Gget_objinfo(dsid, ".", 1, &statbuf) < 0) ERR;
37    objid->fileno[0] = statbuf.fileno[0];
38    objid->objno[0] = statbuf.objno[0];
39    objid->fileno[1] = statbuf.fileno[1];
40    objid->objno[1] = statbuf.objno[1];
41 
42    return 0;
43 }
44 
alien_visitor2(hid_t did,unsigned dim,hid_t dsid,void * visitor_data)45 herr_t alien_visitor2(hid_t did, unsigned dim, hid_t dsid, void *visitor_data)
46 {
47    H5G_stat_t statbuf;
48    HDF5_OBJID_T *objid = visitor_data;
49 
50    /* Get obj id of the dimscale object. THis will be used later to
51     * match dimensions to dimscales. */
52    if (H5Gget_objinfo(dsid, ".", 1, &statbuf) < 0) ERR;
53    objid->fileno[0] = statbuf.fileno[0];
54    objid->objno[0] = statbuf.objno[0];
55    objid->fileno[1] = statbuf.fileno[1];
56    objid->objno[1] = statbuf.objno[1];
57 
58    return 0;
59 }
60 
61 int
main()62 main()
63 {
64    printf("\n*** Checking HDF5 dimscales some more.\n");
65    printf("*** Creating a file with one var with one dimension scale...");
66 
67    {
68       hid_t fileid, spaceid, datasetid, dimscaleid, cparmsid;
69       hsize_t dims[NDIMS] = {DIM1_LEN}, maxdims[NDIMS] = {H5S_UNLIMITED};
70 
71       /* Create file. */
72       if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
73 			      H5P_DEFAULT)) < 0) ERR;
74 
75       /* Create the space that will be used both for the dimscale and
76        * the 1D dataset that will attach it. */
77       if ((spaceid = H5Screate_simple(NDIMS, dims, maxdims)) < 0) ERR;
78 
79       /* Modify dataset creation properties, i.e. enable chunking. */
80       dims[0] = 1;
81       if ((cparmsid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
82       if (H5Pset_chunk(cparmsid, NDIMS, dims) < 0) ERR;
83 
84       /* Create our dimension scale, as an unlimited dataset. */
85       if ((dimscaleid = H5Dcreate(fileid, DIMSCALE_NAME, H5T_NATIVE_INT,
86 				  spaceid, cparmsid)) < 0) ERR;
87       if (H5DSset_scale(dimscaleid, NAME_ATTRIBUTE) < 0) ERR;
88 
89       /* Create a variable which uses it. */
90       if ((datasetid = H5Dcreate(fileid, VAR1_NAME, H5T_NATIVE_INT,
91 				 spaceid, cparmsid)) < 0) ERR;
92       if (H5DSattach_scale(datasetid, dimscaleid, 0) < 0) ERR;
93       if (H5DSset_label(datasetid, 0, DIMSCALE_LABEL) < 0) ERR;
94 
95       /* Fold up our tents. */
96       if (H5Dclose(dimscaleid) < 0 ||
97 	  H5Dclose(datasetid) < 0 ||
98 	  H5Sclose(spaceid) < 0 ||
99 	  H5Fclose(fileid) < 0) ERR;
100    }
101 
102    SUMMARIZE_ERR;
103    printf("*** Checking that one var, one dimscale file can be read...");
104 
105    {
106       hid_t fileid, spaceid = 0, datasetid = 0;
107       hsize_t num_obj, i;
108       int obj_class;
109       char obj_name[STR_LEN + 1];
110       char dimscale_name[STR_LEN+1];
111       htri_t is_scale;
112       char label[STR_LEN+1];
113       int num_scales;
114       hsize_t dims[1], maxdims[1];
115       H5G_stat_t statbuf;
116       HDF5_OBJID_T dimscale_obj, vars_dimscale_obj;
117 
118       /* Open the file. */
119       if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
120 
121       /* Loop through objects in the root group. */
122       if (H5Gget_num_objs(fileid, &num_obj) < 0) ERR;
123       for (i=0; i<num_obj; i++)
124       {
125 	 /* Get the type (i.e. group, dataset, etc.), and the name of
126 	  * the object. */
127 	 if ((obj_class = H5Gget_objtype_by_idx(fileid, i)) < 0) ERR;
128 	 if (H5Gget_objname_by_idx(fileid, i, obj_name, STR_LEN) < 0) ERR;
129 
130 	 /* Deal with object based on its obj_class. */
131 	 switch(obj_class)
132 	 {
133 	    case H5G_GROUP:
134 	       break;
135 	    case H5G_DATASET:
136 	       /* Open the dataset. */
137 	       if ((datasetid = H5Dopen1(fileid, obj_name)) < 0) ERR;
138 
139 	       /* This should be an unlimited dataset. */
140 	       if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
141 	       if (H5Sget_simple_extent_dims(spaceid, dims, maxdims) < 0) ERR;
142 	       if (maxdims[0] != H5S_UNLIMITED) ERR;
143 
144 	       /* Is this a dimscale? */
145 	       if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
146 	       if (is_scale && strcmp(obj_name, DIMSCALE_NAME)) ERR;
147 	       if (is_scale)
148 	       {
149 		  /* A dimscale comes with a NAME attribute, in
150 		   * addition to its real name. */
151 		  if (H5DSget_scale_name(datasetid, dimscale_name, STR_LEN) < 0) ERR;
152 		  if (strcmp(dimscale_name, NAME_ATTRIBUTE)) ERR;
153 
154 		  /* fileno and objno uniquely identify an object and a
155 		   * HDF5 file. */
156 		  if (H5Gget_objinfo(datasetid, ".", 1, &statbuf) < 0) ERR;
157 		  dimscale_obj.fileno[0] = statbuf.fileno[0];
158 		  dimscale_obj.objno[0] = statbuf.objno[0];
159 		  dimscale_obj.fileno[1] = statbuf.fileno[1];
160 		  dimscale_obj.objno[1] = statbuf.objno[1];
161 	       }
162 	       else
163 	       {
164 		  /* Here's how to get the number of scales attached
165 		   * to the dataset's dimension 0. */
166 		  if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
167 		  if (num_scales != 1) ERR;
168 
169 		  /* Go through all dimscales for this var and learn about them. */
170 		  if (H5DSiterate_scales(datasetid, 0, NULL, alien_visitor,
171 					 &vars_dimscale_obj) < 0) ERR;
172 		  if (vars_dimscale_obj.fileno[0] != dimscale_obj.fileno[0] ||
173 		      vars_dimscale_obj.objno[0] != dimscale_obj.objno[0] ||
174 		      vars_dimscale_obj.fileno[1] != dimscale_obj.fileno[1] ||
175 		      vars_dimscale_obj.objno[1] != dimscale_obj.objno[1]) ERR;
176 
177 		  /* There's also a label for dimension 0. */
178 		  if (H5DSget_label(datasetid, 0, label, STR_LEN) < 0) ERR;
179 	       }
180 	       if (H5Dclose(datasetid) < 0) ERR;
181 	       break;
182 	    case H5G_TYPE:
183 	       break;
184 	    case H5G_LINK:
185 	       break;
186 	    default:
187 	       printf("Unknown object class %d!", obj_class);
188 	 }
189       }
190 
191       /* Close up the shop. */
192       if (H5Sclose(spaceid) < 0 ||
193 	  H5Fclose(fileid) < 0) ERR;
194    }
195 
196    SUMMARIZE_ERR;
197    printf("*** Creating a file with one var with two dimension scales...");
198 
199    {
200 #define LAT_LEN 3
201 #define LON_LEN 2
202 #define DIMS_2 2
203 #define LAT_NAME "lat"
204 #define LON_NAME "lon"
205 #define PRES_NAME "pres"
206 
207       hid_t fileid, lat_spaceid, lon_spaceid, pres_spaceid;
208       hid_t pres_datasetid, lat_dimscaleid, lon_dimscaleid;
209       hsize_t dims[DIMS_2];
210 
211       /* Create file. */
212       if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
213 			      H5P_DEFAULT)) < 0) ERR;
214 
215       /* Create the spaces that will be used for the dimscales. */
216       dims[0] = LAT_LEN;
217       if ((lat_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
218       dims[0] = LON_LEN;
219       if ((lon_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
220 
221       /* Create the space for the dataset. */
222       dims[0] = LAT_LEN;
223       dims[1] = LON_LEN;
224       if ((pres_spaceid = H5Screate_simple(DIMS_2, dims, dims)) < 0) ERR;
225 
226       /* Create our dimension scales. */
227       if ((lat_dimscaleid = H5Dcreate(fileid, LAT_NAME, H5T_NATIVE_INT,
228 				      lat_spaceid, H5P_DEFAULT)) < 0) ERR;
229       if (H5DSset_scale(lat_dimscaleid, NULL) < 0) ERR;
230       if ((lon_dimscaleid = H5Dcreate(fileid, LON_NAME, H5T_NATIVE_INT,
231 				      lon_spaceid, H5P_DEFAULT)) < 0) ERR;
232       if (H5DSset_scale(lon_dimscaleid, NULL) < 0) ERR;
233 
234       /* Create a variable which uses these two dimscales. */
235       if ((pres_datasetid = H5Dcreate(fileid, PRES_NAME, H5T_NATIVE_FLOAT,
236 				      pres_spaceid, H5P_DEFAULT)) < 0) ERR;
237       if (H5DSattach_scale(pres_datasetid, lat_dimscaleid, 0) < 0) ERR;
238       if (H5DSattach_scale(pres_datasetid, lon_dimscaleid, 1) < 0) ERR;
239 
240       /* Fold up our tents. */
241       if (H5Dclose(lat_dimscaleid) < 0 ||
242 	  H5Dclose(lon_dimscaleid) < 0 ||
243 	  H5Dclose(pres_datasetid) < 0 ||
244 	  H5Sclose(lat_spaceid) < 0 ||
245 	  H5Sclose(lon_spaceid) < 0 ||
246 	  H5Sclose(pres_spaceid) < 0 ||
247 	  H5Fclose(fileid) < 0) ERR;
248    }
249 
250    SUMMARIZE_ERR;
251    printf("*** Checking that one var, two dimscales file can be read...");
252 
253    {
254 #define NDIMS2 2
255       hid_t fileid, spaceid = 0, datasetid = 0;
256       hsize_t num_obj, i;
257       int obj_class;
258       char obj_name[STR_LEN + 1];
259       htri_t is_scale;
260       int num_scales;
261       hsize_t dims[NDIMS2], maxdims[NDIMS2];
262       H5G_stat_t statbuf;
263       HDF5_OBJID_T dimscale_obj[2], vars_dimscale_obj[2];
264       int dimscale_cnt = 0;
265       int d, ndims;
266 
267       /* Open the file. */
268       if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
269 
270       /* Loop through objects in the root group. */
271       if (H5Gget_num_objs(fileid, &num_obj) < 0) ERR;
272       for (i=0; i<num_obj; i++)
273       {
274 	 /* Get the type (i.e. group, dataset, etc.), and the name of
275 	  * the object. */
276 	 if ((obj_class = H5Gget_objtype_by_idx(fileid, i)) < 0) ERR;
277 	 if (H5Gget_objname_by_idx(fileid, i, obj_name, STR_LEN) < 0) ERR;
278 
279 	 /* Deal with object based on its obj_class. */
280 	 switch(obj_class)
281 	 {
282 	    case H5G_GROUP:
283 	       break;
284 	    case H5G_DATASET:
285 	       /* Open the dataset. */
286 	       if ((datasetid = H5Dopen1(fileid, obj_name)) < 0) ERR;
287 
288 	       /* Get space info. */
289 	       if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
290 	       if (H5Sget_simple_extent_dims(spaceid, dims, maxdims) < 0) ERR;
291 	       if ((ndims = H5Sget_simple_extent_ndims(spaceid)) < 0) ERR;
292 	       if (ndims > NDIMS2) ERR;
293 
294 	       /* Is this a dimscale? */
295 	       if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
296 	       if (is_scale)
297 	       {
298 		  /* fileno and objno uniquely identify an object and a
299 		   * HDF5 file. */
300 		  if (H5Gget_objinfo(datasetid, ".", 1, &statbuf) < 0) ERR;
301 		  dimscale_obj[dimscale_cnt].fileno[0] = statbuf.fileno[0];
302 		  dimscale_obj[dimscale_cnt].objno[0] = statbuf.objno[0];
303 		  dimscale_obj[dimscale_cnt].fileno[1] = statbuf.fileno[1];
304 		  dimscale_obj[dimscale_cnt].objno[1] = statbuf.objno[1];
305 		  dimscale_cnt++;
306 	       }
307 	       else
308 	       {
309 		  /* Here's how to get the number of scales attached
310 		   * to the dataset's dimension 0 and 1. */
311 		  if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
312 		  if (num_scales != 1) ERR;
313 		  if ((num_scales = H5DSget_num_scales(datasetid, 1)) < 0) ERR;
314 		  if (num_scales != 1) ERR;
315 
316 		  /* Go through all dimscales for this var and learn about them. */
317 		  for (d = 0; d < ndims; d++)
318 		  {
319 		     if (H5DSiterate_scales(datasetid, d, NULL, alien_visitor2,
320 		     &(vars_dimscale_obj[d])) < 0) ERR;
321 
322 		     /* Verify that the object ids passed from the
323 		      * alien_visitor2 function match the ones we found
324 		      * for the lat and lon datasets. */
325 		     if (vars_dimscale_obj[d].fileno[0] != dimscale_obj[d].fileno[0] ||
326 		     vars_dimscale_obj[d].objno[0] != dimscale_obj[d].objno[0]) ERR;
327 		     if (vars_dimscale_obj[d].fileno[1] != dimscale_obj[d].fileno[1] ||
328 		     vars_dimscale_obj[d].objno[1] != dimscale_obj[d].objno[1]) ERR;
329 		  }
330 	       }
331 	       if (H5Dclose(datasetid) < 0) ERR;
332 	       if (H5Sclose(spaceid) < 0) ERR;
333 	       break;
334 	    case H5G_TYPE:
335 	       break;
336 	    case H5G_LINK:
337 	       break;
338 	    default:
339 	       printf("Unknown object class %d!", obj_class);
340 	 }
341       }
342 
343       /* Close up the shop. */
344       if (H5Fclose(fileid) < 0) ERR;
345    }
346    SUMMARIZE_ERR;
347    printf("*** Creating a file with one var with two unlimited dimension scales...");
348    {
349 #define U1_LEN 3
350 #define U2_LEN 2
351 #define DIMS2 2
352 #define U1_NAME "u1"
353 #define U2_NAME "u2"
354 #define VNAME "v1"
355 
356       hid_t fapl_id, fcpl_id, grpid, plistid, plistid2;
357       hid_t fileid, lat_spaceid, lon_spaceid, pres_spaceid;
358       hid_t pres_datasetid, lat_dimscaleid, lon_dimscaleid;
359       hsize_t dims[DIMS2], maxdims[DIMS2], chunksize[DIMS2] = {10, 10};
360       hid_t spaceid = 0, datasetid = 0;
361       hsize_t num_obj, i;
362       int obj_class;
363       char obj_name[STR_LEN + 1];
364       htri_t is_scale;
365       int num_scales;
366       H5G_stat_t statbuf;
367       HDF5_OBJID_T dimscale_obj[2], vars_dimscale_obj[2];
368       int dimscale_cnt = 0;
369       int d, ndims;
370 
371       /* Create file access and create property lists. */
372       if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
373       if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR;
374 
375       /* Set latest_format in access propertly list. This ensures that
376        * the latest, greatest, HDF5 versions are used in the file. */
377       if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) ERR;
378 
379       /* Set H5P_CRT_ORDER_TRACKED in the creation property list. This
380        * turns on HDF5 creation ordering in the file. */
381       if (H5Pset_link_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
382 					       H5P_CRT_ORDER_INDEXED)) < 0) ERR;
383       if (H5Pset_attr_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
384 					       H5P_CRT_ORDER_INDEXED)) < 0) ERR;
385 
386       /* Create file. */
387       if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, fcpl_id, fapl_id)) < 0) ERR;
388 
389       /* Open the root group. */
390       if ((grpid = H5Gopen2(fileid, "/", H5P_DEFAULT)) < 0) ERR;
391 
392       /* Create the spaces that will be used for the dimscales. */
393       dims[0] = 0;
394       maxdims[0] = H5S_UNLIMITED;
395       if ((lat_spaceid = H5Screate_simple(1, dims, maxdims)) < 0) ERR;
396       if ((lon_spaceid = H5Screate_simple(1, dims, maxdims)) < 0) ERR;
397 
398       /* Create the space for the dataset. */
399       dims[0] = 0;
400       dims[1] = 0;
401       maxdims[0] = H5S_UNLIMITED;
402       maxdims[1] = H5S_UNLIMITED;
403       if ((pres_spaceid = H5Screate_simple(DIMS2, dims, maxdims)) < 0) ERR;
404 
405       /* Set up the dataset creation property list for the two dimensions. */
406       if ((plistid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
407       if (H5Pset_chunk(plistid, 1, chunksize) < 0) ERR;
408       if (H5Pset_attr_creation_order(plistid, H5P_CRT_ORDER_TRACKED|
409 				     H5P_CRT_ORDER_INDEXED) < 0) ERR;
410 
411       /* Create our dimension scales. */
412       if ((lat_dimscaleid = H5Dcreate(grpid, U1_NAME, H5T_NATIVE_INT,
413 				      lat_spaceid, plistid)) < 0) ERR;
414       if (H5DSset_scale(lat_dimscaleid, NULL) < 0) ERR;
415       if ((lon_dimscaleid = H5Dcreate(grpid, U2_NAME, H5T_NATIVE_INT,
416 				      lon_spaceid, plistid)) < 0) ERR;
417       if (H5DSset_scale(lon_dimscaleid, NULL) < 0) ERR;
418 
419       /* Set up the dataset creation property list for the variable. */
420       if ((plistid2 = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
421       if (H5Pset_chunk(plistid2, DIMS2, chunksize) < 0) ERR;
422       if (H5Pset_attr_creation_order(plistid2, H5P_CRT_ORDER_TRACKED|
423 				     H5P_CRT_ORDER_INDEXED) < 0) ERR;
424 
425       /* Create a variable which uses these two dimscales. */
426       if ((pres_datasetid = H5Dcreate(grpid, VNAME, H5T_NATIVE_DOUBLE, pres_spaceid,
427 				      plistid2)) < 0) ERR;
428       if (H5DSattach_scale(pres_datasetid, lat_dimscaleid, 0) < 0) ERR;
429       if (H5DSattach_scale(pres_datasetid, lon_dimscaleid, 1) < 0) ERR;
430 
431       /* Close down the show. */
432       if (H5Pclose(fapl_id) < 0 ||
433 	  H5Pclose(fcpl_id) < 0 ||
434 	  H5Dclose(lat_dimscaleid) < 0 ||
435 	  H5Dclose(lon_dimscaleid) < 0 ||
436 	  H5Dclose(pres_datasetid) < 0 ||
437 	  H5Sclose(lat_spaceid) < 0 ||
438 	  H5Sclose(lon_spaceid) < 0 ||
439 	  H5Sclose(pres_spaceid) < 0 ||
440 	  H5Pclose(plistid) < 0 ||
441 	  H5Pclose(plistid2) < 0 ||
442 	  H5Gclose(grpid) < 0 ||
443 	  H5Fclose(fileid) < 0) ERR;
444 
445       /* Open the file. */
446       if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
447       if ((grpid = H5Gopen2(fileid, "/", H5P_DEFAULT)) < 0) ERR;
448 
449       /* Loop through objects in the root group. */
450       if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
451 
452       for (i = 0; i < num_obj; i++)
453       {
454 	 /*Get the type (i.e. group, dataset, etc.), and the name of
455 	   the object. */
456 	 if ((obj_class = H5Gget_objtype_by_idx(grpid, i)) < 0) ERR;
457 	 if (H5Gget_objname_by_idx(grpid, i, obj_name, STR_LEN) < 0) ERR;
458 
459 	 /* Deal with object based on its obj_class. */
460 	 switch(obj_class)
461 	 {
462 	    case H5G_GROUP:
463 	       break;
464 	    case H5G_DATASET:
465 	       /* Open the dataset. */
466 	       if ((datasetid = H5Dopen1(grpid, obj_name)) < 0) ERR;
467 
468 	       /* Get space info. */
469 	       if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
470 	       if (H5Sget_simple_extent_dims(spaceid, dims, maxdims) < 0) ERR;
471 	       if ((ndims = H5Sget_simple_extent_ndims(spaceid)) < 0) ERR;
472 
473 	       /* Is this a dimscale? */
474 	       if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
475 	       if (is_scale)
476 	       {
477 		  /* fileno and objno uniquely identify an object and a
478 		   * HDF5 file. */
479 		  if (H5Gget_objinfo(datasetid, ".", 1, &statbuf) < 0) ERR;
480 		  dimscale_obj[dimscale_cnt].fileno[0] = statbuf.fileno[0];
481 		  dimscale_obj[dimscale_cnt].objno[0] = statbuf.objno[0];
482 		  dimscale_obj[dimscale_cnt].fileno[1] = statbuf.fileno[1];
483 		  dimscale_obj[dimscale_cnt].objno[1] = statbuf.objno[1];
484 		  dimscale_cnt++;
485 	       }
486 	       else
487 	       {
488 		  /* Here's how to get the number of scales attached
489 		   * to the dataset's dimension 0 and 1. */
490 		  if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
491 		  if (num_scales != 1) ERR;
492 		  if ((num_scales = H5DSget_num_scales(datasetid, 1)) < 0) ERR;
493 		  if (num_scales != 1) ERR;
494 
495 		  /* Go through all dimscales for this var and learn about them. */
496 		  for (d = 0; d < ndims; d++)
497 		  {
498 		     if (H5DSiterate_scales(datasetid, d, NULL, alien_visitor2,
499 					    &(vars_dimscale_obj[d])) < 0) ERR;
500 
501 		     /* Verify that the object ids passed from the
502 		      * alien_visitor2 function match the ones we found
503 		      * for the lat and lon datasets. */
504 		     if (vars_dimscale_obj[d].fileno[0] != dimscale_obj[d].fileno[0] ||
505 			 vars_dimscale_obj[d].objno[0] != dimscale_obj[d].objno[0]) ERR;
506 		     if (vars_dimscale_obj[d].fileno[1] != dimscale_obj[d].fileno[1] ||
507 			 vars_dimscale_obj[d].objno[1] != dimscale_obj[d].objno[1]) ERR;
508 		  }
509 
510 	       }
511 
512 	       if (H5Dclose(datasetid) < 0) ERR;
513 	       break;
514 	    case H5G_TYPE:
515 	       break;
516 	    case H5G_LINK:
517 	       break;
518 	    default:
519 	       printf("Unknown object class %d!", obj_class);
520 	 }
521      }
522 
523       /* Check the dimension lengths. */
524       {
525 	 hid_t spaceid1;
526 	 hsize_t h5dimlen[DIMS2], h5dimlenmax[DIMS2];
527 	 int dataset_ndims;
528 
529 	 /* Check U1. */
530 	 if ((datasetid = H5Dopen1(grpid, U1_NAME)) < 0) ERR;
531 	 if ((spaceid1 = H5Dget_space(datasetid)) < 0) ERR;
532 	 if ((dataset_ndims = H5Sget_simple_extent_dims(spaceid1, h5dimlen,
533 							h5dimlenmax)) < 0) ERR;
534 	 if (dataset_ndims != 1 || h5dimlen[0] != 0 || h5dimlenmax[0] != H5S_UNLIMITED) ERR;
535 	 if (H5Dclose(datasetid) ||
536 	     H5Sclose(spaceid1)) ERR;
537 
538 	 /* Check U2. */
539 	 if ((datasetid = H5Dopen1(grpid, U2_NAME)) < 0) ERR;
540 	 if ((spaceid1 = H5Dget_space(datasetid)) < 0) ERR;
541 	 if ((dataset_ndims = H5Sget_simple_extent_dims(spaceid1, h5dimlen,
542 							h5dimlenmax)) < 0) ERR;
543 	 if (dataset_ndims != 1 || h5dimlen[0] != 0 || h5dimlenmax[0] != H5S_UNLIMITED) ERR;
544 	 if (H5Dclose(datasetid) ||
545 	     H5Sclose(spaceid1)) ERR;
546 
547 	 /* Check V1. */
548 	 if ((datasetid = H5Dopen1(grpid, VNAME)) < 0) ERR;
549 	 if ((spaceid1 = H5Dget_space(datasetid)) < 0) ERR;
550 	 if ((dataset_ndims = H5Sget_simple_extent_dims(spaceid1, h5dimlen,
551 							h5dimlenmax)) < 0) ERR;
552 	 if (dataset_ndims != 2 || h5dimlen[0] != 0 || h5dimlen[1] != 0 ||
553 	     h5dimlenmax[0] != H5S_UNLIMITED || h5dimlenmax[1] != H5S_UNLIMITED) ERR;
554 
555 	 /* All done. */
556 	 if (H5Dclose(datasetid) ||
557 	     H5Sclose(spaceid1)) ERR;
558       }
559 
560       /* Write two hyperslabs. */
561       {
562 #define NUM_VALS 3
563 	 hid_t file_spaceid, mem_spaceid;
564 	 hsize_t h5dimlen[DIMS2], h5dimlenmax[DIMS2], xtend_size[DIMS2] = {1, NUM_VALS};
565 	 hsize_t start[DIMS2] = {0, 0};
566 	 hsize_t count[DIMS2] = {1, NUM_VALS};
567 	 double value[NUM_VALS];
568 	 int dataset_ndims;
569 	 int i;
570 
571 	 /* Set up phony data. */
572 	 for (i = 0; i < NUM_VALS; i++)
573 	    value[i] = (float)i;
574 
575 	 /* Open the dataset, check its dimlens. */
576 	 if ((datasetid = H5Dopen1(grpid, VNAME)) < 0) ERR;
577 	 if ((file_spaceid = H5Dget_space(datasetid)) < 0) ERR;
578 	 if ((dataset_ndims = H5Sget_simple_extent_dims(file_spaceid, h5dimlen,
579 							h5dimlenmax)) < 0) ERR;
580 	 if (dataset_ndims != 2 || h5dimlen[0] != 0 || h5dimlen[1] != 0 ||
581 	     h5dimlenmax[0] != H5S_UNLIMITED || h5dimlenmax[1] != H5S_UNLIMITED) ERR;
582 
583 	 /* Extend the size of the dataset. */
584 	 if (H5Dextend(datasetid, xtend_size) < 0) ERR;
585 	 if ((file_spaceid = H5Dget_space(datasetid)) < 0) ERR;
586 
587 	 /* Check the size. */
588 	 if ((dataset_ndims = H5Sget_simple_extent_dims(file_spaceid, h5dimlen,
589 							h5dimlenmax)) < 0) ERR;
590 	 if (dataset_ndims != 2 || h5dimlen[0] != 1 || h5dimlen[1] != NUM_VALS ||
591 	     h5dimlenmax[0] != H5S_UNLIMITED || h5dimlenmax[1] != H5S_UNLIMITED) ERR;
592 
593 	 /* Set up the file and memory spaces. */
594 	 if (H5Sselect_hyperslab(file_spaceid, H5S_SELECT_SET,
595 				 start, NULL, count, NULL) < 0) ERR;
596 	 if ((mem_spaceid = H5Screate_simple(DIMS2, count, NULL)) < 0) ERR;
597 
598 	 /* Write a slice of data. */
599 	 if (H5Dwrite(datasetid, H5T_NATIVE_DOUBLE, mem_spaceid, file_spaceid,
600 		      H5P_DEFAULT, value) < 0)
601 
602 	 /* Check the size. */
603 	 if ((file_spaceid = H5Dget_space(datasetid)) < 0) ERR;
604 	 if ((dataset_ndims = H5Sget_simple_extent_dims(file_spaceid, h5dimlen,
605 							h5dimlenmax)) < 0) ERR;
606 	 if (dataset_ndims != 2 || h5dimlen[0] != 1 || h5dimlen[1] != NUM_VALS ||
607 	     h5dimlenmax[0] != H5S_UNLIMITED || h5dimlenmax[1] != H5S_UNLIMITED) ERR;
608 
609 	 /* Extend the size of the dataset for the second slice. */
610 	 xtend_size[0]++;
611 	 if (H5Dextend(datasetid, xtend_size) < 0) ERR;
612 	 if ((file_spaceid = H5Dget_space(datasetid)) < 0) ERR;
613 
614 	 /* Set up the file and memory spaces for a second slice. */
615 	 start[0]++;
616 	 if (H5Sselect_hyperslab(file_spaceid, H5S_SELECT_SET,
617 				 start, NULL, count, NULL) < 0) ERR;
618 	 if ((mem_spaceid = H5Screate_simple(DIMS2, count, NULL)) < 0) ERR;
619 
620 	 /* Write a second slice of data. */
621 	 if (H5Dwrite(datasetid, H5T_NATIVE_DOUBLE, mem_spaceid, file_spaceid,
622 		      H5P_DEFAULT, value) < 0)
623 
624 	 /* Check the size again. */
625 	 if ((file_spaceid = H5Dget_space(datasetid)) < 0) ERR;
626 	 if ((dataset_ndims = H5Sget_simple_extent_dims(file_spaceid, h5dimlen,
627 							h5dimlenmax)) < 0) ERR;
628 	 if (dataset_ndims != 2 || h5dimlen[0] != 2 || h5dimlen[1] != NUM_VALS ||
629 	     h5dimlenmax[0] != H5S_UNLIMITED || h5dimlenmax[1] != H5S_UNLIMITED) ERR;
630 
631 	 /* All done. */
632 	 if (H5Dclose(datasetid) ||
633 	     H5Sclose(mem_spaceid) ||
634 	     H5Sclose(file_spaceid)) ERR;
635       }
636 
637       /* Close up the shop. */
638       if (H5Sclose(spaceid)) ERR;
639       if (H5Gclose(grpid) < 0 ||
640       H5Fclose(fileid) < 0) ERR;
641    }
642    SUMMARIZE_ERR;
643    printf("*** Checking dimension scales with attached dimension scales...");
644 
645    {
646 #define LAT_LEN 3
647 #define LON_LEN 2
648 #define TIME_LEN 5
649 #define LEN_LEN 10
650 #define DIMS_3 3
651 #define NUM_DIMSCALES1 4
652 #define LAT_NAME "lat"
653 #define LON_NAME "lon"
654 #define PRES_NAME1 "z_pres"
655 #define TIME_NAME "time"
656 #define LEN_NAME "u_len"
657 
658       hid_t fileid, lat_spaceid, lon_spaceid, time_spaceid, pres_spaceid, len_spaceid;
659       hid_t pres_datasetid, lat_dimscaleid, lon_dimscaleid, time_dimscaleid, len_dimscaleid;
660       hid_t fapl_id, fcpl_id;
661       hsize_t dims[DIMS_3];
662       hid_t spaceid = 0, datasetid = 0;
663       hsize_t num_obj, i;
664       int obj_class;
665       char obj_name[STR_LEN + 1];
666       htri_t is_scale;
667       int num_scales;
668       hsize_t maxdims[DIMS_3];
669       H5G_stat_t statbuf;
670       HDF5_OBJID_T dimscale_obj[NUM_DIMSCALES1], vars_dimscale_obj[NUM_DIMSCALES1];
671       int dimscale_cnt = 0;
672       int d, ndims;
673 
674       /* Create file access and create property lists. */
675       if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
676       if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR;
677 
678       /* Set latest_format in access propertly list. This ensures that
679        * the latest, greatest, HDF5 versions are used in the file. */
680       if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) ERR;
681 
682       /* Set H5P_CRT_ORDER_TRACKED in the creation property list. This
683        * turns on HDF5 creation ordering in the file. */
684       if (H5Pset_link_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
685 					       H5P_CRT_ORDER_INDEXED)) < 0) ERR;
686       if (H5Pset_attr_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
687 					       H5P_CRT_ORDER_INDEXED)) < 0) ERR;
688 
689       /* Create file. */
690       if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, fcpl_id, fapl_id)) < 0) ERR;
691 
692       /* Create the spaces that will be used for the dimscales. */
693       dims[0] = LAT_LEN;
694       if ((lat_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
695       dims[0] = LON_LEN;
696       if ((lon_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
697       dims[0] = TIME_LEN;
698       if ((time_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
699       dims[0] = LEN_LEN;
700       if ((len_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
701 
702       /* Create the space for the dataset. */
703       dims[0] = LAT_LEN;
704       dims[1] = LON_LEN;
705       dims[2] = TIME_LEN;
706       if ((pres_spaceid = H5Screate_simple(DIMS_3, dims, dims)) < 0) ERR;
707 
708       /* Create our dimension scales. */
709       if ((lat_dimscaleid = H5Dcreate1(fileid, LAT_NAME, H5T_NATIVE_INT,
710 				      lat_spaceid, H5P_DEFAULT)) < 0) ERR;
711       if (H5DSset_scale(lat_dimscaleid, NULL) < 0) ERR;
712       if ((lon_dimscaleid = H5Dcreate1(fileid, LON_NAME, H5T_NATIVE_INT,
713 				      lon_spaceid, H5P_DEFAULT)) < 0) ERR;
714       if (H5DSset_scale(lon_dimscaleid, NULL) < 0) ERR;
715       if ((time_dimscaleid = H5Dcreate1(fileid, TIME_NAME, H5T_NATIVE_INT,
716 				      time_spaceid, H5P_DEFAULT)) < 0) ERR;
717       if (H5DSset_scale(time_dimscaleid, NULL) < 0) ERR;
718       if ((len_dimscaleid = H5Dcreate1(fileid, LEN_NAME, H5T_NATIVE_INT,
719 				      len_spaceid, H5P_DEFAULT)) < 0) ERR;
720       if (H5DSset_scale(len_dimscaleid, NULL) < 0) ERR;
721 
722       /* Create a variable which uses these three dimscales. */
723       if ((pres_datasetid = H5Dcreate1(fileid, PRES_NAME1, H5T_NATIVE_FLOAT,
724 				      pres_spaceid, H5P_DEFAULT)) < 0) ERR;
725       if (H5DSattach_scale(pres_datasetid, lat_dimscaleid, 0) < 0) ERR;
726       if (H5DSattach_scale(pres_datasetid, lon_dimscaleid, 1) < 0) ERR;
727       if (H5DSattach_scale(pres_datasetid, time_dimscaleid, 2) < 0) ERR;
728 
729       /* Attach a dimscale to a dimscale. Unfortunately, HDF5 does not
730        * allow this. Woe is me. */
731       /*if (H5DSattach_scale(time_dimscaleid, len_dimscaleid, 0) < 0) ERR;*/
732 
733       /* Fold up our tents. */
734       if (H5Dclose(lat_dimscaleid) < 0 ||
735 	  H5Dclose(lon_dimscaleid) < 0 ||
736 	  H5Dclose(time_dimscaleid) < 0 ||
737 	  H5Dclose(len_dimscaleid) < 0 ||
738 	  H5Dclose(pres_datasetid) < 0 ||
739 	  H5Sclose(lat_spaceid) < 0 ||
740 	  H5Sclose(lon_spaceid) < 0 ||
741 	  H5Sclose(time_spaceid) < 0 ||
742 	  H5Sclose(pres_spaceid) < 0 ||
743 	  H5Sclose(len_spaceid) < 0 ||
744 	  H5Pclose(fapl_id) < 0 ||
745 	  H5Pclose(fcpl_id) < 0 ||
746 	  H5Fclose(fileid) < 0) ERR;
747 
748       /* Open the file. */
749       if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
750 
751       /* Loop through objects in the root group. */
752       if (H5Gget_num_objs(fileid, &num_obj) < 0) ERR;
753       for (i=0; i<num_obj; i++)
754       {
755 	 /* Get the type (i.e. group, dataset, etc.), and the name of
756 	  * the object. */
757 	 if ((obj_class = H5Gget_objtype_by_idx(fileid, i)) < 0) ERR;
758 	 if (H5Gget_objname_by_idx(fileid, i, obj_name, STR_LEN) < 0) ERR;
759 
760 	 /* Deal with object based on its obj_class. */
761 	 switch(obj_class)
762 	 {
763 	    case H5G_GROUP:
764 	       break;
765 	    case H5G_DATASET:
766 	       /* Open the dataset. */
767 	       if ((datasetid = H5Dopen1(fileid, obj_name)) < 0) ERR;
768 
769 	       /* Get space info. */
770 	       if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
771 	       if (H5Sget_simple_extent_dims(spaceid, dims, maxdims) < 0) ERR;
772 	       if ((ndims = H5Sget_simple_extent_ndims(spaceid)) < 0) ERR;
773 
774 	       /* Is this a dimscale? */
775 	       if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
776 	       if (is_scale)
777 	       {
778 		  /* fileno and objno uniquely identify an object and a
779 		   * HDF5 file. */
780 		  if (H5Gget_objinfo(datasetid, ".", 1, &statbuf) < 0) ERR;
781 		  dimscale_obj[dimscale_cnt].fileno[0] = statbuf.fileno[0];
782 		  dimscale_obj[dimscale_cnt].objno[0] = statbuf.objno[0];
783 		  dimscale_obj[dimscale_cnt].fileno[1] = statbuf.fileno[1];
784 		  dimscale_obj[dimscale_cnt].objno[1] = statbuf.objno[1];
785 		  dimscale_cnt++;
786 	       }
787 	       else
788 	       {
789 		  /* Here's how to get the number of scales attached
790 		   * to the dataset's dimension 0 and 1. */
791 		  if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
792 		  if (num_scales != 1) ERR;
793 		  if ((num_scales = H5DSget_num_scales(datasetid, 1)) < 0) ERR;
794 		  if (num_scales != 1) ERR;
795 
796 		  /* Go through all dimscales for this var and learn about them. */
797 		  for (d = 0; d < ndims; d++)
798 		  {
799 		     if (H5DSiterate_scales(datasetid, d, NULL, alien_visitor2,
800 		     &(vars_dimscale_obj[d])) < 0) ERR;
801 
802 		     /* Verify that the object ids passed from the
803 		      * alien_visitor2 function match the ones we found
804 		      * for the lat and lon datasets. */
805 		     if (vars_dimscale_obj[d].fileno[0] != dimscale_obj[d].fileno[0] ||
806 		     vars_dimscale_obj[d].objno[0] != dimscale_obj[d].objno[0]) ERR;
807 		     if (vars_dimscale_obj[d].fileno[1] != dimscale_obj[d].fileno[1] ||
808 		     vars_dimscale_obj[d].objno[1] != dimscale_obj[d].objno[1]) ERR;
809 		  }
810 	       }
811 	       if (H5Dclose(datasetid) < 0) ERR;
812 	       if (H5Sclose(spaceid) < 0) ERR;
813 	       break;
814 	    case H5G_TYPE:
815 	       break;
816 	    case H5G_LINK:
817 	       break;
818 	    default:
819 	       printf("Unknown object class %d!", obj_class);
820 	 }
821       }
822 
823       /* Close up the shop. */
824       if (H5Fclose(fileid) < 0) ERR;
825    }
826 
827    SUMMARIZE_ERR;
828    printf("*** Checking cration ordering of datasets which are also dimension scales...");
829 
830    {
831 #define LAT_LEN 3
832 #define LON_LEN 2
833 #define TIME_LEN 5
834 #define LEN_LEN 10
835 #define DIMS_3 3
836 #define NUM_DIMSCALES2 4
837 #define LAT_NAME "lat"
838 #define LON_NAME "lon"
839 #define PRES_NAME1 "z_pres"
840 #define TIME_NAME "time"
841 #define LEN_NAME "u_len"
842 
843       hid_t fileid, lat_spaceid, lon_spaceid, time_spaceid, pres_spaceid, len_spaceid;
844       hid_t pres_datasetid, lat_dimscaleid, lon_dimscaleid, time_dimscaleid, len_dimscaleid;
845       hid_t fapl_id, fcpl_id;
846       hsize_t dims[DIMS_3];
847       hid_t spaceid = 0, datasetid = 0;
848       hsize_t num_obj, i;
849       int obj_class;
850       char obj_name[STR_LEN + 1];
851       htri_t is_scale;
852       int num_scales;
853       hsize_t maxdims[DIMS_3];
854       H5G_stat_t statbuf;
855       HDF5_OBJID_T dimscale_obj[NUM_DIMSCALES2], vars_dimscale_obj[NUM_DIMSCALES2];
856       int dimscale_cnt = 0;
857       int d, ndims;
858 
859       /* Create file access and create property lists. */
860       if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
861       if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR;
862 
863       /* Set latest_format in access propertly list. This ensures that
864        * the latest, greatest, HDF5 versions are used in the file. */
865       if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) ERR;
866 
867       /* Set H5P_CRT_ORDER_TRACKED in the creation property list. This
868        * turns on HDF5 creation ordering in the file. */
869       if (H5Pset_link_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
870 					       H5P_CRT_ORDER_INDEXED)) < 0) ERR;
871       if (H5Pset_attr_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
872 					       H5P_CRT_ORDER_INDEXED)) < 0) ERR;
873 
874       /* Create file. */
875       if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, fcpl_id, fapl_id)) < 0) ERR;
876 
877       /* Create the spaces that will be used for the dimscales. */
878       dims[0] = LAT_LEN;
879       if ((lat_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
880       dims[0] = LON_LEN;
881       if ((lon_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
882       dims[0] = TIME_LEN;
883       if ((time_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
884       dims[0] = LEN_LEN;
885       if ((len_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
886 
887       /* Create the space for the dataset. */
888       dims[0] = LAT_LEN;
889       dims[1] = LON_LEN;
890       dims[2] = TIME_LEN;
891       if ((pres_spaceid = H5Screate_simple(DIMS_3, dims, dims)) < 0) ERR;
892 
893       /* Create our dimension scales. */
894       if ((lat_dimscaleid = H5Dcreate1(fileid, LAT_NAME, H5T_NATIVE_INT,
895 				      lat_spaceid, H5P_DEFAULT)) < 0) ERR;
896       if (H5DSset_scale(lat_dimscaleid, NULL) < 0) ERR;
897       if ((lon_dimscaleid = H5Dcreate1(fileid, LON_NAME, H5T_NATIVE_INT,
898 				      lon_spaceid, H5P_DEFAULT)) < 0) ERR;
899       if (H5DSset_scale(lon_dimscaleid, NULL) < 0) ERR;
900       if ((time_dimscaleid = H5Dcreate1(fileid, TIME_NAME, H5T_NATIVE_INT,
901 				      time_spaceid, H5P_DEFAULT)) < 0) ERR;
902       if (H5DSset_scale(time_dimscaleid, NULL) < 0) ERR;
903       if ((len_dimscaleid = H5Dcreate1(fileid, LEN_NAME, H5T_NATIVE_INT,
904 				      len_spaceid, H5P_DEFAULT)) < 0) ERR;
905       if (H5DSset_scale(len_dimscaleid, NULL) < 0) ERR;
906 
907       /* Create a variable which uses these three dimscales. */
908       if ((pres_datasetid = H5Dcreate1(fileid, PRES_NAME1, H5T_NATIVE_FLOAT,
909 				      pres_spaceid, H5P_DEFAULT)) < 0) ERR;
910       if (H5DSattach_scale(pres_datasetid, lat_dimscaleid, 0) < 0) ERR;
911       if (H5DSattach_scale(pres_datasetid, lon_dimscaleid, 1) < 0) ERR;
912       if (H5DSattach_scale(pres_datasetid, time_dimscaleid, 2) < 0) ERR;
913 
914       /* Attach a dimscale to a dimscale. Unfortunately, HDF5 does not
915        * allow this. Woe is me. */
916       /*if (H5DSattach_scale(time_dimscaleid, len_dimscaleid, 0) < 0) ERR;*/
917 
918       /* Fold up our tents. */
919       if (H5Dclose(lat_dimscaleid) < 0 ||
920 	  H5Dclose(lon_dimscaleid) < 0 ||
921 	  H5Dclose(time_dimscaleid) < 0 ||
922 	  H5Dclose(len_dimscaleid) < 0 ||
923 	  H5Dclose(pres_datasetid) < 0 ||
924 	  H5Sclose(lat_spaceid) < 0 ||
925 	  H5Sclose(lon_spaceid) < 0 ||
926 	  H5Sclose(time_spaceid) < 0 ||
927 	  H5Sclose(pres_spaceid) < 0 ||
928 	  H5Sclose(len_spaceid) < 0 ||
929 	  H5Pclose(fapl_id) < 0 ||
930 	  H5Pclose(fcpl_id) < 0 ||
931 	  H5Fclose(fileid) < 0) ERR;
932 
933       /* Open the file. */
934       if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
935 
936       /* Loop through objects in the root group. */
937       if (H5Gget_num_objs(fileid, &num_obj) < 0) ERR;
938       for (i=0; i<num_obj; i++)
939       {
940 	 /* Get the type (i.e. group, dataset, etc.), and the name of
941 	  * the object. */
942 	 if ((obj_class = H5Gget_objtype_by_idx(fileid, i)) < 0) ERR;
943 	 if (H5Gget_objname_by_idx(fileid, i, obj_name, STR_LEN) < 0) ERR;
944 
945 	 /* Deal with object based on its obj_class. */
946 	 switch(obj_class)
947 	 {
948 	    case H5G_GROUP:
949 	       break;
950 	    case H5G_DATASET:
951 	       /* Open the dataset. */
952 	       if ((datasetid = H5Dopen1(fileid, obj_name)) < 0) ERR;
953 
954 	       /* Get space info. */
955 	       if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
956 	       if (H5Sget_simple_extent_dims(spaceid, dims, maxdims) < 0) ERR;
957 	       if ((ndims = H5Sget_simple_extent_ndims(spaceid)) < 0) ERR;
958 
959 	       /* Is this a dimscale? */
960 	       if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
961 	       if (is_scale)
962 	       {
963 		  /* fileno and objno uniquely identify an object and a
964 		   * HDF5 file. */
965 		  if (H5Gget_objinfo(datasetid, ".", 1, &statbuf) < 0) ERR;
966 		  dimscale_obj[dimscale_cnt].fileno[0] = statbuf.fileno[0];
967 		  dimscale_obj[dimscale_cnt].objno[0] = statbuf.objno[0];
968 		  dimscale_obj[dimscale_cnt].fileno[1] = statbuf.fileno[1];
969 		  dimscale_obj[dimscale_cnt].objno[1] = statbuf.objno[1];
970 		  dimscale_cnt++;
971 	       }
972 	       else
973 	       {
974 		  /* Here's how to get the number of scales attached
975 		   * to the dataset's dimension 0 and 1. */
976 		  if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
977 		  if (num_scales != 1) ERR;
978 		  if ((num_scales = H5DSget_num_scales(datasetid, 1)) < 0) ERR;
979 		  if (num_scales != 1) ERR;
980 
981 		  /* Go through all dimscales for this var and learn about them. */
982 		  for (d = 0; d < ndims; d++)
983 		  {
984 		     if (H5DSiterate_scales(datasetid, d, NULL, alien_visitor2,
985 		     &(vars_dimscale_obj[d])) < 0) ERR;
986 
987 		     /* Verify that the object ids passed from the
988 		      * alien_visitor2 function match the ones we found
989 		      * for the lat and lon datasets. */
990 		     if (vars_dimscale_obj[d].fileno[0] != dimscale_obj[d].fileno[0] ||
991 		     vars_dimscale_obj[d].objno[0] != dimscale_obj[d].objno[0]) ERR;
992 		     if (vars_dimscale_obj[d].fileno[1] != dimscale_obj[d].fileno[1] ||
993 		     vars_dimscale_obj[d].objno[1] != dimscale_obj[d].objno[1]) ERR;
994 		  }
995 	       }
996 	       if (H5Dclose(datasetid) < 0) ERR;
997 	       if (H5Sclose(spaceid) < 0) ERR;
998 	       break;
999 	    case H5G_TYPE:
1000 	       break;
1001 	    case H5G_LINK:
1002 	       break;
1003 	    default:
1004 	       printf("Unknown object class %d!", obj_class);
1005 	 }
1006       }
1007 
1008       /* Close up the shop. */
1009       if (H5Fclose(fileid) < 0) ERR;
1010    }
1011 
1012    SUMMARIZE_ERR;
1013    FINAL_RESULTS;
1014 }
1015 
1016