StudentX
StudentX

Reputation: 2323

Why this is not working ? libcurl & c++

I am new to libcurl and am trying to get filelist from a server using ftp, going through the examples and some other posts here, I have come up with the following code. But when I run it, it returns error message :

Failed writing body (4294967295 != 129)

in the error string set by CURLOPT_ERRORBUFFER. The curl_easy_strerror( res ) returns:

Failed writing received data to disk/application

struct FtpFile 
{
    const char *filename;
    FILE *stream;
};

static size_t fileWrite( void *buffer, size_t size, size_t nmemb, void *stream )
{
    struct FtpFile *out=(struct FtpFile *)stream;
    if(out && !out->stream) 
    {
        out->stream=fopen(out->filename, "wb");
        if(!out->stream)
        {
            cout << out->filename << " open failure [fileWrite] " << endl;
            return -1;
        }
    }

    size_t written = fwrite(buffer, size, nmemb, out->stream);    
    cout << written << endl;
    if(written <= 0)
        cout << "Nothing written : " << written;

    return written;
}

void getFileList( const char* url, const char* fname )
{
    CURL *curl;
    CURLcode res;
    FILE *ftpfile;
    const char *errmsg;


    ftpfile = fopen(fname, "wb"); 
    if ( ftpfile == NULL )
    {
        cout << fname << " open failure [getFileList] " << endl ;
        return;
    } 

    curl = curl_easy_init();
    if(curl) 
    {
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fileWrite);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, ftpfile);         
        curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errmsg);            
        curl_easy_setopt(curl, CURLOPT_USERNAME, "username");
        curl_easy_setopt(curl, CURLOPT_PASSWORD, "password");
        curl_easy_setopt(curl, CURLOPT_FTPLISTONLY,TRUE);
        res = curl_easy_perform(curl);
        if(res != CURLE_OK)
        {
            fprintf( stderr, "curl_easy_perform() failed: %s\nError Message: %s\n", curl_easy_strerror( res ), errmsg );
        }

        curl_easy_cleanup(curl);
    }

    fclose(ftpfile);
}

int main(int argc, char *argv[])
{
    getFileList( "ftp://ftp.example.com/public/somefolder/", "file-list.txt" );

    system("PAUSE");
    return EXIT_SUCCESS;
}

Upvotes: 1

Views: 6939

Answers (2)

kmkaplan
kmkaplan

Reputation: 18960

First, your fileWrite function should return the number of bytes written. fwrite returns the number of objects written. So you have to return written * size;

Then, as Daniel Stenberg notes, you are passing a FILE * to fileWrite but using it as a struct FtpFile *. Try this one instead:

static size_t fileWrite( void *buffer, size_t size, size_t nmemb, void *stream )
{
  size_t written = fwrite(buffer, size, nmemb, (FILE*)stream);
  std::cout << written * size << std::endl;
  if(written <= 0)
    std::cout << "Nothing written : " << written;
  return written * size;
}

Upvotes: 0

Daniel Stenberg
Daniel Stenberg

Reputation: 58002

4294967295 is the 32 bit unsigned version of -1, which probably is what your callback returned and thus libcurl considered it an error and stopped everything.

Where is ->filename assigned?

You pass in a FILE * to CURLOPT_WRITEDATA and yet your callback reads it as a struct FtpFile *...

Upvotes: 2

Related Questions