diff options
Diffstat (limited to 'src/H5L.c')
-rw-r--r-- | src/H5L.c | 179 |
1 files changed, 179 insertions, 0 deletions
@@ -590,6 +590,103 @@ done: } /* end H5Lcreate_hard() */ /*------------------------------------------------------------------------- + * Function: H5Lcreate_external + * + * Purpose: Creates an external link from LINK_NAME to OBJ_NAME. + * + * External links are links to objects in other HDF5 files. They + * are allowed to "dangle" like soft links internal to a file. + * FILE_NAME is the name of the file that OBJ_NAME is is contained + * within. If OBJ_NAME is given as a relative path name, the + * path will be relative to the root group of FILE_NAME. + * LINK_NAME is interpreted relative to LINK_LOC_ID, which is + * either a file ID or a group ID. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Wednesday, May 18, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lcreate_external(const char *file_name, const char *obj_name, hid_t link_loc_id, const char *link_name, + hid_t lcpl_id, hid_t lapl_id) +{ + H5VL_object_t * vol_obj = NULL; /* Object of loc_id */ + H5VL_loc_params_t loc_params; + char * norm_obj_name = NULL; /* Pointer to normalized current name */ + void * ext_link_buf = NULL; /* Buffer to contain external link */ + size_t buf_size; /* Size of buffer to hold external link */ + size_t file_name_len; /* Length of file name string */ + size_t norm_obj_name_len; /* Length of normalized object name string */ + uint8_t * p; /* Pointer into external link buffer */ + H5L_type_t link_type = H5L_TYPE_EXTERNAL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE6("e", "*s*si*sii", file_name, obj_name, link_loc_id, link_name, lcpl_id, lapl_id); + + /* Check arguments */ + if (!file_name || !*file_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no file name specified") + if (!obj_name || !*obj_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no object name specified") + if (!link_name || !*link_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no link name specified") + + /* Get the link creation property list */ + if (H5P_DEFAULT == lcpl_id) + lcpl_id = H5P_LINK_CREATE_DEFAULT; + + /* Set the LCPL for the API context */ + H5CX_set_lcpl(lcpl_id); + + /* Verify access property list and set up collective metadata if appropriate */ + if (H5CX_set_apl(&lapl_id, H5P_CLS_LACC, link_loc_id, TRUE) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set access property list info") + + /* Get normalized copy of the link target */ + if (NULL == (norm_obj_name = H5G_normalize(obj_name))) + HGOTO_ERROR(H5E_LINK, H5E_BADVALUE, FAIL, "can't normalize object name") + + /* Combine the filename and link name into a single buffer to give to the UD link */ + file_name_len = HDstrlen(file_name) + 1; + norm_obj_name_len = HDstrlen(norm_obj_name) + 1; + buf_size = 1 + file_name_len + norm_obj_name_len; + if (NULL == (ext_link_buf = H5MM_malloc(buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate udata buffer") + + /* Encode the external link information */ + p = (uint8_t *)ext_link_buf; + *p++ = (H5L_EXT_VERSION << 4) | H5L_EXT_FLAGS_ALL; /* External link version & flags */ + HDstrncpy((char *)p, file_name, buf_size - 1); /* Name of file containing external link's object */ + p += file_name_len; + HDstrncpy((char *)p, norm_obj_name, buf_size - (file_name_len + 1)); /* External link's object */ + + loc_params.type = H5VL_OBJECT_BY_NAME; + loc_params.loc_data.loc_by_name.name = link_name; + loc_params.loc_data.loc_by_name.lapl_id = lapl_id; + loc_params.obj_type = H5I_get_type(link_loc_id); + + /* get the location object */ + if (NULL == (vol_obj = (H5VL_object_t *)H5I_object(link_loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid object identifier") + + /* Create an external link */ + if (H5VL_link_create(H5VL_LINK_CREATE_UD, vol_obj, &loc_params, lcpl_id, lapl_id, + H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL, (int)link_type, ext_link_buf, + buf_size) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create external link") + +done: + H5MM_xfree(ext_link_buf); + H5MM_xfree(norm_obj_name); + + FUNC_LEAVE_API(ret_value) +} /* end H5Lcreate_external() */ + +/*------------------------------------------------------------------------- * Function: H5Lcreate_ud * * Purpose: Creates a user-defined link of type LINK_TYPE named LINK_NAME @@ -1519,6 +1616,88 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Lvisit_by_name2() */ +/*------------------------------------------------------------------------- + * Function: H5Lunpack_elink_val + * + * Purpose: Given a buffer holding the "link value" from an external link, + * gets pointers to the information within the link value buffer. + * + * External link link values contain some flags and + * two NULL-terminated strings, one after the other. + * + * The FLAGS value will be filled in and FILENAME and + * OBJ_PATH will be set to pointers within ext_linkval (unless + * any of these values is NULL). + * + * Using this function on strings that aren't external link + * udata buffers can result in segmentation faults. + * + * Return: Non-negative on success/ Negative on failure + * + * Programmer: James Laird + * Monday, July 17, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Lunpack_elink_val(const void *_ext_linkval, size_t link_size, unsigned *flags, const char **filename, + const char **obj_path) +{ + const uint8_t *ext_linkval = (const uint8_t *)_ext_linkval; /* Pointer to the link value */ + unsigned lnk_version; /* External link format version */ + unsigned lnk_flags; /* External link flags */ + size_t len; /* Length of the filename in the linkval*/ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE5("e", "*xz*Iu**s**s", _ext_linkval, link_size, flags, filename, obj_path); + + /* Sanity check external link buffer */ + if (ext_linkval == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an external link linkval buffer") + lnk_version = (*ext_linkval >> 4) & 0x0F; + lnk_flags = *ext_linkval & 0x0F; + if (lnk_version > H5L_EXT_VERSION) + HGOTO_ERROR(H5E_LINK, H5E_CANTDECODE, FAIL, "bad version number for external link") + if (lnk_flags & (unsigned)~H5L_EXT_FLAGS_ALL) + HGOTO_ERROR(H5E_LINK, H5E_CANTDECODE, FAIL, "bad flags for external link") + if (link_size <= 2) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid external link buffer") + + /* Try to do some error checking. If the last character in the linkval + * (the last character of obj_path) isn't NULL, then something's wrong. + */ + if (ext_linkval[link_size - 1] != '\0') + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "linkval buffer is not NULL-terminated") + + /* We're now guaranteed that HDstrlen won't segfault, since the buffer has + * at least one NULL in it. + */ + len = HDstrlen((const char *)ext_linkval + 1); + + /* If the first NULL we found was at the very end of the buffer, then + * this external link value has no object name and is invalid. + */ + if ((len + 1) >= (link_size - 1)) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "linkval buffer doesn't contain an object path") + + /* If we got here then the buffer contains (at least) two strings packed + * in the correct way. Assume it's correct and return pointers to the + * filename and object path. + */ + if (filename) + *filename = (const char *)ext_linkval + 1; + if (obj_path) + *obj_path = ((const char *)ext_linkval + 1) + len + 1; /* Add one for NULL terminator */ + + /* Set the flags to return */ + if (flags) + *flags = lnk_flags; + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Lunpack_elink_val() */ + /* *------------------------------------------------------------------------- *------------------------------------------------------------------------- |