Compare commits

..

34 Commits

Author SHA1 Message Date
rsync-bugs
42245f1b56 preparing for release of 2.0.19 1998-07-17 14:53:00 +00:00
Andrew Tridgell
c29ee43dbd handle hard links on systems with 16 bit ino_t 1998-07-17 14:42:59 +00:00
Andrew Tridgell
d310a212f7 added a bit in the man page about the clean shell error 1998-07-17 14:25:14 +00:00
Andrew Tridgell
ca6c93f817 check whether there is a / before a : in the rsync command line. If
there is then assume that the : is from a filename, not a host:dir
separator. This allows you to copy files with a : in them. (suggestion
from pfeifer@wait.de)
1998-07-17 14:05:57 +00:00
Andrew Tridgell
72914a606e make rsync behave more like GNU cp with regard to file permissions
when -p (preserve permissions) isn't set.

It works by taking the sending file permissions and masking them with
the umask to create the destination file permissions. (There is really
no "correct" way of doing this but at least we now behave like GNU cp
which fits the principle of least surprise.)

also fixed a race condition in copy_file()
1998-07-17 13:18:32 +00:00
Andrew Tridgell
4b957c2238 added the --safe-links option to disallow symlinks outside the
destination tree
1998-07-17 10:00:48 +00:00
Andrew Tridgell
d853783f21 added the --safe-links option to disallow symlinks outside the
destination tree
1998-07-17 10:00:43 +00:00
Andrew Tridgell
298c10d5bb some code reformatting 1998-07-17 07:42:04 +00:00
Andrew Tridgell
6608462cac removed old "make dist" target 1998-07-17 07:26:08 +00:00
Andrew Tridgell
ca8e96946e changed wording of an error message 1998-07-17 07:25:42 +00:00
Andrew Tridgell
6ed67e6dd5 moved getopt.h above unistd.h to prevent problems with uwin on NT 1998-07-17 07:17:11 +00:00
Andrew Tridgell
1f658d4207 fixed a problem with rsync buffering the debug output when redirected
to a file.
1998-07-17 07:07:23 +00:00
Andrew Tridgell
d3bc0b68ab make a function static 1998-07-17 05:38:51 +00:00
Andrew Tridgell
1a0de6c68b remove a useless debug message 1998-07-17 05:38:21 +00:00
Andrew Tridgell
eb601ffeb8 code style change 1998-07-17 05:37:56 +00:00
Andrew Tridgell
8d72ef6e52 use error to detect lockfile open failures vs. max connections reached
and report an appropriate error message
1998-07-17 05:37:18 +00:00
Andrew Tridgell
bcf5b1335d - use explicit flushes instead of setlinebuf. I've had reports of
verbose info not being line buffered to files.

- add a call to localtime() in open_log() in order to prime the C
  libraries timezone cache before the chroot(). This should fix the
  problem of rsyncd log entries being in GMT time.
1998-07-02 10:57:20 +00:00
Andrew Tridgell
bd7e05d799 remove a redundent continue statement 1998-07-02 03:02:14 +00:00
Andrew Tridgell
c95f1aa9d3 prioritise reading over writing in the select loop. (this is another
ssh-friendly attempt)
1998-07-02 02:59:04 +00:00
Andrew Tridgell
86ffe37f11 fix the problem of --timeout waiting for twice the specified time. 1998-07-02 02:48:09 +00:00
Andrew Tridgell
b536f47e3c - don't show "created directory" message unless verbose is selected
- check for null buf in show_progress
1998-07-02 02:08:55 +00:00
Andrew Tridgell
43b06eeae9 output progress % every 1k instead of every 1%, this is better for
large files.
1998-07-02 01:28:39 +00:00
Andrew Tridgell
067857e0ac the recv_generator can be static 1998-07-02 01:27:51 +00:00
Andrew Tridgell
b3e10ed75b enable output buffering in the recv generator. This makes a
significant difference when the transport is ssh as ssh will otherwise
output a complete frame for each checksum record, which increases the
checksum data in size by a factor of around 4.
1998-07-02 01:27:14 +00:00
Andrew Tridgell
a353d56337 don't need to send --progress option to server as the server never
prints progress info.
1998-07-02 00:48:20 +00:00
Andrew Tridgell
eb86d661d7 added --progress option which shows the progress of transfers. This
gives bored users something to watch.
1998-07-02 00:47:13 +00:00
Andrew Tridgell
fe055c718a - only keep a partial file if some literal data has been transferred,
this prevents a second interrupted transfer from reducing the size of
the transferred file.

- set SIGUSR1 to SIG_IGN early to prevent a race condition that
prevents the --partial code from working properly
1998-07-01 11:03:50 +00:00
Andrew Tridgell
31f440e68b I've had reports of rsyncd leaving zombies under digital unix. This
patch tries to address the problem in two ways:

1) reinstall the SIGCHLD handler before each fork
2) reap any children not caught by the handler using waitpid with
WNOHANG.

I expect this will fix the problem.
1998-07-01 05:10:42 +00:00
Andrew Tridgell
c95da96a0c added a --partial option which tells rsync to keep partially
transferred files if the transfer is interrupted.

added a "options summary" section to the man page
1998-07-01 03:36:03 +00:00
Andrew Tridgell
bf9f01689f if we get EWOULDBLOCK on a write then reduce the amount of data we are
trying to write. This guarantees that the maximum amount of data that
can be written at any one time is written.
1998-06-19 00:55:19 +00:00
Andrew Tridgell
da81e21536 use LDFLAGS in Makefile.in (fix from arndt@schoenewald.de) 1998-06-18 14:15:16 +00:00
Andrew Tridgell
46831d6fcf fixed chmod bug pointed out by Han Holl <jeholl@euronet.nl> 1998-06-18 13:26:10 +00:00
rsync-bugs
b58ad6c569 preparing for release of 2.0.18 1998-06-18 13:06:00 +00:00
Andrew Tridgell
22b1933287 fixed a race condition in rsync that opened a security hole. The
temporary files were being created with the same permissions as the
original file. So if the file was setuid but not owned by the user
doing the transfer then there was a window of opportunity for a
malicious user to execute it with the wrong permissions while it was
being transferred.

Thanks to snabb@epipe.fi for pointing this out.
1998-06-18 12:17:23 +00:00
19 changed files with 1292 additions and 957 deletions

View File

@@ -46,7 +46,7 @@ install: all
${INSTALLCMD} -m 644 $(srcdir)/rsyncd.conf.5 ${INSTALL_MAN}/man5
rsync: $(OBJS)
$(CC) $(CFLAGS) -o rsync $(OBJS) $(LIBS)
$(CC) $(CFLAGS) $(LDFLAGS) -o rsync $(OBJS) $(LIBS)
rsync.1: rsync.yo
yodl2man -o rsync.1 rsync.yo
@@ -60,10 +60,3 @@ proto:
clean:
rm -f *~ $(OBJS) rsync config.cache config.log config.status
dist:
tar --exclude-from .ignore -czf dist.tar.gz .
-mkdir rsync-$(VERSION)
(cd rsync-$(VERSION) ; tar xzf ../dist.tar.gz)
tar -czf rsync-$(VERSION).tar.gz rsync-$(VERSION)
rm -f dist.tar.gz
echo rsync-$(VERSION) >> .cvsignore

View File

@@ -7,3 +7,4 @@
#undef HAVE_UTIMBUF
#undef ino_t
#undef HAVE_CONNECT
#undef HAVE_SHORT_INO_T

View File

@@ -132,9 +132,16 @@ static int rsync_module(int fd, int i)
}
if (!claim_connection(lp_lock_file(), lp_max_connections())) {
rprintf(FERROR,"max connections (%d) reached\n",
lp_max_connections());
io_printf(fd,"@ERROR: max connections (%d) reached - try again later\n", lp_max_connections());
if (errno) {
rprintf(FERROR,"failed to open lock file %s : %s\n",
lp_lock_file(), strerror(errno));
io_printf(fd,"@ERROR: failed to open lock file %s : %s\n",
lp_lock_file(), strerror(errno));
} else {
rprintf(FERROR,"max connections (%d) reached\n",
lp_max_connections());
io_printf(fd,"@ERROR: max connections (%d) reached - try again later\n", lp_max_connections());
}
return -1;
}

View File

@@ -53,6 +53,7 @@ void setup_protocol(int f_out,int f_in)
if (remote_version < MIN_PROTOCOL_VERSION ||
remote_version > MAX_PROTOCOL_VERSION) {
rprintf(FERROR,"protocol version mismatch - is your shell clean?\n");
rprintf(FERROR,"(see the rsync man page for an explanation)\n");
exit_cleanup(1);
}

View File

@@ -41,7 +41,7 @@ AC_FUNC_MEMCMP
AC_FUNC_UTIME_NULL
AC_CHECK_FUNCS(mmap munmap waitpid getcwd strdup strerror chown chmod mknod)
AC_CHECK_FUNCS(fchmod fstat strchr readlink link utime utimes)
AC_CHECK_FUNCS(memmove getopt_long lchown setlinebuf vsnprintf setsid glob strpbrk)
AC_CHECK_FUNCS(memmove getopt_long lchown vsnprintf setsid glob strpbrk)
echo $ac_n "checking for working fnmatch... $ac_c"
AC_TRY_RUN([#include <fnmatch.h>
@@ -62,6 +62,14 @@ main() { struct stat64 st; off64_t s; if (sizeof(off_t) == sizeof(off64_t)) retu
echo yes;AC_DEFINE(HAVE_OFF64_T),
echo no)
echo $ac_n "checking for short ino_t ... $ac_c"
AC_TRY_RUN([#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
main() { if (sizeof(ino_t) < sizeof(unsigned int)) return 0; return 1; }],
echo yes;AC_DEFINE(HAVE_SHORT_INO_T),
echo no)
echo $ac_n "checking for unsigned char ... $ac_c"
AC_TRY_RUN([#include <stdio.h>
main() { char c; c=250; exit((c > 0)?0:1); }],

View File

@@ -29,7 +29,7 @@ int claim_connection(char *fname,int max_connections)
if (max_connections <= 0)
return 1;
fd = open(fname,O_RDWR|O_CREAT, 0600);
if (fd == -1) {
@@ -41,6 +41,9 @@ int claim_connection(char *fname,int max_connections)
if (lock_range(fd, i*4, 4)) return 1;
}
/* only interested in open failures */
errno = 0;
close(fd);
return 0;
}

301
flist.c
View File

@@ -94,95 +94,95 @@ static char *flist_dir;
void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
{
unsigned char flags;
static time_t last_time;
static mode_t last_mode;
static dev_t last_rdev;
static uid_t last_uid;
static gid_t last_gid;
static char lastname[MAXPATHLEN];
char *fname;
int l1,l2;
unsigned char flags;
static time_t last_time;
static mode_t last_mode;
static dev_t last_rdev;
static uid_t last_uid;
static gid_t last_gid;
static char lastname[MAXPATHLEN];
char *fname;
int l1,l2;
if (f == -1) return;
if (f == -1) return;
if (!file) {
write_byte(f,0);
return;
}
if (!file) {
write_byte(f,0);
return;
}
fname = f_name(file);
fname = f_name(file);
flags = base_flags;
flags = base_flags;
if (file->mode == last_mode) flags |= SAME_MODE;
if (file->rdev == last_rdev) flags |= SAME_RDEV;
if (file->uid == last_uid) flags |= SAME_UID;
if (file->gid == last_gid) flags |= SAME_GID;
if (file->modtime == last_time) flags |= SAME_TIME;
if (file->mode == last_mode) flags |= SAME_MODE;
if (file->rdev == last_rdev) flags |= SAME_RDEV;
if (file->uid == last_uid) flags |= SAME_UID;
if (file->gid == last_gid) flags |= SAME_GID;
if (file->modtime == last_time) flags |= SAME_TIME;
for (l1=0;lastname[l1] && (fname[l1] == lastname[l1]) && (l1 < 255);l1++) ;
l2 = strlen(fname) - l1;
for (l1=0;lastname[l1] && (fname[l1] == lastname[l1]) && (l1 < 255);l1++) ;
l2 = strlen(fname) - l1;
if (l1 > 0) flags |= SAME_NAME;
if (l2 > 255) flags |= LONG_NAME;
if (l1 > 0) flags |= SAME_NAME;
if (l2 > 255) flags |= LONG_NAME;
/* we must make sure we don't send a zero flags byte or the other
end will terminate the flist transfer */
if (flags == 0 && !S_ISDIR(file->mode)) flags |= FLAG_DELETE;
if (flags == 0) flags |= LONG_NAME;
/* we must make sure we don't send a zero flags byte or the other
end will terminate the flist transfer */
if (flags == 0 && !S_ISDIR(file->mode)) flags |= FLAG_DELETE;
if (flags == 0) flags |= LONG_NAME;
write_byte(f,flags);
if (flags & SAME_NAME)
write_byte(f,l1);
if (flags & LONG_NAME)
write_int(f,l2);
else
write_byte(f,l2);
write_buf(f,fname+l1,l2);
write_byte(f,flags);
if (flags & SAME_NAME)
write_byte(f,l1);
if (flags & LONG_NAME)
write_int(f,l2);
else
write_byte(f,l2);
write_buf(f,fname+l1,l2);
write_longint(f,file->length);
if (!(flags & SAME_TIME))
write_int(f,(int)file->modtime);
if (!(flags & SAME_MODE))
write_int(f,(int)file->mode);
if (preserve_uid && !(flags & SAME_UID)) {
add_uid(file->uid);
write_int(f,(int)file->uid);
}
if (preserve_gid && !(flags & SAME_GID)) {
add_gid(file->gid);
write_int(f,(int)file->gid);
}
if (preserve_devices && IS_DEVICE(file->mode) && !(flags & SAME_RDEV))
write_int(f,(int)file->rdev);
write_longint(f,file->length);
if (!(flags & SAME_TIME))
write_int(f,(int)file->modtime);
if (!(flags & SAME_MODE))
write_int(f,(int)file->mode);
if (preserve_uid && !(flags & SAME_UID)) {
add_uid(file->uid);
write_int(f,(int)file->uid);
}
if (preserve_gid && !(flags & SAME_GID)) {
add_gid(file->gid);
write_int(f,(int)file->gid);
}
if (preserve_devices && IS_DEVICE(file->mode) && !(flags & SAME_RDEV))
write_int(f,(int)file->rdev);
#if SUPPORT_LINKS
if (preserve_links && S_ISLNK(file->mode)) {
write_int(f,strlen(file->link));
write_buf(f,file->link,strlen(file->link));
}
if (preserve_links && S_ISLNK(file->mode)) {
write_int(f,strlen(file->link));
write_buf(f,file->link,strlen(file->link));
}
#endif
#if SUPPORT_HARD_LINKS
if (preserve_hard_links && S_ISREG(file->mode)) {
write_int(f,(int)file->dev);
write_int(f,(int)file->inode);
}
if (preserve_hard_links && S_ISREG(file->mode)) {
write_int(f,(int)file->dev);
write_int(f,(int)file->inode);
}
#endif
if (always_checksum) {
write_buf(f,file->sum,csum_length);
}
if (always_checksum) {
write_buf(f,file->sum,csum_length);
}
last_mode = file->mode;
last_rdev = file->rdev;
last_uid = file->uid;
last_gid = file->gid;
last_time = file->modtime;
last_mode = file->mode;
last_rdev = file->rdev;
last_uid = file->uid;
last_gid = file->gid;
last_time = file->modtime;
strlcpy(lastname,fname,MAXPATHLEN-1);
lastname[MAXPATHLEN-1] = 0;
strlcpy(lastname,fname,MAXPATHLEN-1);
lastname[MAXPATHLEN-1] = 0;
}
@@ -190,101 +190,108 @@ void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
static void receive_file_entry(struct file_struct **fptr,
unsigned flags,int f)
{
static time_t last_time;
static mode_t last_mode;
static dev_t last_rdev;
static uid_t last_uid;
static gid_t last_gid;
static char lastname[MAXPATHLEN];
char thisname[MAXPATHLEN];
int l1=0,l2=0;
char *p;
struct file_struct *file;
static time_t last_time;
static mode_t last_mode;
static dev_t last_rdev;
static uid_t last_uid;
static gid_t last_gid;
static char lastname[MAXPATHLEN];
char thisname[MAXPATHLEN];
int l1=0,l2=0;
char *p;
struct file_struct *file;
if (flags & SAME_NAME)
l1 = read_byte(f);
if (flags & SAME_NAME)
l1 = read_byte(f);
if (flags & LONG_NAME)
l2 = read_int(f);
else
l2 = read_byte(f);
if (flags & LONG_NAME)
l2 = read_int(f);
else
l2 = read_byte(f);
file = (struct file_struct *)malloc(sizeof(*file));
if (!file) out_of_memory("receive_file_entry");
memset((char *)file, 0, sizeof(*file));
(*fptr) = file;
file = (struct file_struct *)malloc(sizeof(*file));
if (!file) out_of_memory("receive_file_entry");
memset((char *)file, 0, sizeof(*file));
(*fptr) = file;
if (l2 >= MAXPATHLEN-l1) overflow("receive_file_entry");
if (l2 >= MAXPATHLEN-l1) overflow("receive_file_entry");
strlcpy(thisname,lastname,l1);
read_sbuf(f,&thisname[l1],l2);
thisname[l1+l2] = 0;
strlcpy(thisname,lastname,l1);
read_sbuf(f,&thisname[l1],l2);
thisname[l1+l2] = 0;
strlcpy(lastname,thisname,MAXPATHLEN-1);
lastname[MAXPATHLEN-1] = 0;
strlcpy(lastname,thisname,MAXPATHLEN-1);
lastname[MAXPATHLEN-1] = 0;
clean_fname(thisname);
clean_fname(thisname);
if (relative_paths && thisname[0] == '/') {
/* strip / off absolute paths in destination */
memmove(thisname, thisname+1, strlen(thisname));
if (!thisname[0]) strcpy(thisname,".");
}
if (relative_paths && thisname[0] == '/') {
/* strip / off absolute paths in destination */
memmove(thisname, thisname+1, strlen(thisname));
if (!thisname[0]) strcpy(thisname,".");
}
if ((p = strrchr(thisname,'/'))) {
static char *lastdir;
*p = 0;
if (lastdir && strcmp(thisname, lastdir)==0) {
file->dirname = lastdir;
} else {
file->dirname = strdup(thisname);
lastdir = file->dirname;
}
file->basename = strdup(p+1);
} else {
file->dirname = NULL;
file->basename = strdup(thisname);
}
if ((p = strrchr(thisname,'/'))) {
static char *lastdir;
*p = 0;
if (lastdir && strcmp(thisname, lastdir)==0) {
file->dirname = lastdir;
} else {
file->dirname = strdup(thisname);
lastdir = file->dirname;
}
file->basename = strdup(p+1);
} else {
file->dirname = NULL;
file->basename = strdup(thisname);
}
if (!file->basename) out_of_memory("receive_file_entry 1");
if (!file->basename) out_of_memory("receive_file_entry 1");
file->flags = flags;
file->length = read_longint(f);
file->modtime = (flags & SAME_TIME) ? last_time : (time_t)read_int(f);
file->mode = (flags & SAME_MODE) ? last_mode : (mode_t)read_int(f);
if (preserve_uid)
file->uid = (flags & SAME_UID) ? last_uid : (uid_t)read_int(f);
if (preserve_gid)
file->gid = (flags & SAME_GID) ? last_gid : (gid_t)read_int(f);
if (preserve_devices && IS_DEVICE(file->mode))
file->rdev = (flags & SAME_RDEV) ? last_rdev : (dev_t)read_int(f);
file->flags = flags;
file->length = read_longint(f);
file->modtime = (flags & SAME_TIME) ? last_time : (time_t)read_int(f);
file->mode = (flags & SAME_MODE) ? last_mode : (mode_t)read_int(f);
if (preserve_uid)
file->uid = (flags & SAME_UID) ? last_uid : (uid_t)read_int(f);
if (preserve_gid)
file->gid = (flags & SAME_GID) ? last_gid : (gid_t)read_int(f);
if (preserve_devices && IS_DEVICE(file->mode))
file->rdev = (flags & SAME_RDEV) ? last_rdev : (dev_t)read_int(f);
if (preserve_links && S_ISLNK(file->mode)) {
int l = read_int(f);
file->link = (char *)malloc(l+1);
if (!file->link) out_of_memory("receive_file_entry 2");
read_sbuf(f,file->link,l);
}
if (preserve_links && S_ISLNK(file->mode)) {
int l = read_int(f);
file->link = (char *)malloc(l+1);
if (!file->link) out_of_memory("receive_file_entry 2");
read_sbuf(f,file->link,l);
}
#if SUPPORT_HARD_LINKS
if (preserve_hard_links && S_ISREG(file->mode)) {
file->dev = read_int(f);
file->inode = read_int(f);
}
if (preserve_hard_links && S_ISREG(file->mode)) {
file->dev = read_int(f);
file->inode = read_int(f);
}
#endif
if (always_checksum) {
file->sum = (char *)malloc(MD4_SUM_LENGTH);
if (!file->sum) out_of_memory("md4 sum");
read_buf(f,file->sum,csum_length);
}
if (always_checksum) {
file->sum = (char *)malloc(MD4_SUM_LENGTH);
if (!file->sum) out_of_memory("md4 sum");
read_buf(f,file->sum,csum_length);
}
last_mode = file->mode;
last_rdev = file->rdev;
last_uid = file->uid;
last_gid = file->gid;
last_time = file->modtime;
last_mode = file->mode;
last_rdev = file->rdev;
last_uid = file->uid;
last_gid = file->gid;
last_time = file->modtime;
if (!preserve_perms) {
extern int orig_umask;
/* set an appropriate set of permissions based on original
permissions and umask. This emulates what GNU cp does */
file->mode &= ~orig_umask;
}
}

32
io.c
View File

@@ -54,8 +54,8 @@ static void check_timeout(void)
t = time(NULL);
if (last_io && io_timeout && (t-last_io)>io_timeout) {
rprintf(FERROR,"read timeout after %d second - exiting\n",
if (last_io && io_timeout && (t-last_io) >= io_timeout) {
rprintf(FERROR,"io timeout after %d second - exiting\n",
(int)(t-last_io));
exit_cleanup(1);
}
@@ -119,7 +119,7 @@ static int read_timeout(int fd, char *buf, int len)
if (n == 0) {
if (eof_error) {
rprintf(FERROR,"EOF in read_timeout\n");
rprintf(FERROR,"unexpected EOF in read_timeout\n");
}
exit_cleanup(1);
}
@@ -238,7 +238,7 @@ static void readfd(int fd,char *buffer,int N)
int ret;
int total=0;
if (read_buffer_len < N && N < 1024) {
if ((read_buffer_len < N) && (N < 1024)) {
read_check(buffer_f_in);
}
@@ -319,17 +319,19 @@ static void writefd_unbuffered(int fd,char *buf,int len)
int fd_count, count;
struct timeval tv;
int reading;
int blocked=0;
no_flush++;
reading = (buffer_f_in != -1 && read_buffer_len < MAX_READ_BUFFER);
while (total < len) {
FD_ZERO(&w_fds);
FD_ZERO(&r_fds);
FD_SET(fd,&w_fds);
fd_count = fd+1;
reading = (buffer_f_in != -1 &&
read_buffer_len < MAX_READ_BUFFER);
if (reading) {
FD_SET(buffer_f_in,&r_fds);
if (buffer_f_in > fd)
@@ -349,8 +351,13 @@ static void writefd_unbuffered(int fd,char *buf,int len)
continue;
}
if (reading && FD_ISSET(buffer_f_in, &r_fds)) {
read_check(buffer_f_in);
}
if (FD_ISSET(fd, &w_fds)) {
int ret = write(fd,buf+total,len-total);
int n = (len-total)>>blocked;
int ret = write(fd,buf+total,n?n:1);
if (ret == -1 && errno == EINTR) {
continue;
@@ -358,10 +365,7 @@ static void writefd_unbuffered(int fd,char *buf,int len)
if (ret == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK)) {
/* this shouldn't happen, if it does then
sleep for a short time to prevent us
chewing too much CPU */
u_sleep(100);
blocked++;
continue;
}
@@ -370,16 +374,12 @@ static void writefd_unbuffered(int fd,char *buf,int len)
exit_cleanup(1);
}
blocked = 0;
total += ret;
stats.total_written += ret;
if (io_timeout)
last_io = time(NULL);
continue;
}
if (reading && FD_ISSET(buffer_f_in, &r_fds)) {
read_check(buffer_f_in);
}
}

9
log.c
View File

@@ -28,6 +28,7 @@ void log_open(void)
{
static int initialised;
int options = LOG_PID;
time_t t;
if (initialised) return;
initialised = 1;
@@ -45,6 +46,12 @@ void log_open(void)
#ifndef LOG_NDELAY
syslog(LOG_INFO,"rsyncd started\n");
#endif
/* this looks pointless, but it is needed in order for the
C library on some systems to fetch the timezone info
before the chroot */
t = time(NULL);
localtime(&t);
}
@@ -102,6 +109,8 @@ void rprintf(int fd, const char *format, ...)
if (fwrite(buf, len, 1, f) != 1) exit_cleanup(1);
if (buf[len-1] == '\r' || buf[len-1] == '\n') fflush(f);
depth--;
}

57
main.c
View File

@@ -63,29 +63,29 @@ static void report(int f)
}
if (do_stats) {
printf("\nNumber of files: %d\n", stats.num_files);
printf("Number of files transferred: %d\n",
rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
rprintf(FINFO,"Number of files transferred: %d\n",
stats.num_transferred_files);
printf("Total file size: %.0f bytes\n",
rprintf(FINFO,"Total file size: %.0f bytes\n",
(double)stats.total_size);
printf("Total transferred file size: %.0f bytes\n",
rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
(double)stats.total_transferred_size);
printf("Literal data: %.0f bytes\n",
rprintf(FINFO,"Literal data: %.0f bytes\n",
(double)stats.literal_data);
printf("Matched data: %.0f bytes\n",
rprintf(FINFO,"Matched data: %.0f bytes\n",
(double)stats.matched_data);
printf("File list size: %d\n", stats.flist_size);
printf("Total bytes written: %.0f\n",
rprintf(FINFO,"File list size: %d\n", stats.flist_size);
rprintf(FINFO,"Total bytes written: %.0f\n",
(double)stats.total_written);
printf("Total bytes read: %.0f\n\n",
rprintf(FINFO,"Total bytes read: %.0f\n\n",
(double)stats.total_read);
}
printf("wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
rprintf(FINFO,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
(double)stats.total_written,
(double)stats.total_read,
(stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
printf("total size is %.0f speedup is %.2f\n",
rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
(double)stats.total_size,
(1.0*stats.total_size)/(stats.total_written+stats.total_read));
@@ -172,6 +172,10 @@ static char *get_local_name(struct file_list *flist,char *name)
STRUCT_STAT st;
extern int orig_umask;
if (verbose > 2)
rprintf(FINFO,"get_local_name count=%d %s\n",
flist->count, name);
if (do_stat(name,&st) == 0) {
if (S_ISDIR(st.st_mode)) {
if (!push_dir(name, 0)) {
@@ -198,7 +202,8 @@ static char *get_local_name(struct file_list *flist,char *name)
rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
exit_cleanup(1);
} else {
rprintf(FINFO,"created directory %s\n",name);
if (verbose > 0)
rprintf(FINFO,"created directory %s\n",name);
}
if (!push_dir(name, 0)) {
@@ -287,9 +292,6 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
recv_files(f_in,flist,local_name,recv_pipe[1]);
report(f_in);
if (verbose > 3)
rprintf(FINFO,"do_recv waiting on %d\n",pid);
io_flush();
_exit(0);
}
@@ -300,6 +302,8 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
set_nonblocking(f_out);
io_start_buffering(f_out);
generate_files(f_out,flist,local_name,recv_pipe[0]);
io_flush();
@@ -428,6 +432,20 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
return status | status2;
}
static char *find_colon(char *s)
{
char *p, *p2;
p = strchr(s,':');
if (!p) return NULL;
/* now check to see if there is a / in the string before the : - if there is then
discard the colon on the assumption that the : is part of a filename */
p2 = strchr(s,'/');
if (p2 && p2 < p) return NULL;
return p;
}
static int start_client(int argc, char *argv[])
{
@@ -441,7 +459,7 @@ static int start_client(int argc, char *argv[])
extern int am_sender;
extern char *shell_cmd;
p = strchr(argv[0],':');
p = find_colon(argv[0]);
if (p) {
if (p[1] == ':') {
@@ -463,7 +481,7 @@ static int start_client(int argc, char *argv[])
} else {
am_sender = 1;
p = strchr(argv[argc-1],':');
p = find_colon(argv[argc-1]);
if (!p) {
local_server = 1;
} else if (p[1] == ':') {
@@ -511,11 +529,6 @@ static int start_client(int argc, char *argv[])
pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
#if HAVE_SETLINEBUF
setlinebuf(stdout);
setlinebuf(stderr);
#endif
ret = client_run(f_in, f_out, pid, argc, argv);
fflush(stdout);

11
match.c
View File

@@ -118,6 +118,11 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
last_match = offset + s->sums[i].len;
else
last_match = offset;
if (buf)
show_progress(last_match, buf->size);
if (i == -1) end_progress();
}
@@ -252,6 +257,12 @@ void match_sums(int f,struct sum_struct *s,struct map_struct *buf,OFF_T len)
if (verbose > 2)
rprintf(FINFO,"done hash search\n");
} else {
OFF_T j;
/* by doing this in pieces we avoid too many seeks */
for (j=0;j<(len-CHUNK_SIZE);j+=CHUNK_SIZE) {
int n1 = MIN(CHUNK_SIZE,(len-CHUNK_SIZE)-j);
matched(f,s,buf,j+n1,-2);
}
matched(f,s,buf,len,-1);
}

499
options.c
View File

@@ -56,6 +56,9 @@ int recurse = 0;
int am_daemon=0;
int am_client=0;
int do_stats=0;
int do_progress=0;
int keep_partial=0;
int safe_symlinks=0;
int block_size=BLOCK_SIZE;
@@ -93,6 +96,7 @@ void usage(int F)
rprintf(F," -u, --update update only (don't overwrite newer files)\n");
rprintf(F," -l, --links preserve soft links\n");
rprintf(F," -L, --copy-links treat soft links like regular files\n");
rprintf(F," --safe-links ignore links outside the destination tree\n");
rprintf(F," -H, --hard-links preserve hard links\n");
rprintf(F," -p, --perms preserve permissions\n");
rprintf(F," -o, --owner preserve owner (root only)\n");
@@ -108,6 +112,7 @@ void usage(int F)
rprintf(F," --rsync-path=PATH specify path to rsync on the remote machine\n");
rprintf(F," -C, --cvs-exclude auto ignore files in the same way CVS does\n");
rprintf(F," --delete delete files that don't exist on the sending side\n");
rprintf(F," --partial keep partially transferred files\n");
rprintf(F," --force force deletion of directories even if not empty\n");
rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
rprintf(F," --timeout=TIME set IO timeout in seconds\n");
@@ -124,6 +129,7 @@ void usage(int F)
rprintf(F," --config=FILE specify alternate rsyncd.conf file\n");
rprintf(F," --port=PORT specify alternate rsyncd port number\n");
rprintf(F," --stats give some file transfer stats\n");
rprintf(F," --progress show progress during transfer\n");
rprintf(F," -h, --help show this help screen\n");
rprintf(F,"\n");
@@ -137,7 +143,8 @@ void usage(int F)
enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE,
OPT_EXCLUDE_FROM,OPT_DELETE,OPT_NUMERIC_IDS,OPT_RSYNC_PATH,
OPT_FORCE,OPT_TIMEOUT,OPT_DAEMON,OPT_CONFIG,OPT_PORT,
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS};
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS, OPT_PARTIAL, OPT_PROGRESS,
OPT_SAFE_LINKS};
static char *short_options = "oblLWHpguDCtcahvrRIxnSe:B:T:z";
@@ -170,6 +177,7 @@ static struct option long_options[] = {
{"perms", 0, 0, 'p'},
{"links", 0, 0, 'l'},
{"copy-links", 0, 0, 'L'},
{"safe-links", 0, 0, OPT_SAFE_LINKS},
{"whole-file", 0, 0, 'W'},
{"hard-links", 0, 0, 'H'},
{"owner", 0, 0, 'o'},
@@ -183,311 +191,330 @@ static struct option long_options[] = {
{"compress", 0, 0, 'z'},
{"daemon", 0, 0, OPT_DAEMON},
{"stats", 0, 0, OPT_STATS},
{"progress", 0, 0, OPT_PROGRESS},
{"partial", 0, 0, OPT_PARTIAL},
{"config", 1, 0, OPT_CONFIG},
{"port", 1, 0, OPT_PORT},
{0,0,0,0}};
void parse_arguments(int argc, char *argv[])
{
int opt;
int option_index;
int opt;
int option_index;
while ((opt = getopt_long(argc, argv,
short_options, long_options, &option_index))
!= -1) {
switch (opt)
{
case OPT_VERSION:
printf("rsync version %s protocol version %d\n\n",
VERSION,PROTOCOL_VERSION);
printf("Written by Andrew Tridgell and Paul Mackerras\n");
exit_cleanup(0);
while ((opt = getopt_long(argc, argv,
short_options, long_options, &option_index))
!= -1) {
switch (opt) {
case OPT_VERSION:
rprintf(FINFO,"rsync version %s protocol version %d\n\n",
VERSION,PROTOCOL_VERSION);
rprintf(FINFO,"Written by Andrew Tridgell and Paul Mackerras\n");
exit_cleanup(0);
case OPT_SUFFIX:
backup_suffix = optarg;
break;
case OPT_RSYNC_PATH:
rsync_path = optarg;
break;
case 'I':
ignore_times = 1;
break;
case OPT_SUFFIX:
backup_suffix = optarg;
break;
case 'x':
one_file_system=1;
break;
case OPT_RSYNC_PATH:
rsync_path = optarg;
break;
case OPT_DELETE:
delete_mode = 1;
break;
case 'I':
ignore_times = 1;
break;
case OPT_FORCE:
force_delete = 1;
break;
case 'x':
one_file_system=1;
break;
case OPT_NUMERIC_IDS:
numeric_ids = 1;
break;
case OPT_DELETE:
delete_mode = 1;
break;
case OPT_EXCLUDE:
add_exclude(optarg, 0);
break;
case OPT_FORCE:
force_delete = 1;
break;
case OPT_INCLUDE:
add_exclude(optarg, 1);
break;
case OPT_NUMERIC_IDS:
numeric_ids = 1;
break;
case OPT_EXCLUDE_FROM:
add_exclude_file(optarg,1, 0);
break;
case OPT_EXCLUDE:
add_exclude(optarg, 0);
break;
case OPT_INCLUDE_FROM:
add_exclude_file(optarg,1, 1);
break;
case OPT_INCLUDE:
add_exclude(optarg, 1);
break;
case OPT_SAFE_LINKS:
safe_symlinks=1;
break;
case OPT_EXCLUDE_FROM:
add_exclude_file(optarg,1, 0);
break;
case 'h':
usage(FINFO);
exit_cleanup(0);
case OPT_INCLUDE_FROM:
add_exclude_file(optarg,1, 1);
break;
case 'b':
make_backups=1;
break;
case 'h':
usage(FINFO);
exit_cleanup(0);
case 'n':
dry_run=1;
break;
case 'b':
make_backups=1;
break;
case 'S':
sparse_files=1;
break;
case 'n':
dry_run=1;
break;
case 'C':
cvs_exclude=1;
break;
case 'S':
sparse_files=1;
break;
case 'u':
update_only=1;
break;
case 'C':
cvs_exclude=1;
break;
case 'l':
preserve_links=1;
break;
case 'u':
update_only=1;
break;
case 'L':
copy_links=1;
break;
case 'l':
preserve_links=1;
break;
case 'W':
whole_file=1;
break;
case 'L':
copy_links=1;
break;
case 'W':
whole_file=1;
break;
case 'H':
case 'H':
#if SUPPORT_HARD_LINKS
preserve_hard_links=1;
preserve_hard_links=1;
#else
rprintf(FERROR,"ERROR: hard links not supported on this platform\n");
exit_cleanup(1);
rprintf(FERROR,"ERROR: hard links not supported on this platform\n");
exit_cleanup(1);
#endif
break;
break;
case 'p':
preserve_perms=1;
break;
case 'p':
preserve_perms=1;
break;
case 'o':
preserve_uid=1;
break;
case 'o':
preserve_uid=1;
break;
case 'g':
preserve_gid=1;
break;
case 'g':
preserve_gid=1;
break;
case 'D':
preserve_devices=1;
break;
case 'D':
preserve_devices=1;
break;
case 't':
preserve_times=1;
break;
case 't':
preserve_times=1;
break;
case 'c':
always_checksum=1;
break;
case 'c':
always_checksum=1;
break;
case 'v':
verbose++;
break;
case 'v':
verbose++;
break;
case 'a':
recurse=1;
case 'a':
recurse=1;
#if SUPPORT_LINKS
preserve_links=1;
preserve_links=1;
#endif
preserve_perms=1;
preserve_times=1;
preserve_gid=1;
if (am_root) {
preserve_devices=1;
preserve_uid=1;
}
break;
preserve_perms=1;
preserve_times=1;
preserve_gid=1;
if (am_root) {
preserve_devices=1;
preserve_uid=1;
}
break;
case OPT_SERVER:
am_server = 1;
break;
case OPT_SERVER:
am_server = 1;
break;
case OPT_SENDER:
if (!am_server) {
usage(FERROR);
exit_cleanup(1);
}
am_sender = 1;
break;
case OPT_SENDER:
if (!am_server) {
usage(FERROR);
exit_cleanup(1);
}
am_sender = 1;
break;
case 'r':
recurse = 1;
break;
case 'r':
recurse = 1;
break;
case 'R':
relative_paths = 1;
break;
case 'R':
relative_paths = 1;
break;
case 'e':
shell_cmd = optarg;
break;
case 'e':
shell_cmd = optarg;
break;
case 'B':
block_size = atoi(optarg);
break;
case 'B':
block_size = atoi(optarg);
break;
case OPT_TIMEOUT:
io_timeout = atoi(optarg);
break;
case OPT_TIMEOUT:
io_timeout = atoi(optarg);
break;
case 'T':
tmpdir = optarg;
break;
case 'T':
tmpdir = optarg;
break;
case 'z':
do_compression = 1;
break;
case 'z':
do_compression = 1;
break;
case OPT_DAEMON:
am_daemon = 1;
break;
case OPT_DAEMON:
am_daemon = 1;
break;
case OPT_STATS:
do_stats = 1;
break;
case OPT_STATS:
do_stats = 1;
break;
case OPT_CONFIG:
config_file = optarg;
break;
case OPT_PROGRESS:
do_progress = 1;
break;
case OPT_PORT:
rsync_port = atoi(optarg);
break;
case OPT_PARTIAL:
keep_partial = 1;
break;
default:
/* rprintf(FERROR,"bad option -%c\n",opt); */
exit_cleanup(1);
case OPT_CONFIG:
config_file = optarg;
break;
case OPT_PORT:
rsync_port = atoi(optarg);
break;
default:
/* rprintf(FERROR,"bad option -%c\n",opt); */
exit_cleanup(1);
}
}
}
}
void server_options(char **args,int *argc)
{
int ac = *argc;
static char argstr[50];
static char bsize[30];
static char iotime[30];
int i, x;
int ac = *argc;
static char argstr[50];
static char bsize[30];
static char iotime[30];
int i, x;
args[ac++] = "--server";
args[ac++] = "--server";
if (!am_sender)
args[ac++] = "--sender";
if (!am_sender)
args[ac++] = "--sender";
x = 1;
argstr[0] = '-';
for (i=0;i<verbose;i++)
argstr[x++] = 'v';
if (make_backups)
argstr[x++] = 'b';
if (update_only)
argstr[x++] = 'u';
if (dry_run)
argstr[x++] = 'n';
if (preserve_links)
argstr[x++] = 'l';
if (copy_links)
argstr[x++] = 'L';
if (whole_file)
argstr[x++] = 'W';
if (preserve_hard_links)
argstr[x++] = 'H';
if (preserve_uid)
argstr[x++] = 'o';
if (preserve_gid)
argstr[x++] = 'g';
if (preserve_devices)
argstr[x++] = 'D';
if (preserve_times)
argstr[x++] = 't';
if (preserve_perms)
argstr[x++] = 'p';
if (recurse)
argstr[x++] = 'r';
if (always_checksum)
argstr[x++] = 'c';
if (cvs_exclude)
argstr[x++] = 'C';
if (ignore_times)
argstr[x++] = 'I';
if (relative_paths)
argstr[x++] = 'R';
if (one_file_system)
argstr[x++] = 'x';
if (sparse_files)
argstr[x++] = 'S';
if (do_compression)
argstr[x++] = 'z';
argstr[x] = 0;
x = 1;
argstr[0] = '-';
for (i=0;i<verbose;i++)
argstr[x++] = 'v';
if (make_backups)
argstr[x++] = 'b';
if (update_only)
argstr[x++] = 'u';
if (dry_run)
argstr[x++] = 'n';
if (preserve_links)
argstr[x++] = 'l';
if (copy_links)
argstr[x++] = 'L';
if (whole_file)
argstr[x++] = 'W';
if (preserve_hard_links)
argstr[x++] = 'H';
if (preserve_uid)
argstr[x++] = 'o';
if (preserve_gid)
argstr[x++] = 'g';
if (preserve_devices)
argstr[x++] = 'D';
if (preserve_times)
argstr[x++] = 't';
if (preserve_perms)
argstr[x++] = 'p';
if (recurse)
argstr[x++] = 'r';
if (always_checksum)
argstr[x++] = 'c';
if (cvs_exclude)
argstr[x++] = 'C';
if (ignore_times)
argstr[x++] = 'I';
if (relative_paths)
argstr[x++] = 'R';
if (one_file_system)
argstr[x++] = 'x';
if (sparse_files)
argstr[x++] = 'S';
if (do_compression)
argstr[x++] = 'z';
argstr[x] = 0;
if (x != 1) args[ac++] = argstr;
if (x != 1) args[ac++] = argstr;
if (block_size != BLOCK_SIZE) {
sprintf(bsize,"-B%d",block_size);
args[ac++] = bsize;
}
if (block_size != BLOCK_SIZE) {
sprintf(bsize,"-B%d",block_size);
args[ac++] = bsize;
}
if (io_timeout) {
sprintf(iotime,"--timeout=%d",io_timeout);
args[ac++] = iotime;
}
if (io_timeout) {
sprintf(iotime,"--timeout=%d",io_timeout);
args[ac++] = iotime;
}
if (strcmp(backup_suffix, BACKUP_SUFFIX)) {
args[ac++] = "--suffix";
args[ac++] = backup_suffix;
}
if (strcmp(backup_suffix, BACKUP_SUFFIX)) {
args[ac++] = "--suffix";
args[ac++] = backup_suffix;
}
if (delete_mode)
args[ac++] = "--delete";
if (delete_mode)
args[ac++] = "--delete";
if (force_delete)
args[ac++] = "--force";
if (keep_partial)
args[ac++] = "--partial";
if (numeric_ids)
args[ac++] = "--numeric-ids";
if (force_delete)
args[ac++] = "--force";
if (tmpdir) {
args[ac++] = "--temp-dir";
args[ac++] = tmpdir;
}
if (safe_symlinks)
args[ac++] = "--safe-links";
*argc = ac;
if (numeric_ids)
args[ac++] = "--numeric-ids";
if (tmpdir) {
args[ac++] = "--temp-dir";
args[ac++] = tmpdir;
}
*argc = ac;
}

View File

@@ -1,10 +1,10 @@
Summary: Program for efficient remote updates of files.
Name: rsync
Version: 2.0.17
Version: 2.0.19
Release: 1
Copyright: GPL
Group: Applications/Networking
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.0.17.tar.gz
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.0.19.tar.gz
URL: http://samba.anu.edu.au/rsync/
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
BuildRoot: /tmp/rsync

1077
rsync.c
View File

File diff suppressed because it is too large Load Diff

34
rsync.h
View File

@@ -69,6 +69,13 @@
#endif
#include <sys/types.h>
#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#else
#include "lib/getopt.h"
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -162,12 +169,6 @@
#include "lib/fnmatch.h"
#endif
#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#else
#include "lib/getopt.h"
#endif
#ifdef HAVE_GLOB
#include <glob.h>
#endif
@@ -258,6 +259,12 @@
#define NO_INT64
#endif
#if HAVE_SHORT_INO_T
#define INO_T uint32
#else
#define INO_T ino_t
#endif
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
@@ -283,7 +290,7 @@ struct file_struct {
time_t modtime;
OFF_T length;
mode_t mode;
ino_t inode;
INO_T inode;
dev_t dev;
dev_t rdev;
uid_t uid;
@@ -302,11 +309,11 @@ struct file_list {
};
struct sum_buf {
OFF_T offset; /* offset in file of this chunk */
int len; /* length of chunk of file */
int i; /* index of this chunk */
uint32 sum1; /* simple checksum */
char sum2[SUM_LENGTH]; /* checksum */
OFF_T offset; /* offset in file of this chunk */
int len; /* length of chunk of file */
int i; /* index of this chunk */
uint32 sum1; /* simple checksum */
char sum2[SUM_LENGTH]; /* checksum */
};
struct sum_struct {
@@ -437,3 +444,6 @@ extern int errno;
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) || S_ISFIFO(mode))
#ifndef ACCESSPERMS
#define ACCESSPERMS 0777
#endif

101
rsync.yo
View File

@@ -187,6 +187,65 @@ quote(rsync -az -e ssh --delete ~ftp/pub/samba/ nimbus:"~ftp/pub/tridge/samba")
this is launched from cron every few hours.
manpagesection(OPTIONS SUMMARY)
Here is a short summary of the options avalable in rsync. Please refer
to the detailed description below for a complete description.
verb(
Usage: rsync [OPTION]... SRC [USER@]HOST:DEST
or rsync [OPTION]... [USER@]HOST:SRC DEST
or rsync [OPTION]... SRC DEST
or rsync [OPTION]... [USER@]HOST::SRC DEST
or rsync [OPTION]... SRC [USER@]HOST::DEST
Options
-v, --verbose increase verbosity
-c, --checksum always checksum
-a, --archive archive mode
-r, --recursive recurse into directories
-R, --relative use relative path names
-b, --backup make backups (default ~ extension)
-u, --update update only (don't overwrite newer files)
-l, --links preserve soft links
-L, --copy-links treat soft links like regular files
--safe-links ignore links outside the destination tree
-H, --hard-links preserve hard links
-p, --perms preserve permissions
-o, --owner preserve owner (root only)
-g, --group preserve group
-D, --devices preserve devices (root only)
-t, --times preserve times
-S, --sparse handle sparse files efficiently
-n, --dry-run show what would have been transferred
-W, --whole-file copy whole files, no incremental checks
-x, --one-file-system don't cross filesystem boundaries
-B, --block-size=SIZE checksum blocking size
-e, --rsh=COMMAND specify rsh replacement
--rsync-path=PATH specify path to rsync on the remote machine
-C, --cvs-exclude auto ignore files in the same way CVS does
--delete delete files that don't exist on the sending side
--partial keep partially transferred files
--force force deletion of directories even if not empty
--numeric-ids don't map uid/gid values by user/group name
--timeout=TIME set IO timeout in seconds
-I, --ignore-times don't exclude files that match length and time
-T --temp-dir=DIR create temporary files in directory DIR
-z, --compress compress file data
--exclude=PATTERN exclude file FILE
--exclude-from=PATTERN exclude files listed in FILE
--include=PATTERN don't exclude file FILE
--include-from=PATTERN don't exclude files listed in FILE
--suffix=SUFFIX override backup suffix
--version print version number
--daemon run as a rsync daemon
--config=FILE specify alternate rsyncd.conf file
--port=PORT specify alternate rsyncd port number
--stats give some file transfer stats
--progress show progress during transfer
-h, --help show this help screen
)
manpageoptions()
rsync uses the GNU long options package. Many of the command line
@@ -256,6 +315,11 @@ option all symbolic links are skipped.
dit(bf(-L, --copy-links)) This tells rsync to treat symbolic links just
like ordinary files.
dit(bf(--safe-links)) This tells rsync to ignore any symbolic links
which point outside the destination tree. All absolute symlinks are
also ignored. Using this option in conjunction with --relative may
give unexpecetd results.
dit(bf(-H, --hard-links)) This tells rsync to recreate hard links on
the remote system to be the same as the local system. Without this
option hard links are treated like regular files.
@@ -269,6 +333,12 @@ dit(bf(-W, --whole-file)) With this option the incremental rsync algorithm
is not used and the whole file is sent as-is instead. This may be
useful when using rsync with a local machine.
dit(bf(--partial)) By default rsync will delete any partially
transferred file if the transfer is interrupted. In some circumstances
it is more desirable to keep partially transferred files. Using the
--partial option tells rsync to keep the partial file which should
make a subsequent transfer of the rest of the file much faster.
dit(bf(-p, --perms)) This option causes rsync to update the remote
permissions to be the same as the local permissions.
@@ -292,6 +362,10 @@ instead it will just report the actions it would have taken.
dit(bf(-S, --sparse)) Try to handle sparse files efficiently so they take
up less space on the destination.
NOTE: Don't use this option when the destination is a Solaris "tmpfs"
filesystem. It doesn't seem to handle seeks over null regions
correctly and ends up corrupting the files.
dit(bf(-x, --one-file-system)) This tells rsync not to cross filesystem
boundaries when recursing. This is useful for transferring the
contents of only one filesystem.
@@ -454,6 +528,10 @@ on the file transfer, allowing you to tell how effective the rsync
algorithm is for your data. This option only works in conjunction with
the -v (verbose) option.
dit(bf(--progress)) This option tells rsync to print information
showing the progress of the transfer. This gives a bored user
something to watch.
enddit()
manpagesection(EXCLUDE PATTERNS)
@@ -516,6 +594,29 @@ itemize(
directories and C source files.
)
manpagesection(DIAGNOSTICS)
rsync occasinally produces error messages that may seem a little
cryptic. The one that seems to cause the most confusion is "protocol
version mismatch - is your shell clean?".
This message is usually caused by your startup scripts or remote shell
facility producing unwanted garbage on the stream that rsync is using
for its transport. The way ot diagnose this problem is to run your
remote shell like this:
verb(
rsh remotehost /bin/true > out.dat
)
then look at out.dat. If everything is working correctly then out.dat
should be a zero length file. You you are getting the above error from
rsync then you will probably find that out.dat contains some text or
data. Look at the contents and try to work out what is producing
it. The most common cause is incorrectly configued shell startup
scripts (such as .cshrc or .profile) that contain output statements
for non-interactive logins.
manpagesection(ENVIRONMENT VARIABLES)
startdit()

View File

@@ -120,8 +120,6 @@ void start_accept_loop(int port, int (*fn)(int ))
{
int s;
signal(SIGCHLD, SIG_IGN);
/* open an incoming socket */
s = open_socket_in(SOCK_STREAM, port);
if (s == -1)
@@ -155,6 +153,15 @@ void start_accept_loop(int port, int (*fn)(int ))
if (fd == -1) continue;
signal(SIGCHLD, SIG_IGN);
/* we shouldn't have any children left hanging around
but I have had reports that on Digital Unix zombies
are produced, so this ensures that they are reaped */
#ifdef WNOHANG
waitpid(-1, NULL, WNOHANG);
#endif
if (fork()==0) {
close(s);

72
util.c
View File

@@ -685,3 +685,75 @@ int u_strcmp(const char *cs1, const char *cs2)
return (int)*s1 - (int)*s2;
}
static OFF_T last_ofs;
void end_progress(void)
{
extern int do_progress, am_server;
if (do_progress && !am_server) {
rprintf(FINFO,"\n");
}
last_ofs = 0;
}
void show_progress(OFF_T ofs, OFF_T size)
{
extern int do_progress, am_server;
if (do_progress && !am_server) {
if (ofs > last_ofs + 1000) {
int pct = (int)((100.0*ofs)/size);
rprintf(FINFO,"%.0f (%d%%)\r", (double)ofs, pct);
last_ofs = ofs;
}
}
}
/* determine if a symlink points outside the current directory tree */
int unsafe_symlink(char *dest, char *src)
{
char *tok;
int depth = 0;
/* all absolute and null symlinks are unsafe */
if (!dest || !(*dest) || (*dest == '/')) return 1;
src = strdup(src);
if (!src) out_of_memory("unsafe_symlink");
/* find out what our safety margin is */
for (tok=strtok(src,"/"); tok; tok=strtok(NULL,"/")) {
if (strcmp(tok,"..") == 0) {
depth=0;
} else if (strcmp(tok,".") == 0) {
/* nothing */
} else {
depth++;
}
}
free(src);
/* drop by one to account for the filename portion */
depth--;
dest = strdup(dest);
if (!dest) out_of_memory("unsafe_symlink");
for (tok=strtok(dest,"/"); tok; tok=strtok(NULL,"/")) {
if (strcmp(tok,"..") == 0) {
depth--;
} else if (strcmp(tok,".") == 0) {
/* nothing */
} else {
depth++;
}
/* if at any point we go outside the current directory then
stop - it is unsafe */
if (depth < 0) break;
}
free(dest);
return (depth < 0);
}

View File

@@ -1 +1 @@
#define VERSION "2.0.17"
#define VERSION "2.0.19"