From ea87fc8717c34dd376844389fe370ab6d8eec1b1 Mon Sep 17 00:00:00 2001 From: Matthew Larson Date: Thu, 12 Oct 2023 16:41:28 -0500 Subject: [PATCH 1/5] Make server connection info file-local H5Fdelete doesn't receive file information besides the name, so this may be a non-starter. --- src/rest_vol.c | 94 ++++++++++++++++++++++++++------ src/rest_vol.h | 25 ++++++--- src/rest_vol_attr.c | 118 ++++++++++++++++++++++++++++++++++++---- src/rest_vol_dataset.c | 20 +++++-- src/rest_vol_datatype.c | 10 +++- src/rest_vol_file.c | 52 +++++++++++++++--- src/rest_vol_group.c | 22 ++++++-- src/rest_vol_link.c | 44 ++++++++++++++- src/rest_vol_object.c | 83 ++++++++++++++++++++++++---- 9 files changed, 397 insertions(+), 71 deletions(-) diff --git a/src/rest_vol.c b/src/rest_vol.c index 39e84c36..dba1eb1b 100644 --- a/src/rest_vol.c +++ b/src/rest_vol.c @@ -684,8 +684,9 @@ H5Pset_fapl_rest_vol(hid_t fapl_id) if ((ret_value = H5Pset_vol(fapl_id, H5_rest_id_g, NULL)) < 0) FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't set REST VOL connector in FAPL"); - if (H5_rest_set_connection_information() < 0) - FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't set REST VOL connector connection information"); + // now always handled at file open/create time + // if (H5_rest_set_connection_information() < 0) + // FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't set REST VOL connector connection information"); done: PRINT_ERROR_STACK; @@ -725,7 +726,7 @@ H5rest_get_object_uri(hid_t obj_id) * June, 2018 */ herr_t -H5_rest_set_connection_information(void) +H5_rest_set_connection_information(server_info_t *server_info) { H5_rest_ad_info_t ad_info; const char *URL; @@ -733,6 +734,12 @@ H5_rest_set_connection_information(void) FILE *config_file = NULL; herr_t ret_value = SUCCEED; + const char *username = NULL; + const char *password = NULL; + + const char *username = NULL; + const char *password = NULL; + if (base_URL) FUNC_GOTO_DONE(SUCCEED); @@ -771,8 +778,8 @@ H5_rest_set_connection_information(void) strcpy(base_URL, URL); } - const char *username = getenv("HSDS_USERNAME"); - const char *password = getenv("HSDS_PASSWORD"); + username = getenv("HSDS_USERNAME"); + password = getenv("HSDS_PASSWORD"); if (username || password) { /* Attempt to set authentication information */ @@ -938,10 +945,44 @@ H5_rest_set_connection_information(void) "must specify a base URL - please set HSDS_ENDPOINT environment variable or create a " "config file"); + /* Copy server information */ + if (server_info) { + if (username) { + if ((server_info->username = RV_calloc(strlen(username) + 1)) == NULL) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate space for username"); + + strcpy(server_info->username, username); + } + + if (password) { + if ((server_info->password = RV_calloc(strlen(password) + 1)) == NULL) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate space for password"); + + 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"); + + strcpy(server_info->base_URL, base_URL); + } + } + done: if (config_file) fclose(config_file); + if (ret_value < 0 && server_info) { + RV_free(server_info->username); + server_info->username = NULL; + + RV_free(server_info->password); + server_info->password = NULL; + + RV_free(server_info->base_URL); + server_info->base_URL = NULL; + } + PRINT_ERROR_STACK; return ret_value; @@ -2053,7 +2094,7 @@ RV_find_object_by_path(RV_object_t *parent_obj, const char *obj_path, H5I_type_t object_type_to_string(parent_obj->obj_type), parent_obj->URI); #endif - version = parent_obj->domain->u.file.server_version; + version = parent_obj->domain->u.file.server_info.version; /* In order to not confuse the server, make sure the path has no leading spaces */ while (*obj_path == ' ') @@ -2438,10 +2479,11 @@ RV_parse_creation_properties_callback(yajl_val parse_tree, char **GCPL_buf_out) herr_t RV_copy_object_loc_info_callback(char *HTTP_response, void *callback_data_in, void *callback_data_out) { - yajl_val parse_tree = NULL, key_obj; - char *parsed_string; - loc_info *loc_info_out = (loc_info *)callback_data_out; - herr_t ret_value = SUCCEED; + yajl_val parse_tree = NULL, key_obj; + char *parsed_string; + loc_info *loc_info_out = (loc_info *)callback_data_out; + server_info_t *server_info = (server_info_t *)callback_data_in; + herr_t ret_value = SUCCEED; char *GCPL_buf = NULL; @@ -2458,6 +2500,8 @@ RV_copy_object_loc_info_callback(char *HTTP_response, void *callback_data_in, vo FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "HTTP response buffer was NULL"); if (!loc_info_out) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "output buffer was NULL"); + if (!server_info) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "server info was NULL"); if (NULL == (parse_tree = yajl_tree_parse(HTTP_response, NULL, 0))) FUNC_GOTO_ERROR(H5E_OBJECT, H5E_PARSEERROR, FAIL, "parsing JSON failed"); @@ -2519,14 +2563,28 @@ RV_copy_object_loc_info_callback(char *HTTP_response, void *callback_data_in, vo FUNC_GOTO_ERROR(H5E_CALLBACK, H5E_CANTALLOC, FAIL, "failed to allocate memory for new domain path"); - strncpy(new_domain->u.file.filepath_name, found_domain.u.file.filepath_name, - strlen(found_domain.u.file.filepath_name) + 1); + strcpy(new_domain->u.file.filepath_name, found_domain.u.file.filepath_name); + + if ((new_domain->u.file.server_info.username = RV_malloc(strlen(server_info->username) + 1)) == NULL) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate space for copied username"); + + strcpy(new_domain->u.file.server_info.username, server_info->username); + + if ((new_domain->u.file.server_info.password = RV_malloc(strlen(server_info->password) + 1)) == NULL) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate space for copied password"); + + strcpy(new_domain->u.file.server_info.password, server_info->password); + + if ((new_domain->u.file.server_info.base_URL = RV_malloc(strlen(server_info->base_URL) + 1)) == NULL) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate space for copied URL"); + + strcpy(new_domain->u.file.server_info.base_URL, server_info->base_URL); - new_domain->u.file.intent = loc_info_out->domain->u.file.intent; - 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->u.file.intent = loc_info_out->domain->u.file.intent; + 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_info.version = found_domain.u.file.server_info.version; /* Allocate root "path" on heap for consistency with other RV_object_t types */ if ((new_domain->handle_path = RV_malloc(2)) == NULL) @@ -2537,7 +2595,7 @@ RV_copy_object_loc_info_callback(char *HTTP_response, void *callback_data_in, vo /* 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 * objects on different servers entirely. */ - memcpy(&new_domain->u.file.server_version, &loc_info_out->domain->u.file.server_version, + memcpy(&new_domain->u.file.server_info.version, &loc_info_out->domain->u.file.server_info.version, sizeof(server_api_version)); if (RV_file_close(loc_info_out->domain, H5P_DEFAULT, NULL) < 0) diff --git a/src/rest_vol.h b/src/rest_vol.h index e3478f61..58637847 100644 --- a/src/rest_vol.h +++ b/src/rest_vol.h @@ -502,6 +502,14 @@ typedef struct server_api_version { size_t patch; } server_api_version; +// TODO +typedef struct server_info_t { + char *username; + char *password; + char *base_URL; + server_api_version version; +} server_info_t; + /* * Definitions for the basic objects which the REST VOL uses * to represent various HDF5 objects internally. The base object @@ -511,12 +519,13 @@ typedef struct server_api_version { typedef struct RV_object_t RV_object_t; typedef struct RV_file_t { - unsigned intent; - unsigned ref_count; - char *filepath_name; - hid_t fcpl_id; - hid_t fapl_id; - server_api_version server_version; + unsigned intent; + unsigned ref_count; + char *filepath_name; + /* TODO - Username/password in global curl handle are still used for now */ + server_info_t server_info; + hid_t fcpl_id; + hid_t fapl_id; } RV_file_t; typedef struct RV_group_t { @@ -677,8 +686,8 @@ typedef enum { extern "C" { #endif -/* Function to set the connection information for the connector to connect to the server */ -herr_t H5_rest_set_connection_information(void); +/* Function to set the connection information on a file for the connector to connect to the server */ +herr_t H5_rest_set_connection_information(server_info_t *server_info); /* Alternate, more portable version of the basename function which doesn't modify its argument */ const char *H5_rest_basename(const char *path); diff --git a/src/rest_vol_attr.c b/src/rest_vol_attr.c index 5d67f21c..72667f3a 100644 --- a/src/rest_vol_attr.c +++ b/src/rest_vol_attr.c @@ -171,7 +171,7 @@ RV_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_ /* See HSDS#223 */ if ((H5I_DATATYPE == new_attribute->u.attribute.parent_obj_type) && - !(SERVER_VERSION_MATCHES_OR_EXCEEDS(parent->domain->u.file.server_version, 0, 8, 0))) + !(SERVER_VERSION_MATCHES_OR_EXCEEDS(parent->domain->u.file.server_info.version, 0, 8, 0))) FUNC_GOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, NULL, "server versions before 0.8.0 cannot properly create attributes on datatypes"); @@ -327,6 +327,12 @@ RV_attr_create(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_ uinfo.buffer_size = (size_t)create_request_body_len; uinfo.bytes_sent = 0; + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, new_attribute->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, new_attribute->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_ATTR, 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_ATTR, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_UPLOAD, 1)) @@ -553,7 +559,8 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na switch (loc_params->loc_data.loc_by_idx.idx_type) { case (H5_INDEX_CRT_ORDER): - if (SERVER_VERSION_MATCHES_OR_EXCEEDS(parent->domain->u.file.server_version, 0, 8, 0)) { + if (SERVER_VERSION_MATCHES_OR_EXCEEDS(parent->domain->u.file.server_info.version, 0, 8, + 0)) { request_idx_type = "&CreateOrder=1"; } else { @@ -623,6 +630,12 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, NULL, "attribute open URL exceeded maximum URL size"); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, attribute->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, attribute->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_ATTR, 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_ATTR, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) @@ -707,6 +720,10 @@ RV_attr_open(void *obj, const H5VL_loc_params_t *loc_params, const char *attr_na printf("-> URL for attribute open request: %s\n\n", request_url); #endif + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, attribute->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, NULL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, attribute->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_ATTR, 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_ATTR, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) @@ -946,6 +963,10 @@ RV_attr_read(void *attr, hid_t dtype_id, void *buf, hid_t dxpl_id, void **req) printf("-> URL for attribute read request: %s\n\n", request_url); #endif + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, attribute->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, attribute->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_ATTR, 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_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) @@ -1150,6 +1171,11 @@ RV_attr_write(void *attr, hid_t dtype_id, const void *buf, hid_t dxpl_id, void * uinfo.buffer_size = write_body_len; uinfo.bytes_sent = 0; + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, attribute->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, attribute->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_ATTR, 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_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_UPLOAD, 1)) @@ -1435,8 +1461,8 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) switch (loc_params->loc_data.loc_by_idx.idx_type) { case (H5_INDEX_CRT_ORDER): - if (SERVER_VERSION_MATCHES_OR_EXCEEDS(loc_obj->domain->u.file.server_version, 0, - 8, 0)) { + if (SERVER_VERSION_MATCHES_OR_EXCEEDS(loc_obj->domain->u.file.server_info.version, + 0, 8, 0)) { request_idx_type = "&CreateOrder=1"; } else { @@ -1494,7 +1520,14 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) if (url_len >= URL_MAX_LENGTH) FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "attribute open URL exceeded maximum URL size"); - + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, + loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", + curl_err_buf); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, + loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_ATTR, 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_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); @@ -1559,6 +1592,12 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_ATTR, 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_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) @@ -1634,8 +1673,8 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) switch (loc_params->loc_data.loc_by_idx.idx_type) { case (H5_INDEX_CRT_ORDER): - if (SERVER_VERSION_MATCHES_OR_EXCEEDS(loc_obj->domain->u.file.server_version, 0, - 7, 3)) { + if (SERVER_VERSION_MATCHES_OR_EXCEEDS(loc_obj->domain->u.file.server_info.version, + 0, 7, 3)) { request_idx_type = "&CreateOrder=1"; } else { @@ -1690,6 +1729,14 @@ RV_attr_get(void *obj, H5VL_attr_get_args_t *args, hid_t dxpl_id, void **req) FUNC_GOTO_ERROR(H5E_ATTR, H5E_SYSERRSTR, FAIL, "attribute open URL exceeded maximum URL size"); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, + loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", + curl_err_buf); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, + loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_ATTR, 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_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); @@ -1900,6 +1947,12 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_ATTR, 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_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE")) @@ -2070,7 +2123,12 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); - + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_ATTR, 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_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE")) @@ -2232,6 +2290,12 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_ATTR, 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_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) @@ -2319,7 +2383,7 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci switch (parent_obj_type) { case H5I_FILE: - /* Copy fapl, fcpl, and filepath name to new object */ + /* Copy plists, filepath, and server info to new object */ /* FAPL */ if (loc_obj->u.file.fapl_id != H5P_FILE_ACCESS_DEFAULT) { @@ -2343,11 +2407,38 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci if (NULL == (attr_iter_obj->u.file.filepath_name = RV_malloc(strlen(loc_obj->u.file.filepath_name) + 1))) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, - "can't allocate space for copied filepath_name object"); + "can't allocate space for copied filepath"); strncpy(attr_iter_obj->u.file.filepath_name, loc_obj->u.file.filepath_name, strlen(loc_obj->u.file.filepath_name) + 1); + if ((attr_iter_obj->u.file.server_info.username = + RV_malloc(strlen(loc_obj->u.file.server_info.username) + 1)) == NULL) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, + "can't allocate space for copied username"); + + strncpy(attr_iter_obj->u.file.server_info.username, + loc_obj->u.file.server_info.username, + strlen(loc_obj->u.file.server_info.username) + 1); + + if ((attr_iter_obj->u.file.server_info.password = + RV_malloc(strlen(loc_obj->u.file.server_info.password) + 1)) == NULL) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, + "can't allocate space for copied password"); + + strncpy(attr_iter_obj->u.file.server_info.password, + loc_obj->u.file.server_info.password, + strlen(loc_obj->u.file.server_info.password) + 1); + + if ((attr_iter_obj->u.file.server_info.base_URL = + RV_malloc(strlen(loc_obj->u.file.server_info.base_URL) + 1)) == NULL) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, + "can't allocate space for copied URL"); + + strncpy(attr_iter_obj->u.file.server_info.base_URL, + loc_obj->u.file.server_info.base_URL, + strlen(loc_obj->u.file.server_info.base_URL) + 1); + /* This is a copy of the file, not a reference to the same memory */ loc_obj->domain->u.file.ref_count--; break; @@ -2642,7 +2733,12 @@ RV_attr_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_attr_speci /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); - + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_ATTR, 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_ATTR, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) diff --git a/src/rest_vol_dataset.c b/src/rest_vol_dataset.c index c62de081..ea505ed0 100644 --- a/src/rest_vol_dataset.c +++ b/src/rest_vol_dataset.c @@ -251,6 +251,12 @@ RV_dataset_create(void *obj, const H5VL_loc_params_t *loc_params, const char *na printf("-> Dataset creation request URL: %s\n\n", request_url); #endif + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, new_dataset->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTSET, NULL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, new_dataset->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_DATASET, 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_DATASET, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_POST, 1)) @@ -396,8 +402,8 @@ RV_dataset_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name loc_info_out.GCPL_base64 = NULL; /* Locate dataset and set domain */ - search_ret = RV_find_object_by_path(parent, name, &obj_type, RV_copy_object_loc_info_callback, NULL, - &loc_info_out); + search_ret = RV_find_object_by_path(parent, name, &obj_type, RV_copy_object_loc_info_callback, + &dataset->domain->u.file.server_info, &loc_info_out); if (!search_ret || search_ret < 0) FUNC_GOTO_ERROR(H5E_DATASET, H5E_PATH, NULL, "can't locate dataset by path"); @@ -1403,6 +1409,12 @@ RV_dataset_get(void *obj, H5VL_dataset_get_args_t *args, hid_t dxpl_id, void **r /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, dset->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, dset->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_DATASET, 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_DATASET, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); @@ -3600,13 +3612,13 @@ RV_setup_dataset_create_request_body(void *parent_obj, const char *name, hid_t t * Dataset create request */ if (H5P_DATASET_CREATE_DEFAULT != dcpl) { if ((H5Pget_layout(dcpl) == H5D_CONTIGUOUS) && - !(SERVER_VERSION_MATCHES_OR_EXCEEDS(pobj->domain->u.file.server_version, 0, 8, 0))) + !(SERVER_VERSION_MATCHES_OR_EXCEEDS(pobj->domain->u.file.server_info.version, 0, 8, 0))) FUNC_GOTO_ERROR(H5E_PLIST, H5E_UNSUPPORTED, FAIL, "layout H5D_CONTIGUOUS is unsupported for server versions before 0.8.0"); if (RV_convert_dataset_creation_properties_to_JSON(dcpl, &creation_properties_body, &creation_properties_body_len, type_id, - pobj->domain->u.file.server_version) < 0) + pobj->domain->u.file.server_info.version) < 0) FUNC_GOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't convert Dataset Creation Properties to JSON representation"); } diff --git a/src/rest_vol_datatype.c b/src/rest_vol_datatype.c index 8413ff6c..d849e3f0 100644 --- a/src/rest_vol_datatype.c +++ b/src/rest_vol_datatype.c @@ -254,6 +254,12 @@ RV_datatype_commit(void *obj, const H5VL_loc_params_t *loc_params, const char *n printf("-> Datatype commit URL: %s\n\n", request_url); #endif + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, new_datatype->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, NULL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, new_datatype->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_DATATYPE, 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_DATATYPE, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_POST, 1)) @@ -392,8 +398,8 @@ RV_datatype_open(void *obj, const H5VL_loc_params_t *loc_params, const char *nam loc_info_out.GCPL_base64 = NULL; /* Locate datatype and set domain */ - search_ret = RV_find_object_by_path(parent, name, &obj_type, RV_copy_object_loc_info_callback, NULL, - &loc_info_out); + search_ret = RV_find_object_by_path(parent, name, &obj_type, RV_copy_object_loc_info_callback, + &datatype->domain->u.file.server_info, &loc_info_out); if (!search_ret || search_ret < 0) FUNC_GOTO_ERROR(H5E_DATATYPE, H5E_PATH, NULL, "can't locate datatype by path"); diff --git a/src/rest_vol_file.c b/src/rest_vol_file.c index 5ee4c474..003d61a5 100644 --- a/src/rest_vol_file.c +++ b/src/rest_vol_file.c @@ -70,9 +70,6 @@ RV_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, h printf(" - Default FAPL? %s\n\n", (H5P_FILE_ACCESS_DEFAULT == fapl_id) ? "yes" : "no"); #endif - if (H5_rest_set_connection_information() < 0) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't set REST VOL connector connection information"); - if (fapl_id == H5I_INVALID_HID) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid FAPL"); @@ -80,6 +77,9 @@ RV_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, h if (NULL == (new_file = (RV_object_t *)RV_malloc(sizeof(*new_file)))) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "can't allocate space for file object"); + if (H5_rest_set_connection_information(&new_file->u.file.server_info) < 0) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't set REST VOL connector connection information"); + new_file->URI[0] = '\0'; new_file->obj_type = H5I_FILE; new_file->u.file.intent = H5F_ACC_RDWR; @@ -143,6 +143,10 @@ RV_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, h /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, new_file->u.file.server_info.username)) + 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, new_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_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)) @@ -262,7 +266,7 @@ RV_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, h FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTCREATE, NULL, "can't parse new file's URI"); /* Store server version */ - if (RV_parse_response(response_buffer.buffer, NULL, &new_file->u.file.server_version, + if (RV_parse_response(response_buffer.buffer, NULL, &new_file->u.file.server_info.version, RV_parse_server_version) < 0) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTCREATE, NULL, "can't parse server version"); @@ -342,9 +346,6 @@ RV_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, voi printf(" - Default FAPL? %s\n\n", (H5P_FILE_ACCESS_DEFAULT == fapl_id) ? "yes" : "no"); #endif - if (H5_rest_set_connection_information() < 0) - FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't set REST VOL connector connection information"); - if (fapl_id == H5I_INVALID_HID) FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid FAPL"); @@ -352,6 +353,9 @@ RV_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, voi if (NULL == (file = (RV_object_t *)RV_malloc(sizeof(*file)))) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "can't allocate space for file object"); + if (H5_rest_set_connection_information(&file->u.file.server_info) < 0) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't set REST VOL connector connection information"); + file->URI[0] = '\0'; file->obj_type = H5I_FILE; file->u.file.intent = flags; @@ -391,6 +395,10 @@ RV_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, voi /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, file->u.file.server_info.username)) + 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_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)) @@ -414,7 +422,7 @@ RV_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t dxpl_id, voi FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "can't parse file's URI"); /* Store server version */ - if (RV_parse_response(response_buffer.buffer, NULL, &file->u.file.server_version, + if (RV_parse_response(response_buffer.buffer, NULL, &file->u.file.server_info.version, RV_parse_server_version) < 0) FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTCREATE, NULL, "can't parse server version"); @@ -713,6 +721,10 @@ RV_file_specific(void *obj, H5VL_file_specific_args_t *args, hid_t dxpl_id, void snprintf(request_url, URL_MAX_LENGTH, "%s%s", 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); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, file->u.file.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, request_url)) @@ -792,6 +804,15 @@ 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); + */ 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)) @@ -888,6 +909,21 @@ 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; + } + + if (_file->u.file.server_info.base_URL) { + RV_free(_file->u.file.server_info.base_URL); + _file->u.file.server_info.base_URL; + } + if (_file->handle_path) { RV_free(_file->handle_path); _file->handle_path = NULL; diff --git a/src/rest_vol_group.c b/src/rest_vol_group.c index d21014a2..8f3b0054 100644 --- a/src/rest_vol_group.c +++ b/src/rest_vol_group.c @@ -252,6 +252,10 @@ RV_group_create(void *obj, const H5VL_loc_params_t *loc_params, const char *name printf("-> Group create request URL: %s\n\n", request_url); #endif + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, new_group->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, NULL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, new_group->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_SYM, 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_SYM, H5E_CANTSET, NULL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_POST, 1)) @@ -399,8 +403,8 @@ RV_group_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, loc_info_out.domain = group->domain; loc_info_out.GCPL_base64 = NULL; - search_ret = RV_find_object_by_path(parent, name, &obj_type, RV_copy_object_loc_info_callback, NULL, - &loc_info_out); + search_ret = RV_find_object_by_path(parent, name, &obj_type, RV_copy_object_loc_info_callback, + &group->domain->u.file.server_info, &loc_info_out); if (!search_ret || search_ret < 0) FUNC_GOTO_ERROR(H5E_SYM, H5E_PATH, NULL, "can't locate group by path"); @@ -411,7 +415,7 @@ RV_group_open(void *obj, const H5VL_loc_params_t *loc_params, const char *name, #endif /* Decode creation properties, if server supports them and file has them */ - if (SERVER_VERSION_MATCHES_OR_EXCEEDS(parent->domain->u.file.server_version, 0, 8, 0) && + if (SERVER_VERSION_MATCHES_OR_EXCEEDS(parent->domain->u.file.server_info.version, 0, 8, 0) && loc_info_out.GCPL_base64) { if (RV_base64_decode(loc_info_out.GCPL_base64, strlen(loc_info_out.GCPL_base64), (char **)&binary_gcpl, binary_gcpl_size) < 0) @@ -561,9 +565,9 @@ RV_group_get(void *obj, H5VL_group_get_args_t *args, hid_t dxpl_id, void **req) loc_info_out.domain = loc_obj->domain; loc_info_out.GCPL_base64 = NULL; - search_ret = - RV_find_object_by_path(loc_obj, loc_params->loc_data.loc_by_name.name, &obj_type, - RV_copy_object_loc_info_callback, NULL, &loc_info_out); + search_ret = RV_find_object_by_path(loc_obj, loc_params->loc_data.loc_by_name.name, + &obj_type, RV_copy_object_loc_info_callback, + &loc_obj->domain->u.file.server_info, &loc_info_out); if (!search_ret || search_ret < 0) FUNC_GOTO_ERROR(H5E_SYM, H5E_PATH, FAIL, "can't locate group"); @@ -618,6 +622,12 @@ RV_group_get(void *obj, H5VL_group_get_args_t *args, hid_t dxpl_id, void **req) /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_SYM, 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_SYM, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) diff --git a/src/rest_vol_link.c b/src/rest_vol_link.c index 2ee54e45..032cad8d 100644 --- a/src/rest_vol_link.c +++ b/src/rest_vol_link.c @@ -336,7 +336,12 @@ RV_link_create(H5VL_link_create_args_t *args, void *obj, const H5VL_loc_params_t uinfo.buffer = create_request_body; uinfo.buffer_size = (size_t)create_request_body_len; uinfo.bytes_sent = 0; - + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, new_link_loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, new_link_loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_LINK, 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_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_UPLOAD, 1)) @@ -565,7 +570,12 @@ RV_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_args_t /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); - + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_LINK, 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_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) @@ -658,6 +668,12 @@ RV_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_args_t /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_LINK, 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_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) @@ -773,6 +789,12 @@ RV_link_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_get_args_t /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_LINK, 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_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) @@ -942,6 +964,12 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_LINK, 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_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE")) @@ -1020,6 +1048,12 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_LINK, 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_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) @@ -1165,6 +1199,12 @@ RV_link_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_link_speci /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_LINK, 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_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) diff --git a/src/rest_vol_object.c b/src/rest_vol_object.c index 756ed135..b3390d3b 100644 --- a/src/rest_vol_object.c +++ b/src/rest_vol_object.c @@ -421,9 +421,9 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar /* loc_info_out.domain was copied at function start */ /* Locate group and set domain */ - search_ret = - RV_find_object_by_path(loc_obj, loc_params->loc_data.loc_by_name.name, &obj_type, - RV_copy_object_loc_info_callback, NULL, &loc_info_out); + search_ret = RV_find_object_by_path(loc_obj, loc_params->loc_data.loc_by_name.name, + &obj_type, RV_copy_object_loc_info_callback, + &loc_obj->domain->u.file.server_info, &loc_info_out); if (!search_ret || search_ret < 0) FUNC_GOTO_ERROR(H5E_OBJECT, H5E_PATH, FAIL, "can't locate object by path"); @@ -521,9 +521,9 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar /* loc_info_out.domain was copied at function start */ /* Locate group and set domain */ - search_ret = - RV_find_object_by_path(loc_obj, loc_params->loc_data.loc_by_name.name, &obj_type, - RV_copy_object_loc_info_callback, NULL, &loc_info_out); + search_ret = RV_find_object_by_path(loc_obj, loc_params->loc_data.loc_by_name.name, + &obj_type, RV_copy_object_loc_info_callback, + &loc_obj->domain->u.file.server_info, &loc_info_out); if (!search_ret || search_ret < 0) FUNC_GOTO_ERROR(H5E_OBJECT, H5E_PATH, FAIL, "can't locate object by path"); @@ -532,8 +532,8 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar switch (loc_params->loc_data.loc_by_idx.idx_type) { case (H5_INDEX_CRT_ORDER): - if (SERVER_VERSION_MATCHES_OR_EXCEEDS(loc_obj->domain->u.file.server_version, 0, - 8, 0)) { + if (SERVER_VERSION_MATCHES_OR_EXCEEDS(loc_obj->domain->u.file.server_info.version, + 0, 8, 0)) { request_idx_type = "&CreateOrder=1"; } else { @@ -580,6 +580,14 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar FUNC_GOTO_ERROR(H5E_LINK, H5E_SYSERRSTR, FAIL, "attribute open URL exceeded maximum URL size"); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_USERNAME, + loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", + curl_err_buf); + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_PASSWORD, + loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_LINK, 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_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); @@ -614,9 +622,9 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar loc_info_out.GCPL_base64 = NULL; } - search_ret = - RV_find_object_by_path(loc_obj, found_object_name, &obj_type, - RV_copy_object_loc_info_callback, NULL, &loc_info_out); + search_ret = RV_find_object_by_path(loc_obj, found_object_name, &obj_type, + RV_copy_object_loc_info_callback, + &loc_obj->domain->u.file.server_info, &loc_info_out); if (!search_ret || search_ret < 0) FUNC_GOTO_ERROR(H5E_OBJECT, H5E_PATH, FAIL, "can't locate object by path"); @@ -657,6 +665,12 @@ RV_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_ar /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_LINK, 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_OBJECT, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); @@ -827,7 +841,7 @@ RV_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_s /* Increment refs for specific type */ switch (loc_obj->obj_type) { case H5I_FILE: - /* Copy fapl, fcpl, and filepath name to new object */ + /* Copy plists, filepath, and server info to new object */ if (H5I_INVALID_HID == (iter_object->u.file.fapl_id = H5Pcopy(loc_obj->u.file.fapl_id))) @@ -843,6 +857,33 @@ RV_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_s strncpy(iter_object->u.file.filepath_name, loc_obj->u.file.filepath_name, strlen(loc_obj->u.file.filepath_name) + 1); + if ((iter_object->u.file.server_info.username = + RV_malloc(strlen(loc_obj->u.file.server_info.username) + 1)) == NULL) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, + "can't allocate space for copied username"); + + strncpy(iter_object->u.file.server_info.username, + loc_obj->u.file.server_info.username, + strlen(loc_obj->u.file.server_info.username) + 1); + + if ((iter_object->u.file.server_info.password = + RV_malloc(strlen(loc_obj->u.file.server_info.password) + 1)) == NULL) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, + "can't allocate space for copied password"); + + strncpy(iter_object->u.file.server_info.password, + loc_obj->u.file.server_info.password, + strlen(loc_obj->u.file.server_info.password) + 1); + + if ((iter_object->u.file.server_info.base_URL = + RV_malloc(strlen(loc_obj->u.file.server_info.base_URL) + 1)) == NULL) + FUNC_GOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, + "can't allocate space for copied URL"); + + strncpy(iter_object->u.file.server_info.base_URL, + loc_obj->u.file.server_info.base_URL, + strlen(loc_obj->u.file.server_info.base_URL) + 1); + /* This is a copy of the file, not a reference to the same memory */ loc_obj->domain->u.file.ref_count--; iter_object->u.file.ref_count = 1; @@ -1065,6 +1106,12 @@ RV_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_s /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_USERNAME, loc_obj->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", curl_err_buf); + if (CURLE_OK != + curl_easy_setopt(curl, CURLOPT_PASSWORD, loc_obj->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_LINK, 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_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) @@ -1796,6 +1843,18 @@ RV_build_object_table(char *HTTP_response, hbool_t is_recursive, int (*sort_func /* Disable use of Expect: 100 Continue HTTP response */ curl_headers = curl_slist_append(curl_headers, "Expect:"); + if (CURLE_OK != + curl_easy_setopt( + curl, CURLOPT_USERNAME, + object_iter_data->iter_obj_parent->domain->u.file.server_info.username)) + FUNC_GOTO_ERROR(H5E_LINK, H5E_CANTSET, FAIL, "can't set cURL username: %s", + curl_err_buf); + if (CURLE_OK != + curl_easy_setopt( + curl, CURLOPT_PASSWORD, + object_iter_data->iter_obj_parent->domain->u.file.server_info.password)) + FUNC_GOTO_ERROR(H5E_LINK, 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_LINK, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); From 924b2344d5d1f72ecd6f2e8aaead3916752af8c3 Mon Sep 17 00:00:00 2001 From: Matthew Larson Date: Wed, 18 Oct 2023 09:58:03 -0500 Subject: [PATCH 2/5] Make server URL file object local --- src/rest_vol.c | 105 ++++++--------------------------------- src/rest_vol.h | 15 ++---- src/rest_vol_attr.c | 24 +++++++++ src/rest_vol_config.h.in | 12 ++--- src/rest_vol_dataset.c | 17 +++++-- 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 | 23 ++++++--- 10 files changed, 161 insertions(+), 167 deletions(-) diff --git a/src/rest_vol.c b/src/rest_vol.c index dba1eb1b..52cd9448 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 @@ -156,7 +151,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); @@ -609,12 +604,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); @@ -729,19 +718,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 *username = NULL; - const char *password = NULL; - - if (base_URL) - FUNC_GOTO_DONE(SUCCEED); + const char *base_URL = NULL; memset(&ad_info, 0, sizeof(ad_info)); @@ -750,50 +732,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 (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"); - - strcpy(base_URL, URL); - } - 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 (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"); - - strcpy(base_URL, URL); - } + 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"); @@ -811,7 +755,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 */ @@ -887,33 +831,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 (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"); - - strcpy(base_URL, val); - + 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); @@ -936,7 +856,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 */ @@ -961,8 +881,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); } @@ -1006,7 +927,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}; @@ -2072,6 +1993,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; @@ -2088,7 +2010,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 58637847..0155a206 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 @@ -502,7 +497,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; @@ -519,10 +515,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 72667f3a..d70515d0 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"); @@ -438,6 +442,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; @@ -471,6 +476,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"); @@ -839,6 +847,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; @@ -855,6 +864,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"); @@ -1032,6 +1044,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; @@ -1048,6 +1061,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"); @@ -1245,6 +1261,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 @@ -1257,6 +1274,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: { @@ -1867,6 +1887,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; @@ -1879,6 +1900,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 ea505ed0..f75e11a1 100644 --- a/src/rest_vol_dataset.c +++ b/src/rest_vol_dataset.c @@ -140,6 +140,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; @@ -157,6 +158,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)) @@ -687,7 +690,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=" @@ -1131,8 +1135,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) @@ -1327,6 +1331,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"); @@ -1338,6 +1343,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 */ @@ -1378,7 +1385,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"); @@ -1617,7 +1624,7 @@ RV_dataset_specific(void *obj, H5VL_dataset_specific_args_t *args, hid_t dxpl_id FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); if ((url_len = - snprintf(request_url, URL_MAX_LENGTH, "%s/datasets/%s/shape", base_URL, dset->URI)) < 0) + snprintf(request_url, URL_MAX_LENGTH, "%s/datasets/%s/shape", dset->domain->u.file.server_info.base_URL, dset->URI)) < 0) FUNC_GOTO_ERROR(H5E_DATASET, H5E_SYSERRSTR, FAIL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) diff --git a/src/rest_vol_datatype.c b/src/rest_vol_datatype.c index d849e3f0..4f894cfa 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 003d61a5..45c01907 100644 --- a/src/rest_vol_file.c +++ b/src/rest_vol_file.c @@ -149,7 +149,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 @@ -399,13 +399,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"); @@ -669,14 +669,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"); @@ -716,10 +717,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); @@ -804,18 +807,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")) @@ -855,6 +862,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() */ @@ -909,25 +923,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; if (RV_type_info_array_g[H5I_FILE]) rv_hash_table_remove(RV_type_info_array_g[H5I_FILE]->table, (char *)_file); diff --git a/src/rest_vol_group.c b/src/rest_vol_group.c index 8f3b0054..082a80e9 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"); @@ -493,6 +497,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; @@ -505,6 +510,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 b3390d3b..bc6d85e0 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,8 +1041,9 @@ 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, - object_iter_data.iter_obj_parent->URI)) < 0) + 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"); if (url_len >= URL_MAX_LENGTH) @@ -1156,9 +1161,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) @@ -1803,8 +1810,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) From 07eebd3f5813df4006bbed19b42cab620b729d75 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 19:41:16 +0000 Subject: [PATCH 3/5] Committing clang-format changes --- src/rest_vol_dataset.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rest_vol_dataset.c b/src/rest_vol_dataset.c index f75e11a1..d1b79e06 100644 --- a/src/rest_vol_dataset.c +++ b/src/rest_vol_dataset.c @@ -1623,8 +1623,8 @@ RV_dataset_specific(void *obj, H5VL_dataset_specific_args_t *args, hid_t dxpl_id if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers)) FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set cURL HTTP headers: %s", curl_err_buf); - if ((url_len = - snprintf(request_url, URL_MAX_LENGTH, "%s/datasets/%s/shape", dset->domain->u.file.server_info.base_URL, dset->URI)) < 0) + if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datasets/%s/shape", + dset->domain->u.file.server_info.base_URL, dset->URI)) < 0) FUNC_GOTO_ERROR(H5E_DATASET, H5E_SYSERRSTR, FAIL, "snprintf error"); if (url_len >= URL_MAX_LENGTH) From 8e0d25a192896f272a727bec9a1531238f3619ed Mon Sep 17 00:00:00 2001 From: Matthew Larson Date: Wed, 15 Nov 2023 09:50:43 -0600 Subject: [PATCH 4/5] Remove redundant URL check --- src/rest_vol_link.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rest_vol_link.c b/src/rest_vol_link.c index 5d0f1f87..32a486e2 100644 --- a/src/rest_vol_link.c +++ b/src/rest_vol_link.c @@ -121,10 +121,10 @@ 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 (!new_link_loc_obj) + FUNC_GOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "link location object is NULL"); - if (!base_URL) + if ((base_URL = new_link_loc_obj->domain->u.file.server_info.base_URL) == NULL) 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 */ From 656145a4f94e1efe7b9a14728fb2ed54a6cb5219 Mon Sep 17 00:00:00 2001 From: Matthew Larson Date: Thu, 16 Nov 2023 10:31:23 -0600 Subject: [PATCH 5/5] Fix socket connection --- src/rest_vol.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/rest_vol.c b/src/rest_vol.c index 52cd9448..d3d3c27f 100644 --- a/src/rest_vol.c +++ b/src/rest_vol.c @@ -146,6 +146,9 @@ const char *allocated_size_keys[] = {"allocated_size", (const char *)0}; /* JSON key to retrieve the version of server from a request to a file. */ const char *server_version_keys[] = {"version", (const char *)0}; +/* Used for cURL's base URL if the connection is through a local socket */ +const char *socket_base_url = "0"; + /* Internal initialization/termination functions which are called by * the public functions H5rest_init() and H5rest_term() */ static herr_t H5_rest_init(hid_t vipl_id); @@ -673,10 +676,6 @@ H5Pset_fapl_rest_vol(hid_t fapl_id) if ((ret_value = H5Pset_vol(fapl_id, H5_rest_id_g, NULL)) < 0) FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't set REST VOL connector in FAPL"); - // now always handled at file open/create time - // if (H5_rest_set_connection_information() < 0) - // FUNC_GOTO_ERROR(H5E_VOL, H5E_CANTINIT, FAIL, "can't set REST VOL connector connection information"); - done: PRINT_ERROR_STACK; @@ -737,6 +736,10 @@ H5_rest_set_connection_information(server_info_t *server_info) username = getenv("HSDS_USERNAME"); password = getenv("HSDS_PASSWORD"); + if (!strncmp(base_URL, UNIX_SOCKET_PREFIX, strlen(UNIX_SOCKET_PREFIX))) { + base_URL = socket_base_url; + } + if (!username && !password) { const char *clientID = getenv("HSDS_AD_CLIENT_ID"); const char *tenantID = getenv("HSDS_AD_TENANT_ID"); @@ -831,7 +834,12 @@ H5_rest_set_connection_information(server_info_t *server_info) if (!strcmp(key, "hs_endpoint")) { if (val) { - base_URL = val; + if (!strncmp(base_URL, UNIX_SOCKET_PREFIX, strlen(UNIX_SOCKET_PREFIX))) { + base_URL = socket_base_url; + } + else { + base_URL = val; + } } /* end if */ } /* end if */ else if (!strcmp(key, "hs_ad_app_id")) {