Fixes bug 7936.
extern int preserve_devices;
extern int preserve_specials;
extern int delete_during;
-extern int uid_ndx;
-extern int gid_ndx;
extern int eol_nulls;
extern int relative_paths;
extern int implied_dirs;
-extern int file_extra_cnt;
extern int ignore_perishable;
extern int non_perishable_cnt;
extern int prune_empty_dirs;
linkname_len = 0;
#endif
+ if (!uid_ndx && flags & FLAG_DEL_NEEDS_UID)
+ extra_len += EXTRA_LEN;
+
#if SIZEOF_CAPITAL_OFF_T >= 8
if (st.st_size > 0xFFFFFFFFu && S_ISREG(st.st_mode))
extra_len += EXTRA_LEN;
file->mode = st.st_mode;
if (uid_ndx) /* Check uid_ndx instead of preserve_uid for del support */
F_OWNER(file) = st.st_uid;
+ else if (flags & FLAG_DEL_NEEDS_UID)
+ F_DEL_OWNER(file) = st.st_uid;
if (gid_ndx) /* Check gid_ndx instead of preserve_gid for del support */
F_GROUP(file) = st.st_gid;
* of the dirname string, and also indicates that "dirname" is a MAXPATHLEN
* buffer (the functions we call will append names onto the end, but the old
* dir value will be restored on exit). */
-struct file_list *get_dirlist(char *dirname, int dlen, int ignore_filter_rules)
+struct file_list *get_dirlist(char *dirname, int dlen, int flags)
{
struct file_list *dirlist;
char dirbuf[MAXPATHLEN];
int save_recurse = recurse;
int save_xfer_dirs = xfer_dirs;
int save_prune_empty_dirs = prune_empty_dirs;
+ int senddir_fd = flags & GDL_IGNORE_FILTER_RULES ? -2 : -1;
if (dlen < 0) {
dlen = strlcpy(dirbuf, dirname, MAXPATHLEN);
recurse = 0;
xfer_dirs = 1;
- send_directory(ignore_filter_rules ? -2 : -1, dirlist, dirname, dlen, FLAG_CONTENT_DIR);
+ send_directory(senddir_fd, dirlist, dirname, dlen,
+ FLAG_CONTENT_DIR | (flags & GDL_DEL_NEEDS_UID ? FLAG_DEL_NEEDS_UID : 0));
xfer_dirs = save_xfer_dirs;
recurse = save_recurse;
if (do_progress)
extern int preserve_executability;
extern int preserve_perms;
extern int preserve_times;
-extern int uid_ndx;
-extern int gid_ndx;
extern int delete_mode;
extern int delete_before;
extern int delete_during;
do_chmod(fbuf, mode | S_IWUSR);
if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
- int save_uid_ndx = uid_ndx;
/* This only happens on the first call to delete_item() since
* delete_dir_contents() always calls us w/DEL_DIR_IS_EMPTY. */
- if (!uid_ndx)
- uid_ndx = ++file_extra_cnt;
ignore_perishable = 1;
/* If DEL_RECURSE is not set, this just reports emptiness. */
ret = delete_dir_contents(fbuf, flags);
ignore_perishable = 0;
- if (!save_uid_ndx) {
- --file_extra_cnt;
- uid_ndx = 0;
- }
if (ret == DR_NOT_EMPTY || ret == DR_AT_LIMIT)
goto check_ret;
/* OK: try to delete the directory. */
save_filters = push_local_filters(fname, dlen);
non_perishable_cnt = 0;
- dirlist = get_dirlist(fname, dlen, 0);
+ dirlist = get_dirlist(fname, dlen, GDL_DEL_NEEDS_UID);
ret = non_perishable_cnt ? DR_NOT_EMPTY : DR_SUCCESS;
if (!dirlist->used)
for (j = dirlist->used; j--; ) {
struct file_struct *fp = dirlist->files[j];
+ uid_t fp_owner = uid_ndx ? F_OWNER(fp) : F_DEL_OWNER(fp);
if (fp->flags & FLAG_MOUNT_DIR && S_ISDIR(fp->mode)) {
if (verbose > 1) {
}
strlcpy(p, fp->basename, remainder);
- if (!(fp->mode & S_IWUSR) && !am_root && (uid_t)F_OWNER(fp) == our_uid)
+ if (!(fp->mode & S_IWUSR) && !am_root && fp_owner == our_uid)
do_chmod(fname, fp->mode | S_IWUSR);
/* Save stack by recursing to ourself directly. */
if (S_ISDIR(fp->mode)) {
struct file_list *dirlist;
char delbuf[MAXPATHLEN];
int dlen, i;
- int save_uid_ndx = uid_ndx;
if (!fbuf) {
change_local_filter_dir(NULL, 0, 0);
return;
}
- if (!uid_ndx)
- uid_ndx = ++file_extra_cnt;
-
- dirlist = get_dirlist(fbuf, dlen, 0);
+ dirlist = get_dirlist(fbuf, dlen, GDL_DEL_NEEDS_UID);
/* If an item in dirlist is not found in flist, delete it
* from the filesystem. */
* 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)
+ uid_t fp_owner = uid_ndx ? F_OWNER(fp) : F_DEL_OWNER(fp);
+ if (!(fp->mode & S_IWUSR) && !am_root && fp_owner == our_uid)
flags |= DEL_NO_UID_WRITE;
f_name(fp, delbuf);
if (delete_during == 2) {
}
flist_free(dirlist);
-
- if (!save_uid_ndx) {
- --file_extra_cnt;
- uid_ndx = 0;
- }
}
/* This deletes any files on the receiving side that are not present on the
if (need_fuzzy_dirlist && S_ISREG(file->mode)) {
strlcpy(fnamecmpbuf, dn, sizeof fnamecmpbuf);
- fuzzy_dirlist = get_dirlist(fnamecmpbuf, -1, 1);
+ fuzzy_dirlist = get_dirlist(fnamecmpbuf, -1, GDL_IGNORE_FILTER_RULES);
need_fuzzy_dirlist = 0;
}
extern int allow_8bit_chars;
extern int protocol_version;
extern int preserve_times;
-extern int uid_ndx;
-extern int gid_ndx;
extern int progress_is_active;
extern int stdout_format_has_i;
extern int stdout_format_has_o_or_i;
extern int am_starting_up;
extern int allow_8bit_chars;
extern int protocol_version;
-extern int uid_ndx;
-extern int gid_ndx;
extern int inc_recurse;
extern int inplace;
extern int flist_eof;
/* These flags are passed to functions but not stored. */
-#define FLAG_DIVERT_DIRS (1<<16)/* sender */
+#define FLAG_DEL_NEEDS_UID (1<<15)/* generator, but must be unique */
+#define FLAG_DIVERT_DIRS (1<<16)/* sender, but must be unique */
+
+/* These flags are for get_dirlist(). */
+#define GDL_IGNORE_FILTER_RULES (1<<0)
+#define GDL_DEL_NEEDS_UID (1<<1)
#define BITS_SET(val,bits) (((val) & (bits)) == (bits))
#define BITS_SETnUNSET(val,onbits,offbits) (((val) & ((onbits)|(offbits))) == (onbits))
#define F_SUM(f) ((char*)OPT_EXTRA(f, LEN64_BUMP(f) + HLINK_BUMP(f) \
+ SUM_EXTRA_CNT - 1))
+/* When deleting w/o --owner, we put the UID info last (like F_SUM(), but smaller).
+ * This is OK, because delete lists never need checksums. */
+#define F_DEL_OWNER(f) OPT_EXTRA(f, LEN64_BUMP(f) + HLINK_BUMP(f))->unum
+
/* Some utility defines: */
#define F_IS_ACTIVE(f) (f)->basename[0]
#define F_IS_HLINKED(f) ((f)->flags & FLAG_HLINKED)