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