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