From: Wayne Davison Date: Sun, 26 Apr 2009 14:49:00 +0000 (-0700) Subject: Change sending/receiving/storing of the rdev value for special files. X-Git-Tag: v3.0.6~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4640ae85fe8b35d3410b319f532e3ad9ff7eac79;p=thirdparty%2Frsync.git Change sending/receiving/storing of the rdev value for special files. Since the value is not needed, the (superfluous) sending of the value is optimized so that a valid rdev value is sent as efficiently as possible. The receiver no longer caches an rdev value for special files, and the generator will always pass a 0 rdev value to do_mknod() for special files. Fixes bug #6280. --- diff --git a/NEWS b/NEWS index 574f6525..e9a84b42 100644 --- a/NEWS +++ b/NEWS @@ -51,3 +51,5 @@ Changes since 3.0.5: - Complain and die if the user tries to combine --remove-source-files (or the deprecated --remove-sent-files) with --read-batch. + + - Fixed an failure transferring special files from Solaris to Linux. diff --git a/flist.c b/flist.c index a6107b48..83effc08 100644 --- a/flist.c +++ b/flist.c @@ -425,8 +425,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file, else mode = file->mode; - if ((preserve_devices && IS_DEVICE(mode)) - || (preserve_specials && IS_SPECIAL(mode))) { + if (preserve_devices && IS_DEVICE(mode)) { if (protocol_version < 28) { if (tmp_rdev == rdev) xflags |= XMIT_SAME_RDEV_pre28; @@ -441,6 +440,17 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file, if (protocol_version < 30 && (uint32)minor(rdev) <= 0xFFu) xflags |= XMIT_RDEV_MINOR_8_pre30; } + } else if (preserve_specials && IS_SPECIAL(mode)) { + /* Special files don't need an rdev number, so just make + * the historical transmission of the value efficient. */ + if (protocol_version < 28) + xflags |= XMIT_SAME_RDEV_pre28; + else { + rdev = MAKEDEV(major(rdev), 0); + xflags |= XMIT_SAME_RDEV_MAJOR; + if (protocol_version < 30) + xflags |= XMIT_RDEV_MINOR_8_pre30; + } } else if (protocol_version < 28) rdev = MAKEDEV(0, 0); if (!preserve_uid || ((uid_t)F_OWNER(file) == uid && *lastname)) @@ -725,8 +735,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, uid = F_OWNER(first); if (preserve_gid) gid = F_GROUP(first); - if ((preserve_devices && IS_DEVICE(mode)) - || (preserve_specials && IS_SPECIAL(mode))) { + if (preserve_devices && IS_DEVICE(mode)) { uint32 *devp = F_RDEV_P(first); rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); extra_len += DEV_EXTRA_CNT * EXTRA_LEN; @@ -801,7 +810,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist, rdev_minor = read_int(f); rdev = MAKEDEV(rdev_major, rdev_minor); } - extra_len += DEV_EXTRA_CNT * EXTRA_LEN; + if (IS_DEVICE(mode)) + extra_len += DEV_EXTRA_CNT * EXTRA_LEN; file_length = 0; } else if (protocol_version < 28) rdev = MAKEDEV(0, 0); @@ -942,8 +952,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, } } - if ((preserve_devices && IS_DEVICE(mode)) - || (preserve_specials && IS_SPECIAL(mode))) { + if (preserve_devices && IS_DEVICE(mode)) { uint32 *devp = F_RDEV_P(file); DEV_MAJOR(devp) = major(rdev); DEV_MINOR(devp) = minor(rdev); @@ -1257,10 +1266,11 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, #endif #ifdef HAVE_STRUCT_STAT_ST_RDEV - if (IS_DEVICE(st.st_mode) || IS_SPECIAL(st.st_mode)) { + if (IS_DEVICE(st.st_mode)) { tmp_rdev = st.st_rdev; st.st_size = 0; - } + } else if (IS_SPECIAL(st.st_mode)) + st.st_size = 0; #endif file->flags = flags; diff --git a/generator.c b/generator.c index 6c7bf89f..fb832af2 100644 --- a/generator.c +++ b/generator.c @@ -1124,8 +1124,8 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx, } switch (type) { case TYPE_DIR: - break; case TYPE_SPECIAL: + break; case TYPE_DEVICE: devp = F_RDEV_P(file); if (sxp->st.st_rdev != MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp))) @@ -1613,8 +1613,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if ((am_root && preserve_devices && IS_DEVICE(file->mode)) || (preserve_specials && IS_SPECIAL(file->mode))) { - uint32 *devp = F_RDEV_P(file); - dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); + dev_t rdev; + if (IS_DEVICE(file->mode)) { + uint32 *devp = F_RDEV_P(file); + rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); + } else + rdev = 0; if (statret == 0) { int del_for_flag; if (IS_DEVICE(file->mode)) { @@ -1628,7 +1632,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, } if (statret == 0 && BITS_EQUAL(sx.st.st_mode, file->mode, _S_IFMT) - && sx.st.st_rdev == rdev) { + && (IS_SPECIAL(sx.st.st_mode) || sx.st.st_rdev == rdev)) { /* The device or special file is identical. */ set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT); if (itemizing) diff --git a/xattrs.c b/xattrs.c index 674d3578..63b118a7 100644 --- a/xattrs.c +++ b/xattrs.c @@ -989,7 +989,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode) fst.st_mode &= (_S_IFMT | CHMOD_BITS); fmode = new_mode & (_S_IFMT | CHMOD_BITS); - if (IS_DEVICE(fmode) || IS_SPECIAL(fmode)) { + if (IS_DEVICE(fmode)) { uint32 *devp = F_RDEV_P(file); rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); } else @@ -1000,7 +1000,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode) | (S_ISDIR(fst.st_mode) ? 0700 : 0600); if (fst.st_mode != mode) do_chmod(fname, mode); - if (!IS_DEVICE(fst.st_mode) && !IS_SPECIAL(fst.st_mode)) + if (!IS_DEVICE(fst.st_mode)) fst.st_rdev = 0; /* just in case */ if (mode == fmode && fst.st_rdev == rdev