Esempio n. 1
0
static int send_request(char *method, const char *path, FILE *fp,
                        xmlParserCtxtPtr xmlctx, curl_slist *extra_headers)
{
  char url[MAX_URL_SIZE];
  char *slash;
  long response = -1;
  int tries = 0;

  if (!storage_url[0])
  {
    debugf("send_request with no storage_url?");
    abort();
  }

  while ((slash = strstr(path, "%2F")) || (slash = strstr(path, "%2f")))
  {
    *slash = '/';
    memmove(slash+1, slash+3, strlen(slash+3)+1);
  }
  while (*path == '/')
    path++;
  snprintf(url, sizeof(url), "%s/%s", storage_url, path);

  // retry on failures
  for (tries = 0; tries < REQUEST_RETRIES; tries++)
  {
    CURL *curl = get_connection(path);
    if (rhel5_mode)
      curl_easy_setopt(curl, CURLOPT_CAINFO, RHEL5_CERTIFICATE_FILE);
    curl_slist *headers = NULL;
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_HEADER, 0);
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
    curl_easy_setopt(curl, CURLOPT_USERAGENT, USER_AGENT);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, verify_ssl);
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, debug);
    add_header(&headers, "X-Auth-Token", storage_token);
    if (!strcasecmp(method, "MKDIR"))
    {
      curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
      curl_easy_setopt(curl, CURLOPT_INFILESIZE, 0);
      add_header(&headers, "Content-Type", "application/directory");
    }
    else if (!strcasecmp(method, "PUT") && fp)
    {
      rewind(fp);
      curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
      curl_easy_setopt(curl, CURLOPT_INFILESIZE, cloudfs_file_size(fileno(fp)));
      curl_easy_setopt(curl, CURLOPT_READDATA, fp);
    }
    else if (!strcasecmp(method, "GET"))
    {
      if (fp)
      {
        rewind(fp); // make sure the file is ready for a-writin'
        fflush(fp);
        if (ftruncate(fileno(fp), 0) < 0)
        {
          debugf("ftruncate failed.  I don't know what to do about that.");
          abort();
        }
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
      }
      else if (xmlctx)
      {
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, xmlctx);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &xml_dispatch);
      }
    }
    else
      curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method);
    /* add the headers from extra_headers if any */
    curl_slist *extra;
    for (extra = extra_headers; extra; extra = extra->next)
    {
      debugf("adding header: %s", extra->data);
      headers = curl_slist_append(headers, extra->data);
    }
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_perform(curl);
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
    curl_slist_free_all(headers);
    curl_easy_reset(curl);
    return_connection(curl);
    if (response >= 200 && response < 400)
      return response;
    sleep(8 << tries); // backoff
    if (response == 401 && !cloudfs_connect()) // re-authenticate on 401s
      return response;
    if (xmlctx)
      xmlCtxtResetPush(xmlctx, NULL, 0, NULL, NULL);
  }
  return response;
}
Esempio n. 2
0
static int send_request(char *method, const char *path, FILE *fp, xmlParserCtxtPtr xmlctx, curl_slist *extra_headers)
{
  long response = -1;
  int tries = 0;

  // retry on failures
  for (tries = 0; tries < REQUEST_RETRIES; tries++)
  {
    CURL *curl = get_connection(path);
    curl_slist *headers = NULL;
    add_header(&headers, "X-Auth-Token", storage_token);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, debug);
    if (!strcasecmp(method, "MKDIR"))
    {
      curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
      curl_easy_setopt(curl, CURLOPT_INFILESIZE, 0);
      add_header(&headers, "Content-Type", "application/directory");
    }
    else if (!strcasecmp(method, "PUT") && fp)
    {
      rewind(fp);
      curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
      curl_easy_setopt(curl, CURLOPT_INFILESIZE, file_size(fileno(fp)));
      curl_easy_setopt(curl, CURLOPT_READDATA, fp);
    }
    else if (!strcasecmp(method, "GET"))
    {
      if (fp)
      {
        rewind(fp); // make sure the file is ready for a-writin'
        fflush(fp);
        ftruncate(fileno(fp), 0);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
      }
      else if (xmlctx)
      {
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, xmlctx);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &xml_dispatch);
      }
    }
    else
      curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method);
    /* add the headers from extra_headers if any */
    curl_slist *extra;
    for (extra = extra_headers; extra; extra = extra->next)
    {
      debugf("adding header: %s", extra->data);
      headers = curl_slist_append(headers, extra->data);
    }
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_perform(curl);
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
    curl_slist_free_all(headers);
    return_connection(curl);
    if (response >= 200 && response < 400)
      return response;
    sleep(8 << tries); // backoff
    if (response == 401 && !cloudfs_connect(0, 0, 0, 0)) // re-authenticate on 401s
      return response;
    if (xmlctx)
      xmlCtxtResetPush(xmlctx, NULL, 0, NULL, NULL);
  }
  return response;
}
Esempio n. 3
0
int main(int argc, char **argv)
{
  char line[1024];
  char username[sizeof(line)] = "", api_key[sizeof(line)] = "",
       settings_filename[sizeof(line)] = "", use_snet[sizeof(line)] = "",
       authurl[MAX_URL_SIZE] = "https://auth.api.rackspacecloud.com/v1.0";
  FILE *settings;
  int foreground = 0;
  struct fuse_args args = FUSE_ARGS_INIT(argc, argv);

  char *home = get_home_dir();
  snprintf(settings_filename, sizeof(settings_filename), "%s%s.cloudfuse",
           home,  home[strlen(home)] == '/' ? "" : "/");
  if ((settings = fopen(settings_filename, "r")))
  {
    while (fgets(line, sizeof(line), settings))
    {
      sscanf(line, " username = %[^\r\n ]", username);
      sscanf(line, " api_key = %[^\r\n ]", api_key);
      sscanf(line, " cache_timeout = %d", &cache_timeout);
      sscanf(line, " authurl = %[^\r\n ]", authurl);
      sscanf(line, " use_snet = %[^\r\n ]", use_snet);
    }
    fclose(settings);
  }
  if (!*username || !*api_key)
  {
    fprintf(stderr, "Unable to read %s\n", settings_filename);
    fprintf(stderr, "It should contain:\n\n");
    fprintf(stderr, "  username=[Mosso username]\n");
    fprintf(stderr, "  api_key=[Mosso api key]\n\n");
    fprintf(stderr, "These entries are optional:\n\n");
    fprintf(stderr, "  cache_timeout=[seconds for directory caching]\n");
    fprintf(stderr, "  use_snet=[True to connect to snet]\n");
    fprintf(stderr, "  authurl=[used for testing]\n");
    return 1;
  }

  fuse_parse_cmdline(&args, NULL, NULL, &foreground);
  cloudfs_debug(foreground);

  if (!cloudfs_connect(username, api_key, authurl,
        !strncasecmp(use_snet, "true", sizeof(use_snet))))
  {
    fprintf(stderr, "Unable to authenticate.\n");
    return 1;
  }

  static struct fuse_operations cfs_oper = {
    .readdir = cfs_readdir,
    .mkdir = cfs_mkdir,
    .read = cfs_read,
    .create = cfs_create,
    .open = cfs_open,
    .fgetattr = cfs_fgetattr,
    .getattr = cfs_getattr,
    .flush = cfs_flush,
    .release = cfs_release,
    .rmdir = cfs_rmdir,
    .ftruncate = cfs_ftruncate,
    .truncate = cfs_truncate,
    .write = cfs_write,
    .unlink = cfs_unlink,
    .fsync = cfs_fsync,
    .statfs = cfs_statfs,
    .chmod = cfs_chmod,
    .chown = cfs_chown,
  };

  pthread_mutex_init(&dmut, NULL);
  signal(SIGPIPE, SIG_IGN);
  return fuse_main(argc, argv, &cfs_oper, NULL);
}
Esempio n. 4
0
int main(int argc, char **argv)
{
    char settings_filename[MAX_PATH_SIZE] = "";
    FILE *settings;
    struct fuse_args args = FUSE_ARGS_INIT(argc, argv);

    snprintf(settings_filename, sizeof(settings_filename), "%s/.hubicfuse", get_home_dir());
    if ((settings = fopen(settings_filename, "r")))
    {
        char line[OPTION_SIZE];
        while (fgets(line, sizeof(line), settings))
            parse_option(NULL, line, -1, &args);
        fclose(settings);
    }

    fuse_opt_parse(&args, &options, NULL, parse_option);

    cache_timeout = atoi(options.cache_timeout);
    segment_size = atoll(options.segment_size);
    segment_above = atoll(options.segment_above);
    // this is ok since main is on the stack during the entire execution
    override_storage_url = options.storage_url;
    public_container = options.container;
    temp_dir = options.temp_dir;

    if (!*options.client_id || !*options.client_secret || !*options.refresh_token)
    {
        fprintf(stderr, "Unable to determine client_id, client_secret or refresh_token.\n\n");
        fprintf(stderr, "These can be set either as mount options or in "
                "a file named %s\n\n", settings_filename);
        fprintf(stderr, "  client_id=[App's id]\n");
        fprintf(stderr, "  client_secret=[App's secret]\n");
        fprintf(stderr, "  refresh_token=[Get it running hubic_token]\n");
        fprintf(stderr, "The following settings are optional:\n\n");
        fprintf(stderr, "  cache_timeout=[Seconds for directory caching, default 600]\n");
        fprintf(stderr, "  verify_ssl=[False to disable SSL cert verification]\n");
        fprintf(stderr, "  segment_size=[Size to use when creating DLOs, default 1073741824]\n");
        fprintf(stderr, "  segment_above=[File size at which to use segments, defult 2147483648]\n");
        fprintf(stderr, "  storage_url=[Storage URL for other tenant to view container]\n");
        fprintf(stderr, "  container=[Public container to view of tenant specified by storage_url]\n");
        fprintf(stderr, "  temp_dir=[Directory to store temp files]\n");

        return 1;
    }

    cloudfs_init();

    cloudfs_verify_ssl(!strcasecmp(options.verify_ssl, "true"));

    cloudfs_set_credentials(options.client_id, options.client_secret, options.refresh_token);

    if (!cloudfs_connect())
    {
        fprintf(stderr, "Failed to authenticate.\n");
        return 1;
    }

#ifndef HAVE_OPENSSL
#warning Compiling without libssl, will run single-threaded.
    fuse_opt_add_arg(&args, "-s");
#endif

    struct fuse_operations cfs_oper = {
        .readdir = cfs_readdir,
        .mkdir = cfs_mkdir,
        .read = cfs_read,
        .create = cfs_create,
        .open = cfs_open,
        .fgetattr = cfs_fgetattr,
        .getattr = cfs_getattr,
        .flush = cfs_flush,
        .release = cfs_release,
        .rmdir = cfs_rmdir,
        .ftruncate = cfs_ftruncate,
        .truncate = cfs_truncate,
        .write = cfs_write,
        .unlink = cfs_unlink,
        .fsync = cfs_fsync,
        .statfs = cfs_statfs,
        .chmod = cfs_chmod,
        .chown = cfs_chown,
        .rename = cfs_rename,
        .symlink = cfs_symlink,
        .readlink = cfs_readlink,
        .init = cfs_init,
    };

    pthread_mutex_init(&dmut, NULL);
    return fuse_main(args.argc, args.argv, &cfs_oper, &options);
}
Esempio n. 5
0
int main(int argc, char** argv)
{
#if __x86_64__ || __ppc64__
  const unsigned long MAX_SEGMENT_SIZE = (unsigned  long)5 * (unsigned long)(1 << 30);
#else
  const unsigned long MAX_SEGMENT_SIZE = (unsigned  long)2 * (unsigned long)(1 << 30);
#endif

  if (debug)
    fprintf(stderr, "Starting hubicfuse on homedir %s!\n", get_home_dir());

  signal(SIGINT, interrupt_handler);

  int return_code;
  FILE* settings;
  struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
  char default_settings[MAX_PATH_SIZE];

  // Default value for extra_options.settings_filename
  snprintf(default_settings, MAX_PATH_SIZE, "%s/.hubicfuse", get_home_dir());
  strncpy(extra_options.settings_filename, default_settings, MAX_PATH_SIZE);

  // Reading FUSE options
  fuse_opt_parse(&args, &options, NULL, parse_option);

  // Reading hubiC settings
  if ((settings = fopen(extra_options.settings_filename, "r")))
  {
    char line[OPTION_SIZE];
    while (fgets(line, sizeof(line), settings))
      parse_option(NULL, line, -1, &args);
    fclose(settings);
  }

  cache_timeout = atoi(options.cache_timeout);
  segment_size = atoll(options.segment_size);
  segment_above = atoll(options.segment_above);

  // check consistency

  if (segment_above > MAX_SEGMENT_SIZE)
  {
    printf ("A segment cannot be larger than 5Gb\n");
    return 1;
  }
  if (segment_size > segment_above)
  {
    printf ("segment_size must be smaller than segment_above\n");
    return 1;
  }

  // this is ok since main is on the stack during the entire execution
  override_storage_url = options.storage_url;
  public_container = options.container;
  temp_dir = options.temp_dir;

  if (!*options.client_id || !*options.client_secret || !*options.refresh_token)
  {
    fprintf(stderr,
            "Unable to determine client_id, client_secret or refresh_token.\n\n");
    fprintf(stderr, "These can be set either as mount options or in "
            "a file named %s\n\n", default_settings);
    fprintf(stderr, "  client_id=[App's id]\n");
    fprintf(stderr, "  client_secret=[App's secret]\n");
    fprintf(stderr, "  refresh_token=[Get it running hubic_token]\n");
    fprintf(stderr, "The following settings are optional:\n\n");
    fprintf(stderr,
            "  cache_timeout=[Seconds for directory caching, default 600]\n");
    fprintf(stderr, "  verify_ssl=[false to disable SSL cert verification]\n");
    fprintf(stderr,
            "  segment_size=[Size to use when creating DLOs, default 1073741824]\n");
    fprintf(stderr,
            "  segment_above=[File size at which to use segments, default 2147483648]\n");
    fprintf(stderr,
            "  storage_url=[Storage URL for other tenant to view container]\n");
    fprintf(stderr,
            "  container=[Public container to view of tenant specified by storage_url]\n");
    fprintf(stderr, "  temp_dir=[Directory to store temp files]\n");
    fprintf(stderr,
            "  get_extended_metadata=[true to enable download of utime, chmod, chown file attributes (but slower)]\n");
    fprintf(stderr,
            "  curl_verbose=[true to debug info on curl requests (lots of output)]\n");
    fprintf(stderr,
            "  curl_progress_state=[true to enable progress callback enabled. Mostly used for debugging]\n");
    fprintf(stderr,
            "  cache_statfs_timeout=[number of seconds to cache requests to statfs (cloud statistics), 0 for no cache]\n");
    fprintf(stderr,
            "  debug_level=[0 to 2, 0 for minimal verbose debugging. No debug if -d or -f option is not provided.]\n");
    fprintf(stderr, "  enable_chmod=[true to enable chmod support on fuse]\n");
    fprintf(stderr, "  enable_chown=[true to enable chown support on fuse]\n");
    return 1;
  }
  cloudfs_init();
  initialise_options();
  if (debug)
  {
    fprintf(stderr, "settings_filename = %s\n", extra_options.settings_filename);
    fprintf(stderr, "debug_level = %d\n", option_debug_level);
    fprintf(stderr, "get_extended_metadata = %d\n", option_get_extended_metadata);
    fprintf(stderr, "curl_progress_state = %d\n", option_curl_progress_state);
    fprintf(stderr, "enable_chmod = %d\n", option_enable_chmod);
    fprintf(stderr, "enable_chown = %d\n", option_enable_chown);
  }
  cloudfs_set_credentials(options.client_id, options.client_secret,
                          options.refresh_token);

  if (!cloudfs_connect())
  {
    fprintf(stderr, "Failed to authenticate.\n");
    return 1;
  }
  //todo: check why in some cases the define below is not available (when running the binary on symbolic linked folders)
#ifndef HAVE_OPENSSL
#warning Compiling without libssl, will run single-threaded.
  fuse_opt_add_arg(&args, "-s");
#endif

  struct fuse_operations cfs_oper =
  {
    .readdir = cfs_readdir,
    .mkdir = cfs_mkdir,
    .read = cfs_read,
    .create = cfs_create,
    .open = cfs_open,
    .fgetattr = cfs_fgetattr,
    .getattr = cfs_getattr,
    .flush = cfs_flush,
    .release = cfs_release,
    .rmdir = cfs_rmdir,
    .ftruncate = cfs_ftruncate,
    .truncate = cfs_truncate,
    .write = cfs_write,
    .unlink = cfs_unlink,
    .fsync = cfs_fsync,
    .statfs = cfs_statfs,
    .chmod = cfs_chmod,
    .chown = cfs_chown,
    .rename = cfs_rename,
    .symlink = cfs_symlink,
    .readlink = cfs_readlink,
    .init = cfs_init,
    .utimens = cfs_utimens,
#ifdef HAVE_SETXATTR
    .setxattr = cfs_setxattr,
    .getxattr = cfs_getxattr,
    .listxattr = cfs_listxattr,
    .removexattr = cfs_removexattr,
#endif
  };

  pthread_mutexattr_init(&mutex_attr);
  pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
  pthread_mutex_init(&dcachemut, &mutex_attr);
  return_code = fuse_main(args.argc, args.argv, &cfs_oper, &options);

  if (return_code > 0 && !strcmp(extra_options.help, "true"))
  {
    fprintf(stderr, "\nhubiC options:\n");
    fprintf(stderr, "    -o settings_filename=FILE  use FILE as hubiC settings\n");
    fprintf(stderr, "                               instead of %s\n", default_settings);
  }

  return return_code;
}