Package: curlftpfs Version: 0.9.2-9+b1 Hi!
I'm using curlftpfs to backup data off a FTP server. Works mostly, but it breaks with an I/O error for a directory containins a single ' ' (space) in its name. Seems this bug is known upstream. The `curl` people claim that curlftpfs supplies a wrong URL (https://github.com/curl/curl/issues/7621), while a matching bug report exists for curlftpfs on the SF.net site (https://sourceforge.net/p/curlftpfs/bugs/74/). While curlftpfs is _really_ a useful piece of software, it's mostly mature and it seems there isn't done a whole lot of maintenance these days. Maybe we'd like to fix this for Debian? I guess it's not even a hard fix... There is actually already a fix for a similar issue in https://github.com/JackSlateur/curlftpfs/commit/85f3a9ef2accb1093f28c424c72068a06182d6f9 where the author seems to have had issues with '%' and "#". This is an adopted version, additionally incorporating the space character (though no other: an useful extension might be stuff like TABs or '?' or '+' ...) It's in the "Works for me[tm]" state. --- ftpfs.c~bak 2022-06-07 12:47:17.662097505 +0200 +++ ftpfs.c 2022-06-07 13:37:03.054256599 +0200 @@ -208,6 +208,54 @@ ftpfs.attached_to_multi = 0; } +// Code from stackoverflow +static char *replace (char const * const original, char const * const pattern, char const * const replacement) { + size_t const replen = strlen(replacement); + size_t const patlen = strlen(pattern); + size_t const orilen = strlen(original); + size_t patcnt = 0; + const char *oriptr; + const char *patloc; + + // find how many times the pattern occurs in the original string + for (oriptr = original; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen) + patcnt++; + + { + // allocate memory for the new string + size_t const retlen = orilen + patcnt * (replen - patlen); + char * const returned = (char *) malloc( sizeof(char) * (retlen + 1) ); + + if (returned != NULL){ + // copy the original string, + // replacing all the instances of the pattern + char * retptr = returned; + for (oriptr = original; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen){ + size_t const skplen = patloc - oriptr; + // copy the section until the occurence of the pattern + strncpy(retptr, oriptr, skplen); + retptr += skplen; + // copy the replacement + strncpy(retptr, replacement, replen); + retptr += replen; + } + // copy the rest of the string. + strcpy(retptr, oriptr); + } + return returned; + } +} + +char* urlencode(char const * const original){ + //Always process % first + char *tmp_percent = replace(original, "%", "%25"); + char *tmpsharp = replace(tmp_percent, "#", "%23"); + char *tmpspace = replace(tmpsharp, " ", "%20"); + free(tmp_percent); + free(tmpsharp); + return tmpspace; +} + static int op_return(int err, char * operation) { if(!err) @@ -247,6 +295,7 @@ #define curl_easy_setopt_or_die(handle, option, ...) \ do {\ + if (option == CURLOPT_URL) fprintf (stderr, "Access to: %s\n", __VA_ARGS__);\ CURLcode res = curl_easy_setopt(handle, option, __VA_ARGS__);\ if (res != CURLE_OK) {\ fprintf(stderr, "Error setting curl: %s\n", error_buf);\ @@ -254,8 +303,9 @@ }\ }while(0) -static int ftpfs_getdir(const char* path, fuse_cache_dirh_t h, +static int ftpfs_getdir(const char* path_tmp, fuse_cache_dirh_t h, fuse_cache_dirfil_t filler) { + char * const path = urlencode(path_tmp); int err = 0; CURLcode curl_res; char* dir_path = get_fulldir_path(path); @@ -282,10 +332,12 @@ free(dir_path); buf_free(&buf); + free(path); return op_return(err, "ftpfs_getdir"); } -static int ftpfs_getattr(const char* path, struct stat* sbuf) { +static int ftpfs_getattr(const char* path_tmp, struct stat* sbuf) { + char * const path = urlencode(path_tmp); int err; CURLcode curl_res; char* dir_path = get_dir_path(path); @@ -306,13 +358,14 @@ } buf_null_terminate(&buf); - char* name = strrchr(path, '/'); + char* name = strrchr(path_tmp, '/'); ++name; err = parse_dir((char*)buf.p, dir_path + strlen(ftpfs.host) - 1, name, sbuf, NULL, 0, NULL, NULL); free(dir_path); buf_free(&buf); + free(path); if (err) return op_return(-ENOENT, "ftpfs_getattr"); return 0; } @@ -699,9 +752,9 @@ return sbuf.st_size; } -static int ftpfs_open_common(const char* path, mode_t mode, +static int ftpfs_open_common(const char* path_tmp, mode_t mode, struct fuse_file_info* fi) { - + char * const path = urlencode(path_tmp); char * flagsAsStr = flags_to_string(fi->flags); DEBUG(2, "ftpfs_open_common: %s\n", flagsAsStr); int err = 0; @@ -808,6 +861,7 @@ if (err) free_ftpfs_file(fh); + free(path); g_free(flagsAsStr); return op_return(err, "ftpfs_open"); } @@ -823,8 +877,9 @@ } #endif -static int ftpfs_read(const char* path, char* rbuf, size_t size, off_t offset, +static int ftpfs_read(const char* path_tmp, char* rbuf, size_t size, off_t offset, struct fuse_file_info* fi) { + char * const path = urlencode(path_tmp); int ret; struct ftpfs_file *fh = get_ftpfs_file(fi); @@ -844,7 +899,8 @@ } else { ret = size_read; } - + free(path); + if (ret<0) op_return(ret, "ftpfs_read"); return ret; } Also, I had to s/5/7/ in ./debian/compat to build it. Seems this package didn't get updates in the last seven years?! MfG, JBG --
signature.asc
Description: PGP signature