Exemple #1
0
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;
}
Exemple #2
0
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);
}
Exemple #3
0
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);
}
Exemple #4
0
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);
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}
Exemple #7
0
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;
}
Exemple #8
0
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;
}
Exemple #9
0
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;
}
Exemple #10
0
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;
}
Exemple #11
0
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();
}
Exemple #12
0
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;
}