diff --git a/src/rest_vol.c b/src/rest_vol.c index ba42acca..c470bca3 100644 --- a/src/rest_vol.c +++ b/src/rest_vol.c @@ -2437,6 +2437,8 @@ RV_copy_object_loc_info_callback(char *HTTP_response, void *callback_data_in, vo new_domain->u.file.fapl_id = H5Pcopy(loc_info_out->domain->u.file.fapl_id); new_domain->u.file.fcpl_id = H5Pcopy(loc_info_out->domain->u.file.fcpl_id); new_domain->u.file.ref_count = 1; + new_domain->u.file.server_version = found_domain.u.file.server_version; + new_domain->handle_path = "/"; /* Assume that original domain and external domain have the same server version. * This will always be true unless it becomes possible for external links to point to diff --git a/src/rest_vol.h b/src/rest_vol.h index f544d027..91a096b1 100644 --- a/src/rest_vol.h +++ b/src/rest_vol.h @@ -473,6 +473,7 @@ typedef struct RV_attr_t { hid_t aapl_id; hid_t acpl_id; char *attr_name; + char *parent_name; } RV_attr_t; typedef struct RV_datatype_t { @@ -485,6 +486,7 @@ struct RV_object_t { RV_object_t *domain; H5I_type_t obj_type; char URI[URI_MAX_LENGTH]; + char *handle_path; union { RV_datatype_t datatype; diff --git a/src/rest_vol_attr.c b/src/rest_vol_attr.c index 852e4c90..10d5e314 100644 --- a/src/rest_vol_attr.c +++ b/src/rest_vol_attr.c @@ -58,6 +58,8 @@ RV_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_ size_t host_header_len = 0; size_t datatype_body_len = 0; size_t attr_name_len = 0; + size_t path_size = 0; + size_t path_len = 0; char *host_header = NULL; char *create_request_body = NULL; char *datatype_body = NULL; @@ -114,6 +116,41 @@ RV_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_ new_attribute->domain = parent->domain; parent->domain->u.file.ref_count++; + 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); + } + + new_attribute->u.attribute.parent_name = NULL; + + if (parent->handle_path) { + if ((new_attribute->u.attribute.parent_name = RV_malloc(strlen(parent->handle_path) + 1)) == NULL) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "can't allocate space for attribute parent name"); + + strncpy(new_attribute->u.attribute.parent_name, parent->handle_path, strlen(parent->handle_path) + 1); + } + /* If this is a call to H5Acreate_by_name, locate the real parent object */ if (H5VL_OBJECT_BY_NAME == loc_params->type) { @@ -402,6 +439,8 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na RV_object_t *attribute = NULL; size_t attr_name_len = 0; size_t host_header_len = 0; + size_t path_size = 0; + size_t path_len = 0; char *host_header = NULL; char *found_attr_name = NULL; char request_url[URL_MAX_LENGTH]; @@ -456,6 +495,41 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na attribute->domain = parent->domain; parent->domain->u.file.ref_count++; + 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); + } + + attribute->u.attribute.parent_name = NULL; + + if (parent->handle_path) { + if ((attribute->u.attribute.parent_name = RV_malloc(strlen(parent->handle_path) + 1)) == NULL) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, NULL, "can't allocate space for attribute parent name"); + + strncpy(attribute->u.attribute.parent_name, parent->handle_path, strlen(parent->handle_path) + 1); + } + /* Set the parent object's type and URI in the attribute's appropriate fields */ switch (loc_params->type) { /* H5Aopen */ @@ -2170,10 +2244,17 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci } /* Increment refs for specific type */ + + RV_object_t *attr_iter_obj = (RV_object_t *)attr_iter_object; + + if ((attr_iter_obj->handle_path = RV_malloc(strlen(loc_obj->handle_path) +1)) == NULL) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "can't allocate space for copy of object path"); + + strncpy(attr_iter_obj->handle_path, loc_obj->handle_path, strlen(loc_obj->handle_path) + 1); + switch (parent_obj_type) { case H5I_FILE: /* Copy fapl, fcpl, and filepath name to new object */ - RV_object_t *attr_iter_obj = (RV_object_t *)attr_iter_object; if (H5I_INVALID_HID == (attr_iter_obj->u.file.fapl_id = H5Pcopy(loc_obj->u.file.fapl_id))) @@ -2602,6 +2683,8 @@ RV_attr_close(void *attr, hid_t dxpl_id, void **req) if (RV_file_close(_attr->domain, H5P_DEFAULT, NULL) < 0) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "couldn't close attr domain"); + RV_free(_attr->u.attribute.parent_name); + RV_free(_attr->handle_path); RV_free(_attr); _attr = NULL; diff --git a/src/rest_vol_dataset.c b/src/rest_vol_dataset.c index ce17d67b..40551bfe 100644 --- a/src/rest_vol_dataset.c +++ b/src/rest_vol_dataset.c @@ -105,6 +105,8 @@ RV_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *na RV_object_t *new_dataset = NULL; curl_off_t create_request_body_len = 0; size_t host_header_len = 0; + size_t path_size = 0; + size_t path_len = 0; char *host_header = NULL; char *create_request_body = NULL; char request_url[URL_MAX_LENGTH]; @@ -144,6 +146,32 @@ RV_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *na new_dataset->domain = parent->domain; parent->domain->u.file.ref_count++; + 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); + } + /* Copy the DAPL if it wasn't H5P_DEFAULT, else set up a default one so that * H5Dget_access_plist() will function correctly */ @@ -303,6 +331,8 @@ RV_dataset_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name htri_t search_ret; void *ret_value = NULL; loc_info loc_info_out; + size_t path_size = 0; + size_t path_len = 0; #ifdef RV_CONNECTOR_DEBUG printf("-> Received dataset open call with following parameters:\n"); @@ -331,6 +361,32 @@ RV_dataset_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name dataset->domain = parent->domain; parent->domain->u.file.ref_count++; + 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); + } + loc_info_out.URI = dataset->URI; loc_info_out.domain = dataset->domain; loc_info_out.GCPL_base64 = NULL; @@ -1169,6 +1225,7 @@ RV_dataset_close(void *dset, hid_t dxpl_id, void **req) FUNC_DONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file"); } + RV_free(_dset->handle_path); RV_free(_dset); _dset = NULL; diff --git a/src/rest_vol_datatype.c b/src/rest_vol_datatype.c index e3adb8f1..71c14c19 100644 --- a/src/rest_vol_datatype.c +++ b/src/rest_vol_datatype.c @@ -72,6 +72,8 @@ RV_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *n size_t link_body_nalloc = 0; size_t host_header_len = 0; size_t datatype_body_len = 0; + size_t path_size = 0; + size_t path_len = 0; char *host_header = NULL; char *commit_request_body = NULL; char *datatype_body = NULL; @@ -117,6 +119,32 @@ RV_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *n new_datatype->domain = parent->domain; parent->domain->u.file.ref_count++; + 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); + } + /* 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 */ @@ -331,6 +359,8 @@ RV_datatype_open(void *obj, const H5VL_loc_params_t *loc_params, const char *nam H5I_type_t obj_type = H5I_UNINIT; loc_info loc_info_out; htri_t search_ret; + size_t path_size = 0; + size_t path_len = 0; void *ret_value = NULL; #ifdef RV_CONNECTOR_DEBUG @@ -358,6 +388,32 @@ RV_datatype_open(void *obj, const H5VL_loc_params_t *loc_params, const char *nam datatype->domain = parent->domain; parent->domain->u.file.ref_count++; + 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); + } + loc_info_out.URI = datatype->URI; loc_info_out.domain = datatype->domain; loc_info_out.GCPL_base64 = NULL; @@ -545,6 +601,7 @@ RV_datatype_close(void *dt, hid_t dxpl_id, void **req) if (RV_file_close(_dtype->domain, H5P_DEFAULT, NULL) < 0) FUNC_DONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file"); + RV_free(_dtype->handle_path); RV_free(_dtype); _dtype = NULL; diff --git a/src/rest_vol_file.c b/src/rest_vol_file.c index 9a164d27..07bab118 100644 --- a/src/rest_vol_file.c +++ b/src/rest_vol_file.c @@ -76,6 +76,7 @@ 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 = "/"; /* 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 @@ -343,7 +344,8 @@ 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 = "/"; + /* Store self-referential pointer in the domain field for this object * to simplify code for other types of objects */ diff --git a/src/rest_vol_group.c b/src/rest_vol_group.c index 49bd939a..0987662a 100644 --- a/src/rest_vol_group.c +++ b/src/rest_vol_group.c @@ -47,6 +47,8 @@ RV_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name size_t host_header_len = 0; size_t base64_buf_size = 0; size_t plist_nalloc = 0; + size_t path_size = 0; + size_t path_len = 0; char *host_header = NULL; char *create_request_body = NULL; char *path_dirname = NULL; @@ -81,6 +83,9 @@ RV_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name if (NULL == (new_group = (RV_object_t *)RV_malloc(sizeof(*new_group)))) FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTALLOC, NULL, "can't allocate space for group object"); + if (!parent->handle_path) + FUNC_GOTO_ERROR(H5E_SYM, H5E_BADVALUE, NULL, "parent object has NULL path"); + new_group->URI[0] = '\0'; new_group->obj_type = H5I_GROUP; new_group->u.group.gapl_id = FAIL; @@ -89,6 +94,33 @@ RV_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name new_group->domain = parent->domain; parent->domain->u.file.ref_count++; + 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); + } + + /* 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 */ @@ -336,7 +368,8 @@ RV_group_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, // char *base64_binary_gcpl = NULL; void *binary_gcpl = NULL; size_t *binary_gcpl_size = 0; - + size_t path_size = 0; + size_t path_len = 0; H5I_type_t obj_type = H5I_UNINIT; #ifdef RV_CONNECTOR_DEBUG @@ -351,6 +384,9 @@ RV_group_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, if (H5I_FILE != parent->obj_type && H5I_GROUP != parent->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object not a file or group"); + if (!parent->handle_path) + FUNC_GOTO_ERROR(H5E_SYM, H5E_BADVALUE, NULL, "parent object has NULL path"); + /* Allocate and setup internal Group struct */ if (NULL == (group = (RV_object_t *)RV_malloc(sizeof(*group)))) FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTALLOC, NULL, "can't allocate space for group object"); @@ -364,6 +400,32 @@ RV_group_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, group->domain = parent->domain; parent->domain->u.file.ref_count++; + 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); + } + /* Locate group and set domain */ loc_info_out.URI = group->URI; @@ -692,6 +754,8 @@ RV_group_close(void *grp, hid_t dxpl_id, void **req) FUNC_DONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file"); } + RV_free(_grp->handle_path); + RV_free(_grp); _grp = NULL; diff --git a/src/rest_vol_object.c b/src/rest_vol_object.c index bb008f9d..5a7ea3e1 100644 --- a/src/rest_vol_object.c +++ b/src/rest_vol_object.c @@ -275,8 +275,35 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file, group, dataset or committed datatype"); switch (args->op_type) { + case H5VL_OBJECT_GET_NAME: { + size_t copy_size = 0; + char *name = loc_obj->handle_path; + + if (!name) + FUNC_GOTO_ERROR(H5E_OBJECT, H5E_PATH, FAIL, "object has NULL name"); + + /* Only return the name if the user provided an allocate buffer */ + if (args->args.get_name.buf) { + /* Initialize entire buffer regardless of path size */ + memset(args->args.get_name.buf, 0, args->args.get_name.buf_size); + + /* If given an attribute, H5Iget_name returns the name of the object an attribute is attached to */ + if (loc_obj->obj_type == H5I_ATTR) + if ((name = loc_obj->u.attribute.parent_name) == NULL) + FUNC_GOTO_ERROR(H5E_OBJECT, H5E_BADVALUE, FAIL, "attribute parent has NULL name"); + + copy_size = (strlen(name) < args->args.get_name.buf_size - 1) ? strlen(name) : args->args.get_name.buf_size - 1; + strncpy(args->args.get_name.buf, name, copy_size); + args->args.get_name.buf[copy_size + 1] = '\0'; + } + + if (args->args.get_name.name_len) { + *args->args.get_name.name_len = strlen(name); + } + + } + break; case H5VL_OBJECT_GET_FILE: - case H5VL_OBJECT_GET_NAME: case H5VL_OBJECT_GET_TYPE: FUNC_GOTO_ERROR(H5E_OBJECT, H5E_UNSUPPORTED, FAIL, "unsupported object operation"); break;