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 /* Programmer: Robb Matzke <matzke@llnl.gov>
15  *	       Friday, September 19, 1997
16  *
17  */
18 
19 /****************/
20 /* Module Setup */
21 /****************/
22 
23 #include "H5Gmodule.h"          /* This source code file is part of the H5G module */
24 
25 
26 /***********/
27 /* Headers */
28 /***********/
29 #include "H5private.h"		/* Generic Functions			*/
30 #include "H5Eprivate.h"		/* Error handling		  	*/
31 #include "H5Fprivate.h"		/* File access				*/
32 #include "H5Gpkg.h"		/* Groups		  		*/
33 #include "H5HLprivate.h"	/* Local Heaps				*/
34 #include "H5MMprivate.h"	/* Memory management			*/
35 
36 
37 /****************/
38 /* Local Macros */
39 /****************/
40 
41 
42 /******************/
43 /* Local Typedefs */
44 /******************/
45 
46 /* User data for finding link information from B-tree */
47 typedef struct {
48     /* downward */
49     const char *name;           /* Name to search for */
50     H5HL_t *heap;               /* Local heap for group */
51 
52     /* upward */
53     H5O_link_t *lnk;            /* Caller's link location */
54 } H5G_stab_fnd_ud_t;
55 
56 /* Data passed through B-tree iteration for looking up a name by index */
57 typedef struct H5G_bt_it_gnbi_t {
58     /* downward */
59     H5G_bt_it_idx_common_t common; /* Common information for "by index" lookup  */
60     H5HL_t *heap;               /*symbol table heap 			     */
61 
62     /* upward */
63     char         *name;         /*member name to be returned                 */
64 } H5G_bt_it_gnbi_t;
65 
66 #ifndef H5_NO_DEPRECATED_SYMBOLS
67 /* Data passed through B-tree iteration for looking up a type by index */
68 typedef struct H5G_bt_it_gtbi_t {
69     /* downward */
70     H5G_bt_it_idx_common_t common; /* Common information for "by index" lookup  */
71     H5F_t       *f;             /* Pointer to file that symbol table is in */
72     hid_t       dxpl_id;        /* DXPL for operation */
73 
74     /* upward */
75     H5G_obj_t    type;          /*member type to be returned                 */
76 } H5G_bt_it_gtbi_t;
77 #endif /* H5_NO_DEPRECATED_SYMBOLS */
78 
79 /* Data passed through B-tree iteration for looking up a link by index */
80 typedef struct H5G_bt_it_lbi_t {
81     /* downward */
82     H5G_bt_it_idx_common_t common; /* Common information for "by index" lookup  */
83     H5HL_t *heap;               /*symbol table heap 			     */
84 
85     /* upward */
86     H5O_link_t *lnk;            /*link to be returned                        */
87     hbool_t     found;      	/*whether we found the link                  */
88 } H5G_bt_it_lbi_t;
89 
90 
91 /********************/
92 /* Package Typedefs */
93 /********************/
94 
95 
96 /********************/
97 /* Local Prototypes */
98 /********************/
99 
100 
101 /*********************/
102 /* Package Variables */
103 /*********************/
104 
105 
106 /*****************************/
107 /* Library Private Variables */
108 /*****************************/
109 
110 
111 /*******************/
112 /* Local Variables */
113 /*******************/
114 
115 
116 
117 /*-------------------------------------------------------------------------
118  * Function:	H5G__stab_create_components
119  *
120  * Purpose:	Creates the components for a new, empty, symbol table (name heap
121  *		and B-tree).  The caller can specify an initial size for the
122  *		name heap.
123  *
124  *		In order for the B-tree to operate correctly, the first
125  *		item in the heap is the empty string, and must appear at
126  *		heap offset zero.
127  *
128  * Return:	Non-negative on success/Negative on failure
129  *
130  * Programmer:	Quincey Koziol
131  *		koziol@ncsa.uiuc.edu
132  *		Nov  7 2005
133  *
134  *-------------------------------------------------------------------------
135  */
136 herr_t
H5G__stab_create_components(H5F_t * f,H5O_stab_t * stab,size_t size_hint,hid_t dxpl_id)137 H5G__stab_create_components(H5F_t *f, H5O_stab_t *stab, size_t size_hint, hid_t dxpl_id)
138 {
139     H5HL_t *heap = NULL;            /* Pointer to local heap */
140     size_t name_offset;	            /* Offset of "" name */
141     herr_t ret_value = SUCCEED;     /* Return value */
142 
143     FUNC_ENTER_PACKAGE
144 
145     /*
146      * Check arguments.
147      */
148     HDassert(f);
149     HDassert(stab);
150     HDassert(size_hint > 0);
151 
152     /* Create the B-tree */
153     if(H5B_create(f, dxpl_id, H5B_SNODE, NULL, &(stab->btree_addr)/*out*/) < 0)
154         HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create B-tree")
155 
156     /* Create symbol table private heap */
157     if(H5HL_create(f, dxpl_id, size_hint, &(stab->heap_addr)/*out*/) < 0)
158         HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create heap")
159 
160     /* Pin the heap down in memory */
161     if(NULL == (heap = H5HL_protect(f, dxpl_id, stab->heap_addr, H5AC__NO_FLAGS_SET)))
162         HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
163 
164     /* Insert name into the heap */
165     if(UFAIL == (name_offset = H5HL_insert(f, dxpl_id, heap, (size_t)1, "")))
166         HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert name into heap")
167 
168     /*
169      * B-tree's won't work if the first name isn't at the beginning
170      * of the heap.
171      */
172     HDassert(0 == name_offset);
173 
174 done:
175     /* Release resources */
176     if(heap && FAIL == H5HL_unprotect(heap))
177         HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
178 
179     FUNC_LEAVE_NOAPI(ret_value)
180 } /* end H5G__stab_create_components() */
181 
182 
183 /*-------------------------------------------------------------------------
184  * Function:	H5G__stab_create
185  *
186  * Purpose:	Creates a new empty symbol table (object header, name heap,
187  *		and B-tree).  The caller can specify an initial size for the
188  *		name heap.  The object header of the group is opened for
189  *		write access.
190  *
191  *		In order for the B-tree to operate correctly, the first
192  *		item in the heap is the empty string, and must appear at
193  *		heap offset zero.
194  *
195  * Return:	Non-negative on success/Negative on failure
196  *
197  * Programmer:	Robb Matzke
198  *		matzke@llnl.gov
199  *		Aug  1 1997
200  *
201  *-------------------------------------------------------------------------
202  */
203 herr_t
H5G__stab_create(H5O_loc_t * grp_oloc,hid_t dxpl_id,const H5O_ginfo_t * ginfo,H5O_stab_t * stab)204 H5G__stab_create(H5O_loc_t *grp_oloc, hid_t dxpl_id, const H5O_ginfo_t *ginfo,
205     H5O_stab_t *stab)
206 {
207     size_t      heap_hint;              /* Local heap size hint */
208     size_t      size_hint;              /* Local heap size hint */
209     herr_t      ret_value = SUCCEED;    /* Return value */
210 
211     FUNC_ENTER_PACKAGE_TAG(dxpl_id, grp_oloc->addr, FAIL)
212 
213     /*
214      * Check arguments.
215      */
216     HDassert(grp_oloc);
217     HDassert(stab);
218 
219     /* Adjust the size hint, if necessary */
220     if(ginfo->lheap_size_hint == 0)
221         heap_hint = 8 +         /* "null" name inserted for B-tree */
222                 (ginfo->est_num_entries * H5HL_ALIGN(ginfo->est_name_len + 1)) +    /* estimated size of names for links, aligned for inserting into local heap */
223                 H5HL_SIZEOF_FREE(grp_oloc->file);       /* Free list entry in local heap */
224     else
225         heap_hint = ginfo->lheap_size_hint;
226     size_hint = MAX(heap_hint, H5HL_SIZEOF_FREE(grp_oloc->file) + 2);
227 
228     /* Go create the B-tree & local heap */
229     if(H5G__stab_create_components(grp_oloc->file, stab, size_hint, dxpl_id) < 0)
230 	HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create symbol table components")
231 
232     /*
233      * Insert the symbol table message into the object header and the symbol
234      * table entry.
235      */
236     if(H5O_msg_create(grp_oloc, H5O_STAB_ID, 0, H5O_UPDATE_TIME, stab, dxpl_id) < 0)
237 	HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message")
238 
239 done:
240     FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
241 } /* end H5G__stab_create() */
242 
243 
244 /*-------------------------------------------------------------------------
245  * Function:	H5G__stab_insert_real
246  *
247  * Purpose:	Insert a new symbol into a table.
248  *		The name of the new symbol is NAME and its symbol
249  *		table entry is OBJ_LNK.
250  *
251  * Return:	Non-negative on success/Negative on failure
252  *
253  * Programmer:	Quincey Koziol
254  *		koziol@uiuc.edu
255  *		Nov  7 2005
256  *
257  *-------------------------------------------------------------------------
258  */
259 herr_t
H5G__stab_insert_real(H5F_t * f,const H5O_stab_t * stab,const char * name,H5O_link_t * obj_lnk,H5O_type_t obj_type,const void * crt_info,hid_t dxpl_id)260 H5G__stab_insert_real(H5F_t *f, const H5O_stab_t *stab, const char *name,
261     H5O_link_t *obj_lnk, H5O_type_t obj_type, const void *crt_info,
262     hid_t dxpl_id)
263 {
264     H5HL_t       *heap = NULL;          /* Pointer to local heap */
265     H5G_bt_ins_t udata;		        /* Data to pass through B-tree	*/
266     herr_t       ret_value = SUCCEED;   /* Return value */
267 
268     FUNC_ENTER_PACKAGE
269 
270     /* check arguments */
271     HDassert(f);
272     HDassert(stab);
273     HDassert(name && *name);
274     HDassert(obj_lnk);
275 
276     /* Pin the heap down in memory */
277     if(NULL == (heap = H5HL_protect(f, dxpl_id, stab->heap_addr, H5AC__NO_FLAGS_SET)))
278         HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
279 
280     /* Initialize data to pass through B-tree */
281     udata.common.name = name;
282     udata.common.heap = heap;
283     udata.lnk = obj_lnk;
284     udata.obj_type = obj_type;
285     udata.crt_info = crt_info;
286 
287     /* Insert into symbol table */
288     if(H5B_insert(f, dxpl_id, H5B_SNODE, stab->btree_addr, &udata) < 0)
289         HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert entry")
290 
291 done:
292     /* Release resources */
293     if(heap && H5HL_unprotect(heap) < 0)
294         HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
295 
296     FUNC_LEAVE_NOAPI(ret_value)
297 } /* end H5G__stab_insert_real() */
298 
299 
300 /*-------------------------------------------------------------------------
301  * Function:	H5G__stab_insert
302  *
303  * Purpose:	Insert a new symbol into the table described by GRP_ENT in
304  *		file F.	 The name of the new symbol is NAME and its symbol
305  *		table entry is OBJ_ENT.
306  *
307  * Return:	Non-negative on success/Negative on failure
308  *
309  * Programmer:	Robb Matzke
310  *		matzke@llnl.gov
311  *		Aug  1 1997
312  *
313  *-------------------------------------------------------------------------
314  */
315 herr_t
H5G__stab_insert(const H5O_loc_t * grp_oloc,const char * name,H5O_link_t * obj_lnk,H5O_type_t obj_type,const void * crt_info,hid_t dxpl_id)316 H5G__stab_insert(const H5O_loc_t *grp_oloc, const char *name,
317     H5O_link_t *obj_lnk, H5O_type_t obj_type, const void *crt_info,
318     hid_t dxpl_id)
319 {
320     H5O_stab_t		stab;		/* Symbol table message		*/
321     herr_t              ret_value = SUCCEED;       /* Return value */
322 
323     FUNC_ENTER_PACKAGE_TAG(dxpl_id, grp_oloc->addr, FAIL)
324 
325     /* check arguments */
326     HDassert(grp_oloc && grp_oloc->file);
327     HDassert(name && *name);
328     HDassert(obj_lnk);
329 
330     /* Retrieve symbol table message */
331     if(NULL == H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, dxpl_id))
332         HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table")
333 
334     if(H5G__stab_insert_real(grp_oloc->file, &stab, name, obj_lnk, obj_type,
335             crt_info, dxpl_id) < 0)
336         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5_ITER_ERROR, "unable to insert the name")
337 
338 done:
339     FUNC_LEAVE_NOAPI_TAG(ret_value, H5_ITER_ERROR)
340 } /* end H5G__stab_insert() */
341 
342 
343 /*-------------------------------------------------------------------------
344  * Function:	H5G__stab_remove
345  *
346  * Purpose:	Remove NAME from a symbol table.
347  *
348  * Return:	Non-negative on success/Negative on failure
349  *
350  * Programmer:	Robb Matzke
351  *              Thursday, September 17, 1998
352  *
353  *-------------------------------------------------------------------------
354  */
355 herr_t
H5G__stab_remove(const H5O_loc_t * loc,hid_t dxpl_id,H5RS_str_t * grp_full_path_r,const char * name)356 H5G__stab_remove(const H5O_loc_t *loc, hid_t dxpl_id, H5RS_str_t *grp_full_path_r,
357     const char *name)
358 {
359     H5HL_t      *heap = NULL;           /* Pointer to local heap */
360     H5O_stab_t	stab;		        /*symbol table message		*/
361     H5G_bt_rm_t	udata;		        /*data to pass through B-tree	*/
362     herr_t      ret_value = SUCCEED;    /* Return value */
363 
364     FUNC_ENTER_PACKAGE
365 
366     HDassert(loc && loc->file);
367     HDassert(name && *name);
368 
369     /* Read in symbol table message */
370     if(NULL == H5O_msg_read(loc, H5O_STAB_ID, &stab, dxpl_id))
371         HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table")
372 
373     /* Pin the heap down in memory */
374     if(NULL == (heap = H5HL_protect(loc->file, dxpl_id, stab.heap_addr, H5AC__NO_FLAGS_SET)))
375         HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
376 
377     /* Initialize data to pass through B-tree */
378     udata.common.name = name;
379     udata.common.heap = heap;
380     udata.grp_full_path_r = grp_full_path_r;
381 
382     /* Remove from symbol table */
383     if(H5B_remove(loc->file, dxpl_id, H5B_SNODE, stab.btree_addr, &udata) < 0)
384         HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to remove entry")
385 
386 done:
387     /* Release resources */
388     if(heap && H5HL_unprotect(heap) < 0)
389         HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
390 
391     FUNC_LEAVE_NOAPI(ret_value)
392 } /* end H5G__stab_remove() */
393 
394 
395 /*-------------------------------------------------------------------------
396  * Function:	H5G__stab_remove_by_idx
397  *
398  * Purpose:	Remove NAME from a symbol table, according to the name index.
399  *
400  * Return:	Non-negative on success/Negative on failure
401  *
402  * Programmer:	Quincey Koziol
403  *              Wednesday, November 15, 2006
404  *
405  *-------------------------------------------------------------------------
406  */
407 herr_t
H5G__stab_remove_by_idx(const H5O_loc_t * grp_oloc,hid_t dxpl_id,H5RS_str_t * grp_full_path_r,H5_iter_order_t order,hsize_t n)408 H5G__stab_remove_by_idx(const H5O_loc_t *grp_oloc, hid_t dxpl_id, H5RS_str_t *grp_full_path_r,
409     H5_iter_order_t order, hsize_t n)
410 {
411     H5HL_t      *heap = NULL;           /* Pointer to local heap */
412     H5O_stab_t	stab;		        /* Symbol table message		*/
413     H5G_bt_rm_t udata;		        /* Data to pass through B-tree	*/
414     H5O_link_t  obj_lnk;                /* Object's link within group */
415     hbool_t     lnk_copied = FALSE;     /* Whether the link was copied */
416     herr_t      ret_value = SUCCEED;    /* Return value */
417 
418     FUNC_ENTER_PACKAGE
419 
420     HDassert(grp_oloc && grp_oloc->file);
421 
422     /* Look up name of link to remove, by index */
423     if(H5G__stab_lookup_by_idx(grp_oloc, order, n, &obj_lnk, dxpl_id) < 0)
424         HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get link information")
425     lnk_copied = TRUE;
426 
427     /* Read in symbol table message */
428     if(NULL == H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, dxpl_id))
429         HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "not a symbol table")
430 
431     /* Pin the heap down in memory */
432     if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC__NO_FLAGS_SET)))
433         HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
434 
435     /* Initialize data to pass through B-tree */
436     udata.common.name = obj_lnk.name;
437     udata.common.heap = heap;
438     udata.grp_full_path_r = grp_full_path_r;
439 
440     /* Remove link from symbol table */
441     if(H5B_remove(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, &udata) < 0)
442         HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to remove entry")
443 
444 done:
445     /* Release resources */
446     if(heap && H5HL_unprotect(heap) < 0)
447         HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
448 
449     /* Reset the link information, if we have a copy */
450     if(lnk_copied)
451         H5O_msg_reset(H5O_LINK_ID, &obj_lnk);
452 
453     FUNC_LEAVE_NOAPI(ret_value)
454 } /* end H5G__stab_remove_by_idx() */
455 
456 
457 /*-------------------------------------------------------------------------
458  * Function:	H5G__stab_delete
459  *
460  * Purpose:	Delete entire symbol table information from file
461  *
462  * Return:	Non-negative on success/Negative on failure
463  *
464  * Programmer:	Quincey Koziol
465  *              Thursday, March 20, 2003
466  *
467  * Modifications:
468  *
469  *-------------------------------------------------------------------------
470  */
471 herr_t
H5G__stab_delete(H5F_t * f,hid_t dxpl_id,const H5O_stab_t * stab)472 H5G__stab_delete(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab)
473 {
474     H5HL_t *heap = NULL;                /* Pointer to local heap */
475     H5G_bt_rm_t	udata;		        /*data to pass through B-tree	*/
476     herr_t ret_value = SUCCEED;         /* Return value */
477 
478     FUNC_ENTER_PACKAGE
479 
480     HDassert(f);
481     HDassert(stab);
482     HDassert(H5F_addr_defined(stab->btree_addr));
483     HDassert(H5F_addr_defined(stab->heap_addr));
484 
485     /* Pin the heap down in memory */
486     if(NULL == (heap = H5HL_protect(f, dxpl_id, stab->heap_addr, H5AC__NO_FLAGS_SET)))
487         HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
488 
489     /* Set up user data for B-tree deletion */
490     udata.common.name = NULL;
491     udata.common.heap = heap;
492 
493     /* Delete entire B-tree */
494     if(H5B_delete(f, dxpl_id, H5B_SNODE, stab->btree_addr, &udata) < 0)
495         HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete symbol table B-tree")
496 
497     /* Release resources */
498     if(H5HL_unprotect(heap) < 0)
499         HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
500     heap = NULL;
501 
502     /* Delete local heap for names */
503     if(H5HL_delete(f, dxpl_id, stab->heap_addr) < 0)
504         HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete symbol table heap")
505 
506 done:
507     /* Release resources */
508     if(heap && H5HL_unprotect(heap) < 0)
509         HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
510 
511     FUNC_LEAVE_NOAPI(ret_value)
512 } /* end H5G__stab_delete() */
513 
514 
515 /*-------------------------------------------------------------------------
516  * Function:	H5G__stab_iterate
517  *
518  * Purpose:	Iterate over the objects in a group
519  *
520  * Return:	Non-negative on success/Negative on failure
521  *
522  * Programmer:	Quincey Koziol
523  *              Monday, October  3, 2005
524  *
525  *-------------------------------------------------------------------------
526  */
527 herr_t
H5G__stab_iterate(const H5O_loc_t * oloc,hid_t dxpl_id,H5_iter_order_t order,hsize_t skip,hsize_t * last_lnk,H5G_lib_iterate_t op,void * op_data)528 H5G__stab_iterate(const H5O_loc_t *oloc, hid_t dxpl_id, H5_iter_order_t order,
529     hsize_t skip, hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data)
530 {
531     H5HL_t *heap = NULL;                        /* Local heap for group */
532     H5O_stab_t stab;		                /* Info about symbol table */
533     H5G_link_table_t ltable = {0, NULL};        /* Link table */
534     herr_t ret_value = FAIL;                    /* Return value */
535 
536     FUNC_ENTER_PACKAGE_TAG(dxpl_id, oloc->addr, FAIL)
537 
538     /* Sanity check */
539     HDassert(oloc);
540     HDassert(op);
541 
542     /* Get the B-tree info */
543     if(NULL == H5O_msg_read(oloc, H5O_STAB_ID, &stab, dxpl_id))
544 	HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address")
545 
546     /* Pin the heap down in memory */
547     if(NULL == (heap = H5HL_protect(oloc->file, dxpl_id, stab.heap_addr, H5AC__READ_ONLY_FLAG)))
548         HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
549 
550     /* Check on iteration order */
551     /* ("native" iteration order is increasing for this link storage mechanism) */
552     if(order != H5_ITER_DEC) {
553         H5G_bt_it_it_t	udata;                  /* User data to pass to B-tree callback */
554 
555         /* Build udata to pass through H5B_iterate() to H5G__node_iterate() */
556         udata.heap = heap;
557         udata.skip = skip;
558         udata.final_ent = last_lnk;
559         udata.op = op;
560         udata.op_data = op_data;
561 
562         /* Iterate over the group members */
563         if((ret_value = H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_iterate, &udata)) < 0)
564             HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed");
565 
566         /* Check for too high of a starting index (ex post facto :-) */
567         /* (Skipping exactly as many entries as are in the group is currently an error) */
568         if(skip > 0 && skip >= *last_lnk)
569             HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
570     } /* end if */
571     else {
572         H5G_bt_it_bt_t udata;                   /* User data to pass to B-tree callback */
573 
574         /* Build udata to pass through H5B_iterate() to H5G__node_build_table() */
575         udata.alloc_nlinks = 0;
576         udata.heap = heap;
577         udata.ltable = &ltable;
578 
579         /* Iterate over the group members */
580         if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_build_table, &udata) < 0)
581             HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to build link table")
582 
583         /* Check for skipping out of bounds */
584         if(skip > 0 && (size_t)skip >= ltable.nlinks)
585             HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "index out of bound")
586 
587         /* Sort link table in correct iteration order */
588         if(H5G__link_sort_table(&ltable, H5_INDEX_NAME, order) < 0)
589             HGOTO_ERROR(H5E_SYM, H5E_CANTSORT, FAIL, "error sorting link messages")
590 
591         /* Iterate over links in table */
592         if((ret_value = H5G__link_iterate_table(&ltable, skip, last_lnk, op, op_data)) < 0)
593             HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed");
594     } /* end else */
595 
596 done:
597     /* Release resources */
598     if(heap && H5HL_unprotect(heap) < 0)
599         HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
600     if(ltable.lnks && H5G__link_release_table(&ltable) < 0)
601         HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table")
602 
603     FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
604 } /* end H5G__stab_iterate() */
605 
606 
607 /*-------------------------------------------------------------------------
608  * Function:	H5G__stab_count
609  *
610  * Purpose:	Count the # of links in a group
611  *
612  * Return:	Non-negative on success/Negative on failure
613  *
614  * Programmer:	Quincey Koziol
615  *              Tuesday, September  6, 2005
616  *
617  *-------------------------------------------------------------------------
618  */
619 herr_t
H5G__stab_count(H5O_loc_t * oloc,hsize_t * num_objs,hid_t dxpl_id)620 H5G__stab_count(H5O_loc_t *oloc, hsize_t *num_objs, hid_t dxpl_id)
621 {
622     H5O_stab_t		stab;		        /* Info about symbol table */
623     herr_t		ret_value = SUCCEED;
624 
625     FUNC_ENTER_PACKAGE_TAG(dxpl_id, oloc->addr, FAIL)
626 
627     /* Sanity check */
628     HDassert(oloc);
629     HDassert(num_objs);
630 
631     /* Reset the number of objects in the group */
632     *num_objs = 0;
633 
634     /* Get the B-tree info */
635     if(NULL == H5O_msg_read(oloc, H5O_STAB_ID, &stab, dxpl_id))
636 	HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address")
637 
638     /* Iterate over the group members */
639     if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_sumup, num_objs) < 0)
640         HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "iteration operator failed")
641 
642 done:
643     FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
644 } /* end H5G__stab_count() */
645 
646 
647 /*-------------------------------------------------------------------------
648  * Function:	H5G__stab_bh_size
649  *
650  * Purpose:	Retrieve storage for btree and heap (1.6)
651  *
652  * Return:	Non-negative on success/Negative on failure
653  *
654  * Programmer:	Vailin Choi
655  *		June 25 2007
656  *
657  *-------------------------------------------------------------------------
658  */
659 herr_t
H5G__stab_bh_size(H5F_t * f,hid_t dxpl_id,const H5O_stab_t * stab,H5_ih_info_t * bh_info)660 H5G__stab_bh_size(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab,
661     H5_ih_info_t *bh_info)
662 {
663     hsize_t     snode_size;             /* Symbol table node size */
664     H5B_info_t  bt_info;                /* B-tree node info */
665     herr_t      ret_value = SUCCEED;
666 
667     FUNC_ENTER_PACKAGE
668 
669     /* Sanity check */
670     HDassert(f);
671     HDassert(stab);
672     HDassert(bh_info);
673 
674     /* Set up user data for B-tree iteration */
675     snode_size = 0;
676 
677     /* Get the B-tree & symbol table node size info */
678     if(H5B_get_info(f, dxpl_id, H5B_SNODE, stab->btree_addr, &bt_info, H5G__node_iterate_size, &snode_size) < 0)
679         HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "iteration operator failed")
680 
681     /* Add symbol table & B-tree node sizes to index info */
682     bh_info->index_size += snode_size + bt_info.size;
683 
684     /* Get the size of the local heap for the group */
685     if(H5HL_heapsize(f, dxpl_id, stab->heap_addr, &(bh_info->heap_size)) < 0)
686         HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "iteration operator failed")
687 
688 done:
689     FUNC_LEAVE_NOAPI(ret_value)
690 } /* end H5G__stab_bh_size() */
691 
692 
693 /*-------------------------------------------------------------------------
694  * Function:	H5G_stab_get_name_by_idx_cb
695  *
696  * Purpose:     Callback for B-tree iteration 'by index' info query to
697  *              retrieve the name of a link
698  *
699  * Return:	Success:        Non-negative
700  *		Failure:	Negative
701  *
702  * Programmer:	Quincey Koziol
703  *	        Nov  7, 2006
704  *
705  *-------------------------------------------------------------------------
706  */
707 static herr_t
H5G_stab_get_name_by_idx_cb(const H5G_entry_t * ent,void * _udata)708 H5G_stab_get_name_by_idx_cb(const H5G_entry_t *ent, void *_udata)
709 {
710     H5G_bt_it_gnbi_t	*udata = (H5G_bt_it_gnbi_t *)_udata;
711     size_t name_off;                    /* Offset of name in heap */
712     const char *name;                   /* Pointer to name string in heap */
713 
714     FUNC_ENTER_NOAPI_NOINIT_NOERR
715 
716     /* Sanity check */
717     HDassert(ent);
718     HDassert(udata && udata->heap);
719 
720     /* Get name offset in heap */
721     name_off = ent->name_off;
722     name = (const char *)H5HL_offset_into(udata->heap, name_off);
723     HDassert(name);
724     udata->name = H5MM_strdup(name);
725     HDassert(udata->name);
726 
727     FUNC_LEAVE_NOAPI(SUCCEED)
728 } /* end H5G_stab_get_name_by_idx_cb */
729 
730 
731 /*-------------------------------------------------------------------------
732  * Function:	H5G__stab_get_name_by_idx
733  *
734  * Purpose:     Returns the name of objects in the group by giving index.
735  *
736  * Return:	Success:        Non-negative, length of name
737  *		Failure:	Negative
738  *
739  * Programmer:	Raymond Lu
740  *	        Nov 20, 2002
741  *
742  *-------------------------------------------------------------------------
743  */
744 ssize_t
H5G__stab_get_name_by_idx(const H5O_loc_t * oloc,H5_iter_order_t order,hsize_t n,char * name,size_t size,hid_t dxpl_id)745 H5G__stab_get_name_by_idx(const H5O_loc_t *oloc, H5_iter_order_t order, hsize_t n,
746     char* name, size_t size, hid_t dxpl_id)
747 {
748     H5HL_t *heap = NULL;        /* Pointer to local heap */
749     H5O_stab_t	stab;	        /* Info about local heap & B-tree */
750     H5G_bt_it_gnbi_t udata;     /* Iteration information */
751     hbool_t udata_valid = FALSE;        /* Whether iteration information is valid */
752     ssize_t ret_value = -1;             /* Return value */
753 
754     /* Portably clear udata struct (before FUNC_ENTER) */
755     HDmemset(&udata, 0, sizeof(udata));
756 
757     FUNC_ENTER_NOAPI(FAIL)
758 
759     /* Sanity check */
760     HDassert(oloc);
761 
762     /* Get the B-tree & local heap info */
763     if(NULL == H5O_msg_read(oloc, H5O_STAB_ID, &stab, dxpl_id))
764 	HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address")
765 
766     /* Pin the heap down in memory */
767     if(NULL == (heap = H5HL_protect(oloc->file, dxpl_id, stab.heap_addr, H5AC__READ_ONLY_FLAG)))
768         HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
769 
770     /* Remap index for decreasing iteration order */
771     if(order == H5_ITER_DEC) {
772         hsize_t nlinks = 0;           /* Number of links in group */
773 
774         /* Iterate over the symbol table nodes, to count the links */
775         if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_sumup, &nlinks) < 0)
776             HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "iteration operator failed")
777 
778         /* Map decreasing iteration order index to increasing iteration order index */
779         n = nlinks - (n + 1);
780     } /* end if */
781 
782     /* Set iteration information */
783     udata.common.idx = n;
784     udata.common.num_objs = 0;
785     udata.common.op = H5G_stab_get_name_by_idx_cb;
786     udata.heap = heap;
787     udata.name = NULL;
788     udata_valid = TRUE;
789 
790     /* Iterate over the group members */
791     if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_by_idx, &udata) < 0)
792 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "iteration operator failed")
793 
794     /* If we don't know the name now, we almost certainly went out of bounds */
795     if(udata.name == NULL)
796 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "index out of bound")
797 
798     /* Get the length of the name */
799     ret_value = (ssize_t)HDstrlen(udata.name);
800 
801     /* Copy the name into the user's buffer, if given */
802     if(name) {
803         HDstrncpy(name, udata.name, MIN((size_t)(ret_value + 1), size));
804         if((size_t)ret_value >= size)
805             name[size - 1]='\0';
806     } /* end if */
807 
808 done:
809     /* Release resources */
810     if(heap && H5HL_unprotect(heap) < 0)
811         HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
812 
813     /* Free the duplicated name */
814     if(udata_valid && udata.name != NULL)
815         H5MM_xfree(udata.name);
816 
817     FUNC_LEAVE_NOAPI(ret_value)
818 } /* end H5G__stab_get_name_by_idx() */
819 
820 
821 /*-------------------------------------------------------------------------
822  * Function:	H5G_stab_lookup_cb
823  *
824  * Purpose:     B-tree 'find' callback to retrieve location for an object
825  *
826  * Return:	Success:        Non-negative
827  *
828  *		Failure:	Negative
829  *
830  * Programmer:	Quincey Koziol
831  *	        Sep 20, 2005
832  *
833  *-------------------------------------------------------------------------
834  */
835 static herr_t
H5G_stab_lookup_cb(const H5G_entry_t * ent,void * _udata)836 H5G_stab_lookup_cb(const H5G_entry_t *ent, void *_udata)
837 {
838     H5G_stab_fnd_ud_t *udata = (H5G_stab_fnd_ud_t *)_udata;   /* 'User data' passed in */
839     herr_t ret_value = SUCCEED; /* Return value */
840 
841     FUNC_ENTER_NOAPI_NOINIT
842 
843     /* Check for setting link info */
844     if(udata->lnk)
845         /* Convert the entry to a link */
846         if(H5G__ent_to_link(udata->lnk, udata->heap, ent, udata->name) < 0)
847             HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, FAIL, "unable to convert symbol table entry to link")
848 
849 done:
850     FUNC_LEAVE_NOAPI(ret_value)
851 } /* end H5G_stab_lookup_cb() */
852 
853 
854 /*-------------------------------------------------------------------------
855  * Function:	H5G__stab_lookup
856  *
857  * Purpose:	Look up an object relative to a group, using symbol table
858  *
859  * Return:	Non-negative (TRUE/FALSE) on success/Negative on failure
860  *
861  * Programmer:	Quincey Koziol
862  *		koziol@ncsa.uiuc.edu
863  *		Sep 20 2005
864  *
865  *-------------------------------------------------------------------------
866  */
867 htri_t
H5G__stab_lookup(const H5O_loc_t * grp_oloc,const char * name,H5O_link_t * lnk,hid_t dxpl_id)868 H5G__stab_lookup(const H5O_loc_t *grp_oloc, const char *name, H5O_link_t *lnk,
869     hid_t dxpl_id)
870 {
871     H5HL_t *heap = NULL;                /* Pointer to local heap */
872     H5G_bt_lkp_t bt_udata;              /* Data to pass through B-tree	*/
873     H5G_stab_fnd_ud_t udata;            /* 'User data' to give to callback */
874     H5O_stab_t stab;		        /* Symbol table message		*/
875     htri_t     ret_value = FAIL;        /* Return value */
876 
877     FUNC_ENTER_PACKAGE
878 
879     /* check arguments */
880     HDassert(grp_oloc && grp_oloc->file);
881     HDassert(name && *name);
882     HDassert(lnk);
883 
884     /* Retrieve the symbol table message for the group */
885     if(NULL == H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, dxpl_id))
886         HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't read message")
887 
888     /* Pin the heap down in memory */
889     if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC__READ_ONLY_FLAG)))
890         HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
891 
892     /* Set up user data to pass to 'find' operation callback */
893     udata.name = name;
894     udata.lnk = lnk;
895     udata.heap = heap;
896 
897     /* Set up the user data for actual B-tree find operation */
898     bt_udata.common.name = name;
899     bt_udata.common.heap = heap;
900     bt_udata.op = H5G_stab_lookup_cb;
901     bt_udata.op_data = &udata;
902 
903     /* Search the B-tree */
904     if((ret_value = H5B_find(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, &bt_udata)) < 0)
905         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "not found")
906 
907 done:
908     /* Release resources */
909     if(heap && H5HL_unprotect(heap) < 0)
910         HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
911 
912     FUNC_LEAVE_NOAPI(ret_value)
913 } /* end H5G__stab_lookup() */
914 
915 
916 /*-------------------------------------------------------------------------
917  * Function:	H5G_stab_lookup_by_idx_cb
918  *
919  * Purpose:     Callback for B-tree iteration 'by index' info query to
920  *              retrieve the link
921  *
922  * Return:	Success:        Non-negative
923  *		Failure:	Negative
924  *
925  * Programmer:	Quincey Koziol
926  *	        Nov  9, 2006
927  *
928  *-------------------------------------------------------------------------
929  */
930 static herr_t
H5G_stab_lookup_by_idx_cb(const H5G_entry_t * ent,void * _udata)931 H5G_stab_lookup_by_idx_cb(const H5G_entry_t *ent, void *_udata)
932 {
933     H5G_bt_it_lbi_t *udata = (H5G_bt_it_lbi_t *)_udata;
934     const char *name;                   /* Pointer to name string in heap */
935     herr_t ret_value = SUCCEED;         /* Return value */
936 
937     FUNC_ENTER_NOAPI_NOINIT
938 
939     /* Sanity check */
940     HDassert(ent);
941     HDassert(udata && udata->heap);
942 
943     /* Get a pointer to the link name */
944     name = (const char *)H5HL_offset_into(udata->heap, ent->name_off);
945     HDassert(name);
946 
947     /* Convert the entry to a link */
948     if(H5G__ent_to_link(udata->lnk, udata->heap, ent, name) < 0)
949         HGOTO_ERROR(H5E_SYM, H5E_CANTCONVERT, FAIL, "unable to convert symbol table entry to link")
950     udata->found = TRUE;
951 
952 done:
953     FUNC_LEAVE_NOAPI(ret_value)
954 } /* end H5G_stab_lookup_by_idx_cb */
955 
956 
957 /*-------------------------------------------------------------------------
958  * Function:	H5G__stab_lookup_by_idx
959  *
960  * Purpose:	Look up an object in a group, according to the name index
961  *
962  * Return:	Non-negative on success/Negative on failure
963  *
964  * Programmer:	Quincey Koziol
965  *		koziol@hdfgroup.org
966  *		Nov  7 2006
967  *
968  *-------------------------------------------------------------------------
969  */
970 herr_t
H5G__stab_lookup_by_idx(const H5O_loc_t * grp_oloc,H5_iter_order_t order,hsize_t n,H5O_link_t * lnk,hid_t dxpl_id)971 H5G__stab_lookup_by_idx(const H5O_loc_t *grp_oloc, H5_iter_order_t order, hsize_t n,
972     H5O_link_t *lnk, hid_t dxpl_id)
973 {
974     H5HL_t *heap = NULL;                /* Pointer to local heap */
975     H5G_bt_it_lbi_t udata;              /* Iteration information */
976     H5O_stab_t stab;		        /* Symbol table message */
977     herr_t ret_value = SUCCEED;         /* Return value */
978 
979     FUNC_ENTER_PACKAGE
980 
981     /* check arguments */
982     HDassert(grp_oloc && grp_oloc->file);
983     HDassert(lnk);
984 
985     /* Get the B-tree & local heap info */
986     if(NULL == H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, dxpl_id))
987 	HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to determine local heap address")
988 
989     /* Pin the heap down in memory */
990     if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC__READ_ONLY_FLAG)))
991         HGOTO_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to protect symbol table heap")
992 
993     /* Remap index for decreasing iteration order */
994     if(order == H5_ITER_DEC) {
995         hsize_t nlinks = 0;           /* Number of links in group */
996 
997         /* Iterate over the symbol table nodes, to count the links */
998         if(H5B_iterate(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_sumup, &nlinks) < 0)
999             HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "iteration operator failed")
1000 
1001         /* Map decreasing iteration order index to increasing iteration order index */
1002         n = nlinks - (n + 1);
1003     } /* end if */
1004 
1005     /* Set iteration information */
1006     udata.common.idx = n;
1007     udata.common.num_objs = 0;
1008     udata.common.op = H5G_stab_lookup_by_idx_cb;
1009     udata.heap = heap;
1010     udata.lnk = lnk;
1011     udata.found = FALSE;
1012 
1013     /* Iterate over the group members */
1014     if(H5B_iterate(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_by_idx, &udata) < 0)
1015 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "iteration operator failed")
1016 
1017     /* If we didn't find the link, we almost certainly went out of bounds */
1018     if(!udata.found)
1019 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "index out of bound")
1020 
1021 done:
1022     /* Release resources */
1023     if(heap && H5HL_unprotect(heap) < 0)
1024         HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
1025 
1026     FUNC_LEAVE_NOAPI(ret_value)
1027 } /* end H5G__stab_lookup_by_idx() */
1028 
1029 #ifndef H5_STRICT_FORMAT_CHECKS
1030 
1031 /*-------------------------------------------------------------------------
1032  * Function:	H5G__stab_valid
1033  *
1034  * Purpose:	Verify that a group's symbol table message is valid.  If
1035  *              provided, the addresses in alt_stab will be tried if the
1036  *              addresses in the group's stab message are invalid, and
1037  *              the stab message will be updated if necessary.
1038  *
1039  *              NOTE: This function is only called when strict format
1040  *              checks are disabled.  This is so that, when strict
1041  *              format checks are enabled,  errors in the symbol table
1042  *              messages are not fixed by this function and are instead
1043  *              reported by the library.
1044  *
1045  * Return:	Non-negative on success/Negative on failure
1046  *
1047  * Programmer:	Neil Fortner
1048  *		nfortne2@hdfgroup.org
1049  *		Mar 17, 2009
1050  *
1051  *-------------------------------------------------------------------------
1052  */
1053 herr_t
H5G__stab_valid(H5O_loc_t * grp_oloc,hid_t dxpl_id,H5O_stab_t * alt_stab)1054 H5G__stab_valid(H5O_loc_t *grp_oloc, hid_t dxpl_id, H5O_stab_t *alt_stab)
1055 {
1056     H5O_stab_t  stab;                   /* Current symbol table */
1057     H5HL_t      *heap = NULL;           /* Pointer to local heap */
1058     hbool_t     changed = FALSE;        /* Whether stab has been modified */
1059     herr_t      ret_value = SUCCEED;    /* Return value */
1060 
1061     FUNC_ENTER_PACKAGE_TAG(dxpl_id, grp_oloc->addr, FAIL)
1062 
1063     /* Read the symbol table message */
1064     if(NULL == H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, dxpl_id))
1065         HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "unable to read symbol table message");
1066 
1067     /* Check if the symbol table message's b-tree address is valid */
1068     if(H5B_valid(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr) < 0) {
1069         /* Address is invalid, try the b-tree address in the alternate symbol
1070          * table message */
1071         if(!alt_stab || H5B_valid(grp_oloc->file, dxpl_id, H5B_SNODE, alt_stab->btree_addr) < 0)
1072             HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to locate b-tree")
1073         else {
1074             /* The alternate symbol table's b-tree address is valid.  Adjust the
1075              * symbol table message in the group. */
1076             stab.btree_addr = alt_stab->btree_addr;
1077             changed = TRUE;
1078         } /* end else */
1079     } /* end if */
1080 
1081     /* Check if the symbol table message's heap address is valid */
1082     if(NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, stab.heap_addr, H5AC__READ_ONLY_FLAG))) {
1083         /* Address is invalid, try the heap address in the alternate symbol
1084          * table message */
1085         if(!alt_stab || NULL == (heap = H5HL_protect(grp_oloc->file, dxpl_id, alt_stab->heap_addr, H5AC__READ_ONLY_FLAG)))
1086             HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "unable to locate heap")
1087         else {
1088             /* The alternate symbol table's heap address is valid.  Adjust the
1089              * symbol table message in the group. */
1090             stab.heap_addr = alt_stab->heap_addr;
1091             changed = TRUE;
1092         } /* end else */
1093     } /* end if */
1094 
1095     /* Update the symbol table message and clear errors if necessary */
1096     if(changed) {
1097         H5E_clear_stack(NULL);
1098         if(H5O_msg_write(grp_oloc, H5O_STAB_ID, 0, H5O_UPDATE_TIME | H5O_UPDATE_FORCE, &stab, dxpl_id) < 0)
1099             HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to correct symbol table message")
1100     } /* end if */
1101 
1102 done:
1103     /* Release resources */
1104     if(heap && H5HL_unprotect(heap) < 0)
1105         HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
1106 
1107     FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
1108 } /* end H5G__stab_valid */
1109 #endif /* H5_STRICT_FORMAT_CHECKS */
1110 
1111 #ifndef H5_NO_DEPRECATED_SYMBOLS
1112 
1113 /*-------------------------------------------------------------------------
1114  * Function:	H5G_stab_get_type_by_idx_cb
1115  *
1116  * Purpose:     Callback for B-tree iteration 'by index' info query to
1117  *              retrieve the type of an object
1118  *
1119  * Return:	Success:        Non-negative
1120  *		Failure:	Negative
1121  *
1122  * Programmer:	Quincey Koziol
1123  *	        Nov  7, 2006
1124  *
1125  *-------------------------------------------------------------------------
1126  */
1127 static herr_t
H5G_stab_get_type_by_idx_cb(const H5G_entry_t * ent,void * _udata)1128 H5G_stab_get_type_by_idx_cb(const H5G_entry_t *ent, void *_udata)
1129 {
1130     H5G_bt_it_gtbi_t	*udata = (H5G_bt_it_gtbi_t *)_udata;
1131     herr_t ret_value = SUCCEED;         /* Return value */
1132 
1133     FUNC_ENTER_NOAPI_NOINIT
1134 
1135     /* Sanity check */
1136     HDassert(ent);
1137     HDassert(udata);
1138 
1139     /* Check for a soft link */
1140     switch(ent->type) {
1141         case H5G_CACHED_SLINK:
1142             udata->type = H5G_LINK;
1143             break;
1144 
1145         case H5G_CACHED_ERROR:
1146         case H5G_NOTHING_CACHED:
1147         case H5G_CACHED_STAB:
1148         case H5G_NCACHED:
1149         default:
1150             {
1151                 H5O_loc_t tmp_oloc;             /* Temporary object location */
1152                 H5O_type_t obj_type;            /* Type of object at location */
1153 
1154                 /* Build temporary object location */
1155                 tmp_oloc.file = udata->f;
1156                 HDassert(H5F_addr_defined(ent->header));
1157                 tmp_oloc.addr = ent->header;
1158 
1159                 /* Get the type of the object */
1160                 if(H5O_obj_type(&tmp_oloc, &obj_type, udata->dxpl_id) < 0)
1161                     HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get object type")
1162                 udata->type = H5G_map_obj_type(obj_type);
1163             }
1164             break;
1165     } /* end switch */
1166 
1167 done:
1168     FUNC_LEAVE_NOAPI(ret_value)
1169 } /* end H5G_stab_get_type_by_idx_cb */
1170 
1171 
1172 /*-------------------------------------------------------------------------
1173  * Function:	H5G__stab_get_type_by_idx
1174  *
1175  * Purpose:     Private function for H5Gget_objtype_by_idx.
1176  *              Returns the type of objects in the group by giving index.
1177  *
1178  * Return:	Success:        H5G_GROUP(1), H5G_DATASET(2), H5G_TYPE(3)
1179  *
1180  *		Failure:	UNKNOWN
1181  *
1182  * Programmer:	Raymond Lu
1183  *	        Nov 20, 2002
1184  *
1185  *-------------------------------------------------------------------------
1186  */
1187 H5G_obj_t
H5G__stab_get_type_by_idx(H5O_loc_t * oloc,hsize_t idx,hid_t dxpl_id)1188 H5G__stab_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id)
1189 {
1190     H5O_stab_t		stab;	        /* Info about local heap & B-tree */
1191     H5G_bt_it_gtbi_t	udata;          /* User data for B-tree callback */
1192     H5G_obj_t		ret_value = H5G_UNKNOWN;        /* Return value */
1193 
1194     FUNC_ENTER_PACKAGE_TAG(dxpl_id, oloc->addr, H5G_UNKNOWN)
1195 
1196     /* Sanity check */
1197     HDassert(oloc);
1198 
1199     /* Get the B-tree & local heap info */
1200     if(NULL == H5O_msg_read(oloc, H5O_STAB_ID, &stab, dxpl_id))
1201 	HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5G_UNKNOWN, "unable to determine local heap address")
1202 
1203     /* Set iteration information */
1204     udata.common.idx = idx;
1205     udata.common.num_objs = 0;
1206     udata.common.op = H5G_stab_get_type_by_idx_cb;
1207     udata.f = oloc->file;
1208     udata.dxpl_id = dxpl_id;
1209     udata.type = H5G_UNKNOWN;
1210 
1211     /* Iterate over the group members */
1212     if(H5B_iterate(oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr, H5G__node_by_idx, &udata) < 0)
1213 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "iteration operator failed")
1214 
1215     /* If we don't know the type now, we almost certainly went out of bounds */
1216     if(udata.type == H5G_UNKNOWN)
1217 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "index out of bound")
1218 
1219     /* Set the return value */
1220     ret_value = udata.type;
1221 
1222 done:
1223     FUNC_LEAVE_NOAPI_TAG(ret_value, H5G_UNKNOWN)
1224 } /* end H5G__stab_get_type_by_idx() */
1225 #endif /* H5_NO_DEPRECATED_SYMBOLS */
1226 
1227