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)