diff --git a/urifs.c b/urifs.c index 1fbeb6a..f9842c2 100644 --- a/urifs.c +++ b/urifs.c @@ -17,9 +17,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * - * Requirement: libfuse, libcurl and libxml2 + * Requirement: libfuse, libcurl, libxml2 and libcrypto (openssl) * - * Compile with: gcc -O3 -o urifs urifs.c -Wall -ansi -W -std=c99 -D_GNU_SOURCE `pkg-config --cflags --libs libxml-2.0 fuse libcurl` + * Compile with: gcc -g -o urifs urifs.c -Wall -ansi -W -std=c99 -D_GNU_SOURCE `pkg-config --cflags --libs libxml-2.0 fuse libcurl libcrypto` * */ @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include @@ -45,6 +47,7 @@ typedef struct { char *uri; size_t size; + struct curl_slist *header; } uri_fd; uri_fd ** opened_files = NULL; @@ -52,6 +55,7 @@ uri_fd ** opened_files = NULL; char *source_xml; FILE *debug_f = NULL; +FILE *error_f = NULL; #define DEBUG(...) { if(debug_f) { fprintf(debug_f,"%s::%s:%d ",__FILE__,__func__,__LINE__);fprintf(debug_f,__VA_ARGS__); fprintf(debug_f,"\n"); fflush(debug_f); } } @@ -62,6 +66,53 @@ static inline void xfree(void *p) p=NULL; } +static pthread_mutex_t *lockarray; + +static void lock_callback(int mode, int type, char *file, int line) +{ + (void)file; + (void)line; + if (mode & CRYPTO_LOCK) { + pthread_mutex_lock(&(lockarray[type])); + } + else { + pthread_mutex_unlock(&(lockarray[type])); + } +} + +static unsigned long thread_id(void) +{ + unsigned long ret; + + ret=(unsigned long)pthread_self(); + return(ret); +} + +static void init_locks(void) +{ + int i; + + lockarray=(pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); + for (i=0; iread + realsize > buffer->size) @@ -111,12 +162,34 @@ static size_t curl_get_callback(void *contents, size_t size, size_t nmemb, void memcpy(buffer->data+buffer->read, contents, realsize); buffer->read += realsize; + DEBUG("return: %lu", realsize) return realsize; } +static void header_cmd(uri_fd *fd, const char *cmd) +{ + DEBUG("args: uri_fd *fd = %p, const char *cmd = \"%s\"", fd, cmd) + FILE *fp = popen(cmd, "r"); + char *line = NULL; + size_t len = 0; + ssize_t read; + + if (fp != NULL) + { + while ((read = getline(&line, &len, fp)) > 0 && line) + { + line[read-1] = '\0'; + fd->header = curl_slist_append(fd->header,line); + DEBUG("Added header \"%s\"", line) + } + xfree(line); + pclose(fp); + } +} + static int urifs_getattr(const char *path, struct stat *stbuf) { - DEBUG("here") + DEBUG("args: const char *path = \"%s\", struct stat *stbuf = %p", path, stbuf) xmlChar *value; xmlNodeSetPtr nodes; xmlNodePtr node; @@ -124,14 +197,20 @@ static int urifs_getattr(const char *path, struct stat *stbuf) char *xpath = xpath_from_path(path); if (!xpath) + { + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; + } DEBUG("xpath: %s", xpath); xpathObj = xmlXPathEvalExpression((xmlChar*)xpath, fuse_get_context()->private_data); xfree(xpath); if(xpathObj == NULL) + { + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; + } nodes = xpathObj->nodesetval; @@ -216,6 +295,7 @@ static int urifs_getattr(const char *path, struct stat *stbuf) DEBUG("mode: %d", stbuf->st_mode) xmlXPathFreeObject(xpathObj); + DEBUG("return: 0") return 0; } else @@ -223,6 +303,7 @@ static int urifs_getattr(const char *path, struct stat *stbuf) xmlXPathFreeObject(xpathObj); + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; } @@ -230,8 +311,7 @@ static int urifs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, of { (void)offset; (void)fi; - DEBUG("here") - DEBUG("trying '%s'",path); + DEBUG("args: const char *path = \"%s\", void *buf = %p, fuse_fill_dir_t filler = %p, off_t offset = %lu, int fi->fh = %lu", path, buf, filler, offset, fi->fh) int i; int nb; char *xpath; @@ -241,11 +321,15 @@ static int urifs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, of char *tmp = xpath_from_path(path); if (!tmp) + { + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; + } if (asprintf(&xpath, "%s/*[@name]", tmp) == -1) { xfree(tmp); + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; } xfree(tmp); @@ -255,7 +339,10 @@ static int urifs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, of xpathObj = xmlXPathEvalExpression((xmlChar*)xpath, fuse_get_context()->private_data); xfree(xpath); if(xpathObj == NULL) + { + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; + } nodes = xpathObj->nodesetval; @@ -276,13 +363,17 @@ static int urifs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, of } } xmlXPathFreeObject(xpathObj); + DEBUG("return: 0") return 0; } else + { DEBUG("Invalid Xpath") + } xmlXPathFreeObject(xpathObj); + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; } @@ -290,12 +381,14 @@ static int urifs_create(const char *path, mode_t mode, struct fuse_file_info *fi { (void)mode; (void)fi; - DEBUG("here %s", path) + DEBUG("args: const char *path = \"%s\", mode_t mode = %d, int fi->fh = %lu", path, mode, fi->fh) + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; } static int urifs_open(const char *path, struct fuse_file_info *fi) { + DEBUG("args: const char *path = \"%s\", int fi->fh = %lu", path, fi->fh) DEBUG("here") int i = 0; uri_fd *fd = NULL; @@ -306,14 +399,20 @@ static int urifs_open(const char *path, struct fuse_file_info *fi) char *xpath = xpath_from_path(path); if (!xpath) + { + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; + } DEBUG("xpath: %s", xpath); xpathObj = xmlXPathEvalExpression((xmlChar*)xpath, fuse_get_context()->private_data); xfree(xpath); if(xpathObj == NULL) + { + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; + } nodes = xpathObj->nodesetval; @@ -323,9 +422,10 @@ static int urifs_open(const char *path, struct fuse_file_info *fi) node = nodes->nodeTab[0]; fd = (uri_fd*)malloc(sizeof(uri_fd)); - fd->uri = NULL; if (fd) { + fd->uri = NULL; + fd->header = NULL; value = xmlGetProp(node, (xmlChar*)"size"); if(value) { @@ -338,6 +438,19 @@ static int urifs_open(const char *path, struct fuse_file_info *fi) xmlFree(value); if(fd->uri) { + value = xmlGetProp(node, (xmlChar*)"header"); + if(value) + { + fd->header = curl_slist_append(fd->header,(char*)value); + DEBUG("Added header \"%s\"", (char*)value) + xmlFree(value); + } + value = xmlGetProp(node, (xmlChar*)"header-cmd"); + if(value) + { + header_cmd(fd, (char*)value); + xmlFree(value); + } while((i < MAX_ENTRIES)&&(opened_files[i])) i++; if(i < MAX_ENTRIES) @@ -345,8 +458,10 @@ static int urifs_open(const char *path, struct fuse_file_info *fi) fi->fh = i; opened_files[i] = fd; xmlXPathFreeObject(xpathObj); + DEBUG("return: 0") return 0; } + curl_slist_free_all(fd->header); xfree(fd->uri); } } @@ -359,24 +474,35 @@ static int urifs_open(const char *path, struct fuse_file_info *fi) xmlXPathFreeObject(xpathObj); + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; } static int urifs_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { (void)path; - DEBUG("here") + DEBUG("args: const char *path = \"%s\", char *buf = %p, size_t size = %lu, off_t offset = %lu, int fi->fh = %lu", path, buf, size, offset, fi->fh) size_t bytes; uri_fd *fd; char *range; CURL *curl_handle; + CURLcode res; struct curl_buffer buffer; + long http_code = 0; - if(size == 0) { return 0; } + if(size == 0) + { + DEBUG("return: 0") + return 0; + } fd = opened_files[fi->fh]; - if (!fd) { return -ENOENT; } + if (!fd) + { + DEBUG("return: -ENOENT(%d)", -ENOENT) + return -ENOENT; + } if((size + offset) >= fd->size) { bytes = fd->size - offset; @@ -384,26 +510,42 @@ static int urifs_read(const char *path, char *buf, size_t size, off_t offset, st bytes = size; } - if(asprintf(&range, "%llu-%llu", (unsigned long long)offset, (unsigned long long)offset+(unsigned long long)bytes-1) == -1) + if(asprintf(&range, "%llu-%llu", (unsigned long long)offset, (unsigned long long)offset+(unsigned long long)bytes-1) == -1) + { + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; + } DEBUG("Range: %s (bytes: %llu)", range, (unsigned long long)bytes); - buffer.data = buf; - buffer.size = bytes; - buffer.read = 0; - curl_handle = curl_easy_init(); curl_easy_setopt(curl_handle, CURLOPT_URL, fd->uri); + curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, curl_get_callback); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&buffer); curl_easy_setopt(curl_handle, CURLOPT_RANGE, range); + curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, fd->header); + curl_easy_setopt(curl_handle, CURLOPT_FAILONERROR, 1); - curl_easy_perform(curl_handle); - curl_easy_cleanup(curl_handle); + buffer.data = buf; + buffer.size = bytes; + buffer.read = 0; + res = curl_easy_perform(curl_handle); + curl_easy_getinfo (curl_handle, CURLINFO_RESPONSE_CODE, &http_code); + DEBUG("curl_easy_perform() HTTP code %li", http_code); + + if(res != CURLE_OK) + { + DEBUG("curl_easy_perform() failed: %s (%s)", curl_easy_strerror(res),fd->uri); + curl_easy_cleanup(curl_handle); + xfree(range); + return -ENOENT; + } + curl_easy_cleanup(curl_handle); xfree(range); + DEBUG("return: %lu", buffer.read) return buffer.read; } @@ -414,7 +556,8 @@ static int urifs_write(const char *path, const char *buf, size_t size, off_t off (void)size; (void)offset; (void)fi; - DEBUG("here") + DEBUG("args: const char *path = \"%s\", char *buf = %p, size_t size = %lu, off_t offset = %lu, int fi->fh = %lu", path, buf, size, offset, fi->fh) + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; } @@ -423,26 +566,35 @@ static int urifs_fsync(const char *path, int datasync, struct fuse_file_info *fi (void)path; (void)datasync; (void)fi; - DEBUG("here") + DEBUG("args: const char *path = \"%s\", int datasync = %d, int fi->fh = %lu", path, datasync, fi->fh) + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; } static int urifs_release(const char *path, struct fuse_file_info *fi) { (void)path; - DEBUG("here") - if(fi->fh > MAX_ENTRIES) { return -ENOENT; } + DEBUG("args: const char *path = \"%s\", int fi->fh = %lu", path, fi->fh) + if(fi->fh > MAX_ENTRIES) + { + DEBUG("return: -ENOENT(%d)", -ENOENT) + return -ENOENT; + } DEBUG("closing file %lu",fi->fh) + curl_slist_free_all(opened_files[fi->fh]->header); xfree(opened_files[fi->fh]->uri); xfree(opened_files[fi->fh]); opened_files[fi->fh] = NULL; + + DEBUG("return: 0") return 0; } void urifs_cleanup(void *data) { (void)data; + DEBUG("args: void *data = %p", data) DEBUG("here") xmlXPathContextPtr xpathCtx = fuse_get_context()->private_data; xmlDocPtr doc = xpathCtx->doc; @@ -451,6 +603,7 @@ void urifs_cleanup(void *data) { if(opened_files[i]!=NULL) { + curl_slist_free_all(opened_files[i]->header); xfree(opened_files[i]->uri); xfree(opened_files[i]); } @@ -467,14 +620,15 @@ int urifs_flush(const char *path, struct fuse_file_info *fi) { (void)path; (void)fi; - DEBUG("here") + DEBUG("args: const char *path = \"%s\", int fi->fh = %lu", path, fi->fh) + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; } int urifs_statfs(const char *path, struct statvfs *stats) { (void)path; - DEBUG("here") + DEBUG("args: const char *path = \"%s\", struct statvfs *stats = %p", path, stats) stats->f_bsize = 0; stats->f_frsize = 0; stats->f_blocks = 0; @@ -483,6 +637,7 @@ int urifs_statfs(const char *path, struct statvfs *stats) stats->f_namemax = 512; stats->f_files = 1000000000; stats->f_ffree = 1000000000; + DEBUG("return: 0") return 0; } @@ -490,7 +645,8 @@ int urifs_truncate(const char *path, off_t size) { (void)path; (void)size; - DEBUG("here") + DEBUG("args: const char *path = \"%s\", off_t size = %lu", path, size) + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; } @@ -499,14 +655,17 @@ int urifs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi) (void)path; (void)size; (void)fi; + DEBUG("args: const char *path = \"%s\", off_t size = %lu, int fi->fh = %lu", path, size, fi->fh) DEBUG("here") + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; } int urifs_unlink(const char *path) { (void)path; - DEBUG("here") + DEBUG("args: const char *path = \"%s\"", path) + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; } @@ -514,7 +673,8 @@ int urifs_rename(const char *from, const char *to) { (void)from; (void)to; - DEBUG("here") + DEBUG("args: const char *from = \"%s\", const char *to = \"%s\"", from, to) + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; } @@ -522,14 +682,15 @@ int urifs_mkdir(const char *dir, mode_t ignored) { (void)dir; (void)ignored; - DEBUG("here") + DEBUG("args: const char *dir = \"%s\", mode_t ignored = %u", dir, ignored) + DEBUG("return: -ENOENT(%d)", -ENOENT) return -ENOENT; } void *urifs_init(struct fuse_conn_info *conn) { (void)conn; - DEBUG("here") + DEBUG("args: struct fuse_conn_info *conn = %p", conn) int i; xmlDocPtr doc; xmlXPathContextPtr xpathCtx; @@ -542,12 +703,16 @@ void *urifs_init(struct fuse_conn_info *conn) doc = xmlParseFile(source_xml); if (doc == NULL) + { + DEBUG("Can't parse %s", source_xml) exit(1); + } xpathCtx = xmlXPathNewContext(doc); if (xpathCtx == NULL) { xmlFreeDoc(doc); + DEBUG("Can't get xmlXPathNewContext") exit(1); } @@ -557,6 +722,7 @@ void *urifs_init(struct fuse_conn_info *conn) curl_global_init(CURL_GLOBAL_ALL); + DEBUG("return: -ENOENT(%d)", -ENOENT) return xpathCtx; } @@ -584,14 +750,14 @@ static int urifs_opt_proc(void *data, const char *arg, int key, struct fuse_args { (void)data; (void)outargs; - DEBUG("here") + DEBUG("args: void *data = %p, const char *arg = \"%s\", int key = %d, struct fuse_args *outargs = %p", data, arg, key, outargs) static int num = 0; switch(key) { case FUSE_OPT_KEY_OPT: if(strcmp(arg, "--debug") == 0) { debug_f = fopen(LOG_FILE,"w"); - fprintf(stderr,"debug mode started\n"); + DEBUG("debug mode started") return 0; } else if(strcmp(arg, "-oallow-other") == 0) { return 0; @@ -610,7 +776,6 @@ static int urifs_opt_proc(void *data, const char *arg, int key, struct fuse_args int main(int argc, char *argv[]) { - DEBUG("here") struct fuse_args args = FUSE_ARGS_INIT(argc, argv); if (argc < 2) { @@ -625,5 +790,12 @@ int main(int argc, char *argv[]) if(source_xml == NULL) return -1; - return fuse_main(args.argc, args.argv, &urifs_oper, NULL); + init_locks(); + + int ret = fuse_main(args.argc, args.argv, &urifs_oper, NULL); + DEBUG("return: %d", ret) + + kill_locks(); + + return ret; }