diff options
Diffstat (limited to 'src/H5Glink.c')
-rw-r--r-- | src/H5Glink.c | 351 |
1 files changed, 187 insertions, 164 deletions
diff --git a/src/H5Glink.c b/src/H5Glink.c index 018088e..ab9fdce 100644 --- a/src/H5Glink.c +++ b/src/H5Glink.c @@ -33,15 +33,8 @@ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ -#ifdef H5_GROUP_REVISION /* Private typedefs */ -/* Data structure to hold table of links for a group */ -typedef struct { - size_t nlinks; /* # of links in table */ - H5O_link_t *lnks; /* Pointer to array of links */ -} H5G_link_table_t; - /* User data for link message iteration when building link table */ typedef struct { H5G_link_table_t *ltable; /* Pointer to link table to build */ @@ -93,37 +86,9 @@ typedef struct { /* Private macros */ /* PRIVATE PROTOTYPES */ -static int H5G_link_cmp_name(const void *lnk1, const void *lnk2); static herr_t H5G_link_build_table_cb(const void *_mesg, unsigned idx, void *_udata); static herr_t H5G_link_build_table(H5O_loc_t *oloc, hid_t dxpl_id, - H5G_link_table_t *ltable); -static herr_t H5G_link_release_table(H5G_link_table_t *ltable); - - -/*------------------------------------------------------------------------- - * Function: H5G_link_cmp_name - * - * Purpose: Callback routine for comparing two link messages. - * - * Return: An integer less than, equal to, or greater than zero if the - * first argument is considered to be respectively less than, - * equal to, or greater than the second. If two members compare - * as equal, their order in the sorted array is undefined. - * (i.e. same as strcmp()) - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Sep 5 2005 - * - *------------------------------------------------------------------------- - */ -static int -H5G_link_cmp_name(const void *lnk1, const void *lnk2) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_link_cmp_name) - - FUNC_LEAVE_NOAPI(HDstrcmp(((const H5O_link_t *)lnk1)->name, ((const H5O_link_t *)lnk2)->name)) -} /* end H5G_link_cmp_name() */ + const H5O_linfo_t *linfo, H5_iter_order_t order, H5G_link_table_t *ltable); /*------------------------------------------------------------------------- @@ -181,23 +146,21 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5G_link_build_table(H5O_loc_t *oloc, hid_t dxpl_id, H5G_link_table_t *ltable) +H5G_link_build_table(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, + H5_iter_order_t order, H5G_link_table_t *ltable) { - H5O_linfo_t linfo; /* Link info message */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5G_link_build_table) /* Sanity check */ HDassert(oloc); - - /* Retrieve the link info */ - if(NULL == H5O_read(oloc, H5O_LINFO_ID, 0, &linfo, dxpl_id)) - HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info") + HDassert(linfo); + HDassert(ltable); /* Set size of table */ - H5_CHECK_OVERFLOW(linfo.nlinks, hsize_t, size_t); - ltable->nlinks = (size_t)linfo.nlinks; + H5_CHECK_OVERFLOW(linfo->nlinks, hsize_t, size_t); + ltable->nlinks = (size_t)linfo->nlinks; /* Allocate space for the table entries */ if(ltable->nlinks > 0) { @@ -214,8 +177,14 @@ H5G_link_build_table(H5O_loc_t *oloc, hid_t dxpl_id, H5G_link_table_t *ltable) if(H5O_iterate(oloc, H5O_LINK_ID, H5G_link_build_table_cb, &udata, dxpl_id) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "error iterating over link messages") - /* Sort link table (XXX: alphabetically, for now) */ - HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_link_cmp_name); + /* Sort link table in correct iteration order */ + /* (XXX: by name, currently) */ + if(order == H5_ITER_INC) + HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_obj_cmp_name_inc); + else if(order == H5_ITER_INC) + HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_obj_cmp_name_dec); + else + HDassert(order == H5_ITER_NATIVE); } /* end if */ else ltable->lnks = NULL; @@ -226,133 +195,186 @@ done: /*------------------------------------------------------------------------- - * Function: H5G_link_release_table + * Function: H5G_link_convert * - * Purpose: Release table containing a list of links for a group + * Purpose: Convert a symbol table entry to a link * - * Return: Success: Non-negative - * Failure: Negative + * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * Sep 6, 2005 + * koziol@hdfgroup.org + * Sep 16 2006 * *------------------------------------------------------------------------- */ -static herr_t -H5G_link_release_table(H5G_link_table_t *ltable) +herr_t +H5G_link_convert(H5F_t *f, hid_t dxpl_id, H5O_link_t *lnk, haddr_t lheap_addr, + const H5G_entry_t *ent, const char *name) { - size_t u; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5G_link_release_table) + FUNC_ENTER_NOAPI(H5G_link_convert, FAIL) - /* Sanity check */ - HDassert(ltable); + /* check arguments */ + HDassert(f); + HDassert(lnk); + HDassert(ent); - /* Release link info, if any */ - if(ltable->nlinks > 0) { - /* Free link message information */ - for(u = 0; u < ltable->nlinks; u++) - if(H5O_reset(H5O_LINK_ID, &(ltable->lnks[u])) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link message") + /* Set (default) common info for link */ + lnk->cset = H5F_CRT_DEFAULT_CSET; + lnk->corder = 0; + lnk->corder_valid = FALSE; /* Creation order not valid for this link */ + lnk->name = H5MM_xstrdup(name); - /* Free table of links */ - H5MM_xfree(ltable->lnks); - } /* end if */ - else - HDassert(ltable->lnks == NULL); + /* Object is a symbolic or hard link */ + switch(ent->type) { + case H5G_CACHED_SLINK: + { + const char *s; /* Pointer to link value */ + const H5HL_t *heap; /* Pointer to local heap for group */ + + /* Lock the local heap */ + if(NULL == (heap = H5HL_protect(f, dxpl_id, lheap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read protect link value") + + s = H5HL_offset_into(f, heap, ent->cache.slink.lval_offset); + + /* Copy the link value */ + lnk->u.soft.name = H5MM_xstrdup(s); + + /* Release the local heap */ + if(H5HL_unprotect(f, dxpl_id, heap, lheap_addr, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to read unprotect link value") + + /* Set link type */ + lnk->type = H5L_TYPE_SOFT; + } + break; + + default: + /* Set address of object */ + lnk->u.hard.addr = ent->header; + + /* Set link type */ + lnk->type = H5L_TYPE_HARD; + break; + } /* end switch */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_link_release_table() */ +} /* end H5G_link_convert() */ /*------------------------------------------------------------------------- - * Function: H5G_link_convert + * Function: H5G_link_copy_file * - * Purpose: Converts a group entry into a link object. + * Purpose: Copy a link and the object it points to from one file to + * another. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Sep 5 2005 + * koziol@hdfgroup.org + * Sep 29 2006 * *------------------------------------------------------------------------- */ herr_t -H5G_link_convert(H5O_link_t *lnk, const H5G_entry_t *ent, const H5HL_t *heap, - const char *name) +H5G_link_copy_file(H5F_t *dst_file, hid_t dxpl_id, const H5O_link_t *_src_lnk, + const H5O_loc_t *src_oloc, H5O_link_t *dst_lnk, H5O_copy_t *cpy_info) { + H5O_link_t tmp_src_lnk; /* Temporary copy of src link, when needed */ + const H5O_link_t *src_lnk = _src_lnk; /* Source link */ + hbool_t dst_lnk_init = FALSE; /* Whether the destination link is initialized */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5G_link_convert, FAIL) + FUNC_ENTER_NOAPI(H5G_link_copy_file, FAIL) - /* Check arguments. */ - HDassert(lnk); - HDassert(ent); - HDassert(name); + /* check arguments */ + HDassert(dst_file); + HDassert(src_lnk); + HDassert(dst_lnk); + HDassert(cpy_info); + + /* Expand soft link */ + if(H5L_TYPE_SOFT == src_lnk->type && cpy_info->expand_soft_link) { + H5G_stat_t statbuf; /* Information about object pointed to by soft link */ + H5G_loc_t grp_loc; /* Group location holding soft link */ + H5G_name_t grp_path; /* Path for group holding soft link */ + + /* Make a temporary copy, so that it will not change the info in the cache */ + if(NULL == H5O_copy(H5O_LINK_ID, src_lnk, &tmp_src_lnk)) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, H5B2_ITER_ERROR, "unable to copy message") + + /* Set up group location for soft link to start in */ + H5G_name_reset(&grp_path); + grp_loc.path = &grp_path; + grp_loc.oloc = (H5O_loc_t *)src_oloc; /* Casting away const OK -QAK */ + + /* Check if the object pointed by the soft link exists in the source file */ + /* (It would be more efficient to make a specialized traversal callback, + * but this is good enough for now... -QAK) + */ + if(H5G_get_objinfo(&grp_loc, tmp_src_lnk.u.soft.name, TRUE, &statbuf, dxpl_id) >= 0) { + /* Convert soft link to hard link */ + tmp_src_lnk.u.soft.name = H5MM_xfree(tmp_src_lnk.u.soft.name); + tmp_src_lnk.type = H5L_TYPE_HARD; +#if H5_SIZEOF_UINT64_T > H5_SIZEOF_LONG + tmp_src_lnk.u.hard.addr = (((haddr_t)statbuf.objno[1]) << (8 * sizeof(long))) | (haddr_t)statbuf.objno[0]; +#else + tmp_src_lnk.u.hard.addr = statbuf.objno[0]; +#endif + src_lnk = &tmp_src_lnk; + } /* end if */ + else { + /* Discard any errors from a dangling soft link */ + H5E_clear_stack(NULL); - /* Create link message from object entry */ - HDassert(ent->type == H5G_NOTHING_CACHED || ent->type == H5G_CACHED_SLINK - || ent->type == H5G_CACHED_ULINK); -/* XXX: Set character set & creation time for real? */ - lnk->cset = H5F_CRT_DEFAULT_CSET; - lnk->ctime = 0; - lnk->name = H5MM_xstrdup(name); /* Casting away const OK -QAK */ - HDassert(lnk->name); - switch(ent->type) { - case H5G_NOTHING_CACHED: - lnk->type = H5L_LINK_HARD; - lnk->u.hard.addr = ent->header; - break; + /* Release any information copied for temporary src link */ + H5O_reset(H5O_LINK_ID, &tmp_src_lnk); + } /* end else */ + } /* end if */ - case H5G_CACHED_SLINK: - { - const char *s; /* Pointer to link value in heap */ + /* Copy src link information to dst link information */ + if(NULL == H5O_copy(H5O_LINK_ID, src_lnk, dst_lnk)) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, H5B2_ITER_ERROR, "unable to copy message") + dst_lnk_init = TRUE; - lnk->type = H5L_LINK_SOFT; + /* Check if object in source group is a hard link & copy it */ + if(H5L_TYPE_HARD == src_lnk->type) { + H5O_loc_t new_dst_oloc; /* Copied object location in destination */ + H5O_loc_t tmp_src_oloc; /* Temporary object location for source object */ - s = H5HL_offset_into(ent->file, heap, ent->cache.slink.lval_offset); - HDassert(s); + /* Set up copied object location to fill in */ + H5O_loc_reset(&new_dst_oloc); + new_dst_oloc.file = dst_file; - /* Copy to link */ - lnk->u.soft.name = H5MM_xstrdup(s); - HDassert(lnk->u.soft.name); - } - break; + /* Build temporary object location for source */ + H5O_loc_reset(&tmp_src_oloc); + tmp_src_oloc.file = src_oloc->file; + HDassert(H5F_addr_defined(src_lnk->u.hard.addr)); + tmp_src_oloc.addr = src_lnk->u.hard.addr; - case H5G_CACHED_ULINK: - { - const char *s; /* Pointer to link name in heap */ - - /* Copy link type and udata size from entry info */ - lnk->type = ent->cache.ulink.link_type; - lnk->u.ud.size = ent->cache.ulink.udata_size; - - /* Get pointer to udata in heap */ - s = H5HL_offset_into(ent->file, heap, ent->cache.ulink.udata_offset); - HDassert(s); - - /* Read udata from heap if it exists */ - if(lnk->u.ud.size > 0) - { - if(NULL== (lnk->u.ud.udata = H5MM_malloc(lnk->u.ud.size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory for user link data") - HDmemcpy(lnk->u.ud.udata, s, lnk->u.ud.size); - } - else - lnk->u.ud.udata = NULL; - } - break; + /* Copy the shared object from source to destination */ + if(H5O_copy_header_map(&tmp_src_oloc, &new_dst_oloc, dxpl_id, cpy_info, TRUE) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, H5B2_ITER_ERROR, "unable to copy object") - default: - HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unrecognized link type") - } /* end switch */ + /* Copy new destination object's information for eventual insertion */ + dst_lnk->u.hard.addr = new_dst_oloc.addr; + } /* end if */ done: + /* Check if we used a temporary src link */ + if(src_lnk != _src_lnk) { + HDassert(src_lnk == &tmp_src_lnk); + H5O_reset(H5O_LINK_ID, &tmp_src_lnk); + } /* end if */ + if(ret_value < 0) + if(dst_lnk_init) + H5O_reset(H5O_LINK_ID, dst_lnk); + FUNC_LEAVE_NOAPI(ret_value) -} /* end H5G_link_convert() */ +} /* end H5G_link_copy_file() */ /*------------------------------------------------------------------------- @@ -396,7 +418,7 @@ done: * * Purpose: Returns the name of objects in the group by giving index. * - * Return: Success: Non-negative + * Return: Success: Non-negative, length of name * Failure: Negative * * Programmer: Quincey Koziol @@ -405,8 +427,8 @@ done: *------------------------------------------------------------------------- */ ssize_t -H5G_link_get_name_by_idx(H5O_loc_t *oloc, hsize_t idx, char* name, - size_t size, hid_t dxpl_id) +H5G_link_get_name_by_idx(H5O_loc_t *oloc, hid_t dxpl_id, + const H5O_linfo_t *linfo, hsize_t idx, char* name, size_t size) { H5G_link_table_t ltable = {0, NULL}; /* Link table */ ssize_t ret_value; /* Return value */ @@ -417,7 +439,7 @@ H5G_link_get_name_by_idx(H5O_loc_t *oloc, hsize_t idx, char* name, HDassert(oloc); /* Build table of all link messages */ - if(H5G_link_build_table(oloc, dxpl_id, <able) < 0) + if(H5G_link_build_table(oloc, dxpl_id, linfo, H5_ITER_INC, <able) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create link message table") /* Check for going out of bounds */ @@ -438,7 +460,7 @@ done: /* Release link table */ if(ltable.lnks) { /* Free link table information */ - if(H5G_link_release_table(<able) < 0) + if(H5G_obj_release_table(<able) < 0) HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") } /* end if */ @@ -460,7 +482,8 @@ done: *------------------------------------------------------------------------- */ H5G_obj_t -H5G_link_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id) +H5G_link_get_type_by_idx(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, + hsize_t idx) { H5G_link_table_t ltable = {0, NULL}; /* Link table */ H5G_obj_t ret_value; /* Return value */ @@ -471,7 +494,7 @@ H5G_link_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id) HDassert(oloc); /* Build table of all link messages */ - if(H5G_link_build_table(oloc, dxpl_id, <able) < 0) + if(H5G_link_build_table(oloc, dxpl_id, linfo, H5_ITER_INC, <able) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5G_UNKNOWN, "can't create link message table") /* Check for going out of bounds */ @@ -479,11 +502,11 @@ H5G_link_get_type_by_idx(H5O_loc_t *oloc, hsize_t idx, hid_t dxpl_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5G_UNKNOWN, "index out of bound") /* Determine type of object */ - if(ltable.lnks[idx].type == H5L_LINK_SOFT) + if(ltable.lnks[idx].type == H5L_TYPE_SOFT) ret_value = H5G_LINK; - else if(ltable.lnks[idx].type >= H5L_LINK_UD_MIN) + else if(ltable.lnks[idx].type >= H5L_TYPE_UD_MIN) ret_value = H5G_UDLINK; - else if(ltable.lnks[idx].type == H5L_LINK_HARD){ + else if(ltable.lnks[idx].type == H5L_TYPE_HARD){ H5O_loc_t tmp_oloc; /* Temporary object location */ /* Build temporary object location */ @@ -501,7 +524,7 @@ done: /* Release link table */ if(ltable.lnks) { /* Free link table information */ - if(H5G_link_release_table(<able) < 0) + if(H5G_obj_release_table(<able) < 0) HDONE_ERROR(H5E_SYM, H5E_CANTFREE, H5G_UNKNOWN, "unable to release link table") } /* end if */ @@ -540,7 +563,7 @@ H5G_link_remove_cb(const void *_mesg, unsigned UNUSED idx, void *_udata) if(HDstrcmp(lnk->name, udata->name) == 0) { switch(lnk->type) { - case H5L_LINK_HARD: + case H5L_TYPE_HARD: { H5O_loc_t tmp_oloc; /* Temporary object location */ @@ -554,13 +577,13 @@ H5G_link_remove_cb(const void *_mesg, unsigned UNUSED idx, void *_udata) } break; - case H5L_LINK_SOFT: + case H5L_TYPE_SOFT: *(udata->obj_type) = H5G_LINK; break; default: /* User-defined link */ - if(lnk->type < H5L_LINK_UD_MIN) - HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unknown link type"); + if(lnk->type < H5L_TYPE_UD_MIN) + HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "unknown link type") *(udata->obj_type) = H5G_UDLINK; } @@ -615,7 +638,7 @@ done: /*------------------------------------------------------------------------- * Function: H5G_link_iterate * - * Purpose: Iterate over the objects in a group + * Purpose: Iterate over the links in a group * * Return: Non-negative on success/Negative on failure * @@ -625,8 +648,9 @@ done: *------------------------------------------------------------------------- */ herr_t -H5G_link_iterate(H5O_loc_t *oloc, hid_t gid, int skip, int *last_obj, - H5G_iterate_t op, void *op_data, hid_t dxpl_id) +H5G_link_iterate(H5O_loc_t *oloc, hid_t dxpl_id, const H5O_linfo_t *linfo, + H5_iter_order_t order, hid_t gid, hbool_t lib_internal, int skip, + int *last_obj, H5G_link_iterate_t op, void *op_data) { H5G_link_table_t ltable = {0, NULL}; /* Link table */ size_t u; /* Local index variable */ @@ -636,24 +660,24 @@ H5G_link_iterate(H5O_loc_t *oloc, hid_t gid, int skip, int *last_obj, /* Sanity check */ HDassert(oloc); - HDassert(H5I_GROUP == H5I_get_type(gid)); - HDassert(last_obj); - HDassert(op); + HDassert(lib_internal || H5I_GROUP == H5I_get_type(gid)); + HDassert(op.lib_op); /* Build table of all link messages */ - if(H5G_link_build_table(oloc, dxpl_id, <able) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_ITER_ERROR, "can't create link message table") - - /* Check for going out of bounds */ - if(skip > 0 && (size_t)skip >= ltable.nlinks) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5B_ITER_ERROR, "index out of bound") + if(H5G_link_build_table(oloc, dxpl_id, linfo, order, <able) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create link message table") /* Iterate over link messages */ for(u = 0, ret_value = H5B_ITER_CONT; u < ltable.nlinks && !ret_value; u++) { if(skip > 0) --skip; - else - ret_value = (op)(gid, ltable.lnks[u].name, op_data); + else { + /* Check for internal callback with link info */ + if(lib_internal) + ret_value = (op.lib_op)(&(ltable.lnks[u]), op_data); + else + ret_value = (op.app_op)(gid, ltable.lnks[u].name, op_data); + } /* end else */ /* Increment the number of entries passed through */ /* (whether we skipped them or not) */ @@ -668,8 +692,8 @@ done: /* Release link table */ if(ltable.lnks) { /* Free link table information */ - if(H5G_link_release_table(<able) < 0) - HDONE_ERROR(H5E_SYM, H5E_CANTFREE, H5B_ITER_ERROR, "unable to release link table") + if(H5G_obj_release_table(<able) < 0) + HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table") } /* end if */ FUNC_LEAVE_NOAPI(ret_value) @@ -765,5 +789,4 @@ H5G_link_lookup(H5O_loc_t *oloc, const char *name, H5O_link_t *lnk, done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5G_link_lookup() */ -#endif /* H5_GROUP_REVISION */ |