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