mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-29 09:17:21 -04:00
Compare commits
35 Commits
v3.0.0pre8
...
v3.0.0pre9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
205393a2b5 | ||
|
|
5f0f2e0894 | ||
|
|
a5bb0902b4 | ||
|
|
d348d5fd5f | ||
|
|
21897ecbed | ||
|
|
01103e1870 | ||
|
|
2d8f9b1df0 | ||
|
|
68f1e7e594 | ||
|
|
87629cf2f6 | ||
|
|
e7f642cffe | ||
|
|
3e8fe565ed | ||
|
|
e96c7777d7 | ||
|
|
71daa07fb1 | ||
|
|
287bb276d5 | ||
|
|
ddc8110dea | ||
|
|
c0f4228d66 | ||
|
|
d6e6333a02 | ||
|
|
970ce063ee | ||
|
|
dd1f0da818 | ||
|
|
38a4bd432a | ||
|
|
3eabe6aa41 | ||
|
|
f2b7b64d86 | ||
|
|
b2057d38a9 | ||
|
|
964244b90d | ||
|
|
a7c1fa0049 | ||
|
|
42a28d9d3a | ||
|
|
19284e2ef8 | ||
|
|
2268defe66 | ||
|
|
643b018cfb | ||
|
|
e35ad79b1b | ||
|
|
da01d2e843 | ||
|
|
641dc0c51e | ||
|
|
69e2b4ee3a | ||
|
|
75a01a0734 | ||
|
|
b769ad6a3e |
13
NEWS
13
NEWS
@@ -11,6 +11,7 @@ Changes since 2.6.9:
|
||||
an implied dir be duplicated as a symlink, you should specify the
|
||||
transfer of the symlink and the transfer of the referent directory as
|
||||
separate args. (See also --keep-dirlinks and --no-implied-dirs.)
|
||||
Also, exclude rules no longer have a partial effect on implied dirs.
|
||||
|
||||
- Requesting a remote file list without specifying -r (--recursive) now
|
||||
sends the -d (--dirs) option to the remote rsync rather than sending -r
|
||||
@@ -21,7 +22,7 @@ Changes since 2.6.9:
|
||||
- In --dry-run mode, the last line of the verbose summary text is output
|
||||
with a "(DRY RUN)" suffix to help remind you that no updates were made.
|
||||
|
||||
- A writable rsync daemon that disables "use chroot" now defaults to a
|
||||
- A writable rsync daemon with "use chroot" disabled now defaults to a
|
||||
symlink-munging behavior designed to make symlinks safer while also
|
||||
allowing absolute symlinks to be stored and retrieved. This also has
|
||||
the effect of making symlinks unusable while they're in the daemon's
|
||||
@@ -35,8 +36,8 @@ Changes since 2.6.9:
|
||||
--backup-dir, --temp-dir, and --files-from.
|
||||
|
||||
- If a file's data arrived successfully on the receiving side but the
|
||||
rename of the tempory file to the destination file failed AND the
|
||||
--remove-souce-files (or the deprecated --remove-sent-files) option
|
||||
rename of the temporary file to the destination file failed AND the
|
||||
--remove-source-files (or the deprecated --remove-sent-files) option
|
||||
was specified, rsync no longer erroneously removes the associated
|
||||
source file.
|
||||
|
||||
@@ -97,6 +98,10 @@ Changes since 2.6.9:
|
||||
- Any errors output about password-file reading no longer cause an error at
|
||||
the end of the run about a partial transfer.
|
||||
|
||||
- The --read-batch option for protocol 30 now ensures that several more
|
||||
options are set correctly for the current batch file: --iconv, --acls,
|
||||
--xattrs, --inplace, --append, and --append-verify.
|
||||
|
||||
- Using --only-write-batch to a daemon receiver now work properly (older
|
||||
versions would update some files while writing the batch).
|
||||
|
||||
@@ -132,7 +137,7 @@ Changes since 2.6.9:
|
||||
- Added the --acls (-A) option to preserve Access Control Lists. This is
|
||||
an improved version of the prior patch that was available, and it even
|
||||
supports OS X ACLs. If you need to have backward compatibility with old,
|
||||
acl-patched versions of rsync, apply the acls.diff file from the patches
|
||||
ACL-patched versions of rsync, apply the acls.diff file from the patches
|
||||
dir.
|
||||
|
||||
- Added the --xattrs (-X) option to preserver extended attributes. This is
|
||||
|
||||
76
batch.c
76
batch.c
@@ -31,15 +31,25 @@ extern int preserve_hard_links;
|
||||
extern int preserve_devices;
|
||||
extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
extern int preserve_acls;
|
||||
extern int preserve_xattrs;
|
||||
extern int always_checksum;
|
||||
extern int do_compression;
|
||||
extern int def_compress_level;
|
||||
extern int inplace;
|
||||
extern int append_mode;
|
||||
extern int protocol_version;
|
||||
extern char *batch_name;
|
||||
#ifdef ICONV_OPTION
|
||||
extern char *iconv_opt;
|
||||
#endif
|
||||
|
||||
extern struct filter_list_struct filter_list;
|
||||
|
||||
static int tweaked_compress_level;
|
||||
int batch_stream_flags;
|
||||
|
||||
static int tweaked_append;
|
||||
static int tweaked_append_verify;
|
||||
static int tweaked_iconv;
|
||||
|
||||
static int *flag_ptr[] = {
|
||||
&recurse, /* 0 */
|
||||
@@ -50,7 +60,13 @@ static int *flag_ptr[] = {
|
||||
&preserve_hard_links, /* 5 */
|
||||
&always_checksum, /* 6 */
|
||||
&xfer_dirs, /* 7 (protocol 29) */
|
||||
&tweaked_compress_level,/* 8 (protocol 29) */
|
||||
&do_compression, /* 8 (protocol 29) */
|
||||
&tweaked_iconv, /* 9 (protocol 30) */
|
||||
&preserve_acls, /* 10 (protocol 30) */
|
||||
&preserve_xattrs, /* 11 (protocol 30) */
|
||||
&inplace, /* 12 (protocol 30) */
|
||||
&tweaked_append, /* 13 (protocol 30) */
|
||||
&tweaked_append_verify, /* 14 (protocol 30) */
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -64,6 +80,12 @@ static char *flag_name[] = {
|
||||
"--checksum (-c)",
|
||||
"--dirs (-d)",
|
||||
"--compress (-z)",
|
||||
"--iconv",
|
||||
"--acls (-A)",
|
||||
"--xattrs (-X)",
|
||||
"--inplace",
|
||||
"--append",
|
||||
"--append-verify",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -71,16 +93,14 @@ void write_stream_flags(int fd)
|
||||
{
|
||||
int i, flags;
|
||||
|
||||
#if Z_DEFAULT_COMPRESSION == -1
|
||||
tweaked_compress_level = do_compression ? def_compress_level + 2 : 0;
|
||||
#else
|
||||
#error internal logic error! Fix def_compress_level logic above and below too!
|
||||
tweaked_append = append_mode == 1;
|
||||
tweaked_append_verify = append_mode == 2;
|
||||
#ifdef ICONV_OPTION
|
||||
tweaked_iconv = iconv_opt != NULL;
|
||||
#endif
|
||||
|
||||
/* Start the batch file with a bitmap of data-stream-affecting
|
||||
* flags. */
|
||||
if (protocol_version < 29)
|
||||
flag_ptr[7] = NULL;
|
||||
for (i = 0, flags = 0; flag_ptr[i]; i++) {
|
||||
if (*flag_ptr[i])
|
||||
flags |= 1 << i;
|
||||
@@ -90,13 +110,31 @@ void write_stream_flags(int fd)
|
||||
|
||||
void read_stream_flags(int fd)
|
||||
{
|
||||
int i, flags;
|
||||
batch_stream_flags = read_int(fd);
|
||||
}
|
||||
|
||||
void check_batch_flags(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (protocol_version < 29)
|
||||
flag_ptr[7] = NULL;
|
||||
for (i = 0, flags = read_int(fd); flag_ptr[i]; i++) {
|
||||
int set = flags & (1 << i) ? 1 : 0;
|
||||
else if (protocol_version < 30)
|
||||
flag_ptr[9] = NULL;
|
||||
tweaked_append = append_mode == 1;
|
||||
tweaked_append_verify = append_mode == 2;
|
||||
#ifdef ICONV_OPTION
|
||||
tweaked_iconv = iconv_opt != NULL;
|
||||
#endif
|
||||
for (i = 0; flag_ptr[i]; i++) {
|
||||
int set = batch_stream_flags & (1 << i) ? 1 : 0;
|
||||
if (*flag_ptr[i] != set) {
|
||||
if (i == 9) {
|
||||
rprintf(FERROR,
|
||||
"%s specify the --iconv option to use this batch file.\n",
|
||||
set ? "Please" : "Do not");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (verbose) {
|
||||
rprintf(FINFO,
|
||||
"%sing the %s option to match the batchfile.\n",
|
||||
@@ -112,12 +150,10 @@ void read_stream_flags(int fd)
|
||||
xfer_dirs = 0;
|
||||
}
|
||||
|
||||
if (tweaked_compress_level == 0 || tweaked_compress_level == 2)
|
||||
do_compression = 0;
|
||||
else {
|
||||
do_compression = 1;
|
||||
def_compress_level = tweaked_compress_level - 2;
|
||||
}
|
||||
if (tweaked_append)
|
||||
append_mode = 1;
|
||||
else if (tweaked_append_verify)
|
||||
append_mode = 2;
|
||||
}
|
||||
|
||||
static void write_arg(int fd, char *arg)
|
||||
@@ -179,7 +215,7 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
|
||||
if (fd < 0) {
|
||||
rsyserr(FERROR, errno, "Batch file %s open error",
|
||||
filename);
|
||||
exit_cleanup(1);
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
|
||||
/* Write argvs info to BATCH.sh file */
|
||||
@@ -225,6 +261,6 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
|
||||
if (write(fd, "\n", 1) != 1 || close(fd) < 0) {
|
||||
rsyserr(FERROR, errno, "Batch file %s write error",
|
||||
filename);
|
||||
exit_cleanup(1);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
|
||||
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (list_only && strncmp(*argv, modname, modlen) == 0
|
||||
if (strncmp(*argv, modname, modlen) == 0
|
||||
&& argv[0][modlen] == '\0')
|
||||
sargs[sargc++] = modname; /* we send "modname/" */
|
||||
else
|
||||
@@ -703,6 +703,10 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
|
||||
if (write_batch < 0)
|
||||
dry_run = 1;
|
||||
|
||||
#ifdef ICONV_CONST
|
||||
setup_iconv();
|
||||
#endif
|
||||
|
||||
if (lp_fake_super(i))
|
||||
am_root = -1;
|
||||
else if (am_root < 0) /* Treat --fake-super from client as --super. */
|
||||
|
||||
2
compat.c
2
compat.c
@@ -171,6 +171,8 @@ void setup_protocol(int f_out,int f_in)
|
||||
PROTOCOL_VERSION, am_server? "Server" : "Client");
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
if (read_batch)
|
||||
check_batch_flags();
|
||||
|
||||
if (protocol_version < 30) {
|
||||
if (append_mode == 1)
|
||||
|
||||
@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ(2.59)
|
||||
|
||||
RSYNC_VERSION=3.0.0pre8
|
||||
RSYNC_VERSION=3.0.0pre9
|
||||
AC_SUBST(RSYNC_VERSION)
|
||||
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
|
||||
|
||||
|
||||
21
flist.c
21
flist.c
@@ -1037,9 +1037,15 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
|
||||
}
|
||||
if (save_errno == ENOENT) {
|
||||
#ifdef SUPPORT_LINKS
|
||||
/* Avoid "vanished" error if symlink points nowhere. */
|
||||
if (copy_links && x_lstat(thisname, &st, NULL) == 0
|
||||
&& S_ISLNK(st.st_mode)) {
|
||||
/* When our options tell us to follow a symlink that
|
||||
* points nowhere, tell the user about the symlink
|
||||
* instead of giving a "vanished" message. We only
|
||||
* dereference a symlink if one of the --copy*links
|
||||
* options was specified, so there's no need for the
|
||||
* extra lstat() if one of these options isn't on. */
|
||||
if ((copy_links || copy_unsafe_links || copy_dirlinks)
|
||||
&& x_lstat(thisname, &st, NULL) == 0
|
||||
&& S_ISLNK(st.st_mode)) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR_XFER, "symlink has no referent: %s\n",
|
||||
full_fname(thisname));
|
||||
@@ -1525,8 +1531,10 @@ static void send_implied_dirs(int f, struct file_list *flist, char *fname,
|
||||
relnamecache **rnpp;
|
||||
char *slash;
|
||||
int len, need_new_dir;
|
||||
struct filter_list_struct save_filter_list = filter_list;
|
||||
|
||||
flags = (flags | FLAG_IMPLIED_DIR) & ~(FLAG_TOP_DIR | FLAG_CONTENT_DIR);
|
||||
filter_list.head = filter_list.tail = NULL; /* Don't filter implied dirs. */
|
||||
|
||||
if (inc_recurse) {
|
||||
if (lastpath_struct && F_PATHNAME(lastpath_struct) == pathname
|
||||
@@ -1568,11 +1576,11 @@ static void send_implied_dirs(int f, struct file_list *flist, char *fname,
|
||||
xfer_dirs = save_xfer_dirs;
|
||||
|
||||
if (!inc_recurse)
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!lastpath_struct)
|
||||
return; /* dir must have vanished */
|
||||
goto done; /* dir must have vanished */
|
||||
|
||||
len = strlen(limit+1);
|
||||
memcpy(&relname_list, F_DIR_RELNAMES_P(lastpath_struct), sizeof relname_list);
|
||||
@@ -1586,6 +1594,9 @@ static void send_implied_dirs(int f, struct file_list *flist, char *fname,
|
||||
out_of_memory("send_implied_dirs");
|
||||
(*rnpp)->name_type = name_type;
|
||||
strlcpy((*rnpp)->fname, limit+1, len + 1);
|
||||
|
||||
done:
|
||||
filter_list = save_filter_list;
|
||||
}
|
||||
|
||||
static void send1extra(int f, struct file_struct *file, struct file_list *flist)
|
||||
|
||||
108
generator.c
108
generator.c
@@ -91,6 +91,7 @@ extern int one_file_system;
|
||||
extern struct stats stats;
|
||||
extern dev_t filesystem_dev;
|
||||
extern mode_t orig_umask;
|
||||
extern uid_t our_uid;
|
||||
extern char *backup_dir;
|
||||
extern char *backup_suffix;
|
||||
extern int backup_suffix_len;
|
||||
@@ -113,8 +114,16 @@ static int need_retouch_dir_perms;
|
||||
static const char *solo_file = NULL;
|
||||
|
||||
/* For calling delete_item() and delete_dir_contents(). */
|
||||
#define DEL_RECURSE (1<<1) /* recurse */
|
||||
#define DEL_OWNED_BY_US (1<<0) /* file/dir has our uid */
|
||||
#define DEL_RECURSE (1<<1) /* if dir, delete all contents */
|
||||
#define DEL_DIR_IS_EMPTY (1<<2) /* internal delete_FUNCTIONS use only */
|
||||
#define DEL_FOR_FILE (1<<3) /* making room for a replacement file */
|
||||
#define DEL_FOR_DIR (1<<4) /* making room for a replacement dir */
|
||||
#define DEL_FOR_SYMLINK (1<<5) /* making room for a replacement symlink */
|
||||
#define DEL_FOR_DEVICE (1<<6) /* making room for a replacement device */
|
||||
#define DEL_FOR_SPECIAL (1<<7) /* making room for a replacement special */
|
||||
|
||||
#define DEL_MAKE_ROOM (DEL_FOR_FILE|DEL_FOR_DIR|DEL_FOR_SYMLINK|DEL_FOR_DEVICE|DEL_FOR_SPECIAL)
|
||||
|
||||
enum nonregtype {
|
||||
TYPE_DIR, TYPE_SPECIAL, TYPE_DEVICE, TYPE_SYMLINK
|
||||
@@ -127,7 +136,6 @@ enum delret {
|
||||
/* Forward declaration for delete_item(). */
|
||||
static enum delret delete_dir_contents(char *fname, int flags);
|
||||
|
||||
|
||||
static int is_backup_file(char *fn)
|
||||
{
|
||||
int k = strlen(fn) - backup_suffix_len;
|
||||
@@ -140,7 +148,7 @@ static int is_backup_file(char *fn)
|
||||
* Note that fbuf must point to a MAXPATHLEN buffer if the mode indicates it's
|
||||
* a directory! (The buffer is used for recursion, but returned unchanged.)
|
||||
*/
|
||||
static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
|
||||
static enum delret delete_item(char *fbuf, int mode, int flags)
|
||||
{
|
||||
enum delret ret;
|
||||
char *what;
|
||||
@@ -151,6 +159,9 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
|
||||
fbuf, mode, flags);
|
||||
}
|
||||
|
||||
if (!am_root && !(mode & S_IWUSR) && flags & DEL_OWNED_BY_US)
|
||||
do_chmod(fbuf, mode |= S_IWUSR);
|
||||
|
||||
if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
|
||||
ignore_perishable = 1;
|
||||
/* If DEL_RECURSE is not set, this just reports emptiness. */
|
||||
@@ -161,7 +172,7 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
|
||||
/* OK: try to delete the directory. */
|
||||
}
|
||||
|
||||
if (!replace && max_delete >= 0 && ++deletion_count > max_delete)
|
||||
if (!(flags & DEL_MAKE_ROOM) && max_delete >= 0 && ++deletion_count > max_delete)
|
||||
return DR_AT_LIMIT;
|
||||
|
||||
if (S_ISDIR(mode)) {
|
||||
@@ -176,7 +187,7 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
if (!replace)
|
||||
if (!(flags & DEL_MAKE_ROOM))
|
||||
log_delete(fbuf, mode);
|
||||
ret = DR_SUCCESS;
|
||||
} else {
|
||||
@@ -195,9 +206,18 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
|
||||
}
|
||||
|
||||
check_ret:
|
||||
if (replace && ret != DR_SUCCESS) {
|
||||
if (ret != DR_SUCCESS && flags & DEL_MAKE_ROOM) {
|
||||
const char *desc;
|
||||
switch (flags & DEL_MAKE_ROOM) {
|
||||
case DEL_FOR_FILE: desc = "regular file"; break;
|
||||
case DEL_FOR_DIR: desc = "directory"; break;
|
||||
case DEL_FOR_SYMLINK: desc = "symlink"; break;
|
||||
case DEL_FOR_DEVICE: desc = "device file"; break;
|
||||
case DEL_FOR_SPECIAL: desc = "special file"; break;
|
||||
default: exit_cleanup(RERR_UNSUPPORTED); /* IMPOSSIBLE */
|
||||
}
|
||||
rprintf(FERROR_XFER, "could not make way for new %s: %s\n",
|
||||
replace, fbuf);
|
||||
desc, fbuf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -242,7 +262,7 @@ static enum delret delete_dir_contents(char *fname, int flags)
|
||||
remainder = MAXPATHLEN - (p - fname);
|
||||
|
||||
/* We do our own recursion, so make delete_item() non-recursive. */
|
||||
flags = (flags & ~DEL_RECURSE) | DEL_DIR_IS_EMPTY;
|
||||
flags = (flags & ~(DEL_RECURSE|DEL_MAKE_ROOM)) | DEL_DIR_IS_EMPTY;
|
||||
|
||||
for (j = dirlist->used; j--; ) {
|
||||
struct file_struct *fp = dirlist->files[j];
|
||||
@@ -258,11 +278,18 @@ static enum delret delete_dir_contents(char *fname, int flags)
|
||||
}
|
||||
|
||||
strlcpy(p, fp->basename, remainder);
|
||||
if (!uid_ndx || (uid_t)F_OWNER(fp) == our_uid)
|
||||
flags |= DEL_OWNED_BY_US;
|
||||
else
|
||||
flags &= ~DEL_OWNED_BY_US;
|
||||
/* Save stack by recursing to ourself directly. */
|
||||
if (S_ISDIR(fp->mode)
|
||||
&& delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
|
||||
ret = DR_NOT_EMPTY;
|
||||
if (delete_item(fname, fp->mode, NULL, flags) != DR_SUCCESS)
|
||||
if (S_ISDIR(fp->mode)) {
|
||||
if (!am_root && !(fp->mode & S_IWUSR) && flags & DEL_OWNED_BY_US)
|
||||
do_chmod(fname, fp->mode |= S_IWUSR);
|
||||
if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
|
||||
ret = DR_NOT_EMPTY;
|
||||
}
|
||||
if (delete_item(fname, fp->mode, flags) != DR_SUCCESS)
|
||||
ret = DR_NOT_EMPTY;
|
||||
}
|
||||
|
||||
@@ -312,14 +339,17 @@ static int flush_delete_delay(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int remember_delete(struct file_struct *file, const char *fname)
|
||||
static int remember_delete(struct file_struct *file, const char *fname, int flags)
|
||||
{
|
||||
const char *plus = (!am_root && !(file->mode & S_IWUSR) && flags & DEL_OWNED_BY_US)
|
||||
? "+" : "";
|
||||
int len;
|
||||
|
||||
while (1) {
|
||||
len = snprintf(deldelay_buf + deldelay_cnt,
|
||||
deldelay_size - deldelay_cnt,
|
||||
"%x %s%c", (int)file->mode, fname, '\0');
|
||||
"%s%x %s%c",
|
||||
plus, (int)file->mode, fname, '\0');
|
||||
if ((deldelay_cnt += len) <= deldelay_size)
|
||||
break;
|
||||
if (deldelay_fd < 0 && !start_delete_delay_temp())
|
||||
@@ -332,7 +362,7 @@ static int remember_delete(struct file_struct *file, const char *fname)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_delay_line(char *buf)
|
||||
static int read_delay_line(char *buf, int *own_flag_p)
|
||||
{
|
||||
static int read_pos = 0;
|
||||
int j, len, mode;
|
||||
@@ -373,6 +403,11 @@ static int read_delay_line(char *buf)
|
||||
}
|
||||
|
||||
bp = deldelay_buf + read_pos;
|
||||
if (*bp == '+') {
|
||||
bp++;
|
||||
*own_flag_p = DEL_OWNED_BY_US;
|
||||
} else
|
||||
*own_flag_p = 0;
|
||||
|
||||
if (sscanf(bp, "%x ", &mode) != 1) {
|
||||
invalid_data:
|
||||
@@ -397,15 +432,15 @@ static int read_delay_line(char *buf)
|
||||
|
||||
static void do_delayed_deletions(char *delbuf)
|
||||
{
|
||||
int mode;
|
||||
int mode, own_flag;
|
||||
|
||||
if (deldelay_fd >= 0) {
|
||||
if (deldelay_cnt && !flush_delete_delay())
|
||||
return;
|
||||
lseek(deldelay_fd, 0, 0);
|
||||
}
|
||||
while ((mode = read_delay_line(delbuf)) >= 0)
|
||||
delete_item(delbuf, mode, NULL, DEL_RECURSE);
|
||||
while ((mode = read_delay_line(delbuf, &own_flag)) >= 0)
|
||||
delete_item(delbuf, mode, own_flag | DEL_RECURSE);
|
||||
if (deldelay_fd >= 0)
|
||||
close(deldelay_fd);
|
||||
}
|
||||
@@ -467,12 +502,14 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
|
||||
continue;
|
||||
}
|
||||
if (flist_find(cur_flist, fp) < 0) {
|
||||
int flags = DEL_RECURSE
|
||||
| (!uid_ndx || (uid_t)F_OWNER(fp) == our_uid ? DEL_OWNED_BY_US : 0);
|
||||
f_name(fp, delbuf);
|
||||
if (delete_during == 2) {
|
||||
if (!remember_delete(fp, delbuf))
|
||||
if (!remember_delete(fp, delbuf, flags))
|
||||
break;
|
||||
} else
|
||||
delete_item(delbuf, fp->mode, NULL, DEL_RECURSE);
|
||||
delete_item(delbuf, fp->mode, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -945,10 +982,6 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
|
||||
return -1;
|
||||
if (itemizing)
|
||||
itemize(cmpbuf, file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL);
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs)
|
||||
xattr_clear_locals(file);
|
||||
#endif
|
||||
if (maybe_ATTRS_REPORT
|
||||
&& ((!itemizing && verbose && match_level == 2)
|
||||
|| (verbose > 1 && match_level == 3))) {
|
||||
@@ -1196,11 +1229,9 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
excluded_dir = file;
|
||||
}
|
||||
skipping:
|
||||
if (verbose) {
|
||||
rprintf(FINFO,
|
||||
"skipping server-excluded file \"%s\"\n",
|
||||
fname);
|
||||
}
|
||||
rprintf(FERROR_XFER,
|
||||
"skipping daemon-excluded file \"%s\"\n",
|
||||
fname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1283,6 +1314,9 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
return;
|
||||
}
|
||||
|
||||
if (statret == 0 && sx.st.st_uid == our_uid)
|
||||
del_opts |= DEL_OWNED_BY_US;
|
||||
|
||||
if (S_ISDIR(file->mode)) {
|
||||
if (!implied_dirs && file->flags & FLAG_IMPLIED_DIR)
|
||||
goto cleanup;
|
||||
@@ -1294,7 +1328,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
* full later (right before we handle its contents). */
|
||||
if (statret == 0
|
||||
&& (S_ISDIR(sx.st.st_mode)
|
||||
|| delete_item(fname, sx.st.st_mode, "directory", del_opts) != 0))
|
||||
|| delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_DIR) != 0))
|
||||
goto cleanup; /* Any errors get reported later. */
|
||||
if (do_mkdir(fname, file->mode & 0700) == 0)
|
||||
file->flags |= FLAG_DIR_CREATED;
|
||||
@@ -1306,7 +1340,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
* we need to delete it. If it doesn't exist, then
|
||||
* (perhaps recursively) create it. */
|
||||
if (statret == 0 && !S_ISDIR(sx.st.st_mode)) {
|
||||
if (delete_item(fname, sx.st.st_mode, "directory", del_opts) != 0)
|
||||
if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_DIR) != 0)
|
||||
goto skipping_dir_contents;
|
||||
statret = -1;
|
||||
}
|
||||
@@ -1435,7 +1469,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
}
|
||||
/* Not the right symlink (or not a symlink), so
|
||||
* delete it. */
|
||||
if (delete_item(fname, sx.st.st_mode, "symlink", del_opts) != 0)
|
||||
if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_SYMLINK) != 0)
|
||||
goto cleanup;
|
||||
} else if (basis_dir[0] != NULL) {
|
||||
int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
|
||||
@@ -1489,15 +1523,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
uint32 *devp = F_RDEV_P(file);
|
||||
dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
|
||||
if (statret == 0) {
|
||||
char *t;
|
||||
int del_for_flag;
|
||||
if (IS_DEVICE(file->mode)) {
|
||||
if (!IS_DEVICE(sx.st.st_mode))
|
||||
statret = -1;
|
||||
t = "device file";
|
||||
del_for_flag = DEL_FOR_DEVICE;
|
||||
} else {
|
||||
if (!IS_SPECIAL(sx.st.st_mode))
|
||||
statret = -1;
|
||||
t = "special file";
|
||||
del_for_flag = DEL_FOR_SPECIAL;
|
||||
}
|
||||
if (statret == 0
|
||||
&& BITS_EQUAL(sx.st.st_mode, file->mode, _S_IFMT)
|
||||
@@ -1514,7 +1548,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
goto return_with_success;
|
||||
goto cleanup;
|
||||
}
|
||||
if (delete_item(fname, sx.st.st_mode, t, del_opts) != 0)
|
||||
if (delete_item(fname, sx.st.st_mode, del_opts | del_for_flag) != 0)
|
||||
goto cleanup;
|
||||
} else if (basis_dir[0] != NULL) {
|
||||
int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
|
||||
@@ -1605,7 +1639,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
fnamecmp_type = FNAMECMP_FNAME;
|
||||
|
||||
if (statret == 0 && !S_ISREG(sx.st.st_mode)) {
|
||||
if (delete_item(fname, sx.st.st_mode, "regular file", del_opts) != 0)
|
||||
if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_FILE) != 0)
|
||||
goto cleanup;
|
||||
statret = -1;
|
||||
stat_errno = ENOENT;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
struct hashtable *hashtable_create(int size, int key64)
|
||||
{
|
||||
struct hashtable *tbl;
|
||||
int node_size = key64 ? sizeof (struct ht_int64_node )
|
||||
int node_size = key64 ? sizeof (struct ht_int64_node)
|
||||
: sizeof (struct ht_int32_node);
|
||||
|
||||
/* Pick a power of 2 that can hold the requested size. */
|
||||
@@ -41,6 +41,7 @@ struct hashtable *hashtable_create(int size, int key64)
|
||||
tbl->size = size;
|
||||
tbl->entries = 0;
|
||||
tbl->node_size = node_size;
|
||||
tbl->key64 = key64;
|
||||
|
||||
return tbl;
|
||||
}
|
||||
@@ -55,7 +56,7 @@ void hashtable_destroy(struct hashtable *tbl)
|
||||
* already existing. Returns NULL if not allocating and not found. */
|
||||
void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing)
|
||||
{
|
||||
int key64 = (tbl->node_size > sizeof (struct ht_int32_node));
|
||||
int key64 = tbl->key64;
|
||||
struct ht_int32_node *node;
|
||||
uint32 ndx;
|
||||
|
||||
|
||||
2
hlink.c
2
hlink.c
@@ -393,7 +393,7 @@ int hard_link_one(struct file_struct *file, const char *fname,
|
||||
enum logcode code;
|
||||
if (terse) {
|
||||
if (!verbose)
|
||||
return -1;
|
||||
return 0;
|
||||
code = FINFO;
|
||||
} else
|
||||
code = FERROR_XFER;
|
||||
|
||||
11
main.c
11
main.c
@@ -45,6 +45,7 @@ extern int got_xfer_error;
|
||||
extern int module_id;
|
||||
extern int copy_links;
|
||||
extern int copy_dirlinks;
|
||||
extern int copy_unsafe_links;
|
||||
extern int keep_dirlinks;
|
||||
extern int preserve_hard_links;
|
||||
extern int protocol_version;
|
||||
@@ -82,6 +83,7 @@ extern struct filter_list_struct server_filter_list;
|
||||
extern iconv_t ic_send;
|
||||
#endif
|
||||
|
||||
uid_t our_uid;
|
||||
int local_server = 0;
|
||||
int daemon_over_rsh = 0;
|
||||
mode_t orig_umask = 0;
|
||||
@@ -278,7 +280,7 @@ static void output_summary(void)
|
||||
rprintf(FINFO, "total size is %s speedup is %.2f%s\n",
|
||||
human_num(stats.total_size),
|
||||
(double)stats.total_size / (total_written+total_read),
|
||||
dry_run ? " (DRY RUN)" : "");
|
||||
write_batch < 0 ? " (BATCH ONLY)" : dry_run ? " (DRY RUN)" : "");
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
@@ -640,7 +642,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
|
||||
* dry-run mode and the destination dir does not yet exist, we'll try to
|
||||
* tweak any dest-relative paths to make them work for a dry-run (the
|
||||
* destination dir must be in curr_dir[] when this function is called).
|
||||
* We also report if any arg that is non-existent or not a directory. */
|
||||
* We also warn about any arg that is non-existent or not a directory. */
|
||||
static void check_alt_basis_dirs(void)
|
||||
{
|
||||
STRUCT_STAT st;
|
||||
@@ -758,7 +760,7 @@ static int do_recv(int f_in, int f_out, char *local_name)
|
||||
|
||||
/* The receiving side mustn't obey this, or an existing symlink that
|
||||
* points to an identical file won't be replaced by the referent. */
|
||||
copy_links = copy_dirlinks = 0;
|
||||
copy_links = copy_dirlinks = copy_unsafe_links = 0;
|
||||
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
if (preserve_hard_links && !inc_recurse)
|
||||
@@ -1427,7 +1429,8 @@ int main(int argc,char *argv[])
|
||||
#endif
|
||||
|
||||
starttime = time(NULL);
|
||||
am_root = (MY_UID() == 0);
|
||||
our_uid = MY_UID();
|
||||
am_root = our_uid == 0;
|
||||
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
|
||||
|
||||
@@ -1306,7 +1306,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
|
||||
batch_name = NULL;
|
||||
} else if (dry_run)
|
||||
write_batch = 0;
|
||||
}
|
||||
} else if (write_batch < 0 && dry_run)
|
||||
write_batch = 0;
|
||||
if (read_batch && files_from) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--read-batch cannot be used with --files-from\n");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Summary: A fast, versatile, remote (and local) file-copying tool
|
||||
Name: rsync
|
||||
Version: 3.0.0pre8
|
||||
Version: 3.0.0pre9
|
||||
Release: 1
|
||||
Group: Applications/Internet
|
||||
Source: http://rsync.samba.org/ftp/rsync/rsync-%{version}.tar.gz
|
||||
@@ -45,5 +45,5 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%{_mandir}/man5/rsyncd.conf.5*
|
||||
|
||||
%changelog
|
||||
* Sat Jan 12 2008 Wayne Davison <wayned@samba.org>
|
||||
Released 3.0.0pre8.
|
||||
* Sun Feb 10 2008 Wayne Davison <wayned@samba.org>
|
||||
Released 3.0.0pre9.
|
||||
|
||||
@@ -252,7 +252,7 @@ system "fakeroot tar czf $srctar_file rsync-$version; rm -rf rsync-$version";
|
||||
|
||||
mkdir("rsync-$version", 0755);
|
||||
mkdir("rsync-$version/patches", 0755);
|
||||
system "support/patch-update --gen=rsync-$version/patches";
|
||||
system "support/patch-update --skip-check --gen=rsync-$version/patches";
|
||||
system "fakeroot tar chzf $pattar_file rsync-$version/patches; rm -rf rsync-$version";
|
||||
|
||||
print "Updating the other files in $dest ...\n";
|
||||
|
||||
12
pipe.c
12
pipe.c
@@ -133,6 +133,12 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
|
||||
filesfrom_fd = -1;
|
||||
chmod_modes = NULL; /* Let the sending side handle this. */
|
||||
|
||||
/* Let the client side handle this. */
|
||||
if (logfile_name) {
|
||||
logfile_name = NULL;
|
||||
logfile_close();
|
||||
}
|
||||
|
||||
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
|
||||
close(to_child_pipe[1]) < 0 ||
|
||||
close(from_child_pipe[0]) < 0 ||
|
||||
@@ -150,12 +156,6 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
|
||||
child_main(argc, argv);
|
||||
}
|
||||
|
||||
/* Let the client side handle this. */
|
||||
if (logfile_name) {
|
||||
logfile_name = NULL;
|
||||
logfile_close();
|
||||
}
|
||||
|
||||
if (close(from_child_pipe[1]) < 0 ||
|
||||
close(to_child_pipe[0]) < 0) {
|
||||
rsyserr(FERROR, errno, "Failed to close");
|
||||
|
||||
19
receiver.c
19
receiver.c
@@ -352,10 +352,11 @@ static int get_next_gen_ndx(int fd, int next_gen_ndx, int desired_ndx)
|
||||
{
|
||||
while (next_gen_ndx < desired_ndx) {
|
||||
if (next_gen_ndx >= 0) {
|
||||
rprintf(FINFO,
|
||||
struct file_struct *file = cur_flist->files[next_gen_ndx];
|
||||
rprintf(FERROR_XFER,
|
||||
"(No batched update for%s \"%s\")\n",
|
||||
redoing ? " resend of" : "",
|
||||
f_name(cur_flist->files[next_gen_ndx], NULL));
|
||||
file->flags & FLAG_FILE_SENT ? " resend of" : "",
|
||||
f_name(file, NULL));
|
||||
}
|
||||
next_gen_ndx = read_int(fd);
|
||||
if (next_gen_ndx == -1) {
|
||||
@@ -720,8 +721,8 @@ int recv_files(int f_in, char *local_name)
|
||||
send_msg_int(MSG_SUCCESS, ndx);
|
||||
break;
|
||||
case 0: {
|
||||
enum logcode msgtype = redoing || read_batch ? FERROR : FWARNING;
|
||||
if (msgtype == FERROR || verbose) {
|
||||
enum logcode msgtype = redoing ? FERROR_XFER : FWARNING;
|
||||
if (msgtype == FERROR_XFER || verbose) {
|
||||
char *errstr, *redostr, *keptstr;
|
||||
if (!(keep_partial && partialptr) && !inplace)
|
||||
keptstr = "discarded";
|
||||
@@ -729,16 +730,18 @@ int recv_files(int f_in, char *local_name)
|
||||
keptstr = "put into partial-dir";
|
||||
else
|
||||
keptstr = "retained";
|
||||
if (msgtype == FERROR) {
|
||||
if (msgtype == FERROR_XFER) {
|
||||
errstr = "ERROR";
|
||||
redostr = "";
|
||||
} else {
|
||||
errstr = "WARNING";
|
||||
redostr = " (will try again)";
|
||||
redostr = read_batch ? " (may try again)"
|
||||
: " (will try again)";
|
||||
}
|
||||
rprintf(msgtype,
|
||||
"%s: %s failed verification -- update %s%s.\n",
|
||||
errstr, fname, keptstr, redostr);
|
||||
errstr, local_name ? f_name(file, NULL) : fname,
|
||||
keptstr, redostr);
|
||||
}
|
||||
if (!redoing) {
|
||||
send_msg_int(MSG_REDO, ndx);
|
||||
|
||||
36
rsync.c
36
rsync.c
@@ -422,24 +422,24 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
|
||||
fname, (unsigned)sxp->st.st_gid, F_GROUP(file));
|
||||
}
|
||||
}
|
||||
if (am_root < 0) {
|
||||
;
|
||||
} else if (do_lchown(fname,
|
||||
change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
|
||||
change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) {
|
||||
/* shouldn't have attempted to change uid or gid
|
||||
* unless have the privilege */
|
||||
rsyserr(FERROR_XFER, errno, "%s %s failed",
|
||||
change_uid ? "chown" : "chgrp",
|
||||
full_fname(fname));
|
||||
goto cleanup;
|
||||
} else
|
||||
/* a lchown had been done - we have to re-stat if the
|
||||
* destination had the setuid or setgid bits set due
|
||||
* to the side effect of the chown call */
|
||||
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
|
||||
link_stat(fname, &sxp->st,
|
||||
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
|
||||
if (am_root >= 0) {
|
||||
if (do_lchown(fname,
|
||||
change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
|
||||
change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) {
|
||||
/* We shouldn't have attempted to change uid
|
||||
* or gid unless have the privilege. */
|
||||
rsyserr(FERROR_XFER, errno, "%s %s failed",
|
||||
change_uid ? "chown" : "chgrp",
|
||||
full_fname(fname));
|
||||
goto cleanup;
|
||||
}
|
||||
/* A lchown had been done, so we need to re-stat if
|
||||
* the destination had the setuid or setgid bits set
|
||||
* (due to the side effect of the chown call). */
|
||||
if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
|
||||
link_stat(fname, &sxp->st,
|
||||
keep_dirlinks && S_ISDIR(sxp->st.st_mode));
|
||||
}
|
||||
}
|
||||
updated = 1;
|
||||
}
|
||||
|
||||
1
rsync.h
1
rsync.h
@@ -540,6 +540,7 @@ struct hashtable {
|
||||
void *nodes;
|
||||
int32 size, entries;
|
||||
uint32 node_size;
|
||||
int key64;
|
||||
};
|
||||
|
||||
struct ht_int32_node {
|
||||
|
||||
36
rsync.yo
36
rsync.yo
@@ -1,5 +1,5 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsync)(1)(12 Jan 2008)()()
|
||||
manpage(rsync)(1)(10 Feb 2008)()()
|
||||
manpagename(rsync)(a fast, versatile, remote (and local) file-copying tool)
|
||||
manpagesynopsis()
|
||||
|
||||
@@ -817,11 +817,24 @@ the transfer and link together the corresponding files on the receiving
|
||||
side. Without this option, hard-linked files in the transfer are treated
|
||||
as though they were separate files.
|
||||
|
||||
Note that rsync can only detect hard links if both parts of the link
|
||||
are in the list of files being sent.
|
||||
When you are updating a non-empty destination, this option only ensures
|
||||
that files that are hard-linked together on the source are hard-linked
|
||||
together on the destination. It does NOT currently endeavor to break
|
||||
already existing hard links on the destination that do not exist between
|
||||
the source files. Note, however, that if one or more extra-linked files
|
||||
have content changes, they will become unlinked when updated (assuming you
|
||||
are not using the bf(--inplace) option).
|
||||
|
||||
Note that rsync can only detect hard links between files that are inside
|
||||
the transfer set. If rsync updates a file that has extra hard-link
|
||||
connections to files outside the transfer, that linkage will be broken. If
|
||||
you are tempted to use the bf(--inplace) option to avoid this breakage, be
|
||||
very careful that you know how your files are being updated so that you are
|
||||
certain that no unintended changes happen due to lingering hard links (and
|
||||
see the bf(--inplace) option for more caveats).
|
||||
|
||||
If incremental recursion is active (see bf(--recursive)), rsync may transfer
|
||||
a missing hard-linked file before it finds that another link for the file
|
||||
a missing hard-linked file before it finds that another link for that contents
|
||||
exists elsewhere in the hierarchy. This does not affect the accuracy of
|
||||
the transfer, just its efficiency. One way to avoid this is to disable
|
||||
incremental recursion using the bf(--no-inc-recursive) option.
|
||||
@@ -1293,7 +1306,10 @@ exclude certain files from the list of files to be transferred. This is
|
||||
most useful in combination with a recursive transfer.
|
||||
|
||||
You may use as many bf(--filter) options on the command line as you like
|
||||
to build up the list of files to exclude.
|
||||
to build up the list of files to exclude. If the filter contains whitespace,
|
||||
be sure to quote it so that the shell gives the rule to rsync as a single
|
||||
argument. The text below also mentions that you can use an underscore to
|
||||
replace the space that separates a rule from its arg.
|
||||
|
||||
See the FILTER RULES section for detailed information on this option.
|
||||
|
||||
@@ -1944,6 +1960,8 @@ dit(bf(--password-file)) This option allows you to provide a password in a
|
||||
file for accessing an rsync daemon. The file must not be world readable.
|
||||
It should contain just the password as a single line.
|
||||
|
||||
This option does not supply a password to a remote shell transport such as
|
||||
ssh; to learn how to do that, consult the remote shell's documentation.
|
||||
When accessing an rsync daemon using a remote shell as the transport, this
|
||||
option only comes into effect after the remote shell finishes its
|
||||
authentication (i.e. if you have also specified a password in the daemon's
|
||||
@@ -2015,7 +2033,8 @@ dit(bf(--iconv=CONVERT_SPEC)) Rsync can convert filenames between character
|
||||
sets using this option. Using a CONVERT_SPEC of "." tells rsync to look up
|
||||
the default character-set via the locale setting. Alternately, you can
|
||||
fully specify what conversion to do by giving a local and a remote charset
|
||||
separated by a comma (local first), e.g. bf(--iconv=utf8,iso88591).
|
||||
separated by a comma (local first), e.g. bf(--iconv=utf8,iso88591). (Run
|
||||
"iconv --list" to see a list of the charset names that a machine supports.)
|
||||
Finally, you can specify a CONVERT_SPEC of "-" to turn off any conversion.
|
||||
The default setting of this option is site-specific, and can also be
|
||||
affected via the RSYNC_ICONV environment variable.
|
||||
@@ -2800,7 +2819,8 @@ rsync daemon. You should set RSYNC_PROXY to a hostname:port pair.
|
||||
dit(bf(RSYNC_PASSWORD)) Setting RSYNC_PASSWORD to the required
|
||||
password allows you to run authenticated rsync connections to an rsync
|
||||
daemon without user intervention. Note that this does not supply a
|
||||
password to a shell transport such as ssh.
|
||||
password to a remote shell transport such as ssh; to learn how to do that,
|
||||
consult the remote shell's documentation.
|
||||
dit(bf(USER) or bf(LOGNAME)) The USER or LOGNAME environment variables
|
||||
are used to determine the default username sent to an rsync daemon.
|
||||
If neither is set, the username defaults to "nobody".
|
||||
@@ -2834,7 +2854,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
|
||||
|
||||
manpagesection(VERSION)
|
||||
|
||||
This man page is current for version 3.0.0pre8 of rsync.
|
||||
This man page is current for version 3.0.0pre9 of rsync.
|
||||
|
||||
manpagesection(INTERNAL OPTIONS)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsyncd.conf)(5)(12 Jan 2008)()()
|
||||
manpage(rsyncd.conf)(5)(10 Feb 2008)()()
|
||||
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
|
||||
manpagesynopsis()
|
||||
|
||||
@@ -655,7 +655,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
|
||||
|
||||
manpagesection(VERSION)
|
||||
|
||||
This man page is current for version 3.0.0pre8 of rsync.
|
||||
This man page is current for version 3.0.0pre9 of rsync.
|
||||
|
||||
manpagesection(CREDITS)
|
||||
|
||||
|
||||
2
sender.c
2
sender.c
@@ -229,7 +229,7 @@ void send_files(int f_in, int f_out)
|
||||
rprintf(FINFO, "send_files(%d, %s%s%s)\n", ndx, path,slash,fname);
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR)
|
||||
if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && !dry_run)
|
||||
recv_xattr_request(file, f_in);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -6,19 +6,35 @@
|
||||
# diffs.
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
|
||||
my $patches_dir = 'patches';
|
||||
my $incl_generated_files;
|
||||
my $tmp_dir = "patches.$$";
|
||||
|
||||
if (@ARGV && $ARGV[0] =~ /^--gen(?:=(\S+))?$/) {
|
||||
$patches_dir = $1 if defined $1;
|
||||
&Getopt::Long::Configure('bundling');
|
||||
&usage if !&GetOptions(
|
||||
'skip-check' => \( my $skip_branch_check ),
|
||||
'gen:s' => \( my $incl_generated_files ),
|
||||
'help|h' => \( my $help_opt ),
|
||||
);
|
||||
&usage if $help_opt;
|
||||
|
||||
if (defined $incl_generated_files) {
|
||||
$patches_dir = $incl_generated_files if $incl_generated_files ne '';
|
||||
$incl_generated_files = 1;
|
||||
shift;
|
||||
}
|
||||
|
||||
die "No '$patches_dir' directory was found.\n" unless -d $patches_dir;
|
||||
die "No '.git' directory present in the current dir.\n" unless -d '.git';
|
||||
|
||||
unless ($skip_branch_check) {
|
||||
open(IN, '-|', 'git status') or die $!;
|
||||
my $status = join('', <IN>);
|
||||
close IN;
|
||||
die "The checkout is not clean:\n", $status unless $status =~ /\nnothing to commit \(working directory clean\)/;
|
||||
die "The checkout is not on the master branch.\n" unless $status =~ /^# On branch master\n/;
|
||||
}
|
||||
|
||||
my @extra_files;
|
||||
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
|
||||
while (<IN>) {
|
||||
@@ -32,25 +48,17 @@ while (<IN>) {
|
||||
}
|
||||
close IN;
|
||||
|
||||
system "git checkout master" and exit 1;
|
||||
if ($incl_generated_files) {
|
||||
die "'a' must not exist in the current directory.\n" if -e 'a';
|
||||
die "'b' must not exist in the current directory.\n" if -e 'b';
|
||||
system "./config.status Makefile && make gen && rsync -a @extra_files a/" and exit 1;
|
||||
die "'$tmp_dir' must not exist in the current directory.\n" if -e $tmp_dir;
|
||||
mkdir($tmp_dir, 0700) or die "Unable to mkdir($tmp_dir): $!\n";
|
||||
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/master/" and exit 1;
|
||||
}
|
||||
my $last_touch = time;
|
||||
|
||||
my(@patches, %local_patch);
|
||||
if (@ARGV) {
|
||||
foreach (@ARGV) {
|
||||
s{^(patches|patch|origin/patch)/} {};
|
||||
s{\.diff$} {};
|
||||
push(@patches, $_);
|
||||
}
|
||||
open(PIPE, '-|', 'git', 'branch', '-l') or die $!;
|
||||
} else {
|
||||
open(PIPE, '-|', 'git', 'branch', '-a') or die $!;
|
||||
}
|
||||
|
||||
# Start by finding all patches so that we can load all possible parents.
|
||||
open(PIPE, '-|', 'git', 'branch', '-a') or die $!;
|
||||
while (<PIPE>) {
|
||||
if (m# origin/patch/(.*)#) {
|
||||
push(@patches, $1);
|
||||
@@ -78,6 +86,16 @@ foreach my $patch (@patches) {
|
||||
$description{$patch} = $desc;
|
||||
}
|
||||
|
||||
if (@ARGV) {
|
||||
# Limit the list of patches to actually process based on @ARGV.
|
||||
@patches = ( );
|
||||
foreach (@ARGV) {
|
||||
s{^(patches|patch|origin/patch)/} {};
|
||||
s{\.diff$} {};
|
||||
push(@patches, $_);
|
||||
}
|
||||
}
|
||||
|
||||
my %completed;
|
||||
foreach my $patch (@patches) {
|
||||
next if $completed{$patch}++;
|
||||
@@ -85,11 +103,11 @@ foreach my $patch (@patches) {
|
||||
}
|
||||
|
||||
if ($incl_generated_files) {
|
||||
system "rm -rf a b";
|
||||
system "rm -rf $tmp_dir";
|
||||
}
|
||||
|
||||
sleep 1 if $last_touch == time;
|
||||
system "git checkout master";
|
||||
system "git checkout master" and exit 1;
|
||||
|
||||
exit;
|
||||
|
||||
@@ -120,14 +138,14 @@ sub update_patch
|
||||
open(OUT, '>', "$patches_dir/$patch.diff") or die $!;
|
||||
print OUT $description{$patch}, "\n";
|
||||
|
||||
if (system("git rebase -m $parent") != 0) {
|
||||
print qq|"git rebase -m $parent" incomplete -- please fix.\n|;
|
||||
if (system("git merge $parent") != 0) {
|
||||
print qq|"git merge $parent" incomplete -- please fix.\n|;
|
||||
$ENV{PS1} = "[$parent] patch/$patch: ";
|
||||
system $ENV{SHELL} and exit 1;
|
||||
}
|
||||
|
||||
if ($incl_generated_files) {
|
||||
system "./config.status Makefile && make gen && rsync -a @extra_files b/" and exit 1;
|
||||
system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/$patch/" and exit 1;
|
||||
}
|
||||
$last_touch = time;
|
||||
|
||||
@@ -145,9 +163,12 @@ sub update_patch
|
||||
close PIPE;
|
||||
|
||||
if ($incl_generated_files) {
|
||||
open(PIPE, '-|', 'diff', '-up', 'a', 'b') or die $!;
|
||||
$parent =~ s#.*/##;
|
||||
open(PIPE, '-|', 'diff', '-up', "$tmp_dir/$parent", "$tmp_dir/$patch") or die $!;
|
||||
while (<PIPE>) {
|
||||
s/^((?:---|\+\+\+) [^\t]+)\t.*/$1/;
|
||||
s#^(diff -up) $tmp_dir/[^/]+/(.*?) $tmp_dir/[^/]+/(.*)#$1 a/$2 b/$3#o;
|
||||
s#^\Q---\E $tmp_dir/[^/]+/([^\t]+)\t.*#--- a/$1#o;
|
||||
s#^\Q+++\E $tmp_dir/[^/]+/([^\t]+)\t.*#+++ b/$1#o;
|
||||
print OUT $_;
|
||||
}
|
||||
close PIPE;
|
||||
@@ -155,3 +176,15 @@ sub update_patch
|
||||
|
||||
close OUT;
|
||||
}
|
||||
|
||||
exit;
|
||||
|
||||
sub usage
|
||||
{
|
||||
die <<EOT;
|
||||
Usage: patch-update [OPTIONS]
|
||||
|
||||
--gen[=DIR] Include generated files. Optional dest DIR overrides "patches".
|
||||
--skip-check Skip the check that ensures starting with a clean master branch.
|
||||
EOT
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ extern int am_root;
|
||||
extern int read_only;
|
||||
extern int list_only;
|
||||
extern int preserve_perms;
|
||||
extern int preserve_executability;
|
||||
|
||||
#define RETURN_ERROR_IF(x,e) \
|
||||
do { \
|
||||
@@ -167,7 +168,7 @@ int do_chmod(const char *path, mode_t mode)
|
||||
#endif
|
||||
} else
|
||||
code = chmod(path, mode & CHMOD_BITS);
|
||||
if (code != 0 && preserve_perms)
|
||||
if (code != 0 && (preserve_perms || preserve_executability))
|
||||
return code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ int read_only = 0;
|
||||
int list_only = 0;
|
||||
int verbose = 0;
|
||||
int preserve_perms = 0;
|
||||
int preserve_executability = 0;
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
|
||||
@@ -43,7 +43,7 @@ runtest "BATCH.sh use of --read-batch" 'checkit "./BATCH.sh" "$chkdir" "$todir"'
|
||||
|
||||
rm -rf "$todir"
|
||||
mkdir "$todir" || test_fail "failed to restore empty destination directory"
|
||||
runtest "daemon recv --write-batch" 'checkit "$RSYNC -av --write-batch=BATCH \"$fromdir/\" rsync://localhost/test-to" "$chkdir" "$todir"'
|
||||
runtest "daemon recv --write-batch" 'checkit "\"$ignore23\" $RSYNC -av --write-batch=BATCH \"$fromdir/\" rsync://localhost/test-to" "$chkdir" "$todir"'
|
||||
|
||||
# The script would have aborted on error, so getting here means we pass.
|
||||
exit 0
|
||||
|
||||
@@ -25,7 +25,7 @@ hands_setup
|
||||
# Build chkdir with a normal rsync and an --exclude.
|
||||
$RSYNC -av --exclude=foobar.baz "$fromdir/" "$chkdir/"
|
||||
|
||||
checkit "$RSYNC -avvvvz '$fromdir/' localhost::test-to/" "$chkdir" "$todir"
|
||||
checkit "'$ignore23' $RSYNC -avvvvz '$fromdir/' localhost::test-to/" "$chkdir" "$todir"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
|
||||
@@ -256,6 +256,25 @@ gid = 0
|
||||
path = $scratchdir
|
||||
read only = no
|
||||
EOF
|
||||
|
||||
# Build a helper script to ignore exit code 23
|
||||
ignore23="$scratchdir/ignore23"
|
||||
echo "building help script $ignore23"
|
||||
|
||||
cat >"$ignore23" <<'EOT'
|
||||
if "${@}"; then
|
||||
exit
|
||||
fi
|
||||
|
||||
ret=$?
|
||||
|
||||
if test $ret = 23; then
|
||||
exit
|
||||
fi
|
||||
|
||||
exit $ret
|
||||
EOT
|
||||
chmod +x "$ignore23"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -34,18 +34,19 @@ case "`xattr 2>&1`" in
|
||||
;;
|
||||
esac
|
||||
|
||||
makepath "$fromdir/foo"
|
||||
makepath "$fromdir/foo/bar"
|
||||
echo now >"$fromdir/file0"
|
||||
echo something >"$fromdir/file1"
|
||||
echo else >"$fromdir/file2"
|
||||
echo deep >"$fromdir/foo/file3"
|
||||
echo normal >"$fromdir/file4"
|
||||
echo deeper >"$fromdir/foo/bar/file5"
|
||||
|
||||
makepath "$chkdir/foo"
|
||||
echo wow >"$chkdir/file1"
|
||||
cp -p "$fromdir/foo/file3" "$chkdir/foo"
|
||||
|
||||
files='foo file0 file1 file2 foo/file3 file4'
|
||||
files='foo file0 file1 file2 foo/file3 file4 foo/bar/file5'
|
||||
|
||||
cd "$fromdir"
|
||||
|
||||
@@ -61,10 +62,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.foo 'new foo' foo/file3
|
||||
xset user.bar 'new bar' foo/file3
|
||||
xset user.long 'this is also a long attribute that will be truncated in the initial data send' foo/file3
|
||||
xset user.equal 'this long attribute should remain the same and not need to be transferred' foo/file3
|
||||
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
|
||||
xset user.equal 'this long attribute should remain the same and not need to be transferred' foo/file3 foo/bar/file5
|
||||
|
||||
xset user.short 'old short' "$chkdir/file1"
|
||||
xset user.extra 'remove me' "$chkdir/file1"
|
||||
|
||||
1
tls.c
1
tls.c
@@ -46,6 +46,7 @@ int am_root = 0;
|
||||
int read_only = 1;
|
||||
int list_only = 0;
|
||||
int preserve_perms = 0;
|
||||
int preserve_executability = 0;
|
||||
|
||||
#ifdef SUPPORT_XATTRS
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ int am_root = 0;
|
||||
int read_only = 1;
|
||||
int list_only = 0;
|
||||
int preserve_perms = 0;
|
||||
int preserve_executability = 0;
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
|
||||
4
util.c
4
util.c
@@ -147,8 +147,8 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode)
|
||||
t[1].tv_usec = 0;
|
||||
# ifdef HAVE_LUTIMES
|
||||
if (S_ISLNK(mode)) {
|
||||
if (lutimes(fname, t) < 0 && errno != ENOSYS)
|
||||
return -1;
|
||||
if (lutimes(fname, t) < 0)
|
||||
return errno == ENOSYS ? 1 : -1;
|
||||
return 0;
|
||||
}
|
||||
# endif
|
||||
|
||||
74
xattrs.c
74
xattrs.c
@@ -47,7 +47,6 @@ extern int checksum_seed;
|
||||
#define XSTATE_ABBREV 0
|
||||
#define XSTATE_DONE 1
|
||||
#define XSTATE_TODO 2
|
||||
#define XSTATE_LOCAL 3
|
||||
|
||||
#define USER_PREFIX "user."
|
||||
#define UPRE_LEN ((int)sizeof USER_PREFIX - 1)
|
||||
@@ -112,6 +111,7 @@ static int rsync_xal_compare_names(const void *x1, const void *x2)
|
||||
static ssize_t get_xattr_names(const char *fname)
|
||||
{
|
||||
ssize_t list_len;
|
||||
double arg;
|
||||
|
||||
if (!namebuf) {
|
||||
namebuf_len = 1024;
|
||||
@@ -120,23 +120,26 @@ static ssize_t get_xattr_names(const char *fname)
|
||||
out_of_memory("get_xattr_names");
|
||||
}
|
||||
|
||||
/* The length returned includes all the '\0' terminators. */
|
||||
list_len = sys_llistxattr(fname, namebuf, namebuf_len);
|
||||
if (list_len > (ssize_t)namebuf_len) {
|
||||
list_len = -1;
|
||||
errno = ERANGE;
|
||||
}
|
||||
if (list_len >= 0)
|
||||
return list_len;
|
||||
if (errno == ENOTSUP)
|
||||
return 0;
|
||||
if (errno == ERANGE) {
|
||||
while (1) {
|
||||
/* The length returned includes all the '\0' terminators. */
|
||||
list_len = sys_llistxattr(fname, namebuf, namebuf_len);
|
||||
if (list_len >= 0) {
|
||||
if ((size_t)list_len <= namebuf_len)
|
||||
break;
|
||||
} else if (errno == ENOTSUP)
|
||||
return 0;
|
||||
else if (errno != ERANGE) {
|
||||
arg = (double)namebuf_len;
|
||||
got_error:
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"get_xattr_names: llistxattr(\"%s\",%.0f) failed",
|
||||
fname, arg);
|
||||
return -1;
|
||||
}
|
||||
list_len = sys_llistxattr(fname, NULL, 0);
|
||||
if (list_len < 0) {
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"get_xattr_names: llistxattr(\"%s\",0) failed",
|
||||
fname);
|
||||
return -1;
|
||||
arg = 0;
|
||||
goto got_error;
|
||||
}
|
||||
if (namebuf_len)
|
||||
free(namebuf);
|
||||
@@ -144,15 +147,9 @@ static ssize_t get_xattr_names(const char *fname)
|
||||
namebuf = new_array(char, namebuf_len);
|
||||
if (!namebuf)
|
||||
out_of_memory("get_xattr_names");
|
||||
list_len = sys_llistxattr(fname, namebuf, namebuf_len);
|
||||
if (list_len >= 0)
|
||||
return list_len;
|
||||
}
|
||||
|
||||
rsyserr(FERROR_XFER, errno,
|
||||
"get_xattr_names: llistxattr(\"%s\",%ld) failed",
|
||||
fname, (long)namebuf_len);
|
||||
return -1;
|
||||
return list_len;
|
||||
}
|
||||
|
||||
/* On entry, the *len_ptr parameter contains the size of the extra space we
|
||||
@@ -472,9 +469,11 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
|
||||
if (rxa->datum_len <= MAX_FULL_DATUM)
|
||||
continue;
|
||||
switch (rxa->datum[0]) {
|
||||
case XSTATE_LOCAL:
|
||||
/* Items set locally will get cached by receiver. */
|
||||
rxa->datum[0] = XSTATE_DONE;
|
||||
case XSTATE_ABBREV:
|
||||
/* Items left abbreviated matched the sender's checksum, so
|
||||
* the receiver will cache the local data for future use. */
|
||||
if (am_generator)
|
||||
rxa->datum[0] = XSTATE_DONE;
|
||||
continue;
|
||||
case XSTATE_TODO:
|
||||
break;
|
||||
@@ -508,27 +507,6 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
|
||||
write_byte(f_out, 0); /* end the list */
|
||||
}
|
||||
|
||||
/* Any items set locally by the generator that the receiver doesn't
|
||||
* get told about get changed back to XSTATE_ABBREV. */
|
||||
void xattr_clear_locals(struct file_struct *file)
|
||||
{
|
||||
item_list *lst = rsync_xal_l.items;
|
||||
rsync_xa *rxa;
|
||||
int cnt;
|
||||
|
||||
if (F_XATTR(file) < 0)
|
||||
return;
|
||||
|
||||
lst += F_XATTR(file);
|
||||
cnt = lst->count;
|
||||
for (rxa = lst->items; cnt--; rxa++) {
|
||||
if (rxa->datum_len <= MAX_FULL_DATUM)
|
||||
continue;
|
||||
if (rxa->datum[0] == XSTATE_LOCAL)
|
||||
rxa->datum[0] = XSTATE_ABBREV;
|
||||
}
|
||||
}
|
||||
|
||||
/* When called by the sender, read the request from the generator and mark
|
||||
* any needed xattrs with a flag that lets us know they need to be sent to
|
||||
* the receiver. When called by the receiver, reads the sent data and
|
||||
@@ -751,8 +729,6 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
|
||||
sxp->st.st_mtime = (time_t)-1;
|
||||
|
||||
if (am_generator) { /* generator items stay abbreviated */
|
||||
if (rxas[i].datum[0] == XSTATE_ABBREV)
|
||||
rxas[i].datum[0] = XSTATE_LOCAL;
|
||||
free(ptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user