⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 3 页
字号:
        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 + -