summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWayne Davison <wayned@samba.org>2009-04-26 07:49:00 -0700
committerWayne Davison <wayned@samba.org>2009-04-26 07:51:50 -0700
commit4640ae85fe8b35d3410b319f532e3ad9ff7eac79 (patch)
tree323da129ce549483dfd152100a07915928f2e49d
parent24f739c11845b467175e75f5d15a2645af0bb473 (diff)
downloadrsync-4640ae85fe8b35d3410b319f532e3ad9ff7eac79.tar.gz
rsync-4640ae85fe8b35d3410b319f532e3ad9ff7eac79.tar.bz2
rsync-4640ae85fe8b35d3410b319f532e3ad9ff7eac79.zip
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.
-rw-r--r--NEWS2
-rw-r--r--flist.c28
-rw-r--r--generator.c12
-rw-r--r--xattrs.c4
4 files changed, 31 insertions, 15 deletions
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