Browse Source

ftpfs: use new parser.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
Andrew Borodin 10 years ago
parent
commit
dc8db0089f
2 changed files with 34 additions and 29 deletions
  1. 24 29
      src/vfs/ftpfs/ftpfs.c
  2. 10 0
      src/vfs/ftpfs/ftpfs_parse_ls.c

+ 24 - 29
src/vfs/ftpfs/ftpfs.c

@@ -1725,11 +1725,16 @@ resolve_symlink (struct vfs_class *me, struct vfs_s_super *super, struct vfs_s_i
 static int
 static int
 ftpfs_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
 ftpfs_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
 {
 {
-    struct vfs_s_entry *ent;
     struct vfs_s_super *super = dir->super;
     struct vfs_s_super *super = dir->super;
     ftp_super_t *ftp_super = FTP_SUPER (super);
     ftp_super_t *ftp_super = FTP_SUPER (super);
-    int sock, num_entries = 0;
+    int sock;
+    char lc_buffer[BUF_8K];
+    int res;
     gboolean cd_first;
     gboolean cd_first;
+    GSList *dirlist = NULL;
+    GSList *entlist;
+    GSList *iter;
+    int err_count = 0;
 
 
     cd_first = ftpfs_first_cd_then_ls || (ftp_super->strict == RFC_STRICT)
     cd_first = ftpfs_first_cd_then_ls || (ftp_super->strict == RFC_STRICT)
         || (strchr (remote_path, ' ') != NULL);
         || (strchr (remote_path, ' ') != NULL);
@@ -1783,25 +1788,16 @@ ftpfs_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path
         ERRNOR (EACCES, -1);
         ERRNOR (EACCES, -1);
     }
     }
 
 
-    vfs_parse_ls_lga_init ();
-
-    while (TRUE)
+    /* read full directory list, then parse it */
+    while ((res = vfs_s_get_line_interruptible (me, lc_buffer, sizeof (lc_buffer), sock)) != 0)
     {
     {
-        int i;
-        size_t count_spaces = 0;
-        int res;
-        char lc_buffer[BUF_8K] = "\0";
-
-        res = vfs_s_get_line_interruptible (me, lc_buffer, sizeof (lc_buffer), sock);
-        if (res == 0)
-            break;
-
         if (res == EINTR)
         if (res == EINTR)
         {
         {
             me->verrno = ECONNRESET;
             me->verrno = ECONNRESET;
             close (sock);
             close (sock);
             ftp_super->ctl_connection_busy = FALSE;
             ftp_super->ctl_connection_busy = FALSE;
             ftpfs_get_reply (me, ftp_super->sock, NULL, 0);
             ftpfs_get_reply (me, ftp_super->sock, NULL, 0);
+            g_slist_free_full (dirlist, g_free);
             vfs_print_message (_("%s: failure"), me->name);
             vfs_print_message (_("%s: failure"), me->name);
             return (-1);
             return (-1);
         }
         }
@@ -1813,28 +1809,19 @@ ftpfs_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path
             fflush (me->logfile);
             fflush (me->logfile);
         }
         }
 
 
-        ent = vfs_s_generate_entry (me, NULL, dir, 0);
-        i = ent->ino->st.st_nlink;
-
-        if (!vfs_parse_ls_lga
-            (lc_buffer, &ent->ino->st, &ent->name, &ent->ino->linkname, &count_spaces))
-            vfs_s_free_entry (me, ent);
-        else
-        {
-            ent->ino->st.st_nlink = i;  /* Ouch, we need to preserve our counts :-( */
-            num_entries++;
-            vfs_s_store_filename_leading_spaces (ent, count_spaces);
-            vfs_s_insert_entry (me, dir, ent);
-        }
+        dirlist = g_slist_prepend (dirlist, g_strdup (lc_buffer));
     }
     }
 
 
     close (sock);
     close (sock);
     ftp_super->ctl_connection_busy = FALSE;
     ftp_super->ctl_connection_busy = FALSE;
     me->verrno = E_REMOTE;
     me->verrno = E_REMOTE;
     if ((ftpfs_get_reply (me, ftp_super->sock, NULL, 0) != COMPLETE))
     if ((ftpfs_get_reply (me, ftp_super->sock, NULL, 0) != COMPLETE))
+    {
+        g_slist_free_full (dirlist, g_free);
         goto fallback;
         goto fallback;
+    }
 
 
-    if (num_entries == 0 && !cd_first)
+    if (dirlist == NULL && !cd_first)
     {
     {
         /* The LIST command may produce an empty output. In such scenario
         /* The LIST command may produce an empty output. In such scenario
            it is not clear whether this is caused by  'remote_path' being
            it is not clear whether this is caused by  'remote_path' being
@@ -1850,7 +1837,15 @@ ftpfs_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path
         goto again;
         goto again;
     }
     }
 
 
-    vfs_s_normalize_filename_leading_spaces (dir, vfs_parse_ls_lga_get_final_spaces ());
+    /* parse server's reply */
+    dirlist = g_slist_reverse (dirlist);        /* restore order */
+    entlist = ftpfs_parse_long_list (me, dir, dirlist, &err_count);
+    g_slist_free_full (dirlist, g_free);
+
+    for (iter = entlist; iter != NULL; iter = g_slist_next (iter))
+        vfs_s_insert_entry (me, dir, VFS_ENTRY (iter->data));
+
+    g_slist_free (entlist);
 
 
     if (ftp_super->strict == RFC_AUTODETECT)
     if (ftp_super->strict == RFC_AUTODETECT)
         ftp_super->strict = RFC_DARING;
         ftp_super->strict = RFC_DARING;

+ 10 - 0
src/vfs/ftpfs/ftpfs_parse_ls.c

@@ -1155,15 +1155,20 @@ ftpfs_parse_long_list (struct vfs_class * me, struct vfs_s_inode * dir, GSList *
                 struct vfs_s_entry *info;
                 struct vfs_s_entry *info;
                 gboolean ok;
                 gboolean ok;
                 char *tmp_line;
                 char *tmp_line;
+                int nlink;
 
 
                 /* parser can clobber the line - work on a copy */
                 /* parser can clobber the line - work on a copy */
                 tmp_line = g_strndup (b, blen);
                 tmp_line = g_strndup (b, blen);
 
 
                 info = vfs_s_generate_entry (me, NULL, dir, 0);
                 info = vfs_s_generate_entry (me, NULL, dir, 0);
+                nlink = info->ino->st.st_nlink;
                 ok = (*line_parsers[i]) (tmp_line, &info->ino->st, &info->name,
                 ok = (*line_parsers[i]) (tmp_line, &info->ino->st, &info->name,
                                          &info->ino->linkname, &err[i]);
                                          &info->ino->linkname, &err[i]);
                 if (ok && strchr (info->name, '/') == NULL)
                 if (ok && strchr (info->name, '/') == NULL)
+                {
+                    info->ino->st.st_nlink = nlink;     /* Ouch, we need to preserve our counts :-( */
                     set[i] = g_slist_prepend (set[i], info);
                     set[i] = g_slist_prepend (set[i], info);
+                }
                 else
                 else
                     vfs_s_free_entry (me, info);
                     vfs_s_free_entry (me, info);
 
 
@@ -1191,15 +1196,20 @@ ftpfs_parse_long_list (struct vfs_class * me, struct vfs_s_inode * dir, GSList *
             struct vfs_s_entry *info;
             struct vfs_s_entry *info;
             gboolean ok;
             gboolean ok;
             char *tmp_line;
             char *tmp_line;
+            int nlink;
 
 
             /* parser can clobber the line - work on a copy */
             /* parser can clobber the line - work on a copy */
             tmp_line = g_strndup (b, blen);
             tmp_line = g_strndup (b, blen);
 
 
             info = vfs_s_generate_entry (me, NULL, dir, 0);
             info = vfs_s_generate_entry (me, NULL, dir, 0);
+            nlink = info->ino->st.st_nlink;
             ok = guessed_parser (tmp_line, &info->ino->st, &info->name, &info->ino->linkname,
             ok = guessed_parser (tmp_line, &info->ino->st, &info->name, &info->ino->linkname,
                                  the_err);
                                  the_err);
             if (ok && strchr (info->name, '/') == NULL)
             if (ok && strchr (info->name, '/') == NULL)
+            {
+                info->ino->st.st_nlink = nlink; /* Ouch, we need to preserve our counts :-( */
                 *the_set = g_slist_prepend (*the_set, info);
                 *the_set = g_slist_prepend (*the_set, info);
+            }
             else
             else
                 vfs_s_free_entry (me, info);
                 vfs_s_free_entry (me, info);