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  *
16  * Created:		H5Odbg.c
17  *			Nov 17 2006
18  *			Quincey Koziol <koziol@hdfgroup.org>
19  *
20  * Purpose:		Object header debugging routines.
21  *
22  *-------------------------------------------------------------------------
23  */
24 
25 /****************/
26 /* Module Setup */
27 /****************/
28 
29 #define H5O_PACKAGE		/*suppress error about including H5Opkg	  */
30 
31 /***********/
32 /* Headers */
33 /***********/
34 #include "H5private.h"		/* Generic Functions			*/
35 #include "H5Eprivate.h"		/* Error handling		  	*/
36 #include "H5MMprivate.h"	/* Memory management			*/
37 #include "H5Opkg.h"             /* Object headers			*/
38 #include "H5Ppublic.h"		/* Property Lists			*/
39 
40 /****************/
41 /* Local Macros */
42 /****************/
43 
44 
45 /******************/
46 /* Local Typedefs */
47 /******************/
48 
49 
50 /********************/
51 /* Package Typedefs */
52 /********************/
53 
54 
55 /********************/
56 /* Local Prototypes */
57 /********************/
58 
59 
60 /*********************/
61 /* Package Variables */
62 /*********************/
63 
64 
65 /*****************************/
66 /* Library Private Variables */
67 /*****************************/
68 
69 
70 /*******************/
71 /* Local Variables */
72 /*******************/
73 
74 
75 #ifdef H5O_DEBUG
76 
77 /*-------------------------------------------------------------------------
78  * Function:	H5O_assert
79  *
80  * Purpose:	Sanity check the information for an object header data
81  *              structure.
82  *
83  * Return:	Non-negative on success/Negative on failure
84  *
85  * Programmer:	Quincey Koziol
86  *		koziol@hdfgroup.org
87  *		Oct 17 2006
88  *
89  *-------------------------------------------------------------------------
90  */
91 herr_t
H5O_assert(const H5O_t * oh)92 H5O_assert(const H5O_t *oh)
93 {
94     H5O_mesg_t *curr_msg;               /* Pointer to current message to examine */
95     H5O_mesg_t *tmp_msg;                /* Pointer to temporary message to examine */
96     unsigned cont_msgs_found = 0;       /* # of continuation messages for object */
97     size_t meta_space;                  /* Size of header metadata */
98     size_t mesg_space;                  /* Size of message raw data */
99     size_t free_space;                  /* Size of free space in header */
100     size_t hdr_size;                    /* Size of header's chunks */
101     unsigned u, v;                      /* Local index variables */
102 
103     FUNC_ENTER_NOAPI_NOINIT_NOERR
104 
105     /* Initialize the tracking variables */
106     hdr_size = 0;
107     meta_space = (size_t)H5O_SIZEOF_HDR(oh) + (size_t)(H5O_SIZEOF_CHKHDR_OH(oh) * (oh->nchunks - 1));
108     mesg_space = 0;
109     free_space = 0;
110 
111     /* Loop over all chunks in object header */
112     for(u = 0; u < oh->nchunks; u++) {
113         /* Accumulate the size of the header on header */
114         hdr_size += oh->chunk[u].size;
115 
116         /* If the chunk has a gap, add it to the free space */
117         free_space += oh->chunk[u].gap;
118 
119         /* Check for valid raw data image */
120         HDassert(oh->chunk[u].image);
121         HDassert(oh->chunk[u].size > (size_t)H5O_SIZEOF_CHKHDR_OH(oh));
122 
123         /* All chunks must be allocated on disk */
124         HDassert(H5F_addr_defined(oh->chunk[u].addr));
125 
126         /* Version specific checks */
127         if(oh->version > H5O_VERSION_1) {
128             /* Make certain that the magic number is correct for each chunk */
129             HDassert(!HDmemcmp(oh->chunk[u].image, (u == 0 ? H5O_HDR_MAGIC : H5O_CHK_MAGIC), H5_SIZEOF_MAGIC));
130 
131             /* Check for valid gap size */
132             HDassert(oh->chunk[u].gap < (size_t)H5O_SIZEOF_MSGHDR_OH(oh));
133         } /* end if */
134         else
135             /* Gaps should never occur in version 1 of the format */
136             HDassert(oh->chunk[u].gap == 0);
137     } /* end for */
138 
139     /* Check for correct chunk #0 size flags */
140     if(oh->version > H5O_VERSION_1) {
141         uint64_t chunk0_size = oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh);
142 
143         if(chunk0_size <= 255)
144             HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_1);
145         else if(chunk0_size <= 65535)
146             HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_2);
147         else if(chunk0_size <= 4294967295)
148             HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_4);
149         else
150             HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_8);
151     } /* end if */
152 
153     /* Loop over all messages in object header */
154     for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) {
155         uint8_t *curr_hdr;      /* Start of current message header */
156         size_t  curr_tot_size;  /* Total size of current message (including header) */
157 
158         curr_hdr = curr_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh);
159         curr_tot_size = curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
160 
161         /* Accumulate information, based on the type of message */
162 	if(H5O_NULL_ID == curr_msg->type->id)
163             free_space += curr_tot_size;
164         else if(H5O_CONT_ID == curr_msg->type->id) {
165             H5O_cont_t *cont = (H5O_cont_t *)curr_msg->native;
166             hbool_t found_chunk = FALSE;        /* Found a chunk that matches */
167 
168             HDassert(cont);
169 
170             /* Increment # of continuation messages found */
171             cont_msgs_found++;
172 
173             /* Sanity check that every continuation message has a matching chunk */
174             /* (and only one) */
175             for(v = 0; v < oh->nchunks; v++) {
176                 if(H5F_addr_eq(cont->addr, oh->chunk[v].addr) && cont->size == oh->chunk[v].size) {
177                     HDassert(cont->chunkno == v);
178                     HDassert(!found_chunk);
179                     found_chunk = TRUE;
180                 } /* end if */
181             } /* end for */
182             HDassert(found_chunk);
183 
184             meta_space += curr_tot_size;
185         } /* end if */
186         else {
187             meta_space += (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
188             mesg_space += curr_msg->raw_size;
189 
190             /* Make sure the message has a native form if it is marked dirty */
191             HDassert(curr_msg->native || !curr_msg->dirty);
192         } /* end else */
193 
194         /* Make certain that the message is in a valid chunk */
195         HDassert(curr_msg->chunkno < oh->nchunks);
196 
197         /* Make certain null messages aren't in chunks with gaps */
198         if(H5O_NULL_ID == curr_msg->type->id)
199             HDassert(oh->chunk[curr_msg->chunkno].gap == 0);
200 
201         /* Make certain that the message is completely in a chunk message area */
202         HDassert(curr_tot_size <= (oh->chunk[curr_msg->chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[curr_msg->chunkno].gap));
203         if(curr_msg->chunkno == 0)
204             HDassert(curr_hdr >= oh->chunk[curr_msg->chunkno].image + (H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
205         else
206             HDassert(curr_hdr >= oh->chunk[curr_msg->chunkno].image + (H5O_SIZEOF_CHKHDR_OH(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
207         HDassert(curr_msg->raw + curr_msg->raw_size <= (oh->chunk[curr_msg->chunkno].image + oh->chunk[curr_msg->chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[curr_msg->chunkno].gap));
208 
209         /* Make certain that no other messages overlap this message */
210         for(v = 0, tmp_msg = &oh->mesg[0]; v < oh->nmesgs; v++, tmp_msg++) {
211             if(u != v)
212                 HDassert(!((tmp_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh)) >= curr_hdr
213                         && (tmp_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh))
214                         < (curr_hdr + curr_tot_size)));
215         } /* end for */
216     } /* end for */
217 
218     /* Sanity check that the # of cont. messages is correct for the # of chunks */
219     HDassert(oh->nchunks == (cont_msgs_found + 1));
220 
221     /* Sanity check that all the bytes are accounted for */
222     HDassert(hdr_size == (free_space + meta_space + mesg_space));
223 
224     FUNC_LEAVE_NOAPI(SUCCEED)
225 } /* end H5O_assert() */
226 #endif /* H5O_DEBUG */
227 
228 
229 /*-------------------------------------------------------------------------
230  * Function:	H5O_debug_id
231  *
232  * Purpose:	Act as a proxy for calling the 'debug' method for a
233  *              particular class of object header.
234  *
235  * Return:	Non-negative on success/Negative on failure
236  *
237  * Programmer:	Quincey Koziol
238  *		koziol@ncsa.uiuc.edu
239  *		Feb 13 2003
240  *
241  * Modifications:
242  *
243  *-------------------------------------------------------------------------
244  */
245 herr_t
H5O_debug_id(unsigned type_id,H5F_t * f,hid_t dxpl_id,const void * mesg,FILE * stream,int indent,int fwidth)246 H5O_debug_id(unsigned type_id, H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *stream, int indent, int fwidth)
247 {
248     const H5O_msg_class_t *type;            /* Actual H5O class type for the ID */
249     herr_t      ret_value;       /* Return value */
250 
251     FUNC_ENTER_NOAPI(FAIL)
252 
253     /* Check args */
254     HDassert(type_id < NELMTS(H5O_msg_class_g));
255     type = H5O_msg_class_g[type_id];    /* map the type ID to the actual type object */
256     HDassert(type);
257     HDassert(type->debug);
258     HDassert(f);
259     HDassert(mesg);
260     HDassert(stream);
261     HDassert(indent >= 0);
262     HDassert(fwidth >= 0);
263 
264     /* Call the debug method in the class */
265     if((ret_value = (type->debug)(f, dxpl_id, mesg, stream, indent, fwidth)) < 0)
266         HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, FAIL, "unable to debug message")
267 
268 done:
269     FUNC_LEAVE_NOAPI(ret_value)
270 } /* end H5O_debug_id() */
271 
272 
273 /*-------------------------------------------------------------------------
274  * Function:	H5O_debug_real
275  *
276  * Purpose:	Prints debugging info about an object header.
277  *
278  * Return:	Non-negative on success/Negative on failure
279  *
280  * Programmer:	Robb Matzke
281  *		matzke@llnl.gov
282  *		Aug  6 1997
283  *
284  * Modifications:
285  *   Feb. 2009: Vailin Choi
286  *	Fixed bug in the accumulation of chunk_total
287  *	Used the appropriate flag when printing creation order tracked/indexed
288  *-------------------------------------------------------------------------
289  */
290 herr_t
H5O_debug_real(H5F_t * f,hid_t dxpl_id,H5O_t * oh,haddr_t addr,FILE * stream,int indent,int fwidth)291 H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, int indent, int fwidth)
292 {
293     size_t	mesg_total = 0, chunk_total = 0, gap_total = 0;
294     unsigned	*sequence = NULL;
295     unsigned	i;              /* Local index variable */
296     herr_t	ret_value = SUCCEED;
297 
298     FUNC_ENTER_NOAPI(FAIL)
299 
300     /* check args */
301     HDassert(f);
302     HDassert(oh);
303     HDassert(H5F_addr_defined(addr));
304     HDassert(stream);
305     HDassert(indent >= 0);
306     HDassert(fwidth >= 0);
307 
308     /* debug */
309     HDfprintf(stream, "%*sObject Header...\n", indent, "");
310 
311     HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
312 	      "Dirty:",
313 	      oh->cache_info.is_dirty);
314     HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
315 	      "Version:",
316 	      oh->version);
317     HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
318 	      "Header size (in bytes):",
319 	      (unsigned)H5O_SIZEOF_HDR(oh));
320     HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
321 	      "Number of links:",
322 	      oh->nlink);
323 
324     /* Extra information for later versions */
325     if(oh->version > H5O_VERSION_1) {
326         /* Display object's status flags */
327 	HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
328 		   "Attribute creation order tracked:",
329 		   (oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED) ? "Yes" : "No");
330 	HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
331 		   "Attribute creation order indexed:",
332 		   (oh->flags & H5O_HDR_ATTR_CRT_ORDER_INDEXED) ? "Yes" : "No");
333 	HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
334 		   "Attribute storage phase change values:",
335 		   (oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) ? "Non-default" : "Default");
336 	HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
337 		   "Timestamps:",
338 		   (oh->flags & H5O_HDR_STORE_TIMES) ? "Enabled" : "Disabled");
339         if(oh->flags & ~H5O_HDR_ALL_FLAGS)
340             HDfprintf(stream, "*** UNKNOWN OBJECT HEADER STATUS FLAG: %02x!\n",
341                 (unsigned)oh->flags);
342 
343         /* Only dump times, if they are tracked */
344         if(oh->flags & H5O_HDR_STORE_TIMES) {
345             struct tm *tm;          /* Time structure */
346             char buf[128];          /* Buffer for formatting time info */
347 
348             /* Time fields */
349             tm = HDlocaltime(&oh->atime);
350             HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
351             HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
352                     "Access Time:", buf);
353             tm = HDlocaltime(&oh->mtime);
354             HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
355             HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
356                     "Modification Time:", buf);
357             tm = HDlocaltime(&oh->ctime);
358             HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
359             HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
360                     "Change Time:", buf);
361             tm = HDlocaltime(&oh->btime);
362             HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
363             HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
364                     "Birth Time:", buf);
365         } /* end if */
366 
367         /* Attribute tracking fields */
368         if(oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) {
369             HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
370                       "Max. compact attributes:",
371                       (unsigned)oh->max_compact);
372             HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
373                       "Min. dense attributes:",
374                       (unsigned)oh->min_dense);
375         } /* end if */
376     } /* end if */
377 
378     HDfprintf(stream, "%*s%-*s %Zu (%Zu)\n", indent, "", fwidth,
379 	      "Number of messages (allocated):",
380 	      oh->nmesgs, oh->alloc_nmesgs);
381     HDfprintf(stream, "%*s%-*s %Zu (%Zu)\n", indent, "", fwidth,
382 	      "Number of chunks (allocated):",
383 	      oh->nchunks, oh->alloc_nchunks);
384 
385     /* debug each chunk */
386     for(i = 0, chunk_total = 0; i < oh->nchunks; i++) {
387         size_t chunk_size;
388 
389 	HDfprintf(stream, "%*sChunk %d...\n", indent, "", i);
390 
391 	HDfprintf(stream, "%*s%-*s %a\n", indent + 3, "", MAX(0, fwidth - 3),
392 		  "Address:",
393                   oh->chunk[i].addr);
394 
395         /* Decrement chunk 0's size by the object header prefix size */
396 	if(0 == i) {
397             if(H5F_addr_ne(oh->chunk[i].addr, addr))
398                 HDfprintf(stream, "*** WRONG ADDRESS FOR CHUNK #0!\n");
399             chunk_size = oh->chunk[i].size - (size_t)H5O_SIZEOF_HDR(oh);
400         } /* end if */
401         else
402             chunk_size = oh->chunk[i].size;
403 
404         /* Accumulate chunk's size to total */
405 	chunk_total += chunk_size;
406 	gap_total += oh->chunk[i].gap;
407 
408 	HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3),
409 		  "Size in bytes:",
410 		  chunk_size);
411 
412 	HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3),
413 		  "Gap:",
414                   oh->chunk[i].gap);
415     } /* end for */
416 
417     /* debug each message */
418     if(NULL == (sequence = (unsigned *)H5MM_calloc(NELMTS(H5O_msg_class_g) * sizeof(unsigned))))
419 	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
420     for(i = 0, mesg_total = 0; i < oh->nmesgs; i++) {
421         const H5O_msg_class_t  *debug_type;              /* Type of message to use for callbacks */
422         unsigned chunkno;                       /* Chunk for message */
423 
424         /* Accumulate message's size to total */
425 	mesg_total += (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[i].raw_size;
426 
427 	/* For version 2 object header, add size of "OCHK" for continuation chunk */
428 	if (oh->mesg[i].type->id == H5O_CONT_ID)
429 	    mesg_total += H5O_SIZEOF_CHKHDR_OH(oh);
430 
431 	HDfprintf(stream, "%*sMessage %d...\n", indent, "", i);
432 
433 	/* check for bad message id */
434 	if(oh->mesg[i].type->id >= (int)NELMTS(H5O_msg_class_g)) {
435 	    HDfprintf(stream, "*** BAD MESSAGE ID 0x%04x\n",
436 		      oh->mesg[i].type->id);
437 	    continue;
438 	} /* end if */
439 
440 	/* message name and size */
441 	HDfprintf(stream, "%*s%-*s 0x%04x `%s' (%d)\n",
442 		  indent + 3, "", MAX(0, fwidth - 3),
443 		  "Message ID (sequence number):",
444 		  (unsigned) (oh->mesg[i].type->id),
445 		  oh->mesg[i].type->name,
446 		  sequence[oh->mesg[i].type->id]++);
447 	HDfprintf(stream, "%*s%-*s %t\n", indent + 3, "", MAX (0, fwidth - 3),
448 		   "Dirty:",
449 		   oh->mesg[i].dirty);
450         HDfprintf(stream, "%*s%-*s ", indent + 3, "", MAX (0, fwidth - 3),
451                    "Message flags:");
452 	if(oh->mesg[i].flags) {
453             hbool_t flag_printed = FALSE;
454 
455             if(oh->mesg[i].flags & H5O_MSG_FLAG_SHARED) {
456                 HDfprintf(stream, "<S");
457                 flag_printed = TRUE;
458             } /* end if */
459             if(oh->mesg[i].flags & H5O_MSG_FLAG_CONSTANT) {
460                 HDfprintf(stream, "%sC", (flag_printed ? ", " : "<"));
461                 flag_printed = TRUE;
462             } /* end if */
463             if(oh->mesg[i].flags & H5O_MSG_FLAG_DONTSHARE) {
464                 HDfprintf(stream, "%sDS", (flag_printed ? ", " : "<"));
465                 flag_printed = TRUE;
466             } /* end if */
467             if(oh->mesg[i].flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN_AND_OPEN_FOR_WRITE) {
468                 HDfprintf(stream, "%sFIU", (flag_printed ? ", " : "<"));
469                 flag_printed = TRUE;
470             } /* end if */
471             if(oh->mesg[i].flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN) {
472                 HDfprintf(stream, "%sMIU", (flag_printed ? ", " : "<"));
473                 flag_printed = TRUE;
474             } /* end if */
475             if(oh->mesg[i].flags & H5O_MSG_FLAG_WAS_UNKNOWN) {
476                 HDassert(oh->mesg[i].flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN);
477                 HDfprintf(stream, "%sWU", (flag_printed ? ", " : "<"));
478                 flag_printed = TRUE;
479             } /* end if */
480             if(!flag_printed)
481                 HDfprintf(stream, "-");
482             HDfprintf(stream, ">\n");
483             if(oh->mesg[i].flags & ~H5O_MSG_FLAG_BITS)
484                 HDfprintf(stream, "%*s%-*s 0x%02x\n", indent + 3,"", MAX(0, fwidth - 3),
485                            "*** ADDITIONAL UNKNOWN FLAGS --->",
486                            oh->mesg[i].flags & ~H5O_MSG_FLAG_BITS);
487         } /* end if */
488         else
489             HDfprintf(stream, "<none>\n");
490 	HDfprintf(stream, "%*s%-*s %u\n", indent + 3, "", MAX(0, fwidth - 3),
491 		  "Chunk number:",
492 		  oh->mesg[i].chunkno);
493 	chunkno = oh->mesg[i].chunkno;
494 	if(chunkno >= oh->nchunks)
495 	    HDfprintf(stream, "*** BAD CHUNK NUMBER\n");
496 	HDfprintf(stream, "%*s%-*s (%Zu, %Zu) bytes\n", indent + 3, "", MAX(0, fwidth - 3),
497 		  "Raw message data (offset, size) in chunk:",
498 		  (size_t)(oh->mesg[i].raw - oh->chunk[chunkno].image),
499 		  oh->mesg[i].raw_size);
500 
501 	/* check the size */
502 	if((oh->mesg[i].raw + oh->mesg[i].raw_size >
503                  oh->chunk[chunkno].image + oh->chunk[chunkno].size) ||
504                 (oh->mesg[i].raw < oh->chunk[chunkno].image))
505 	    HDfprintf(stream, "*** BAD MESSAGE RAW ADDRESS\n");
506 
507 	/* decode the message */
508 	debug_type = oh->mesg[i].type;
509 	if(NULL == oh->mesg[i].native && debug_type->decode)
510             H5O_LOAD_NATIVE(f, dxpl_id, H5O_DECODEIO_NOCHANGE, oh, &oh->mesg[i], FAIL)
511 
512 	/* print the message */
513 	HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3),
514 		  "Message Information:");
515 	if(debug_type->debug && oh->mesg[i].native != NULL)
516 	    (debug_type->debug)(f, dxpl_id, oh->mesg[i].native, stream, indent + 6, MAX(0, fwidth - 6));
517 	else
518 	    HDfprintf(stream, "%*s<No info for this message>\n", indent + 6, "");
519     } /* end for */
520 
521     if((mesg_total + gap_total) != chunk_total)
522 	HDfprintf(stream, "*** TOTAL SIZE DOES NOT MATCH ALLOCATED SIZE!\n");
523 
524 done:
525     /* Release resources */
526     if(sequence)
527         sequence = (unsigned *)H5MM_xfree(sequence);
528 
529     FUNC_LEAVE_NOAPI(ret_value)
530 } /* end H5O_debug_real() */
531 
532 
533 /*-------------------------------------------------------------------------
534  * Function:	H5O_debug
535  *
536  * Purpose:	Prints debugging info about an object header.
537  *
538  * Return:	Non-negative on success/Negative on failure
539  *
540  * Programmer:	Robb Matzke
541  *		matzke@llnl.gov
542  *		Aug  6 1997
543  *
544  *-------------------------------------------------------------------------
545  */
546 herr_t
H5O_debug(H5F_t * f,hid_t dxpl_id,haddr_t addr,FILE * stream,int indent,int fwidth)547 H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth)
548 {
549     H5O_t	*oh = NULL;             /* Object header to display */
550     H5O_loc_t   loc;                    /* Object location for object to delete */
551     herr_t	ret_value = SUCCEED;    /* Return value */
552 
553     FUNC_ENTER_NOAPI(FAIL)
554 
555     /* check args */
556     HDassert(f);
557     HDassert(H5F_addr_defined(addr));
558     HDassert(stream);
559     HDassert(indent >= 0);
560     HDassert(fwidth >= 0);
561 
562     /* Set up the object location */
563     loc.file = f;
564     loc.addr = addr;
565     loc.holding_file = FALSE;
566 
567     if(NULL == (oh = H5O_protect(&loc, dxpl_id, H5AC_READ)))
568 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
569 
570     /* debug */
571     H5O_debug_real(f, dxpl_id, oh, addr, stream, indent, fwidth);
572 
573 done:
574     if(oh && H5O_unprotect(&loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
575 	HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
576 
577     FUNC_LEAVE_NOAPI(ret_value)
578 } /* end H5O_debug() */
579 
580