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