diff options
Diffstat (limited to 'src/H5Lexternal.c')
-rw-r--r-- | src/H5Lexternal.c | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/src/H5Lexternal.c b/src/H5Lexternal.c new file mode 100644 index 0000000..5609658 --- /dev/null +++ b/src/H5Lexternal.c @@ -0,0 +1,314 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#define H5L_PACKAGE /*suppress error about including H5Lpkg */ +#define H5G_PACKAGE /*suppress error about including H5Gpkg */ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5L_init_extern_interface + +#include "H5private.h" /* Generic Functions */ +#include "H5Lpkg.h" /* Links */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Opublic.h" /* File objects */ +#include "H5Ppublic.h" /* Property lists */ +#include "H5Gpkg.h" /* Groups */ + +/*------------------------------------------------------------------------- + * Function: H5L_extern_traverse + * + * Purpose: Default traversal function for external links. This can + * be overridden using H5Lregister(). + * + * Given a filename and path packed into the link udata, + * attempts to open an object within an external file. + * If the H5L_ELINK_PREFIX_PROP property is set in the + * link access property list, appends that prefix to the + * filename being opened. + * + * Return: ID of the opened object on success/Negative on failure + * + * Programmer: James Laird + * Monday, July 10, 2006 + * + *------------------------------------------------------------------------- + */ +static hid_t H5L_extern_traverse(const char * link_name, hid_t cur_group, void * udata, size_t udata_size, hid_t lapl_id) +{ + hid_t fid; + char *file_name; + char *obj_name; + size_t fname_len; + htri_t result; + hbool_t fname_alloc = FALSE; + hid_t ret_value = -1; + + file_name = (char *) udata; + fname_len = strlen(file_name); + obj_name = ((char *) udata) + fname_len + 1; + + /* See if the external link prefix property is set */ + if((result = H5Pexist(lapl_id, H5L_ELINK_PREFIX_PROP)) < 0) + goto error; + + /* If so, prepend it to the filename */ + if(result > 0) + { + size_t buf_size; + + if(H5Pget_size(lapl_id, H5L_ELINK_PREFIX_PROP, &buf_size) < 0) + goto error; + + /* Allocate a buffer to hold the filename plus prefix */ + file_name = malloc(buf_size + fname_len + 1); + fname_alloc = TRUE; + + if(H5Pget(lapl_id, H5L_ELINK_PREFIX_PROP, file_name) < 0) + goto error; + + /* Add the external link's filename to the prefix supplied */ + strcat(file_name, udata); + } + + if((fid = H5Fopen(file_name, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) + goto error; + ret_value = H5Oopen(fid, obj_name, lapl_id); /* If this fails, our return value will be negative. */ + if(H5Fclose(fid) < 0) + goto error; + + /* Free file_name if it's been allocated */ + if(fname_alloc) + free(file_name); + + return ret_value; + +error: + /* Free file_name if it's been allocated */ + if(fname_alloc) + free(file_name); + return -1; +} + + +/*------------------------------------------------------------------------- + * Function: H5L_extern_query + * + * Purpose: Default query function for external links. This can + * be overridden using H5Lregister(). + * + * Returns the size of the link's user data. If a buffer of + * is provided, copies at most buf_size bytes of the udata + * into it. + * + * Return: Size of buffer on success/Negative on failure + * + * Programmer: James Laird + * Monday, July 10, 2006 + * + *------------------------------------------------------------------------- + */ +static ssize_t H5L_extern_query(const char * link_name, void * udata, size_t udata_size, void * buf /*out*/, size_t buf_size) +{ + size_t ret_value; + + /* If the buffer is NULL, skip writng anything in it and just return + * the size needed */ + if(buf) + { + if(udata_size < buf_size) + buf_size = udata_size; + + /* Copy the udata verbatim up to udata_size*/ + memcpy(buf, udata, udata_size); + } + + ret_value = udata_size; + return ret_value; +} + +/* Default External Link link class */ +const H5L_link_class_t H5L_EXTERN_LINK_CLASS[1] = {{ + H5L_LINK_CLASS_T_VERS, /* H5L_link_class_t version */ + H5L_LINK_EXTERNAL, /* Link type id number */ + "external_link", /* Link name for debugging */ + NULL, /* Creation callback */ + NULL, /* Move callback */ + NULL, /* Copy callback */ + H5L_extern_traverse, /* The actual traversal function */ + NULL, /* Deletion callback */ + H5L_extern_query /* Query callback */ +}}; + + +/*-------------------------------------------------------------------------- +NAME + H5L_init_extern_interface -- Initialize interface-specific information +USAGE + herr_t H5L_init_extern_interface() + +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. (Just calls + H5T_init_iterface currently). + +--------------------------------------------------------------------------*/ +static herr_t +H5L_init_extern_interface(void) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5L_init_extern_interface) + + FUNC_LEAVE_NOAPI(H5L_init()) +} /* H5L_init_extern_interface() */ + + + +/*------------------------------------------------------------------------- + * 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) +{ + H5G_loc_t link_loc; + char *temp_name = NULL; + size_t buf_size; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Lcreate_external, FAIL) + H5TRACE6("e","ssisii",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(H5G_loc(link_loc_id, &link_loc) < 0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!link_name || !*link_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no link name specified") + + /* Combine the filename and link name into a single buffer to give to the UD link */ + buf_size = HDstrlen(file_name) + HDstrlen(obj_name) + 2; + if(NULL == (temp_name = H5MM_malloc(buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate udata buffer") + HDstrcpy(temp_name, file_name); + HDstrcpy(temp_name + (HDstrlen(file_name) + 1), obj_name); + + /* Create an external link */ + if(H5L_create_ud(&link_loc, link_name, temp_name, buf_size, H5L_LINK_EXTERNAL, H5G_TARGET_NORMAL, lcpl_id, lapl_id, H5AC_dxpl_id) < 0) + HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "unable to create link") + +done: + if(temp_name != NULL) + H5MM_free(temp_name); + FUNC_LEAVE_API(ret_value); +} /* end H5Lcreate_external() */ + + +/*------------------------------------------------------------------------- + * Function: H5L_register_external + * + * Purpose: Registers default "External Link" link class. + * Use during library initialization or to restore the default + * after users change it. + * + * Return: Non-negative on success/ negative on failure + * + * Programmer: James Laird + * Monday, July 17, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5L_register_external() +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5L_register_external, FAIL) + + if(H5L_register(H5L_EXTERN_LINK_CLASS) < 0) + HGOTO_ERROR(H5E_LINK, H5E_NOTREGISTERED, FAIL, "unable to register external link class") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- + * Function: H5Lunpack_elink_path + * + * Purpose: Given a buffer holding the "link value" from an external link, + * gets pointers to the filename and object path within the + * link value buffer. + * + * External link linkvalues are two NULL-terminated strings + * one after the other. + * + * FILENAME and OBJ_PATH will be set to pointers within + * ext_linkval unless they are 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(char *ext_linkval, char **filename, char **obj_path) +{ + size_t len; /* Length of the filename in the linkval*/ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Lunpack_elink_val, FAIL) + H5TRACE3("e","s*s*s",ext_linkval,filename,obj_path); + + if(ext_linkval == NULL ) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not an external link linkval buffer") + + if(filename != NULL) + *filename = ext_linkval; + + if(obj_path != NULL) + { + len = HDstrlen(ext_linkval); + *obj_path = ext_linkval + len + 1; /* Add one for NULL terminator */ + } + +done: + FUNC_LEAVE_API(ret_value) +} |