+ dlen = strlcpy(fbuf, fname, MAXPATHLEN);
+ if (need_first_push) {
+ if (dlen != 1 || fbuf[0] != '.') {
+ char *s = strrchr(fbuf, '/');
+ int first_dlen;
+ if (s)
+ first_dlen = s - fbuf;
+ else
+ first_dlen = 0;
+ if (!s || s[1] != '.' || s[2] != '\0') {
+ filt_array[fa_lvl++] = push_local_filters(fbuf,
+ first_dlen);
+ }
+ }
+ need_first_push = False;
+ }
+
+ if (dlen >= MAXPATHLEN - 1)
+ return;
+ if (fa_lvl >= MAXPATHLEN/2)
+ return; /* impossible... */
+
+ if (link_stat(fname, &st, keep_dirlinks) < 0)
+ return;
+
+ if (one_file_system)
+ filesystem_dev = st.st_dev;
+
+ dir_list = flist_new(WITHOUT_HLINK, "delete_in_dir");
+
+ recurse = 0;
+ filt_array[fa_lvl++] = push_local_filters(fbuf, dlen);
+ send_directory(-1, dir_list, fbuf, dlen);
+ recurse = -1;
+
+ if (dlen == 1 && *fbuf == '.')
+ *fbuf = '\0';
+
+ clean_flist(dir_list, 0, 0);
+
+ if (verbose > 3)
+ output_flist(dir_list, "delete");
+
+ delete_missing(flist, dir_list, fname);
+
+ flist_free(dir_list);
+}
+
+
+/* If an item in dir_list is not found in full_list, delete it from the
+ * filesystem. */
+void delete_missing(struct file_list *full_list, struct file_list *dir_list,
+ const char *dirname)
+{
+ int i, j, mode;
+
+ if (max_delete && deletion_count >= max_delete)
+ return;
+
+ if (verbose > 1)
+ rprintf(FINFO, "deleting in %s\n", safe_fname(dirname));
+
+ for (i = dir_list->count; i--; ) {
+ if (!dir_list->files[i]->basename)
+ continue;
+ mode = dir_list->files[i]->mode;
+ if ((j = flist_find(full_list, dir_list->files[i])) < 0
+ || (delete_during && S_ISDIR(mode)
+ && !S_ISDIR(full_list->files[j]->mode))) {
+ char *f = f_name(dir_list->files[i]);
+ if (make_backups && (backup_dir || !is_backup_file(f))
+ && !S_ISDIR(mode)) {
+ make_backup(f);
+ if (verbose) {
+ rprintf(FINFO, "deleting %s\n",
+ safe_fname(f));
+ }
+ } else if (S_ISDIR(mode)) {
+ int dflag = delete_during ? DEL_FORCE_RECURSE
+ : DEL_NO_RECURSE;
+ delete_file(f, DEL_DIR | dflag);
+ } else {
+ delete_file(f, 0);
+ }
+ deletion_count++;
+ if (max_delete && deletion_count >= max_delete)
+ break;
+ }
+ }