removed the fixed dir depth limit in the FTP code
authorDaniel Stenberg <daniel@haxx.se>
Thu, 15 Apr 2004 07:52:39 +0000 (07:52 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 15 Apr 2004 07:52:39 +0000 (07:52 +0000)
CHANGES
RELEASE-NOTES
lib/ftp.c
lib/urldata.h
tests/data/test142

diff --git a/CHANGES b/CHANGES
index b802a61..7477dc4 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,13 @@
 
                                   Changelog
 
+Daniel (15 April 2004)
+- Removed the fixed maximum amount of dir levels the FTP code supported.
+  Previously we had a fixed array for 100 levels, now we save space in each
+  handle by allocating only for a few level by default and then enlarging that
+  in case of need (with no maximum depth). Adjusted test case 142 to verify
+  that 150 dir levels work fine.
+
 Daniel (14 April 2004)
 - Asking for CURL_IPRESOLVE_V6 when ipv6 addresses can't be resolved will
   now cause the resolve function to return NULL immediately. This flaw was
index 9caf178..e8914b2 100644 (file)
@@ -7,6 +7,7 @@ Curl and libcurl 7.11.2. A bugfix release.
 
 This release includes the following changes:
 
+ o removed maximum dir depth limit in the FTP code
  o the ares build now requires c-ares 1.2.0 or later
  o --tcp-nodelay and CURLOPT_TCP_NODELAY were added
  o curl/curlver.h contains the libcurl version info now
index d9028d4..7b942d8 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -124,9 +124,19 @@ static CURLcode ftp_cwd_and_mkd(struct connectdata *conn, char *path);
 static void freedirs(struct FTP *ftp)
 {
   int i;
-  for (i=0; ftp->dirs[i]; i++){
-    free(ftp->dirs[i]);
-    ftp->dirs[i]=NULL;
+  if(ftp->dirs) {
+    for (i=0; i < ftp->dirdepth; i++){
+      if(ftp->dirs[i]) {
+        free(ftp->dirs[i]);
+        ftp->dirs[i]=NULL;
+      }
+    }
+    free(ftp->dirs);
+    ftp->dirs = NULL;
+  }
+  if(ftp->file) {
+    free(ftp->file);
+    ftp->file = NULL;
   }
 }
 
@@ -732,14 +742,9 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
   int ftpcode;
   CURLcode result=CURLE_OK;
 
-  /* free the dir tree parts */
+  /* free the dir tree and file parts */
   freedirs(ftp);
 
-  if(ftp->file) {
-    free(ftp->file);
-    ftp->file = NULL;
-  }
-
   if(data->set.upload) {
     if((-1 != data->set.infilesize) &&
        (data->set.infilesize != *ftp->bytecountp) &&
@@ -2317,7 +2322,6 @@ CURLcode Curl_ftp(struct connectdata *conn)
   char *slash_pos;  /* position of the first '/' char in curpos */
   char *cur_pos=conn->ppath; /* current position in ppath. point at the begin
                                 of next path component */
-  int path_part=0;/* current path component */
 
   /* the ftp struct is already inited in ftp_connect() */
   ftp = conn->proto.ftp;
@@ -2329,23 +2333,28 @@ CURLcode Curl_ftp(struct connectdata *conn)
   Curl_pgrsSetUploadSize(data, 0);
   Curl_pgrsSetDownloadSize(data, 0);
 
-  /*  fixed : initialize ftp->dirs[xxx] to NULL !
-      is done in Curl_ftp_connect() */
-
+  ftp->dirdepth = 0;
+  ftp->diralloc = 5; /* default dir depth to allocate */
+  ftp->dirs = (char **)malloc(ftp->diralloc * sizeof(ftp->dirs[0]));
+  if(!ftp->dirs)
+    return CURLE_OUT_OF_MEMORY;
+  ftp->dirs[0] = NULL; /* to start with */
+  
   /* parse the URL path into separate path components */
   while((slash_pos=strchr(cur_pos, '/'))) {
     /* 1 or 0 to indicate absolute directory */
-    bool absolute_dir = (cur_pos - conn->ppath > 0) && (path_part == 0);
+    bool absolute_dir = (cur_pos - conn->ppath > 0) && (ftp->dirdepth == 0);
 
     /* seek out the next path component */
     if (slash_pos-cur_pos) {
       /* we skip empty path components, like "x//y" since the FTP command CWD
          requires a parameter and a non-existant parameter a) doesn't work on
          many servers and b) has no effect on the others. */
-      ftp->dirs[path_part] = curl_unescape(cur_pos - absolute_dir,
-                                           slash_pos - cur_pos + absolute_dir);
+      ftp->dirs[ftp->dirdepth] = curl_unescape(cur_pos - absolute_dir,
+                                               slash_pos - cur_pos +
+                                               absolute_dir);
     
-      if (!ftp->dirs[path_part]) { /* run out of memory ... */
+      if (!ftp->dirs[ftp->dirdepth]) { /* run out of memory ... */
         failf(data, "no memory");
         freedirs(ftp);
         return CURLE_OUT_OF_MEMORY;
@@ -2358,12 +2367,16 @@ CURLcode Curl_ftp(struct connectdata *conn)
 
     if(!retcode) {
       cur_pos = slash_pos + 1; /* jump to the rest of the string */
-      if(++path_part >= (CURL_MAX_FTP_DIRDEPTH-1)) {
-        /* too deep, we need the last entry to be kept NULL at all
-           times to signal end of list */
-        failf(data, "too deep dir hierarchy");
-        freedirs(ftp);
-        return CURLE_URL_MALFORMAT;
+      if(++ftp->dirdepth >= ftp->diralloc) {
+        /* enlarge array */
+        char *bigger;
+        ftp->diralloc *= 2; /* double the size each time */
+        bigger = realloc(ftp->dirs, ftp->diralloc * sizeof(ftp->dirs[0]));
+        if(!bigger) {
+          freedirs(ftp);
+          return CURLE_OUT_OF_MEMORY;
+        }
+        ftp->dirs = (char **)bigger;
       }
     }
   }
@@ -2511,10 +2524,6 @@ CURLcode Curl_ftp_disconnect(struct connectdata *conn)
       free(ftp->cache);
       ftp->cache = NULL;
     }
-    if(ftp->file) {
-      free(ftp->file);
-      ftp->file = NULL; /* zero */
-    }
     freedirs(ftp);
   }
   return CURLE_OK;
index f138fc4..1da8351 100644 (file)
    of need. */
 #define HEADERSIZE 256
 
-/* Maximum number of dirs supported by libcurl in a FTP dir hierarchy */
-#define CURL_MAX_FTP_DIRDEPTH 100
-
 /* Just a convenience macro to get the larger value out of two given.
    We prefix with CURL to prevent name collisions. */
 #define CURLMAX(x,y) ((x)>(y)?(x):(y))
@@ -244,7 +241,9 @@ struct FTP {
   char *user;    /* user name string */
   char *passwd;  /* password string */
   char *urlpath; /* the originally given path part of the URL */
-  char *dirs[CURL_MAX_FTP_DIRDEPTH]; /* path components */
+  char **dirs;   /* realloc()ed array for path components */
+  int dirdepth;  /* number of entries used in the 'dirs' array */
+  int diralloc;  /* number of entries allocated for the 'dirs' array */
   char *file;    /* decoded file */
 
   char *entrypath; /* the PWD reply when we logged on */
index b9470ab..b69550b 100644 (file)
@@ -1,6 +1,7 @@
 # Server-side
 <reply>
 <data>
+many parts there are
 </data>
 </reply>
 
 ftp
 </server>
  <name>
-FTP URL with too deep (100+) dir hierarchy
+FTP URL with 150 dir levels
  </name>
  <command>
-ftp://%HOSTIP:%FTPPORT/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/a/b
+ftp://%HOSTIP:%FTPPORT/part1/part2/part3/part4/part5/part6/part7/part8/part9/part10/part11/part12/part13/part14/part15/part16/part17/part18/part19/part20/part21/part22/part23/part24/part25/part26/part27/part28/part29/part30/part31/part32/part33/part34/part35/part36/part37/part38/part39/part40/part41/part42/part43/part44/part45/part46/part47/part48/part49/part50/part51/part52/part53/part54/part55/part56/part57/part58/part59/part60/part61/part62/part63/part64/part65/part66/part67/part68/part69/part70/part71/part72/part73/part74/part75/part76/part77/part78/part79/part80/part81/part82/part83/part84/part85/part86/part87/part88/part89/part90/part91/part92/part93/part94/part95/part96/part97/part98/part99/part100/part101/part102/part103/part104/part105/part106/part107/part108/part109/part110/part111/part112/part113/part114/part115/part116/part117/part118/part119/part120/part121/part122/part123/part124/part125/part126/part127/part128/part129/part130/part131/part132/part133/part134/part135/part136/part137/part138/part139/part140/part141/part142/part143/part144/part145/part146/part147/part148/part149/part150/142
 </command>
 </test>
 
 # Verify data after the test has been "shot"
 <verify>
-<errorcode>
-3
-</errorcode>
 <protocol>
 USER anonymous\r
 PASS curl_by_daniel@haxx.se\r
 PWD\r
+CWD part1\r
+CWD part2\r
+CWD part3\r
+CWD part4\r
+CWD part5\r
+CWD part6\r
+CWD part7\r
+CWD part8\r
+CWD part9\r
+CWD part10\r
+CWD part11\r
+CWD part12\r
+CWD part13\r
+CWD part14\r
+CWD part15\r
+CWD part16\r
+CWD part17\r
+CWD part18\r
+CWD part19\r
+CWD part20\r
+CWD part21\r
+CWD part22\r
+CWD part23\r
+CWD part24\r
+CWD part25\r
+CWD part26\r
+CWD part27\r
+CWD part28\r
+CWD part29\r
+CWD part30\r
+CWD part31\r
+CWD part32\r
+CWD part33\r
+CWD part34\r
+CWD part35\r
+CWD part36\r
+CWD part37\r
+CWD part38\r
+CWD part39\r
+CWD part40\r
+CWD part41\r
+CWD part42\r
+CWD part43\r
+CWD part44\r
+CWD part45\r
+CWD part46\r
+CWD part47\r
+CWD part48\r
+CWD part49\r
+CWD part50\r
+CWD part51\r
+CWD part52\r
+CWD part53\r
+CWD part54\r
+CWD part55\r
+CWD part56\r
+CWD part57\r
+CWD part58\r
+CWD part59\r
+CWD part60\r
+CWD part61\r
+CWD part62\r
+CWD part63\r
+CWD part64\r
+CWD part65\r
+CWD part66\r
+CWD part67\r
+CWD part68\r
+CWD part69\r
+CWD part70\r
+CWD part71\r
+CWD part72\r
+CWD part73\r
+CWD part74\r
+CWD part75\r
+CWD part76\r
+CWD part77\r
+CWD part78\r
+CWD part79\r
+CWD part80\r
+CWD part81\r
+CWD part82\r
+CWD part83\r
+CWD part84\r
+CWD part85\r
+CWD part86\r
+CWD part87\r
+CWD part88\r
+CWD part89\r
+CWD part90\r
+CWD part91\r
+CWD part92\r
+CWD part93\r
+CWD part94\r
+CWD part95\r
+CWD part96\r
+CWD part97\r
+CWD part98\r
+CWD part99\r
+CWD part100\r
+CWD part101\r
+CWD part102\r
+CWD part103\r
+CWD part104\r
+CWD part105\r
+CWD part106\r
+CWD part107\r
+CWD part108\r
+CWD part109\r
+CWD part110\r
+CWD part111\r
+CWD part112\r
+CWD part113\r
+CWD part114\r
+CWD part115\r
+CWD part116\r
+CWD part117\r
+CWD part118\r
+CWD part119\r
+CWD part120\r
+CWD part121\r
+CWD part122\r
+CWD part123\r
+CWD part124\r
+CWD part125\r
+CWD part126\r
+CWD part127\r
+CWD part128\r
+CWD part129\r
+CWD part130\r
+CWD part131\r
+CWD part132\r
+CWD part133\r
+CWD part134\r
+CWD part135\r
+CWD part136\r
+CWD part137\r
+CWD part138\r
+CWD part139\r
+CWD part140\r
+CWD part141\r
+CWD part142\r
+CWD part143\r
+CWD part144\r
+CWD part145\r
+CWD part146\r
+CWD part147\r
+CWD part148\r
+CWD part149\r
+CWD part150\r
+EPSV\r
+TYPE I\r
+SIZE 142\r
+RETR 142\r
+QUIT\r
 </protocol>
 </verify>