cURL / Mailing Lists / curl-library / Single Mail

curl-library

The problem of implementing ftp client function: listDirContents()

From: HU Chengzhe <Chengzhe.Hu_at_alcatel-sbell.com.cn>
Date: Mon, 23 Aug 2010 09:06:18 +0800

Hello,
    when I plan to implement some ftp client functions based on
libcurl, I encounter some problems:
   
    listDirContents(), this function is expected to return the detail
file informations of the specific directory, such as like this:
       -r--r--r-- 1 oamops oamgroup 9539 Jul 9 2008 .alias_oam
     
my code is as follow:
 
________________________________________________________________________
_______
 struct FtpFile {
  const char *filename;
  FILE *stream;
};

static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void
*stream)
{
  struct FtpFile *out=(struct FtpFile *)stream;
  if(out && !out->stream) {
    /* open file for writing */
    out->stream=fopen(out->filename, "wb");
    if(!out->stream)
      return -1; /* failure, can't open file to write */
  }
  return fwrite(buffer, size, nmemb, out->stream);
}

struct MemoryStruct {
  char *memory;
  size_t size;
};
 
static void *myrealloc(void *ptr, size_t size);
 
static void *myrealloc(void *ptr, size_t size)
{
  if(ptr)
    return realloc(ptr, size);
  else
    return malloc(size);
}

static size_t
WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
  size_t realsize = size * nmemb;
  struct MemoryStruct *mem = (struct MemoryStruct *)data;
 
  mem->memory = (char *)myrealloc(mem->memory, mem->size + realsize +
1);
  if (mem->memory) {
    memcpy(&(mem->memory[mem->size]), ptr, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;
  }
  return realsize;
}

int main(void){
     CURL *curl;
  CURLcode res;
  struct FtpFile ftpfile={
    "./dadafile", /* name to store the file as if succesful */
    NULL
  };

  curl_global_init(CURL_GLOBAL_DEFAULT);

struct MemoryStruct chunk;
 
  chunk.memory=NULL; /* we expect realloc(NULL, size) to work */
  chunk.size = 0;

  curl = curl_easy_init();
  if(curl) {
   
    curl_easy_setopt(curl, CURLOPT_URL,
                     "ftp://137.212.232.82");
    //set username for transfer
    curl_easy_setopt(curl, CURLOPT_USERNAME, "user");

    //set password for transfer
    curl_easy_setopt(curl, CURLOPT_PASSWORD, "user");

    struct curl_slist *headerlist = NULL;
    const char s[] = "PWD";
    const char s1[] = "LIST ";
    const char s2[] = "CWD /home/oamops/cid";
    headerlist = curl_slist_append(headerlist, s);
    headerlist = curl_slist_append(headerlist, s2);
   headerlist = curl_slist_append(headerlist, s1);
   curl_easy_setopt(curl, CURLOPT_POSTQUOTE, headerlist);
  
  /* As I am not sure the return list would be by header or data,
   * I try the two ways at same time
  */
   curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, WriteMemoryCallback);
   curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *)&chunk);
   
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);

    res = curl_easy_perform(curl);

    /* always cleanup */
    curl_easy_cleanup(curl);

    if(CURLE_OK != res) {
      /* we failed */
      fprintf(stderr, "curl told us %d\n", res);
    }
}
    if(ftpfile.stream)
    fclose(ftpfile.stream); /* close the local file */
   
    cout<<"#####################"<<endl;
    cout<<"chunk.size: "<<chunk.size<<endl;
    cout<<"chunk.memory: "<<chunk.memory<<endl;
  
  curl_global_cleanup();

}
_________________________________________________________________
expected result: the list of file information for directory
"/home/oamops/cid" would display in file datafile or print to stdout.
actual result:
the context in file datafile is the list of file information for ftp
server root path ("home/oamops"), not the "/home/oamops/cid" .
the stdout is:
chunk.size: 595
chunk.memory: 220-Restricted Access System
220-
220 zsups382 FTP server ready.
331 Password required for oamops.
230 User oamops logged in.
257 "/home/oamops" is current directory.
229 Entering Extended Passive Mode (|||46616|)
200 Type set to A.
150 Opening ASCII mode data connection for /bin/ls.
226 Transfer complete.
257 "/home/oamops" is current directory.
425 Can't build data connection: Connection refused.
221-You have transferred 0 bytes in 0 files.
221-Total traffic for this session was 3409 bytes in 1 transfers.
221-Thank you for using the FTP service on zsups382.
221 Goodbye.

so my question is:
1) why the actual result is not same as expected result?
2) Or Is there some code wrong?
3) My thought about implementation of listDirContents() is right? Is
there some way is more convenient than mine?

Thank you for answer in advanced.

Best Regards,
Arkie

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2010-08-23