Line | Count | Source |
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: H5Glink.c |
16 | | * |
17 | | * Purpose: Functions for handling links in 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 "H5Gpkg.h" /* Groups */ |
34 | | #include "H5HLprivate.h" /* Local Heaps */ |
35 | | #include "H5Iprivate.h" /* IDs */ |
36 | | #include "H5Lprivate.h" /* Links */ |
37 | | #include "H5MMprivate.h" /* Memory management */ |
38 | | |
39 | | #include "H5VLnative_private.h" /* Native VOL connector */ |
40 | | |
41 | | /****************/ |
42 | | /* Local Macros */ |
43 | | /****************/ |
44 | | |
45 | | /******************/ |
46 | | /* Local Typedefs */ |
47 | | /******************/ |
48 | | |
49 | | /********************/ |
50 | | /* Package Typedefs */ |
51 | | /********************/ |
52 | | |
53 | | /********************/ |
54 | | /* Local Prototypes */ |
55 | | /********************/ |
56 | | |
57 | | static int H5G__link_cmp_name_inc(const void *lnk1, const void *lnk2); |
58 | | static int H5G__link_cmp_name_dec(const void *lnk1, const void *lnk2); |
59 | | static int H5G__link_cmp_corder_inc(const void *lnk1, const void *lnk2); |
60 | | static int H5G__link_cmp_corder_dec(const void *lnk1, const void *lnk2); |
61 | | |
62 | | /*********************/ |
63 | | /* Package Variables */ |
64 | | /*********************/ |
65 | | |
66 | | /*****************************/ |
67 | | /* Library Private Variables */ |
68 | | /*****************************/ |
69 | | |
70 | | /*******************/ |
71 | | /* Local Variables */ |
72 | | /*******************/ |
73 | | |
74 | | /*------------------------------------------------------------------------- |
75 | | * Function: H5G__link_cmp_name_inc |
76 | | * |
77 | | * Purpose: Callback routine for comparing two link names, in |
78 | | * increasing alphabetic order |
79 | | * |
80 | | * Return: An integer less than, equal to, or greater than zero if the |
81 | | * first argument is considered to be respectively less than, |
82 | | * equal to, or greater than the second. If two members compare |
83 | | * as equal, their order in the sorted array is undefined. |
84 | | * (i.e. same as strcmp()) |
85 | | * |
86 | | *------------------------------------------------------------------------- |
87 | | */ |
88 | | static int |
89 | | H5G__link_cmp_name_inc(const void *lnk1, const void *lnk2) |
90 | 0 | { |
91 | 0 | FUNC_ENTER_PACKAGE_NOERR |
92 | |
|
93 | 0 | FUNC_LEAVE_NOAPI(strcmp(((const H5O_link_t *)lnk1)->name, ((const H5O_link_t *)lnk2)->name)) |
94 | 0 | } /* end H5G__link_cmp_name_inc() */ |
95 | | |
96 | | /*------------------------------------------------------------------------- |
97 | | * Function: H5G__link_cmp_name_dec |
98 | | * |
99 | | * Purpose: Callback routine for comparing two link names, in |
100 | | * decreasing alphabetic order |
101 | | * |
102 | | * Return: An integer less than, equal to, or greater than zero if the |
103 | | * second argument is considered to be respectively less than, |
104 | | * equal to, or greater than the first. If two members compare |
105 | | * as equal, their order in the sorted array is undefined. |
106 | | * (i.e. opposite strcmp()) |
107 | | * |
108 | | *------------------------------------------------------------------------- |
109 | | */ |
110 | | static int |
111 | | H5G__link_cmp_name_dec(const void *lnk1, const void *lnk2) |
112 | 0 | { |
113 | 0 | FUNC_ENTER_PACKAGE_NOERR |
114 | |
|
115 | 0 | FUNC_LEAVE_NOAPI(strcmp(((const H5O_link_t *)lnk2)->name, ((const H5O_link_t *)lnk1)->name)) |
116 | 0 | } /* end H5G__link_cmp_name_dec() */ |
117 | | |
118 | | /*------------------------------------------------------------------------- |
119 | | * Function: H5G__link_cmp_corder_inc |
120 | | * |
121 | | * Purpose: Callback routine for comparing two link creation orders, in |
122 | | * increasing order |
123 | | * |
124 | | * Return: An integer less than, equal to, or greater than zero if the |
125 | | * first argument is considered to be respectively less than, |
126 | | * equal to, or greater than the second. If two members compare |
127 | | * as equal, their order in the sorted array is undefined. |
128 | | * |
129 | | *------------------------------------------------------------------------- |
130 | | */ |
131 | | static int |
132 | | H5G__link_cmp_corder_inc(const void *lnk1, const void *lnk2) |
133 | 0 | { |
134 | 0 | int ret_value = -1; /* Return value */ |
135 | |
|
136 | 0 | FUNC_ENTER_PACKAGE_NOERR |
137 | |
|
138 | 0 | if (((const H5O_link_t *)lnk1)->corder < ((const H5O_link_t *)lnk2)->corder) |
139 | 0 | ret_value = -1; |
140 | 0 | else if (((const H5O_link_t *)lnk1)->corder > ((const H5O_link_t *)lnk2)->corder) |
141 | 0 | ret_value = 1; |
142 | 0 | else |
143 | 0 | ret_value = 0; |
144 | |
|
145 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
146 | 0 | } /* end H5G__link_cmp_corder_inc() */ |
147 | | |
148 | | /*------------------------------------------------------------------------- |
149 | | * Function: H5G__link_cmp_corder_dec |
150 | | * |
151 | | * Purpose: Callback routine for comparing two link creation orders, in |
152 | | * decreasing order |
153 | | * |
154 | | * Return: An integer less than, equal to, or greater than zero if the |
155 | | * second argument is considered to be respectively less than, |
156 | | * equal to, or greater than the first. If two members compare |
157 | | * as equal, their order in the sorted array is undefined. |
158 | | * |
159 | | *------------------------------------------------------------------------- |
160 | | */ |
161 | | static int |
162 | | H5G__link_cmp_corder_dec(const void *lnk1, const void *lnk2) |
163 | 0 | { |
164 | 0 | int ret_value = -1; /* Return value */ |
165 | |
|
166 | 0 | FUNC_ENTER_PACKAGE_NOERR |
167 | |
|
168 | 0 | if (((const H5O_link_t *)lnk1)->corder < ((const H5O_link_t *)lnk2)->corder) |
169 | 0 | ret_value = 1; |
170 | 0 | else if (((const H5O_link_t *)lnk1)->corder > ((const H5O_link_t *)lnk2)->corder) |
171 | 0 | ret_value = -1; |
172 | 0 | else |
173 | 0 | ret_value = 0; |
174 | |
|
175 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
176 | 0 | } /* end H5G__link_cmp_corder_dec() */ |
177 | | |
178 | | /*------------------------------------------------------------------------- |
179 | | * Function: H5G_link_to_info |
180 | | * |
181 | | * Purpose: Retrieve information from a link object |
182 | | * |
183 | | * Return: Non-negative on success/Negative on failure |
184 | | * |
185 | | *------------------------------------------------------------------------- |
186 | | */ |
187 | | herr_t |
188 | | H5G_link_to_info(const H5O_loc_t *link_loc, const H5O_link_t *lnk, H5L_info2_t *info) |
189 | 15.4k | { |
190 | 15.4k | herr_t ret_value = SUCCEED; /* Return value */ |
191 | | |
192 | 15.4k | FUNC_ENTER_NOAPI(FAIL) |
193 | | |
194 | | /* Sanity check */ |
195 | 15.4k | assert(link_loc); |
196 | 15.4k | assert(lnk); |
197 | | |
198 | | /* Get information from the link */ |
199 | 15.4k | if (info) { |
200 | 15.4k | info->cset = lnk->cset; |
201 | 15.4k | info->corder = lnk->corder; |
202 | 15.4k | info->corder_valid = lnk->corder_valid; |
203 | 15.4k | info->type = lnk->type; |
204 | | |
205 | 15.4k | switch (lnk->type) { |
206 | 15.4k | case H5L_TYPE_HARD: |
207 | | /* Serialize the address into a VOL token */ |
208 | 15.4k | if (H5VL_native_addr_to_token(link_loc->file, H5I_FILE, lnk->u.hard.addr, &info->u.token) < 0) |
209 | 0 | HGOTO_ERROR(H5E_LINK, H5E_CANTSERIALIZE, FAIL, |
210 | 15.4k | "can't serialize address into object token"); |
211 | 15.4k | break; |
212 | | |
213 | 15.4k | case H5L_TYPE_SOFT: |
214 | 0 | info->u.val_size = strlen(lnk->u.soft.name) + 1; /*count the null terminator*/ |
215 | 0 | break; |
216 | | |
217 | 0 | case H5L_TYPE_ERROR: |
218 | 0 | case H5L_TYPE_EXTERNAL: |
219 | 0 | case H5L_TYPE_MAX: |
220 | 0 | default: { |
221 | 0 | const H5L_class_t *link_class; /* User-defined link class */ |
222 | |
|
223 | 0 | if (lnk->type < H5L_TYPE_UD_MIN || lnk->type > H5L_TYPE_MAX) |
224 | 0 | HGOTO_ERROR(H5E_LINK, H5E_BADTYPE, FAIL, "unknown link class"); |
225 | | |
226 | | /* User-defined link; call its query function to get the link udata size. */ |
227 | | /* Get the link class for this type of link. It's okay if the class |
228 | | * isn't registered, though--we just can't give any more information |
229 | | * about it |
230 | | */ |
231 | 0 | link_class = H5L_find_class(lnk->type); |
232 | |
|
233 | 0 | if (link_class != NULL && link_class->query_func != NULL) { |
234 | 0 | ssize_t cb_ret; /* Return value from UD callback */ |
235 | | |
236 | | /* Prepare & restore library for user callback */ |
237 | 0 | H5_BEFORE_USER_CB(FAIL) |
238 | 0 | { |
239 | | /* Call the link's query routine to retrieve the user-defined link's value size */ |
240 | | /* (in case the query routine packs/unpacks the link value in some way that |
241 | | * changes its size) */ |
242 | 0 | cb_ret = (link_class->query_func)(lnk->name, lnk->u.ud.udata, lnk->u.ud.size, |
243 | 0 | NULL, (size_t)0); |
244 | 0 | } |
245 | 0 | H5_AFTER_USER_CB(FAIL) |
246 | 0 | if (cb_ret < 0) |
247 | 0 | HGOTO_ERROR(H5E_LINK, H5E_CALLBACK, FAIL, |
248 | 0 | "query buffer size callback returned failure"); |
249 | | |
250 | 0 | info->u.val_size = (size_t)cb_ret; |
251 | 0 | } /* end if */ |
252 | 0 | else |
253 | 0 | info->u.val_size = 0; |
254 | 0 | } /* end case */ |
255 | 15.4k | } /* end switch */ |
256 | 15.4k | } /* end if */ |
257 | | |
258 | 15.4k | done: |
259 | 15.4k | FUNC_LEAVE_NOAPI(ret_value) |
260 | 15.4k | } /* end H5G_link_to_info() */ |
261 | | |
262 | | /*------------------------------------------------------------------------- |
263 | | * Function: H5G__link_to_ent |
264 | | * |
265 | | * Purpose: Convert a link to a symbol table entry |
266 | | * |
267 | | * Return: Success: Non-negative |
268 | | * Failure: Negative |
269 | | * |
270 | | *------------------------------------------------------------------------- |
271 | | */ |
272 | | herr_t |
273 | | H5G__link_to_ent(H5F_t *f, H5HL_t *heap, const H5O_link_t *lnk, H5O_type_t obj_type, const void *crt_info, |
274 | | H5G_entry_t *ent) |
275 | 0 | { |
276 | 0 | size_t name_offset; /* Offset of name in heap */ |
277 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
278 | |
|
279 | 0 | FUNC_ENTER_PACKAGE |
280 | | |
281 | | /* check arguments */ |
282 | 0 | assert(f); |
283 | 0 | assert(heap); |
284 | 0 | assert(lnk && lnk->name); |
285 | | |
286 | | /* Reset the new entry */ |
287 | 0 | H5G__ent_reset(ent); |
288 | | |
289 | | /* Add the new name to the heap */ |
290 | 0 | if (H5HL_insert(f, heap, strlen(lnk->name) + 1, lnk->name, &name_offset) < 0) |
291 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert symbol name into heap"); |
292 | 0 | ent->name_off = name_offset; |
293 | | |
294 | | /* Build correct information for symbol table entry based on link type */ |
295 | 0 | switch (lnk->type) { |
296 | 0 | case H5L_TYPE_HARD: |
297 | 0 | if (obj_type == H5O_TYPE_GROUP) { |
298 | 0 | const H5G_obj_create_t *gcrt_info = (const H5G_obj_create_t *)crt_info; |
299 | |
|
300 | 0 | ent->type = gcrt_info->cache_type; |
301 | 0 | if (ent->type != H5G_NOTHING_CACHED) |
302 | 0 | ent->cache = gcrt_info->cache; |
303 | | #ifndef NDEBUG |
304 | | else { |
305 | | /* Make sure there is no stab message in the target object |
306 | | */ |
307 | | H5O_loc_t targ_oloc; /* Location of link target */ |
308 | | htri_t stab_exists; /* Whether the target symbol table exists */ |
309 | | |
310 | | /* Build target object location */ |
311 | | if (H5O_loc_reset(&targ_oloc) < 0) |
312 | | HGOTO_ERROR(H5E_SYM, H5E_CANTRESET, FAIL, "unable to initialize target location"); |
313 | | targ_oloc.file = f; |
314 | | targ_oloc.addr = lnk->u.hard.addr; |
315 | | |
316 | | /* Check if a symbol table message exists */ |
317 | | if ((stab_exists = H5O_msg_exists(&targ_oloc, H5O_STAB_ID)) < 0) |
318 | | HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to check for STAB message"); |
319 | | |
320 | | assert(!stab_exists); |
321 | | } /* end else */ |
322 | | #endif /* NDEBUG */ |
323 | 0 | } /* end if */ |
324 | 0 | else if (obj_type == H5O_TYPE_UNKNOWN) { |
325 | | /* Try to retrieve symbol table information for caching */ |
326 | 0 | H5O_loc_t targ_oloc; /* Location of link target */ |
327 | 0 | H5O_t *oh; /* Link target object header */ |
328 | 0 | H5O_stab_t stab; /* Link target symbol table */ |
329 | 0 | htri_t stab_exists; /* Whether the target symbol table exists */ |
330 | | |
331 | | /* Build target object location */ |
332 | 0 | if (H5O_loc_reset(&targ_oloc) < 0) |
333 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTRESET, FAIL, "unable to initialize target location"); |
334 | 0 | targ_oloc.file = f; |
335 | 0 | targ_oloc.addr = lnk->u.hard.addr; |
336 | | |
337 | | /* Get the object header */ |
338 | 0 | if (NULL == (oh = H5O_protect(&targ_oloc, H5AC__READ_ONLY_FLAG, false))) |
339 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTPROTECT, FAIL, "unable to protect target object header"); |
340 | | |
341 | | /* Check if a symbol table message exists */ |
342 | 0 | if ((stab_exists = H5O_msg_exists_oh(oh, H5O_STAB_ID)) < 0) { |
343 | 0 | if (H5O_unprotect(&targ_oloc, oh, H5AC__NO_FLAGS_SET) < 0) |
344 | 0 | HERROR(H5E_SYM, H5E_CANTUNPROTECT, "unable to release object header"); |
345 | 0 | HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to check for STAB message"); |
346 | 0 | } /* end if */ |
347 | | |
348 | 0 | if (stab_exists) { |
349 | | /* Read symbol table message */ |
350 | 0 | if (NULL == H5O_msg_read_oh(f, oh, H5O_STAB_ID, &stab)) { |
351 | 0 | if (H5O_unprotect(&targ_oloc, oh, H5AC__NO_FLAGS_SET) < 0) |
352 | 0 | HERROR(H5E_SYM, H5E_CANTUNPROTECT, "unable to release object header"); |
353 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to read STAB message"); |
354 | 0 | } /* end if */ |
355 | | |
356 | | /* Cache symbol table message */ |
357 | 0 | ent->type = H5G_CACHED_STAB; |
358 | 0 | ent->cache.stab.btree_addr = stab.btree_addr; |
359 | 0 | ent->cache.stab.heap_addr = stab.heap_addr; |
360 | 0 | } /* end if */ |
361 | 0 | else |
362 | | /* No symbol table message, don't cache anything */ |
363 | 0 | ent->type = H5G_NOTHING_CACHED; |
364 | | |
365 | 0 | if (H5O_unprotect(&targ_oloc, oh, H5AC__NO_FLAGS_SET) < 0) |
366 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTUNPROTECT, FAIL, "unable to release object header"); |
367 | 0 | } /* end else */ |
368 | 0 | else |
369 | 0 | ent->type = H5G_NOTHING_CACHED; |
370 | | |
371 | 0 | ent->header = lnk->u.hard.addr; |
372 | 0 | break; |
373 | | |
374 | 0 | case H5L_TYPE_SOFT: { |
375 | 0 | size_t lnk_offset; /* Offset to sym-link value */ |
376 | | |
377 | | /* Insert link value into local heap */ |
378 | 0 | if (H5HL_insert(f, heap, strlen(lnk->u.soft.name) + 1, lnk->u.soft.name, &lnk_offset) < 0) |
379 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to write link value to local heap"); |
380 | | |
381 | 0 | ent->type = H5G_CACHED_SLINK; |
382 | 0 | ent->cache.slink.lval_offset = lnk_offset; |
383 | 0 | } break; |
384 | | |
385 | 0 | case H5L_TYPE_ERROR: |
386 | 0 | case H5L_TYPE_EXTERNAL: |
387 | 0 | case H5L_TYPE_MAX: |
388 | 0 | default: |
389 | 0 | HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unrecognized link type"); |
390 | 0 | } /* end switch */ |
391 | | |
392 | 0 | done: |
393 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
394 | 0 | } /* end H5G__link_to_ent() */ |
395 | | |
396 | | /*------------------------------------------------------------------------- |
397 | | * Function: H5G__link_to_loc |
398 | | * |
399 | | * Purpose: Build group location from group and link object |
400 | | * |
401 | | * Return: Non-negative on success/Negative on failure |
402 | | * |
403 | | *------------------------------------------------------------------------- |
404 | | */ |
405 | | herr_t |
406 | | H5G__link_to_loc(const H5G_loc_t *grp_loc, const H5O_link_t *lnk, H5G_loc_t *obj_loc) |
407 | 11.3k | { |
408 | 11.3k | herr_t ret_value = SUCCEED; /* Return value */ |
409 | | |
410 | 11.3k | FUNC_ENTER_PACKAGE |
411 | | |
412 | | /* Sanity check */ |
413 | 11.3k | assert(grp_loc); |
414 | 11.3k | assert(lnk); |
415 | 11.3k | assert(obj_loc); |
416 | | |
417 | | /* |
418 | | * Build location from the link |
419 | | */ |
420 | | |
421 | | /* Check for unknown library-internal link */ |
422 | 11.3k | if (lnk->type > H5L_TYPE_BUILTIN_MAX && lnk->type < H5L_TYPE_UD_MIN) |
423 | 0 | HGOTO_ERROR(H5E_SYM, H5E_UNSUPPORTED, FAIL, "unknown link type"); |
424 | | |
425 | | /* Build object's group hier. location */ |
426 | 11.3k | if (H5G_name_set(grp_loc->path, obj_loc->path, lnk->name) < 0) |
427 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "cannot set name"); |
428 | | |
429 | | /* Set the object location, if it's a hard link set the address also */ |
430 | 11.3k | obj_loc->oloc->file = grp_loc->oloc->file; |
431 | 11.3k | obj_loc->oloc->holding_file = false; |
432 | 11.3k | if (lnk->type == H5L_TYPE_HARD) |
433 | 11.3k | obj_loc->oloc->addr = lnk->u.hard.addr; |
434 | | |
435 | 11.3k | done: |
436 | 11.3k | FUNC_LEAVE_NOAPI(ret_value) |
437 | 11.3k | } /* end H5G__link_to_loc() */ |
438 | | |
439 | | /*------------------------------------------------------------------------- |
440 | | * Function: H5G__link_sort_table |
441 | | * |
442 | | * Purpose: Sort table containing a list of links for a group |
443 | | * |
444 | | * Return: SUCCEED/FAIL |
445 | | * |
446 | | *------------------------------------------------------------------------- |
447 | | */ |
448 | | herr_t |
449 | | H5G__link_sort_table(H5G_link_table_t *ltable, H5_index_t idx_type, H5_iter_order_t order) |
450 | 0 | { |
451 | 0 | herr_t ret_value = SUCCEED; |
452 | |
|
453 | 0 | FUNC_ENTER_PACKAGE_NOERR |
454 | | |
455 | | /* Sanity check */ |
456 | 0 | assert(ltable); |
457 | | |
458 | | /* Can't sort when empty since the links table will be NULL */ |
459 | 0 | if (0 == ltable->nlinks) |
460 | 0 | HGOTO_DONE(ret_value); |
461 | | |
462 | | /* This should never be NULL if the number of links is non-zero */ |
463 | 0 | assert(ltable->lnks); |
464 | | |
465 | | /* Pick appropriate sorting routine */ |
466 | 0 | if (idx_type == H5_INDEX_NAME) { |
467 | 0 | if (order == H5_ITER_INC) |
468 | 0 | qsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G__link_cmp_name_inc); |
469 | 0 | else if (order == H5_ITER_DEC) |
470 | 0 | qsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G__link_cmp_name_dec); |
471 | 0 | else |
472 | 0 | assert(order == H5_ITER_NATIVE); |
473 | 0 | } /* end if */ |
474 | 0 | else { |
475 | 0 | assert(idx_type == H5_INDEX_CRT_ORDER); |
476 | 0 | if (order == H5_ITER_INC) |
477 | 0 | qsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G__link_cmp_corder_inc); |
478 | 0 | else if (order == H5_ITER_DEC) |
479 | 0 | qsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G__link_cmp_corder_dec); |
480 | 0 | else |
481 | 0 | assert(order == H5_ITER_NATIVE); |
482 | 0 | } /* end else */ |
483 | |
|
484 | 0 | done: |
485 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
486 | 0 | } /* end H5G__link_sort_table() */ |
487 | | |
488 | | /*------------------------------------------------------------------------- |
489 | | * Function: H5G__link_iterate_table |
490 | | * |
491 | | * Purpose: Iterate over table containing a list of links for a group, |
492 | | * making appropriate callbacks |
493 | | * |
494 | | * Return: Success: Non-negative |
495 | | * Failure: Negative |
496 | | * |
497 | | *------------------------------------------------------------------------- |
498 | | */ |
499 | | herr_t |
500 | | H5G__link_iterate_table(const H5G_link_table_t *ltable, hsize_t skip, hsize_t *last_lnk, |
501 | | const H5G_lib_iterate_t op, void *op_data) |
502 | 0 | { |
503 | 0 | size_t u; /* Local index variable */ |
504 | 0 | herr_t ret_value = H5_ITER_CONT; /* Return value */ |
505 | |
|
506 | 0 | FUNC_ENTER_PACKAGE_NOERR |
507 | | |
508 | | /* Sanity check */ |
509 | 0 | assert(ltable); |
510 | 0 | assert(op); |
511 | | |
512 | | /* Skip over links, if requested */ |
513 | 0 | if (last_lnk) |
514 | 0 | *last_lnk += skip; |
515 | | |
516 | | /* Iterate over link messages */ |
517 | 0 | H5_CHECKED_ASSIGN(u, size_t, skip, hsize_t); |
518 | 0 | for (; u < ltable->nlinks && !ret_value; u++) { |
519 | | /* Make the callback */ |
520 | 0 | ret_value = (op)(&(ltable->lnks[u]), op_data); |
521 | | |
522 | | /* Increment the number of entries passed through */ |
523 | 0 | if (last_lnk) |
524 | 0 | (*last_lnk)++; |
525 | 0 | } /* end for */ |
526 | | |
527 | | /* Check for callback failure and pass along return value */ |
528 | 0 | if (ret_value < 0) |
529 | 0 | HERROR(H5E_SYM, H5E_CANTNEXT, "iteration operator failed"); |
530 | |
|
531 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
532 | 0 | } /* end H5G__link_iterate_table() */ |
533 | | |
534 | | /*------------------------------------------------------------------------- |
535 | | * Function: H5G__link_release_table |
536 | | * |
537 | | * Purpose: Release table containing a list of links for a group |
538 | | * |
539 | | * Return: Success: Non-negative |
540 | | * Failure: Negative |
541 | | * |
542 | | *------------------------------------------------------------------------- |
543 | | */ |
544 | | herr_t |
545 | | H5G__link_release_table(H5G_link_table_t *ltable) |
546 | 0 | { |
547 | 0 | size_t u; /* Local index variable */ |
548 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
549 | |
|
550 | 0 | FUNC_ENTER_PACKAGE |
551 | | |
552 | | /* Sanity check */ |
553 | 0 | assert(ltable); |
554 | | |
555 | | /* Release link info, if any */ |
556 | 0 | if (ltable->nlinks > 0) { |
557 | | /* Free link message information */ |
558 | 0 | for (u = 0; u < ltable->nlinks; u++) |
559 | 0 | if (H5O_msg_reset(H5O_LINK_ID, &(ltable->lnks[u])) < 0) |
560 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link message"); |
561 | | |
562 | | /* Free table of links */ |
563 | 0 | H5MM_xfree(ltable->lnks); |
564 | 0 | } /* end if */ |
565 | 0 | else |
566 | 0 | assert(ltable->lnks == NULL); |
567 | | |
568 | 0 | done: |
569 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
570 | 0 | } /* end H5G__link_release_table() */ |
571 | | |
572 | | /*------------------------------------------------------------------------- |
573 | | * Function: H5G__link_name_replace |
574 | | * |
575 | | * Purpose: Determine the type of object referred to (for hard links) or |
576 | | * the link type (for soft links and user-defined links). |
577 | | * |
578 | | * Return: Non-negative on success/Negative on failure |
579 | | * |
580 | | *------------------------------------------------------------------------- |
581 | | */ |
582 | | herr_t |
583 | | H5G__link_name_replace(H5F_t *file, H5RS_str_t *grp_full_path_r, const H5O_link_t *lnk) |
584 | 0 | { |
585 | 0 | H5RS_str_t *obj_path_r = NULL; /* Full path for link being removed */ |
586 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
587 | |
|
588 | 0 | FUNC_ENTER_PACKAGE |
589 | | |
590 | | /* check arguments */ |
591 | 0 | assert(file); |
592 | | |
593 | | /* Search the open IDs and replace names for unlinked object */ |
594 | 0 | if (grp_full_path_r) { |
595 | 0 | obj_path_r = H5G_build_fullpath_refstr_str(grp_full_path_r, lnk->name); |
596 | 0 | if (H5G_name_replace(lnk, H5G_NAME_DELETE, file, obj_path_r, NULL, NULL) < 0) |
597 | 0 | HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to replace name"); |
598 | 0 | } |
599 | | |
600 | 0 | done: |
601 | 0 | if (obj_path_r) |
602 | 0 | H5RS_decr(obj_path_r); |
603 | |
|
604 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
605 | 0 | } /* end H5G__link_name_replace() */ |