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 /*
15  * Programmer: Robb Matzke <matzke@llnl.gov>
16  *	       Tuesday, November 25, 1997
17  */
18 
19 #include "H5Omodule.h"          /* This source code file is part of the H5O module */
20 
21 
22 #include "H5private.h"		/* Generic Functions			*/
23 #include "H5Eprivate.h"		/* Error handling		  	*/
24 #include "H5Fprivate.h"		/* File access				*/
25 #include "H5HLprivate.h"	/* Local Heaps				*/
26 #include "H5MMprivate.h"	/* Memory management			*/
27 #include "H5Opkg.h"             /* Object headers			*/
28 
29 /* PRIVATE PROTOTYPES */
30 static void *H5O_efl_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags,
31     unsigned *ioflags, size_t p_size, const uint8_t *p);
32 static herr_t H5O_efl_encode(H5F_t *f, hbool_t disable_shared, uint8_t *p, const void *_mesg);
33 static void *H5O_efl_copy(const void *_mesg, void *_dest);
34 static size_t H5O_efl_size(const H5F_t *f, hbool_t disable_shared, const void *_mesg);
35 static herr_t H5O__efl_reset(void *_mesg);
36 static void *H5O__efl_copy_file(H5F_t *file_src, void *mesg_src,
37     H5F_t *file_dst, hbool_t *recompute_size, unsigned *mesg_flags,
38     H5O_copy_t *cpy_info, void *udata);
39 static herr_t H5O__efl_debug(H5F_t *f, const void *_mesg, FILE * stream,
40     int indent, int fwidth);
41 
42 /* This message derives from H5O message class */
43 const H5O_msg_class_t H5O_MSG_EFL[1] = {{
44     H5O_EFL_ID,		    	/*message id number		*/
45     "external file list",   	/*message name for debugging    */
46     sizeof(H5O_efl_t),	    	/*native message size	    	*/
47     0,				/* messages are sharable?       */
48     H5O_efl_decode,	    	/*decode message		*/
49     H5O_efl_encode,	    	/*encode message		*/
50     H5O_efl_copy,	    	/*copy native value		*/
51     H5O_efl_size,	    	/*size of message on disk	*/
52     H5O__efl_reset,	    	/*reset method		    	*/
53     NULL,		        /* free method			*/
54     NULL,		        /* file delete method		*/
55     NULL,			/* link method			*/
56     NULL,			/*set share method		*/
57     NULL,		    	/*can share method		*/
58     NULL,			/* pre copy native value to file */
59     H5O__efl_copy_file,		/* copy native value to file    */
60     NULL,			/* post copy native value to file    */
61     NULL,			/* get creation index		*/
62     NULL,			/* set creation index		*/
63     H5O__efl_debug	    	/*debug the message		*/
64 }};
65 
66 #define H5O_EFL_VERSION		1
67 
68 
69 /*-------------------------------------------------------------------------
70  * Function:    H5O_efl_decode
71  *
72  * Purpose:	Decode an external file list message and return a pointer to
73  *          the message (and some other data).
74  *
75  * Return:  Success:    Ptr to a new message struct.
76  *
77  *          Failure:    NULL
78  *
79  * Programmer:	Robb Matzke
80  *              Tuesday, November 25, 1997
81  *
82  * Modification:
83  *              Raymond Lu
84  *              11 April 2011
85  *              We allow zero dimension size starting from the 1.8.7 release.
86  *              The dataset size of external storage can be zero.
87  *-------------------------------------------------------------------------
88  */
89 static void *
H5O_efl_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)90 H5O_efl_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh,
91     unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
92     size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
93 {
94     H5O_efl_t   *mesg = NULL;
95     int         version;
96     const char  *s = NULL;
97     H5HL_t      *heap;
98     size_t      u;                  /* Local index variable */
99     void        *ret_value = NULL;  /* Return value */
100 
101     FUNC_ENTER_NOAPI_NOINIT
102 
103     /* Check args */
104     HDassert(f);
105     HDassert(p);
106 
107     if(NULL == (mesg = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t))))
108         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
109 
110     /* Version */
111     version = *p++;
112     if(version != H5O_EFL_VERSION)
113         HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for external file list message")
114 
115     /* Reserved */
116     p += 3;
117 
118     /* Number of slots */
119     UINT16DECODE(p, mesg->nalloc);
120     HDassert(mesg->nalloc>0);
121     UINT16DECODE(p, mesg->nused);
122     HDassert(mesg->nused <= mesg->nalloc);
123 
124     /* Heap address */
125     H5F_addr_decode(f, &p, &(mesg->heap_addr));
126 
127 #ifndef NDEBUG
128     HDassert(H5F_addr_defined(mesg->heap_addr));
129 
130     if(NULL == (heap = H5HL_protect(f, mesg->heap_addr, H5AC__READ_ONLY_FLAG)))
131         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read protect link value")
132 
133     s = (const char *)H5HL_offset_into(heap, 0);
134 
135     HDassert(s && !*s);
136 
137     if(H5HL_unprotect(heap) < 0)
138         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read unprotect link value")
139     heap = NULL;
140 #endif
141 
142     /* Decode the file list */
143     mesg->slot = (H5O_efl_entry_t *)H5MM_calloc(mesg->nalloc * sizeof(H5O_efl_entry_t));
144     if(NULL == mesg->slot)
145         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
146 
147     if(NULL == (heap = H5HL_protect(f, mesg->heap_addr, H5AC__READ_ONLY_FLAG)))
148         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read protect link value")
149     for(u = 0; u < mesg->nused; u++) {
150         /* Name */
151         H5F_DECODE_LENGTH (f, p, mesg->slot[u].name_offset);
152 
153         if((s = (const char *)H5HL_offset_into(heap, mesg->slot[u].name_offset)) == NULL)
154             HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "unable to get external file name")
155         if(*s == (char)'\0')
156             HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "invalid external file name")
157         mesg->slot[u].name = H5MM_xstrdup (s);
158         HDassert(mesg->slot[u].name);
159 
160         /* File offset */
161         H5F_DECODE_LENGTH (f, p, mesg->slot[u].offset);
162 
163         /* Size */
164         H5F_DECODE_LENGTH (f, p, mesg->slot[u].size);
165     } /* end for */
166 
167     if(H5HL_unprotect(heap) < 0)
168         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read unprotect link value")
169     heap = NULL;
170 
171     /* Set return value */
172     ret_value = mesg;
173 
174 done:
175     if(ret_value == NULL)
176         if(mesg != NULL)
177             H5MM_xfree(mesg);
178 
179     FUNC_LEAVE_NOAPI(ret_value)
180 } /* end H5O_efl_decode() */
181 
182 
183 /*-------------------------------------------------------------------------
184  * Function:	H5O_efl_encode
185  *
186  * Purpose:	Encodes a message.
187  *
188  * Return:	Non-negative on success/Negative on failure
189  *
190  * Programmer:	Robb Matzke
191  *		Tuesday, November 25, 1997
192  *
193  *-------------------------------------------------------------------------
194  */
195 static herr_t
H5O_efl_encode(H5F_t * f,hbool_t H5_ATTR_UNUSED disable_shared,uint8_t * p,const void * _mesg)196 H5O_efl_encode(H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, uint8_t *p, const void *_mesg)
197 {
198     const H5O_efl_t	*mesg = (const H5O_efl_t *)_mesg;
199     size_t		u;      /* Local index variable */
200 
201     FUNC_ENTER_NOAPI_NOINIT_NOERR
202 
203     /* check args */
204     HDassert(f);
205     HDassert(mesg);
206     HDassert(p);
207 
208     /* Version */
209     *p++ = H5O_EFL_VERSION;
210 
211     /* Reserved */
212     *p++ = 0;
213     *p++ = 0;
214     *p++ = 0;
215 
216     /* Number of slots */
217     HDassert(mesg->nalloc > 0);
218     UINT16ENCODE(p, mesg->nused); /*yes, twice*/
219     HDassert(mesg->nused > 0 && mesg->nused <= mesg->nalloc);
220     UINT16ENCODE(p, mesg->nused);
221 
222     /* Heap address */
223     HDassert(H5F_addr_defined(mesg->heap_addr));
224     H5F_addr_encode(f, &p, mesg->heap_addr);
225 
226     /* Encode file list */
227     for(u = 0; u < mesg->nused; u++) {
228 	/*
229 	 * The name should have been added to the heap when the dataset was
230 	 * created.
231 	 */
232 	HDassert(mesg->slot[u].name_offset);
233 	H5F_ENCODE_LENGTH(f, p, mesg->slot[u].name_offset);
234 	H5F_ENCODE_LENGTH(f, p, (hsize_t)mesg->slot[u].offset);
235 	H5F_ENCODE_LENGTH(f, p, mesg->slot[u].size);
236     } /* end for */
237 
238     FUNC_LEAVE_NOAPI(SUCCEED)
239 } /* end H5O_efl_encode() */
240 
241 
242 /*-------------------------------------------------------------------------
243  * Function:	H5O_efl_copy
244  *
245  * Purpose:	Copies a message from _MESG to _DEST, allocating _DEST if
246  *		necessary.
247  *
248  * Return:	Success:	Ptr to _DEST
249  *
250  *		Failure:	NULL
251  *
252  * Programmer:	Robb Matzke
253  *		Tuesday, November 25, 1997
254  *
255  *-------------------------------------------------------------------------
256  */
257 static void *
H5O_efl_copy(const void * _mesg,void * _dest)258 H5O_efl_copy(const void *_mesg, void *_dest)
259 {
260     const H5O_efl_t	*mesg = (const H5O_efl_t *) _mesg;
261     H5O_efl_t		*dest = (H5O_efl_t *) _dest;
262     size_t		u;                      /* Local index variable */
263     hbool_t             slot_allocated = FALSE; /* Flag to indicate that dynamic allocation has begun */
264     void                *ret_value = NULL;      /* Return value */
265 
266     FUNC_ENTER_NOAPI_NOINIT
267 
268     /* check args */
269     HDassert(mesg);
270 
271     /* Allocate destination message, if necessary */
272     if(!dest && NULL == (dest = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t))))
273         HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "can't allocate efl message")
274 
275     /* copy */
276     *dest = *mesg;
277 
278     /* Deep copy allocated information */
279     if(dest->nalloc > 0) {
280         if(NULL == (dest->slot = (H5O_efl_entry_t *)H5MM_calloc(dest->nalloc * sizeof(H5O_efl_entry_t))))
281             HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "can't allocate efl message slots")
282         slot_allocated = TRUE;
283         for(u = 0; u < mesg->nused; u++) {
284             dest->slot[u] = mesg->slot[u];
285             if(NULL == (dest->slot[u].name = H5MM_xstrdup(mesg->slot[u].name)))
286                 HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "can't allocate efl message slot name")
287         } /* end for */
288     } /* end if */
289 
290     /* Set return value */
291     ret_value = dest;
292 
293 done:
294     if(NULL == ret_value) {
295         if(slot_allocated) {
296             for(u = 0; u < dest->nused; u++)
297                 if(dest->slot[u].name != NULL && dest->slot[u].name != mesg->slot[u].name)
298                     dest->slot[u].name = (char *)H5MM_xfree(dest->slot[u].name);
299             dest->slot = (H5O_efl_entry_t *)H5MM_xfree(dest->slot);
300         } /* end if */
301         if(NULL == _dest)
302             dest = (H5O_efl_t *)H5MM_xfree(dest);
303     } /* end if */
304 
305     FUNC_LEAVE_NOAPI(ret_value)
306 } /* end H5O_efl_copy() */
307 
308 
309 /*-------------------------------------------------------------------------
310  * Function:	H5O_efl_size
311  *
312  * Purpose:	Returns the size of the raw message in bytes not counting the
313  *		message type or size fields, but only the data fields.	This
314  *		function doesn't take into account message alignment. This
315  *		function doesn't count unused slots.
316  *
317  * Return:	Success:	Message data size in bytes.
318  *
319  *		Failure:	0
320  *
321  * Programmer:	Robb Matzke
322  *		Tuesday, November 25, 1997
323  *
324  *-------------------------------------------------------------------------
325  */
326 static size_t
H5O_efl_size(const H5F_t * f,hbool_t H5_ATTR_UNUSED disable_shared,const void * _mesg)327 H5O_efl_size(const H5F_t *f, hbool_t H5_ATTR_UNUSED disable_shared, const void *_mesg)
328 {
329     const H5O_efl_t	*mesg = (const H5O_efl_t *) _mesg;
330     size_t		ret_value = 0;
331 
332     FUNC_ENTER_NOAPI_NOINIT_NOERR
333 
334     /* check args */
335     HDassert(f);
336     HDassert(mesg);
337 
338     ret_value = (size_t)H5F_SIZEOF_ADDR(f) +			/*heap address	*/
339 		2 +					/*slots allocated*/
340 		2 +					/*num slots used*/
341 		4 +					/*reserved	*/
342 		mesg->nused * ((size_t)H5F_SIZEOF_SIZE(f) +	/*name offset	*/
343 			       (size_t)H5F_SIZEOF_SIZE(f) +	/*file offset	*/
344 			       (size_t)H5F_SIZEOF_SIZE(f));	/*file size	*/
345 
346     FUNC_LEAVE_NOAPI(ret_value)
347 } /* end H5O_efl_size() */
348 
349 
350 /*-------------------------------------------------------------------------
351  * Function:	H5O__efl_reset
352  *
353  * Purpose:	Frees internal pointers and resets the message to an
354  *		initialial state.
355  *
356  * Return:	Non-negative on success/Negative on failure
357  *
358  * Programmer:	Robb Matzke
359  *		Tuesday, November 25, 1997
360  *
361  *-------------------------------------------------------------------------
362  */
363 static herr_t
H5O__efl_reset(void * _mesg)364 H5O__efl_reset(void *_mesg)
365 {
366     H5O_efl_t	*mesg = (H5O_efl_t *) _mesg;
367     size_t	u;              /* Local index variable */
368 
369     FUNC_ENTER_STATIC_NOERR
370 
371     /* check args */
372     HDassert(mesg);
373 
374     /* reset */
375     if(mesg->slot) {
376         for(u = 0; u < mesg->nused; u++) {
377             mesg->slot[u].name = (char *)H5MM_xfree(mesg->slot[u].name);
378             mesg->slot[u].name_offset = 0;
379         } /* end for */
380         mesg->slot = (H5O_efl_entry_t *)H5MM_xfree(mesg->slot);
381     } /* end if */
382     mesg->heap_addr = HADDR_UNDEF;
383     mesg->nused = mesg->nalloc = 0;
384 
385     FUNC_LEAVE_NOAPI(SUCCEED)
386 } /* end H5O__efl_reset() */
387 
388 
389 /*-------------------------------------------------------------------------
390  * Function:	H5O_efl_total_size
391  *
392  * Purpose:	Return the total size of the external file list by summing
393  *		the sizes of all of the files.
394  *
395  * Return:	Success:	Total reserved size for external data.
396  *
397  *		Failure:	0
398  *
399  * Programmer:	Robb Matzke
400  *              Tuesday, March  3, 1998
401  *
402  *-------------------------------------------------------------------------
403  */
404 hsize_t
H5O_efl_total_size(H5O_efl_t * efl)405 H5O_efl_total_size (H5O_efl_t *efl)
406 {
407     hsize_t	ret_value = 0, tmp;
408 
409     FUNC_ENTER_NOAPI_NOINIT
410 
411     if(efl->nused > 0 && H5O_EFL_UNLIMITED == efl->slot[efl->nused - 1].size)
412 	ret_value = H5O_EFL_UNLIMITED;
413     else {
414         size_t		u;      /* Local index variable */
415 
416 	for(u = 0; u < efl->nused; u++, ret_value = tmp) {
417 	    tmp = ret_value + efl->slot[u].size;
418 	    if(tmp <= ret_value)
419 		HGOTO_ERROR(H5E_EFL, H5E_OVERFLOW, 0, "total external storage size overflowed");
420 	} /* end for */
421     } /* end else */
422 
423 done:
424     FUNC_LEAVE_NOAPI(ret_value)
425 } /* end H5O_efl_total_size() */
426 
427 
428 /*-------------------------------------------------------------------------
429  * Function:    H5O__efl_copy_file
430  *
431  * Purpose:     Copies an efl message from _MESG to _DEST in file
432  *
433  * Return:      Success:        Ptr to _DEST
434  *
435  *              Failure:        NULL
436  *
437  * Programmer:  Peter Cao
438  *              September 29, 2005
439  *
440  *-------------------------------------------------------------------------
441  */
442 static void *
H5O__efl_copy_file(H5F_t H5_ATTR_UNUSED * file_src,void * mesg_src,H5F_t * file_dst,hbool_t H5_ATTR_UNUSED * recompute_size,unsigned H5_ATTR_UNUSED * mesg_flags,H5O_copy_t H5_ATTR_UNUSED * cpy_info,void H5_ATTR_UNUSED * _udata)443 H5O__efl_copy_file(H5F_t H5_ATTR_UNUSED *file_src, void *mesg_src, H5F_t *file_dst,
444     hbool_t H5_ATTR_UNUSED *recompute_size, unsigned H5_ATTR_UNUSED *mesg_flags,
445     H5O_copy_t H5_ATTR_UNUSED *cpy_info, void H5_ATTR_UNUSED *_udata)
446 {
447     H5O_efl_t   *efl_src = (H5O_efl_t *) mesg_src;
448     H5O_efl_t   *efl_dst = NULL;
449     H5HL_t      *heap = NULL;                   /* Pointer to local heap for EFL file names */
450     size_t      idx, size, name_offset, heap_size;
451     void        *ret_value = NULL;              /* Return value */
452 
453     FUNC_ENTER_STATIC_TAG(H5AC__COPIED_TAG)
454 
455     /* check args */
456     HDassert(efl_src);
457     HDassert(file_dst);
458 
459     /* Allocate space for the destination efl */
460     if(NULL == (efl_dst = (H5O_efl_t *)H5MM_calloc(sizeof(H5O_efl_t))))
461         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
462 
463     /* Copy the "top level" information */
464     HDmemcpy(efl_dst, efl_src, sizeof(H5O_efl_t));
465 
466     /* Determine size needed for destination heap */
467     heap_size = H5HL_ALIGN(1);  /* "empty" name */
468     for(idx = 0; idx < efl_src->nused; idx++)
469         heap_size += H5HL_ALIGN(HDstrlen(efl_src->slot[idx].name) + 1);
470 
471     /* Create name heap */
472     if(H5HL_create(file_dst, heap_size, &efl_dst->heap_addr/*out*/) < 0)
473         HGOTO_ERROR(H5E_EFL, H5E_CANTINIT, NULL, "can't create heap")
474 
475     /* Pin the heap down in memory */
476     if(NULL == (heap = H5HL_protect(file_dst, efl_dst->heap_addr, H5AC__NO_FLAGS_SET)))
477         HGOTO_ERROR(H5E_EFL, H5E_PROTECT, NULL, "unable to protect EFL file name heap")
478 
479     /* Insert "empty" name first */
480     if(UFAIL == (name_offset = H5HL_insert(file_dst, heap, (size_t)1, "")))
481         HGOTO_ERROR(H5E_EFL, H5E_CANTINSERT, NULL, "can't insert file name into heap")
482     HDassert(0 == name_offset);
483 
484     /* allocate array of external file entries */
485     if(efl_src->nalloc > 0) {
486         size = efl_src->nalloc * sizeof(H5O_efl_entry_t);
487         if((efl_dst->slot = (H5O_efl_entry_t *)H5MM_calloc(size)) == NULL)
488             HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
489 
490         /* copy content from the source. Need to update later */
491         HDmemcpy(efl_dst->slot, efl_src->slot, size);
492     } /* end if */
493 
494     /* copy the name from the source */
495     for(idx = 0; idx < efl_src->nused; idx++) {
496         efl_dst->slot[idx].name = H5MM_xstrdup(efl_src->slot[idx].name);
497         if(UFAIL == (efl_dst->slot[idx].name_offset = H5HL_insert(file_dst, heap,
498                 HDstrlen(efl_dst->slot[idx].name) + 1, efl_dst->slot[idx].name)))
499             HGOTO_ERROR(H5E_EFL, H5E_CANTINSERT, NULL, "can't insert file name into heap")
500     } /* end for */
501 
502     /* Set return value */
503     ret_value = efl_dst;
504 
505 done:
506     /* Release resources */
507     if(heap && H5HL_unprotect(heap) < 0)
508         HDONE_ERROR(H5E_EFL, H5E_PROTECT, NULL, "unable to unprotect EFL file name heap")
509     if(!ret_value)
510         if(efl_dst)
511             H5MM_xfree(efl_dst);
512 
513     FUNC_LEAVE_NOAPI_TAG(ret_value)
514 } /* end H5O__efl_copy_file() */
515 
516 
517 /*-------------------------------------------------------------------------
518  * Function:	H5O__efl_debug
519  *
520  * Purpose:	Prints debugging info for a message.
521  *
522  * Return:	Non-negative on success/Negative on failure
523  *
524  * Programmer:	Robb Matzke
525  *		Tuesday, November 25, 1997
526  *
527  *-------------------------------------------------------------------------
528  */
529 static herr_t
H5O__efl_debug(H5F_t H5_ATTR_UNUSED * f,const void * _mesg,FILE * stream,int indent,int fwidth)530 H5O__efl_debug(H5F_t H5_ATTR_UNUSED *f, const void *_mesg, FILE * stream,
531     int indent, int fwidth)
532 {
533     const H5O_efl_t	   *mesg = (const H5O_efl_t *) _mesg;
534     size_t		    u;
535 
536     FUNC_ENTER_STATIC_NOERR
537 
538     /* check args */
539     HDassert(f);
540     HDassert(mesg);
541     HDassert(stream);
542     HDassert(indent >= 0);
543     HDassert(fwidth >= 0);
544 
545     HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
546 	      "Heap address:", mesg->heap_addr);
547 
548     HDfprintf(stream, "%*s%-*s %u/%u\n", indent, "", fwidth,
549 	      "Slots used/allocated:",
550 	      mesg->nused, mesg->nalloc);
551 
552     for(u = 0; u < mesg->nused; u++) {
553         char		    buf[64];
554 
555 	HDsnprintf(buf, sizeof(buf), "File %u", (unsigned)u);
556 	HDfprintf(stream, "%*s%s:\n", indent, "", buf);
557 
558 	HDfprintf(stream, "%*s%-*s \"%s\"\n", indent+3, "", MAX (fwidth-3, 0),
559 		  "Name:",
560 		  mesg->slot[u].name);
561 
562 	HDfprintf(stream, "%*s%-*s %lu\n", indent+3, "", MAX (fwidth-3, 0),
563 		  "Name offset:",
564 		  (unsigned long)(mesg->slot[u].name_offset));
565 
566 	HDfprintf(stream, "%*s%-*s %lu\n", indent+3, "", MAX (fwidth-3, 0),
567 		   "Offset of data in file:",
568 		   (unsigned long)(mesg->slot[u].offset));
569 
570 	HDfprintf(stream, "%*s%-*s %lu\n", indent+3, "", MAX (fwidth-3, 0),
571 		   "Bytes reserved for data:",
572 		   (unsigned long)(mesg->slot[u].size));
573     } /* end for */
574 
575     FUNC_LEAVE_NOAPI(SUCCEED)
576 } /* end H5O__efl_debug() */
577 
578