Line | Count | Source (jump to first uncovered line) |
1 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | | * Copyright by The HDF Group. * |
3 | | * All rights reserved. * |
4 | | * * |
5 | | * This file is part of HDF5. The full HDF5 copyright notice, including * |
6 | | * terms governing use, modification, and redistribution, is contained in * |
7 | | * the LICENSE file, which can be found at the root of the source code * |
8 | | * distribution tree, or in https://www.hdfgroup.org/licenses. * |
9 | | * If you do not have access to either file, you may request a copy from * |
10 | | * help@hdfgroup.org. * |
11 | | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
12 | | |
13 | | /*------------------------------------------------------------------------- |
14 | | * |
15 | | * Created: H5Gint.c |
16 | | * |
17 | | * Purpose: General use, "internal" routines for groups. |
18 | | * |
19 | | *------------------------------------------------------------------------- |
20 | | */ |
21 | | |
22 | | /****************/ |
23 | | /* Module Setup */ |
24 | | /****************/ |
25 | | |
26 | | #include "H5Gmodule.h" /* This source code file is part of the H5G module */ |
27 | | |
28 | | /***********/ |
29 | | /* Headers */ |
30 | | /***********/ |
31 | | #include "H5private.h" /* Generic Functions */ |
32 | | #include "H5Eprivate.h" /* Error handling */ |
33 | | #include "H5FLprivate.h" /* Free Lists */ |
34 | | #include "H5FOprivate.h" /* File objects */ |
35 | | #include "H5Gpkg.h" /* Groups */ |
36 | | #include "H5Iprivate.h" /* IDs */ |
37 | | #include "H5Lprivate.h" /* Links */ |
38 | | #include "H5MMprivate.h" /* Memory management */ |
39 | | #include "H5SLprivate.h" /* Skip lists */ |
40 | | |
41 | | /****************/ |
42 | | /* Local Macros */ |
43 | | /****************/ |
44 | | |
45 | | /******************/ |
46 | | /* Local Typedefs */ |
47 | | /******************/ |
48 | | |
49 | | /* User data for path traversal routine for "insertion file" routine */ |
50 | | typedef struct { |
51 | | H5G_loc_t *loc; /* Pointer to the location for insertion */ |
52 | | } H5G_trav_ins_t; |
53 | | |
54 | | /* User data for application-style iteration over links in a group */ |
55 | | typedef struct { |
56 | | hid_t gid; /* The group ID for the application callback */ |
57 | | H5O_loc_t *link_loc; /* The object location for the link */ |
58 | | H5G_link_iterate_t lnk_op; /* Application callback */ |
59 | | void *op_data; /* Application's op data */ |
60 | | } H5G_iter_appcall_ud_t; |
61 | | |
62 | | /* User data for recursive traversal over links from a group */ |
63 | | typedef struct { |
64 | | hid_t gid; /* The group ID for the starting group */ |
65 | | H5G_loc_t *curr_loc; /* Location of starting group */ |
66 | | H5_index_t idx_type; /* Index to use */ |
67 | | H5_iter_order_t order; /* Iteration order within index */ |
68 | | H5SL_t *visited; /* Skip list for tracking visited nodes */ |
69 | | char *path; /* Path name of the link */ |
70 | | size_t curr_path_len; /* Current length of the path in the buffer */ |
71 | | size_t path_buf_size; /* Size of path buffer */ |
72 | | H5L_iterate2_t op; /* Application callback */ |
73 | | void *op_data; /* Application's op data */ |
74 | | } H5G_iter_visit_ud_t; |
75 | | |
76 | | /********************/ |
77 | | /* Package Typedefs */ |
78 | | /********************/ |
79 | | |
80 | | /********************/ |
81 | | /* Local Prototypes */ |
82 | | /********************/ |
83 | | |
84 | | static herr_t H5G__open_oid(H5G_t *grp); |
85 | | static herr_t H5G__visit_cb(const H5O_link_t *lnk, void *_udata); |
86 | | static herr_t H5G__close_cb(H5VL_object_t *grp_vol_obj, void **request); |
87 | | |
88 | | /*********************/ |
89 | | /* Package Variables */ |
90 | | /*********************/ |
91 | | |
92 | | /* Package initialization variable */ |
93 | | bool H5_PKG_INIT_VAR = false; |
94 | | |
95 | | /* Declare a free list to manage the H5G_t struct */ |
96 | | H5FL_DEFINE(H5G_t); |
97 | | H5FL_DEFINE(H5G_shared_t); |
98 | | |
99 | | /* Declare the free list to manage H5_obj_t's */ |
100 | | H5FL_DEFINE(H5_obj_t); |
101 | | |
102 | | /*****************************/ |
103 | | /* Library Private Variables */ |
104 | | /*****************************/ |
105 | | |
106 | | /*******************/ |
107 | | /* Local Variables */ |
108 | | /*******************/ |
109 | | |
110 | | /* Group ID class */ |
111 | | static const H5I_class_t H5I_GROUP_CLS[1] = {{ |
112 | | H5I_GROUP, /* ID class value */ |
113 | | 0, /* Class flags */ |
114 | | 0, /* # of reserved IDs for class */ |
115 | | (H5I_free_t)H5G__close_cb /* Callback routine for closing objects of this class */ |
116 | | }}; |
117 | | |
118 | | /* Flag indicating "top" of interface has been initialized */ |
119 | | static bool H5G_top_package_initialize_s = false; |
120 | | |
121 | | /*------------------------------------------------------------------------- |
122 | | * Function: H5G_init |
123 | | * |
124 | | * Purpose: Initialize the interface from some other layer. |
125 | | * |
126 | | * Return: Success: non-negative |
127 | | * |
128 | | * Failure: negative |
129 | | *------------------------------------------------------------------------- |
130 | | */ |
131 | | herr_t |
132 | | H5G_init(void) |
133 | 2 | { |
134 | 2 | herr_t ret_value = SUCCEED; /* Return value */ |
135 | | |
136 | 2 | FUNC_ENTER_NOAPI(FAIL) |
137 | | /* FUNC_ENTER() does all the work */ |
138 | | |
139 | 2 | done: |
140 | 2 | FUNC_LEAVE_NOAPI(ret_value) |
141 | 2 | } /* end H5G_init() */ |
142 | | |
143 | | /*------------------------------------------------------------------------- |
144 | | * Function: H5G__init_package |
145 | | * |
146 | | * Purpose: Initializes the H5G interface. |
147 | | * |
148 | | * Return: Non-negative on success/Negative on failure |
149 | | * |
150 | | * Programmer: Robb Matzke |
151 | | * Monday, January 5, 1998 |
152 | | * |
153 | | * Notes: The group creation properties are registered in the property |
154 | | * list interface initialization routine (H5P_init_package) |
155 | | * so that the file creation property class can inherit from it |
156 | | * correctly. (Which allows the file creation property list to |
157 | | * control the group creation properties of the root group of |
158 | | * a file) QAK - 24/10/2005 |
159 | | * |
160 | | *------------------------------------------------------------------------- |
161 | | */ |
162 | | herr_t |
163 | | H5G__init_package(void) |
164 | 2 | { |
165 | 2 | herr_t ret_value = SUCCEED; /* Return value */ |
166 | | |
167 | 2 | FUNC_ENTER_PACKAGE |
168 | | |
169 | | /* Initialize the ID group for the group IDs */ |
170 | 2 | if (H5I_register_type(H5I_GROUP_CLS) < 0) |
171 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to initialize interface"); |
172 | | |
173 | | /* Mark "top" of interface as initialized, too */ |
174 | 2 | H5G_top_package_initialize_s = true; |
175 | | |
176 | 2 | done: |
177 | 2 | FUNC_LEAVE_NOAPI(ret_value) |
178 | 2 | } /* end H5G__init_package() */ |
179 | | |
180 | | /*------------------------------------------------------------------------- |
181 | | * Function: H5G_top_term_package |
182 | | * |
183 | | * Purpose: Close the "top" of the interface, releasing IDs, etc. |
184 | | * |
185 | | * Return: Success: Positive if anything is done that might |
186 | | * affect other interfaces; zero otherwise. |
187 | | * Failure: Negative. |
188 | | * |
189 | | *------------------------------------------------------------------------- |
190 | | */ |
191 | | int |
192 | | H5G_top_term_package(void) |
193 | 18 | { |
194 | 18 | int n = 0; |
195 | | |
196 | 18 | FUNC_ENTER_NOAPI_NOINIT_NOERR |
197 | | |
198 | 8 | if (H5G_top_package_initialize_s) { |
199 | 2 | if (H5I_nmembers(H5I_GROUP) > 0) { |
200 | 0 | (void)H5I_clear_type(H5I_GROUP, false, false); |
201 | 0 | n++; |
202 | 0 | } |
203 | | |
204 | | /* Mark closed */ |
205 | 2 | if (0 == n) |
206 | 2 | H5G_top_package_initialize_s = false; |
207 | 2 | } /* end if */ |
208 | | |
209 | 8 | FUNC_LEAVE_NOAPI(n) |
210 | 18 | } /* end H5G_top_term_package() */ |
211 | | |
212 | | /*------------------------------------------------------------------------- |
213 | | * Function: H5G_term_package |
214 | | * |
215 | | * Purpose: Terminates the H5G interface |
216 | | * |
217 | | * Note: Finishes shutting down the interface, after |
218 | | * H5G_top_term_package() is called |
219 | | * |
220 | | * Return: Success: Positive if anything is done that might |
221 | | * affect other interfaces; zero otherwise. |
222 | | * Failure: Negative. |
223 | | * |
224 | | *------------------------------------------------------------------------- |
225 | | */ |
226 | | int |
227 | | H5G_term_package(void) |
228 | 12 | { |
229 | 12 | int n = 0; |
230 | | |
231 | 12 | FUNC_ENTER_NOAPI_NOINIT_NOERR |
232 | | |
233 | 2 | if (H5_PKG_INIT_VAR) { |
234 | | /* Sanity checks */ |
235 | 2 | assert(0 == H5I_nmembers(H5I_GROUP)); |
236 | 2 | assert(false == H5G_top_package_initialize_s); |
237 | | |
238 | | /* Destroy the group object id group */ |
239 | 2 | n += (H5I_dec_type_ref(H5I_GROUP) > 0); |
240 | | |
241 | | /* Mark closed */ |
242 | 2 | if (0 == n) |
243 | 2 | H5_PKG_INIT_VAR = false; |
244 | 2 | } /* end if */ |
245 | | |
246 | 2 | FUNC_LEAVE_NOAPI(n) |
247 | 12 | } /* end H5G_term_package() */ |
248 | | |
249 | | /*------------------------------------------------------------------------- |
250 | | * Function: H5G__close_cb |
251 | | * |
252 | | * Purpose: Called when the ref count reaches zero on the group's ID |
253 | | * |
254 | | * Return: SUCCEED/FAIL |
255 | | * |
256 | | *------------------------------------------------------------------------- |
257 | | */ |
258 | | static herr_t |
259 | | H5G__close_cb(H5VL_object_t *grp_vol_obj, void **request) |
260 | 0 | { |
261 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
262 | |
|
263 | 0 | FUNC_ENTER_PACKAGE |
264 | | |
265 | | /* Sanity check */ |
266 | 0 | assert(grp_vol_obj); |
267 | | |
268 | | /* Close the group */ |
269 | 0 | if (H5VL_group_close(grp_vol_obj, H5P_DATASET_XFER_DEFAULT, request) < 0) |
270 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to close group"); |
271 | | |
272 | | /* Free the VOL object */ |
273 | 0 | if (H5VL_free_object(grp_vol_obj) < 0) |
274 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTDEC, FAIL, "unable to free VOL object"); |
275 | | |
276 | 0 | done: |
277 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
278 | 0 | } /* end H5G__close_cb() */ |
279 | | |
280 | | /*------------------------------------------------------------------------- |
281 | | * Function: H5G__create_named |
282 | | * |
283 | | * Purpose: Internal routine to create a new "named" group. |
284 | | * |
285 | | * Return: Success: Non-NULL, pointer to new group object. |
286 | | * |
287 | | * Failure: NULL |
288 | | * |
289 | | *------------------------------------------------------------------------- |
290 | | */ |
291 | | H5G_t * |
292 | | H5G__create_named(const H5G_loc_t *loc, const char *name, hid_t lcpl_id, hid_t gcpl_id) |
293 | 0 | { |
294 | 0 | H5O_obj_create_t ocrt_info; /* Information for object creation */ |
295 | 0 | H5G_obj_create_t gcrt_info; /* Information for group creation */ |
296 | 0 | H5G_t *ret_value = NULL; /* Return value */ |
297 | |
|
298 | 0 | FUNC_ENTER_PACKAGE |
299 | | |
300 | | /* Check arguments */ |
301 | 0 | assert(loc); |
302 | 0 | assert(name && *name); |
303 | 0 | assert(lcpl_id != H5P_DEFAULT); |
304 | 0 | assert(gcpl_id != H5P_DEFAULT); |
305 | | |
306 | | /* Set up group creation info */ |
307 | 0 | gcrt_info.gcpl_id = gcpl_id; |
308 | 0 | gcrt_info.cache_type = H5G_NOTHING_CACHED; |
309 | 0 | memset(&gcrt_info.cache, 0, sizeof(gcrt_info.cache)); |
310 | | |
311 | | /* Set up object creation information */ |
312 | 0 | ocrt_info.obj_type = H5O_TYPE_GROUP; |
313 | 0 | ocrt_info.crt_info = &gcrt_info; |
314 | 0 | ocrt_info.new_obj = NULL; |
315 | | |
316 | | /* Create the new group and link it to its parent group */ |
317 | 0 | if (H5L_link_object(loc, name, &ocrt_info, lcpl_id) < 0) |
318 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "unable to create and link to group"); |
319 | 0 | assert(ocrt_info.new_obj); |
320 | | |
321 | | /* Set the return value */ |
322 | 0 | ret_value = (H5G_t *)ocrt_info.new_obj; |
323 | |
|
324 | 0 | done: |
325 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
326 | 0 | } /* end H5G__create_named() */ |
327 | | |
328 | | /*------------------------------------------------------------------------- |
329 | | * Function: H5G__create |
330 | | * |
331 | | * Purpose: Creates a new empty group with the specified name. The name |
332 | | * is either an absolute name or is relative to LOC. |
333 | | * |
334 | | * Return: Success: A handle for the group. The group is opened |
335 | | * and should eventually be close by calling |
336 | | * H5G_close(). |
337 | | * |
338 | | * Failure: NULL |
339 | | * |
340 | | *------------------------------------------------------------------------- |
341 | | */ |
342 | | H5G_t * |
343 | | H5G__create(H5F_t *file, H5G_obj_create_t *gcrt_info) |
344 | 0 | { |
345 | 0 | H5G_t *grp = NULL; /*new group */ |
346 | 0 | unsigned oloc_init = 0; /* Flag to indicate that the group object location was created successfully */ |
347 | 0 | H5G_t *ret_value = NULL; /* Return value */ |
348 | |
|
349 | 0 | FUNC_ENTER_PACKAGE |
350 | | |
351 | | /* check args */ |
352 | 0 | assert(file); |
353 | 0 | assert(gcrt_info->gcpl_id != H5P_DEFAULT); |
354 | | |
355 | | /* create an open group */ |
356 | 0 | if (NULL == (grp = H5FL_CALLOC(H5G_t))) |
357 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
358 | 0 | if (NULL == (grp->shared = H5FL_CALLOC(H5G_shared_t))) |
359 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
360 | | |
361 | | /* Create the group object header */ |
362 | 0 | if (H5G__obj_create(file, gcrt_info, &(grp->oloc) /*out*/) < 0) |
363 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "unable to create group object header"); |
364 | 0 | oloc_init = 1; /* Indicate that the object location information is valid */ |
365 | | |
366 | | /* Add group to list of open objects in file */ |
367 | 0 | if (H5FO_top_incr(grp->oloc.file, grp->oloc.addr) < 0) |
368 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINC, NULL, "can't incr object ref. count"); |
369 | 0 | if (H5FO_insert(grp->oloc.file, grp->oloc.addr, grp->shared, true) < 0) |
370 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert group into list of open objects"); |
371 | | |
372 | | /* Set the count of times the object is opened */ |
373 | 0 | grp->shared->fo_count = 1; |
374 | | |
375 | | /* Set return value */ |
376 | 0 | ret_value = grp; |
377 | |
|
378 | 0 | done: |
379 | 0 | if (ret_value == NULL) { |
380 | | /* Check if we need to release the file-oriented symbol table info */ |
381 | 0 | if (oloc_init) { |
382 | 0 | if (H5O_dec_rc_by_loc(&(grp->oloc)) < 0) |
383 | 0 | HDONE_ERROR(H5E_SYM, H5E_CANTDEC, NULL, |
384 | 0 | "unable to decrement refcount on newly created object"); |
385 | 0 | if (H5O_close(&(grp->oloc), NULL) < 0) |
386 | 0 | HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, NULL, "unable to release object header"); |
387 | 0 | if (H5O_delete(file, grp->oloc.addr) < 0) |
388 | 0 | HDONE_ERROR(H5E_SYM, H5E_CANTDELETE, NULL, "unable to delete object header"); |
389 | 0 | } /* end if */ |
390 | 0 | if (grp != NULL) { |
391 | 0 | if (grp->shared != NULL) |
392 | 0 | grp->shared = H5FL_FREE(H5G_shared_t, grp->shared); |
393 | 0 | grp = H5FL_FREE(H5G_t, grp); |
394 | 0 | } /* end if */ |
395 | 0 | } /* end if */ |
396 | |
|
397 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
398 | 0 | } /* end H5G__create() */ |
399 | | |
400 | | /*------------------------------------------------------------------------- |
401 | | * Function: H5G__open_name |
402 | | * |
403 | | * Purpose: Opens an existing group by name. |
404 | | * |
405 | | * Return: Success: Ptr to a new group. |
406 | | * Failure: NULL |
407 | | * |
408 | | *------------------------------------------------------------------------- |
409 | | */ |
410 | | H5G_t * |
411 | | H5G__open_name(const H5G_loc_t *loc, const char *name) |
412 | 0 | { |
413 | 0 | H5G_t *grp = NULL; /* Group to open */ |
414 | 0 | H5G_loc_t grp_loc; /* Location used to open group */ |
415 | 0 | H5G_name_t grp_path; /* Opened object group hier. path */ |
416 | 0 | H5O_loc_t grp_oloc; /* Opened object object location */ |
417 | 0 | bool loc_found = false; /* Location at 'name' found */ |
418 | 0 | H5O_type_t obj_type; /* Type of object at location */ |
419 | 0 | H5G_t *ret_value = NULL; /* Return value */ |
420 | |
|
421 | 0 | FUNC_ENTER_PACKAGE |
422 | | |
423 | | /* Check args */ |
424 | 0 | assert(loc); |
425 | 0 | assert(name); |
426 | | |
427 | | /* Set up opened group location to fill in */ |
428 | 0 | grp_loc.oloc = &grp_oloc; |
429 | 0 | grp_loc.path = &grp_path; |
430 | 0 | H5G_loc_reset(&grp_loc); |
431 | | |
432 | | /* Find the group object */ |
433 | 0 | if (H5G_loc_find(loc, name, &grp_loc /*out*/) < 0) |
434 | 0 | HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "group not found"); |
435 | 0 | loc_found = true; |
436 | | |
437 | | /* Check that the object found is the correct type */ |
438 | 0 | if (H5O_obj_type(&grp_oloc, &obj_type) < 0) |
439 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "can't get object type"); |
440 | 0 | if (obj_type != H5O_TYPE_GROUP) |
441 | 0 | HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, NULL, "not a group"); |
442 | | |
443 | | /* Open the group */ |
444 | 0 | if (NULL == (grp = H5G_open(&grp_loc))) |
445 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to open group"); |
446 | | |
447 | | /* Set return value */ |
448 | 0 | ret_value = grp; |
449 | |
|
450 | 0 | done: |
451 | 0 | if (!ret_value) |
452 | 0 | if (loc_found && H5G_loc_free(&grp_loc) < 0) |
453 | 0 | HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, NULL, "can't free location"); |
454 | |
|
455 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
456 | 0 | } /* end H5G__open_name() */ |
457 | | |
458 | | /*------------------------------------------------------------------------- |
459 | | * Function: H5G_open |
460 | | * |
461 | | * Purpose: Opens an existing group. The group should eventually be |
462 | | * closed by calling H5G_close(). |
463 | | * |
464 | | * Return: Success: Ptr to a new group. |
465 | | * |
466 | | * Failure: NULL |
467 | | * |
468 | | *------------------------------------------------------------------------- |
469 | | */ |
470 | | H5G_t * |
471 | | H5G_open(const H5G_loc_t *loc) |
472 | 0 | { |
473 | 0 | H5G_t *grp = NULL; /* Group opened */ |
474 | 0 | H5G_shared_t *shared_fo; /* Shared group object */ |
475 | 0 | H5G_t *ret_value = NULL; /* Return value */ |
476 | |
|
477 | 0 | FUNC_ENTER_NOAPI(NULL) |
478 | | |
479 | | /* Check args */ |
480 | 0 | assert(loc); |
481 | | |
482 | | /* Allocate the group structure */ |
483 | 0 | if (NULL == (grp = H5FL_CALLOC(H5G_t))) |
484 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for group"); |
485 | | |
486 | | /* Shallow copy (take ownership) of the group location object */ |
487 | 0 | if (H5O_loc_copy_shallow(&(grp->oloc), loc->oloc) < 0) |
488 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "can't copy object location"); |
489 | 0 | if (H5G_name_copy(&(grp->path), loc->path, H5_COPY_SHALLOW) < 0) |
490 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, NULL, "can't copy path"); |
491 | | |
492 | | /* Check if group was already open */ |
493 | 0 | if ((shared_fo = (H5G_shared_t *)H5FO_opened(grp->oloc.file, grp->oloc.addr)) == NULL) { |
494 | | /* Open the group object */ |
495 | 0 | if (H5G__open_oid(grp) < 0) |
496 | 0 | HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "not found"); |
497 | | |
498 | | /* Add group to list of open objects in file */ |
499 | 0 | if (H5FO_insert(grp->oloc.file, grp->oloc.addr, grp->shared, false) < 0) { |
500 | 0 | grp->shared = H5FL_FREE(H5G_shared_t, grp->shared); |
501 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert group into list of open objects"); |
502 | 0 | } /* end if */ |
503 | | |
504 | | /* Increment object count for the object in the top file */ |
505 | 0 | if (H5FO_top_incr(grp->oloc.file, grp->oloc.addr) < 0) |
506 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINC, NULL, "can't increment object count"); |
507 | | |
508 | | /* Set open object count */ |
509 | 0 | grp->shared->fo_count = 1; |
510 | 0 | } /* end if */ |
511 | 0 | else { |
512 | | /* Point to shared group info */ |
513 | 0 | grp->shared = shared_fo; |
514 | | |
515 | | /* Increment shared reference count */ |
516 | 0 | shared_fo->fo_count++; |
517 | | |
518 | | /* Check if the object has been opened through the top file yet */ |
519 | 0 | if (H5FO_top_count(grp->oloc.file, grp->oloc.addr) == 0) { |
520 | | /* Open the object through this top file */ |
521 | 0 | if (H5O_open(&(grp->oloc)) < 0) |
522 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to open object header"); |
523 | 0 | } /* end if */ |
524 | | |
525 | | /* Increment object count for the object in the top file */ |
526 | 0 | if (H5FO_top_incr(grp->oloc.file, grp->oloc.addr) < 0) |
527 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINC, NULL, "can't increment object count"); |
528 | 0 | } /* end else */ |
529 | | |
530 | | /* Set return value */ |
531 | 0 | ret_value = grp; |
532 | |
|
533 | 0 | done: |
534 | 0 | if (!ret_value && grp) { |
535 | 0 | H5O_loc_free(&(grp->oloc)); |
536 | 0 | H5G_name_free(&(grp->path)); |
537 | 0 | grp = H5FL_FREE(H5G_t, grp); |
538 | 0 | } /* end if */ |
539 | |
|
540 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
541 | 0 | } /* end H5G_open() */ |
542 | | |
543 | | /*------------------------------------------------------------------------- |
544 | | * Function: H5G__open_oid |
545 | | * |
546 | | * Purpose: Opens an existing group. The group should eventually be |
547 | | * closed by calling H5G_close(). |
548 | | * |
549 | | * Return: Success: Ptr to a new group. |
550 | | * |
551 | | * Failure: NULL |
552 | | * |
553 | | *------------------------------------------------------------------------- |
554 | | */ |
555 | | static herr_t |
556 | | H5G__open_oid(H5G_t *grp) |
557 | 0 | { |
558 | 0 | bool obj_opened = false; |
559 | 0 | htri_t msg_exists; |
560 | 0 | herr_t ret_value = SUCCEED; |
561 | |
|
562 | 0 | FUNC_ENTER_PACKAGE |
563 | | |
564 | | /* Check args */ |
565 | 0 | assert(grp); |
566 | | |
567 | | /* Allocate the shared information for the group */ |
568 | 0 | if (NULL == (grp->shared = H5FL_CALLOC(H5G_shared_t))) |
569 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); |
570 | | |
571 | | /* Grab the object header */ |
572 | 0 | if (H5O_open(&(grp->oloc)) < 0) |
573 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group"); |
574 | 0 | obj_opened = true; |
575 | | |
576 | | /* Check if this object has the right message(s) to be treated as a group */ |
577 | 0 | if ((msg_exists = H5O_msg_exists(&(grp->oloc), H5O_STAB_ID)) < 0) |
578 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check if symbol table message exists"); |
579 | 0 | if (!msg_exists) { |
580 | 0 | if ((msg_exists = H5O_msg_exists(&(grp->oloc), H5O_LINFO_ID)) < 0) |
581 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check if link info message exists"); |
582 | 0 | if (!msg_exists) |
583 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "not a group"); |
584 | 0 | } |
585 | | |
586 | 0 | done: |
587 | 0 | if (ret_value < 0) { |
588 | 0 | if (obj_opened) |
589 | 0 | H5O_close(&(grp->oloc), NULL); |
590 | 0 | if (grp->shared) |
591 | 0 | grp->shared = H5FL_FREE(H5G_shared_t, grp->shared); |
592 | 0 | } /* end if */ |
593 | |
|
594 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
595 | 0 | } /* end H5G__open_oid() */ |
596 | | |
597 | | /*------------------------------------------------------------------------- |
598 | | * Function: H5G_close |
599 | | * |
600 | | * Purpose: Closes the specified group. |
601 | | * |
602 | | * Return: Non-negative on success/Negative on failure |
603 | | * |
604 | | *------------------------------------------------------------------------- |
605 | | */ |
606 | | herr_t |
607 | | H5G_close(H5G_t *grp) |
608 | 0 | { |
609 | 0 | bool corked; /* Whether the group is corked or not */ |
610 | 0 | bool file_closed = true; /* H5O_close also closed the file? */ |
611 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
612 | |
|
613 | 0 | FUNC_ENTER_NOAPI(FAIL) |
614 | | |
615 | | /* Check args */ |
616 | 0 | assert(grp && grp->shared); |
617 | 0 | assert(grp->shared->fo_count > 0); |
618 | |
|
619 | 0 | --grp->shared->fo_count; |
620 | |
|
621 | 0 | if (0 == grp->shared->fo_count) { |
622 | 0 | assert(grp != H5G_rootof(H5G_fileof(grp))); |
623 | | |
624 | | /* Uncork cache entries with object address tag */ |
625 | 0 | if (H5AC_cork(grp->oloc.file, grp->oloc.addr, H5AC__GET_CORKED, &corked) < 0) |
626 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to retrieve an object's cork status"); |
627 | 0 | if (corked) |
628 | 0 | if (H5AC_cork(grp->oloc.file, grp->oloc.addr, H5AC__UNCORK, NULL) < 0) |
629 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTUNCORK, FAIL, "unable to uncork an object"); |
630 | | |
631 | | /* Remove the group from the list of opened objects in the file */ |
632 | 0 | if (H5FO_top_decr(grp->oloc.file, grp->oloc.addr) < 0) |
633 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't decrement count for object"); |
634 | 0 | if (H5FO_delete(grp->oloc.file, grp->oloc.addr) < 0) |
635 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't remove group from list of open objects"); |
636 | 0 | if (H5O_close(&(grp->oloc), &file_closed) < 0) |
637 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close"); |
638 | | |
639 | | /* Evict group metadata if evicting on close */ |
640 | 0 | if (!file_closed && H5F_SHARED(grp->oloc.file) && H5F_EVICT_ON_CLOSE(grp->oloc.file)) { |
641 | 0 | if (H5AC_flush_tagged_metadata(grp->oloc.file, grp->oloc.addr) < 0) |
642 | 0 | HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush tagged metadata"); |
643 | 0 | if (H5AC_evict_tagged_metadata(grp->oloc.file, grp->oloc.addr, false) < 0) |
644 | 0 | HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to evict tagged metadata"); |
645 | 0 | } /* end if */ |
646 | | |
647 | | /* Free memory */ |
648 | 0 | grp->shared = H5FL_FREE(H5G_shared_t, grp->shared); |
649 | 0 | } |
650 | 0 | else { |
651 | | /* Decrement the ref. count for this object in the top file */ |
652 | 0 | if (H5FO_top_decr(grp->oloc.file, grp->oloc.addr) < 0) |
653 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't decrement count for object"); |
654 | | |
655 | | /* Check reference count for this object in the top file */ |
656 | 0 | if (H5FO_top_count(grp->oloc.file, grp->oloc.addr) == 0) { |
657 | 0 | if (H5O_close(&(grp->oloc), NULL) < 0) |
658 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to close"); |
659 | 0 | } /* end if */ |
660 | 0 | else |
661 | | /* Free object location (i.e. "unhold" the file if appropriate) */ |
662 | 0 | if (H5O_loc_free(&(grp->oloc)) < 0) |
663 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "problem attempting to free location"); |
664 | | |
665 | | /* If this group is a mount point and the mount point is the last open |
666 | | * reference to the group (i.e. fo_count == 1 now), then attempt to |
667 | | * close down the file hierarchy |
668 | | */ |
669 | 0 | if (grp->shared->mounted && grp->shared->fo_count == 1) { |
670 | | /* Attempt to close down the file hierarchy */ |
671 | 0 | if (H5F_try_close(grp->oloc.file, NULL) < 0) |
672 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problem attempting file close"); |
673 | 0 | } /* end if */ |
674 | 0 | } /* end else */ |
675 | | |
676 | 0 | if (H5G_name_free(&(grp->path)) < 0) { |
677 | 0 | grp = H5FL_FREE(H5G_t, grp); |
678 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't free group entry name"); |
679 | 0 | } /* end if */ |
680 | | |
681 | 0 | grp = H5FL_FREE(H5G_t, grp); |
682 | |
|
683 | 0 | done: |
684 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
685 | 0 | } /* end H5G_close() */ |
686 | | |
687 | | /*------------------------------------------------------------------------- |
688 | | * Function: H5G_oloc |
689 | | * |
690 | | * Purpose: Returns a pointer to the object location for a group. |
691 | | * |
692 | | * Return: Success: Ptr to group entry |
693 | | * Failure: NULL |
694 | | * |
695 | | *------------------------------------------------------------------------- |
696 | | */ |
697 | | H5O_loc_t * |
698 | | H5G_oloc(H5G_t *grp) |
699 | 0 | { |
700 | | /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ |
701 | 0 | FUNC_ENTER_NOAPI_NOINIT_NOERR |
702 | |
|
703 | 0 | FUNC_LEAVE_NOAPI(grp ? &(grp->oloc) : NULL) |
704 | 0 | } /* end H5G_oloc() */ |
705 | | |
706 | | /*------------------------------------------------------------------------- |
707 | | * Function: H5G_nameof |
708 | | * |
709 | | * Purpose: Returns a pointer to the hier. name for a group. |
710 | | * |
711 | | * Return: Success: Ptr to hier. name |
712 | | * Failure: NULL |
713 | | * |
714 | | *------------------------------------------------------------------------- |
715 | | */ |
716 | | H5G_name_t * |
717 | | H5G_nameof(H5G_t *grp) |
718 | 0 | { |
719 | | /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ |
720 | 0 | FUNC_ENTER_NOAPI_NOINIT_NOERR |
721 | |
|
722 | 0 | FUNC_LEAVE_NOAPI(grp ? &(grp->path) : NULL) |
723 | 0 | } /* end H5G_nameof() */ |
724 | | |
725 | | /*------------------------------------------------------------------------- |
726 | | * Function: H5G_fileof |
727 | | * |
728 | | * Purpose: Returns the file to which the specified group belongs. |
729 | | * |
730 | | * Return: Success: File pointer. |
731 | | * |
732 | | * Failure: NULL |
733 | | * |
734 | | *------------------------------------------------------------------------- |
735 | | */ |
736 | | H5F_t * |
737 | | H5G_fileof(H5G_t *grp) |
738 | 0 | { |
739 | | /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ |
740 | 0 | FUNC_ENTER_NOAPI_NOINIT_NOERR |
741 | |
|
742 | 0 | assert(grp); |
743 | |
|
744 | 0 | FUNC_LEAVE_NOAPI(grp->oloc.file) |
745 | 0 | } /* end H5G_fileof() */ |
746 | | |
747 | | /*------------------------------------------------------------------------- |
748 | | * Function: H5G_get_shared_count |
749 | | * |
750 | | * Purpose: Queries the group object's "shared count" |
751 | | * |
752 | | * Return: Non-negative on success/Negative on failure |
753 | | * |
754 | | *------------------------------------------------------------------------- |
755 | | */ |
756 | | herr_t |
757 | | H5G_get_shared_count(H5G_t *grp) |
758 | 0 | { |
759 | 0 | FUNC_ENTER_NOAPI_NOINIT_NOERR |
760 | | |
761 | | /* Check args */ |
762 | 0 | assert(grp && grp->shared); |
763 | |
|
764 | 0 | FUNC_LEAVE_NOAPI(grp->shared->fo_count) |
765 | 0 | } /* end H5G_get_shared_count() */ |
766 | | |
767 | | /*------------------------------------------------------------------------- |
768 | | * Function: H5G_mount |
769 | | * |
770 | | * Purpose: Sets the 'mounted' flag for a group |
771 | | * |
772 | | * Return: Non-negative on success/Negative on failure |
773 | | * |
774 | | *------------------------------------------------------------------------- |
775 | | */ |
776 | | herr_t |
777 | | H5G_mount(H5G_t *grp) |
778 | 0 | { |
779 | 0 | FUNC_ENTER_NOAPI_NOINIT_NOERR |
780 | | |
781 | | /* Check args */ |
782 | 0 | assert(grp && grp->shared); |
783 | 0 | assert(grp->shared->mounted == false); |
784 | | |
785 | | /* Set the 'mounted' flag */ |
786 | 0 | grp->shared->mounted = true; |
787 | |
|
788 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
789 | 0 | } /* end H5G_mount() */ |
790 | | |
791 | | /*------------------------------------------------------------------------- |
792 | | * Function: H5G_mounted |
793 | | * |
794 | | * Purpose: Retrieves the 'mounted' flag for a group |
795 | | * |
796 | | * Return: Non-negative on success/Negative on failure |
797 | | * |
798 | | *------------------------------------------------------------------------- |
799 | | */ |
800 | | bool |
801 | | H5G_mounted(H5G_t *grp) |
802 | 0 | { |
803 | 0 | FUNC_ENTER_NOAPI_NOINIT_NOERR |
804 | | |
805 | | /* Check args */ |
806 | 0 | assert(grp && grp->shared); |
807 | |
|
808 | 0 | FUNC_LEAVE_NOAPI(grp->shared->mounted) |
809 | 0 | } /* end H5G_mounted() */ |
810 | | |
811 | | /*------------------------------------------------------------------------- |
812 | | * Function: H5G_unmount |
813 | | * |
814 | | * Purpose: Resets the 'mounted' flag for a group |
815 | | * |
816 | | * Return: Non-negative on success/Negative on failure |
817 | | * |
818 | | *------------------------------------------------------------------------- |
819 | | */ |
820 | | herr_t |
821 | | H5G_unmount(H5G_t *grp) |
822 | 0 | { |
823 | 0 | FUNC_ENTER_NOAPI_NOINIT_NOERR |
824 | | |
825 | | /* Check args */ |
826 | 0 | assert(grp && grp->shared); |
827 | 0 | assert(grp->shared->mounted == true); |
828 | | |
829 | | /* Reset the 'mounted' flag */ |
830 | 0 | grp->shared->mounted = false; |
831 | |
|
832 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
833 | 0 | } /* end H5G_unmount() */ |
834 | | |
835 | | /*------------------------------------------------------------------------- |
836 | | * Function: H5G__iterate_cb |
837 | | * |
838 | | * Purpose: Callback function for iterating over links in a group |
839 | | * |
840 | | * Return: Success: Non-negative |
841 | | * Failure: Negative |
842 | | * |
843 | | *------------------------------------------------------------------------- |
844 | | */ |
845 | | static herr_t |
846 | | H5G__iterate_cb(const H5O_link_t *lnk, void *_udata) |
847 | 0 | { |
848 | 0 | H5G_iter_appcall_ud_t *udata = (H5G_iter_appcall_ud_t *)_udata; /* User data for callback */ |
849 | 0 | herr_t ret_value = H5_ITER_ERROR; /* Return value */ |
850 | |
|
851 | 0 | FUNC_ENTER_PACKAGE |
852 | | |
853 | | /* Sanity check */ |
854 | 0 | assert(lnk); |
855 | 0 | assert(udata); |
856 | |
|
857 | 0 | switch (udata->lnk_op.op_type) { |
858 | 0 | #ifndef H5_NO_DEPRECATED_SYMBOLS |
859 | 0 | case H5G_LINK_OP_OLD: |
860 | | /* Prepare & restore library for user callback */ |
861 | 0 | H5_BEFORE_USER_CB(H5_ITER_ERROR) |
862 | 0 | { |
863 | | /* Make the old-type application callback */ |
864 | 0 | ret_value = (udata->lnk_op.op_func.op_old)(udata->gid, lnk->name, udata->op_data); |
865 | 0 | } |
866 | 0 | H5_AFTER_USER_CB(H5_ITER_ERROR) |
867 | 0 | break; |
868 | 0 | #endif /* H5_NO_DEPRECATED_SYMBOLS */ |
869 | | |
870 | 0 | case H5G_LINK_OP_NEW: { |
871 | 0 | H5L_info2_t info; /* Link info */ |
872 | | |
873 | | /* Retrieve the info for the link */ |
874 | 0 | if (H5G_link_to_info(udata->link_loc, lnk, &info) < 0) |
875 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link"); |
876 | | |
877 | | /* Prepare & restore library for user callback */ |
878 | 0 | H5_BEFORE_USER_CB(H5_ITER_ERROR) |
879 | 0 | { |
880 | | /* Make the application callback */ |
881 | 0 | ret_value = (udata->lnk_op.op_func.op_new)(udata->gid, lnk->name, &info, udata->op_data); |
882 | 0 | } |
883 | 0 | H5_AFTER_USER_CB(H5_ITER_ERROR) |
884 | 0 | } break; |
885 | | |
886 | 0 | default: |
887 | 0 | assert(0 && "Unknown link op type?!?"); |
888 | 0 | } /* end switch */ |
889 | | |
890 | 0 | done: |
891 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
892 | 0 | } /* end H5G__iterate_cb() */ |
893 | | |
894 | | /*------------------------------------------------------------------------- |
895 | | * Function: H5G_iterate |
896 | | * |
897 | | * Purpose: Private function for iterating over links in a group |
898 | | * |
899 | | * Return: SUCCEED/FAIL |
900 | | * |
901 | | *------------------------------------------------------------------------- |
902 | | */ |
903 | | herr_t |
904 | | H5G_iterate(H5G_loc_t *loc, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, |
905 | | hsize_t *last_lnk, const H5G_link_iterate_t *lnk_op, void *op_data) |
906 | 0 | { |
907 | 0 | hid_t gid = H5I_INVALID_HID; /* ID of group to iterate over */ |
908 | 0 | H5G_t *grp = NULL; /* Pointer to group data structure to iterate over */ |
909 | 0 | H5G_iter_appcall_ud_t udata; /* User data for callback */ |
910 | 0 | herr_t ret_value = FAIL; /* Return value */ |
911 | |
|
912 | 0 | FUNC_ENTER_NOAPI(FAIL) |
913 | | |
914 | | /* Sanity check */ |
915 | 0 | assert(loc); |
916 | 0 | assert(group_name); |
917 | 0 | assert(last_lnk); |
918 | 0 | assert(lnk_op && lnk_op->op_func.op_new); |
919 | | |
920 | | /* Open the group on which to operate. We also create a group ID which |
921 | | * we can pass to the application-defined operator. |
922 | | */ |
923 | 0 | if (NULL == (grp = H5G__open_name(loc, group_name))) |
924 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group"); |
925 | 0 | if ((gid = H5VL_wrap_register(H5I_GROUP, grp, true)) < 0) |
926 | 0 | HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, FAIL, "unable to register group"); |
927 | | |
928 | | /* Set up user data for callback */ |
929 | 0 | udata.gid = gid; |
930 | 0 | udata.link_loc = &grp->oloc; |
931 | 0 | udata.lnk_op = *lnk_op; |
932 | 0 | udata.op_data = op_data; |
933 | | |
934 | | /* Call the real group iteration routine */ |
935 | 0 | if ((ret_value = |
936 | 0 | H5G__obj_iterate(&(grp->oloc), idx_type, order, skip, last_lnk, H5G__iterate_cb, &udata)) < 0) |
937 | 0 | HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "error iterating over links"); |
938 | | |
939 | 0 | done: |
940 | | /* Release the group opened */ |
941 | 0 | if (gid != H5I_INVALID_HID) { |
942 | 0 | if (H5I_dec_app_ref(gid) < 0) |
943 | 0 | HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close group"); |
944 | 0 | } |
945 | 0 | else if (grp && H5G_close(grp) < 0) |
946 | 0 | HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release group"); |
947 | |
|
948 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
949 | 0 | } /* end H5G_iterate() */ |
950 | | |
951 | | /*------------------------------------------------------------------------- |
952 | | * Function: H5G__free_visit_visited |
953 | | * |
954 | | * Purpose: Free the key for an object visited during a group traversal |
955 | | * |
956 | | * Return: Non-negative on success, negative on failure |
957 | | * |
958 | | *------------------------------------------------------------------------- |
959 | | */ |
960 | | static herr_t |
961 | | H5G__free_visit_visited(void *item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSED *operator_data /*in,out*/) |
962 | 0 | { |
963 | 0 | FUNC_ENTER_PACKAGE_NOERR |
964 | |
|
965 | 0 | item = H5FL_FREE(H5_obj_t, item); |
966 | |
|
967 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
968 | 0 | } /* end H5G__free_visit_visited() */ |
969 | | |
970 | | /*------------------------------------------------------------------------- |
971 | | * Function: H5G__visit_cb |
972 | | * |
973 | | * Purpose: Callback function for recursively visiting links from a group |
974 | | * |
975 | | * Return: Success: Non-negative |
976 | | * Failure: Negative |
977 | | * |
978 | | *------------------------------------------------------------------------- |
979 | | */ |
980 | | static herr_t |
981 | | H5G__visit_cb(const H5O_link_t *lnk, void *_udata) |
982 | 0 | { |
983 | 0 | H5G_iter_visit_ud_t *udata = (H5G_iter_visit_ud_t *)_udata; /* User data for callback */ |
984 | 0 | H5L_info2_t info; /* Link info */ |
985 | 0 | H5G_loc_t obj_loc; /* Location of object */ |
986 | 0 | H5G_name_t obj_path; /* Object's group hier. path */ |
987 | 0 | H5O_loc_t obj_oloc; /* Object's object location */ |
988 | 0 | bool obj_found = false; /* Object at 'name' found */ |
989 | 0 | size_t old_path_len = udata->curr_path_len; /* Length of path before appending this link's name */ |
990 | 0 | size_t link_name_len; /* Length of link's name */ |
991 | 0 | size_t len_needed; /* Length of path string needed */ |
992 | 0 | herr_t ret_value = H5_ITER_CONT; /* Return value */ |
993 | |
|
994 | 0 | FUNC_ENTER_PACKAGE |
995 | | |
996 | | /* Sanity check */ |
997 | 0 | assert(lnk); |
998 | 0 | assert(udata); |
999 | | |
1000 | | /* Check if we will need more space to store this link's relative path */ |
1001 | | /* ("+2" is for string terminator and possible '/' for group separator later) */ |
1002 | 0 | link_name_len = strlen(lnk->name); |
1003 | 0 | len_needed = udata->curr_path_len + link_name_len + 2; |
1004 | 0 | if (len_needed > udata->path_buf_size) { |
1005 | 0 | void *new_path; /* Pointer to new path buffer */ |
1006 | | |
1007 | | /* Attempt to allocate larger buffer for path */ |
1008 | 0 | if (NULL == (new_path = H5MM_realloc(udata->path, len_needed))) |
1009 | 0 | HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate path string"); |
1010 | 0 | udata->path = (char *)new_path; |
1011 | 0 | udata->path_buf_size = len_needed; |
1012 | 0 | } /* end if */ |
1013 | | |
1014 | | /* Build the link's relative path name */ |
1015 | 0 | assert(udata->path[old_path_len] == '\0'); |
1016 | 0 | strncpy(&(udata->path[old_path_len]), lnk->name, link_name_len + 1); |
1017 | 0 | udata->curr_path_len += link_name_len; |
1018 | | |
1019 | | /* Construct the link info from the link message */ |
1020 | 0 | if (H5G_link_to_info(udata->curr_loc->oloc, lnk, &info) < 0) |
1021 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get info for link"); |
1022 | | |
1023 | | /* Prepare & restore library for user callback */ |
1024 | 0 | H5_BEFORE_USER_CB(H5_ITER_ERROR) |
1025 | 0 | { |
1026 | | /* Make the application callback */ |
1027 | 0 | ret_value = (udata->op)(udata->gid, udata->path, &info, udata->op_data); |
1028 | 0 | } |
1029 | 0 | H5_AFTER_USER_CB(H5_ITER_ERROR) |
1030 | | |
1031 | | /* Check for doing more work */ |
1032 | 0 | if (ret_value == H5_ITER_CONT && lnk->type == H5L_TYPE_HARD) { |
1033 | 0 | H5_obj_t obj_pos; /* Object "position" for this object */ |
1034 | | |
1035 | | /* Set up opened group location to fill in */ |
1036 | 0 | obj_loc.oloc = &obj_oloc; |
1037 | 0 | obj_loc.path = &obj_path; |
1038 | 0 | H5G_loc_reset(&obj_loc); |
1039 | | |
1040 | | /* Find the object using the LAPL passed in */ |
1041 | | /* (Correctly handles mounted files) */ |
1042 | 0 | if (H5G_loc_find(udata->curr_loc, lnk->name, &obj_loc /*out*/) < 0) |
1043 | 0 | HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5_ITER_ERROR, "object not found"); |
1044 | 0 | obj_found = true; |
1045 | | |
1046 | | /* Construct unique "position" for this object */ |
1047 | 0 | H5F_GET_FILENO(obj_oloc.file, obj_pos.fileno); |
1048 | 0 | obj_pos.addr = obj_oloc.addr; |
1049 | | |
1050 | | /* Check if we've seen the object the link references before */ |
1051 | 0 | if (NULL == H5SL_search(udata->visited, &obj_pos)) { |
1052 | 0 | H5O_type_t otype; /* Basic object type (group, dataset, etc.) */ |
1053 | | |
1054 | | /* Get the object's reference count and type */ |
1055 | 0 | if (H5O_get_rc_and_type(&obj_oloc, NULL, &otype) < 0) |
1056 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info"); |
1057 | | |
1058 | | /* Add it to the list of visited objects */ |
1059 | 0 | { |
1060 | 0 | H5_obj_t *new_node; /* New object node for visited list */ |
1061 | | |
1062 | | /* Allocate new object "position" node */ |
1063 | 0 | if ((new_node = H5FL_MALLOC(H5_obj_t)) == NULL) |
1064 | 0 | HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate object node"); |
1065 | | |
1066 | | /* Set node information */ |
1067 | 0 | *new_node = obj_pos; |
1068 | | |
1069 | | /* Add to list of visited objects */ |
1070 | 0 | if (H5SL_insert(udata->visited, new_node, new_node) < 0) |
1071 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5_ITER_ERROR, |
1072 | 0 | "can't insert object node into visited list"); |
1073 | 0 | } |
1074 | | |
1075 | | /* If it's a group, we recurse into it */ |
1076 | 0 | if (otype == H5O_TYPE_GROUP) { |
1077 | 0 | H5G_loc_t *old_loc = udata->curr_loc; /* Pointer to previous group location info */ |
1078 | 0 | H5_index_t idx_type = udata->idx_type; /* Type of index to use */ |
1079 | 0 | H5O_linfo_t linfo; /* Link info message */ |
1080 | 0 | htri_t linfo_exists; /* Whether the link info message exists */ |
1081 | | |
1082 | | /* Add the path separator to the current path */ |
1083 | 0 | assert(udata->path[udata->curr_path_len] == '\0'); |
1084 | 0 | strncpy(&(udata->path[udata->curr_path_len]), "/", (size_t)2); |
1085 | 0 | udata->curr_path_len++; |
1086 | | |
1087 | | /* Attempt to get the link info for this group */ |
1088 | 0 | if ((linfo_exists = H5G__obj_get_linfo(&obj_oloc, &linfo)) < 0) |
1089 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5_ITER_ERROR, "can't check for link info message"); |
1090 | 0 | if (linfo_exists) { |
1091 | | /* Check for creation order tracking, if creation order index lookup requested */ |
1092 | 0 | if (idx_type == H5_INDEX_CRT_ORDER) { |
1093 | | /* Check if creation order is tracked */ |
1094 | 0 | if (!linfo.track_corder) |
1095 | | /* Switch to name order for this group */ |
1096 | 0 | idx_type = H5_INDEX_NAME; |
1097 | 0 | } /* end if */ |
1098 | 0 | else |
1099 | 0 | assert(idx_type == H5_INDEX_NAME); |
1100 | 0 | } /* end if */ |
1101 | 0 | else { |
1102 | | /* Can only perform name lookups on groups with symbol tables */ |
1103 | 0 | if (idx_type != H5_INDEX_NAME) |
1104 | | /* Switch to name order for this group */ |
1105 | 0 | idx_type = H5_INDEX_NAME; |
1106 | 0 | } /* end if */ |
1107 | | |
1108 | | /* Point to this group's location info */ |
1109 | 0 | udata->curr_loc = &obj_loc; |
1110 | | |
1111 | | /* Iterate over links in group */ |
1112 | 0 | ret_value = H5G__obj_iterate(&obj_oloc, idx_type, udata->order, (hsize_t)0, NULL, |
1113 | 0 | H5G__visit_cb, udata); |
1114 | | |
1115 | | /* Restore location */ |
1116 | 0 | udata->curr_loc = old_loc; |
1117 | 0 | } /* end if */ |
1118 | 0 | } /* end if */ |
1119 | 0 | } /* end if */ |
1120 | | |
1121 | 0 | done: |
1122 | | /* Reset path back to incoming path */ |
1123 | 0 | udata->path[old_path_len] = '\0'; |
1124 | 0 | udata->curr_path_len = old_path_len; |
1125 | | |
1126 | | /* Release resources */ |
1127 | 0 | if (obj_found && H5G_loc_free(&obj_loc) < 0) |
1128 | 0 | HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location"); |
1129 | |
|
1130 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1131 | 0 | } /* end H5G__visit_cb() */ |
1132 | | |
1133 | | /*------------------------------------------------------------------------- |
1134 | | * Function: H5G_visit |
1135 | | * |
1136 | | * Purpose: Recursively visit all the links in a group and all |
1137 | | * the groups that are linked to from that group. Links within |
1138 | | * each group are visited according to the order within the |
1139 | | * specified index (unless the specified index does not exist for |
1140 | | * a particular group, then the "name" index is used). |
1141 | | * |
1142 | | * NOTE: Each _link_ reachable from the initial group will only be |
1143 | | * visited once. However, because an object may be reached from |
1144 | | * more than one link, the visitation may call the application's |
1145 | | * callback with more than one link that points to a particular |
1146 | | * _object_. |
1147 | | * |
1148 | | * Return: Success: The return value of the first operator that |
1149 | | * returns non-zero, or zero if all members were |
1150 | | * processed with no operator returning non-zero. |
1151 | | * |
1152 | | * Failure: Negative if something goes wrong within the |
1153 | | * library, or the negative value returned by one |
1154 | | * of the operators. |
1155 | | * |
1156 | | *------------------------------------------------------------------------- |
1157 | | */ |
1158 | | herr_t |
1159 | | H5G_visit(H5G_loc_t *loc, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, |
1160 | | H5L_iterate2_t op, void *op_data) |
1161 | 0 | { |
1162 | 0 | H5G_iter_visit_ud_t udata; /* User data for callback */ |
1163 | 0 | H5O_linfo_t linfo; /* Link info message */ |
1164 | 0 | htri_t linfo_exists; /* Whether the link info message exists */ |
1165 | 0 | hid_t gid = H5I_INVALID_HID; /* Group ID */ |
1166 | 0 | H5G_t *grp = NULL; /* Group opened */ |
1167 | 0 | H5G_loc_t start_loc; /* Location of starting group */ |
1168 | 0 | herr_t ret_value = FAIL; /* Return value */ |
1169 | | |
1170 | | /* Portably clear udata struct (before FUNC_ENTER) */ |
1171 | 0 | memset(&udata, 0, sizeof(udata)); |
1172 | |
|
1173 | 0 | FUNC_ENTER_NOAPI(FAIL) |
1174 | | |
1175 | | /* Check args */ |
1176 | 0 | if (!loc) |
1177 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "loc parameter cannot be NULL"); |
1178 | | |
1179 | | /* Open the group to begin visiting within */ |
1180 | 0 | if (NULL == (grp = H5G__open_name(loc, group_name))) |
1181 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open group"); |
1182 | | |
1183 | | /* Register an ID for the starting group */ |
1184 | 0 | if ((gid = H5VL_wrap_register(H5I_GROUP, grp, true)) < 0) |
1185 | 0 | HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, FAIL, "unable to register group"); |
1186 | | |
1187 | | /* Get the location of the starting group */ |
1188 | 0 | if (H5G_loc(gid, &start_loc) < 0) |
1189 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); |
1190 | | |
1191 | | /* Set up user data */ |
1192 | 0 | udata.gid = gid; |
1193 | 0 | udata.curr_loc = &start_loc; |
1194 | 0 | udata.idx_type = idx_type; |
1195 | 0 | udata.order = order; |
1196 | 0 | udata.op = op; |
1197 | 0 | udata.op_data = op_data; |
1198 | | |
1199 | | /* Allocate space for the path name */ |
1200 | 0 | if (NULL == (udata.path = H5MM_strdup(""))) |
1201 | 0 | HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate path name buffer"); |
1202 | 0 | udata.path_buf_size = 1; |
1203 | 0 | udata.curr_path_len = 0; |
1204 | | |
1205 | | /* Create skip list to store visited object information */ |
1206 | 0 | if ((udata.visited = H5SL_create(H5SL_TYPE_OBJ, NULL)) == NULL) |
1207 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create skip list for visited objects"); |
1208 | | |
1209 | | /* Add it to the list of visited objects */ |
1210 | 0 | { |
1211 | 0 | H5_obj_t *obj_pos; /* New object node for visited list */ |
1212 | | |
1213 | | /* Allocate new object "position" node */ |
1214 | 0 | if ((obj_pos = H5FL_MALLOC(H5_obj_t)) == NULL) |
1215 | 0 | HGOTO_ERROR(H5E_SYM, H5E_NOSPACE, FAIL, "can't allocate object node"); |
1216 | | |
1217 | | /* Construct unique "position" for this object */ |
1218 | 0 | H5F_GET_FILENO(grp->oloc.file, obj_pos->fileno); |
1219 | 0 | obj_pos->addr = grp->oloc.addr; |
1220 | | |
1221 | | /* Add to list of visited objects */ |
1222 | 0 | if (H5SL_insert(udata.visited, obj_pos, obj_pos) < 0) |
1223 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "can't insert object node into visited list"); |
1224 | 0 | } |
1225 | | |
1226 | | /* Attempt to get the link info for this group */ |
1227 | 0 | if ((linfo_exists = H5G__obj_get_linfo(&(grp->oloc), &linfo)) < 0) |
1228 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message"); |
1229 | 0 | if (linfo_exists) { |
1230 | | /* Check for creation order tracking, if creation order index lookup requested */ |
1231 | 0 | if (idx_type == H5_INDEX_CRT_ORDER) { |
1232 | | /* Check if creation order is tracked */ |
1233 | 0 | if (!linfo.track_corder) |
1234 | | /* Switch to name order for this group */ |
1235 | 0 | idx_type = H5_INDEX_NAME; |
1236 | 0 | } /* end if */ |
1237 | 0 | else |
1238 | 0 | assert(idx_type == H5_INDEX_NAME); |
1239 | 0 | } /* end if */ |
1240 | 0 | else { |
1241 | | /* Can only perform name lookups on groups with symbol tables */ |
1242 | 0 | if (idx_type != H5_INDEX_NAME) |
1243 | | /* Switch to name order for this group */ |
1244 | 0 | idx_type = H5_INDEX_NAME; |
1245 | 0 | } /* end if */ |
1246 | | |
1247 | | /* Call the link iteration routine */ |
1248 | 0 | if ((ret_value = |
1249 | 0 | H5G__obj_iterate(&(grp->oloc), idx_type, order, (hsize_t)0, NULL, H5G__visit_cb, &udata)) < 0) |
1250 | 0 | HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't visit links"); |
1251 | | |
1252 | 0 | done: |
1253 | | /* Release user data resources */ |
1254 | 0 | H5MM_xfree(udata.path); |
1255 | 0 | if (udata.visited) |
1256 | 0 | H5SL_destroy(udata.visited, H5G__free_visit_visited, NULL); |
1257 | | |
1258 | | /* Release the group opened */ |
1259 | 0 | if (gid != H5I_INVALID_HID) { |
1260 | 0 | if (H5I_dec_app_ref(gid) < 0) |
1261 | 0 | HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "unable to close group"); |
1262 | 0 | } |
1263 | 0 | else if (grp && H5G_close(grp) < 0) |
1264 | 0 | HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "unable to release group"); |
1265 | |
|
1266 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1267 | 0 | } /* end H5G_visit() */ |
1268 | | |
1269 | | /*------------------------------------------------------------------------- |
1270 | | * Function: H5G_get_create_plist |
1271 | | * |
1272 | | * Purpose: Private function for H5Gget_create_plist |
1273 | | * |
1274 | | * Return: Success: ID for a copy of the group creation |
1275 | | * property list. The property list ID should be |
1276 | | * released by calling H5Pclose(). |
1277 | | * |
1278 | | * Failure: H5I_INVALID_HID |
1279 | | * |
1280 | | *------------------------------------------------------------------------- |
1281 | | */ |
1282 | | hid_t |
1283 | | H5G_get_create_plist(const H5G_t *grp) |
1284 | 0 | { |
1285 | 0 | H5O_linfo_t linfo; /* Link info message */ |
1286 | 0 | htri_t ginfo_exists; |
1287 | 0 | htri_t linfo_exists; |
1288 | 0 | htri_t pline_exists; |
1289 | 0 | H5P_genplist_t *gcpl_plist; |
1290 | 0 | H5P_genplist_t *new_plist; |
1291 | 0 | hid_t new_gcpl_id = H5I_INVALID_HID; |
1292 | 0 | hid_t ret_value = H5I_INVALID_HID; |
1293 | |
|
1294 | 0 | FUNC_ENTER_NOAPI(H5I_INVALID_HID) |
1295 | | |
1296 | | /* Copy the default group creation property list */ |
1297 | 0 | if (NULL == (gcpl_plist = (H5P_genplist_t *)H5I_object(H5P_LST_GROUP_CREATE_ID_g))) |
1298 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "can't get default group creation property list"); |
1299 | 0 | if ((new_gcpl_id = H5P_copy_plist(gcpl_plist, true)) < 0) |
1300 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5I_INVALID_HID, "unable to copy the creation property list"); |
1301 | 0 | if (NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_gcpl_id))) |
1302 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "can't get property list"); |
1303 | | |
1304 | | /* Retrieve any object creation properties */ |
1305 | 0 | if (H5O_get_create_plist(&grp->oloc, new_plist) < 0) |
1306 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5I_INVALID_HID, "can't get object creation info"); |
1307 | | |
1308 | | /* Check for the group having a group info message */ |
1309 | 0 | if ((ginfo_exists = H5O_msg_exists(&(grp->oloc), H5O_GINFO_ID)) < 0) |
1310 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5I_INVALID_HID, "unable to read object header"); |
1311 | 0 | if (ginfo_exists) { |
1312 | 0 | H5O_ginfo_t ginfo; /* Group info message */ |
1313 | | |
1314 | | /* Read the group info */ |
1315 | 0 | if (NULL == H5O_msg_read(&(grp->oloc), H5O_GINFO_ID, &ginfo)) |
1316 | 0 | HGOTO_ERROR(H5E_SYM, H5E_BADMESG, H5I_INVALID_HID, "can't get group info"); |
1317 | | |
1318 | | /* Set the group info for the property list */ |
1319 | 0 | if (H5P_set(new_plist, H5G_CRT_GROUP_INFO_NAME, &ginfo) < 0) |
1320 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set group info"); |
1321 | 0 | } /* end if */ |
1322 | | |
1323 | | /* Check for the group having a link info message */ |
1324 | 0 | if ((linfo_exists = H5G__obj_get_linfo(&(grp->oloc), &linfo)) < 0) |
1325 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5I_INVALID_HID, "unable to read object header"); |
1326 | 0 | if (linfo_exists) { |
1327 | | /* Set the link info for the property list */ |
1328 | 0 | if (H5P_set(new_plist, H5G_CRT_LINK_INFO_NAME, &linfo) < 0) |
1329 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set link info"); |
1330 | 0 | } /* end if */ |
1331 | | |
1332 | | /* Check for the group having a pipeline message */ |
1333 | 0 | if ((pline_exists = H5O_msg_exists(&(grp->oloc), H5O_PLINE_ID)) < 0) |
1334 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, H5I_INVALID_HID, "unable to read object header"); |
1335 | 0 | if (pline_exists) { |
1336 | 0 | H5O_pline_t pline; /* Pipeline message */ |
1337 | | |
1338 | | /* Read the pipeline */ |
1339 | 0 | if (NULL == H5O_msg_read(&(grp->oloc), H5O_PLINE_ID, &pline)) |
1340 | 0 | HGOTO_ERROR(H5E_SYM, H5E_BADMESG, H5I_INVALID_HID, "can't get link pipeline"); |
1341 | | |
1342 | | /* Set the pipeline for the property list */ |
1343 | 0 | if (H5P_poke(new_plist, H5O_CRT_PIPELINE_NAME, &pline) < 0) |
1344 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, H5I_INVALID_HID, "can't set link pipeline"); |
1345 | 0 | } /* end if */ |
1346 | | |
1347 | | /* Set the return value */ |
1348 | 0 | ret_value = new_gcpl_id; |
1349 | |
|
1350 | 0 | done: |
1351 | 0 | if (ret_value < 0) { |
1352 | 0 | if (new_gcpl_id > 0) |
1353 | 0 | if (H5I_dec_app_ref(new_gcpl_id) < 0) |
1354 | 0 | HDONE_ERROR(H5E_SYM, H5E_CANTDEC, H5I_INVALID_HID, "can't free"); |
1355 | 0 | } /* end if */ |
1356 | |
|
1357 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1358 | 0 | } /* end H5G_get_create_plist() */ |
1359 | | |
1360 | | /*------------------------------------------------------------------------- |
1361 | | * Function: H5G__get_info_by_name |
1362 | | * |
1363 | | * Purpose: Internal routine to retrieve the info for a group, by name. |
1364 | | * |
1365 | | * Return: SUCCEED/FAIL |
1366 | | * |
1367 | | *------------------------------------------------------------------------- |
1368 | | */ |
1369 | | herr_t |
1370 | | H5G__get_info_by_name(const H5G_loc_t *loc, const char *name, H5G_info_t *grp_info) |
1371 | 0 | { |
1372 | 0 | H5G_loc_t grp_loc; /* Location used to open group */ |
1373 | 0 | H5G_name_t grp_path; /* Opened object group hier. path */ |
1374 | 0 | H5O_loc_t grp_oloc; /* Opened object object location */ |
1375 | 0 | bool loc_found = false; /* Location at 'name' found */ |
1376 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
1377 | |
|
1378 | 0 | FUNC_ENTER_PACKAGE |
1379 | | |
1380 | | /* Check arguments */ |
1381 | 0 | assert(loc); |
1382 | 0 | assert(grp_info); |
1383 | | |
1384 | | /* Set up opened group location to fill in */ |
1385 | 0 | grp_loc.oloc = &grp_oloc; |
1386 | 0 | grp_loc.path = &grp_path; |
1387 | 0 | H5G_loc_reset(&grp_loc); |
1388 | | |
1389 | | /* Find the group object */ |
1390 | 0 | if (H5G_loc_find(loc, name, &grp_loc /*out*/) < 0) |
1391 | 0 | HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found"); |
1392 | 0 | loc_found = true; |
1393 | | |
1394 | | /* Retrieve the group's information */ |
1395 | 0 | if (H5G__obj_info(grp_loc.oloc, grp_info /*out*/) < 0) |
1396 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve group info"); |
1397 | | |
1398 | 0 | done: |
1399 | | /* Clean up */ |
1400 | 0 | if (loc_found && H5G_loc_free(&grp_loc) < 0) |
1401 | 0 | HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't free location"); |
1402 | |
|
1403 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1404 | 0 | } /* end H5G__get_info_by_name() */ |
1405 | | |
1406 | | /*------------------------------------------------------------------------- |
1407 | | * Function: H5G__get_info_by_idx |
1408 | | * |
1409 | | * Purpose: Internal routine to retrieve the info for a group, by index. |
1410 | | * |
1411 | | * Return: SUCCEED/FAIL |
1412 | | * |
1413 | | *------------------------------------------------------------------------- |
1414 | | */ |
1415 | | herr_t |
1416 | | H5G__get_info_by_idx(const H5G_loc_t *loc, const char *group_name, H5_index_t idx_type, H5_iter_order_t order, |
1417 | | hsize_t n, H5G_info_t *grp_info) |
1418 | 0 | { |
1419 | 0 | H5G_loc_t grp_loc; /* Location used to open group */ |
1420 | 0 | H5G_name_t grp_path; /* Opened object group hier. path */ |
1421 | 0 | H5O_loc_t grp_oloc; /* Opened object object location */ |
1422 | 0 | bool loc_found = false; /* Location at 'name' found */ |
1423 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
1424 | |
|
1425 | 0 | FUNC_ENTER_PACKAGE |
1426 | | |
1427 | | /* Check arguments */ |
1428 | 0 | assert(loc); |
1429 | 0 | assert(grp_info); |
1430 | | |
1431 | | /* Set up opened group location to fill in */ |
1432 | 0 | grp_loc.oloc = &grp_oloc; |
1433 | 0 | grp_loc.path = &grp_path; |
1434 | 0 | H5G_loc_reset(&grp_loc); |
1435 | | |
1436 | | /* Find the object's location, according to the order in the index */ |
1437 | 0 | if (H5G_loc_find_by_idx(loc, group_name, idx_type, order, n, &grp_loc /*out*/) < 0) |
1438 | 0 | HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "group not found"); |
1439 | 0 | loc_found = true; |
1440 | | |
1441 | | /* Retrieve the group's information */ |
1442 | 0 | if (H5G__obj_info(grp_loc.oloc, grp_info /*out*/) < 0) |
1443 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve group info"); |
1444 | | |
1445 | 0 | done: |
1446 | | /* Clean up */ |
1447 | 0 | if (loc_found && H5G_loc_free(&grp_loc) < 0) |
1448 | 0 | HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't free location"); |
1449 | |
|
1450 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1451 | 0 | } /* end H5G__get_info_by_idx() */ |
1452 | | |
1453 | | /*------------------------------------------------------------------------- |
1454 | | * Function: H5G_get_gcpl_id |
1455 | | * |
1456 | | * Purpose: Quick and dirty routine to retrieve the |
1457 | | * gcpl_id (group creation property list) from the |
1458 | | * group creation operation struct |
1459 | | * |
1460 | | * Return: 'gcpl_id' on success/abort on failure (shouldn't fail) |
1461 | | *------------------------------------------------------------------------- |
1462 | | */ |
1463 | | hid_t |
1464 | | H5G_get_gcpl_id(const H5G_obj_create_t *g) |
1465 | 0 | { |
1466 | | /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */ |
1467 | 0 | FUNC_ENTER_NOAPI_NOINIT_NOERR |
1468 | |
|
1469 | 0 | assert(g); |
1470 | |
|
1471 | 0 | FUNC_LEAVE_NOAPI(g->gcpl_id); |
1472 | 0 | } /* end H5G_get_gcpl_id() */ |