+static char lastpath[MAXPATHLEN] = "";
+static int lastpath_len = 0;
+static struct file_struct *lastpath_struct;
+
+static void send_implied_dirs(int f, struct file_list *flist, char *fname,
+ char *start, char *limit, int flags, int is_dot_dir)
+{
+ struct file_struct *file;
+ item_list *rel_list;
+ char **ep, *slash;
+ int len, need_new_dir;
+
+ flags &= ~FLAG_XFER_DIR;
+
+ if (inc_recurse) {
+ if (lastpath_struct && F_PATHNAME(lastpath_struct) == pathname
+ && lastpath_len == limit - fname
+ && strncmp(lastpath, fname, lastpath_len) == 0)
+ need_new_dir = 0;
+ else
+ need_new_dir = 1;
+ } else
+ need_new_dir = 1;
+
+ if (need_new_dir) {
+ int save_copy_links = copy_links;
+ int save_xfer_dirs = xfer_dirs;
+
+ copy_links |= copy_unsafe_links;
+ xfer_dirs = 1;
+
+ *limit = '\0';
+
+ for (slash = start; (slash = strchr(slash+1, '/')) != NULL; ) {
+ *slash = '\0';
+ send_file_name(f, flist, fname, NULL, flags, ALL_FILTERS);
+ *slash = '/';
+ }
+
+ file = send_file_name(f, flist, fname, NULL, flags, ALL_FILTERS);
+ if (inc_recurse) {
+ if (file && !S_ISDIR(file->mode))
+ file = NULL;
+ else if (file)
+ memset(F_DIR_RELS_P(file), 0, sizeof (item_list*));
+ lastpath_struct = file;
+ }
+
+ strlcpy(lastpath, fname, sizeof lastpath);
+ lastpath_len = limit - fname;
+
+ *limit = '/';
+
+ copy_links = save_copy_links;
+ xfer_dirs = save_xfer_dirs;
+
+ if (!inc_recurse)
+ return;
+ }
+
+ if (!lastpath_struct)
+ return; /* dir must have vanished */
+
+ len = strlen(limit+1);
+ memcpy(&rel_list, F_DIR_RELS_P(lastpath_struct), sizeof rel_list);
+ if (!rel_list) {
+ if (!(rel_list = new0(item_list)))
+ out_of_memory("send_implied_dirs");
+ memcpy(F_DIR_RELS_P(lastpath_struct), &rel_list, sizeof rel_list);
+ }
+ ep = EXPAND_ITEM_LIST(rel_list, char *, 32);
+ if (!(*ep = new_array(char, 1 + len + 1)))
+ out_of_memory("send_implied_dirs");
+ **ep = is_dot_dir;
+ strlcpy(*ep + 1, limit+1, len + 1);
+}
+
+static void send1extra(int f, struct file_struct *file, struct file_list *flist)