static dpl_vec_t * get_canonical_params(const char *subresource, const dpl_dict_t *query_params, unsigned char encode_url) { dpl_status_t ret = DPL_SUCCESS; dpl_vec_t *params; params = dpl_vec_new(1, 0); if (params == NULL) return NULL; if (subresource != NULL) ret = parse_query_params_from_subresource(params, subresource, encode_url); if (ret == DPL_SUCCESS && query_params != NULL) ret = insert_query_params_in_vec(params, query_params, encode_url); if (ret != DPL_SUCCESS) { int item; for (item = 0; item < params->n_items; item++) { dpl_dict_var_t *param = (dpl_dict_var_t *) dpl_vec_get(params, item); free(param->key); dpl_dict_var_free(param); } dpl_vec_free(params); return NULL; } dpl_vec_sort(params, var_cmp); return params; }
void dpl_vec_common_prefixes_free(dpl_vec_t *vec) { int i; for (i = 0;i < vec->n_items;i++) dpl_common_prefix_free((dpl_common_prefix_t *) dpl_vec_get(vec, i)); dpl_vec_free(vec); }
void dpl_vec_delete_objects_free(dpl_vec_t *vec) { int i; for (i = 0; i < vec->n_items; i++) dpl_delete_object_free((dpl_delete_object_t *) dpl_vec_get(vec, i)); dpl_vec_free(vec); }
void dpl_vec_buckets_free(dpl_vec_t *vec) { int i; for (i = 0;i < vec->n_items;i++) dpl_bucket_free((dpl_bucket_t *) dpl_vec_get(vec, i)); dpl_vec_free(vec); }
static dpl_status_t create_authorization(const dpl_req_t *req, struct tm *tm, dpl_vec_t *canonical_headers, char *signature, char *p, unsigned int len) { int ret; char date_buf[9]; ret = strftime(date_buf, sizeof(date_buf), "%Y%m%d", tm); if (ret == 0) return DPL_FAILURE; DPL_APPEND_STR("AWS4-HMAC-SHA256"); DPL_APPEND_STR(" "); DPL_APPEND_STR("Credential="); DPL_APPEND_STR(req->ctx->access_key); DPL_APPEND_STR("/"); DPL_APPEND_STR(date_buf); DPL_APPEND_STR("/"); DPL_APPEND_STR(req->ctx->aws_region); DPL_APPEND_STR("/s3/aws4_request"); DPL_APPEND_STR(","); DPL_APPEND_STR("SignedHeaders="); { int item; char *c; dpl_dict_var_t *header; for (item = 0; item < canonical_headers->n_items; item++) { header = (dpl_dict_var_t *) dpl_vec_get(canonical_headers, item); if (header == NULL) continue; if (item > 0) DPL_APPEND_STR(";"); for (c = header->key; *c != '\0'; c++) DPL_APPEND_CHAR(tolower(*c)); } } DPL_APPEND_STR(","); DPL_APPEND_STR("Signature="); DPL_APPEND_STR(signature); return DPL_SUCCESS; }
static dpl_status_t dpl_s3_insert_signature_v4_params(const dpl_req_t *req, dpl_dict_t *query_params, struct tm *tm, char *date_str, char *signature) { int item; dpl_status_t ret; dpl_vec_t *canonical_params; char canonical_request[4096] = ""; char sign_request[1024] = ""; canonical_params = get_canonical_params(req->subresource, query_params, 0); if (canonical_params == NULL) return DPL_FAILURE; ret = create_canonical_request(req, NULL, NULL, canonical_params, canonical_request, sizeof(canonical_request)); if (ret == DPL_SUCCESS) { DPRINTF("Canonical request:\n%s\n", canonical_request); ret = create_sign_request(req, canonical_request, tm, date_str, sign_request, sizeof(sign_request)); } if (ret == DPL_SUCCESS) { DPRINTF("Signing request:\n%s\n", sign_request); ret = create_signature(req, tm, sign_request, signature); } if (ret == DPL_SUCCESS) DPRINTF("Signature: %s\n", signature); for (item = 0; item < canonical_params->n_items; item++) { dpl_dict_var_t *param = (dpl_dict_var_t *) dpl_vec_get(canonical_params, item); free(param->key); dpl_dict_var_free(param); } dpl_vec_free(canonical_params); return ret; }
double dpl_price_storage(dpl_ctx_t *ctx, size_t size) { int i; struct dpl_data_pricing *datp = NULL; for (i = 0;i < ctx->data_pricing[DPL_DATA_TYPE_STORAGE]->n_items;i++) { datp = (struct dpl_data_pricing *) dpl_vec_get(ctx->data_pricing[DPL_DATA_TYPE_STORAGE], i); //dpl_data_pricing_print(datp); if (size < datp->limit) break ; } if (NULL == datp) return .0; return ((double) size / (double) datp->quantity) * datp->price; }
static dpl_status_t dpl_s3_make_signature_v2(dpl_ctx_t *ctx, const char *method, const char *bucket, const char *resource, const char *subresource, char *date, dpl_dict_t *headers, char *buf, unsigned int len, unsigned int *lenp) { char *p; char *value; int ret; p = buf; //method DPL_APPEND_STR(method); DPL_APPEND_STR("\n"); //md5 if (headers != NULL) { value = dpl_dict_get_value(headers, "Content-MD5"); if (NULL != value) DPL_APPEND_STR(value); } DPL_APPEND_STR("\n"); //content type if (headers != NULL) { value = dpl_dict_get_value(headers, "Content-Type"); if (NULL != value) DPL_APPEND_STR(value); } DPL_APPEND_STR("\n"); //expires or date if (date != NULL) DPL_APPEND_STR(date); DPL_APPEND_STR("\n"); //x-amz headers if (headers != NULL) { int bucket; dpl_dict_var_t *var; dpl_vec_t *vec; int i; vec = dpl_vec_new(2, 2); if (NULL == vec) return DPL_ENOMEM; for (bucket = 0; bucket < headers->n_buckets; bucket++) { for (var = headers->buckets[bucket];var;var = var->prev) { if (!strncmp(var->key, "x-amz-", 6) && strcmp(var->key, "x-amz-date")) { assert(DPL_VALUE_STRING == var->val->type); ret = dpl_vec_add(vec, var); if (DPL_SUCCESS != ret) { dpl_vec_free(vec); return DPL_FAILURE; } } } } dpl_vec_sort(vec, var_cmp); for (i = 0;i < vec->n_items;i++) { var = (dpl_dict_var_t *) dpl_vec_get(vec, i); if (var == NULL) continue; assert(DPL_VALUE_STRING == var->val->type); DPL_APPEND_STR(var->key); DPL_APPEND_STR(":"); DPL_APPEND_STR(dpl_sbuf_get_str(var->val->string)); DPL_APPEND_STR("\n"); } dpl_vec_free(vec); } //resource if (NULL != bucket) { DPL_APPEND_STR("/"); DPL_APPEND_STR(bucket); } if (NULL != resource) DPL_APPEND_STR(resource); if (NULL != subresource) { DPL_APPEND_STR("?"); DPL_APPEND_STR(subresource); } if (NULL != lenp) *lenp = p - buf; return DPL_SUCCESS; }
static dpl_status_t create_canonical_request(const dpl_req_t *req, dpl_dict_t *headers, dpl_vec_t *canonical_headers, dpl_vec_t *canonical_params, char *p, unsigned int len) { // Method { const char *method = dpl_method_str(req->method); DPL_APPEND_STR(method); DPL_APPEND_STR("\n"); } // Resource if (req->resource != NULL) { char resource_ue[DPL_URL_LENGTH(strlen(req->resource)) + 1]; if (req->resource[0] != '/') DPL_APPEND_STR("/"); dpl_url_encode_no_slashes(req->resource, resource_ue); DPL_APPEND_STR(resource_ue); } DPL_APPEND_STR("\n"); // Query params { int item; for (item = 0; item < canonical_params->n_items; item++) { dpl_dict_var_t *param = (dpl_dict_var_t *) dpl_vec_get(canonical_params, item); if (param == NULL) continue; if (item > 0) DPL_APPEND_STR("&"); DPL_APPEND_STR(param->key); DPL_APPEND_STR("="); DPL_APPEND_STR(dpl_sbuf_get_str(param->val->string)); } DPL_APPEND_STR("\n"); } // Headers if (canonical_headers != NULL) { int item; char *c; dpl_dict_var_t *header; for (item = 0; item < canonical_headers->n_items; item++) { header = (dpl_dict_var_t *) dpl_vec_get(canonical_headers, item); if (header == NULL) continue; for (c = header->key; *c != '\0'; c++) DPL_APPEND_CHAR(tolower(*c)); DPL_APPEND_STR(":"); DPL_APPEND_STR(dpl_sbuf_get_str(header->val->string)); DPL_APPEND_STR("\n"); } DPL_APPEND_STR("\n"); for (item = 0; item < canonical_headers->n_items; item++) { header = (dpl_dict_var_t *) dpl_vec_get(canonical_headers, item); if (header == NULL) continue; if (item > 0) DPL_APPEND_STR(";"); for (c = header->key; *c != '\0'; c++) DPL_APPEND_CHAR(tolower(*c)); } DPL_APPEND_STR("\n"); } else { DPL_APPEND_STR("host:"); DPL_APPEND_STR(req->host); DPL_APPEND_STR("\n\n"); DPL_APPEND_STR("host\n"); } // Hashed payload if (headers != NULL) { char *value = dpl_dict_get_value(headers, "x-amz-content-sha256"); if (value != NULL) DPL_APPEND_STR(value); } else DPL_APPEND_STR("UNSIGNED-PAYLOAD"); return DPL_SUCCESS; }
dpl_status_t dpl_s3_add_authorization_v4_to_headers(const dpl_req_t *req, dpl_dict_t *headers, const dpl_dict_t *query_params, struct tm *i_tm) { int item; dpl_status_t ret; char canonical_request[4096] = ""; char sign_request[1024] = ""; char signature[DPL_HEX_LENGTH(SHA256_DIGEST_LENGTH) + 1]; char authorization[1024] = ""; char date_str[32] = ""; dpl_vec_t *canonical_headers; dpl_vec_t *canonical_params; struct tm tm; ret = add_payload_signature_to_headers(req, headers); if (ret != DPL_SUCCESS) return ret; ret = get_current_utc_date(&tm, i_tm, date_str, sizeof(date_str)); if (ret != DPL_SUCCESS) return ret; ret = dpl_dict_add(headers, "x-amz-date", date_str, 0); if (ret != DPL_SUCCESS) return ret; canonical_headers = get_canonical_headers(headers); if (canonical_headers == NULL) return DPL_FAILURE; canonical_params = get_canonical_params(req->subresource, query_params, 1); if (canonical_params == NULL) { dpl_vec_free(canonical_headers); return DPL_FAILURE; } ret = create_canonical_request(req, headers, canonical_headers, canonical_params, canonical_request, sizeof(canonical_request)); if (ret == DPL_SUCCESS) { DPRINTF("Canonical request:\n%s\n", canonical_request); ret = create_sign_request(req, canonical_request, &tm, date_str, sign_request, sizeof(sign_request)); } if (ret == DPL_SUCCESS) { DPRINTF("Signing request:\n%s\n", sign_request); ret = create_signature(req, &tm, sign_request, signature); } if (ret == DPL_SUCCESS) { DPRINTF("Signature: %s\n", signature); ret = create_authorization(req, &tm, canonical_headers, signature, authorization, sizeof(authorization)); } if (ret == DPL_SUCCESS) ret = dpl_dict_add(headers, "Authorization", authorization, 0); for (item = 0; item < canonical_params->n_items; item++) { dpl_dict_var_t *param = (dpl_dict_var_t *) dpl_vec_get(canonical_params, item); free(param->key); dpl_dict_var_free(param); } dpl_vec_free(canonical_params); dpl_vec_free(canonical_headers); return ret; }
void cb_list_bucket(void *handle) { dpl_async_task_t *atask = (dpl_async_task_t *) handle; int i; if (DPL_SUCCESS != atask->ret) { fprintf(stderr, "error listing folder: %s (%d)\n", dpl_status_str(atask->ret), atask->ret); exit(1); } pthread_mutex_init(&list_lock, NULL); pthread_cond_init(&list_cond, NULL); for (i = 0;i < atask->u.list_bucket.objects->n_items;i++) { dpl_object_t *obj = (dpl_object_t *) dpl_vec_get(atask->u.list_bucket.objects, i); dpl_sysmd_t obj_sysmd; dpl_dict_t *obj_md = NULL; dpl_async_task_t *sub_atask = NULL; fprintf(stderr, "getting md\n"); sub_atask = (dpl_async_task_t *) dpl_head_async_prepare(ctx, NULL, //no bucket obj->path, NULL, //option DPL_FTYPE_UNDEF, //no matter the file type NULL); //condition if (NULL == sub_atask) { fprintf(stderr, "error preparing task\n"); exit(1); } sub_atask->cb_func = cb_head_object; sub_atask->cb_arg = sub_atask; dpl_task_pool_put(pool, (dpl_task_t *) sub_atask); } for (i = 0;i < atask->u.list_bucket.common_prefixes->n_items;i++) { dpl_common_prefix_t *dir = (dpl_common_prefix_t *) dpl_vec_get(atask->u.list_bucket.common_prefixes, i); fprintf(stderr, "dir %s\n", dir->prefix); } again: pthread_cond_wait(&list_cond, &list_lock); //printf("n_ok=%d\n", n_ok); if (n_ok != atask->u.list_bucket.objects->n_items) goto again; dpl_async_task_free(atask); delete_object(); }
int main(int argc, char **argv) { int ret; dpl_ctx_t *ctx; char *folder = NULL; int folder_len; dpl_dict_t *metadata = NULL; char *data_buf = NULL; size_t data_len; char *data_buf_returned = NULL; u_int data_len_returned; dpl_dict_t *metadata_returned = NULL; dpl_dict_t *metadata2_returned = NULL; dpl_dict_var_t *metadatum = NULL; dpl_sysmd_t sysmd; char new_path[MAXPATHLEN]; dpl_vec_t *files = NULL; dpl_vec_t *sub_directories = NULL; int i; if (2 != argc) { fprintf(stderr, "usage: restrest folder\n"); ret = 1; goto end; } folder = argv[1]; folder_len = strlen(folder); if (folder_len < 1) { fprintf(stderr, "bad folder\n"); ret = 1; goto end; } if (folder[folder_len-1] != '/') { fprintf(stderr, "folder name must end with a slash\n"); ret = 1; goto end; } ret = dpl_init(); //init droplet library if (DPL_SUCCESS != ret) { fprintf(stderr, "dpl_init failed\n"); ret = 1; goto end; } //open default profile ctx = dpl_ctx_new(NULL, //droplet directory, default: "~/.droplet" NULL); //droplet profile, default: "default" if (NULL == ctx) { fprintf(stderr, "dpl_ctx_new failed\n"); ret = 1; goto free_dpl; } //ctx->trace_level = ~0; //ctx->trace_buffers = 1; /**/ fprintf(stderr, "creating folder\n"); ret = dpl_put(ctx, //the context NULL, //no bucket folder, //the folder NULL, //no option DPL_FTYPE_DIR, //directory NULL, //no condition NULL, //no range NULL, //no metadata NULL, //no sysmd NULL, //object body 0); //object length if (DPL_SUCCESS != ret) { fprintf(stderr, "dpl_put failed: %s (%d)\n", dpl_status_str(ret), ret); ret = 1; goto free_all; } /**/ data_len = 10000; data_buf = malloc(data_len); if (NULL == data_buf) { fprintf(stderr, "alloc data failed\n"); ret = 1; goto free_all; } memset(data_buf, 'z', data_len); metadata = dpl_dict_new(13); if (NULL == metadata) { fprintf(stderr, "dpl_dict_new failed\n"); ret = 1; goto free_all; } ret = dpl_dict_add(metadata, "foo", "bar", 0); if (DPL_SUCCESS != ret) { fprintf(stderr, "dpl_dict_add failed\n"); ret = 1; goto free_all; } ret = dpl_dict_add(metadata, "foo2", "qux", 0); if (DPL_SUCCESS != ret) { fprintf(stderr, "dpl_dict_add failed\n"); ret = 1; goto free_all; } /**/ fprintf(stderr, "atomic creation of an object+MD\n"); ret = dpl_post(ctx, //the context NULL, //no bucket folder, //the folder NULL, //no option DPL_FTYPE_REG, //regular object NULL, //condition NULL, //range metadata, //the metadata NULL, //no sysmd data_buf, //object body data_len, //object length NULL, //no query params &sysmd); //the returned sysmd if (DPL_SUCCESS != ret) { fprintf(stderr, "dpl_post failed: %s (%d)\n", dpl_status_str(ret), ret); ret = 1; goto free_all; } if (!(sysmd.mask & DPL_SYSMD_MASK_PATH)) { fprintf(stderr, "path is absent from sysmd\n"); ret = 1; goto free_all; } fprintf(stderr, "resource path %s\n", sysmd.path); snprintf(new_path, sizeof (new_path), "%su.1", folder); ret = dpl_copy(ctx, NULL, //no src bucket sysmd.path, //the src resource NULL, //no dst bucket new_path, //dst resource NULL, //no option DPL_FTYPE_REG, //regular file DPL_COPY_DIRECTIVE_MOVE, //rename NULL, //no metadata NULL, //no sysmd NULL); //no server side condition if (DPL_SUCCESS != ret) { fprintf(stderr, "dpl_move %s to %s failed: %s (%d)\n", sysmd.path, new_path, dpl_status_str(ret), ret); ret = 1; goto free_all; } /**/ fprintf(stderr, "getting object+MD\n"); ret = dpl_get(ctx, //the context NULL, //no bucket new_path, //the key NULL, //no opion DPL_FTYPE_REG, //object type NULL, //no condition NULL, //no range &data_buf_returned, //data object &data_len_returned, //data object length &metadata_returned, //metadata NULL); //sysmd if (DPL_SUCCESS != ret) { fprintf(stderr, "dpl_get_id failed: %s (%d)\n", dpl_status_str(ret), ret); ret = 1; goto free_all; } fprintf(stderr, "checking object\n"); if (data_len != data_len_returned) { fprintf(stderr, "data lengths mismatch\n"); ret = 1; goto free_all; } if (0 != memcmp(data_buf, data_buf_returned, data_len)) { fprintf(stderr, "data content mismatch\n"); ret = 1; goto free_all; } fprintf(stderr, "checking metadata\n"); metadatum = dpl_dict_get(metadata_returned, "foo"); if (NULL == metadatum) { fprintf(stderr, "missing metadatum\n"); ret = 1; goto free_all; } assert(metadatum->val->type == DPL_VALUE_STRING); if (strcmp(metadatum->val->string, "bar")) { fprintf(stderr, "bad value in metadatum\n"); ret = 1; goto free_all; } metadatum = dpl_dict_get(metadata_returned, "foo2"); if (NULL == metadatum) { fprintf(stderr, "missing metadatum\n"); ret = 1; goto free_all; } assert(metadatum->val->type == DPL_VALUE_STRING); if (strcmp(metadatum->val->string, "qux")) { fprintf(stderr, "bad value in metadatum\n"); ret = 1; goto free_all; } /**/ fprintf(stderr, "setting MD only\n"); ret = dpl_dict_add(metadata, "foo", "bar2", 0); if (DPL_SUCCESS != ret) { fprintf(stderr, "error updating metadatum: %s (%d)\n", dpl_status_str(ret), ret); ret = 1; goto free_all; } ret = dpl_copy(ctx, //the context NULL, //no src bucket new_path, //the key NULL, //no dst bucket new_path, //the same key NULL, //no option DPL_FTYPE_REG, //object type DPL_COPY_DIRECTIVE_METADATA_REPLACE, //tell server to replace metadata metadata, //the updated metadata NULL, //no sysmd NULL); //no condition if (DPL_SUCCESS != ret) { fprintf(stderr, "error updating metadata: %s (%d)\n", dpl_status_str(ret), ret); ret = 1; goto free_all; } /**/ fprintf(stderr, "getting MD only\n"); ret = dpl_head(ctx, //the context NULL, //no bucket, new_path, //the key NULL, //no option DPL_FTYPE_UNDEF, //no matter the file type NULL, //no condition, &metadata2_returned, NULL); if (DPL_SUCCESS != ret) { fprintf(stderr, "error getting metadata: %s (%d)\n", dpl_status_str(ret), ret); ret = 1; goto free_all; } fprintf(stderr, "checking metadata\n"); metadatum = dpl_dict_get(metadata2_returned, "foo"); if (NULL == metadatum) { fprintf(stderr, "missing metadatum\n"); ret = 1; goto free_all; } assert(metadatum->val->type == DPL_VALUE_STRING); if (strcmp(metadatum->val->string, "bar2")) { fprintf(stderr, "bad value in metadatum\n"); ret = 1; goto free_all; } metadatum = dpl_dict_get(metadata2_returned, "foo2"); if (NULL == metadatum) { fprintf(stderr, "missing metadatum\n"); ret = 1; goto free_all; } assert(metadatum->val->type == DPL_VALUE_STRING); if (strcmp(metadatum->val->string, "qux")) { fprintf(stderr, "bad value in metadatum\n"); ret = 1; goto free_all; } /**/ fprintf(stderr, "listing of folder\n"); ret = dpl_list_bucket(ctx, NULL, folder, "/", -1, &files, &sub_directories); if (DPL_SUCCESS != ret) { fprintf(stderr, "error listing folder: %s (%d)\n", dpl_status_str(ret), ret); ret = 1; goto free_all; } for (i = 0;i < files->n_items;i++) { dpl_object_t *obj = (dpl_object_t *) dpl_vec_get(files, i); dpl_sysmd_t obj_sysmd; dpl_dict_t *obj_md = NULL; ret = dpl_head(ctx, NULL, //no bucket obj->path, NULL, //option DPL_FTYPE_UNDEF, //no matter the file type NULL, //condition &obj_md, //user metadata &obj_sysmd); //system metadata if (DPL_SUCCESS != ret) { fprintf(stderr, "getattr error on %s: %s (%d)\n", obj->path, dpl_status_str(ret), ret); ret = 1; goto free_all; } fprintf(stderr, "file %s: size=%ld mtime=%lu\n", obj->path, obj_sysmd.size, obj_sysmd.mtime); //dpl_dict_print(obj_md, stderr, 5); dpl_dict_free(obj_md); } for (i = 0;i < sub_directories->n_items;i++) { dpl_common_prefix_t *dir = (dpl_common_prefix_t *) dpl_vec_get(sub_directories, i); fprintf(stderr, "dir %s\n", dir->prefix); } /**/ fprintf(stderr, "delete object+MD\n"); ret = dpl_delete(ctx, //the context NULL, //no bucket new_path, //the key NULL, //no option DPL_FTYPE_UNDEF, //no matter the file type NULL); //no condition if (DPL_SUCCESS != ret) { fprintf(stderr, "error deleting object: %s (%d)\n", dpl_status_str(ret), ret); ret = 1; goto free_all; } ret = 0; free_all: if (NULL != sub_directories) dpl_vec_common_prefixes_free(sub_directories); if (NULL != files) dpl_vec_objects_free(files); if (NULL != metadata2_returned) dpl_dict_free(metadata2_returned); if (NULL != metadata_returned) dpl_dict_free(metadata_returned); if (NULL != data_buf_returned) free(data_buf_returned); if (NULL != metadata) dpl_dict_free(metadata); if (NULL != data_buf) free(data_buf); dpl_ctx_free(ctx); //free context free_dpl: dpl_free(); //free droplet library end: return ret; }