From d4d56eed8a2dfdd2cd78a19f9c1bae02496427e3 Mon Sep 17 00:00:00 2001 From: Matt McCutchen Date: Mon, 10 Nov 2008 06:44:01 -0800 Subject: [PATCH] Add flist_find_ignore_dirness() and change delete_in_dir() to use it. This fixes an issue with -K noticed by eric casteleijn, avoids some inconsistent itemizing when a file/dir is replaced by a dir/file, and removes a now-obsolete chunk of code from make_file(). --- flist.c | 41 ++++++++++++++++++++++------------------- generator.c | 5 ++++- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/flist.c b/flist.c index 19936cab..570c3b79 100644 --- a/flist.c +++ b/flist.c @@ -1332,25 +1332,6 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, else if (!pool) F_DEPTH(file) = extra_len / EXTRA_LEN; - /* This code is only used by the receiver when it is building - * a list of files for a delete pass. */ - if (keep_dirlinks && linkname_len && flist) { - STRUCT_STAT st2; - int save_mode = file->mode; - file->mode = S_IFDIR; /* Find a directory with our name. */ - if (flist_find(dir_flist, file) >= 0 - && x_stat(thisname, &st2, NULL) == 0 && S_ISDIR(st2.st_mode)) { - file->modtime = st2.st_mtime; - file->len32 = 0; - file->mode = st2.st_mode; - if (uid_ndx) - F_OWNER(file) = st2.st_uid; - if (gid_ndx) - F_GROUP(file) = st2.st_gid; - } else - file->mode = save_mode; - } - if (basename_len == 0+1) { if (!pool) unmake_file(file); @@ -2533,6 +2514,28 @@ int flist_find(struct file_list *flist, struct file_struct *f) return -1; } +/* Search for an identically-named item in the file list. Differs from + * flist_find in that an item that agrees with "f" in directory-ness is + * preferred but one that does not is still found. */ +int flist_find_ignore_dirness(struct file_list *flist, struct file_struct *f) +{ + mode_t save_mode; + int ndx; + + /* First look for an item that agrees in directory-ness. */ + ndx = flist_find(flist, f); + if (ndx >= 0) + return ndx; + + /* Temporarily flip f->mode to look for an item of opposite + * directory-ness. */ + save_mode = f->mode; + f->mode = S_ISDIR(f->mode) ? S_IFREG : S_IFDIR; + ndx = flist_find(flist, f); + f->mode = save_mode; + return ndx; +} + /* * Free up any resources a file_struct has allocated * and clear the file. diff --git a/generator.c b/generator.c index 6a0d5271..1db0fe01 100644 --- a/generator.c +++ b/generator.c @@ -535,7 +535,10 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev) f_name(fp, NULL)); continue; } - if (flist_find(cur_flist, fp) < 0) { + /* Here we want to match regardless of file type. Replacement + * of a file with one of another type is handled separately by + * a delete_item call with a DEL_MAKE_ROOM flag. */ + if (flist_find_ignore_dirness(cur_flist, fp) < 0) { int flags = DEL_RECURSE; if (!(fp->mode & S_IWUSR) && !am_root && (uid_t)F_OWNER(fp) == our_uid) flags |= DEL_NO_UID_WRITE; -- 2.34.1