Compare commits

...

28 Commits

Author SHA1 Message Date
Wayne Davison
13074c982b Preparing for release of 3.0.3pre3 2008-06-22 19:03:46 -07:00
Matt McCutchen
2171b9395b The sender now sets IOERR_GENERAL in more skipped-file instances. 2008-06-22 19:00:51 -07:00
Wayne Davison
20bb1eb7ae Mention more fixes in the NEWS. 2008-06-22 18:45:07 -07:00
Wayne Davison
7ee7bcd4e9 Improved the build rules for rsync.1 and rsyncd.conf.5 when building
in a separate build directory from the source.
2008-06-22 18:26:15 -07:00
Wayne Davison
844810d609 Avoid problems with timestamp rounding that cp -p and touch -r may do. 2008-06-17 15:59:47 -07:00
Wayne Davison
67347196b1 Fix the problem with setting xattrs on a directory that has an
identical match found in a --link-dest/--copy-dest hierarchy.
2008-06-12 23:08:43 -07:00
Wayne Davison
e424e26128 Cast the datum_len value to a long for rprintf(). 2008-06-12 06:59:51 -07:00
Wayne Davison
ca7d17e41d Handle a solo_file of a directory for --delete-during. 2008-06-09 07:42:03 -07:00
Wayne Davison
6283e9ef43 A couple more xattr improvements:
- Made the XSTATE_* defines avoid using 0.
- Call !XATTR_ABBREV() in recv_xattr_request().
- Improved the "internal abbrev" error message.
- Fixed the potential for a directory time glitch in xattrs.diff.
2008-06-08 21:14:46 -07:00
Wayne Davison
7462c6ac39 Fixed an "Internal abbrev error" when dealing with an xattr value
that is unchanged on an early file, and changed on a later file.
Added 2 new test cases to ensure this stays fixed.
2008-06-08 20:40:11 -07:00
Wayne Davison
f31850966f Improved the progress_is_active code to not overwrite the progress
output in more circumstances.
2008-06-04 09:01:02 -07:00
Wayne Davison
4ecf3e0671 Improved handling of a system that doesn't have a 64-bit offset type. 2008-06-04 08:15:51 -07:00
Wayne Davison
60a986f504 Improved the proto.h target so that a build in a different dir from the
srcdir will ensure that the builddir has a copy of the proto.h file when
the Makefile found it to be out of date.  This prevents the repeated
building of all the targets when the srcdir's proto.h file is accurate,
but older than the newest .c file.
2008-06-04 07:13:22 -07:00
Wayne Davison
0e9c3564c6 Improved the daemon testing, including adding a test to ensure that
daemon excludes can't exclude a dot dir.
2008-05-31 14:52:24 -07:00
Wayne Davison
164cb66add Fixed the destination path check so that it cannot exclude a
dot dir.
2008-05-31 14:51:38 -07:00
Wayne Davison
0d9eba0312 Have send_file_list() check is_excluded() (but only on non-dot-dirs)
and then call send_file_name() with NO_FILTERS.  This gets rid of
the need for a FLAG_DOTDIR_NAME flag (used only by make_file()).
2008-05-31 14:41:20 -07:00
Wayne Davison
d1f66d8d79 If an arg is excluded, don't include its implied dirs. 2008-05-31 11:29:24 -07:00
Wayne Davison
cc911409d6 Make sure the generator doesn't try to send a negative checksum count to
the sender (which would cause it to die with a cryptic error).  Instead,
warn the user when the file's size is too large for checksum processing.
2008-05-31 10:13:28 -07:00
Wayne Davison
a64f19e24b Fixed the backing up of a device or socket. 2008-05-22 16:44:01 -07:00
Wayne Davison
4337eeb754 A cuple more fixes for --xattrs combined with --backup, this time to
handle when --link-dest is also used.
2008-05-22 07:32:11 -07:00
Wayne Davison
928da42359 Fixed the "src" symlink in each testtmp subdir. 2008-05-18 07:00:48 -07:00
Wayne Davison
e717fa4d37 Fix some path problems when the build dir is not the
source dir.
2008-05-17 15:07:24 -07:00
Wayne Davison
cc56eb2acc Preparing for release of 3.0.3pre2 2008-05-17 10:02:19 -07:00
Wayne Davison
88e05f8489 Fixed an "else" in the device-making part of keep_backup(). 2008-05-17 09:57:08 -07:00
Wayne Davison
9ec8583ef5 Mention the latest fixes in the NEWS. 2008-05-17 09:45:13 -07:00
Wayne Davison
e9489cd6cb Fixed several issues with preserving xattrs when using --backup. 2008-05-17 09:35:46 -07:00
Wayne Davison
f1ca7c4429 Preserve the right errno value when trying adjunct functions during
robust backup, copy, and renaming activities.
2008-05-17 08:25:22 -07:00
Wayne Davison
adc4ebdd76 Improved the docs for --inplace and made the mentions of
rsync's delta-transfer algorithm more consistent.
2008-05-09 23:49:41 -07:00
31 changed files with 493 additions and 158 deletions

View File

@@ -66,8 +66,8 @@ install: all
${INSTALLCMD} ${INSTALL_STRIP} -m 755 rsync$(EXEEXT) ${DESTDIR}${bindir}
-mkdir -p ${DESTDIR}${mandir}/man1
-mkdir -p ${DESTDIR}${mandir}/man5
if test -f $(srcdir)/rsync.1; then ${INSTALLMAN} -m 644 $(srcdir)/rsync.1 ${DESTDIR}${mandir}/man1; fi
if test -f $(srcdir)/rsyncd.conf.5; then ${INSTALLMAN} -m 644 $(srcdir)/rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
if test -f rsync.1; then ${INSTALLMAN} -m 644 rsync.1 ${DESTDIR}${mandir}/man1; fi
if test -f rsyncd.conf.5; then ${INSTALLMAN} -m 644 rsyncd.conf.5 ${DESTDIR}${mandir}/man5; fi
install-strip:
$(MAKE) INSTALL_STRIP='-s' install
@@ -146,12 +146,14 @@ Makefile: Makefile.in config.status
proto: proto.h-tstamp
proto.h: proto.h-tstamp
@echo ' ' >/dev/null
@if test -f proto.h; then :; else cp -p $(srcdir)/proto.h .; fi
proto.h-tstamp: $(srcdir)/*.c $(srcdir)/lib/compat.c
perl $(srcdir)/mkproto.pl $(srcdir)/*.c $(srcdir)/lib/compat.c
man: rsync.1 rsyncd.conf.5
@if test -f rsync.1; then :; else cp -p $(srcdir)/rsync.1 .; fi
@if test -f rsyncd.conf.5; then :; else cp -p $(srcdir)/rsyncd.conf.5 .; fi
rsync.1: rsync.yo
yodl2man -o rsync.1 $(srcdir)/rsync.yo

48
NEWS
View File

@@ -9,30 +9,72 @@ Changes since 3.0.2:
- Fixed a crash bug in the hard-link code.
- Fixed the sending of xattr directory information when the code finds a
--link-dest or --copy-dest directory with unchanged xattrs -- the
destination directory now gets these unchanged xattrs properly applied.
- Fixed an xattr-sending glitch that could cause an "Internal abbrev"
error.
- Fixed the combination of --xattrs and --backup.
- The generator no longer allows a '.' dir to be excluded by a daemon-
exclude rule.
- Fixed deletion handling when copying a single, empty directory (with no
files) to a differently named, non-existent directory.
- Fixed the conversion of spaces into dashes in the %M log escape.
- Fixed several places in the code that were not returning the right
errno when a function failed.
- Fixed the backing up of a device or special file into a backup dir.
- Moved the setting of the socket options prior to the connect().
- If rsync exits in the middle of a --progress output, it now outputs a
newline to prevent the progress line from being overwritten.
newline to help prevent the progress line from being overwritten.
- Fixed a problem with how a destination path with a trailing slash was
compared against the daemon excludes.
- Fixed a problem with how a destination path with a trailing slash or
a trailing dot-dir was compared against the daemon excludes.
- If a file's length is so huge that we overflow a checksum buffer count
(i.e. several hundred TB), warn the user and avoid sending an invalid
checksum struct over the wire.
- If an source arg is excluded, --relative no longer adds the excluded
arg's implied dirs to the transfer. This fix also made the exclude
check happen in the better place in the sending code.
- Use the overflow_exit() function for overflows, not out_of_memory().
- Improved the code to better handle a system that has only 32-bit file
offsets.
ENHANCEMENTS:
- The rsyncd.conf manpage now consistently refers to the parameters in
the daemon config file as "parameters".
- The description of the --inplace option was improved.
DEVELOPER RELATED:
- Fixed a testcase failure if the tests are run as root and made some
compatibility improvements.
- Improved the daemon tests, including checking module comments, the
listing of files, and the ensuring that daemon excludes can't affect
a dot-dir arg.
- Improved some build rules for those that build in a separate directory
from the source, including better install rules for the man pages, and
the fixing of a proto.h-tstamp rule that could make the binaries get
rebuild without cause.
- Improved the testsuite to work around a problem with some utilities
(e.g. cp -p & touch -r) rounding sub-second timestamps.
- Ensure that the early patches don't cause any generated-file hunks to
bleed-over into patches that follow.

View File

@@ -180,10 +180,19 @@ int make_bak_dir(const char *fullpath)
/* robustly move a file, creating new directory structures if necessary */
static int robust_move(const char *src, char *dst)
{
if (robust_rename(src, dst, NULL, 0755) < 0
&& (errno != ENOENT || make_bak_dir(dst) < 0
|| robust_rename(src, dst, NULL, 0755) < 0))
return -1;
if (robust_rename(src, dst, NULL, 0755) < 0) {
int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (errno == ENOENT && make_bak_dir(dst) == 0) {
if (robust_rename(src, dst, NULL, 0755) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
errno = save_errno;
return -1;
}
}
return 0;
}
@@ -195,6 +204,7 @@ static int keep_backup(const char *fname)
stat_x sx;
struct file_struct *file;
char *buf;
int save_preserve_xattrs = preserve_xattrs;
int kept = 0;
int ret_code;
@@ -234,15 +244,23 @@ static int keep_backup(const char *fname)
/* Check to see if this is a device file, or link */
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));
int save_errno;
do_unlink(buf);
if (do_mknod(buf, file->mode, rdev) < 0
&& (errno != ENOENT || make_bak_dir(buf) < 0
|| do_mknod(buf, file->mode, rdev) < 0)) {
rsyserr(FERROR, errno, "mknod %s failed",
full_fname(buf));
} else if (verbose > 2) {
if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0) {
save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (errno == ENOENT && make_bak_dir(buf) == 0) {
if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FERROR, save_errno, "mknod %s failed",
full_fname(buf));
}
} else
save_errno = 0;
if (verbose > 2 && save_errno == 0) {
rprintf(FINFO, "make_backup: DEVICE %s successful.\n",
fname);
}
@@ -252,11 +270,18 @@ static int keep_backup(const char *fname)
if (!kept && S_ISDIR(file->mode)) {
/* make an empty directory */
if (do_mkdir(buf, file->mode) < 0
&& (errno != ENOENT || make_bak_dir(buf) < 0
|| do_mkdir(buf, file->mode) < 0)) {
rsyserr(FINFO, errno, "mkdir %s failed",
full_fname(buf));
if (do_mkdir(buf, file->mode) < 0) {
int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (errno == ENOENT && make_bak_dir(buf) == 0) {
if (do_mkdir(buf, file->mode) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FINFO, save_errno, "mkdir %s failed",
full_fname(buf));
}
}
ret_code = do_rmdir(fname);
@@ -278,11 +303,18 @@ static int keep_backup(const char *fname)
kept = 1;
} else {
do_unlink(buf);
if (do_symlink(sl, buf) < 0
&& (errno != ENOENT || make_bak_dir(buf) < 0
|| do_symlink(sl, buf) < 0)) {
rsyserr(FERROR, errno, "link %s -> \"%s\"",
full_fname(buf), sl);
if (do_symlink(sl, buf) < 0) {
int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (errno == ENOENT && make_bak_dir(buf) == 0) {
if (do_symlink(sl, buf) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FERROR, save_errno, "link %s -> \"%s\"",
full_fname(buf), sl);
}
}
do_unlink(fname);
kept = 1;
@@ -308,7 +340,9 @@ static int keep_backup(const char *fname)
robust_unlink(fname); /* Just in case... */
}
}
preserve_xattrs = 0;
set_file_attrs(buf, file, NULL, fname, 0);
preserve_xattrs = save_preserve_xattrs;
unmake_file(file);
if (verbose > 1) {

View File

@@ -27,7 +27,6 @@ extern int am_daemon;
extern int io_error;
extern int keep_partial;
extern int got_xfer_error;
extern int progress_is_active;
extern char *partial_dir;
extern char *logfile_name;
@@ -116,9 +115,6 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
exit_code = unmodified_code = code;
if (progress_is_active && exit_code && !am_server)
rprintf(FINFO, "\n");
if (verbose > 3) {
rprintf(FINFO,
"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",

View File

@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.59)
RSYNC_VERSION=3.0.3pre1
RSYNC_VERSION=3.0.3pre3
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])

64
flist.c
View File

@@ -638,7 +638,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
int alloc_len, basename_len, linkname_len;
int extra_len = file_extra_cnt * EXTRA_LEN;
int first_hlink_ndx = -1;
OFF_T file_length;
int64 file_length;
const char *basename;
struct file_struct *file;
alloc_pool_t *pool;
@@ -837,8 +837,14 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
if (always_checksum && S_ISREG(mode))
extra_len += SUM_EXTRA_CNT * EXTRA_LEN;
#if SIZEOF_INT64 >= 8
if (file_length > 0xFFFFFFFFu && S_ISREG(mode))
extra_len += EXTRA_LEN;
#endif
if (file_length < 0) {
rprintf(FERROR, "Offset underflow: file-length is negative\n");
exit_cleanup(RERR_UNSUPPORTED);
}
if (inc_recurse && S_ISDIR(mode)) {
if (one_file_system) {
@@ -871,10 +877,17 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
#endif
file->modtime = (time_t)modtime;
file->len32 = (uint32)file_length;
#if SIZEOF_INT64 >= 8
if (file_length > 0xFFFFFFFFu && S_ISREG(mode)) {
#if SIZEOF_CAPITAL_OFF_T < 8
rprintf(FERROR, "Offset overflow: attempted 64-bit file-length\n");
exit_cleanup(RERR_UNSUPPORTED);
#else
file->flags |= FLAG_LENGTH64;
OPT_EXTRA(file, 0)->unum = (uint32)(file_length >> 32);
#endif
}
#endif
file->mode = mode;
if (preserve_uid)
F_OWNER(file) = uid;
@@ -1009,7 +1022,12 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
* and performing extensive checks against global options.
*
* Returns a pointer to the new file struct, or NULL if there was an error
* or this file should be excluded. */
* or this file should be excluded.
*
* Note: Any error (here or in send_file_name) that results in the omission of
* an existent source file from the file list should set
* "io_error |= IOERR_GENERAL" to avoid deletion of the file from the
* destination if --delete is on. */
struct file_struct *make_file(const char *fname, struct file_list *flist,
STRUCT_STAT *stp, int flags, int filter_level)
{
@@ -1023,10 +1041,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
const char *basename;
alloc_pool_t *pool;
STRUCT_STAT st;
int excl_ret;
char *bp;
if (strlcpy(thisname, fname, sizeof thisname) >= sizeof thisname) {
io_error |= IOERR_GENERAL;
rprintf(FINFO, "skipping overly long name: %s\n", fname);
return NULL;
}
@@ -1078,7 +1096,6 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
return NULL;
}
/* backup.c calls us with filter_level set to NO_FILTERS. */
if (filter_level == NO_FILTERS)
goto skip_filters;
@@ -1106,17 +1123,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
} else
flags &= ~FLAG_CONTENT_DIR;
if (S_ISDIR(st.st_mode)) {
if (flags & FLAG_DOTDIR_NAME) {
/* A "." fname (or "/." fname in relative mode) is
* never excluded. No other trailing-dotdir names
* are possible. */
excl_ret = 0;
} else
excl_ret = is_excluded(thisname, 1, filter_level);
} else
excl_ret = is_excluded(thisname, 0, filter_level);
if (excl_ret) {
if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) {
if (ignore_perishable)
non_perishable_cnt++;
return NULL;
@@ -1175,8 +1182,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
linkname_len = 0;
#endif
#if SIZEOF_CAPITAL_OFF_T >= 8
if (st.st_size > 0xFFFFFFFFu && S_ISREG(st.st_mode))
extra_len += EXTRA_LEN;
#endif
#if EXTRA_ROUNDING > 0
if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
@@ -1221,10 +1230,12 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
file->flags = flags;
file->modtime = st.st_mtime;
file->len32 = (uint32)st.st_size;
#if SIZEOF_CAPITAL_OFF_T >= 8
if (st.st_size > 0xFFFFFFFFu && S_ISREG(st.st_mode)) {
file->flags |= FLAG_LENGTH64;
OPT_EXTRA(file, 0)->unum = (uint32)(st.st_size >> 32);
}
#endif
file->mode = st.st_mode;
if (uid_ndx) /* Check uid_ndx instead of preserve_uid for del support */
F_OWNER(file) = st.st_uid;
@@ -1336,15 +1347,19 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
if (preserve_acls && !S_ISLNK(file->mode)) {
sx.st.st_mode = file->mode;
sx.acc_acl = sx.def_acl = NULL;
if (get_acl(fname, &sx) < 0)
if (get_acl(fname, &sx) < 0) {
io_error |= IOERR_GENERAL;
return NULL;
}
}
#endif
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
sx.xattr = NULL;
if (get_xattr(fname, &sx) < 0)
if (get_xattr(fname, &sx) < 0) {
io_error |= IOERR_GENERAL;
return NULL;
}
}
#endif
@@ -1853,7 +1868,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
int64 start_write;
int use_ff_fd = 0;
int disable_buffering;
int arg_flags, flags = recurse ? FLAG_CONTENT_DIR : 0;
int flags = recurse ? FLAG_CONTENT_DIR : 0;
int reading_remotely = filesfrom_host != NULL;
int rl_flags = (reading_remotely ? 0 : RL_DUMP_COMMENTS)
#ifdef ICONV_OPTION
@@ -2035,6 +2050,11 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
continue;
}
/* A dot-dir should not be excluded! */
if (name_type != DOTDIR_NAME
&& is_excluded(fbuf, S_ISDIR(st.st_mode) != 0, ALL_FILTERS))
continue;
if (S_ISDIR(st.st_mode) && !xfer_dirs) {
rprintf(FINFO, "skipping directory %s\n", fbuf);
continue;
@@ -2060,13 +2080,11 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
if (one_file_system)
filesystem_dev = st.st_dev;
arg_flags = name_type == DOTDIR_NAME ? FLAG_DOTDIR_NAME : 0;
if (recurse || (xfer_dirs && name_type != NORMAL_NAME)) {
struct file_struct *file;
arg_flags |= FLAG_TOP_DIR | FLAG_CONTENT_DIR;
file = send_file_name(f, flist, fbuf, &st,
arg_flags | flags, ALL_FILTERS);
FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags,
NO_FILTERS);
if (!file)
continue;
if (inc_recurse) {
@@ -2080,7 +2098,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
} else
send_if_directory(f, flist, file, fbuf, len, flags);
} else
send_file_name(f, flist, fbuf, &st, arg_flags | flags, ALL_FILTERS);
send_file_name(f, flist, fbuf, &st, flags, NO_FILTERS);
}
gettimeofday(&end_tv, NULL);

View File

@@ -697,8 +697,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
if (iflags & ITEM_XNAME_FOLLOWS)
write_vstring(sock_f_out, xname, strlen(xname));
#ifdef SUPPORT_XATTRS
if (iflags & ITEM_REPORT_XATTR && !dry_run)
send_xattr_request(NULL, file, sock_f_out);
if (preserve_xattrs && !dry_run
&& iflags & (ITEM_REPORT_XATTR|ITEM_TRANSFER)) {
send_xattr_request(NULL, file,
iflags & ITEM_REPORT_XATTR ? sock_f_out : -1);
}
#endif
} else if (ndx >= 0) {
enum logcode code = logfile_format_has_i ? FINFO : FCLIENT;
@@ -753,6 +756,7 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len)
{
int32 blength;
int s2length;
int64 l;
if (block_size)
blength = block_size;
@@ -760,7 +764,6 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len)
blength = BLOCK_SIZE;
else {
int32 c;
int64 l;
int cnt;
for (c = 1, l = len, cnt = 0; l >>= 2; c <<= 1, cnt++) {}
if (cnt >= 31 || c >= MAX_BLOCK_SIZE)
@@ -783,7 +786,6 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len)
s2length = SUM_LENGTH;
} else {
int32 c;
int64 l;
int b = BLOCKSUM_BIAS;
for (l = len; l >>= 1; b += 2) {}
for (c = blength; (c >>= 1) && b; b--) {}
@@ -797,7 +799,10 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len)
sum->blength = blength;
sum->s2length = s2length;
sum->remainder = (int32)(len % blength);
sum->count = (int32)(len / blength) + (sum->remainder != 0);
sum->count = (int32)(l = (len / blength) + (sum->remainder != 0));
if ((int64)sum->count != l)
sum->count = -1;
if (sum->count && verbose > 2) {
rprintf(FINFO,
@@ -813,7 +818,7 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len)
*
* Generate approximately one checksum every block_len bytes.
*/
static void generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy)
static int generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy)
{
int32 i;
struct map_struct *mapbuf;
@@ -821,10 +826,12 @@ static void generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy)
OFF_T offset = 0;
sum_sizes_sqroot(&sum, len);
if (sum.count < 0)
return -1;
write_sum_head(f_out, &sum);
if (append_mode > 0 && f_copy < 0)
return;
return 0;
if (len > 0)
mapbuf = map_file(fd, len, MAX_MAP_SIZE, sum.blength);
@@ -861,6 +868,8 @@ static void generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy)
if (mapbuf)
unmap_file(mapbuf);
return 0;
}
@@ -922,6 +931,7 @@ static int copy_altdest_file(const char *src, const char *dest, struct file_stru
{
char buf[MAXPATHLEN];
const char *copy_to, *partialptr;
int save_preserve_xattrs = preserve_xattrs;
int ok, fd_w;
if (inplace) {
@@ -946,7 +956,9 @@ static int copy_altdest_file(const char *src, const char *dest, struct file_stru
return -1;
}
partialptr = partial_dir ? partial_dir_fname(dest) : NULL;
preserve_xattrs = 0; /* xattrs were copied with file */
ok = finish_transfer(dest, copy_to, src, partialptr, file, 1, 0);
preserve_xattrs = save_preserve_xattrs;
cleanup_disable();
return ok ? 0 : -1;
}
@@ -1432,6 +1444,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
if (j == -2) {
itemizing = 0;
code = FNONE;
statret = 1;
} else if (j >= 0)
statret = 1;
}
@@ -1454,6 +1467,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
goto cleanup;
}
}
#ifdef SUPPORT_XATTRS
if (preserve_xattrs && statret == 1)
copy_xattrs(fnamecmpbuf, fname);
#endif
if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0)
&& verbose && code != FNONE && f_out != -1)
rprintf(code, "%s/\n", fname);
@@ -1868,15 +1885,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
close(fd);
goto cleanup;
}
if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0
&& (errno != ENOENT || make_bak_dir(backupptr) < 0
|| (f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0)) {
rsyserr(FERROR_XFER, errno, "open %s",
full_fname(backupptr));
unmake_file(back_file);
back_file = NULL;
close(fd);
goto cleanup;
if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) {
int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (errno == ENOENT && make_bak_dir(backupptr) == 0) {
if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(backupptr));
unmake_file(back_file);
back_file = NULL;
close(fd);
goto cleanup;
}
}
fnamecmp_type = FNAMECMP_BACKUP;
}
@@ -1929,18 +1952,31 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
if (read_batch)
goto cleanup;
if (statret != 0 || whole_file)
if (statret != 0 || whole_file || sx.st.st_size <= 0)
write_sum_head(f_out, NULL);
else {
generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy);
if (generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy) < 0) {
rprintf(FWARNING,
"WARNING: file is too large for checksum sending: %s\n",
fnamecmp);
write_sum_head(f_out, NULL);
}
close(fd);
}
cleanup:
if (back_file) {
int save_preserve_xattrs = preserve_xattrs;
if (f_copy >= 0)
close(f_copy);
#ifdef SUPPORT_XATTRS
if (preserve_xattrs) {
copy_xattrs(fname, backupptr);
preserve_xattrs = 0;
}
#endif
set_file_attrs(backupptr, back_file, NULL, NULL, 0);
preserve_xattrs = save_preserve_xattrs;
if (verbose > 1) {
rprintf(FINFO, "backed up %s to %s\n",
fname, backupptr);
@@ -2179,7 +2215,10 @@ void generate_files(int f_out, const char *local_name)
if (inc_recurse && cur_flist->parent_ndx >= 0) {
struct file_struct *fp = dir_flist->files[cur_flist->parent_ndx];
f_name(fp, fbuf);
if (solo_file)
strlcpy(fbuf, solo_file, sizeof fbuf);
else
f_name(fp, fbuf);
ndx = cur_flist->ndx_start - 1;
recv_generator(fbuf, fp, ndx, itemizing, code, f_out);
if (delete_during && dry_run < 2 && !list_only

View File

@@ -104,7 +104,9 @@ void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
a = b = c = 0xdeadbeef + (8 << 2);
#define rot(x,k) (((x)<<(k)) ^ ((x)>>(32-(k))))
#if SIZEOF_INT64 >= 8
b += (uint32)(key >> 32);
#endif
a += (uint32)key;
c ^= b; c -= rot(b, 14);
a ^= c; a -= rot(c, 11);

6
log.c
View File

@@ -37,6 +37,7 @@ 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 logfile_format_has_i;
@@ -320,6 +321,11 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
exit_cleanup(RERR_MESSAGEIO);
}
if (progress_is_active && !am_server) {
fputc('\n', f);
progress_is_active = 0;
}
trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r')
? buf[--len] : 0;

7
main.c
View File

@@ -509,12 +509,13 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
if (daemon_filter_list.head) {
char *slash = strrchr(dest_path, '/');
if (slash && slash[1] == '\0')
if (slash && (slash[1] == '\0' || (slash[1] == '.' && slash[2] == '\0')))
*slash = '\0';
else
slash = NULL;
if (check_filter(&daemon_filter_list, FLOG, dest_path, 0) < 0
|| check_filter(&daemon_filter_list, FLOG, dest_path, 1) < 0) {
if ((*dest_path != '.' || dest_path[1] != '\0')
&& (check_filter(&daemon_filter_list, FLOG, dest_path, 0) < 0
|| check_filter(&daemon_filter_list, FLOG, dest_path, 1) < 0)) {
rprintf(FERROR, "skipping daemon-excluded destination \"%s\"\n",
dest_path);
exit_cleanup(RERR_FILESELECT);

View File

@@ -1,8 +1,8 @@
Summary: A fast, versatile, remote (and local) file-copying tool
Name: rsync
Version: 3.0.3
%define fullversion %{version}pre1
Release: 0.1.pre1
%define fullversion %{version}pre3
Release: 0.1.pre3
%define srcdir src-previews
Group: Applications/Internet
Source0: http://rsync.samba.org/ftp/rsync/%{srcdir}/rsync-%{fullversion}.tar.gz
@@ -66,8 +66,8 @@ rm -rf $RPM_BUILD_ROOT
%{_mandir}/man5/rsyncd.conf.5*
%changelog
* Wed May 07 2008 Wayne Davison <wayned@samba.org>
Released 3.0.3pre1.
* Sun Jun 22 2008 Wayne Davison <wayned@samba.org>
Released 3.0.3pre3.
* Fri Mar 21 2008 Wayne Davison <wayned@samba.org>
Added installation of /etc/xinetd.d/rsync file and some commented-out

View File

@@ -111,13 +111,13 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
stats.num_transferred_files,
stats.num_files - current_file_index - 1,
stats.num_files);
progress_is_active = 0;
} else {
} else
strlcpy(eol, "\r", sizeof eol);
progress_is_active = 1;
}
progress_is_active = 0;
rprintf(FCLIENT, "%12s %3d%% %7.2f%s %s%s",
human_num(ofs), pct, rate, units, rembuf, eol);
if (!is_last)
progress_is_active = 1;
}
void set_current_file_index(struct file_struct *file, int ndx)

View File

@@ -561,8 +561,12 @@ int finish_transfer(const char *fname, const char *fnametmp,
goto do_set_file_attrs;
}
if (make_backups > 0 && overwriting_basis && !make_backup(fname))
return 1;
if (make_backups > 0 && overwriting_basis) {
if (!make_backup(fname))
return 1;
if (fnamecmp == fname)
fnamecmp = get_backup_name(fname);
}
/* Change permissions before putting the file into place. */
set_file_attrs(fnametmp, file, NULL, fnamecmp,

View File

@@ -83,7 +83,6 @@
/* These flags are passed to functions but not stored. */
#define FLAG_DIVERT_DIRS (1<<16)/* sender */
#define FLAG_DOTDIR_NAME (1<<17)/* sender */
#define BITS_SET(val,bits) (((val) & (bits)) == (bits))
#define BITS_SETnUNSET(val,onbits,offbits) (((val) & ((onbits)|(offbits))) == (onbits))
@@ -498,10 +497,12 @@ typedef unsigned int size_t;
#if SIZEOF_OFF_T == 8 || !SIZEOF_OFF64_T || !defined HAVE_STRUCT_STAT64
#define OFF_T off_t
#define STRUCT_STAT struct stat
#define SIZEOF_CAPITAL_OFF_T SIZEOF_OFF_T
#else
#define OFF_T off64_t
#define STRUCT_STAT struct stat64
#define USE_STAT64_FUNCS 1
#define SIZEOF_CAPITAL_OFF_T SIZEOF_OFF64_T
#endif
/* CAVEAT: on some systems, int64 will really be a 32-bit integer IFF

View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsync)(1)(7 May 2008)()()
manpage(rsync)(1)(22 Jun 2008)()()
manpagename(rsync)(a fast, versatile, remote (and local) file-copying tool)
manpagesynopsis()
@@ -697,13 +697,25 @@ date is on the objects. In other words, if the source has a directory
where the destination has a file, the transfer would occur regardless of
the timestamps.
dit(bf(--inplace)) This causes rsync not to create a new copy of the file
and then move it into place. Instead rsync will overwrite the existing
file, meaning that the rsync algorithm can't accomplish the full amount of
network reduction it might be able to otherwise (since it does not yet try
to sort data matches). One exception to this is if you combine the option
with bf(--backup), since rsync is smart enough to use the backup file as the
basis file for the transfer.
dit(bf(--inplace)) This option changes how rsync transfers a file when the
file's data needs to be updated: instead of the default method of creating
a new copy of the file and moving it into place when it is complete, rsync
instead writes the updated data directly to the destination file.
This has several effects: (1) in-use binaries cannot be updated (either the
OS will prevent this from happening, or binaries that attempt to swap-in
their data will misbehave or crash), (2) the file's data will be in an
inconsistent state during the transfer, (3) a file's data may be left in an
inconsistent state after the transfer if the transfer is interrupted or if
an update fails, (4) a file that does not have write permissions can not be
updated, and (5) the efficiency of rsync's delta-transfer algorithm may be
reduced if some data in the destination file is overwritten before it can
be copied to a position later in the file (one exception to this is if you
combine this option with bf(--backup), since rsync is smart enough to use
the backup file as the basis file for the transfer).
WARNING: you should not use this option to update files that are being
accessed by others, so be careful when choosing to use this for a copy.
This option is useful for transfer of large files with block-based changes
or appended data, and also on systems that are disk bound, not network
@@ -714,12 +726,6 @@ the file), but conflicts with bf(--partial-dir) and bf(--delay-updates).
Prior to rsync 2.6.4 bf(--inplace) was also incompatible with bf(--compare-dest)
and bf(--link-dest).
WARNING: The file's data will be in an inconsistent state during the
transfer (and possibly afterward if the transfer gets interrupted), so you
should not use this option to update files that are in use. Also note that
rsync will be unable to update a file in-place that is not writable by the
receiving user.
dit(bf(--append)) This causes rsync to update a file by appending data onto
the end of the file, which presumes that the data that already exists on
the receiving side is identical with the start of the file on the sending
@@ -986,7 +992,7 @@ with the files and update them on the remote system. Note that if this
option is not used, the optimization that excludes files that have not been
modified cannot be effective; in other words, a missing bf(-t) or bf(-a) will
cause the next transfer to behave as if it used bf(-I), causing all files to be
updated (though the rsync algorithm will make the update fairly efficient
updated (though rsync's delta-transfer algorithm will make the update fairly efficient
if the files haven't actually changed, you're much better off using bf(-t)).
dit(bf(-O, --omit-dir-times)) This tells rsync to omit directories when
@@ -1058,7 +1064,7 @@ the "bytes sent", "bytes received", "literal data", and "matched data"
statistics are too small, and the "speedup" value is equivalent to a run
where no file transfers are needed.
dit(bf(-W, --whole-file)) With this option the delta-transfer algorithm
dit(bf(-W, --whole-file)) With this option rsync's delta-transfer algorithm
is not used and the whole file is sent as-is instead. The transfer may be
faster if this option is used when the bandwidth between the source and
destination machines is higher than the bandwidth to disk (especially when the
@@ -1225,7 +1231,7 @@ transferring small, junk files.
See the bf(--max-size) option for a description of SIZE.
dit(bf(-B, --block-size=BLOCKSIZE)) This forces the block size used in
the rsync algorithm to a fixed value. It is normally selected based on
rsync's delta-transfer algorithm to a fixed value. It is normally selected based on
the size of each file being updated. See the technical report for details.
dit(bf(-e, --rsh=COMMAND)) This option allows you to choose an alternative
@@ -1759,14 +1765,14 @@ For a list of the possible escape characters, see the "log format" setting
in the rsyncd.conf manpage.
dit(bf(--stats)) This tells rsync to print a verbose set of statistics
on the file transfer, allowing you to tell how effective the rsync
on the file transfer, allowing you to tell how effective rsync's delta-transfer
algorithm is for your data.
The current statistics are as follows: quote(itemization(
it() bf(Number of files) is the count of all "files" (in the generic
sense), which includes directories, symlinks, etc.
it() bf(Number of files transferred) is the count of normal files that
were updated via the rsync algorithm, which does not include created
were updated via rsync's delta-transfer algorithm, which does not include created
dirs, symlinks, etc.
it() bf(Total file size) is the total sum of all file sizes in the transfer.
This does not count any size for directories or special files, but does
@@ -1827,7 +1833,7 @@ after it has served its purpose.
Note that if bf(--whole-file) is specified (or implied), any partial-dir
file that is found for a file that is being updated will simply be removed
(since
rsync is sending files without using the delta transfer algorithm).
rsync is sending files without using rsync's delta-transfer algorithm).
Rsync will create the em(DIR) if it is missing (just the last dir -- not
the whole path). This makes it easy to use a relative path (such as
@@ -1945,7 +1951,7 @@ sender's file, which is being reconstructed at a rate of 110.64 kilobytes
per second, and the transfer will finish in 4 seconds if the current rate
is maintained until the end.
These statistics can be misleading if the delta transfer algorithm is
These statistics can be misleading if rsync's delta-transfer algorithm is
in use. For example, if the sender's file consists of the basis file
followed by additional data, the reported rate will probably drop
dramatically when the receiver gets to the literal data, and the transfer
@@ -2876,7 +2882,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 3.0.3pre1 of rsync.
This man page is current for version 3.0.3pre3 of rsync.
manpagesection(INTERNAL OPTIONS)

View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsyncd.conf)(5)(7 May 2008)()()
manpage(rsyncd.conf)(5)(22 Jun 2008)()()
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
manpagesynopsis()
@@ -700,7 +700,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 3.0.3pre1 of rsync.
This man page is current for version 3.0.3pre3 of rsync.
manpagesection(CREDITS)

View File

@@ -155,10 +155,10 @@ RSYNC="$rsync_bin $*"
#RSYNC="valgrind $rsync_bin $*"
TLS_ARGS=''
if egrep '^#define HAVE_LUTIMES 1' "$srcdir/config.h" >/dev/null; then
if egrep '^#define HAVE_LUTIMES 1' config.h >/dev/null; then
TLS_ARGS="$TLS_ARGS -l"
fi
if egrep '#undef CHOWN_MODIFIES_SYMLINK' "$srcdir/config.h" >/dev/null; then
if egrep '#undef CHOWN_MODIFIES_SYMLINK' config.h >/dev/null; then
TLS_ARGS="$TLS_ARGS -L"
fi
@@ -238,7 +238,10 @@ prep_scratch() {
# Get rid of default ACLs and dir-setgid to avoid confusing some tests.
$setfacl_nodef "$scratchdir" || true
chmod g-s "$scratchdir"
ln -s "$srcdir" "$scratchdir/src"
case "$srcdir" in
/*) ln -s "$srcdir" "$scratchdir/src" ;;
*) ln -s "$TOOLDIR/$srcdir" "$scratchdir/src" ;;
esac
return 0
}

View File

@@ -26,6 +26,7 @@ int module_id = -1;
int relative_paths = 0;
int human_readable = 0;
int module_dirlen = 0;
int preserve_xattrs = 0;
mode_t orig_umask = 002;
char *partial_dir;
char *module_dir;
@@ -69,6 +70,11 @@ struct filter_list_struct daemon_filter_list;
return -1;
}
int copy_xattrs(UNUSED(const char *source), UNUSED(const char *dest))
{
return -1;
}
char *lp_name(UNUSED(int mod))
{
return NULL;

View File

@@ -36,7 +36,7 @@ for fn in deep/name1 deep/name2; do
done
echo deleted-file >"$todir/dname"
cp -p "$todir/dname" "$chkdir"
cp_touch "$todir/dname" "$chkdir"
checkit "$RSYNC -avv --no-whole-file --delete-delay \
--backup --backup-dir='$bakdir' '$fromdir/' '$todir/'" "$fromdir" "$todir" \

View File

@@ -19,15 +19,23 @@
# checking the log file
# password authentication
# TODO: Put the common framework in a common file, so that we can have
# subtests fail and keep going.
. "$suitedir/rsync.fns"
chkfile="$scratchdir/rsync.chk"
outfile="$scratchdir/rsync.out"
SSH="src/support/lsh --no-cd"
DIR_REPL='s/^\(d[^ ]*\) *[0-9][0-9]* /\1 DIR /'
LS_REPL='s;[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9];####/##/## ##:##:##;'
build_rsyncd_conf
makepath "$fromdir/foo" "$fromdir/bar/baz"
makepath "$todir"
echo one >"$fromdir/foo/one"
echo two >"$fromdir/bar/two"
echo three >"$fromdir/bar/baz/three"
cd "$scratchdir"
ln -s test-rsyncd.conf rsyncd.conf
@@ -46,4 +54,36 @@ $RSYNC -ve "$SSH" --rsync-path="$RSYNC$confopt" localhost::
RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
export RSYNC_CONNECT_PROG
$RSYNC -v localhost::
$RSYNC -v localhost:: \
| tee "$outfile"
# These have a space-padded 15-char name, then a tab, then a comment.
sed 's/NOCOMMENT//' <<EOT >"$chkfile"
test-from r/o
test-to r/w
test-scratch NOCOMMENT
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
$RSYNC -r localhost::test-hidden \
| sed "$DIR_REPL" | sed "$LS_REPL" \
| tee "$outfile"
cat <<EOT >"$chkfile"
drwxr-xr-x DIR ####/##/## ##:##:## .
drwxr-xr-x DIR ####/##/## ##:##:## bar
-rw-r--r-- 4 ####/##/## ##:##:## bar/two
drwxr-xr-x DIR ####/##/## ##:##:## bar/baz
-rw-r--r-- 6 ####/##/## ##:##:## bar/baz/three
drwxr-xr-x DIR ####/##/## ##:##:## foo
-rw-r--r-- 4 ####/##/## ##:##:## foo/one
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
$RSYNC -r localhost::test-from/f* \
| sed "$DIR_REPL" | sed "$LS_REPL" \
| tee "$outfile"
cat <<EOT >"$chkfile"
drwxr-xr-x DIR ####/##/## ##:##:## foo
-rw-r--r-- 4 ####/##/## ##:##:## foo/one
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"

View File

@@ -76,7 +76,8 @@ mknod "$fromdir/block2" b 42 73 || test_skipped "Can't create block device node"
mknod "$fromdir/block3" b 105 73 || test_skipped "Can't create block device node"
ln "$fromdir/block3" "$fromdir/block2.5" || echo "Skipping hard-linked device test..."
mkfifo "$fromdir/fifo" || mknod "$fromdir/fifo" p || test_skipped "Can't run mkfifo"
touch -r "$fromdir/block" "$fromdir/block2"
# Work around time rounding/truncating issue by touching both files.
touch -r "$fromdir/block" "$fromdir/block" "$fromdir/block2"
$RSYNC -ai "$fromdir/block" "$todir/block2" \
| tee "$outfile"

View File

@@ -153,13 +153,13 @@ checkit "$RSYNC -avvC --filter='merge $excl' --delete-excluded \
rm "$chkdir"/foo/file1
rm "$chkdir"/bar/down/to/bar/baz/*.deep
cp -p "$fromdir"/bar/down/to/foo/*.junk "$chkdir"/bar/down/to/foo
cp -p "$fromdir"/bar/down/to/foo/to "$chkdir"/bar/down/to/foo
cp_touch "$fromdir"/bar/down/to/foo/*.junk "$chkdir"/bar/down/to/foo
cp_touch "$fromdir"/bar/down/to/foo/to "$chkdir"/bar/down/to/foo
$RSYNC -av --existing -f 'show .filt*' -f 'hide,! */' --del "$fromdir/" "$todir/"
echo retained >"$todir"/bar/down/to/bar/baz/nodel.deep
cp -p "$todir"/bar/down/to/bar/baz/nodel.deep "$chkdir"/bar/down/to/bar/baz
cp_touch "$todir"/bar/down/to/bar/baz/nodel.deep "$chkdir"/bar/down/to/bar/baz
$RSYNC -av --existing --filter='-! */' "$fromdir/" "$chkdir/"

View File

@@ -13,7 +13,7 @@ mkdir "$fromdir"
mkdir "$todir"
cp -p "$srcdir"/rsync.c "$fromdir"/rsync.c
cp -p "$fromdir"/rsync.c "$todir"/rsync2.c
cp_touch "$fromdir"/rsync.c "$todir"/rsync2.c
sleep 1
# Let's do it!

View File

@@ -11,7 +11,7 @@
. "$suitedir/rsync.fns"
SSH=support/lsh
SSH="$scratchdir/src/support/lsh"
outfile="$scratchdir/rsync.out"

View File

@@ -28,8 +28,7 @@ ln "$fromdir/foo/config1" "$fromdir/foo/extra"
rm -f "$to2dir"
# Check if rsync is set to hard-link symlinks.
confile=`echo "$scratchdir" | sed 's;/testtmp/itemize$;/config.h;'`
if egrep '^#define CAN_HARDLINK_SYMLINK 1' "$confile" >/dev/null; then
if egrep '^#define CAN_HARDLINK_SYMLINK 1' config.h >/dev/null; then
L=hL
else
L=cL

View File

@@ -19,15 +19,15 @@ mkdir from2/sub1 from3/sub1
mkdir from3/sub2 from1/dir-and-not-dir
mkdir chk chk/sub1 chk/sub2 chk/dir-and-not-dir
echo "one" >from1/one
cp -p from1/one from2/one
cp -p from1/one from3/one
cp_touch from1/one from2/one
cp_touch from1/one from3/one
echo "two" >from1/two
echo "three" >from2/three
echo "four" >from3/four
echo "five" >from1/five
echo "six" >from3/six
echo "sub1" >from2/sub1/uno
cp -p from2/sub1/uno from3/sub1/uno
cp_touch from2/sub1/uno from3/sub1/uno
echo "sub2" >from3/sub1/dos
echo "sub3" >from2/sub1/tres
echo "subby" >from3/sub2/subby
@@ -36,11 +36,11 @@ echo "not-dir" >from3/dir-and-not-dir
echo "arg-test" >deep/arg-test
echo "shallow" >shallow
cp -p from1/one from1/two from2/three from3/four from1/five from3/six chk
cp -p deep/arg-test shallow chk
cp -p from1/dir-and-not-dir/inside chk/dir-and-not-dir
cp -p from2/sub1/uno from3/sub1/dos from2/sub1/tres chk/sub1
cp -p from3/sub2/subby chk/sub2
cp_touch from1/one from1/two from2/three from3/four from1/five from3/six chk
cp_touch deep/arg-test shallow chk
cp_touch from1/dir-and-not-dir/inside chk/dir-and-not-dir
cp_touch from2/sub1/uno from3/sub1/dos from2/sub1/tres chk/sub1
cp_touch from3/sub2/subby chk/sub2
# Make sure that time has moved on.
sleep 1

View File

@@ -52,6 +52,29 @@ runtest() {
fi
}
set_cp_destdir() {
while test $# -gt 1; do
shift
done
destdir="$1"
}
# Perform a "cp -p", making sure that timestamps are really the same,
# even if the copy rounded microsecond times on the destination file.
cp_touch() {
cp -p "${@}" || test_fail "cp -p failed"
if test $# -gt 2 -o -d "$2"; then
set_cp_destdir "${@}" # sets destdir var
while test $# -gt 1; do
destname="$destdir/`basename $1`"
touch -r "$destname" "$1" "$destname"
shift
done
else
touch -r "$2" "$1" "$2"
fi
}
# Call this if you want to filter out verbose messages (-v or -vv) from
# the output of an rsync run (whittling the output down to just the file
# messages). This isn't needed if you use -i without -v.
@@ -244,7 +267,7 @@ hosts allow = localhost 127.0.0.0/24 192.168.0.0/16 10.0.0.0/8 $hostname
log file = $logfile
log format = %i %h [%a] %m (%u) %l %f%L
transfer logging = yes
exclude = foobar.baz
exclude = ? foobar.baz
max verbosity = 9
uid = 0
gid = 0
@@ -252,14 +275,20 @@ gid = 0
[test-from]
path = $fromdir
read only = yes
comment = r/o
[test-to]
path = $todir
read only = no
comment = r/w
[test-scratch]
path = $scratchdir
read only = no
[test-hidden]
path = $fromdir
list = no
EOF
# Build a helper script to ignore exit code 23

View File

@@ -10,7 +10,7 @@
. "$suitedir/rsync.fns"
SSH=support/lsh
SSH="$scratchdir/src/support/lsh"
if test x"$rsync_enable_ssh_tests" = xyes; then
if type ssh >/dev/null ; then

View File

@@ -46,7 +46,7 @@ echo deeper >"$fromdir/foo/bar/file5"
makepath "$chkdir/foo"
echo wow >"$chkdir/file1"
cp -p "$fromdir/foo/file3" "$chkdir/foo"
cp_touch "$fromdir/foo/file3" "$chkdir/foo"
files='foo file0 file1 file2 foo/file3 file4 foo/bar/file5'
@@ -64,6 +64,10 @@ xset user.foo foo file2
xset user.bar bar file2
xset user.long 'a long attribute for our new file that tests to ensure that this works' file2
xset user.dir1 'need to test directory xattrs too' foo
xset user.dir2 'another xattr' foo
xset user.dir3 'this is one last one for the moment' foo
xset user.foo 'new foo' foo/file3 foo/bar/file5
xset user.bar 'new bar' foo/file3 foo/bar/file5
xset user.long 'this is also a long attribute that will be truncated in the initial data send' foo/file3 foo/bar/file5
@@ -91,12 +95,12 @@ cd "$todir"
xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
cd "$fromdir"
rm -rf "$todir"
xset user.nice 'this is nice, but different' file1
xls $files >"$scratchdir/xattrs.txt"
rm -rf "$todir"
checkit "$RSYNC -aiX --fake-super --link-dest=../chk . ../to" "$chkdir" "$todir"
cd "$todir"
@@ -109,5 +113,31 @@ if [ -s "$scratchdir/ls-diff" ]; then
exit 1
fi
cd "$fromdir"
rm -rf "$todir" "$chkdir"
rsync -aX file1 file2
rsync -aX file1 file2 ../chk/
rsync -aX --del ../chk/ .
rsync -aX file1 ../lnk/
xls file1 file2 >"$scratchdir/xattrs.txt"
checkit "$RSYNC -aiiX --copy-dest=../lnk . ../to" "$chkdir" "$todir"
cd "$todir"
xls file1 file2 | diff $diffopt "$scratchdir/xattrs.txt" -
cd "$fromdir"
rm "$todir/file2"
echo extra >file1
rsync -aX . ../chk/
checkit "$RSYNC -aiiX . ../to" "$chkdir" "$todir"
cd "$todir"
xls file1 file2 | diff $diffopt "$scratchdir/xattrs.txt" -
# The script would have aborted on error, so getting here means we've won.
exit 0

43
util.c
View File

@@ -29,6 +29,7 @@ extern int module_id;
extern int modify_window;
extern int relative_paths;
extern int human_readable;
extern int preserve_xattrs;
extern char *module_dir;
extern unsigned int module_dirlen;
extern mode_t orig_umask;
@@ -264,6 +265,8 @@ static int safe_read(int desc, char *ptr, size_t len)
/* Copy a file. If ofd < 0, copy_file unlinks and opens the "dest" file.
* Otherwise, it just writes to and closes the provided file descriptor.
* In either case, if --xattrs are being preserved, the dest file will
* have its xattrs set from the source file.
*
* This is used in conjunction with the --temp-dir, --backup, and
* --copy-dest options. */
@@ -275,38 +278,54 @@ int copy_file(const char *source, const char *dest, int ofd,
int len; /* Number of bytes read into `buf'. */
if ((ifd = do_open(source, O_RDONLY, 0)) < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "open %s", full_fname(source));
errno = save_errno;
return -1;
}
if (ofd < 0) {
if (robust_unlink(dest) && errno != ENOENT) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(dest));
errno = save_errno;
return -1;
}
if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0
&& (!create_bak_dir || errno != ENOENT || make_bak_dir(dest) < 0
|| (ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)) {
rsyserr(FERROR_XFER, errno, "open %s", full_fname(dest));
close(ifd);
return -1;
if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) {
int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
if (create_bak_dir && errno == ENOENT && make_bak_dir(dest) == 0) {
if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(dest));
close(ifd);
errno = save_errno;
return -1;
}
}
}
while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
if (full_write(ofd, buf, len) < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "write %s", full_fname(dest));
close(ifd);
close(ofd);
errno = save_errno;
return -1;
}
}
if (len < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "read %s", full_fname(source));
close(ifd);
close(ofd);
errno = save_errno;
return -1;
}
@@ -316,11 +335,18 @@ int copy_file(const char *source, const char *dest, int ofd,
}
if (close(ofd) < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "close failed on %s",
full_fname(dest));
errno = save_errno;
return -1;
}
#ifdef SUPPORT_XATTRS
if (preserve_xattrs)
copy_xattrs(source, dest);
#endif
return 0;
}
@@ -401,8 +427,11 @@ int robust_rename(const char *from, const char *to, const char *partialptr,
switch (errno) {
#ifdef ETXTBSY
case ETXTBSY:
if (robust_unlink(to) != 0)
if (robust_unlink(to) != 0) {
errno = ETXTBSY;
return -1;
}
errno = ETXTBSY;
break;
#endif
case EXDEV:

View File

@@ -44,9 +44,9 @@ extern int checksum_seed;
#define XATTR_ABBREV(x) ((size_t)((x).name - (x).datum) < (x).datum_len)
#define XSTATE_ABBREV 0
#define XSTATE_DONE 1
#define XSTATE_TODO 2
#define XSTATE_ABBREV 1
#define XSTATE_DONE 2
#define XSTATE_TODO 3
#define USER_PREFIX "user."
#define UPRE_LEN ((int)sizeof USER_PREFIX - 1)
@@ -288,6 +288,48 @@ int get_xattr(const char *fname, stat_x *sxp)
return 0;
}
int copy_xattrs(const char *source, const char *dest)
{
ssize_t list_len, name_len;
size_t datum_len;
char *name, *ptr;
#ifdef HAVE_LINUX_XATTRS
int user_only = am_sender ? 0 : !am_root;
#endif
/* This puts the name list into the "namebuf" buffer. */
if ((list_len = get_xattr_names(source)) < 0)
return -1;
for (name = namebuf; list_len > 0; name += name_len) {
name_len = strlen(name) + 1;
list_len -= name_len;
#ifdef HAVE_LINUX_XATTRS
/* We always ignore the system namespace, and non-root
* ignores everything but the user namespace. */
if (user_only ? !HAS_PREFIX(name, USER_PREFIX)
: HAS_PREFIX(name, SYSTEM_PREFIX))
continue;
#endif
datum_len = 0;
if (!(ptr = get_xattr_data(source, name, &datum_len, 0)))
return -1;
if (sys_lsetxattr(dest, name, ptr, datum_len) < 0) {
int save_errno = errno ? errno : EINVAL;
rsyserr(FERROR_XFER, errno,
"rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
dest, name);
errno = save_errno;
return -1;
}
free(ptr);
}
return 0;
}
static int find_matching_xattr(item_list *xalp)
{
size_t i, j;
@@ -461,9 +503,11 @@ int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all)
return !xattrs_equal;
}
/* When called by the generator with a NULL fname, this tells the sender
* which abbreviated xattr values we need. When called by the sender
* (with a non-NULL fname), we send all the extra xattr data it needs. */
/* When called by the generator (with a NULL fname), this tells the sender
* all the abbreviated xattr values we need. When called by the sender
* (with a non-NULL fname), we send all the extra xattr data it needs.
* The generator may also call with f_out < 0 to just change all the
* XSTATE_ABBREV states into XSTATE_DONE. */
void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
{
item_list *lst = rsync_xal_l.items;
@@ -482,6 +526,7 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
rxa->datum[0] = XSTATE_DONE;
continue;
case XSTATE_TODO:
assert(f_out >= 0);
break;
default:
continue;
@@ -510,7 +555,8 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
}
}
write_byte(f_out, 0); /* end the list */
if (f_out >= 0)
write_byte(f_out, 0); /* end the list */
}
/* When called by the sender, read the request from the generator and mark
@@ -544,8 +590,9 @@ int recv_xattr_request(struct file_struct *file, int f_in)
who_am_i(), num, f_name(file, NULL));
exit_cleanup(RERR_STREAMIO);
}
if (rxa->datum_len <= MAX_FULL_DATUM || rxa->datum[0] != XSTATE_ABBREV) {
rprintf(FERROR, "[%s] internal abbrev error!\n", who_am_i());
if (!XATTR_ABBREV(*rxa) || rxa->datum[0] != XSTATE_ABBREV) {
rprintf(FERROR, "[%s] internal abbrev error on %s (%s, len=%ld)!\n",
who_am_i(), f_name(file, NULL), rxa->name, (long)rxa->datum_len);
exit_cleanup(RERR_STREAMIO);
}