changeset 787:3751478bb260

2006-7-27 Brian Masney <masneyb@gftp.org> * lib/protocols.c (gftp_get_all_subdirs) - split this function into several smaller functions. Added support for getting the true file size if it is a symlink. Added more error handling. Fixed a segfault that may occur when transferring deeply nested directories * lib/fsp.c lib/gftp.h lib/local.c lib/protocols.c lib/rfc2068.c lib/rfc959.c lib/sshv2.c (*_chdir) - removed support for passing the request->directory into this function. There is no longer a need for this. (*_stat_filename) - added support for getting the file size
author masneyb
date Fri, 28 Jul 2006 01:44:54 +0000
parents 78bad9db6cb0
children 0e7ab0a51ddd
files ChangeLog lib/fsp.c lib/gftp.h lib/local.c lib/protocols.c lib/rfc2068.c lib/rfc959.c lib/sshv2.c
diffstat 8 files changed, 259 insertions(+), 177 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Jul 27 18:25:38 2006 +0000
+++ b/ChangeLog	Fri Jul 28 01:44:54 2006 +0000
@@ -1,3 +1,15 @@
+2006-7-27 Brian Masney <masneyb@gftp.org>
+	* lib/protocols.c (gftp_get_all_subdirs) - split this function into
+	several smaller functions. Added support for getting the true file
+	size if it is a symlink. Added more error handling. Fixed a segfault
+	that may occur when transferring deeply nested directories
+
+	* lib/fsp.c lib/gftp.h lib/local.c lib/protocols.c lib/rfc2068.c
+	lib/rfc959.c lib/sshv2.c (*_chdir) - removed support for passing
+	the request->directory into this function. There is no longer a
+	need for this. (*_stat_filename) - added support for getting the
+	file size
+ 
 2006-7-21 Brian Masney <masneyb@gftp.org>
 	* src/gtk/transfer.c (transfer_done) - fixed race condition that
 	would occur when selecting Stop Transfer and then Start Transfer
@@ -3484,7 +3496,7 @@
 
 	* cvsclean - added this script
 
-	* *.[ch] - added $Id: ChangeLog,v 1.456 2006/07/21 13:30:11 masneyb Exp $ tags
+	* *.[ch] - added $Id: ChangeLog,v 1.457 2006/07/28 01:44:52 masneyb Exp $ tags
 
 	* debian/* - updated files from Debian maintainer
 
--- a/lib/fsp.c	Thu Jul 27 18:25:38 2006 +0000
+++ b/lib/fsp.c	Fri Jul 28 01:44:54 2006 +0000
@@ -278,10 +278,10 @@
 
 static int
 fsp_stat_filename (gftp_request * request, const char *filename,
-                     mode_t * mode)
+                   mode_t * mode, off_t * filesize)
 {
+  fsp_protocol_data * lpd;
   struct stat st;
-  fsp_protocol_data * lpd;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
   g_return_val_if_fail (request->protonum == GFTP_FSP_NUM, GFTP_EFATAL);
@@ -294,6 +294,8 @@
     return (GFTP_ERETRYABLE);
 
   *mode = st.st_mode;
+  *filesize = st.st_size;
+
   return (0);
 }
 
@@ -417,19 +419,16 @@
   
   olddir=NULL;
   /* build new directory string */
-  if (request->directory != directory)
-    {
-      olddir = request->directory;
+  olddir = request->directory;
 
-      if (*directory != '/' && request->directory != NULL)
-        {
-          tempstr = g_strconcat (request->directory, "/", directory, NULL);
-          request->directory = gftp_expand_path (request, tempstr);
-          g_free (tempstr);
-        }
-      else
-        request->directory = gftp_expand_path (request, directory);
+  if (*directory != '/' && request->directory != NULL)
+    {
+      tempstr = g_strconcat (request->directory, "/", directory, NULL);
+      request->directory = gftp_expand_path (request, tempstr);
+      g_free (tempstr);
     }
+  else
+    request->directory = gftp_expand_path (request, directory);
 
   if (fsp_getpro (lpd->fsp,request->directory,NULL) == 0)
     {
--- a/lib/gftp.h	Thu Jul 27 18:25:38 2006 +0000
+++ b/lib/gftp.h	Fri Jul 28 01:44:54 2006 +0000
@@ -254,7 +254,9 @@
                done_edit : 1,	/* Edit the file when done transfering? */
                done_rm : 1,	/* Remove the file when done */
                transfer_done : 1, /* Is current file transfer done? */
-               is_fd : 1;	/* Is this a file descriptor? */
+               is_fd : 1,	/* Is this a file descriptor? */
+               exists_other_side; /* The file exists on the other side during
+                                     the file transfer */
   char transfer_action;		/* See the GFTP_TRANS_ACTION_* vars above */
   /*@null@*/ void *user_data;
 };
@@ -452,7 +454,8 @@
   int (*abort_transfer) 		( gftp_request * request );
   int (*stat_filename) 			( gftp_request * request,
 					  const char *filename,
-					  mode_t * mode );
+					  mode_t * mode,
+					  off_t * filesize );
   int (*list_files) 			( gftp_request * request );
   int (*get_next_file)			( gftp_request * request, 
 					  gftp_file *fle, 
@@ -927,7 +930,8 @@
 
 int gftp_stat_filename			( gftp_request * request,
 					  const char *filename,
-					  mode_t * mode );
+					  mode_t * mode,
+					  off_t * filesize );
 
 void gftp_set_hostname 			( gftp_request * request, 
 					  const char *hostname );
--- a/lib/local.c	Thu Jul 27 18:25:38 2006 +0000
+++ b/lib/local.c	Fri Jul 28 01:44:54 2006 +0000
@@ -28,8 +28,7 @@
 
 
 static void
-local_remove_key (/*@unused@*/ gpointer key, gpointer value,
-                  /*@unused@*/ gpointer user_data)
+local_remove_key (gpointer key, gpointer value, gpointer user_data)
 {
   g_free (value);
 }
@@ -155,7 +154,7 @@
 
 static int
 local_put_file (gftp_request * request, const char *filename, int fd,
-                off_t startsize, /*@unused@*/ off_t totalsize)
+                off_t startsize, off_t totalsize)
 {
   int flags;
 
@@ -226,8 +225,8 @@
 
 
 static int
-local_stat_filename (/*@unused@*/ gftp_request * request, const char *filename,
-                     mode_t * mode)
+local_stat_filename (gftp_request * request, const char *filename,
+                     mode_t * mode, off_t * filesize)
 {
   struct stat st;
 
@@ -235,6 +234,8 @@
     return (GFTP_ERETRYABLE);
 
   *mode = st.st_mode;
+  *filesize = st.st_size;
+
   return (0);
 }
 
@@ -360,7 +361,7 @@
 
 
 static off_t 
-local_get_file_size (/*@unused@*/ gftp_request * request, const char *filename)
+local_get_file_size (gftp_request * request, const char *filename)
 {
   struct stat st;
 
@@ -373,7 +374,7 @@
 static int
 local_chdir (gftp_request * request, const char *directory)
 {
-  char tempstr[255];
+  char tempstr[MAXNAMLEN];
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
   g_return_val_if_fail (request->protonum == GFTP_LOCAL_NUM, GFTP_EFATAL);
@@ -385,28 +386,25 @@
                           _("Successfully changed local directory to %s\n"),
                           directory);
 
-      if (request->directory != directory)
+      if (getcwd (tempstr, sizeof (tempstr)) == NULL)
         {
-          if (getcwd (tempstr, sizeof (tempstr)) == NULL)
-            {
-              request->logging_function (gftp_logging_error, request,
-                             _("Could not get current working directory: %s\n"),
-                             g_strerror (errno));
-	      return (GFTP_ERETRYABLE);
-            }
-
-          if (request->directory)
-            g_free (request->directory);
-          request->directory = g_strdup (tempstr);
+          request->logging_function (gftp_logging_error, request,
+                                     _("Could not get current working directory: %s\n"),
+                                     g_strerror (errno));
+          return (GFTP_ERETRYABLE);
         }
 
+      if (request->directory)
+        g_free (request->directory);
+
+      request->directory = g_strdup (tempstr);
       return (0);
     }
   else
     {
       request->logging_function (gftp_logging_error, request,
-                              _("Could not change local directory to %s: %s\n"),
-                              directory, g_strerror (errno));
+                                 _("Could not change local directory to %s: %s\n"),
+                                 directory, g_strerror (errno));
       return (GFTP_ERETRYABLE);
     }
 }
--- a/lib/protocols.c	Thu Jul 27 18:25:38 2006 +0000
+++ b/lib/protocols.c	Fri Jul 28 01:44:54 2006 +0000
@@ -345,13 +345,14 @@
 
 
 int
-gftp_stat_filename (gftp_request * request, const char *filename, mode_t * mode)
+gftp_stat_filename (gftp_request * request, const char *filename, mode_t * mode,
+                    off_t * filesize)
 {
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
   g_return_val_if_fail (filename != NULL, GFTP_EFATAL);
 
   if (request->stat_filename != NULL)
-    return (request->stat_filename (request, filename, mode));
+    return (request->stat_filename (request, filename, mode, filesize));
   else
     return (0);
 }
@@ -1864,7 +1865,6 @@
   GHashTable * dirhash;
   gftp_file * fle;
   off_t *newsize;
-  char * newname;
 
   dirhash = g_hash_table_new (string_hash_function, string_hash_compare);
   *ret = gftp_list_files (request);
@@ -1873,10 +1873,9 @@
       fle = g_malloc0 (sizeof (*fle));
       while (gftp_get_next_file (request, NULL, fle) > 0)
         {
-          newname = fle->file;
           newsize = g_malloc (sizeof (*newsize));
           *newsize = fle->size;
-          g_hash_table_insert (dirhash, newname, newsize);
+          g_hash_table_insert (dirhash, fle->file, newsize);
           fle->file = NULL;
           gftp_file_destroy (fle, 0);
         }
@@ -1905,6 +1904,9 @@
 static void
 gftp_destroy_dir_hash (GHashTable * dirhash)
 {
+  if (dirhash == NULL)
+    return;
+
   g_hash_table_foreach (dirhash, destroy_hash_ent, NULL);
   g_hash_table_destroy (dirhash);
 }
@@ -1919,10 +1921,10 @@
   off_t *newsize;
   char *newname;
 
-  if (getothdir && transfer->toreq)
+  if (getothdir && transfer->toreq != NULL)
     {
       dirhash = gftp_gen_dir_hash (transfer->toreq, ret);
-      if (*ret < 0)
+      if (*ret == GFTP_EFATAL)
         return (NULL);
     }
   else 
@@ -1930,7 +1932,10 @@
 
   *ret = gftp_list_files (transfer->fromreq);
   if (*ret < 0)
-    return (NULL);
+    {
+      gftp_destroy_dir_hash (dirhash);
+      return (NULL);
+    }
 
   fle = g_malloc (sizeof (*fle));
   templist = NULL;
@@ -1944,7 +1949,12 @@
 
       if (dirhash && 
           (newsize = g_hash_table_lookup (dirhash, fle->file)) != NULL)
-        fle->startsize = *newsize;
+        {
+          fle->exists_other_side = 1;
+          fle->startsize = *newsize;
+        }
+      else
+        fle->exists_other_side = 0;
 
       if (transfer->toreq && fle->destfile == NULL)
         fle->destfile = gftp_build_path (transfer->toreq,
@@ -1965,41 +1975,51 @@
 
       templist = g_list_append (templist, fle);
 
-      fle = g_malloc (sizeof (*fle));
+      fle = g_malloc0 (sizeof (*fle));
     }
   gftp_end_transfer (transfer->fromreq);
 
   gftp_file_destroy (fle, 1);
-
-  if (dirhash != NULL)
-    gftp_destroy_dir_hash (dirhash);
+  gftp_destroy_dir_hash (dirhash);
 
   return (templist);
 }
 
 
-int
-gftp_get_all_subdirs (gftp_transfer * transfer,
-                      void (*update_func) (gftp_transfer * transfer))
+static void
+_cleanup_get_all_subdirs (gftp_transfer * transfer, char *oldfromdir,
+                          char *oldtodir,
+                          void (*update_func) (gftp_transfer * transfer))
 {
-  char *oldfromdir, *oldtodir, *newname, *pos;
-  int forcecd, remotechanged, ret;
-  GList * templist, * lastlist;
+  if (update_func != NULL)
+    {
+      transfer->numfiles = transfer->numdirs = -1;
+      update_func (transfer);
+    }
+
+  if (oldfromdir != NULL)
+    g_free (oldfromdir);
+
+  if (oldtodir != NULL)
+    g_free (oldtodir);
+}
+
+
+static GList *
+_setup_current_directory_transfer (gftp_transfer * transfer, int *ret)
+{
   GHashTable * dirhash;
+  char *pos, *newname;
   gftp_file * curfle;
+  GList * lastlist;
   off_t *newsize;
-  mode_t st_mode;
-
-  g_return_val_if_fail (transfer != NULL, GFTP_EFATAL);
-  g_return_val_if_fail (transfer->fromreq != NULL, GFTP_EFATAL);
-  g_return_val_if_fail (transfer->files != NULL, GFTP_EFATAL);
-
+
+  *ret = 0;
   if (transfer->toreq != NULL)
     {
-      ret = 0;
-      dirhash = gftp_gen_dir_hash (transfer->toreq, &ret);
-      if (ret < 0)
-        return (ret);
+      dirhash = gftp_gen_dir_hash (transfer->toreq, ret);
+      if (*ret == GFTP_EFATAL)
+        return (NULL);
     }
   else
     dirhash = NULL;
@@ -2015,13 +2035,22 @@
 
       if (dirhash != NULL && 
           (newsize = g_hash_table_lookup (dirhash, pos)) != NULL)
-        curfle->startsize = *newsize;
+        {
+          curfle->exists_other_side = 1;
+          curfle->startsize = *newsize;
+        }
+      else
+        curfle->exists_other_side = 0;
 
       if (curfle->size < 0 && GFTP_IS_CONNECTED (transfer->fromreq))
         {
           curfle->size = gftp_get_file_size (transfer->fromreq, curfle->file);
-          if (curfle->size < 0)
-            return (curfle->size);
+          if (curfle->size == GFTP_EFATAL)
+            {
+              gftp_destroy_dir_hash (dirhash);
+              *ret = curfle->size;
+              return (NULL);
+            }
         }
 
       if (transfer->toreq && curfle->destfile == NULL)
@@ -2043,12 +2072,37 @@
         break;
     }
 
-  if (dirhash != NULL)
-    gftp_destroy_dir_hash (dirhash);
+  gftp_destroy_dir_hash (dirhash);
+
+  return (lastlist);
+}
+
+
+int
+gftp_get_all_subdirs (gftp_transfer * transfer,
+                      void (*update_func) (gftp_transfer * transfer))
+{
+  GList * templist, * lastlist;
+  char *oldfromdir, *oldtodir;
+  gftp_file * curfle;
+  off_t linksize;
+  mode_t st_mode;
+  int ret;
+
+  g_return_val_if_fail (transfer != NULL, GFTP_EFATAL);
+  g_return_val_if_fail (transfer->fromreq != NULL, GFTP_EFATAL);
+  g_return_val_if_fail (transfer->files != NULL, GFTP_EFATAL);
+
+  if (transfer->files == NULL)
+    return (0);
+
+  ret = 0;
+  lastlist = _setup_current_directory_transfer (transfer, &ret);
+  if (lastlist == NULL)
+    return (ret);
 
   oldfromdir = oldtodir = NULL;
-  remotechanged = 0;
-  forcecd = 0;
+
   for (templist = transfer->files; templist != NULL; templist = templist->next)
     {
       curfle = templist->data;
@@ -2056,84 +2110,107 @@
       if (S_ISLNK (curfle->st_mode) && !S_ISDIR (curfle->st_mode))
         {
           st_mode = 0;
-          ret = gftp_stat_filename (transfer->fromreq, curfle->file, &st_mode);
+          linksize = 0;
+          ret = gftp_stat_filename (transfer->fromreq, curfle->file, &st_mode,
+                                    &linksize);
           if (ret < 0)
-            return (ret);
+            {
+              _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
+                                        update_func);
+              return (ret);
+            }
           else if (S_ISDIR (st_mode))
             curfle->st_mode = st_mode;
+          else
+            curfle->size = linksize;
         }
 
-      if (curfle->st_mode & S_IFDIR)
+      if (!(curfle->st_mode & S_IFDIR))
         {
-          oldfromdir = transfer->fromreq->directory;
-          transfer->fromreq->directory = g_strdup (curfle->file);
-
-          if (transfer->toreq != NULL)
+          transfer->numfiles++;
+          continue;
+        }
+
+      /* Got a directory... */
+      if (oldfromdir == NULL)
+        oldfromdir = g_strdup (transfer->fromreq->directory);
+
+      ret = gftp_set_directory (transfer->fromreq, curfle->file);
+      if (ret < 0)
+        {
+          _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
+                                    update_func);
+          return (ret);
+        }
+
+      if (transfer->toreq != NULL)
+        {
+          if (oldtodir == NULL)
+            oldtodir = g_strdup (transfer->toreq->directory);
+
+          if (curfle->exists_other_side)
             {
-              oldtodir = transfer->toreq->directory;
-              transfer->toreq->directory = g_strdup (curfle->destfile);
-            } 
-
-          forcecd = 1;
-          ret = gftp_set_directory (transfer->fromreq,
-                                    transfer->fromreq->directory);
-          if (ret < 0)
-            return (ret);
-
-          if (curfle->startsize > 0 && transfer->toreq != NULL)
-            {
-              remotechanged = 1;
-              ret = gftp_set_directory (transfer->toreq, 
-                                        transfer->toreq->directory);
-              if (ret < 0)
-                return (ret);
-            } 
-
-          ret = 0;
-          lastlist->next = gftp_get_dir_listing (transfer, 
-                                                 curfle->startsize > 0,
-                                                 &ret);
-          if (ret < 0)
-            return (ret);
-
-          if (lastlist->next != NULL)
+              ret = gftp_set_directory (transfer->toreq, curfle->destfile);
+              if (ret == GFTP_EFATAL)
+                {
+                  _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
+                                            update_func);
+                  return (ret);
+                }
+            }
+          else
             {
-              lastlist->next->prev = lastlist;
-              for (; lastlist->next != NULL; lastlist = lastlist->next);
+              if (transfer->toreq->directory != NULL)
+                g_free (transfer->toreq->directory);
+
+              transfer->toreq->directory = g_strdup (curfle->destfile);
             }
-
-          transfer->numdirs++;
-          if (update_func != NULL)
-            update_func (transfer);
-
-          transfer->fromreq->directory = oldfromdir;
-          if (transfer->toreq != NULL)
-            transfer->toreq->directory = oldtodir;
+        } 
+
+      ret = 0;
+      lastlist->next = gftp_get_dir_listing (transfer,
+                                             curfle->exists_other_side, &ret);
+      if (ret < 0)
+        {
+          _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
+                                    update_func);
+          return (ret);
         }
-      else
-        transfer->numfiles++;
+
+      if (lastlist->next != NULL)
+        {
+          lastlist->next->prev = lastlist;
+          for (; lastlist->next != NULL; lastlist = lastlist->next);
+        }
+
+      transfer->numdirs++;
+      if (update_func != NULL)
+        update_func (transfer);
     }
 
-  if (forcecd)
+  if (oldfromdir != NULL)
     {
-      ret = gftp_set_directory (transfer->fromreq,
-                                transfer->fromreq->directory);
+      ret = gftp_set_directory (transfer->fromreq, oldfromdir);
       if (ret < 0)
-        return (ret);
+        {
+          _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
+                                    update_func);
+          return (ret);
+        }
     }
 
-  if (remotechanged && transfer->toreq != NULL)
+  if (oldtodir != NULL)
     {
-      ret = gftp_set_directory (transfer->toreq, transfer->toreq->directory);
+      ret = gftp_set_directory (transfer->toreq, oldtodir);
       if (ret < 0)
-        return (ret);
+        {
+          _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir,
+                                    update_func);
+          return (ret);
+        }
     }
 
-  if (update_func != NULL)
-    {
-      transfer->numfiles = transfer->numdirs = -1;
-      update_func (transfer);
-    }
+  _cleanup_get_all_subdirs (transfer, oldfromdir, oldtodir, update_func);
 
   return (0);
 }
--- a/lib/rfc2068.c	Thu Jul 27 18:25:38 2006 +0000
+++ b/lib/rfc2068.c	Fri Jul 28 01:44:54 2006 +0000
@@ -640,27 +640,26 @@
 static int
 rfc2068_chdir (gftp_request * request, const char *directory)
 {
-  char *tempstr, *olddir;
+  char *tempstr;
 
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
   g_return_val_if_fail (directory != NULL, GFTP_EFATAL);
 
-  if (request->directory != directory)
+  if (*directory != '/' && request->directory != NULL)
     {
-      olddir = request->directory;
+      tempstr = g_strconcat (request->directory, "/", directory, NULL);
+      g_free (request->directory);
+      request->directory = gftp_expand_path (request, tempstr);
+      g_free (tempstr);
+    }
+  else
+    {
+      if (request->directory != NULL)
+        g_free (request->directory);
 
-      if (*directory != '/' && request->directory != NULL)
-        {
-          tempstr = g_strconcat (request->directory, "/", directory, NULL);
-          request->directory = gftp_expand_path (request, tempstr);
-          g_free (tempstr);
-        }
-      else
-        request->directory = gftp_expand_path (request, directory);
+      request->directory = gftp_expand_path (request, directory);
+    }
 
-      if (olddir != NULL)
-        g_free (olddir);
-    }
   return (0);
 }
 
--- a/lib/rfc959.c	Thu Jul 27 18:25:38 2006 +0000
+++ b/lib/rfc959.c	Fri Jul 28 01:44:54 2006 +0000
@@ -378,11 +378,8 @@
   else if (ret != '2')
     return (GFTP_ERETRYABLE);
 
-  if (directory != request->directory)
-    {
-      if ((ret = rfc959_getcwd (request)) < 0)
-        return (ret);
-    }
+  if ((ret = rfc959_getcwd (request)) < 0)
+    return (ret);
 
   return (0);
 }
--- a/lib/sshv2.c	Thu Jul 27 18:25:38 2006 +0000
+++ b/lib/sshv2.c	Fri Jul 28 01:44:54 2006 +0000
@@ -1416,38 +1416,32 @@
   g_return_val_if_fail (request != NULL, GFTP_EFATAL);
   g_return_val_if_fail (request->protonum == GFTP_SSHV2_NUM, GFTP_EFATAL);
 
-  if (request->directory != directory)
-    {
-      len = 0;
-      tempstr = sshv2_initialize_string_with_path (request, directory,
-                                                   &len, NULL);
+  len = 0;
+  tempstr = sshv2_initialize_string_with_path (request, directory, &len, NULL);
 
-      ret = sshv2_send_command (request, SSH_FXP_REALPATH, tempstr, len);
+  ret = sshv2_send_command (request, SSH_FXP_REALPATH, tempstr, len);
 
-      g_free (tempstr);
-      if (ret < 0)
-        return (ret);
+  g_free (tempstr);
+  if (ret < 0)
+    return (ret);
 
-      ret = sshv2_read_status_response (request, &message, -1, SSH_FXP_STATUS,
-                                        SSH_FXP_NAME);
-      if (ret < 0)
-        return (ret);
+  ret = sshv2_read_status_response (request, &message, -1, SSH_FXP_STATUS,
+                                    SSH_FXP_NAME);
+  if (ret < 0)
+    return (ret);
 
-      message.pos += 4;
-      if ((ret = sshv2_buffer_get_int32 (request, &message, 1, 1, NULL)) < 0)
-        return (ret);
+  message.pos += 4;
+  if ((ret = sshv2_buffer_get_int32 (request, &message, 1, 1, NULL)) < 0)
+    return (ret);
 
-      if ((dir = sshv2_buffer_get_string (request, &message, 1)) == NULL)
-        return (GFTP_EFATAL);
-
-      if (request->directory)
-        g_free (request->directory);
+  if ((dir = sshv2_buffer_get_string (request, &message, 1)) == NULL)
+    return (GFTP_EFATAL);
 
-      request->directory = dir;
-      sshv2_message_free (&message);
-      return (0);
-    }
+  if (request->directory)
+    g_free (request->directory);
 
+  request->directory = dir;
+  sshv2_message_free (&message);
   return (0);
 }
 
@@ -1744,7 +1738,7 @@
 
 static int
 sshv2_stat_filename (gftp_request * request, const char *filename,
-                     mode_t * mode)
+                     mode_t * mode, off_t * filesize)
 {
   gftp_file fle;
   int ret;
@@ -1755,6 +1749,8 @@
     return (ret);
 
   *mode = fle.st_mode;
+  *filesize = fle.size;
+
   gftp_file_destroy (&fle, 0);
 
   return (0);