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; }
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; }
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); }
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); }
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; }