diff --git a/src/rest_vol.c b/src/rest_vol.c index cb2cc8ee..d065d55e 100644 --- a/src/rest_vol.c +++ b/src/rest_vol.c @@ -3382,6 +3382,56 @@ RV_set_object_type_header(H5I_type_t parent_obj_type, const char **parent_obj_ty return (ret_value); } /* end RV_set_object_type_header */ +/* Helper function to initialize an object's name based on its parent's name. + * Allocates memory that must be closed by caller. */ +herr_t RV_set_object_handle_path(const char *obj_path, const char *parent_path, char **buf) { + herr_t ret_value = SUCCEED; + hbool_t include_parent_path = false; + size_t path_size = 0; + size_t path_len = 0; + char *handle_path = NULL; + + /* Objects can be created/opened without reference to their path. Leave handle_path NULL in this case */ + if (!obj_path) { + *buf = NULL; + FUNC_GOTO_DONE(SUCCEED); + } + + /* Parent name is included if it is not the root and the object is opened by relative path */ + include_parent_path = parent_path && strcmp(parent_path, "/") && (obj_path[0] != '/'); + + path_size = include_parent_path ? + strlen(parent_path) + 1 + strlen(obj_path) + 1 + : 1 + strlen(obj_path) + 1; + + if ((handle_path = RV_malloc(path_size)) == NULL) + FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTALLOC, NULL, "can't allocate space for handle path"); + + if (include_parent_path) { + strncpy(handle_path, parent_path, strlen(parent_path)); + path_len += strlen(parent_path); + } + + /* Add leading slash if not in group name */ + if (obj_path[0] != '/') { + handle_path[path_len] = '/'; + path_len += 1; + } + + strncpy(handle_path + path_len, obj_path, strlen(obj_path) + 1); + path_len += (strlen(obj_path) + 1); + + /* Make user pointer point at allocated memory */ + *buf = handle_path; + +done: + if (ret_value < 0) { + RV_free(handle_path); + *buf = NULL; + } + + return ret_value; +} /************************************************* * The following two routines allow the REST VOL * * connector to be dynamically loaded by HDF5. * diff --git a/src/rest_vol.h b/src/rest_vol.h index 2f8acfe4..9cc1c65c 100644 --- a/src/rest_vol.h +++ b/src/rest_vol.h @@ -625,6 +625,9 @@ herr_t RV_base64_decode(const char *in, size_t in_size, char **out, size_t *out_ /* Comparison function to compare two keys in an rv_hash_table_t */ int H5_rest_compare_string_keys(void *value1, void *value2); +/* Helper function to initialize an object's name based on its parent's name. */ +herr_t RV_set_object_handle_path(const char *obj_path, const char *parent_path, char **buf); + /* Helper to turn an object type into a string for a server request */ herr_t RV_set_object_type_header(H5I_type_t parent_obj_type, const char **parent_obj_type_header); diff --git a/src/rest_vol_attr.c b/src/rest_vol_attr.c index ffc48718..7e5036d5 100644 --- a/src/rest_vol_attr.c +++ b/src/rest_vol_attr.c @@ -118,30 +118,8 @@ RV_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_ new_attribute->handle_path = NULL; - if (attr_name) { - /* Parent name is included if it is not the root */ - hbool_t include_parent_name = strcmp(parent->handle_path, "/"); - - path_size = (include_parent_name ? strlen(parent->handle_path) + 1 + strlen(attr_name) + 1 - : 1 + strlen(attr_name) + 1); - - if ((new_attribute->handle_path = RV_malloc(path_size)) == NULL) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTALLOC, NULL, "can't allocate space for handle path"); - - if (include_parent_name) { - strncpy(new_attribute->handle_path, parent->handle_path, strlen(parent->handle_path)); - path_len += strlen(parent->handle_path); - } - - /* Add leading slash if not in attribute name */ - if (attr_name[0] != '/') { - new_attribute->handle_path[path_len] = '/'; - path_len += 1; - } - - strncpy(new_attribute->handle_path + path_len, attr_name, strlen(attr_name) + 1); - path_len += (strlen(attr_name) + 1); - } + if (RV_set_object_handle_path(attr_name, parent->handle_path, &new_attribute->handle_path) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_PATH, NULL, "can't set up object path"); new_attribute->u.attribute.parent_name = NULL; @@ -498,30 +476,8 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na attribute->handle_path = NULL; - if (attr_name) { - /* Parent name is included if it is not the root */ - hbool_t include_parent_name = strcmp(parent->handle_path, "/"); - - path_size = (include_parent_name ? strlen(parent->handle_path) + 1 + strlen(attr_name) + 1 - : 1 + strlen(attr_name) + 1); - - if ((attribute->handle_path = RV_malloc(path_size)) == NULL) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTALLOC, NULL, "can't allocate space for handle path"); - - if (include_parent_name) { - strncpy(attribute->handle_path, parent->handle_path, strlen(parent->handle_path)); - path_len += strlen(parent->handle_path); - } - - /* Add leading slash if not in attribute name */ - if (attr_name[0] != '/') { - attribute->handle_path[path_len] = '/'; - path_len += 1; - } - - strncpy(attribute->handle_path + path_len, attr_name, strlen(attr_name) + 1); - path_len += (strlen(attr_name) + 1); - } + if (RV_set_object_handle_path(attr_name, parent->handle_path, &attribute->handle_path) < 0) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_PATH, NULL, "can't set up object path"); attribute->u.attribute.parent_name = NULL; diff --git a/src/rest_vol_dataset.c b/src/rest_vol_dataset.c index b3cddfdc..55b186a3 100644 --- a/src/rest_vol_dataset.c +++ b/src/rest_vol_dataset.c @@ -148,30 +148,8 @@ RV_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *na new_dataset->handle_path = NULL; - if (name) { - /* Parent name is included if it is not the root and the dataset is opened by relative path */ - hbool_t include_parent_name = strcmp(parent->handle_path, "/") && (name[0] != '/'); - - path_size = - (include_parent_name ? strlen(parent->handle_path) + 1 + strlen(name) + 1 : 1 + strlen(name) + 1); - - if ((new_dataset->handle_path = RV_malloc(path_size)) == NULL) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTALLOC, NULL, "can't allocate space for handle path"); - - if (include_parent_name) { - strncpy(new_dataset->handle_path, parent->handle_path, strlen(parent->handle_path)); - path_len += strlen(parent->handle_path); - } - - /* Add leading slash if not in dataset path */ - if (name[0] != '/') { - new_dataset->handle_path[path_len] = '/'; - path_len += 1; - } - - strncpy(new_dataset->handle_path + path_len, name, strlen(name) + 1); - path_len += (strlen(name) + 1); - } + if (RV_set_object_handle_path(name, parent->handle_path, &new_dataset->handle_path) < 0) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_PATH, NULL, "can't set up object path"); /* Copy the DAPL if it wasn't H5P_DEFAULT, else set up a default one so that * H5Dget_access_plist() will function correctly @@ -364,30 +342,8 @@ RV_dataset_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name dataset->handle_path = NULL; - if (name) { - /* Parent name is included if it is not the root and the dataset is opened by relative path */ - hbool_t include_parent_name = strcmp(parent->handle_path, "/") && (name[0] != '/'); - - path_size = - (include_parent_name ? strlen(parent->handle_path) + 1 + strlen(name) + 1 : 1 + strlen(name) + 1); - - if ((dataset->handle_path = RV_malloc(path_size)) == NULL) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTALLOC, NULL, "can't allocate space for handle path"); - - if (include_parent_name) { - strncpy(dataset->handle_path, parent->handle_path, strlen(parent->handle_path)); - path_len += strlen(parent->handle_path); - } - - /* Add leading slash if not in dataset path */ - if (name[0] != '/') { - dataset->handle_path[path_len] = '/'; - path_len += 1; - } - - strncpy(dataset->handle_path + path_len, name, strlen(name) + 1); - path_len += (strlen(name) + 1); - } + if (RV_set_object_handle_path(name, parent->handle_path, &dataset->handle_path) < 0) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_PATH, NULL, "can't set up object path"); loc_info_out.URI = dataset->URI; loc_info_out.domain = dataset->domain; diff --git a/src/rest_vol_datatype.c b/src/rest_vol_datatype.c index 29daea5d..42f83df9 100644 --- a/src/rest_vol_datatype.c +++ b/src/rest_vol_datatype.c @@ -126,30 +126,8 @@ RV_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *n new_datatype->handle_path = NULL; - if (name) { - /* Parent name is included if it is not the root and the datatype is opened by relative path */ - hbool_t include_parent_name = strcmp(parent->handle_path, "/") && (name[0] != '/'); - - path_size = - (include_parent_name ? strlen(parent->handle_path) + 1 + strlen(name) + 1 : 1 + strlen(name) + 1); - - if ((new_datatype->handle_path = RV_malloc(path_size)) == NULL) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTALLOC, NULL, "can't allocate space for handle path"); - - if (include_parent_name) { - strncpy(new_datatype->handle_path, parent->handle_path, strlen(parent->handle_path)); - path_len += strlen(parent->handle_path); - } - - /* Add leading slash if not in datatype path */ - if (name[0] != '/') { - new_datatype->handle_path[path_len] = '/'; - path_len += 1; - } - - strncpy(new_datatype->handle_path + path_len, name, strlen(name) + 1); - path_len += (strlen(name) + 1); - } + if (RV_set_object_handle_path(name, parent->handle_path, &new_datatype->handle_path) < 0) + FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_PATH, NULL, "can't set up object path"); /* Copy the TAPL if it wasn't H5P_DEFAULT, else set up a default one so that * datatype access property list functions will function correctly @@ -396,30 +374,8 @@ RV_datatype_open(void *obj, const H5VL_loc_params_t *loc_params, const char *nam datatype->handle_path = NULL; - if (name) { - /* Parent name is included if it is not the root and the datatype is opened by relative path */ - hbool_t include_parent_name = strcmp(parent->handle_path, "/") && (name[0] != '/'); - - path_size = - (include_parent_name ? strlen(parent->handle_path) + 1 + strlen(name) + 1 : 1 + strlen(name) + 1); - - if ((datatype->handle_path = RV_malloc(path_size)) == NULL) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTALLOC, NULL, "can't allocate space for handle path"); - - if (include_parent_name) { - strncpy(datatype->handle_path, parent->handle_path, strlen(parent->handle_path)); - path_len += strlen(parent->handle_path); - } - - /* Add leading slash if not in datatype path */ - if (name[0] != '/') { - datatype->handle_path[path_len] = '/'; - path_len += 1; - } - - strncpy(datatype->handle_path + path_len, name, strlen(name) + 1); - path_len += (strlen(name) + 1); - } + if (RV_set_object_handle_path(name, parent->handle_path, &datatype->handle_path) < 0) + FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_PATH, NULL, "can't set up object path"); loc_info_out.URI = datatype->URI; loc_info_out.domain = datatype->domain; diff --git a/src/rest_vol_file.c b/src/rest_vol_file.c index 2ba774e3..d17d9863 100644 --- a/src/rest_vol_file.c +++ b/src/rest_vol_file.c @@ -76,7 +76,12 @@ RV_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, h new_file->u.file.fapl_id = FAIL; new_file->u.file.fcpl_id = FAIL; new_file->u.file.ref_count = 1; - new_file->handle_path = "/"; + + /* Allocate root "path" on heap for consistency with other RV_object_t types */ + if ((new_file->handle_path = RV_malloc(2)) == NULL) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "can't allocate space for filepath"); + + strncpy(new_file->handle_path, "/", 2); /* Copy the FAPL if it wasn't H5P_DEFAULT, else set up a default one so that * H5Fget_access_plist() will function correctly. Note that due to the nature @@ -344,7 +349,13 @@ RV_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, voi file->u.file.fapl_id = FAIL; file->u.file.fcpl_id = FAIL; file->u.file.ref_count = 1; - file->handle_path = "/"; + + /* Allocate root "path" on heap for consistency with other RV_object_t types */ + if ((file->handle_path = RV_malloc(2)) == NULL) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "can't allocate space for filepath"); + + strncpy(file->handle_path, "/", 2); + /* Store self-referential pointer in the domain field for this object * to simplify code for other types of objects @@ -730,6 +741,7 @@ RV_file_close(void *file, hid_t dxpl_id, void **req) _file->u.file.filepath_name = NULL; } + RV_free(_file->handle_path); RV_free(_file); } diff --git a/src/rest_vol_group.c b/src/rest_vol_group.c index 1025bf45..acdfc8b5 100644 --- a/src/rest_vol_group.c +++ b/src/rest_vol_group.c @@ -96,30 +96,8 @@ RV_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name new_group->handle_path = NULL; - if (name) { - /* Parent name is included if it is not the root and the group is opened by relative path */ - hbool_t include_parent_name = strcmp(parent->handle_path, "/") && (name[0] != '/'); - - path_size = - (include_parent_name ? strlen(parent->handle_path) + 1 + strlen(name) + 1 : 1 + strlen(name) + 1); - - if ((new_group->handle_path = RV_malloc(path_size)) == NULL) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTALLOC, NULL, "can't allocate space for handle path"); - - if (include_parent_name) { - strncpy(new_group->handle_path, parent->handle_path, strlen(parent->handle_path)); - path_len += strlen(parent->handle_path); - } - - /* Add leading slash if not in group name */ - if (name[0] != '/') { - new_group->handle_path[path_len] = '/'; - path_len += 1; - } - - strncpy(new_group->handle_path + path_len, name, strlen(name) + 1); - path_len += (strlen(name) + 1); - } + if (RV_set_object_handle_path(name, parent->handle_path, &new_group->handle_path) < 0) + FUNC_GOTO_ERROR(H5E_SYM, H5E_PATH, NULL, "can't set up object path"); /* Copy the GAPL if it wasn't H5P_DEFAULT, else set up a default one so that * group access property list functions will function correctly @@ -402,30 +380,8 @@ RV_group_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, group->handle_path = NULL; - if (name) { - /* Parent name is included if it is not the root and the group is opened by relative path */ - hbool_t include_parent_name = strcmp(parent->handle_path, "/") && (name[0] != '/'); - - path_size = - (include_parent_name ? strlen(parent->handle_path) + 1 + strlen(name) + 1 : 1 + strlen(name) + 1); - - if ((group->handle_path = RV_malloc(path_size)) == NULL) - FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTALLOC, NULL, "can't allocate space for handle path"); - - if (include_parent_name) { - strncpy(group->handle_path, parent->handle_path, strlen(parent->handle_path)); - path_len += strlen(parent->handle_path); - } - - /* Add leading slash if not in group name */ - if (name[0] != '/') { - group->handle_path[path_len] = '/'; - path_len += 1; - } - - strncpy(group->handle_path + path_len, name, strlen(name) + 1); - path_len += (strlen(name) + 1); - } + if (RV_set_object_handle_path(name, parent->handle_path, &group->handle_path) < 0) + FUNC_GOTO_ERROR(H5E_SYM, H5E_PATH, NULL, "can't set up object path"); /* Locate group and set domain */ diff --git a/src/rest_vol_object.c b/src/rest_vol_object.c index 2d27401f..361f09d0 100644 --- a/src/rest_vol_object.c +++ b/src/rest_vol_object.c @@ -819,6 +819,12 @@ RV_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_s memcpy(iter_object, loc_obj, sizeof(RV_object_t)); + if ((iter_object->handle_path = RV_malloc(strlen(loc_obj->handle_path) + 1)) == NULL) + FUNC_GOTO_ERROR(H5E_OBJECT, H5E_CANTALLOC, FAIL, + "couldn't allocate space for iteration object path"); + + memcpy(iter_object->handle_path, loc_obj->handle_path, strlen(loc_obj->handle_path) + 1); + /* Increment refs for specific type */ switch (loc_obj->obj_type) { case H5I_FILE: @@ -826,13 +832,13 @@ RV_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_s if (H5I_INVALID_HID == (iter_object->u.file.fapl_id = H5Pcopy(loc_obj->u.file.fapl_id))) - FUNC_GOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, NULL, "can't copy FAPL"); + FUNC_GOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy FAPL"); if (H5I_INVALID_HID == (iter_object->u.file.fcpl_id = H5Pcopy(loc_obj->u.file.fcpl_id))) - FUNC_GOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, NULL, "can't copy FCPL"); + FUNC_GOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy FCPL"); if (NULL == (iter_object->u.file.filepath_name = RV_malloc(strlen(loc_obj->u.file.filepath_name) + 1))) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate space for copied filepath_name object"); strncpy(iter_object->u.file.filepath_name, loc_obj->u.file.filepath_name, @@ -1178,7 +1184,12 @@ RV_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_s } else { /* If execution failed before the wrap, free the RV_object_t block directly*/ - RV_free(iter_object); + if (iter_object) { + if (args->op_type == H5VL_OBJECT_VISIT && loc_params->type == H5VL_OBJECT_BY_SELF) { + RV_free(iter_object->handle_path); + } + RV_free(iter_object); + } } PRINT_ERROR_STACK; @@ -1788,6 +1799,8 @@ RV_build_object_table(char *HTTP_response, hbool_t is_recursive, int (*sort_func subgroup->obj_type = H5I_GROUP; subgroup->u.group.gcpl_id = H5P_DEFAULT; subgroup->u.group.gapl_id = H5P_DEFAULT; + if (RV_set_object_handle_path(link_name, object_iter_data->iter_obj_parent->handle_path, &subgroup->handle_path) < 0) + FUNC_GOTO_ERROR(H5E_OBJECT, H5E_PATH, FAIL, "can't set up object path"); object_iter_data->iter_obj_parent->domain->u.file.ref_count++;