📄 s3.c
字号:
hdl->last_s3_error_code = 0; hdl->last_num_retries = 0; if (hdl->last_response_body) { g_free(hdl->last_response_body); hdl->last_response_body = NULL; } hdl->last_response_body_size = 0; }}/* }}} *//* {{{ s3_error */voids3_error(S3Handle *hdl, const char **message, guint *response_code, s3_error_code_t *s3_error_code, const char **s3_error_name, CURLcode *curl_code, guint *num_retries){ if (hdl) { if (message) *message = hdl->last_message; if (response_code) *response_code = hdl->last_response_code; if (s3_error_code) *s3_error_code = hdl->last_s3_error_code; if (s3_error_name) *s3_error_name = s3_error_name_from_code(hdl->last_s3_error_code); if (curl_code) *curl_code = hdl->last_curl_code; if (num_retries) *num_retries = hdl->last_num_retries; } else { /* no hdl? return something coherent, anyway */ if (message) *message = "NULL S3Handle"; if (response_code) *response_code = 0; if (s3_error_code) *s3_error_code = 0; if (s3_error_name) *s3_error_name = NULL; if (curl_code) *curl_code = 0; if (num_retries) *num_retries = 0; }}/* }}} *//* {{{ s3_verbose */voids3_verbose(S3Handle *hdl, gboolean verbose){ hdl->verbose = verbose;}/* }}} *//* {{{ s3_sterror */char *s3_strerror(S3Handle *hdl){ const char *message; guint response_code; const char *s3_error_name; CURLcode curl_code; guint num_retries; char s3_info[256] = ""; char response_info[16] = ""; char curl_info[32] = ""; char retries_info[32] = ""; s3_error(hdl, &message, &response_code, NULL, &s3_error_name, &curl_code, &num_retries); if (!message) message = "Unkonwn S3 error"; if (s3_error_name) g_snprintf(s3_info, sizeof(s3_info), " (%s)", s3_error_name); if (response_code) g_snprintf(response_info, sizeof(response_info), " (HTTP %d)", response_code); if (curl_code) g_snprintf(curl_info, sizeof(curl_info), " (CURLcode %d)", curl_code); if (num_retries) g_snprintf(retries_info, sizeof(retries_info), " (after %d retries)", num_retries); return g_strdup_printf("%s%s%s%s%s", message, s3_info, curl_info, response_info, retries_info);}/* }}} *//* {{{ s3_upload *//* Perform an upload. When this function returns, KEY and * BUFFER remain the responsibility of the caller. * * @param self: the s3 device * @param key: the key to which the upload should be made * @param buffer: the data to be uploaded * @param buffer_len: the length of the data to upload * @returns: false if an error ocurred */gbooleans3_upload(S3Handle *hdl, const char *bucket, const char *key, gpointer buffer, guint buffer_len){ char *resource = NULL; s3_result_t result = S3_RESULT_FAIL; static result_handling_t result_handling[] = { { 200, 0, 0, S3_RESULT_OK }, RESULT_HANDLING_ALWAYS_RETRY, { 0, 0, 0, /* default: */ S3_RESULT_FAIL } }; g_return_val_if_fail(hdl != NULL, FALSE); resource = build_resource(bucket, key); if (resource) { result = perform_request(hdl, resource, resource, "PUT", buffer, buffer_len, MAX_ERROR_RESPONSE_LEN, 0, result_handling); g_free(resource); } return result == S3_RESULT_OK;}/* }}} *//* {{{ s3_list_keys *//* Private structure for our "thunk", which tracks where the user is in the list * of keys. */struct list_keys_thunk { GSList *filename_list; /* all pending filenames */ gboolean in_contents; /* look for "key" entities in here */ gboolean in_common_prefixes; /* look for "prefix" entities in here */ gboolean is_truncated; gchar *next_marker; gboolean want_text; gchar *text; gsize text_len;};/* Functions for a SAX parser to parse the XML from Amazon */static voidlist_start_element(GMarkupParseContext *context G_GNUC_UNUSED, const gchar *element_name, const gchar **attribute_names G_GNUC_UNUSED, const gchar **attribute_values G_GNUC_UNUSED, gpointer user_data, GError **error G_GNUC_UNUSED){ struct list_keys_thunk *thunk = (struct list_keys_thunk *)user_data; thunk->want_text = 0; if (strcasecmp(element_name, "contents") == 0) { thunk->in_contents = 1; } else if (strcasecmp(element_name, "commonprefixes") == 0) { thunk->in_common_prefixes = 1; } else if (strcasecmp(element_name, "prefix") == 0 && thunk->in_common_prefixes) { thunk->want_text = 1; } else if (strcasecmp(element_name, "key") == 0 && thunk->in_contents) { thunk->want_text = 1; } else if (strcasecmp(element_name, "istruncated")) { thunk->want_text = 1; } else if (strcasecmp(element_name, "nextmarker")) { thunk->want_text = 1; }}static voidlist_end_element(GMarkupParseContext *context G_GNUC_UNUSED, const gchar *element_name, gpointer user_data, GError **error G_GNUC_UNUSED){ struct list_keys_thunk *thunk = (struct list_keys_thunk *)user_data; if (strcasecmp(element_name, "contents") == 0) { thunk->in_contents = 0; } else if (strcasecmp(element_name, "commonprefixes") == 0) { thunk->in_common_prefixes = 0; } else if (strcasecmp(element_name, "key") == 0 && thunk->in_contents) { thunk->filename_list = g_slist_prepend(thunk->filename_list, thunk->text); thunk->text = NULL; } else if (strcasecmp(element_name, "prefix") == 0 && thunk->in_common_prefixes) { thunk->filename_list = g_slist_prepend(thunk->filename_list, thunk->text); thunk->text = NULL; } else if (strcasecmp(element_name, "istruncated") == 0) { if (thunk->text && strncasecmp(thunk->text, "false", 5) != 0) thunk->is_truncated = TRUE; } else if (strcasecmp(element_name, "nextmarker") == 0) { if (thunk->next_marker) g_free(thunk->next_marker); thunk->next_marker = thunk->text; thunk->text = NULL; }}static voidlist_text(GMarkupParseContext *context G_GNUC_UNUSED, const gchar *text, gsize text_len, gpointer user_data, GError **error G_GNUC_UNUSED){ struct list_keys_thunk *thunk = (struct list_keys_thunk *)user_data; if (thunk->want_text) { if (thunk->text) g_free(thunk->text); thunk->text = g_strndup(text, text_len); }}/* Helper function for list_fetch */static gbooleanlist_build_url_component(char **rv, const char *delim, const char *key, const char *value){ char *esc_value = NULL; char *new_rv = NULL; esc_value = curl_escape(value, 0); if (!esc_value) goto cleanup; new_rv = g_strconcat(*rv, delim, key, "=", esc_value, NULL); if (!new_rv) goto cleanup; g_free(*rv); *rv = new_rv; curl_free(esc_value); return TRUE;cleanup: if (new_rv) g_free(new_rv); if (esc_value) curl_free(esc_value); return FALSE;}/* Perform a fetch from S3; several fetches may be involved in a * single listing operation */static s3_result_tlist_fetch(S3Handle *hdl, const char *resource, const char *prefix, const char *delimiter, const char *marker, const char *max_keys){ char *urldelim = "?"; char *uri = g_strdup(resource); s3_result_t result = S3_RESULT_FAIL; static result_handling_t result_handling[] = { { 200, 0, 0, S3_RESULT_OK }, RESULT_HANDLING_ALWAYS_RETRY, { 0, 0, 0, /* default: */ S3_RESULT_FAIL } }; /* build the URI */ if (prefix) { if (!list_build_url_component(&uri, urldelim, "prefix", prefix)) goto cleanup; urldelim = "&"; } if (delimiter) { if (!list_build_url_component(&uri, urldelim, "delimiter", delimiter)) goto cleanup; urldelim = "&"; } if (marker) { if (!list_build_url_component(&uri, urldelim, "marker", marker)) goto cleanup; urldelim = "&"; } if (max_keys) { if (!list_build_url_component(&uri, urldelim, "max-keys", max_keys)) goto cleanup; urldelim = "&"; } /* and perform the request on that URI */ result = perform_request(hdl, resource, uri, "GET", NULL, 0, MAX_ERROR_RESPONSE_LEN, 0, result_handling);cleanup: if (uri) g_free(uri); return result;}gbooleans3_list_keys(S3Handle *hdl, const char *bucket, const char *prefix, const char *delimiter, GSList **list){ char *resource = NULL; struct list_keys_thunk thunk; GMarkupParseContext *ctxt = NULL; static GMarkupParser parser = { list_start_element, list_end_element, list_text, NULL, NULL }; GError *err = NULL; s3_result_t result = S3_RESULT_FAIL; g_assert(list); *list = NULL; thunk.filename_list = NULL; thunk.text = NULL; thunk.next_marker = NULL; resource = build_resource(bucket, NULL); if (!resource) goto cleanup; /* Loop until S3 has given us the entire picture */ do { /* get some data from S3 */ result = list_fetch(hdl, resource, prefix, delimiter, thunk.next_marker, NULL); if (result != S3_RESULT_OK) goto cleanup; /* run the parser over it */ thunk.in_contents = FALSE; thunk.in_common_prefixes = FALSE; thunk.is_truncated = FALSE; thunk.want_text = FALSE; ctxt = g_markup_parse_context_new(&parser, 0, (gpointer)&thunk, NULL); if (!g_markup_parse_context_parse(ctxt, hdl->last_response_body, hdl->last_response_body_size, &err)) { if (hdl->last_message) g_free(hdl->last_message); hdl->last_message = g_strdup(err->message); result = S3_RESULT_FAIL; goto cleanup; } if (!g_markup_parse_context_end_parse(ctxt, &err)) { if (hdl->last_message) g_free(hdl->last_message); hdl->last_message = g_strdup(err->message); result = S3_RESULT_FAIL; goto cleanup; } g_markup_parse_context_free(ctxt); ctxt = NULL; } while (thunk.next_marker);cleanup: if (err) g_error_free(err); if (thunk.text) g_free(thunk.text); if (thunk.next_marker) g_free(thunk.next_marker); if (resource) g_free(resource); if (ctxt) g_markup_parse_context_free(ctxt); if (result != S3_RESULT_OK) { g_slist_free(thunk.filename_list); return FALSE; } else { *list = thunk.filename_list; return TRUE; }}/* }}} *//* {{{ s3_read */gbooleans3_read(S3Handle *hdl, const char *bucket, const char *key, gpointer *buf_ptr, guint *buf_size, guint max_size){ char *resource = NULL; s3_result_t result = S3_RESULT_FAIL; static result_handling_t result_handling[] = { { 200, 0, 0, S3_RESULT_OK }, RESULT_HANDLING_ALWAYS_RETRY, { 0, 0, 0, /* default: */ S3_RESULT_FAIL } }; g_return_val_if_fail(hdl != NULL, FALSE); g_assert(buf_ptr != NULL); g_assert(buf_size != NULL); *buf_ptr = NULL; *buf_size = 0; resource = build_resource(bucket, key); if (resource) { result = perform_request(hdl, resource, resource, "GET", NULL, 0, max_size, 0, result_handling); g_free(resource); /* copy the pointer to the result parameters and remove * our reference to it */ if (result == S3_RESULT_OK) { *buf_ptr = hdl->last_response_body; *buf_size = hdl->last_response_body_size; hdl->last_response_body = NULL; hdl->last_response_body_size = 0; } } return result == S3_RESULT_OK;}/* }}} *//* {{{ s3_delete */gbooleans3_delete(S3Handle *hdl, const char *bucket, const char *key){ char *resource = NULL; s3_result_t result = S3_RESULT_FAIL; static result_handling_t result_handling[] = { { 204, 0, 0, S3_RESULT_OK }, RESULT_HANDLING_ALWAYS_RETRY, { 0, 0, 0, /* default: */ S3_RESULT_FAIL } }; g_return_val_if_fail(hdl != NULL, FALSE); resource = build_resource(bucket, key); if (resource) { result = perform_request(hdl, resource, resource, "DELETE", NULL, 0, MAX_ERROR_RESPONSE_LEN, 0, result_handling); g_free(resource); } return result == S3_RESULT_OK;}/* }}} *//* {{{ s3_make_bucket */gbooleans3_make_bucket(S3Handle *hdl, const char *bucket){ char *resource = NULL; s3_result_t result = result = S3_RESULT_FAIL; static result_handling_t result_handling[] = { { 200, 0, 0, S3_RESULT_OK }, RESULT_HANDLING_ALWAYS_RETRY, { 0, 0, 0, /* default: */ S3_RESULT_FAIL } }; g_return_val_if_fail(hdl != NULL, FALSE); resource = build_resource(bucket, NULL); if (resource) { result = perform_request(hdl, resource, resource, "PUT", NULL, 0, MAX_ERROR_RESPONSE_LEN, 0, result_handling); g_free(resource); } return result == S3_RESULT_OK;}/* }}} */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -