From 9872181d09146b004136019cd566ea68840a8307 Mon Sep 17 00:00:00 2001 From: Matthew Larson Date: Wed, 18 Oct 2023 09:58:03 -0500 Subject: [PATCH] Make server URL file object local --- src/rest_vol.c | 129 +++++---------------------------------- src/rest_vol.h | 15 ++--- src/rest_vol_attr.c | 24 ++++++++ src/rest_vol_config.h.in | 12 ++-- src/rest_vol_dataset.c | 15 +++-- src/rest_vol_datatype.c | 4 ++ src/rest_vol_file.c | 85 ++++++++++++++------------ src/rest_vol_group.c | 7 +++ src/rest_vol_link.c | 36 ++++++++--- src/rest_vol_object.c | 21 +++++-- 10 files changed, 159 insertions(+), 189 deletions(-) diff --git a/src/rest_vol.c b/src/rest_vol.c index d34f79fc..99f3b8b4 100644 --- a/src/rest_vol.c +++ b/src/rest_vol.c @@ -68,11 +68,6 @@ char curl_err_buf[CURL_ERROR_SIZE]; */ struct curl_slist *curl_headers = NULL; -/* - * Saved copy of the base URL for operating on - */ -char *base_URL = NULL; - #ifdef RV_TRACK_MEM_USAGE /* * Counter to keep track of the currently allocated amount of bytes @@ -153,7 +148,7 @@ const char *server_version_keys[] = {"version", (const char *)0}; static herr_t H5_rest_init(hid_t vipl_id); static herr_t H5_rest_term(void); -static herr_t H5_rest_authenticate_with_AD(H5_rest_ad_info_t *ad_info); +static herr_t H5_rest_authenticate_with_AD(H5_rest_ad_info_t *ad_info, const char *base_URL); /* Introspection callbacks */ static herr_t H5_rest_get_conn_cls(void *obj, H5VL_get_conn_lvl_t lvl, const struct H5VL_class_t **conn_cls); @@ -600,12 +595,6 @@ H5_rest_term(void) if (!H5_rest_initialized_g) FUNC_GOTO_DONE(SUCCEED); - /* Free base URL */ - if (base_URL) { - RV_free(base_URL); - base_URL = NULL; - } - /* Free memory for cURL response buffer */ if (response_buffer.buffer) { RV_free(response_buffer.buffer); @@ -709,13 +698,12 @@ herr_t H5_rest_set_connection_information(server_info_t *server_info) { H5_rest_ad_info_t ad_info; - const char *URL; - size_t URL_len = 0; FILE *config_file = NULL; herr_t ret_value = SUCCEED; const char *username = NULL; const char *password = NULL; + const char *base_URL = NULL; memset(&ad_info, 0, sizeof(ad_info)); @@ -724,70 +712,12 @@ H5_rest_set_connection_information(server_info_t *server_info) * the environment. */ - if ((URL = getenv("HSDS_ENDPOINT"))) { - - if (!strncmp(URL, UNIX_SOCKET_PREFIX, strlen(UNIX_SOCKET_PREFIX))) { - /* This is just a placeholder URL for curl's syntax, its specific value is unimportant */ - URL = "0"; - URL_len = 1; - - if (!base_URL || (0 != (strncmp(base_URL, URL, strlen(URL))))) { - - /* If previous value is incorrect, reassign */ - if (base_URL) { - free(base_URL); - base_URL = NULL; - } - - if (NULL == (base_URL = (char *)RV_malloc(URL_len + 1))) - FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, - "can't allocate space necessary for placeholder base URL"); - - strncpy(base_URL, URL, URL_len); - base_URL[URL_len] = '\0'; - } - } - else { - /* - * Save a copy of the base URL being worked on so that operations like - * creating a Group can be redirected to "base URL"/groups by building - * off of the base URL supplied. - */ - URL_len = strlen(URL); - - if (!base_URL || (0 != (strncmp(base_URL, URL, strlen(URL))))) { - - /* If previous value is incorrect, reassign */ - if (base_URL) { - free(base_URL); - base_URL = NULL; - } - - if (NULL == (base_URL = (char *)RV_malloc(URL_len + 1))) - FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, - "can't allocate space necessary for placeholder base URL"); - - strncpy(base_URL, URL, URL_len); - base_URL[URL_len] = '\0'; - } - } + if (base_URL = getenv("HSDS_ENDPOINT")) { username = getenv("HSDS_USERNAME"); password = getenv("HSDS_PASSWORD"); - if (username || password) { - /* Attempt to set authentication information */ - if (username && strlen(username)) { - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, username)) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_CANTSET, FAIL, "can't set username: %s", curl_err_buf); - } /* end if */ - - if (password && strlen(password)) { - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, password)) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_CANTSET, FAIL, "can't set password: %s", curl_err_buf); - } /* end if */ - } /* end if */ - else { + if (!username && !password) { const char *clientID = getenv("HSDS_AD_CLIENT_ID"); const char *tenantID = getenv("HSDS_AD_TENANT_ID"); const char *resourceID = getenv("HSDS_AD_RESOURCE_ID"); @@ -805,7 +735,7 @@ H5_rest_set_connection_information(server_info_t *server_info) } /* end if */ /* Attempt authentication with Active Directory */ - if (H5_rest_authenticate_with_AD(&ad_info) < 0) + if (H5_rest_authenticate_with_AD(&ad_info, base_URL) < 0) FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't authenticate with Active Directory"); } /* end else */ } /* end if */ @@ -881,43 +811,9 @@ H5_rest_set_connection_information(server_info_t *server_info) if (!strcmp(key, "hs_endpoint")) { if (val) { - /* - * Save a copy of the base URL being worked on so that operations like - * creating a Group can be redirected to "base URL"/groups by building - * off of the base URL supplied. - */ - URL_len = strlen(val); - - if (!base_URL || (0 != (strncmp(base_URL, val, URL_len)))) { - - /* If previous value is incorrect, reassign */ - if (base_URL) { - free(base_URL); - base_URL = NULL; - } - - if (NULL == (base_URL = (char *)RV_malloc(URL_len + 1))) - FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTALLOC, FAIL, - "can't allocate space necessary for placeholder base URL"); - - strncpy(base_URL, val, URL_len); - base_URL[URL_len] = '\0'; - } - + base_URL = val; } /* end if */ } /* end if */ - else if (!strcmp(key, "hs_username")) { - if (val && strlen(val)) { - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, val)) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_CANTSET, FAIL, "can't set username: %s", curl_err_buf); - } /* end if */ - } /* end else if */ - else if (!strcmp(key, "hs_password")) { - if (val && strlen(val)) { - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, val)) - FUNC_GOTO_ERROR(H5E_ARGS, H5E_CANTSET, FAIL, "can't set password: %s", curl_err_buf); - } /* end if */ - } /* end else if */ else if (!strcmp(key, "hs_ad_app_id")) { if (val && strlen(val)) strncpy(ad_info.clientID, val, sizeof(ad_info.clientID) - 1); @@ -940,7 +836,7 @@ H5_rest_set_connection_information(server_info_t *server_info) /* Attempt authentication with Active Directory if ID values are present */ if (ad_info.clientID[0] != '\0' && ad_info.tenantID[0] != '\0' && ad_info.resourceID[0] != '\0') - if (H5_rest_authenticate_with_AD(&ad_info) < 0) + if (!base_URL || (H5_rest_authenticate_with_AD(&ad_info, base_URL) < 0)) FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't authenticate with Active Directory"); } /* end else */ @@ -965,8 +861,9 @@ H5_rest_set_connection_information(server_info_t *server_info) strcpy(server_info->password, password); } - if ((server_info->base_URL = RV_calloc(strlen(base_URL) + 1)) == NULL) { - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate space for URL"); + if (base_URL) { + if ((server_info->base_URL = RV_calloc(strlen(base_URL) + 1)) == NULL) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate space for URL"); strcpy(server_info->base_URL, base_URL); } @@ -1010,7 +907,7 @@ H5_rest_set_connection_information(server_info_t *server_info) *------------------------------------------------------------------------- */ static herr_t -H5_rest_authenticate_with_AD(H5_rest_ad_info_t *ad_info) +H5_rest_authenticate_with_AD(H5_rest_ad_info_t *ad_info, const char *base_URL) { const char *access_token_key[] = {"access_token", (const char *)0}; const char *refresh_token_key[] = {"refresh_token", (const char *)0}; @@ -2076,6 +1973,7 @@ RV_find_object_by_path(RV_object_t *parent_obj, const char *obj_path, H5I_type_t char *url_encoded_path_name = NULL; const char *ext_filename = NULL; const char *ext_obj_path = NULL; + const char *base_URL; char request_url[URL_MAX_LENGTH]; long http_response; int url_len = 0; @@ -2092,7 +1990,8 @@ RV_find_object_by_path(RV_object_t *parent_obj, const char *obj_path, H5I_type_t if (H5I_FILE != parent_obj->obj_type && H5I_GROUP != parent_obj->obj_type && H5I_DATATYPE != parent_obj->obj_type && H5I_DATASET != parent_obj->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent object not a file, group, datatype or dataset"); - + if ((base_URL = parent_obj->domain->u.file.server_info.base_URL) == NULL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent object does not have valid server URL"); #ifdef RV_CONNECTOR_DEBUG printf("-> Finding object by path '%s' from parent object of type %s with URI %s\n\n", obj_path, object_type_to_string(parent_obj->obj_type), parent_obj->URI); diff --git a/src/rest_vol.h b/src/rest_vol.h index 53eef39d..913f8bd4 100644 --- a/src/rest_vol.h +++ b/src/rest_vol.h @@ -375,11 +375,6 @@ extern struct curl_slist *curl_headers; */ #define CURL_RESPONSE_BUFFER_DEFAULT_SIZE 1024 -/* - * Saved copy of the base URL for operating on - */ -extern char *base_URL; - #ifdef RV_TRACK_MEM_USAGE /* * Counter to keep track of the currently allocated amount of bytes @@ -490,7 +485,8 @@ typedef struct server_api_version { size_t patch; } server_api_version; -// TODO +/* Structure containing information to connect to and evaluate + * features of a server */ typedef struct server_info_t { char *username; char *password; @@ -507,10 +503,9 @@ typedef struct server_info_t { typedef struct RV_object_t RV_object_t; typedef struct RV_file_t { - unsigned intent; - unsigned ref_count; - char *filepath_name; - /* TODO - Username/password in global curl handle are still used for now */ + unsigned intent; + unsigned ref_count; + char *filepath_name; server_info_t server_info; hid_t fcpl_id; hid_t fapl_id; diff --git a/src/rest_vol_attr.c b/src/rest_vol_attr.c index bef1963f..4d331b24 100644 --- a/src/rest_vol_attr.c +++ b/src/rest_vol_attr.c @@ -68,6 +68,7 @@ RV_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_ char *url_encoded_attr_name = NULL; int create_request_body_len = 0; int url_len = 0; + const char *base_URL = NULL; void *ret_value = NULL; #ifdef RV_CONNECTOR_DEBUG @@ -97,6 +98,9 @@ RV_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_ H5I_DATASET != parent->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object not a file, group, datatype or dataset"); + if ((base_URL = parent->domain->u.file.server_info.base_URL) == NULL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object does not have valid server URL"); + /* Check for write access */ if (!(parent->domain->u.file.intent & H5F_ACC_RDWR)) FUNC_GOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "no write intent on file"); @@ -434,6 +438,7 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na char request_url[URL_MAX_LENGTH]; char *url_encoded_attr_name = NULL; const char *parent_obj_type_header = NULL; + const char *base_URL = NULL; int url_len = 0; void *ret_value = NULL; @@ -467,6 +472,9 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na H5I_DATASET != parent->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object not a file, group, datatype or dataset"); + if ((base_URL = parent->domain->u.file.server_info.base_URL) == NULL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object does not have valid server URL"); + if (aapl_id == H5I_INVALID_HID) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid AAPL"); @@ -831,6 +839,7 @@ RV_attr_read(void *attr, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req) char *host_header = NULL; char *url_encoded_attr_name = NULL; char request_url[URL_MAX_LENGTH]; + const char *base_URL = NULL; int url_len = 0; herr_t ret_value = SUCCEED; @@ -847,6 +856,9 @@ RV_attr_read(void *attr, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req) if (!buf) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "read buffer was NULL"); + if ((base_URL = attribute->domain->u.file.server_info.base_URL) == NULL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "attribute does not have valid server URL"); + /* Determine whether it's possible to receive the data as a binary blob instead of as JSON */ if (H5T_NO_CLASS == (dtype_class = H5Tget_class(dtype_id))) FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, "memory datatype is invalid"); @@ -1024,6 +1036,7 @@ RV_attr_write(void *attr, hid_t dtype_id, const void *buf, hid_t dxpl_id, void * char *host_header = NULL; char *url_encoded_attr_name = NULL; char request_url[URL_MAX_LENGTH]; + const char *base_URL = NULL; int url_len = 0; herr_t ret_value = SUCCEED; @@ -1040,6 +1053,9 @@ RV_attr_write(void *attr, hid_t dtype_id, const void *buf, hid_t dxpl_id, void * if (!buf) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "write buffer was NULL"); + if ((base_URL = attribute->domain->u.file.server_info.base_URL) == NULL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "attribute does not have valid server URL"); + /* Check for write access */ if (!(attribute->domain->u.file.intent & H5F_ACC_RDWR)) FUNC_GOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "no write intent on file"); @@ -1237,6 +1253,7 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) int url_len = 0; const char *parent_obj_type_header = NULL; const char *request_idx_type = NULL; + const char *base_URL = NULL; herr_t ret_value = SUCCEED; #ifdef RV_CONNECTOR_DEBUG @@ -1249,6 +1266,9 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent object not an attribute, file, group, datatype or dataset"); + if ((base_URL = loc_obj->domain->u.file.server_info.base_URL) == NULL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "location object does not have valid server URL"); + switch (args->op_type) { /* H5Aget_create_plist */ case H5VL_ATTR_GET_ACPL: { @@ -1859,6 +1879,7 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci char attr_name_to_delete[ATTRIBUTE_NAME_MAX_LENGTH]; char *url_encoded_attr_name = NULL; const char *parent_obj_type_header = NULL; + const char *base_URL = NULL; int url_len = 0; herr_t ret_value = SUCCEED; @@ -1871,6 +1892,9 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci H5I_DATATYPE != loc_obj->obj_type && H5I_DATASET != loc_obj->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent object not a file, group, datatype or dataset"); + if ((base_URL = loc_obj->domain->u.file.server_info.base_URL) == NULL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "location object does not have valid server URL"); + switch (args->op_type) { /* H5Adelete (_by_name/_by_idx) */ case H5VL_ATTR_DELETE_BY_IDX: { diff --git a/src/rest_vol_config.h.in b/src/rest_vol_config.h.in index 5e0997d4..fe6e7dca 100644 --- a/src/rest_vol_config.h.in +++ b/src/rest_vol_config.h.in @@ -126,13 +126,13 @@ /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif +#if defined __BIG_ENDIAN__ +#define WORDS_BIGENDIAN 1 +#endif #else -# ifndef WORDS_BIGENDIAN -# undef WORDS_BIGENDIAN -# endif +#ifndef WORDS_BIGENDIAN +#undef WORDS_BIGENDIAN +#endif #endif /* Define to empty if `const' does not conform to ANSI C. */ diff --git a/src/rest_vol_dataset.c b/src/rest_vol_dataset.c index b09b9fa2..bf46173e 100644 --- a/src/rest_vol_dataset.c +++ b/src/rest_vol_dataset.c @@ -136,6 +136,7 @@ RV_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *na char *host_header = NULL; char *create_request_body = NULL; char request_url[URL_MAX_LENGTH]; + const char *base_URL = NULL; int url_len = 0; void *ret_value = NULL; @@ -153,6 +154,8 @@ RV_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *na 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 ((base_URL = parent->domain->u.file.server_info.base_URL) == NULL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object does not have valid server URL"); /* Check for write access */ if (!(parent->domain->u.file.intent & H5F_ACC_RDWR)) @@ -651,7 +654,8 @@ RV_dataset_read(size_t count, void *dset[], hid_t mem_type_id[], hid_t _mem_spac /* Redirect cURL from the base URL to "/datasets//value" to get the dataset data values */ if ((url_len = snprintf(transfer_info[i].request_url, URL_MAX_LENGTH, "%s/datasets/%s/value%s%s", - base_URL, transfer_info[i].dataset->URI, + transfer_info[i].dataset->domain->u.file.server_info.base_URL, + transfer_info[i].dataset->URI, is_transfer_binary && transfer_info[i].selection_body && (H5S_SEL_POINTS != transfer_info[i].u.read_info.sel_type) ? "?select=" @@ -1052,8 +1056,8 @@ RV_dataset_write(size_t count, void *dset[], hid_t mem_type_id[], hid_t _mem_spa /* Redirect cURL from the base URL to "/datasets//value" to write the value out */ if ((url_len = snprintf( - transfer_info[i].request_url, URL_MAX_LENGTH, "%s/datasets/%s/value%s%s", base_URL, - transfer_info[i].dataset->URI, + transfer_info[i].request_url, URL_MAX_LENGTH, "%s/datasets/%s/value%s%s", + transfer_info[i].dataset->domain->u.file.server_info.base_URL, transfer_info[i].dataset->URI, is_transfer_binary && selection_body && (H5S_SEL_POINTS != sel_type) ? "?select=" : "", is_transfer_binary && selection_body && (H5S_SEL_POINTS != sel_type) ? selection_body : "")) < 0) @@ -1242,6 +1246,7 @@ RV_dataset_get(void *obj, H5VL_dataset_get_args_t *args, hid_t dxpl_id, void **r size_t host_header_len = 0; char *host_header = NULL; char request_url[URL_MAX_LENGTH]; + const char *base_URL = NULL; #ifdef RV_CONNECTOR_DEBUG printf("-> Received dataset get call with following parameters:\n"); @@ -1253,6 +1258,8 @@ RV_dataset_get(void *obj, H5VL_dataset_get_args_t *args, hid_t dxpl_id, void **r if (H5I_DATASET != dset->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a dataset"); + if ((base_URL = dset->domain->u.file.server_info.base_URL) == NULL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataset does not have valid server URL"); switch (args->op_type) { /* H5Dget_access_plist */ @@ -1293,7 +1300,7 @@ RV_dataset_get(void *obj, H5VL_dataset_get_args_t *args, hid_t dxpl_id, void **r /* H5Dget_storage_size */ case H5VL_DATASET_GET_STORAGE_SIZE: - if (!(SERVER_VERSION_SUPPORTS_GET_STORAGE_SIZE(dset->domain->u.file.server_version))) + if (!(SERVER_VERSION_SUPPORTS_GET_STORAGE_SIZE(dset->domain->u.file.server_info.version))) FUNC_GOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "H5Dget_storage_size requires HSDS 0.8.5 or higher"); diff --git a/src/rest_vol_datatype.c b/src/rest_vol_datatype.c index edc48515..37a18721 100644 --- a/src/rest_vol_datatype.c +++ b/src/rest_vol_datatype.c @@ -74,6 +74,7 @@ RV_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *n size_t datatype_body_len = 0; size_t path_size = 0; size_t path_len = 0; + const char *base_URL = NULL; char *host_header = NULL; char *commit_request_body = NULL; char *datatype_body = NULL; @@ -102,6 +103,9 @@ RV_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *n 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 ((base_URL = parent->domain->u.file.server_info.base_URL) == NULL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object does not have valid server URL"); + /* Check for write access */ if (!(parent->domain->u.file.intent & H5F_ACC_RDWR)) FUNC_GOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "no write intent on file"); diff --git a/src/rest_vol_file.c b/src/rest_vol_file.c index 7546ff7c..53c251f6 100644 --- a/src/rest_vol_file.c +++ b/src/rest_vol_file.c @@ -143,7 +143,7 @@ RV_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, h FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL password: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, base_URL)) + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, new_file->u.file.server_info.base_URL)) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL request URL: %s", curl_err_buf); /* Before making the actual request, check the file creation flags for @@ -390,13 +390,13 @@ RV_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, voi FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL username: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, file->u.file.server_info.password)) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL password: %s", curl_err_buf); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, file->u.file.server_info.base_URL)) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL request URL: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set up cURL to make HTTP GET request: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, base_URL)) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set cURL request URL: %s", curl_err_buf); #ifdef RV_CONNECTOR_DEBUG printf("-> Retrieving info for file open\n\n"); @@ -624,14 +624,15 @@ RV_file_get(void *obj, H5VL_file_get_args_t *args, hid_t dxpl_id, void **req) herr_t RV_file_specific(void *obj, H5VL_file_specific_args_t *args, hid_t dxpl_id, void **req) { - RV_object_t *file = (RV_object_t *)obj; - herr_t ret_value = SUCCEED; - size_t host_header_len; - size_t name_length; - long http_response; - char *host_header = NULL; - const char *filename = NULL; - char *request_url = NULL; + RV_object_t *file = (RV_object_t *)obj; + herr_t ret_value = SUCCEED; + size_t host_header_len; + size_t name_length; + long http_response; + char *host_header = NULL; + const char *filename = NULL; + char *request_url = NULL; + server_info_t *server_info = NULL; #ifdef RV_CONNECTOR_DEBUG printf("-> Received file-specific call with following parameters:\n"); @@ -671,10 +672,12 @@ RV_file_specific(void *obj, H5VL_file_specific_args_t *args, hid_t dxpl_id, void /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); - if (NULL == (request_url = (char *)RV_malloc(strlen(flush_string) + strlen(base_URL) + 1))) + if (NULL == (request_url = (char *)RV_malloc( + strlen(flush_string) + strlen(target_domain->u.file.server_info.base_URL) + 1))) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate space for request URL"); - snprintf(request_url, URL_MAX_LENGTH, "%s%s", base_URL, flush_string); + snprintf(request_url, URL_MAX_LENGTH, "%s%s", target_domain->u.file.server_info.base_URL, + flush_string); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, file->u.file.server_info.username)) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); @@ -759,18 +762,22 @@ RV_file_specific(void *obj, H5VL_file_specific_args_t *args, hid_t dxpl_id, void /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); - /* TODO - H5Fdelete doesn't receive a file handle, so the username/password can't be pulled from - * it */ - /* - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, - file->domain->u.file.server_info.username)) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't - set cURL username: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, - file->domain->u.file.server_info.password)) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't - set cURL password: %s", curl_err_buf); - */ + /* H5Fdelete doesn't receive a file handle, so the username/password must be pulled + * from environment for now */ + if ((server_info = RV_calloc(sizeof(server_info_t))) == NULL) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate space for server information"); + + if (H5_rest_set_connection_information(server_info) < 0) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get server connection information"); + + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, server_info->username)) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, server_info->password)) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set cURL password: %s", curl_err_buf); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, base_URL)) + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, server_info->base_URL)) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE")) @@ -810,6 +817,13 @@ RV_file_specific(void *obj, H5VL_file_specific_args_t *args, hid_t dxpl_id, void if (request_url) RV_free(request_url); + if (server_info) { + RV_free(server_info->base_URL); + RV_free(server_info->username); + RV_free(server_info->password); + RV_free(server_info); + } + return ret_value; } /* end RV_file_specific() */ @@ -864,25 +878,16 @@ RV_file_close(void *file, hid_t dxpl_id, void **req) _file->u.file.filepath_name = NULL; } - if (_file->u.file.server_info.username) { - RV_free(_file->u.file.server_info.username); - _file->u.file.server_info.username; - } - - if (_file->u.file.server_info.password) { - RV_free(_file->u.file.server_info.password); - _file->u.file.server_info.password; - } + RV_free(_file->u.file.server_info.username); + RV_free(_file->u.file.server_info.password); + RV_free(_file->u.file.server_info.base_URL); - if (_file->u.file.server_info.base_URL) { - RV_free(_file->u.file.server_info.base_URL); - _file->u.file.server_info.base_URL; - } + _file->u.file.server_info.username = NULL; + _file->u.file.server_info.password = NULL; + _file->u.file.server_info.base_URL = NULL; - if (_file->handle_path) { - RV_free(_file->handle_path); - _file->handle_path = NULL; - } + RV_free(_file->handle_path); + _file->handle_path = NULL; RV_free(_file); } diff --git a/src/rest_vol_group.c b/src/rest_vol_group.c index f3319b7f..8f795170 100644 --- a/src/rest_vol_group.c +++ b/src/rest_vol_group.c @@ -49,6 +49,7 @@ RV_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name size_t plist_nalloc = 0; size_t path_size = 0; size_t path_len = 0; + const char *base_URL = NULL; char *host_header = NULL; char *create_request_body = NULL; char *path_dirname = NULL; @@ -75,6 +76,9 @@ RV_group_create(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 ((base_URL = parent->domain->u.file.server_info.base_URL) == NULL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "parent object does not have valid server URL"); + if (gapl_id == H5I_INVALID_HID) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid GAPL"); @@ -486,6 +490,7 @@ RV_group_get(void *obj, H5VL_group_get_args_t *args, hid_t dxpl_id, void **req) char *host_header = NULL; char request_url[URL_MAX_LENGTH]; int url_len = 0; + const char *base_URL = NULL; herr_t ret_value = SUCCEED; loc_info loc_info_out; @@ -498,6 +503,8 @@ RV_group_get(void *obj, H5VL_group_get_args_t *args, hid_t dxpl_id, void **req) if (H5I_FILE != loc_obj->obj_type && H5I_GROUP != loc_obj->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a group"); + if ((base_URL = loc_obj->domain->u.file.server_info.base_URL) == NULL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent object does not have valid server URL"); switch (args->op_type) { /* H5Gget_create_plist */ diff --git a/src/rest_vol_link.c b/src/rest_vol_link.c index 032cad8d..5d0f1f87 100644 --- a/src/rest_vol_link.c +++ b/src/rest_vol_link.c @@ -31,7 +31,8 @@ static herr_t RV_link_iter_callback(char *HTTP_response, void *callback_data_in, /* Helper functions to work with a table of links for link iteration */ static herr_t RV_build_link_table(char *HTTP_response, hbool_t is_recursive, int (*sort_func)(const void *, const void *), link_table_entry **link_table, - size_t *num_entries, rv_hash_table_t *visited_link_table); + size_t *num_entries, rv_hash_table_t *visited_link_table, + const char *base_URL); static void RV_free_link_table(link_table_entry *link_table, size_t num_entries); static herr_t RV_traverse_link_table(link_table_entry *link_table, size_t num_entries, iter_data *iter_data, const char *cur_link_rel_path); @@ -74,6 +75,7 @@ RV_link_create(H5VL_link_create_args_t *args, void *obj, const H5VL_loc_params_t size_t create_request_nalloc = 0; size_t host_header_len = 0; void *hard_link_target_obj; + const char *base_URL = NULL; char *host_header = NULL; char *create_request_body = NULL; char request_url[URL_MAX_LENGTH]; @@ -94,7 +96,6 @@ RV_link_create(H5VL_link_create_args_t *args, void *obj, const H5VL_loc_params_t printf(" - Default LCPL? %s\n", (H5P_LINK_CREATE_DEFAULT == lcpl_id) ? "yes" : "no"); printf(" - Default LAPL? %s\n\n", (H5P_LINK_ACCESS_DEFAULT == lapl_id) ? "yes" : "no"); #endif - if (lcpl_id == H5I_INVALID_HID) FUNC_GOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "invalid LCPL"); @@ -120,6 +121,12 @@ RV_link_create(H5VL_link_create_args_t *args, void *obj, const H5VL_loc_params_t new_link_loc_obj = (RV_object_t *)hard_link_target_obj; } /* end if */ + if (new_link_loc_obj && ((base_URL = new_link_loc_obj->domain->u.file.server_info.base_URL) == NULL)) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "location object does not have valid server URL"); + + if (!base_URL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "link creation requires valid server URL"); + /* Validate loc_id and check for write access on the file */ if (H5I_FILE != new_link_loc_obj->obj_type && H5I_GROUP != new_link_loc_obj->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "link location object not a file or group"); @@ -467,6 +474,7 @@ RV_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_args_t RV_object_t *loc_obj = (RV_object_t *)obj; hbool_t empty_dirname; size_t host_header_len = 0; + const char *base_URL = NULL; char *host_header = NULL; char *link_dir_name = NULL; char *url_encoded_link_name = NULL; @@ -483,6 +491,9 @@ RV_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_args_t printf(" - Link loc_obj's domain path: %s\n\n", loc_obj->domain->u.file.filepath_name); #endif + if ((base_URL = loc_obj->domain->u.file.server_info.base_URL) == NULL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "location object does not have valid server URL"); + switch (args->op_type) { /* H5Lget_info */ case H5VL_LINK_GET_INFO: { @@ -628,7 +639,7 @@ RV_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_args_t by_idx_data.idx_p = &loc_params->loc_data.loc_by_idx.n; by_idx_data.iter_function.link_iter_op = NULL; by_idx_data.op_data = NULL; - + by_idx_data.iter_obj_parent = loc_obj; /* * Setup information to be passed back from link name retrieval callback */ @@ -866,6 +877,7 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci size_t host_header_len = 0; hid_t link_iter_group_id = H5I_INVALID_HID; void *link_iter_group_object = NULL; + const char *base_URL = NULL; char *host_header = NULL; char *link_path_dirname = NULL; char temp_URI[URI_MAX_LENGTH]; @@ -885,6 +897,9 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci if (H5I_FILE != loc_obj->obj_type && H5I_GROUP != loc_obj->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parent object not a file or group"); + if ((base_URL = loc_obj->domain->u.file.server_info.base_URL) == NULL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "location object does not have valid server URL"); + switch (args->op_type) { /* H5Ldelete */ case H5VL_LINK_DELETE: { @@ -1090,6 +1105,7 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci link_iter_data.idx_p = args->args.iterate.idx_p; link_iter_data.iter_function.link_iter_op = args->args.iterate.op; link_iter_data.op_data = args->args.iterate.op_data; + link_iter_data.iter_obj_parent = loc_obj; if (!link_iter_data.iter_function.link_iter_op) FUNC_GOTO_ERROR(H5E_LINK, H5E_LINKITERERROR, FAIL, "no link iteration function specified"); @@ -1666,7 +1682,8 @@ RV_get_link_name_by_idx_callback(char *HTTP_response, void *callback_data_in, vo #endif if (RV_build_link_table(HTTP_response, by_idx_data->is_recursive, link_table_sort_func, &link_table, - &link_table_num_entries, NULL) < 0) + &link_table_num_entries, NULL, + by_idx_data->iter_obj_parent->domain->u.file.server_info.base_URL) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTBUILDLINKTABLE, FAIL, "can't build link table"); /* Check to make sure the index given is within bounds */ @@ -1765,7 +1782,8 @@ RV_link_iter_callback(char *HTTP_response, void *callback_data_in, void *callbac */ if (RV_build_link_table(HTTP_response, link_iter_data->is_recursive, H5_rest_cmp_links_by_creation_order_inc, &link_table, &link_table_num_entries, - visited_link_table) < 0) + visited_link_table, + link_iter_data->iter_obj_parent->domain->u.file.server_info.base_URL) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTBUILDLINKTABLE, FAIL, "can't build link table"); #ifdef RV_CONNECTOR_DEBUG @@ -1774,7 +1792,8 @@ RV_link_iter_callback(char *HTTP_response, void *callback_data_in, void *callbac } /* end if */ else { if (RV_build_link_table(HTTP_response, link_iter_data->is_recursive, NULL, &link_table, - &link_table_num_entries, visited_link_table) < 0) + &link_table_num_entries, visited_link_table, + link_iter_data->iter_obj_parent->domain->u.file.server_info.base_URL) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTBUILDLINKTABLE, FAIL, "can't build link table"); } /* end else */ @@ -1827,7 +1846,8 @@ RV_link_iter_callback(char *HTTP_response, void *callback_data_in, void *callbac */ static herr_t RV_build_link_table(char *HTTP_response, hbool_t is_recursive, int (*sort_func)(const void *, const void *), - link_table_entry **link_table, size_t *num_entries, rv_hash_table_t *visited_link_table) + link_table_entry **link_table, size_t *num_entries, rv_hash_table_t *visited_link_table, + const char *base_URL) { link_table_entry *table = NULL; yajl_val parse_tree = NULL, key_obj; @@ -2024,7 +2044,7 @@ RV_build_link_table(char *HTTP_response, hbool_t is_recursive, int (*sort_func)( if (RV_build_link_table(response_buffer.buffer, is_recursive, sort_func, &table[i].subgroup.subgroup_link_table, - &table[i].subgroup.num_entries, visited_link_table) < 0) + &table[i].subgroup.num_entries, visited_link_table, base_URL) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTBUILDLINKTABLE, FAIL, "can't build link table for subgroup '%s'", table[i].link_name); diff --git a/src/rest_vol_object.c b/src/rest_vol_object.c index b3587c29..e69cad47 100644 --- a/src/rest_vol_object.c +++ b/src/rest_vol_object.c @@ -270,6 +270,7 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar char *host_header = NULL; char request_url[URL_MAX_LENGTH]; char *found_object_name = NULL; + const char *base_URL = NULL; int url_len = 0; herr_t ret_value = SUCCEED; loc_info loc_info_out; @@ -290,6 +291,9 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar H5I_DATATYPE != loc_obj->obj_type && H5I_DATASET != loc_obj->obj_type) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file, group, dataset or committed datatype"); + if ((base_URL = loc_obj->domain->u.file.server_info.base_URL) == NULL) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "location object does not have valid server URL"); + switch (args->op_type) { case H5VL_OBJECT_GET_NAME: { size_t copy_size = 0; @@ -1037,7 +1041,8 @@ RV_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_s /* To build object table, information about parent object will be needed */ object_iter_data.iter_obj_parent = iter_object; - if (url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/%s/%s", base_URL, object_type_header, + if (url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/%s/%s", + iter_object->domain->u.file.server_info.base_URL, object_type_header, object_iter_data.iter_obj_parent->URI) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); @@ -1151,9 +1156,11 @@ RV_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_s switch (iter_object_type) { case H5I_FILE: case H5I_GROUP: - if (url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/%s/%s%s", base_URL, - object_type_header, object_iter_data.iter_obj_parent->URI, - (!strcmp(object_type_header, "groups") ? "/links" : "")) < 0) + if (url_len = + snprintf(request_url, URL_MAX_LENGTH, "%s/%s/%s%s", + object_iter_data.iter_obj_parent->domain->u.file.server_info.base_URL, + object_type_header, object_iter_data.iter_obj_parent->URI, + (!strcmp(object_type_header, "groups") ? "/links" : "")) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) @@ -1782,8 +1789,10 @@ RV_build_object_table(char *HTTP_response, hbool_t is_recursive, int (*sort_func curl, H5_rest_basename(YAJL_GET_STRING(link_field_obj)), 0))) FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTENCODE, FAIL, "can't URL-encode link name"); - if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/links", base_URL, - url_encoded_link_name)) < 0) + if ((url_len = + snprintf(request_url, URL_MAX_LENGTH, "%s/groups/%s/links", + object_iter_data->iter_obj_parent->domain->u.file.server_info.base_URL, + url_encoded_link_name)) < 0) FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "snprintf error"); if (url_len >= URL_MAX_LENGTH)