+ if (!lastpath_struct)
+ goto done; /* dir must have vanished */
+
+ len = strlen(limit+1);
+ memcpy(&relname_list, F_DIR_RELNAMES_P(lastpath_struct), sizeof relname_list);
+ if (!relname_list) {
+ if (!(relname_list = new0(item_list)))
+ out_of_memory("send_implied_dirs");
+ memcpy(F_DIR_RELNAMES_P(lastpath_struct), &relname_list, sizeof relname_list);
+ }
+ rnpp = EXPAND_ITEM_LIST(relname_list, relnamecache *, 32);
+ if (!(*rnpp = (relnamecache*)new_array(char, sizeof (relnamecache) + len)))
+ out_of_memory("send_implied_dirs");
+ (*rnpp)->name_type = name_type;
+ strlcpy((*rnpp)->fname, limit+1, len + 1);
+
+done:
+ filter_list = save_filter_list;
+}
+
+static void send1extra(int f, struct file_struct *file, struct file_list *flist)
+{
+ char fbuf[MAXPATHLEN];
+ item_list *relname_list;
+ int len, dlen, flags = FLAG_DIVERT_DIRS | FLAG_CONTENT_DIR;
+ size_t j;
+
+ f_name(file, fbuf);
+ dlen = strlen(fbuf);
+
+ if (!change_pathname(file, NULL, 0))
+ exit_cleanup(RERR_FILESELECT);
+
+ change_local_filter_dir(fbuf, dlen, send_dir_depth);
+
+ if (file->flags & FLAG_CONTENT_DIR) {
+ if (one_file_system) {
+ STRUCT_STAT st;
+ if (link_stat(fbuf, &st, copy_dirlinks) != 0) {
+ interpret_stat_error(fbuf, True);
+ return;
+ }
+ filesystem_dev = st.st_dev;
+ }
+ send_directory(f, flist, fbuf, dlen, flags);
+ }
+
+ if (!relative_paths)
+ return;
+
+ memcpy(&relname_list, F_DIR_RELNAMES_P(file), sizeof relname_list);
+ if (!relname_list)
+ return;
+
+ for (j = 0; j < relname_list->count; j++) {
+ char *slash;
+ relnamecache *rnp = ((relnamecache**)relname_list->items)[j];
+ char name_type = rnp->name_type;
+
+ fbuf[dlen] = '/';
+ len = strlcpy(fbuf + dlen + 1, rnp->fname, sizeof fbuf - dlen - 1);
+ free(rnp);
+ if (len >= (int)sizeof fbuf)
+ continue; /* Impossible... */
+
+ slash = strchr(fbuf+dlen+1, '/');
+ if (slash) {
+ send_implied_dirs(f, flist, fbuf, fbuf+dlen+1, slash, flags, name_type);
+ continue;
+ }
+
+ if (name_type != NORMAL_NAME) {
+ STRUCT_STAT st;
+ if (link_stat(fbuf, &st, 1) != 0) {
+ interpret_stat_error(fbuf, True);
+ continue;
+ }
+ send_file_name(f, flist, fbuf, &st, FLAG_TOP_DIR | flags, ALL_FILTERS);
+ } else
+ send_file_name(f, flist, fbuf, NULL, FLAG_TOP_DIR | flags, ALL_FILTERS);
+ }
+
+ free(relname_list);
+}
+
+void send_extra_file_list(int f, int at_least)
+{
+ struct file_list *flist;
+ int64 start_write;
+ uint16 prev_flags;
+ int save_io_error = io_error;
+
+ if (flist_eof)
+ return;
+
+ if (at_least < 0)
+ at_least = file_total - file_old_total + 1;
+
+ /* Keep sending data until we have the requested number of
+ * files in the upcoming file-lists. */
+ while (file_total - file_old_total < at_least) {
+ struct file_struct *file = dir_flist->sorted[send_dir_ndx];
+ int dir_ndx, dstart = stats.num_dirs;
+ const char *pathname = F_PATHNAME(file);
+ int32 *dp;
+
+ flist = flist_new(0, "send_extra_file_list");
+ start_write = stats.total_written;