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 files COPYING and Copyright.html.  COPYING can be found at the root   *
9  * of the source code distribution tree; Copyright.html can be found at the  *
10  * root level of an installed copy of the electronic HDF5 document set and   *
11  * is linked from the top-level documents page.  It can also be found at     *
12  * http://hdfgroup.org/HDF5/doc/Copyright.html.  If you do not have          *
13  * access to either file, you may request a copy from help@hdfgroup.org.     *
14  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /*-------------------------------------------------------------------------
17  *
18  * Created:		H5Gloc.c
19  *			Sep 13 2005
20  *			Quincey Koziol <koziol@ncsa.uiuc.edu>
21  *
22  * Purpose:		Functions for working with group "locations"
23  *
24  *-------------------------------------------------------------------------
25  */
26 
27 /****************/
28 /* Module Setup */
29 /****************/
30 
31 #define H5G_PACKAGE		/*suppress error about including H5Gpkg	  */
32 
33 
34 /***********/
35 /* Headers */
36 /***********/
37 #include "H5private.h"		/* Generic Functions			*/
38 #include "H5Aprivate.h"		/* Attributes				*/
39 #include "H5Dprivate.h"		/* Datasets				*/
40 #include "H5Eprivate.h"		/* Error handling		  	*/
41 #include "H5Gpkg.h"		/* Groups		  		*/
42 #include "H5Iprivate.h"		/* IDs			  		*/
43 #include "H5Lprivate.h"		/* Links				*/
44 
45 
46 /****************/
47 /* Local Macros */
48 /****************/
49 
50 
51 /******************/
52 /* Local Typedefs */
53 /******************/
54 
55 /* User data for looking up an object in a group */
56 typedef struct {
57     /* upward */
58     H5G_loc_t  *loc;            /* Group location to set */
59 } H5G_loc_fnd_t;
60 
61 /* User data for checking if an object exists */
62 typedef struct {
63     /* upward */
64     htri_t exists;              /* Whether the object exists */
65 } H5G_loc_exists_t;
66 
67 /* User data for looking up an object in a group by index */
68 typedef struct {
69     /* downward */
70     hid_t lapl_id;              /* LAPL to use for operation */
71     hid_t dxpl_id;              /* DXPL to use for operation */
72     H5_index_t idx_type;        /* Index to use */
73     H5_iter_order_t order;      /* Iteration order within index */
74     hsize_t n;                  /* Offset within index */
75 
76     /* upward */
77     H5G_loc_t  *loc;            /* Group location to set */
78 } H5G_loc_fbi_t;
79 
80 /* User data for getting an object's info in a group */
81 typedef struct {
82     /* downward */
83     hid_t dxpl_id;              /* DXPL to use for operation */
84     hbool_t want_ih_info;       /* Whether to retrieve the index & heap info */
85 
86     /* upward */
87     H5O_info_t  *oinfo;         /* Object information to retrieve */
88 } H5G_loc_info_t;
89 
90 /* User data for setting an object's comment in a group */
91 typedef struct {
92     /* downward */
93     hid_t dxpl_id;              /* DXPL to use for operation */
94     const char *comment;        /* Object comment buffer */
95 
96     /* upward */
97 } H5G_loc_sc_t;
98 
99 /* User data for getting an object's comment in a group */
100 typedef struct {
101     /* downward */
102     hid_t dxpl_id;              /* DXPL to use for operation */
103     char  *comment;             /* Object comment buffer */
104     size_t bufsize;             /* Size of object comment buffer */
105 
106     /* upward */
107     ssize_t comment_size;       /* Actual size of object comment */
108 } H5G_loc_gc_t;
109 
110 
111 /********************/
112 /* Local Prototypes */
113 /********************/
114 
115 /* Group traversal callbacks */
116 static herr_t H5G_loc_find_cb(H5G_loc_t *grp_loc, const char *name,
117     const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata,
118     H5G_own_loc_t *own_loc);
119 static herr_t H5G_loc_find_by_idx_cb(H5G_loc_t *grp_loc, const char *name,
120     const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata,
121     H5G_own_loc_t *own_loc);
122 static herr_t H5G_loc_set_comment_cb(H5G_loc_t *grp_loc, const char *name,
123     const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata,
124     H5G_own_loc_t *own_loc);
125 static herr_t H5G_loc_get_comment_cb(H5G_loc_t *grp_loc, const char *name,
126     const H5O_link_t *lnk, H5G_loc_t *obj_loc, void *_udata,
127     H5G_own_loc_t *own_loc);
128 
129 
130 /*********************/
131 /* Package Variables */
132 /*********************/
133 
134 
135 /*****************************/
136 /* Library Private Variables */
137 /*****************************/
138 
139 
140 /*******************/
141 /* Local Variables */
142 /*******************/
143 
144 
145 
146 /*-------------------------------------------------------------------------
147  * Function:	H5G_loc
148  *
149  * Purpose:	Given an object ID return a location for the object.
150  *
151  * Return:	Success:	Group pointer.
152  *		Failure:	NULL
153  *
154  * Programmer:	Quincey Koziol
155  *              Tuesday, September 13, 2005
156  *
157  *-------------------------------------------------------------------------
158  */
159 herr_t
H5G_loc(hid_t loc_id,H5G_loc_t * loc)160 H5G_loc(hid_t loc_id, H5G_loc_t *loc)
161 {
162     herr_t      ret_value = SUCCEED;    /* Return value */
163 
164     FUNC_ENTER_NOAPI(FAIL)
165 
166     switch(H5I_get_type(loc_id)) {
167         case H5I_FILE:
168             {
169                 H5F_t	*f;
170 
171                 /* Get the file struct */
172                 if(NULL == (f = (H5F_t *)H5I_object(loc_id)))
173                     HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file ID")
174 
175                 /* Construct a group location for root group of the file */
176                 if(H5G_root_loc(f, loc) < 0)
177                     HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unable to create location for file")
178             } /* end case */
179             break;
180 
181         case H5I_GENPROP_CLS:
182         case H5I_GENPROP_LST:
183             HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get group location of property list")
184 
185         case H5I_ERROR_CLASS:
186         case H5I_ERROR_MSG:
187         case H5I_ERROR_STACK:
188             HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get group location of error class, message or stack")
189 
190         case H5I_GROUP:
191             {
192                 H5G_t	*group;
193 
194                 if(NULL == (group = (H5G_t *)H5I_object(loc_id)))
195                     HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid group ID")
196                 if(NULL == (loc->oloc = H5G_oloc(group)))
197                     HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of group")
198                 if(NULL == (loc->path = H5G_nameof(group)))
199                     HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path of group")
200             } /* end case */
201             break;
202 
203         case H5I_DATATYPE:
204             {
205                 H5T_t	*dt;
206 
207                 if(NULL == (dt = (H5T_t *)H5I_object(loc_id)))
208                     HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid type ID")
209                 if(NULL == (loc->oloc = H5T_oloc(dt)))
210                     HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of datatype")
211                 if(NULL == (loc->path = H5T_nameof(dt)))
212                     HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path of datatype")
213             } /* end case */
214             break;
215 
216         case H5I_DATASPACE:
217             HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get group location of dataspace")
218 
219         case H5I_DATASET:
220             {
221                 H5D_t	*dset;
222 
223                 if(NULL == (dset = (H5D_t *)H5I_object(loc_id)))
224                     HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid data ID")
225                 if(NULL == (loc->oloc = H5D_oloc(dset)))
226                     HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of dataset")
227                 if(NULL == (loc->path = H5D_nameof(dset)))
228                     HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path of dataset")
229             } /* end case */
230             break;
231 
232         case H5I_ATTR:
233             {
234                 H5A_t	*attr;
235 
236                 if(NULL == (attr = (H5A_t *)H5I_object(loc_id)))
237                     HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid attribute ID")
238                 if(NULL == (loc->oloc = H5A_oloc(attr)))
239                     HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location of attribute")
240                 if(NULL == (loc->path = H5A_nameof(attr)))
241                     HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path of attribute")
242             } /* end case */
243             break;
244 
245         case H5I_REFERENCE:
246             HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get group location of reference")
247 
248         case H5I_UNINIT:
249         case H5I_BADID:
250         case H5I_VFL:
251         case H5I_NTYPES:
252         default:
253             HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid object ID")
254     } /* end switch */
255 
256 done:
257     FUNC_LEAVE_NOAPI(ret_value)
258 } /* end H5G_loc() */
259 
260 
261 /*-------------------------------------------------------------------------
262  * Function:	H5G__loc_copy
263  *
264  * Purpose:	Copy over information for a location
265  *
266  * Return:	Non-negative on success/Negative on failure
267  *
268  * Programmer:	Quincey Koziol
269  *		Tuesday, September 13, 2005
270  *
271  *-------------------------------------------------------------------------
272  */
273 herr_t
H5G__loc_copy(H5G_loc_t * dst,const H5G_loc_t * src,H5_copy_depth_t depth)274 H5G__loc_copy(H5G_loc_t *dst, const H5G_loc_t *src, H5_copy_depth_t depth)
275 {
276     herr_t      ret_value = SUCCEED;       /* Return value */
277 
278     FUNC_ENTER_PACKAGE
279 
280     /* Check args. */
281     HDassert(dst);
282     HDassert(src);
283 
284     /* Copy components of the location */
285     if(H5O_loc_copy(dst->oloc, src->oloc, depth) < 0)
286         HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to copy entry")
287     if(H5G_name_copy(dst->path, src->path, depth) < 0)
288         HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to copy path")
289 
290 done:
291     FUNC_LEAVE_NOAPI(ret_value)
292 } /* end H5G__loc_copy() */
293 
294 
295 /*-------------------------------------------------------------------------
296  * Function:	H5G_loc_reset
297  *
298  * Purpose:	Reset information for a location
299  *
300  * Return:	Non-negative on success/Negative on failure
301  *
302  * Programmer:	Quincey Koziol
303  *		Tuesday, September 13, 2005
304  *
305  *-------------------------------------------------------------------------
306  */
307 herr_t
H5G_loc_reset(H5G_loc_t * loc)308 H5G_loc_reset(H5G_loc_t *loc)
309 {
310     herr_t      ret_value = SUCCEED;       /* Return value */
311 
312     FUNC_ENTER_NOAPI(FAIL)
313 
314     /* Check args. */
315     HDassert(loc);
316 
317     /* Reset components of the location */
318     if(H5O_loc_reset(loc->oloc) < 0)
319         HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to reset entry")
320     if(H5G_name_reset(loc->path) < 0)
321         HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to reset path")
322 
323 done:
324     FUNC_LEAVE_NOAPI(ret_value)
325 } /* end H5G_loc_reset() */
326 
327 
328 /*-------------------------------------------------------------------------
329  * Function:	H5G_loc_free
330  *
331  * Purpose:	Free information for a location
332  *
333  * Return:	Non-negative on success/Negative on failure
334  *
335  * Programmer:	Quincey Koziol
336  *		Tuesday, September 13, 2005
337  *
338  *-------------------------------------------------------------------------
339  */
340 herr_t
H5G_loc_free(H5G_loc_t * loc)341 H5G_loc_free(H5G_loc_t *loc)
342 {
343     herr_t      ret_value = SUCCEED;       /* Return value */
344 
345     FUNC_ENTER_NOAPI(FAIL)
346 
347     /* Check args. */
348     HDassert(loc);
349 
350     /* Reset components of the location */
351     if(H5G_name_free(loc->path) < 0)
352         HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to free path")
353     if(H5O_loc_free(loc->oloc) < 0)
354         HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to free object header location")
355 
356 done:
357     FUNC_LEAVE_NOAPI(ret_value)
358 } /* end H5G_loc_free() */
359 
360 
361 /*-------------------------------------------------------------------------
362  * Function:	H5G_loc_find_cb
363  *
364  * Purpose:	Callback for retrieving object location for an object in a group
365  *
366  * Return:	Non-negative on success/Negative on failure
367  *
368  * Programmer:	Quincey Koziol
369  *              Monday, October 17, 2005
370  *
371  *-------------------------------------------------------------------------
372  */
373 static herr_t
H5G_loc_find_cb(H5G_loc_t UNUSED * grp_loc,const char * name,const H5O_link_t UNUSED * lnk,H5G_loc_t * obj_loc,void * _udata,H5G_own_loc_t * own_loc)374 H5G_loc_find_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char *name,
375     const H5O_link_t UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
376     H5G_own_loc_t *own_loc/*out*/)
377 {
378     H5G_loc_fnd_t *udata = (H5G_loc_fnd_t *)_udata;   /* User data passed in */
379     herr_t ret_value = SUCCEED;         /* Return value */
380 
381     FUNC_ENTER_NOAPI_NOINIT
382 
383     /* Check if the name in this group resolved to a valid object */
384     if(obj_loc == NULL)
385         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object '%s' doesn't exist", name)
386 
387     /* Take ownership of the object's group location */
388     /* (Group traversal callbacks are responsible for either taking ownership
389      *  of the group location for the object, or freeing it. - QAK)
390      */
391     H5G__loc_copy(udata->loc, obj_loc, H5_COPY_SHALLOW);
392     *own_loc = H5G_OWN_OBJ_LOC;
393 
394 done:
395     FUNC_LEAVE_NOAPI(ret_value)
396 } /* end H5G_loc_find_cb() */
397 
398 
399 /*-------------------------------------------------------------------------
400  * Function:	H5G_loc_find
401  *
402  * Purpose:	Find a symbol from a location
403  *
404  * Return:	Non-negative on success/Negative on failure
405  *
406  * Programmer:	Quincey Koziol
407  *		Tuesday, September 13, 2005
408  *
409  *-------------------------------------------------------------------------
410  */
411 herr_t
H5G_loc_find(const H5G_loc_t * loc,const char * name,H5G_loc_t * obj_loc,hid_t lapl_id,hid_t dxpl_id)412 H5G_loc_find(const H5G_loc_t *loc, const char *name, H5G_loc_t *obj_loc/*out*/,
413     hid_t lapl_id, hid_t dxpl_id)
414 {
415     H5G_loc_fnd_t udata;                /* User data for traversal callback */
416     herr_t ret_value = SUCCEED;         /* Return value */
417 
418     FUNC_ENTER_NOAPI(FAIL)
419 
420     /* Check args. */
421     HDassert(loc);
422     HDassert(name && *name);
423     HDassert(obj_loc);
424 
425     /* Set up user data for locating object */
426     udata.loc = obj_loc;
427 
428     /* Traverse group hierarchy to locate object */
429     if(H5G_traverse(loc, name, H5G_TARGET_NORMAL, H5G_loc_find_cb, &udata, lapl_id, dxpl_id) < 0)
430         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object")
431 
432 done:
433     FUNC_LEAVE_NOAPI(ret_value)
434 } /* end H5G_loc_find() */
435 
436 
437 /*-------------------------------------------------------------------------
438  * Function:	H5G_loc_find_by_idx_cb
439  *
440  * Purpose:	Callback for retrieving object location for an object in a group
441  *              according to the order within an index
442  *
443  * Return:	Non-negative on success/Negative on failure
444  *
445  * Programmer:	Quincey Koziol
446  *              Monday, November 20, 2006
447  *
448  *-------------------------------------------------------------------------
449  */
450 static herr_t
H5G_loc_find_by_idx_cb(H5G_loc_t UNUSED * grp_loc,const char UNUSED * name,const H5O_link_t UNUSED * lnk,H5G_loc_t * obj_loc,void * _udata,H5G_own_loc_t * own_loc)451 H5G_loc_find_by_idx_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name,
452     const H5O_link_t UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
453     H5G_own_loc_t *own_loc/*out*/)
454 {
455     H5G_loc_fbi_t *udata = (H5G_loc_fbi_t *)_udata;   /* User data passed in */
456     H5O_link_t fnd_lnk;                 /* Link within group */
457     hbool_t lnk_copied = FALSE;         /* Whether the link was copied */
458     size_t links_left = H5L_NUM_LINKS;  /* # of links left to traverse */
459     hbool_t obj_loc_valid = FALSE;      /* Flag to indicate that the object location is valid */
460     hbool_t obj_exists = FALSE;         /* Whether the object exists (unused) */
461     herr_t ret_value = SUCCEED;         /* Return value */
462 
463     FUNC_ENTER_NOAPI_NOINIT
464 
465     /* Check if the name in this group resolved to a valid link */
466     if(obj_loc == NULL)
467         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group doesn't exist")
468 
469     /* Query link */
470     if(H5G_obj_lookup_by_idx(obj_loc->oloc, udata->idx_type, udata->order,
471                 udata->n, &fnd_lnk, udata->dxpl_id) < 0)
472         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "link not found")
473     lnk_copied = TRUE;
474 
475     /* Build the initial object location for the link */
476     if(H5G__link_to_loc(obj_loc, &fnd_lnk, udata->loc) < 0)
477         HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot initialize object location")
478     obj_loc_valid = TRUE;
479 
480     /* Perform any special traversals that the link needs */
481     /* (soft links, user-defined links, file mounting, etc.) */
482     /* (may modify the object location) */
483     if(H5G__traverse_special(obj_loc, &fnd_lnk, H5G_TARGET_NORMAL, &links_left, TRUE, udata->loc, &obj_exists, udata->lapl_id, udata->dxpl_id) < 0)
484         HGOTO_ERROR(H5E_LINK, H5E_TRAVERSE, FAIL, "special link traversal failed")
485 
486 done:
487     /* Reset the link information, if we have a copy */
488     if(lnk_copied)
489         H5O_msg_reset(H5O_LINK_ID, &fnd_lnk);
490 
491     /* Release the object location if we failed after copying it */
492     if(ret_value < 0 && obj_loc_valid)
493         if(H5G_loc_free(udata->loc) < 0)
494             HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't free location")
495 
496     /* Indicate that this callback didn't take ownership of the group *
497      * location for the object */
498     *own_loc = H5G_OWN_NONE;
499 
500     FUNC_LEAVE_NOAPI(ret_value)
501 } /* end H5G_loc_find_by_idx_cb() */
502 
503 
504 /*-------------------------------------------------------------------------
505  * Function:	H5G_loc_find_by_idx
506  *
507  * Purpose:	Find a symbol from a location, according to the order in an index
508  *
509  * Return:	Non-negative on success/Negative on failure
510  *
511  * Programmer:	Quincey Koziol
512  *		Monday, November 20, 2006
513  *
514  *-------------------------------------------------------------------------
515  */
516 herr_t
H5G_loc_find_by_idx(H5G_loc_t * loc,const char * group_name,H5_index_t idx_type,H5_iter_order_t order,hsize_t n,H5G_loc_t * obj_loc,hid_t lapl_id,hid_t dxpl_id)517 H5G_loc_find_by_idx(H5G_loc_t *loc, const char *group_name, H5_index_t idx_type,
518     H5_iter_order_t order, hsize_t n, H5G_loc_t *obj_loc/*out*/, hid_t lapl_id,
519     hid_t dxpl_id)
520 {
521     H5G_loc_fbi_t udata;                /* User data for traversal callback */
522     herr_t ret_value = SUCCEED;         /* Return value */
523 
524     FUNC_ENTER_NOAPI(FAIL)
525 
526     /* Check args. */
527     HDassert(loc);
528     HDassert(group_name && *group_name);
529     HDassert(obj_loc);
530 
531     /* Set up user data for locating object */
532     udata.dxpl_id = dxpl_id;
533     udata.lapl_id = lapl_id;
534     udata.idx_type = idx_type;
535     udata.order = order;
536     udata.n = n;
537     udata.loc = obj_loc;
538 
539     /* Traverse group hierarchy to locate object */
540     if(H5G_traverse(loc, group_name, H5G_TARGET_NORMAL, H5G_loc_find_by_idx_cb, &udata, lapl_id, dxpl_id) < 0)
541         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object")
542 
543 done:
544     FUNC_LEAVE_NOAPI(ret_value)
545 } /* end H5G_loc_find_by_idx() */
546 
547 
548 /*-------------------------------------------------------------------------
549  * Function:	H5G__loc_insert
550  *
551  * Purpose:	Insert an object at a location
552  *
553  * Return:	Non-negative on success/Negative on failure
554  *
555  * Programmer:	Quincey Koziol
556  *		Tuesday, September 13, 2005
557  *
558  *-------------------------------------------------------------------------
559  */
560 herr_t
H5G__loc_insert(H5G_loc_t * grp_loc,const char * name,H5G_loc_t * obj_loc,H5O_type_t obj_type,const void * crt_info,hid_t dxpl_id)561 H5G__loc_insert(H5G_loc_t *grp_loc, const char *name, H5G_loc_t *obj_loc,
562     H5O_type_t obj_type, const void *crt_info, hid_t dxpl_id)
563 {
564     H5O_link_t  lnk;                    /* Link for object to insert */
565     herr_t      ret_value = SUCCEED;    /* Return value */
566 
567     FUNC_ENTER_PACKAGE
568 
569     /* Check args. */
570     HDassert(grp_loc);
571     HDassert(name && *name);
572     HDassert(obj_loc);
573 
574     /* Create link object for the object location */
575     lnk.type = H5L_TYPE_HARD;
576     lnk.cset = H5F_DEFAULT_CSET;
577     lnk.corder = 0;     /* Will be reset if the group is tracking creation order */
578     lnk.corder_valid = FALSE;   /* Indicate that the creation order isn't valid (yet) */
579     /* Casting away const OK -QAK */
580     lnk.name = (char *)name;
581     lnk.u.hard.addr = obj_loc->oloc->addr;
582 
583     /* Insert new group into current group's symbol table */
584     if(H5G_obj_insert(grp_loc->oloc, name, &lnk, TRUE, obj_type, crt_info,
585             dxpl_id) < 0)
586         HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert object")
587 
588     /* Set the name of the object location */
589     if(H5G_name_set(grp_loc->path, obj_loc->path, name) < 0)
590        HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot set name")
591 
592 done:
593     FUNC_LEAVE_NOAPI(ret_value)
594 } /* end H5G__loc_insert() */
595 
596 
597 /*-------------------------------------------------------------------------
598  * Function:	H5G_loc_exists_cb
599  *
600  * Purpose:	Callback for checking if an object exists
601  *
602  * Return:	Non-negative on success/Negative on failure
603  *
604  * Programmer:	Quincey Koziol
605  *              Tuesday, February 2, 2010
606  *
607  *-------------------------------------------------------------------------
608  */
609 static herr_t
H5G_loc_exists_cb(H5G_loc_t UNUSED * grp_loc,const char UNUSED * name,const H5O_link_t UNUSED * lnk,H5G_loc_t * obj_loc,void * _udata,H5G_own_loc_t * own_loc)610 H5G_loc_exists_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name,
611     const H5O_link_t UNUSED *lnk, H5G_loc_t *obj_loc, void *_udata/*in,out*/,
612     H5G_own_loc_t *own_loc/*out*/)
613 {
614     H5G_loc_exists_t *udata = (H5G_loc_exists_t *)_udata;   /* User data passed in */
615 
616     FUNC_ENTER_NOAPI_NOINIT_NOERR
617 
618     /* Check if the name in this group resolved to a valid object */
619     if(obj_loc == NULL)
620         if(lnk)
621             udata->exists = FALSE;
622         else
623             udata->exists = FAIL;
624     else
625         udata->exists = TRUE;
626 
627     /* Indicate that this callback didn't take ownership of the group *
628      * location for the object */
629     *own_loc = H5G_OWN_NONE;
630 
631     FUNC_LEAVE_NOAPI(SUCCEED)
632 } /* end H5G_loc_exists_cb() */
633 
634 
635 /*-------------------------------------------------------------------------
636  * Function:	H5G_loc_exists
637  *
638  * Purpose:	Check if an object actually exists at a location
639  *
640  * Return:	Success:	TRUE/FALSE
641  * 		Failure:	Negative
642  *
643  * Programmer:	Quincey Koziol
644  *		Tuesday, February 2, 2010
645  *
646  *-------------------------------------------------------------------------
647  */
648 htri_t
H5G_loc_exists(const H5G_loc_t * loc,const char * name,hid_t lapl_id,hid_t dxpl_id)649 H5G_loc_exists(const H5G_loc_t *loc, const char *name, hid_t lapl_id, hid_t dxpl_id)
650 {
651     H5G_loc_exists_t udata;     /* User data for traversal callback */
652     htri_t ret_value;           /* Return value */
653 
654     FUNC_ENTER_NOAPI(FAIL)
655 
656     /* Check args. */
657     HDassert(loc);
658     HDassert(name && *name);
659 
660     /* Set up user data for locating object */
661     udata.exists = FALSE;
662 
663     /* Traverse group hierarchy to locate object */
664     if(H5G_traverse(loc, name, H5G_TARGET_EXISTS, H5G_loc_exists_cb, &udata, lapl_id, dxpl_id) < 0)
665         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't check if object exists")
666 
667     /* Set return value */
668     ret_value = udata.exists;
669 
670 done:
671     FUNC_LEAVE_NOAPI(ret_value)
672 } /* end H5G_loc_exists() */
673 
674 
675 /*-------------------------------------------------------------------------
676  * Function:	H5G_loc_info_cb
677  *
678  * Purpose:	Callback for retrieving object info for an object in a group
679  *
680  * Return:	Non-negative on success/Negative on failure
681  *
682  * Programmer:	Quincey Koziol
683  *              Thursday, November 23, 2006
684  *
685  *-------------------------------------------------------------------------
686  */
687 static herr_t
H5G_loc_info_cb(H5G_loc_t UNUSED * grp_loc,const char UNUSED * name,const H5O_link_t UNUSED * lnk,H5G_loc_t * obj_loc,void * _udata,H5G_own_loc_t * own_loc)688 H5G_loc_info_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const H5O_link_t UNUSED *lnk,
689     H5G_loc_t *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/)
690 {
691     H5G_loc_info_t *udata = (H5G_loc_info_t *)_udata;   /* User data passed in */
692     herr_t ret_value = SUCCEED;         /* Return value */
693 
694     FUNC_ENTER_NOAPI_NOINIT
695 
696     /* Check if the name in this group resolved to a valid link */
697     if(obj_loc == NULL)
698         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist")
699 
700     /* Query object information */
701     if(H5O_get_info(obj_loc->oloc, udata->dxpl_id, udata->want_ih_info, udata->oinfo) < 0)
702         HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get object info")
703 
704 done:
705     /* Indicate that this callback didn't take ownership of the group *
706      * location for the object */
707     *own_loc = H5G_OWN_NONE;
708 
709     FUNC_LEAVE_NOAPI(ret_value)
710 } /* end H5G_loc_info_cb() */
711 
712 
713 /*-------------------------------------------------------------------------
714  * Function:	H5G_loc_info
715  *
716  * Purpose:	Retrieve the information for an object from a group location
717  *              and path to that object
718  *
719  * Return:	Non-negative on success/Negative on failure
720  *
721  * Programmer:	Quincey Koziol
722  *		Thursday, November 23, 2006
723  *
724  *-------------------------------------------------------------------------
725  */
726 herr_t
H5G_loc_info(H5G_loc_t * loc,const char * name,hbool_t want_ih_info,H5O_info_t * oinfo,hid_t lapl_id,hid_t dxpl_id)727 H5G_loc_info(H5G_loc_t *loc, const char *name, hbool_t want_ih_info, H5O_info_t *oinfo/*out*/,
728     hid_t lapl_id, hid_t dxpl_id)
729 {
730     H5G_loc_info_t udata;               /* User data for traversal callback */
731     herr_t ret_value = SUCCEED;         /* Return value */
732 
733     FUNC_ENTER_NOAPI(FAIL)
734 
735     /* Check args. */
736     HDassert(loc);
737     HDassert(name && *name);
738     HDassert(oinfo);
739 
740     /* Set up user data for locating object */
741     udata.dxpl_id = dxpl_id;
742     udata.want_ih_info = want_ih_info;
743     udata.oinfo = oinfo;
744 
745     /* Traverse group hierarchy to locate object */
746     if(H5G_traverse(loc, name, H5G_TARGET_NORMAL, H5G_loc_info_cb, &udata, lapl_id, dxpl_id) < 0)
747         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object")
748 
749 done:
750     FUNC_LEAVE_NOAPI(ret_value)
751 } /* end H5G_loc_info() */
752 
753 
754 /*-------------------------------------------------------------------------
755  * Function:	H5G_loc_set_comment_cb
756  *
757  * Purpose:	Callback for (re)setting object comment for an object in a group
758  *
759  * Return:	Non-negative on success/Negative on failure
760  *
761  * Programmer:	Quincey Koziol
762  *              Thursday, August 30, 2007
763  *
764  *-------------------------------------------------------------------------
765  */
766 static herr_t
H5G_loc_set_comment_cb(H5G_loc_t UNUSED * grp_loc,const char UNUSED * name,const H5O_link_t UNUSED * lnk,H5G_loc_t * obj_loc,void * _udata,H5G_own_loc_t * own_loc)767 H5G_loc_set_comment_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const H5O_link_t UNUSED *lnk,
768     H5G_loc_t *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/)
769 {
770     H5G_loc_sc_t *udata = (H5G_loc_sc_t *)_udata;   /* User data passed in */
771     H5O_name_t comment;                 /* Object header "comment" message */
772     htri_t exists;                      /* Whether a "comment" message already exists */
773     herr_t ret_value = SUCCEED;         /* Return value */
774 
775     FUNC_ENTER_NOAPI_NOINIT
776 
777     /* Check if the name in this group resolved to a valid link */
778     if(obj_loc == NULL)
779         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist")
780 
781     /* Check for existing comment message */
782     if((exists = H5O_msg_exists(obj_loc->oloc, H5O_NAME_ID, udata->dxpl_id)) < 0)
783 	HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read object header")
784 
785     /* Remove the previous comment message if any */
786     if(exists)
787         if(H5O_msg_remove(obj_loc->oloc, H5O_NAME_ID, 0, TRUE, udata->dxpl_id) < 0)
788             HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete existing comment object header message")
789 
790     /* Add the new message */
791     if(udata->comment && *udata->comment) {
792         /* Casting away const OK -QAK */
793 	comment.s = (char *)udata->comment;
794 	if(H5O_msg_create(obj_loc->oloc, H5O_NAME_ID, 0, H5O_UPDATE_TIME, &comment, udata->dxpl_id) < 0)
795 	    HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to set comment object header message")
796     } /* end if */
797 
798 done:
799     /* Indicate that this callback didn't take ownership of the group *
800      * location for the object */
801     *own_loc = H5G_OWN_NONE;
802 
803     FUNC_LEAVE_NOAPI(ret_value)
804 } /* end H5G_loc_set_comment_cb() */
805 
806 
807 /*-------------------------------------------------------------------------
808  * Function:	H5G_loc_set_comment
809  *
810  * Purpose:	(Re)set the information for an object from a group location
811  *              and path to that object
812  *
813  * Return:	Non-negative on success/Negative on failure
814  *
815  * Programmer:	Quincey Koziol
816  *		Thursday, August 30, 2007
817  *
818  *-------------------------------------------------------------------------
819  */
820 herr_t
H5G_loc_set_comment(H5G_loc_t * loc,const char * name,const char * comment,hid_t lapl_id,hid_t dxpl_id)821 H5G_loc_set_comment(H5G_loc_t *loc, const char *name, const char *comment,
822     hid_t lapl_id, hid_t dxpl_id)
823 {
824     H5G_loc_sc_t udata;         /* User data for traversal callback */
825     herr_t ret_value = SUCCEED; /* Return value */
826 
827     FUNC_ENTER_NOAPI(FAIL)
828 
829     /* Check args. */
830     HDassert(loc);
831     HDassert(name && *name);
832 
833     /* Set up user data for locating object */
834     udata.dxpl_id = dxpl_id;
835     udata.comment = comment;
836 
837     /* Traverse group hierarchy to locate object */
838     if(H5G_traverse(loc, name, H5G_TARGET_NORMAL, H5G_loc_set_comment_cb, &udata, lapl_id, dxpl_id) < 0)
839         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object")
840 
841 done:
842     FUNC_LEAVE_NOAPI(ret_value)
843 } /* end H5G_loc_set_comment() */
844 
845 
846 /*-------------------------------------------------------------------------
847  * Function:	H5G_loc_get_comment_cb
848  *
849  * Purpose:	Callback for retrieving object comment for an object in a group
850  *
851  * Return:	Non-negative on success/Negative on failure
852  *
853  * Programmer:	Quincey Koziol
854  *              Thursday, August 30, 2007
855  *
856  *-------------------------------------------------------------------------
857  */
858 static herr_t
H5G_loc_get_comment_cb(H5G_loc_t UNUSED * grp_loc,const char UNUSED * name,const H5O_link_t UNUSED * lnk,H5G_loc_t * obj_loc,void * _udata,H5G_own_loc_t * own_loc)859 H5G_loc_get_comment_cb(H5G_loc_t UNUSED *grp_loc/*in*/, const char UNUSED *name, const H5O_link_t UNUSED *lnk,
860     H5G_loc_t *obj_loc, void *_udata/*in,out*/, H5G_own_loc_t *own_loc/*out*/)
861 {
862     H5G_loc_gc_t *udata = (H5G_loc_gc_t *)_udata;   /* User data passed in */
863     H5O_name_t comment;                 /* Object header "comment" message */
864     herr_t ret_value = SUCCEED;         /* Return value */
865 
866     FUNC_ENTER_NOAPI_NOINIT
867 
868     /* Check if the name in this group resolved to a valid link */
869     if(obj_loc == NULL)
870         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "name doesn't exist")
871 
872     /* Query object comment */
873     comment.s = NULL;
874     if(NULL == H5O_msg_read(obj_loc->oloc, H5O_NAME_ID, &comment, udata->dxpl_id)) {
875 	if(udata->comment && udata->bufsize > 0)
876             udata->comment[0] = '\0';
877 	udata->comment_size = 0;
878     } else {
879         if(udata->comment && udata->bufsize)
880 	   HDstrncpy(udata->comment, comment.s, udata->bufsize);
881 	udata->comment_size = (ssize_t)HDstrlen(comment.s);
882 	H5O_msg_reset(H5O_NAME_ID, &comment);
883     } /* end else */
884 
885 done:
886     /* Indicate that this callback didn't take ownership of the group *
887      * location for the object */
888     *own_loc = H5G_OWN_NONE;
889 
890     FUNC_LEAVE_NOAPI(ret_value)
891 } /* end H5G_loc_get_comment_cb() */
892 
893 
894 /*-------------------------------------------------------------------------
895  * Function:	H5G_loc_get_comment
896  *
897  * Purpose:	Retrieve the information for an object from a group location
898  *              and path to that object
899  *
900  * Return:	Success:	Number of bytes in the comment excluding the
901  *				null terminator.  Zero if the object has no
902  *				comment.
903  *
904  *		Failure:	Negative
905  *
906  * Programmer:	Quincey Koziol
907  *		Thursday, August 30, 2007
908  *
909  *-------------------------------------------------------------------------
910  */
911 ssize_t
H5G_loc_get_comment(H5G_loc_t * loc,const char * name,char * comment,size_t bufsize,hid_t lapl_id,hid_t dxpl_id)912 H5G_loc_get_comment(H5G_loc_t *loc, const char *name, char *comment/*out*/,
913     size_t bufsize, hid_t lapl_id, hid_t dxpl_id)
914 {
915     H5G_loc_gc_t udata;         /* User data for traversal callback */
916     ssize_t ret_value;          /* Return value */
917 
918     FUNC_ENTER_NOAPI(FAIL)
919 
920     /* Check args. */
921     HDassert(loc);
922     HDassert(name && *name);
923 
924     /* Set up user data for locating object */
925     udata.dxpl_id = dxpl_id;
926     udata.comment = comment;
927     udata.bufsize = bufsize;
928     udata.comment_size = (-1);
929 
930     /* Traverse group hierarchy to locate object */
931     if(H5G_traverse(loc, name, H5G_TARGET_NORMAL, H5G_loc_get_comment_cb, &udata, lapl_id, dxpl_id) < 0)
932         HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't find object")
933 
934     /* Set the return value */
935     ret_value = udata.comment_size;
936 
937 done:
938     FUNC_LEAVE_NOAPI(ret_value)
939 } /* end H5G_loc_get_comment() */
940 
941