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