1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 #include "H5Omodule.h"          /* This source code file is part of the H5O module */
15 #define H5S_FRIEND		/*prevent warning from including H5Spkg.h */
16 
17 #include "H5private.h"		/* Generic Functions			*/
18 #include "H5Dprivate.h"		/* Datasets				*/
19 #include "H5Eprivate.h"		/* Error handling		  	*/
20 #include "H5FLprivate.h"	/* Free lists                           */
21 #include "H5Gprivate.h"		/* Groups			  	*/
22 #include "H5MMprivate.h"	/* Memory management			*/
23 #include "H5Opkg.h"		/* Object headers		  	*/
24 #include "H5Spkg.h"		/* Dataspaces 				*/
25 
26 
27 /* PRIVATE PROTOTYPES */
28 static void *H5O__sdspace_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags,
29     unsigned *ioflags, size_t p_size, const uint8_t *p);
30 static herr_t H5O_sdspace_encode(H5F_t *f, uint8_t *p, const void *_mesg);
31 static void *H5O_sdspace_copy(const void *_mesg, void *_dest);
32 static size_t H5O_sdspace_size(const H5F_t *f, const void *_mesg);
33 static herr_t H5O__sdspace_reset(void *_mesg);
34 static herr_t H5O__sdspace_free(void *_mesg);
35 static herr_t H5O_sdspace_pre_copy_file(H5F_t *file_src, const void *mesg_src,
36     hbool_t *deleted, const H5O_copy_t *cpy_info, void *_udata);
37 static herr_t H5O__sdspace_debug(H5F_t *f, const void *_mesg, FILE * stream,
38     int indent, int fwidth);
39 
40 /* Set up & include shared message "interface" info */
41 #define H5O_SHARED_TYPE			H5O_MSG_SDSPACE
42 #define H5O_SHARED_DECODE		H5O_sdspace_shared_decode
43 #define H5O_SHARED_DECODE_REAL		H5O__sdspace_decode
44 #define H5O_SHARED_ENCODE		H5O_sdspace_shared_encode
45 #define H5O_SHARED_ENCODE_REAL		H5O_sdspace_encode
46 #define H5O_SHARED_SIZE			H5O_sdspace_shared_size
47 #define H5O_SHARED_SIZE_REAL		H5O_sdspace_size
48 #define H5O_SHARED_DELETE		H5O__sdspace_shared_delete
49 #undef H5O_SHARED_DELETE_REAL
50 #define H5O_SHARED_LINK			H5O__sdspace_shared_link
51 #undef H5O_SHARED_LINK_REAL
52 #define H5O_SHARED_COPY_FILE		H5O__sdspace_shared_copy_file
53 #undef H5O_SHARED_COPY_FILE_REAL
54 #define H5O_SHARED_POST_COPY_FILE	H5O_sdspace_shared_post_copy_file
55 #undef H5O_SHARED_POST_COPY_FILE_REAL
56 #undef  H5O_SHARED_POST_COPY_FILE_UPD
57 #define H5O_SHARED_DEBUG		H5O_sdspace_shared_debug
58 #define H5O_SHARED_DEBUG_REAL		H5O__sdspace_debug
59 #include "H5Oshared.h"			/* Shared Object Header Message Callbacks */
60 
61 /* This message derives from H5O message class */
62 const H5O_msg_class_t H5O_MSG_SDSPACE[1] = {{
63     H5O_SDSPACE_ID,	    	/* message id number		    	*/
64     "dataspace",	    	/* message name for debugging	   	*/
65     sizeof(H5S_extent_t),   	/* native message size		    	*/
66     H5O_SHARE_IS_SHARABLE|H5O_SHARE_IN_OHDR,	/* messages are sharable?       */
67     H5O_sdspace_shared_decode,	/* decode message			*/
68     H5O_sdspace_shared_encode,	/* encode message			*/
69     H5O_sdspace_copy,	    	/* copy the native value		*/
70     H5O_sdspace_shared_size,	/* size of symbol table entry	    	*/
71     H5O__sdspace_reset,	    	/* default reset method		    	*/
72     H5O__sdspace_free,		/* free method				*/
73     H5O__sdspace_shared_delete,	/* file delete method		*/
74     H5O__sdspace_shared_link,	/* link method			*/
75     NULL,			/* set share method		*/
76     NULL,		    	/*can share method		*/
77     H5O_sdspace_pre_copy_file,	/* pre copy native value to file */
78     H5O__sdspace_shared_copy_file,/* copy native value to file    */
79     H5O_sdspace_shared_post_copy_file,/* post copy native value to file    */
80     NULL,			/* get creation index		*/
81     NULL,			/* set creation index		*/
82     H5O_sdspace_shared_debug	/* debug the message		    	*/
83 }};
84 
85 /* Declare external the free list for H5S_extent_t's */
86 H5FL_EXTERN(H5S_extent_t);
87 
88 /* Declare external the free list for hsize_t arrays */
89 H5FL_ARR_EXTERN(hsize_t);
90 
91 
92 /*--------------------------------------------------------------------------
93  NAME
94     H5O__sdspace_decode
95  PURPOSE
96     Decode a simple dimensionality message and return a pointer to a memory
97 	struct with the decoded information
98  USAGE
99     void *H5O__sdspace_decode(f, mesg_flags, p)
100 	H5F_t *f;	        IN: pointer to the HDF5 file struct
101         unsigned mesg_flags;    IN: Message flags to influence decoding
102 	const uint8 *p;		IN: the raw information buffer
103  RETURNS
104     Pointer to the new message in native order on success, NULL on failure
105  DESCRIPTION
106 	This function decodes the "raw" disk form of a simple dimensionality
107     message into a struct in memory native format.  The struct is allocated
108     within this function using malloc() and is returned to the caller.
109 --------------------------------------------------------------------------*/
110 static void *
H5O__sdspace_decode(H5F_t * f,H5O_t H5_ATTR_UNUSED * open_oh,unsigned H5_ATTR_UNUSED mesg_flags,unsigned H5_ATTR_UNUSED * ioflags,size_t H5_ATTR_UNUSED p_size,const uint8_t * p)111 H5O__sdspace_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh,
112     unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
113     size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
114 {
115     H5S_extent_t	*sdim = NULL;/* New extent dimensionality structure */
116     unsigned		flags, version;
117     unsigned		i;                      /* Local counting variable */
118     void                *ret_value = NULL;      /* Return value */
119 
120     FUNC_ENTER_STATIC
121 
122     /* check args */
123     HDassert(f);
124     HDassert(p);
125 
126     /* decode */
127     if(NULL == (sdim = H5FL_CALLOC(H5S_extent_t)))
128         HGOTO_ERROR(H5E_DATASPACE, H5E_NOSPACE, NULL, "dataspace structure allocation failed")
129 
130     /* Check version */
131     version = *p++;
132     if(version < H5O_SDSPACE_VERSION_1 || version > H5O_SDSPACE_VERSION_2)
133         HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "wrong version number in dataspace message")
134     sdim->version = version;
135 
136     /* Get rank */
137     sdim->rank = *p++;
138     if(sdim->rank > H5S_MAX_RANK)
139         HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "simple dataspace dimensionality is too large")
140 
141     /* Get dataspace flags for later */
142     flags = *p++;
143 
144     /* Get or determine the type of the extent */
145     if(version >= H5O_SDSPACE_VERSION_2)
146         sdim->type = (H5S_class_t)*p++;
147     else {
148         /* Set the dataspace type to be simple or scalar as appropriate */
149         if(sdim->rank > 0)
150             sdim->type = H5S_SIMPLE;
151         else
152             sdim->type = H5S_SCALAR;
153 
154         /* Increment past reserved byte */
155         p++;
156     } /* end else */
157     HDassert(sdim->type != H5S_NULL || sdim->version >= H5O_SDSPACE_VERSION_2);
158 
159     /* Only Version 1 has these reserved bytes */
160     if(version == H5O_SDSPACE_VERSION_1)
161         p += 4; /*reserved*/
162 
163     /* Decode dimension sizes */
164     if(sdim->rank > 0) {
165         if(NULL == (sdim->size = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)sdim->rank)))
166             HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
167 
168         for(i = 0; i < sdim->rank; i++)
169             H5F_DECODE_LENGTH(f, p, sdim->size[i]);
170 
171         if(flags & H5S_VALID_MAX) {
172             if(NULL == (sdim->max = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)sdim->rank)))
173                 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
174             for(i = 0; i < sdim->rank; i++)
175                 H5F_DECODE_LENGTH (f, p, sdim->max[i]);
176         } /* end if */
177     } /* end if */
178 
179     /* Compute the number of elements in the extent */
180     if(sdim->type == H5S_NULL)
181         sdim->nelem = 0;
182     else {
183         for(i = 0, sdim->nelem = 1; i < sdim->rank; i++)
184             sdim->nelem *= sdim->size[i];
185     } /* end else */
186 
187     /* Set return value */
188     ret_value = (void*)sdim;	/*success*/
189 
190 done:
191     if(!ret_value && sdim) {
192         H5S_extent_release(sdim);
193         sdim = H5FL_FREE(H5S_extent_t, sdim);
194     } /* end if */
195 
196     FUNC_LEAVE_NOAPI(ret_value)
197 } /* end H5O__sdspace_decode() */
198 
199 
200 /*--------------------------------------------------------------------------
201  NAME
202     H5O_sdspace_encode
203  PURPOSE
204     Encode a simple dimensionality message
205  USAGE
206     herr_t H5O_sdspace_encode(f, raw_size, p, mesg)
207 	H5F_t *f;	        IN: pointer to the HDF5 file struct
208 	size_t raw_size;	IN: size of the raw information buffer
209 	const uint8 *p;		IN: the raw information buffer
210 	const void *mesg;	IN: Pointer to the extent dimensionality struct
211  RETURNS
212     Non-negative on success/Negative on failure
213  DESCRIPTION
214 	This function encodes the native memory form of the simple
215     dimensionality message in the "raw" disk form.
216 
217  MODIFICATIONS
218 	Robb Matzke, 1998-04-09
219 	The current and maximum dimensions are now H5F_SIZEOF_SIZET bytes
220 	instead of just four bytes.
221 
222   	Robb Matzke, 1998-07-20
223         Added a version number and reformatted the message for aligment.
224 
225         Raymond Lu
226         April 8, 2004
227         Added the type of dataspace into this header message using a reserved
228         byte.
229 
230 --------------------------------------------------------------------------*/
231 static herr_t
H5O_sdspace_encode(H5F_t * f,uint8_t * p,const void * _mesg)232 H5O_sdspace_encode(H5F_t *f, uint8_t *p, const void *_mesg)
233 {
234     const H5S_extent_t	*sdim = (const H5S_extent_t *)_mesg;
235     unsigned		flags = 0;
236     unsigned		u;  /* Local counting variable */
237 
238     FUNC_ENTER_NOAPI_NOINIT_NOERR
239 
240     /* check args */
241     HDassert(f);
242     HDassert(p);
243     HDassert(sdim);
244 
245     /* Version */
246     HDassert(sdim->version > 0);
247     HDassert(sdim->type != H5S_NULL || sdim->version >= H5O_SDSPACE_VERSION_2);
248     *p++ = (uint8_t)sdim->version;
249 
250     /* Rank */
251     *p++ = (uint8_t)sdim->rank;
252 
253     /* Flags */
254     if(sdim->max)
255         flags |= H5S_VALID_MAX;
256     *p++ = (uint8_t)flags;
257 
258     /* Dataspace type */
259     if(sdim->version > H5O_SDSPACE_VERSION_1)
260         *p++ = sdim->type;
261     else {
262         *p++ = 0; /*reserved*/
263         *p++ = 0; /*reserved*/
264         *p++ = 0; /*reserved*/
265         *p++ = 0; /*reserved*/
266         *p++ = 0; /*reserved*/
267     } /* end else */
268 
269     /* Current & maximum dimensions */
270     if(sdim->rank > 0) {
271         for(u = 0; u < sdim->rank; u++)
272             H5F_ENCODE_LENGTH(f, p, sdim->size[u]);
273         if(flags & H5S_VALID_MAX) {
274             for(u = 0; u < sdim->rank; u++)
275                 H5F_ENCODE_LENGTH(f, p, sdim->max[u]);
276         } /* end if */
277     } /* end if */
278 
279     FUNC_LEAVE_NOAPI(SUCCEED)
280 } /* end H5O_sdspace_encode() */
281 
282 
283 /*--------------------------------------------------------------------------
284  NAME
285     H5O_sdspace_copy
286  PURPOSE
287     Copies a message from MESG to DEST, allocating DEST if necessary.
288  USAGE
289     void *H5O_sdspace_copy(_mesg, _dest)
290 	const void *_mesg;	IN: Pointer to the source extent dimensionality struct
291 	const void *_dest;	IN: Pointer to the destination extent dimensionality struct
292  RETURNS
293     Pointer to DEST on success, NULL on failure
294  DESCRIPTION
295 	This function copies a native (memory) simple dimensionality message,
296     allocating the destination structure if necessary.
297 --------------------------------------------------------------------------*/
298 static void *
H5O_sdspace_copy(const void * _mesg,void * _dest)299 H5O_sdspace_copy(const void *_mesg, void *_dest)
300 {
301     const H5S_extent_t	   *mesg = (const H5S_extent_t *)_mesg;
302     H5S_extent_t	   *dest = (H5S_extent_t *)_dest;
303     void                   *ret_value = NULL;   /* Return value */
304 
305     FUNC_ENTER_NOAPI_NOINIT
306 
307     /* check args */
308     HDassert(mesg);
309     if(!dest && NULL == (dest = H5FL_CALLOC(H5S_extent_t)))
310 	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
311 
312     /* Copy extent information */
313     if(H5S_extent_copy_real(dest, mesg, TRUE) < 0)
314         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy extent")
315 
316     /* Set return value */
317     ret_value = dest;
318 
319 done:
320     if(NULL == ret_value)
321         if(dest && NULL == _dest)
322             dest = H5FL_FREE(H5S_extent_t, dest);
323 
324     FUNC_LEAVE_NOAPI(ret_value)
325 } /* end H5O_sdspace_copy() */
326 
327 
328 /*--------------------------------------------------------------------------
329  NAME
330     H5O_sdspace_size
331  PURPOSE
332     Return the raw message size in bytes
333  USAGE
334     void *H5O_sdspace_size(f, mesg)
335 	H5F_t *f;	  IN: pointer to the HDF5 file struct
336 	const void *mesg;	IN: Pointer to the source extent dimensionality struct
337  RETURNS
338     Size of message on success, zero on failure
339  DESCRIPTION
340 	This function returns the size of the raw simple dimensionality message on
341     success.  (Not counting the message type or size fields, only the data
342     portion of the message).  It doesn't take into account alignment.
343 
344  MODIFICATIONS
345 	Robb Matzke, 1998-04-09
346 	The current and maximum dimensions are now H5F_SIZEOF_SIZET bytes
347 	instead of just four bytes.
348 --------------------------------------------------------------------------*/
349 static size_t
H5O_sdspace_size(const H5F_t * f,const void * _mesg)350 H5O_sdspace_size(const H5F_t *f, const void *_mesg)
351 {
352     const H5S_extent_t	*space = (const H5S_extent_t *)_mesg;
353     size_t		ret_value = 0;  /* Return value */
354 
355     FUNC_ENTER_NOAPI_NOINIT_NOERR
356 
357     /* Basic information for all dataspace messages */
358     ret_value = 1 +             /* Version */
359             1 +                 /* Rank */
360             1 +                 /* Flags */
361             1 +                 /* Dataspace type/reserved */
362             ((space->version > H5O_SDSPACE_VERSION_1) ? 0 : 4); /* Eliminated/reserved */
363 
364     /* Add in the dimension sizes */
365     ret_value += space->rank * H5F_SIZEOF_SIZE(f);
366 
367     /* Add in the space for the maximum dimensions, if they are present */
368     ret_value += space->max ? (space->rank * H5F_SIZEOF_SIZE(f)) : 0;
369 
370     FUNC_LEAVE_NOAPI(ret_value)
371 } /* end H5O_sdspace_size() */
372 
373 
374 /*-------------------------------------------------------------------------
375  * Function:	H5O__sdspace_reset
376  *
377  * Purpose:	Frees the inside of a dataspace message and resets it to some
378  *		initial value.
379  *
380  * Return:	Non-negative on success/Negative on failure
381  *
382  * Programmer:	Robb Matzke
383  *              Thursday, April 30, 1998
384  *
385  *-------------------------------------------------------------------------
386  */
387 static herr_t
H5O__sdspace_reset(void * _mesg)388 H5O__sdspace_reset(void *_mesg)
389 {
390     H5S_extent_t	*mesg = (H5S_extent_t*)_mesg;
391 
392     FUNC_ENTER_STATIC_NOERR
393 
394     H5S_extent_release(mesg);
395 
396     FUNC_LEAVE_NOAPI(SUCCEED)
397 } /* end H5O__sdspace_reset() */
398 
399 
400 /*-------------------------------------------------------------------------
401  * Function:	H5O__sdsdpace_free
402  *
403  * Purpose:	Frees the message
404  *
405  * Return:	Non-negative on success/Negative on failure
406  *
407  * Programmer:	Quincey Koziol
408  *              Thursday, March 30, 2000
409  *
410  *-------------------------------------------------------------------------
411  */
412 static herr_t
H5O__sdspace_free(void * mesg)413 H5O__sdspace_free(void *mesg)
414 {
415     FUNC_ENTER_STATIC_NOERR
416 
417     HDassert(mesg);
418 
419     mesg = H5FL_FREE(H5S_extent_t, mesg);
420 
421     FUNC_LEAVE_NOAPI(SUCCEED)
422 } /* end H5O__sdspace_free() */
423 
424 
425 /*-------------------------------------------------------------------------
426  * Function:    H5O_sdspace_pre_copy_file
427  *
428  * Purpose:     Perform any necessary actions before copying message between
429  *              files
430  *
431  * Return:      Success:        Non-negative
432  *
433  *              Failure:        Negative
434  *
435  * Programmer:  Quincey Koziol
436  *              November 30, 2006
437  *
438  *-------------------------------------------------------------------------
439  */
440 static herr_t
H5O_sdspace_pre_copy_file(H5F_t H5_ATTR_UNUSED * file_src,const void * mesg_src,hbool_t H5_ATTR_UNUSED * deleted,const H5O_copy_t * cpy_info,void * _udata)441 H5O_sdspace_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *mesg_src,
442     hbool_t H5_ATTR_UNUSED *deleted, const H5O_copy_t *cpy_info, void *_udata)
443 {
444     const H5S_extent_t *src_space_extent = (const H5S_extent_t *)mesg_src;  /* Source dataspace extent */
445     H5D_copy_file_ud_t *udata = (H5D_copy_file_ud_t *)_udata;   /* Dataset copying user data */
446     herr_t         ret_value = SUCCEED;          /* Return value */
447 
448     FUNC_ENTER_NOAPI_NOINIT
449 
450     /* check args */
451     HDassert(file_src);
452     HDassert(src_space_extent);
453     HDassert(cpy_info);
454     HDassert(cpy_info->file_dst);
455 
456     /* Check to ensure that the version of the message to be copied does not exceed
457        the message version allowed by the destination file's high bound */
458     if(src_space_extent->version > H5O_sdspace_ver_bounds[H5F_HIGH_BOUND(cpy_info->file_dst)])
459         HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "dataspace message version out of bounds")
460 
461     /* If the user data is non-NULL, assume we are copying a dataset
462      * and make a copy of the dataspace extent for later in the object copying
463      * process.  (We currently only need to make a copy of the dataspace extent
464      * if the layout is an early version, but that information isn't
465      * available here, so we just make a copy of it in all cases)
466      */
467     if(udata) {
468         /* Allocate copy of dataspace extent */
469         if(NULL == (udata->src_space_extent = H5FL_CALLOC(H5S_extent_t)))
470             HGOTO_ERROR(H5E_DATASPACE, H5E_NOSPACE, FAIL, "dataspace extent allocation failed")
471 
472         /* Create a copy of the dataspace extent */
473         if(H5S_extent_copy_real(udata->src_space_extent, src_space_extent, TRUE) < 0)
474             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy extent")
475     } /* end if */
476 
477 done:
478     FUNC_LEAVE_NOAPI(ret_value)
479 } /* end H5O_dspace_pre_copy_file() */
480 
481 
482 /*--------------------------------------------------------------------------
483  NAME
484     H5O__sdspace_debug
485  PURPOSE
486     Prints debugging information for a simple dimensionality message
487  USAGE
488     void *H5O__sdspace_debug(f, mesg, stream, indent, fwidth)
489 	H5F_t *f;	        IN: pointer to the HDF5 file struct
490 	const void *mesg;	IN: Pointer to the source extent dimensionality struct
491 	FILE *stream;		IN: Pointer to the stream for output data
492 	int indent;		IN: Amount to indent information by
493 	int fwidth;		IN: Field width (?)
494  RETURNS
495     Non-negative on success/Negative on failure
496  DESCRIPTION
497 	This function prints debugging output to the stream passed as a
498     parameter.
499 --------------------------------------------------------------------------*/
500 static herr_t
H5O__sdspace_debug(H5F_t H5_ATTR_UNUSED * f,const void * mesg,FILE * stream,int indent,int fwidth)501 H5O__sdspace_debug(H5F_t H5_ATTR_UNUSED *f, const void *mesg, FILE * stream,
502     int indent, int fwidth)
503 {
504     const H5S_extent_t	   *sdim = (const H5S_extent_t *)mesg;
505 
506     FUNC_ENTER_STATIC_NOERR
507 
508     /* check args */
509     HDassert(f);
510     HDassert(sdim);
511     HDassert(stream);
512     HDassert(indent >= 0);
513     HDassert(fwidth >= 0);
514 
515     HDfprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth,
516 	    "Rank:",
517 	    (unsigned long) (sdim->rank));
518 
519     if(sdim->rank > 0) {
520         unsigned		    u;	/* local counting variable */
521 
522         HDfprintf(stream, "%*s%-*s {", indent, "", fwidth, "Dim Size:");
523         for(u = 0; u < sdim->rank; u++)
524             HDfprintf (stream, "%s%Hu", u?", ":"", sdim->size[u]);
525         HDfprintf (stream, "}\n");
526 
527         HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Dim Max:");
528         if(sdim->max) {
529             HDfprintf (stream, "{");
530             for(u = 0; u < sdim->rank; u++) {
531                 if(H5S_UNLIMITED==sdim->max[u])
532                     HDfprintf (stream, "%sUNLIM", u?", ":"");
533                 else
534                     HDfprintf (stream, "%s%Hu", u?", ":"", sdim->max[u]);
535             } /* end for */
536             HDfprintf (stream, "}\n");
537         } /* end if */
538         else
539             HDfprintf (stream, "CONSTANT\n");
540     } /* end if */
541 
542     FUNC_LEAVE_NOAPI(SUCCEED)
543 } /* end H5O__sdspace_debug() */
544 
545