mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-27 08:22:52 -04:00
Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b41c3f9273 | ||
|
|
35bdd146e4 | ||
|
|
8d249b635c | ||
|
|
932be9aa52 | ||
|
|
c6b81a9865 | ||
|
|
e0414f4202 | ||
|
|
6e4fb64e61 | ||
|
|
37863201ad | ||
|
|
4f6325c362 | ||
|
|
f98df1d9b7 | ||
|
|
3d913675a1 | ||
|
|
2f9af90118 | ||
|
|
3eb388185b | ||
|
|
858fb9ebad | ||
|
|
2f03f956f4 | ||
|
|
0199b05f25 | ||
|
|
e2d1033d5d | ||
|
|
c46ded4621 | ||
|
|
8cd9fd4e8c | ||
|
|
41979ff87c | ||
|
|
b11ed3b150 | ||
|
|
42245f1b56 | ||
|
|
c29ee43dbd | ||
|
|
d310a212f7 | ||
|
|
ca6c93f817 | ||
|
|
72914a606e | ||
|
|
4b957c2238 | ||
|
|
d853783f21 | ||
|
|
298c10d5bb | ||
|
|
6608462cac | ||
|
|
ca8e96946e | ||
|
|
6ed67e6dd5 | ||
|
|
1f658d4207 | ||
|
|
d3bc0b68ab | ||
|
|
1a0de6c68b | ||
|
|
eb601ffeb8 | ||
|
|
8d72ef6e52 | ||
|
|
bcf5b1335d | ||
|
|
bd7e05d799 | ||
|
|
c95f1aa9d3 | ||
|
|
86ffe37f11 | ||
|
|
b536f47e3c | ||
|
|
43b06eeae9 | ||
|
|
067857e0ac | ||
|
|
b3e10ed75b | ||
|
|
a353d56337 | ||
|
|
eb86d661d7 | ||
|
|
fe055c718a | ||
|
|
31f440e68b | ||
|
|
c95da96a0c | ||
|
|
bf9f01689f | ||
|
|
da81e21536 | ||
|
|
46831d6fcf | ||
|
|
b58ad6c569 | ||
|
|
22b1933287 | ||
|
|
5a03f68a5a | ||
|
|
e81da93e86 | ||
|
|
f578043391 | ||
|
|
e8f5b936ad | ||
|
|
667e72a195 | ||
|
|
e1b3d5c4be | ||
|
|
f7b9377863 | ||
|
|
a5343e765b | ||
|
|
704f908eae | ||
|
|
de2fd20eb7 | ||
|
|
100e5241b0 | ||
|
|
ddecf7060b | ||
|
|
56cdbccb92 | ||
|
|
fc8a6b9705 | ||
|
|
143384f367 | ||
|
|
8c3b04730b | ||
|
|
aa9b77a56c | ||
|
|
b72f24c719 | ||
|
|
a800434a82 | ||
|
|
3b3c3d4390 | ||
|
|
d846b09874 | ||
|
|
1d3754aede | ||
|
|
e44f9a12c4 | ||
|
|
5243c216d6 | ||
|
|
79a51e7ee6 | ||
|
|
cad2bba7d8 | ||
|
|
fe8c0a9824 | ||
|
|
6cdc6b1344 | ||
|
|
05848a2cc7 | ||
|
|
528bfcd79a |
19
Makefile.in
19
Makefile.in
@@ -24,7 +24,7 @@ LIBOBJ=lib/getopt.o lib/fnmatch.o lib/compat.o
|
||||
ZLIBOBJ=zlib/deflate.o zlib/infblock.o zlib/infcodes.o zlib/inffast.o \
|
||||
zlib/inflate.o zlib/inftrees.o zlib/infutil.o zlib/trees.o \
|
||||
zlib/zutil.o zlib/adler32.o
|
||||
OBJS1=rsync.o exclude.o util.o md4.o main.o checksum.o match.o syscall.o log.o
|
||||
OBJS1=rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o md4.o main.o checksum.o match.o syscall.o log.o
|
||||
OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o fileio.o
|
||||
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
|
||||
OBJS=$(OBJS1) $(OBJS2) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ)
|
||||
@@ -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,11 @@ 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
|
||||
|
||||
# this target is really just for my use. It only works on a limited
|
||||
# range of machines and is used to produce a list of potentially
|
||||
# dead (ie. unused) functions in the code. (tridge)
|
||||
finddead:
|
||||
nm *.o */*.o |grep 'U ' | awk '{print $$2}' | sort -u > nmused.txt
|
||||
nm *.o */*.o |grep 'T ' | awk '{print $$3}' | sort -u > nmfns.txt
|
||||
comm -13 nmused.txt nmfns.txt
|
||||
|
||||
@@ -7,3 +7,4 @@
|
||||
#undef HAVE_UTIMBUF
|
||||
#undef ino_t
|
||||
#undef HAVE_CONNECT
|
||||
#undef HAVE_SHORT_INO_T
|
||||
|
||||
@@ -112,7 +112,7 @@ static int get_secret(int module, char *user, char *secret, int len)
|
||||
}
|
||||
|
||||
/* generate a 16 byte hash from a password and challenge */
|
||||
void generate_hash(char *in, char *challenge, char *out)
|
||||
static void generate_hash(char *in, char *challenge, char *out)
|
||||
{
|
||||
char buf[16];
|
||||
|
||||
|
||||
16
checksum.c
16
checksum.c
@@ -77,7 +77,7 @@ void get_checksum2(char *buf,int len,char *sum)
|
||||
|
||||
MDbegin(&MD);
|
||||
|
||||
bcopy(buf,buf1,len);
|
||||
memcpy(buf1,buf,len);
|
||||
if (checksum_seed) {
|
||||
SIVAL(buf1,len,checksum_seed);
|
||||
len += 4;
|
||||
@@ -102,7 +102,7 @@ void file_checksum(char *fname,char *sum,OFF_T size)
|
||||
OFF_T len = size;
|
||||
char tmpchunk[CSUM_CHUNK];
|
||||
|
||||
bzero(sum,csum_length);
|
||||
memset(sum,0,csum_length);
|
||||
|
||||
fd = open(fname,O_RDONLY);
|
||||
if (fd == -1) return;
|
||||
@@ -112,12 +112,12 @@ void file_checksum(char *fname,char *sum,OFF_T size)
|
||||
MDbegin(&MD);
|
||||
|
||||
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
|
||||
bcopy(map_ptr(buf,i,CSUM_CHUNK),tmpchunk,CSUM_CHUNK);
|
||||
memcpy(tmpchunk, map_ptr(buf,i,CSUM_CHUNK), CSUM_CHUNK);
|
||||
MDupdate(&MD, tmpchunk, CSUM_CHUNK*8);
|
||||
}
|
||||
|
||||
if (len - i > 0) {
|
||||
bcopy(map_ptr(buf,i,len-i),tmpchunk,len-i);
|
||||
memcpy(tmpchunk, map_ptr(buf,i,len-i), len-i);
|
||||
MDupdate(&MD, tmpchunk, (len-i)*8);
|
||||
}
|
||||
|
||||
@@ -155,27 +155,27 @@ void sum_update(char *p,int len)
|
||||
{
|
||||
int i;
|
||||
if (len + sumresidue < CSUM_CHUNK) {
|
||||
bcopy(p,sumrbuf+sumresidue,len);
|
||||
memcpy(sumrbuf+sumresidue, p, len);
|
||||
sumresidue += len;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sumresidue) {
|
||||
i = MIN(CSUM_CHUNK-sumresidue,len);
|
||||
bcopy(p,sumrbuf+sumresidue,i);
|
||||
memcpy(sumrbuf+sumresidue,p,i);
|
||||
MDupdate(&sumMD, sumrbuf, (i+sumresidue)*8);
|
||||
len -= i;
|
||||
p += i;
|
||||
}
|
||||
|
||||
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
|
||||
bcopy(p+i,sumrbuf,CSUM_CHUNK);
|
||||
memcpy(sumrbuf,p+i,CSUM_CHUNK);
|
||||
MDupdate(&sumMD, sumrbuf, CSUM_CHUNK*8);
|
||||
}
|
||||
|
||||
if (len - i > 0) {
|
||||
sumresidue = len-i;
|
||||
bcopy(p+i,sumrbuf,sumresidue);
|
||||
memcpy(sumrbuf,p+i,sumresidue);
|
||||
} else {
|
||||
sumresidue = 0;
|
||||
}
|
||||
|
||||
72
cleanup.c
Normal file
72
cleanup.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
/* handling the cleanup when a transfer is interrupted is tricky when
|
||||
--partial is selected. We need to ensure that the partial file is
|
||||
kept if any real data has been transferred */
|
||||
int cleanup_got_literal=0;
|
||||
|
||||
static char *cleanup_fname;
|
||||
static char *cleanup_new_fname;
|
||||
static struct file_struct *cleanup_file;
|
||||
static int cleanup_fd1, cleanup_fd2;
|
||||
static struct map_struct *cleanup_buf;
|
||||
|
||||
void exit_cleanup(int code)
|
||||
{
|
||||
extern int keep_partial;
|
||||
|
||||
signal(SIGUSR1, SIG_IGN);
|
||||
|
||||
if (cleanup_got_literal && cleanup_fname && keep_partial) {
|
||||
char *fname = cleanup_fname;
|
||||
cleanup_fname = NULL;
|
||||
if (cleanup_buf) unmap_file(cleanup_buf);
|
||||
if (cleanup_fd1 != -1) close(cleanup_fd1);
|
||||
if (cleanup_fd2 != -1) close(cleanup_fd2);
|
||||
finish_transfer(cleanup_new_fname, fname, cleanup_file);
|
||||
}
|
||||
io_flush();
|
||||
if (cleanup_fname)
|
||||
do_unlink(cleanup_fname);
|
||||
if (code) {
|
||||
kill_all(SIGUSR1);
|
||||
}
|
||||
exit(code);
|
||||
}
|
||||
|
||||
void cleanup_disable(void)
|
||||
{
|
||||
cleanup_fname = NULL;
|
||||
cleanup_got_literal = 0;
|
||||
}
|
||||
|
||||
|
||||
void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
|
||||
struct map_struct *buf, int fd1, int fd2)
|
||||
{
|
||||
cleanup_fname = fnametmp;
|
||||
cleanup_new_fname = fname;
|
||||
cleanup_file = file;
|
||||
cleanup_buf = buf;
|
||||
cleanup_fd1 = fd1;
|
||||
cleanup_fd2 = fd2;
|
||||
}
|
||||
@@ -36,6 +36,11 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
|
||||
extern int am_client;
|
||||
extern int am_sender;
|
||||
|
||||
if (*path == '/') {
|
||||
rprintf(FERROR,"ERROR: The remote path must start with a module name\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = strchr(host, '@');
|
||||
if (p) {
|
||||
user = host;
|
||||
@@ -118,6 +123,7 @@ static int rsync_module(int fd, int i)
|
||||
char *name = lp_name(i);
|
||||
char *user;
|
||||
int start_glob=0;
|
||||
int ret;
|
||||
char *request=NULL;
|
||||
extern int am_sender;
|
||||
extern int remote_version;
|
||||
@@ -132,9 +138,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;
|
||||
}
|
||||
|
||||
@@ -244,7 +257,7 @@ static int rsync_module(int fd, int i)
|
||||
}
|
||||
}
|
||||
|
||||
parse_arguments(argc, argv);
|
||||
ret = parse_arguments(argc, argv);
|
||||
|
||||
if (request) {
|
||||
if (*user) {
|
||||
@@ -259,8 +272,10 @@ static int rsync_module(int fd, int i)
|
||||
free(request);
|
||||
}
|
||||
|
||||
#if !TRIDGE
|
||||
/* don't allow the logs to be flooded too fast */
|
||||
if (verbose > 1) verbose = 1;
|
||||
#endif
|
||||
|
||||
argc -= optind;
|
||||
argp = argv + optind;
|
||||
@@ -269,6 +284,11 @@ static int rsync_module(int fd, int i)
|
||||
if (remote_version > 17 && am_sender)
|
||||
io_start_multiplex_out(fd);
|
||||
|
||||
if (!ret) {
|
||||
rprintf(FERROR,"Error parsing options (unsupported option?) - aborting\n");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
start_server(fd, fd, argc, argp);
|
||||
|
||||
return 0;
|
||||
@@ -362,8 +382,24 @@ int daemon_main(void)
|
||||
{
|
||||
extern char *config_file;
|
||||
|
||||
/* this ensures that we don't call getcwd after the chroot,
|
||||
which doesn't work on platforms that use popen("pwd","r")
|
||||
for getcwd */
|
||||
push_dir("/", 0);
|
||||
|
||||
if (is_a_socket(STDIN_FILENO)) {
|
||||
/* we are running via inetd */
|
||||
int i;
|
||||
|
||||
/* we are running via inetd - close off stdout and
|
||||
stderr so that library functions (and getopt) don't
|
||||
try to use them. Redirect them to /dev/null */
|
||||
for (i=1;i<3;i++) {
|
||||
close(i);
|
||||
open("/dev/null", O_RDWR);
|
||||
}
|
||||
|
||||
set_nonblocking(STDIN_FILENO);
|
||||
|
||||
return start_daemon(STDIN_FILENO);
|
||||
}
|
||||
|
||||
|
||||
1
compat.c
1
compat.c
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
13
configure.in
13
configure.in
@@ -16,6 +16,7 @@ AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h unistd.h utime.h grp.h)
|
||||
AC_CHECK_HEADERS(compat.h sys/param.h ctype.h sys/wait.h sys/ioctl.h)
|
||||
AC_CHECK_HEADERS(sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h)
|
||||
AC_CHECK_HEADERS(glob.h)
|
||||
|
||||
AC_CHECK_SIZEOF(int)
|
||||
AC_CHECK_SIZEOF(long)
|
||||
@@ -40,8 +41,8 @@ echo no)
|
||||
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 bcopy bzero readlink link utime utimes)
|
||||
AC_CHECK_FUNCS(memmove getopt_long lchown setlinebuf vsnprintf setsid glob strpbrk)
|
||||
AC_CHECK_FUNCS(fchmod fstat strchr readlink link utime utimes strftime)
|
||||
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 +63,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); }],
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -146,11 +146,7 @@ void add_exclude_list(char *pattern,struct exclude_struct ***list, int include)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!*list) {
|
||||
*list = (struct exclude_struct **)malloc(sizeof(struct exclude_struct *)*2);
|
||||
} else {
|
||||
*list = (struct exclude_struct **)realloc(*list,sizeof(struct exclude_struct *)*(len+2));
|
||||
}
|
||||
*list = (struct exclude_struct **)Realloc(*list,sizeof(struct exclude_struct *)*(len+2));
|
||||
|
||||
if (!*list || !((*list)[len] = make_exclude(pattern, include)))
|
||||
out_of_memory("add_exclude");
|
||||
|
||||
434
flist.c
434
flist.c
@@ -21,12 +21,13 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern struct stats stats;
|
||||
|
||||
extern int csum_length;
|
||||
|
||||
extern int verbose;
|
||||
extern int am_server;
|
||||
extern int always_checksum;
|
||||
extern int64 total_size;
|
||||
|
||||
extern int cvs_exclude;
|
||||
|
||||
@@ -48,6 +49,8 @@ extern int io_error;
|
||||
|
||||
static struct exclude_struct **local_exclude_list;
|
||||
|
||||
static void clean_flist(struct file_list *flist, int strip_root);
|
||||
|
||||
int link_stat(const char *Path, STRUCT_STAT *Buffer)
|
||||
{
|
||||
#if SUPPORT_LINKS
|
||||
@@ -90,136 +93,98 @@ static void send_directory(int f,struct file_list *flist,char *dir);
|
||||
|
||||
static char *flist_dir;
|
||||
|
||||
static void clean_fname(char *name)
|
||||
|
||||
static void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
|
||||
{
|
||||
char *p;
|
||||
int l;
|
||||
int modified = 1;
|
||||
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 (!name) return;
|
||||
if (f == -1) return;
|
||||
|
||||
while (modified) {
|
||||
modified = 0;
|
||||
if (!file) {
|
||||
write_byte(f,0);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((p=strstr(name,"/./"))) {
|
||||
modified = 1;
|
||||
while (*p) {
|
||||
p[0] = p[2];
|
||||
p++;
|
||||
}
|
||||
}
|
||||
fname = f_name(file);
|
||||
|
||||
if ((p=strstr(name,"//"))) {
|
||||
modified = 1;
|
||||
while (*p) {
|
||||
p[0] = p[1];
|
||||
p++;
|
||||
}
|
||||
}
|
||||
flags = base_flags;
|
||||
|
||||
if (strncmp(p=name,"./",2) == 0) {
|
||||
modified = 1;
|
||||
do {
|
||||
p[0] = p[2];
|
||||
} while (*p++);
|
||||
}
|
||||
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;
|
||||
|
||||
l = strlen(p=name);
|
||||
if (l > 1 && p[l-1] == '/') {
|
||||
modified = 1;
|
||||
p[l-1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
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);
|
||||
|
||||
if (f == -1) return;
|
||||
|
||||
if (!file) {
|
||||
write_byte(f,0);
|
||||
return;
|
||||
}
|
||||
|
||||
fname = f_name(file);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -227,101 +192,102 @@ 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");
|
||||
bzero((char *)file,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 ((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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -362,7 +328,7 @@ static struct file_struct *make_file(char *fname)
|
||||
clean_fname(cleaned_name);
|
||||
fname = cleaned_name;
|
||||
|
||||
bzero(sum,SUM_LENGTH);
|
||||
memset(sum,0,SUM_LENGTH);
|
||||
|
||||
if (link_stat(fname,&st) != 0) {
|
||||
io_error = 1;
|
||||
@@ -389,7 +355,7 @@ static struct file_struct *make_file(char *fname)
|
||||
|
||||
file = (struct file_struct *)malloc(sizeof(*file));
|
||||
if (!file) out_of_memory("make_file");
|
||||
bzero((char *)file,sizeof(*file));
|
||||
memset((char *)file,0,sizeof(*file));
|
||||
|
||||
if ((p = strrchr(fname,'/'))) {
|
||||
static char *lastdir;
|
||||
@@ -459,7 +425,7 @@ static struct file_struct *make_file(char *fname)
|
||||
}
|
||||
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
total_size += st.st_size;
|
||||
stats.total_size += st.st_size;
|
||||
|
||||
return file;
|
||||
}
|
||||
@@ -532,6 +498,8 @@ static void send_directory(int f,struct file_list *flist,char *dir)
|
||||
}
|
||||
p = fname + strlen(fname);
|
||||
|
||||
local_exclude_list = NULL;
|
||||
|
||||
if (cvs_exclude) {
|
||||
if (strlen(fname) + strlen(".cvsignore") <= MAXPATHLEN-1) {
|
||||
strcpy(p,".cvsignore");
|
||||
@@ -551,6 +519,10 @@ static void send_directory(int f,struct file_list *flist,char *dir)
|
||||
send_file_name(f,flist,fname,recurse,0);
|
||||
}
|
||||
|
||||
if (local_exclude_list) {
|
||||
add_exclude_list("!", &local_exclude_list, 0);
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
@@ -561,15 +533,17 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
int i,l;
|
||||
STRUCT_STAT st;
|
||||
char *p,*dir;
|
||||
char dbuf[MAXPATHLEN];
|
||||
char lastpath[MAXPATHLEN]="";
|
||||
struct file_list *flist;
|
||||
int64 start_write;
|
||||
|
||||
if (verbose && recurse && !am_server && f != -1) {
|
||||
rprintf(FINFO,"building file list ... ");
|
||||
rflush(FINFO);
|
||||
}
|
||||
|
||||
start_write = stats.total_written;
|
||||
|
||||
flist = (struct file_list *)malloc(sizeof(flist[0]));
|
||||
if (!flist) out_of_memory("send_file_list");
|
||||
|
||||
@@ -641,24 +615,23 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
fname = ".";
|
||||
|
||||
if (dir && *dir) {
|
||||
if (getcwd(dbuf,MAXPATHLEN-1) == NULL) {
|
||||
rprintf(FERROR,"getwd : %s\n",strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
if (chdir(dir) != 0) {
|
||||
char *olddir = push_dir(dir, 1);
|
||||
|
||||
if (!olddir) {
|
||||
io_error=1;
|
||||
rprintf(FERROR,"chdir %s : %s\n",
|
||||
rprintf(FERROR,"push_dir %s : %s\n",
|
||||
dir,strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
flist_dir = dir;
|
||||
if (one_file_system)
|
||||
set_filesystem(fname);
|
||||
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
|
||||
flist_dir = NULL;
|
||||
if (chdir(dbuf) != 0) {
|
||||
rprintf(FERROR,"chdir %s : %s\n",
|
||||
dbuf,strerror(errno));
|
||||
if (pop_dir(olddir) != 0) {
|
||||
rprintf(FERROR,"pop_dir %s : %s\n",
|
||||
dir,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
continue;
|
||||
@@ -676,7 +649,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
if (verbose && recurse && !am_server && f != -1)
|
||||
rprintf(FINFO,"done\n");
|
||||
|
||||
clean_flist(flist);
|
||||
clean_flist(flist, 0);
|
||||
|
||||
/* now send the uid/gid list. This was introduced in protocol
|
||||
version 15 */
|
||||
@@ -691,6 +664,8 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
|
||||
if (f != -1) {
|
||||
io_end_buffering(f);
|
||||
stats.flist_size = stats.total_written - start_write;
|
||||
stats.num_files = flist->count;
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
@@ -704,12 +679,15 @@ struct file_list *recv_file_list(int f)
|
||||
{
|
||||
struct file_list *flist;
|
||||
unsigned char flags;
|
||||
int64 start_read;
|
||||
|
||||
if (verbose && recurse && !am_server) {
|
||||
rprintf(FINFO,"receiving file list ... ");
|
||||
rflush(FINFO);
|
||||
}
|
||||
|
||||
start_read = stats.total_read;
|
||||
|
||||
flist = (struct file_list *)malloc(sizeof(flist[0]));
|
||||
if (!flist)
|
||||
goto oom;
|
||||
@@ -740,7 +718,7 @@ struct file_list *recv_file_list(int f)
|
||||
receive_file_entry(&flist->files[i],flags,f);
|
||||
|
||||
if (S_ISREG(flist->files[i]->mode))
|
||||
total_size += flist->files[i]->length;
|
||||
stats.total_size += flist->files[i]->length;
|
||||
|
||||
flist->count++;
|
||||
|
||||
@@ -752,7 +730,7 @@ struct file_list *recv_file_list(int f)
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"received %d names\n",flist->count);
|
||||
|
||||
clean_flist(flist);
|
||||
clean_flist(flist, relative_paths);
|
||||
|
||||
if (verbose && recurse && !am_server) {
|
||||
rprintf(FINFO,"done\n");
|
||||
@@ -771,6 +749,9 @@ struct file_list *recv_file_list(int f)
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_file_list done\n");
|
||||
|
||||
stats.flist_size = stats.total_read - start_read;
|
||||
stats.num_files = flist->count;
|
||||
|
||||
return flist;
|
||||
|
||||
oom:
|
||||
@@ -785,8 +766,8 @@ int file_compare(struct file_struct **f1,struct file_struct **f2)
|
||||
if (!(*f1)->basename) return -1;
|
||||
if (!(*f2)->basename) return 1;
|
||||
if ((*f1)->dirname == (*f2)->dirname)
|
||||
return strcmp((*f1)->basename, (*f2)->basename);
|
||||
return strcmp(f_name(*f1),f_name(*f2));
|
||||
return u_strcmp((*f1)->basename, (*f2)->basename);
|
||||
return u_strcmp(f_name(*f1),f_name(*f2));
|
||||
}
|
||||
|
||||
|
||||
@@ -822,7 +803,7 @@ static void free_file(struct file_struct *file)
|
||||
if (file->basename) free(file->basename);
|
||||
if (file->link) free(file->link);
|
||||
if (file->sum) free(file->sum);
|
||||
bzero((char *)file, sizeof(*file));
|
||||
memset((char *)file, 0, sizeof(*file));
|
||||
}
|
||||
|
||||
|
||||
@@ -836,9 +817,9 @@ void flist_free(struct file_list *flist)
|
||||
free_file(flist->files[i]);
|
||||
free(flist->files[i]);
|
||||
}
|
||||
bzero((char *)flist->files, sizeof(flist->files[0])*flist->count);
|
||||
memset((char *)flist->files, 0, sizeof(flist->files[0])*flist->count);
|
||||
free(flist->files);
|
||||
bzero((char *)flist, sizeof(*flist));
|
||||
memset((char *)flist, 0, sizeof(*flist));
|
||||
free(flist);
|
||||
}
|
||||
|
||||
@@ -847,7 +828,7 @@ void flist_free(struct file_list *flist)
|
||||
* This routine ensures we don't have any duplicate names in our file list.
|
||||
* duplicate names can cause corruption because of the pipelining
|
||||
*/
|
||||
void clean_flist(struct file_list *flist)
|
||||
static void clean_flist(struct file_list *flist, int strip_root)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -869,6 +850,37 @@ void clean_flist(struct file_list *flist)
|
||||
free_file(flist->files[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (strip_root) {
|
||||
/* we need to strip off the root directory in the case
|
||||
of relative paths, but this must be done _after_
|
||||
the sorting phase */
|
||||
for (i=0;i<flist->count;i++) {
|
||||
if (flist->files[i]->dirname &&
|
||||
flist->files[i]->dirname[0] == '/') {
|
||||
memmove(&flist->files[i]->dirname[0],
|
||||
&flist->files[i]->dirname[1],
|
||||
strlen(flist->files[i]->dirname));
|
||||
}
|
||||
|
||||
if (flist->files[i]->dirname &&
|
||||
!flist->files[i]->dirname[0]) {
|
||||
flist->files[i]->dirname = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (verbose <= 3) return;
|
||||
|
||||
for (i=0;i<flist->count;i++) {
|
||||
rprintf(FINFO,"[%d] i=%d %s %s mode=0%o len=%d\n",
|
||||
getpid(), i,
|
||||
flist->files[i]->dirname,
|
||||
flist->files[i]->basename,
|
||||
flist->files[i]->mode,
|
||||
flist->files[i]->length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
399
generator.c
Normal file
399
generator.c
Normal file
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int dry_run;
|
||||
extern int relative_paths;
|
||||
extern int preserve_links;
|
||||
extern int am_root;
|
||||
extern int preserve_devices;
|
||||
extern int preserve_hard_links;
|
||||
extern int update_only;
|
||||
extern int whole_file;
|
||||
extern int block_size;
|
||||
extern int csum_length;
|
||||
extern int ignore_times;
|
||||
extern int io_timeout;
|
||||
extern int remote_version;
|
||||
extern int always_checksum;
|
||||
|
||||
|
||||
/* choose whether to skip a particular file */
|
||||
static int skip_file(char *fname,
|
||||
struct file_struct *file, STRUCT_STAT *st)
|
||||
{
|
||||
if (st->st_size != file->length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if always checksum is set then we use the checksum instead
|
||||
of the file time to determine whether to sync */
|
||||
if (always_checksum && S_ISREG(st->st_mode)) {
|
||||
char sum[MD4_SUM_LENGTH];
|
||||
file_checksum(fname,sum,st->st_size);
|
||||
return (memcmp(sum,file->sum,csum_length) == 0);
|
||||
}
|
||||
|
||||
if (ignore_times) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (st->st_mtime == file->modtime);
|
||||
}
|
||||
|
||||
|
||||
/* use a larger block size for really big files */
|
||||
static int adapt_block_size(struct file_struct *file, int bsize)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (bsize != BLOCK_SIZE) return bsize;
|
||||
|
||||
ret = file->length / (10000); /* rough heuristic */
|
||||
ret = ret & ~15; /* multiple of 16 */
|
||||
if (ret < bsize) ret = bsize;
|
||||
if (ret > CHUNK_SIZE/2) ret = CHUNK_SIZE/2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
send a sums struct down a fd
|
||||
*/
|
||||
static void send_sums(struct sum_struct *s,int f_out)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* tell the other guy how many we are going to be doing and how many
|
||||
bytes there are in the last chunk */
|
||||
write_int(f_out,s?s->count:0);
|
||||
write_int(f_out,s?s->n:block_size);
|
||||
write_int(f_out,s?s->remainder:0);
|
||||
if (s)
|
||||
for (i=0;i<s->count;i++) {
|
||||
write_int(f_out,s->sums[i].sum1);
|
||||
write_buf(f_out,s->sums[i].sum2,csum_length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
generate a stream of signatures/checksums that describe a buffer
|
||||
|
||||
generate approximately one checksum every n bytes
|
||||
*/
|
||||
static struct sum_struct *generate_sums(struct map_struct *buf,OFF_T len,int n)
|
||||
{
|
||||
int i;
|
||||
struct sum_struct *s;
|
||||
int count;
|
||||
int block_len = n;
|
||||
int remainder = (len%block_len);
|
||||
OFF_T offset = 0;
|
||||
|
||||
count = (len+(block_len-1))/block_len;
|
||||
|
||||
s = (struct sum_struct *)malloc(sizeof(*s));
|
||||
if (!s) out_of_memory("generate_sums");
|
||||
|
||||
s->count = count;
|
||||
s->remainder = remainder;
|
||||
s->n = n;
|
||||
s->flength = len;
|
||||
|
||||
if (count==0) {
|
||||
s->sums = NULL;
|
||||
return s;
|
||||
}
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"count=%d rem=%d n=%d flength=%d\n",
|
||||
s->count,s->remainder,s->n,(int)s->flength);
|
||||
|
||||
s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
|
||||
if (!s->sums) out_of_memory("generate_sums");
|
||||
|
||||
for (i=0;i<count;i++) {
|
||||
int n1 = MIN(len,n);
|
||||
char *map = map_ptr(buf,offset,n1);
|
||||
|
||||
s->sums[i].sum1 = get_checksum1(map,n1);
|
||||
get_checksum2(map,n1,s->sums[i].sum2);
|
||||
|
||||
s->sums[i].offset = offset;
|
||||
s->sums[i].len = n1;
|
||||
s->sums[i].i = i;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"chunk[%d] offset=%d len=%d sum1=%08x\n",
|
||||
i,(int)s->sums[i].offset,s->sums[i].len,s->sums[i].sum1);
|
||||
|
||||
len -= n1;
|
||||
offset += n1;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
{
|
||||
int fd;
|
||||
STRUCT_STAT st;
|
||||
struct map_struct *buf;
|
||||
struct sum_struct *s;
|
||||
int statret;
|
||||
struct file_struct *file = flist->files[i];
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_generator(%s,%d)\n",fname,i);
|
||||
|
||||
statret = link_stat(fname,&st);
|
||||
|
||||
if (S_ISDIR(file->mode)) {
|
||||
if (dry_run) return;
|
||||
if (statret == 0 && !S_ISDIR(st.st_mode)) {
|
||||
if (do_unlink(fname) != 0) {
|
||||
rprintf(FERROR,"unlink %s : %s\n",fname,strerror(errno));
|
||||
return;
|
||||
}
|
||||
statret = -1;
|
||||
}
|
||||
if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
|
||||
if (!(relative_paths && errno==ENOENT &&
|
||||
create_directory_path(fname)==0 &&
|
||||
do_mkdir(fname,file->mode)==0)) {
|
||||
rprintf(FERROR,"mkdir %s : %s (2)\n",
|
||||
fname,strerror(errno));
|
||||
}
|
||||
}
|
||||
if (set_perms(fname,file,NULL,0) && verbose)
|
||||
rprintf(FINFO,"%s/\n",fname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (preserve_links && S_ISLNK(file->mode)) {
|
||||
#if SUPPORT_LINKS
|
||||
char lnk[MAXPATHLEN];
|
||||
int l;
|
||||
extern int safe_symlinks;
|
||||
|
||||
if (safe_symlinks && unsafe_symlink(file->link, fname)) {
|
||||
if (verbose) {
|
||||
rprintf(FINFO,"ignoring unsafe symlink %s -> %s\n",
|
||||
fname,file->link);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (statret == 0) {
|
||||
l = readlink(fname,lnk,MAXPATHLEN-1);
|
||||
if (l > 0) {
|
||||
lnk[l] = 0;
|
||||
if (strcmp(lnk,file->link) == 0) {
|
||||
set_perms(fname,file,&st,1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete_file(fname);
|
||||
if (do_symlink(file->link,fname) != 0) {
|
||||
rprintf(FERROR,"link %s -> %s : %s\n",
|
||||
fname,file->link,strerror(errno));
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
if (verbose) {
|
||||
rprintf(FINFO,"%s -> %s\n",
|
||||
fname,file->link);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MKNOD
|
||||
if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
|
||||
if (statret != 0 ||
|
||||
st.st_mode != file->mode ||
|
||||
st.st_rdev != file->rdev) {
|
||||
delete_file(fname);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
|
||||
fname,(int)file->mode,(int)file->rdev);
|
||||
if (do_mknod(fname,file->mode,file->rdev) != 0) {
|
||||
rprintf(FERROR,"mknod %s : %s\n",fname,strerror(errno));
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
if (verbose)
|
||||
rprintf(FINFO,"%s\n",fname);
|
||||
}
|
||||
} else {
|
||||
set_perms(fname,file,&st,1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (preserve_hard_links && check_hard_link(file)) {
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO,"%s is a hard link\n",f_name(file));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!S_ISREG(file->mode)) {
|
||||
rprintf(FINFO,"skipping non-regular file %s\n",fname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (statret == -1) {
|
||||
if (errno == ENOENT) {
|
||||
write_int(f_out,i);
|
||||
if (!dry_run) send_sums(NULL,f_out);
|
||||
} else {
|
||||
if (verbose > 1)
|
||||
rprintf(FERROR,"recv_generator failed to open %s\n",fname);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
if (delete_file(fname) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* now pretend the file didn't exist */
|
||||
write_int(f_out,i);
|
||||
if (!dry_run) send_sums(NULL,f_out);
|
||||
return;
|
||||
}
|
||||
|
||||
if (update_only && st.st_mtime > file->modtime) {
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO,"%s is newer\n",fname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (skip_file(fname, file, &st)) {
|
||||
set_perms(fname,file,&st,1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dry_run) {
|
||||
write_int(f_out,i);
|
||||
return;
|
||||
}
|
||||
|
||||
if (whole_file) {
|
||||
write_int(f_out,i);
|
||||
send_sums(NULL,f_out);
|
||||
return;
|
||||
}
|
||||
|
||||
/* open the file */
|
||||
fd = open(fname,O_RDONLY);
|
||||
|
||||
if (fd == -1) {
|
||||
rprintf(FERROR,"failed to open %s : %s\n",fname,strerror(errno));
|
||||
rprintf(FERROR,"skipping %s\n",fname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (st.st_size > 0) {
|
||||
buf = map_file(fd,st.st_size);
|
||||
} else {
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"gen mapped %s of size %d\n",fname,(int)st.st_size);
|
||||
|
||||
s = generate_sums(buf,st.st_size,adapt_block_size(file, block_size));
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"sending sums for %d\n",i);
|
||||
|
||||
write_int(f_out,i);
|
||||
send_sums(s,f_out);
|
||||
|
||||
close(fd);
|
||||
if (buf) unmap_file(buf);
|
||||
|
||||
free_sums(s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
|
||||
{
|
||||
int i;
|
||||
int phase=0;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"generator starting pid=%d count=%d\n",
|
||||
(int)getpid(),flist->count);
|
||||
|
||||
for (i = 0; i < flist->count; i++) {
|
||||
struct file_struct *file = flist->files[i];
|
||||
mode_t saved_mode = file->mode;
|
||||
if (!file->basename) continue;
|
||||
|
||||
/* we need to ensure that any directories we create have writeable
|
||||
permissions initially so that we can create the files within
|
||||
them. This is then fixed after the files are transferred */
|
||||
if (!am_root && S_ISDIR(file->mode)) {
|
||||
file->mode |= S_IWUSR; /* user write */
|
||||
}
|
||||
|
||||
recv_generator(local_name?local_name:f_name(file),
|
||||
flist,i,f);
|
||||
|
||||
file->mode = saved_mode;
|
||||
}
|
||||
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
ignore_times=1;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"generate_files phase=%d\n",phase);
|
||||
|
||||
write_int(f,-1);
|
||||
|
||||
/* we expect to just sit around now, so don't exit on a
|
||||
timeout. If we really get a timeout then the other process should
|
||||
exit */
|
||||
io_timeout = 0;
|
||||
|
||||
if (remote_version >= 13) {
|
||||
/* in newer versions of the protocol the files can cycle through
|
||||
the system more than once to catch initial checksum errors */
|
||||
for (i=read_int(f_recv); i != -1; i=read_int(f_recv)) {
|
||||
struct file_struct *file = flist->files[i];
|
||||
recv_generator(local_name?local_name:f_name(file),
|
||||
flist,i,f);
|
||||
}
|
||||
|
||||
phase++;
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"generate_files phase=%d\n",phase);
|
||||
|
||||
write_int(f,-1);
|
||||
}
|
||||
}
|
||||
2
hlink.c
2
hlink.c
@@ -56,7 +56,7 @@ void init_hard_links(struct file_list *flist)
|
||||
out_of_memory("init_hard_links");
|
||||
|
||||
for (i = 0; i < flist->count; i++)
|
||||
bcopy(flist->files[i], &hlink_list[i], sizeof(hlink_list[0]));
|
||||
memcpy(&hlink_list[i], flist->files[i], sizeof(hlink_list[0]));
|
||||
|
||||
qsort(hlink_list,flist->count,
|
||||
sizeof(hlink_list[0]),
|
||||
|
||||
108
io.c
108
io.c
@@ -24,27 +24,18 @@
|
||||
*/
|
||||
#include "rsync.h"
|
||||
|
||||
static int64 total_written;
|
||||
static int64 total_read;
|
||||
/* if no timeout is specified then use a 60 second select timeout */
|
||||
#define SELECT_TIMEOUT 60
|
||||
|
||||
static int io_multiplexing_out;
|
||||
static int io_multiplexing_in;
|
||||
static int multiplex_in_fd;
|
||||
static int multiplex_out_fd;
|
||||
static time_t last_io;
|
||||
|
||||
static int eof_error=1;
|
||||
extern int verbose;
|
||||
extern int io_timeout;
|
||||
|
||||
int64 write_total(void)
|
||||
{
|
||||
return total_written;
|
||||
}
|
||||
|
||||
int64 read_total(void)
|
||||
{
|
||||
return total_read;
|
||||
}
|
||||
extern struct stats stats;
|
||||
|
||||
static int buffer_f_in = -1;
|
||||
|
||||
@@ -66,8 +57,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);
|
||||
}
|
||||
@@ -78,6 +69,8 @@ static char *read_buffer;
|
||||
static char *read_buffer_p;
|
||||
static int read_buffer_len;
|
||||
static int read_buffer_size;
|
||||
static int no_flush;
|
||||
static int no_flush_read;
|
||||
|
||||
/* read from a socket with IO timeout. return the number of
|
||||
bytes read. If no bytes can be read then exit, never return
|
||||
@@ -86,7 +79,9 @@ static int read_timeout(int fd, char *buf, int len)
|
||||
{
|
||||
int n, ret=0;
|
||||
|
||||
no_flush_read++;
|
||||
io_flush();
|
||||
no_flush_read--;
|
||||
|
||||
while (ret == 0) {
|
||||
fd_set fds;
|
||||
@@ -94,11 +89,10 @@ static int read_timeout(int fd, char *buf, int len)
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
tv.tv_sec = io_timeout;
|
||||
tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (select(fd+1, &fds, NULL, NULL,
|
||||
io_timeout?&tv:NULL) != 1) {
|
||||
if (select(fd+1, &fds, NULL, NULL, &tv) != 1) {
|
||||
check_timeout();
|
||||
continue;
|
||||
}
|
||||
@@ -106,6 +100,7 @@ static int read_timeout(int fd, char *buf, int len)
|
||||
n = read(fd, buf, len);
|
||||
|
||||
if (n > 0) {
|
||||
stats.total_read += n;
|
||||
buf += n;
|
||||
len -= n;
|
||||
ret += n;
|
||||
@@ -118,8 +113,19 @@ static int read_timeout(int fd, char *buf, int len)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n == -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);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
rprintf(FERROR,"EOF in read_timeout\n");
|
||||
if (eof_error) {
|
||||
rprintf(FERROR,"unexpected EOF in read_timeout\n");
|
||||
}
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
@@ -142,7 +148,7 @@ static void read_loop(int fd, char *buf, int len)
|
||||
}
|
||||
}
|
||||
|
||||
/* read from the file descriptor handing multiplexing -
|
||||
/* read from the file descriptor handling multiplexing -
|
||||
return number of bytes read
|
||||
never return <= 0 */
|
||||
static int read_unbuffered(int fd, char *buf, int len)
|
||||
@@ -220,10 +226,7 @@ static void read_check(int f)
|
||||
|
||||
if (n > (read_buffer_size - read_buffer_len)) {
|
||||
read_buffer_size += n;
|
||||
if (!read_buffer)
|
||||
read_buffer = (char *)malloc(read_buffer_size);
|
||||
else
|
||||
read_buffer = (char *)realloc(read_buffer,read_buffer_size);
|
||||
read_buffer = (char *)Realloc(read_buffer,read_buffer_size);
|
||||
if (!read_buffer) out_of_memory("read check");
|
||||
read_buffer_p = read_buffer;
|
||||
}
|
||||
@@ -240,7 +243,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);
|
||||
}
|
||||
|
||||
@@ -254,7 +257,9 @@ static void readfd(int fd,char *buffer,int N)
|
||||
continue;
|
||||
}
|
||||
|
||||
no_flush_read++;
|
||||
io_flush();
|
||||
no_flush_read--;
|
||||
|
||||
ret = read_unbuffered(fd,buffer + total,N-total);
|
||||
total += ret;
|
||||
@@ -266,7 +271,6 @@ int32 read_int(int f)
|
||||
{
|
||||
char b[4];
|
||||
readfd(f,b,4);
|
||||
total_read += 4;
|
||||
return IVAL(b,0);
|
||||
}
|
||||
|
||||
@@ -285,7 +289,6 @@ int64 read_longint(int f)
|
||||
#else
|
||||
if (remote_version >= 16) {
|
||||
readfd(f,b,8);
|
||||
total_read += 8;
|
||||
ret = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
|
||||
}
|
||||
#endif
|
||||
@@ -296,7 +299,6 @@ int64 read_longint(int f)
|
||||
void read_buf(int f,char *buf,int len)
|
||||
{
|
||||
readfd(f,buf,len);
|
||||
total_read += len;
|
||||
}
|
||||
|
||||
void read_sbuf(int f,char *buf,int len)
|
||||
@@ -323,9 +325,10 @@ static void writefd_unbuffered(int fd,char *buf,int len)
|
||||
fd_set w_fds, r_fds;
|
||||
int fd_count, count;
|
||||
struct timeval tv;
|
||||
int reading;
|
||||
int reading=0;
|
||||
int blocked=0;
|
||||
|
||||
reading = (buffer_f_in != -1 && read_buffer_len < MAX_READ_BUFFER);
|
||||
no_flush++;
|
||||
|
||||
while (total < len) {
|
||||
FD_ZERO(&w_fds);
|
||||
@@ -333,47 +336,62 @@ static void writefd_unbuffered(int fd,char *buf,int len)
|
||||
FD_SET(fd,&w_fds);
|
||||
fd_count = fd+1;
|
||||
|
||||
if (!no_flush_read) {
|
||||
reading = (buffer_f_in != -1);
|
||||
}
|
||||
|
||||
if (reading) {
|
||||
FD_SET(buffer_f_in,&r_fds);
|
||||
if (buffer_f_in > fd)
|
||||
fd_count = buffer_f_in+1;
|
||||
}
|
||||
|
||||
tv.tv_sec = io_timeout;
|
||||
tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
count = select(fd_count,
|
||||
reading?&r_fds:NULL,
|
||||
&w_fds,NULL,
|
||||
io_timeout?&tv:NULL);
|
||||
&tv);
|
||||
|
||||
if (count <= 0) {
|
||||
check_timeout();
|
||||
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;
|
||||
}
|
||||
|
||||
if (ret == -1 &&
|
||||
(errno == EAGAIN || errno == EWOULDBLOCK)) {
|
||||
blocked++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret <= 0) {
|
||||
rprintf(FERROR,"erroring writing %d bytes - exiting\n", 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);
|
||||
}
|
||||
}
|
||||
|
||||
no_flush--;
|
||||
}
|
||||
|
||||
|
||||
@@ -395,7 +413,7 @@ void io_start_buffering(int fd)
|
||||
void io_flush(void)
|
||||
{
|
||||
int fd = multiplex_out_fd;
|
||||
if (!io_buffer_count) return;
|
||||
if (!io_buffer_count || no_flush) return;
|
||||
|
||||
if (io_multiplexing_out) {
|
||||
SIVAL(io_buffer-4, 0, (MPLEX_BASE<<24) + io_buffer_count);
|
||||
@@ -441,7 +459,6 @@ void write_int(int f,int32 x)
|
||||
char b[4];
|
||||
SIVAL(b,0,x);
|
||||
writefd(f,b,4);
|
||||
total_written += 4;
|
||||
}
|
||||
|
||||
void write_longint(int f, int64 x)
|
||||
@@ -459,17 +476,15 @@ void write_longint(int f, int64 x)
|
||||
SIVAL(b,4,((x>>32)&0xFFFFFFFF));
|
||||
|
||||
writefd(f,b,8);
|
||||
total_written += 8;
|
||||
}
|
||||
|
||||
void write_buf(int f,char *buf,int len)
|
||||
{
|
||||
writefd(f,buf,len);
|
||||
total_written += len;
|
||||
}
|
||||
|
||||
/* write a string to the connection */
|
||||
void write_sbuf(int f,char *buf)
|
||||
static void write_sbuf(int f,char *buf)
|
||||
{
|
||||
write_buf(f, buf, strlen(buf));
|
||||
}
|
||||
@@ -482,8 +497,12 @@ void write_byte(int f,unsigned char c)
|
||||
|
||||
int read_line(int f, char *buf, int maxlen)
|
||||
{
|
||||
eof_error = 0;
|
||||
|
||||
while (maxlen) {
|
||||
buf[0] = 0;
|
||||
read_buf(f, buf, 1);
|
||||
if (buf[0] == 0) return 0;
|
||||
if (buf[0] == '\n') {
|
||||
buf[0] = 0;
|
||||
break;
|
||||
@@ -497,6 +516,9 @@ int read_line(int f, char *buf, int maxlen)
|
||||
*buf = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
eof_error = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ pid_t waitpid(pid_t pid, int *statptr, int options)
|
||||
#ifndef HAVE_MEMMOVE
|
||||
void *memmove(void *dest, const void *src, size_t n)
|
||||
{
|
||||
bcopy(src, dest, n);
|
||||
memcpy(dest, src, n);
|
||||
return dest;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
#define BOOL int
|
||||
#define False 0
|
||||
#define True 1
|
||||
#define Realloc realloc
|
||||
#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2)))
|
||||
#define strequal(a,b) (strcasecmp(a,b)==0)
|
||||
#define BOOLSTR(b) ((b) ? "Yes" : "No")
|
||||
@@ -99,6 +98,7 @@ typedef struct
|
||||
{
|
||||
char *motd_file;
|
||||
char *lock_file;
|
||||
char *log_file;
|
||||
int syslog_facility;
|
||||
int max_connections;
|
||||
char *socket_options;
|
||||
@@ -232,6 +232,7 @@ static struct parm_struct parm_table[] =
|
||||
{"lock file", P_STRING, P_GLOBAL, &Globals.lock_file, NULL, 0},
|
||||
{"syslog facility", P_ENUM, P_GLOBAL, &Globals.syslog_facility, enum_facilities,0},
|
||||
{"socket options", P_STRING, P_GLOBAL, &Globals.socket_options,NULL, 0},
|
||||
{"log file", P_STRING, P_GLOBAL, &Globals.log_file, NULL, 0},
|
||||
|
||||
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL, 0},
|
||||
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, 0},
|
||||
@@ -296,6 +297,7 @@ static void init_locals(void)
|
||||
|
||||
FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
|
||||
FN_GLOBAL_STRING(lp_lock_file, &Globals.lock_file)
|
||||
FN_GLOBAL_STRING(lp_log_file, &Globals.log_file)
|
||||
FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
|
||||
FN_GLOBAL_INTEGER(lp_max_connections, &Globals.max_connections)
|
||||
FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
|
||||
@@ -330,7 +332,7 @@ initialise a service to the defaults
|
||||
***************************************************************************/
|
||||
static void init_service(service *pservice)
|
||||
{
|
||||
bzero((char *)pservice,sizeof(service));
|
||||
memset((char *)pservice,0,sizeof(service));
|
||||
copy_service(pservice,&sDefault);
|
||||
}
|
||||
|
||||
@@ -368,6 +370,7 @@ static int add_a_service(service *pservice, char *name)
|
||||
i = iNumServices;
|
||||
|
||||
ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
|
||||
|
||||
if (ServicePtrs)
|
||||
pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
|
||||
|
||||
|
||||
52
log.c
52
log.c
@@ -23,15 +23,55 @@
|
||||
*/
|
||||
#include "rsync.h"
|
||||
|
||||
static FILE *logfile;
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
return the date and time as a string
|
||||
****************************************************************************/
|
||||
static char *timestring(void )
|
||||
{
|
||||
static char TimeBuf[200];
|
||||
time_t t = time(NULL);
|
||||
struct tm *tm = localtime(&t);
|
||||
|
||||
#ifdef HAVE_STRFTIME
|
||||
strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm);
|
||||
#else
|
||||
strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf)-1);
|
||||
#endif
|
||||
|
||||
if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
|
||||
TimeBuf[strlen(TimeBuf)-1] = 0;
|
||||
}
|
||||
|
||||
return(TimeBuf);
|
||||
}
|
||||
|
||||
static void logit(int priority, char *buf)
|
||||
{
|
||||
if (logfile) {
|
||||
fprintf(logfile,"%s %s", timestring(), buf);
|
||||
fflush(logfile);
|
||||
} else {
|
||||
syslog(priority, "%s", buf);
|
||||
}
|
||||
}
|
||||
|
||||
void log_open(void)
|
||||
{
|
||||
static int initialised;
|
||||
int options = LOG_PID;
|
||||
time_t t;
|
||||
|
||||
if (initialised) return;
|
||||
initialised = 1;
|
||||
|
||||
if (lp_log_file()) {
|
||||
logfile = fopen(lp_log_file(), "a");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef LOG_NDELAY
|
||||
options |= LOG_NDELAY;
|
||||
#endif
|
||||
@@ -43,8 +83,14 @@ void log_open(void)
|
||||
#endif
|
||||
|
||||
#ifndef LOG_NDELAY
|
||||
syslog(LOG_INFO,"rsyncd started\n");
|
||||
logit(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);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +125,7 @@ void rprintf(int fd, const char *format, ...)
|
||||
|
||||
log_open();
|
||||
if (!io_multiplex_write(fd, buf, strlen(buf))) {
|
||||
syslog(priority, "%s", buf);
|
||||
logit(priority, buf);
|
||||
}
|
||||
|
||||
depth--;
|
||||
@@ -102,6 +148,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--;
|
||||
}
|
||||
|
||||
|
||||
154
main.c
154
main.c
@@ -20,7 +20,8 @@
|
||||
#include "rsync.h"
|
||||
|
||||
time_t starttime = 0;
|
||||
int64 total_size = 0;
|
||||
|
||||
struct stats stats;
|
||||
|
||||
extern int csum_length;
|
||||
|
||||
@@ -28,16 +29,17 @@ extern int verbose;
|
||||
|
||||
static void report(int f)
|
||||
{
|
||||
int64 in,out,tsize;
|
||||
time_t t = time(NULL);
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int am_daemon;
|
||||
extern int do_stats;
|
||||
|
||||
if (am_daemon) {
|
||||
syslog(LOG_INFO,"wrote %.0f bytes read %.0f bytes total size %.0f\n",
|
||||
(double)write_total(),(double)read_total(),
|
||||
(double)total_size);
|
||||
(double)stats.total_written,
|
||||
(double)stats.total_read,
|
||||
(double)stats.total_size);
|
||||
if (f == -1 || !am_sender) return;
|
||||
}
|
||||
|
||||
@@ -46,26 +48,49 @@ static void report(int f)
|
||||
if (am_server && !am_sender) return;
|
||||
|
||||
if (am_server && am_sender) {
|
||||
write_longint(f,read_total());
|
||||
write_longint(f,write_total());
|
||||
write_longint(f,total_size);
|
||||
write_longint(f,stats.total_read);
|
||||
write_longint(f,stats.total_written);
|
||||
write_longint(f,stats.total_size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (am_sender) {
|
||||
in = read_total();
|
||||
out = write_total();
|
||||
tsize = total_size;
|
||||
} else {
|
||||
out = read_longint(f);
|
||||
in = read_longint(f);
|
||||
tsize = read_longint(f);
|
||||
if (!am_sender) {
|
||||
int64 r;
|
||||
stats.total_written = read_longint(f);
|
||||
r = read_longint(f);
|
||||
stats.total_size = read_longint(f);
|
||||
stats.total_read = r;
|
||||
}
|
||||
|
||||
if (do_stats) {
|
||||
rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
|
||||
rprintf(FINFO,"Number of files transferred: %d\n",
|
||||
stats.num_transferred_files);
|
||||
rprintf(FINFO,"Total file size: %.0f bytes\n",
|
||||
(double)stats.total_size);
|
||||
rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
|
||||
(double)stats.total_transferred_size);
|
||||
rprintf(FINFO,"Literal data: %.0f bytes\n",
|
||||
(double)stats.literal_data);
|
||||
rprintf(FINFO,"Matched data: %.0f bytes\n",
|
||||
(double)stats.matched_data);
|
||||
rprintf(FINFO,"File list size: %d\n", stats.flist_size);
|
||||
rprintf(FINFO,"Total bytes written: %.0f\n",
|
||||
(double)stats.total_written);
|
||||
rprintf(FINFO,"Total bytes read: %.0f\n\n",
|
||||
(double)stats.total_read);
|
||||
}
|
||||
|
||||
printf("wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
|
||||
(double)out,(double)in,(in+out)/(0.5 + (t-starttime)));
|
||||
printf("total size is %.0f speedup is %.2f\n",
|
||||
(double)tsize,(1.0*tsize)/(in+out));
|
||||
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)));
|
||||
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));
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
|
||||
@@ -147,10 +172,14 @@ 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 (chdir(name) != 0) {
|
||||
rprintf(FERROR,"chdir %s : %s (1)\n",
|
||||
if (!push_dir(name, 0)) {
|
||||
rprintf(FERROR,"push_dir %s : %s (1)\n",
|
||||
name,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
@@ -173,11 +202,13 @@ 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 (chdir(name) != 0) {
|
||||
rprintf(FERROR,"chdir %s : %s (2)\n",name,strerror(errno));
|
||||
if (!push_dir(name, 0)) {
|
||||
rprintf(FERROR,"push_dir %s : %s (2)\n",
|
||||
name,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
@@ -198,8 +229,8 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
|
||||
|
||||
if (!relative_paths && chdir(dir) != 0) {
|
||||
rprintf(FERROR,"chdir %s: %s (3)\n",dir,strerror(errno));
|
||||
if (!relative_paths && !push_dir(dir, 0)) {
|
||||
rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
argc--;
|
||||
@@ -219,6 +250,10 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
|
||||
argv[0] = ".";
|
||||
}
|
||||
|
||||
set_nonblocking(f_out);
|
||||
if (f_in != f_out)
|
||||
set_nonblocking(f_in);
|
||||
|
||||
flist = send_file_list(f_out,argc,argv);
|
||||
if (!flist || flist->count == 0) {
|
||||
exit_cleanup(0);
|
||||
@@ -252,12 +287,12 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
close(recv_pipe[0]);
|
||||
if (f_in != f_out) close(f_out);
|
||||
|
||||
set_nonblocking(f_in);
|
||||
set_nonblocking(recv_pipe[1]);
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -265,6 +300,12 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
close(recv_pipe[1]);
|
||||
io_close_input(f_in);
|
||||
if (f_in != f_out) close(f_in);
|
||||
|
||||
set_nonblocking(f_out);
|
||||
set_nonblocking(recv_pipe[0]);
|
||||
|
||||
io_start_buffering(f_out);
|
||||
|
||||
generate_files(f_out,flist,local_name,recv_pipe[0]);
|
||||
|
||||
io_flush();
|
||||
@@ -289,8 +330,8 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
|
||||
dir = argv[0];
|
||||
argc--;
|
||||
argv++;
|
||||
if (!am_daemon && chdir(dir) != 0) {
|
||||
rprintf(FERROR,"chdir %s : %s (4)\n",
|
||||
if (!am_daemon && !push_dir(dir, 0)) {
|
||||
rprintf(FERROR,"push_dir %s : %s (4)\n",
|
||||
dir,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
@@ -323,8 +364,12 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
|
||||
extern int cvs_exclude;
|
||||
extern int am_sender;
|
||||
|
||||
set_nonblocking(f_out);
|
||||
if (f_in != f_out)
|
||||
set_nonblocking(f_in);
|
||||
|
||||
setup_protocol(f_out, f_in);
|
||||
|
||||
|
||||
if (am_sender) {
|
||||
recv_exclude_list(f_in);
|
||||
if (cvs_exclude)
|
||||
@@ -355,6 +400,11 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
|
||||
flist = send_file_list(f_out,argc,argv);
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"file list sent\n");
|
||||
|
||||
set_nonblocking(f_out);
|
||||
if (f_in != f_out)
|
||||
set_nonblocking(f_in);
|
||||
|
||||
send_files(flist,f_out,f_in);
|
||||
if (pid != -1) {
|
||||
if (verbose > 3)
|
||||
@@ -388,20 +438,34 @@ 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;
|
||||
|
||||
int start_client(int argc, char *argv[])
|
||||
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[])
|
||||
{
|
||||
char *p;
|
||||
char *shell_machine = NULL;
|
||||
char *shell_path = NULL;
|
||||
char *shell_user = NULL;
|
||||
int pid;
|
||||
int pid, ret;
|
||||
int f_in,f_out;
|
||||
extern int local_server;
|
||||
extern int am_sender;
|
||||
extern char *shell_cmd;
|
||||
|
||||
p = strchr(argv[0],':');
|
||||
p = find_colon(argv[0]);
|
||||
|
||||
if (p) {
|
||||
if (p[1] == ':') {
|
||||
@@ -423,7 +487,7 @@ 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] == ':') {
|
||||
@@ -471,16 +535,16 @@ 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);
|
||||
|
||||
return client_run(f_in, f_out, pid, argc, argv);
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
RETSIGTYPE sigusr1_handler(int val) {
|
||||
static RETSIGTYPE sigusr1_handler(int val) {
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
@@ -497,6 +561,8 @@ int main(int argc,char *argv[])
|
||||
starttime = time(NULL);
|
||||
am_root = (getuid() == 0);
|
||||
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
|
||||
if (argc < 2) {
|
||||
usage(FERROR);
|
||||
exit_cleanup(1);
|
||||
@@ -506,7 +572,9 @@ int main(int argc,char *argv[])
|
||||
carried across */
|
||||
orig_umask = (int)umask(0);
|
||||
|
||||
parse_arguments(argc, argv);
|
||||
if (!parse_arguments(argc, argv)) {
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
32
match.c
32
match.c
@@ -29,18 +29,18 @@ extern int remote_version;
|
||||
typedef unsigned short tag;
|
||||
|
||||
#define TABLESIZE (1<<16)
|
||||
#define NULL_TAG ((tag)-1)
|
||||
#define NULL_TAG (-1)
|
||||
|
||||
static int false_alarms;
|
||||
static int tag_hits;
|
||||
static int matches;
|
||||
static int data_transfer;
|
||||
static int64 data_transfer;
|
||||
|
||||
static int total_false_alarms;
|
||||
static int total_tag_hits;
|
||||
static int total_matches;
|
||||
static int64 total_data_transfer;
|
||||
|
||||
extern struct stats stats;
|
||||
|
||||
struct target {
|
||||
tag t;
|
||||
@@ -49,7 +49,7 @@ struct target {
|
||||
|
||||
static struct target *targets;
|
||||
|
||||
static tag *tag_table;
|
||||
static int *tag_table;
|
||||
|
||||
#define gettag2(s1,s2) (((s1) + (s2)) & 0xFFFF)
|
||||
#define gettag(sum) gettag2((sum)&0xFFFF,(sum)>>16)
|
||||
@@ -65,7 +65,7 @@ static void build_hash_table(struct sum_struct *s)
|
||||
int i;
|
||||
|
||||
if (!tag_table)
|
||||
tag_table = (tag *)malloc(sizeof(tag)*TABLESIZE);
|
||||
tag_table = (int *)malloc(sizeof(tag_table[0])*TABLESIZE);
|
||||
|
||||
targets = (struct target *)malloc(sizeof(targets[0])*s->count);
|
||||
if (!tag_table || !targets)
|
||||
@@ -103,8 +103,10 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
|
||||
send_token(f,i,buf,last_match,n,i<0?0:s->sums[i].len);
|
||||
data_transfer += n;
|
||||
|
||||
if (i >= 0)
|
||||
if (i >= 0) {
|
||||
stats.matched_data += s->sums[i].len;
|
||||
n += s->sums[i].len;
|
||||
}
|
||||
|
||||
for (j=0;j<n;j+=CHUNK_SIZE) {
|
||||
int n1 = MIN(CHUNK_SIZE,n-j);
|
||||
@@ -116,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();
|
||||
}
|
||||
|
||||
|
||||
@@ -250,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);
|
||||
}
|
||||
|
||||
@@ -273,7 +286,7 @@ void match_sums(int f,struct sum_struct *s,struct map_struct *buf,OFF_T len)
|
||||
total_tag_hits += tag_hits;
|
||||
total_false_alarms += false_alarms;
|
||||
total_matches += matches;
|
||||
total_data_transfer += data_transfer;
|
||||
stats.literal_data += data_transfer;
|
||||
}
|
||||
|
||||
void match_report(void)
|
||||
@@ -282,7 +295,8 @@ void match_report(void)
|
||||
return;
|
||||
|
||||
rprintf(FINFO,
|
||||
"total: matches=%d tag_hits=%d false_alarms=%d data=%ld\n",
|
||||
"total: matches=%d tag_hits=%d false_alarms=%d data=%.0f\n",
|
||||
total_matches,total_tag_hits,
|
||||
total_false_alarms,(long)total_data_transfer);
|
||||
total_false_alarms,
|
||||
(double)stats.literal_data);
|
||||
}
|
||||
|
||||
2
md4.c
2
md4.c
@@ -102,7 +102,7 @@
|
||||
** Assumes X is an array of 16 ints.
|
||||
** The macro revx reverses the byte-ordering of the next word of X.
|
||||
*/
|
||||
void MDreverse(X)
|
||||
static void MDreverse(X)
|
||||
unsigned int32 *X;
|
||||
{ register unsigned int32 t;
|
||||
register unsigned int i;
|
||||
|
||||
596
options.c
596
options.c
@@ -55,6 +55,10 @@ int am_sender=0;
|
||||
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;
|
||||
|
||||
@@ -74,58 +78,73 @@ void usage(int F)
|
||||
{
|
||||
rprintf(F,"rsync version %s Copyright Andrew Tridgell and Paul Mackerras\n\n",
|
||||
VERSION);
|
||||
rprintf(F,"Usage:\t%s [options] src user@host:dest\nOR",RSYNC_NAME);
|
||||
rprintf(F,"\t%s [options] user@host:src dest\n\n",RSYNC_NAME);
|
||||
rprintf(F,"Options:\n");
|
||||
rprintf(F,"-v, --verbose increase verbosity\n");
|
||||
rprintf(F,"-c, --checksum always checksum\n");
|
||||
rprintf(F,"-a, --archive archive mode (same as -rlptDog)\n");
|
||||
rprintf(F,"-r, --recursive recurse into directories\n");
|
||||
rprintf(F,"-R, --relative use relative path names\n");
|
||||
rprintf(F,"-b, --backup make backups (default ~ extension)\n");
|
||||
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,"-H, --hard-links preserve hard links\n");
|
||||
rprintf(F,"-p, --perms preserve permissions\n");
|
||||
rprintf(F,"-o, --owner preserve owner (root only)\n");
|
||||
rprintf(F,"-g, --group preserve group\n");
|
||||
rprintf(F,"-D, --devices preserve devices (root only)\n");
|
||||
rprintf(F,"-t, --times preserve times\n");
|
||||
rprintf(F,"-S, --sparse handle sparse files efficiently\n");
|
||||
rprintf(F,"-n, --dry-run show what would have been transferred\n");
|
||||
rprintf(F,"-W, --whole-file copy whole files, no incremental checks\n");
|
||||
rprintf(F,"-x, --one-file-system don't cross filesystem boundaries\n");
|
||||
rprintf(F,"-B, --block-size SIZE checksum blocking size\n");
|
||||
rprintf(F,"-e, --rsh COMMAND specify rsh replacement\n");
|
||||
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," --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");
|
||||
rprintf(F,"-I, --ignore-times don't exclude files that match length and time\n");
|
||||
rprintf(F,"-T --temp-dir DIR create temporary files in directory DIR\n");
|
||||
rprintf(F,"-z, --compress compress file data\n");
|
||||
rprintf(F," --exclude FILE exclude file FILE\n");
|
||||
rprintf(F," --exclude-from FILE exclude files listed in FILE\n");
|
||||
rprintf(F," --include FILE don't exclude file FILE\n");
|
||||
rprintf(F," --include-from FILE don't exclude files listed in FILE\n");
|
||||
rprintf(F," --suffix SUFFIX override backup suffix\n");
|
||||
rprintf(F," --version print version number\n");
|
||||
rprintf(F," --daemon run as a rsync daemon\n");
|
||||
rprintf(F," --config FILE specify alternate rsyncd.conf file\n");
|
||||
rprintf(F," --port PORT specify alternate rsyncd port number\n");
|
||||
|
||||
rprintf(F,"rsync is a file transfer program capable of efficient remote update\nvia a fast differencing algorithm.\n\n");
|
||||
|
||||
rprintf(F,"Usage: rsync [OPTION]... SRC [USER@]HOST:DEST\n");
|
||||
rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC DEST\n");
|
||||
rprintf(F," or rsync [OPTION]... SRC DEST\n");
|
||||
rprintf(F," or rsync [OPTION]... [USER@]HOST::SRC DEST\n");
|
||||
rprintf(F," or rsync [OPTION]... SRC [USER@]HOST::DEST\n");
|
||||
rprintf(F,"\nOptions\n");
|
||||
rprintf(F," -v, --verbose increase verbosity\n");
|
||||
rprintf(F," -c, --checksum always checksum\n");
|
||||
rprintf(F," -a, --archive archive mode\n");
|
||||
rprintf(F," -r, --recursive recurse into directories\n");
|
||||
rprintf(F," -R, --relative use relative path names\n");
|
||||
rprintf(F," -b, --backup make backups (default ~ extension)\n");
|
||||
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");
|
||||
rprintf(F," -g, --group preserve group\n");
|
||||
rprintf(F," -D, --devices preserve devices (root only)\n");
|
||||
rprintf(F," -t, --times preserve times\n");
|
||||
rprintf(F," -S, --sparse handle sparse files efficiently\n");
|
||||
rprintf(F," -n, --dry-run show what would have been transferred\n");
|
||||
rprintf(F," -W, --whole-file copy whole files, no incremental checks\n");
|
||||
rprintf(F," -x, --one-file-system don't cross filesystem boundaries\n");
|
||||
rprintf(F," -B, --block-size=SIZE checksum blocking size\n");
|
||||
rprintf(F," -e, --rsh=COMMAND specify rsh replacement\n");
|
||||
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");
|
||||
rprintf(F," -I, --ignore-times don't exclude files that match length and time\n");
|
||||
rprintf(F," -T --temp-dir=DIR create temporary files in directory DIR\n");
|
||||
rprintf(F," -z, --compress compress file data\n");
|
||||
rprintf(F," --exclude=PATTERN exclude file FILE\n");
|
||||
rprintf(F," --exclude-from=FILE exclude patterns listed in FILE\n");
|
||||
rprintf(F," --include=PATTERN don't exclude file FILE\n");
|
||||
rprintf(F," --include-from=FILE don't exclude patterns listed in FILE\n");
|
||||
rprintf(F," --suffix=SUFFIX override backup suffix\n");
|
||||
rprintf(F," --version print version number\n");
|
||||
rprintf(F," --daemon run as a rsync daemon\n");
|
||||
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");
|
||||
rprintf(F,"the backup suffix defaults to %s\n",BACKUP_SUFFIX);
|
||||
rprintf(F,"the block size defaults to %d\n",BLOCK_SIZE);
|
||||
|
||||
rprintf(F,"\nPlease see the rsync(1) and rsyncd.conf(5) man pages for full documentation\n");
|
||||
rprintf(F,"See http://samba.anu.edu.au/rsync/ for updates and bug reports\n");
|
||||
}
|
||||
|
||||
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_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS, OPT_PARTIAL, OPT_PROGRESS,
|
||||
OPT_SAFE_LINKS};
|
||||
|
||||
static char *short_options = "oblLWHpguDCtcahvrRIxnSe:B:T:z";
|
||||
|
||||
@@ -158,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'},
|
||||
@@ -170,306 +190,332 @@ static struct option long_options[] = {
|
||||
{"temp-dir", 1, 0, 'T'},
|
||||
{"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 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",
|
||||
VERSION,PROTOCOL_VERSION);
|
||||
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");
|
||||
return 0;
|
||||
#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_CONFIG:
|
||||
config_file = optarg;
|
||||
break;
|
||||
case OPT_STATS:
|
||||
do_stats = 1;
|
||||
break;
|
||||
|
||||
case OPT_PORT:
|
||||
rsync_port = atoi(optarg);
|
||||
break;
|
||||
case OPT_PROGRESS:
|
||||
do_progress = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* rprintf(FERROR,"bad option -%c\n",opt); */
|
||||
exit_cleanup(1);
|
||||
case OPT_PARTIAL:
|
||||
keep_partial = 1;
|
||||
break;
|
||||
|
||||
case OPT_CONFIG:
|
||||
config_file = optarg;
|
||||
break;
|
||||
|
||||
case OPT_PORT:
|
||||
rsync_port = atoi(optarg);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.0.13
|
||||
Version: 2.1.1
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.0.13.tar.gz
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.1.1.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
1
params.c
1
params.c
@@ -77,7 +77,6 @@
|
||||
#define BOOL int
|
||||
#define False 0
|
||||
#define True 1
|
||||
#define Realloc realloc
|
||||
|
||||
/* -------------------------------------------------------------------------- **
|
||||
* Constants...
|
||||
|
||||
450
receiver.c
Normal file
450
receiver.c
Normal file
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int recurse;
|
||||
extern int delete_mode;
|
||||
extern int remote_version;
|
||||
extern int csum_length;
|
||||
extern struct stats stats;
|
||||
extern int dry_run;
|
||||
extern int am_server;
|
||||
extern int relative_paths;
|
||||
extern int preserve_hard_links;
|
||||
extern int cvs_exclude;
|
||||
extern int io_error;
|
||||
extern char *tmpdir;
|
||||
|
||||
|
||||
static struct delete_list {
|
||||
dev_t dev;
|
||||
INO_T inode;
|
||||
} *delete_list;
|
||||
static int dlist_len, dlist_alloc_len;
|
||||
|
||||
|
||||
/* yuck! This function wouldn't have been necessary if I had the sorting
|
||||
algorithm right. Unfortunately fixing the sorting algorithm would introduce
|
||||
a backward incompatibility as file list indexes are sent over the link.
|
||||
*/
|
||||
static int delete_already_done(struct file_list *flist,int j)
|
||||
{
|
||||
int i;
|
||||
STRUCT_STAT st;
|
||||
|
||||
if (link_stat(f_name(flist->files[j]), &st)) return 1;
|
||||
|
||||
for (i=0;i<dlist_len;i++) {
|
||||
if (st.st_ino == delete_list[i].inode &&
|
||||
st.st_dev == delete_list[i].dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void add_delete_entry(struct file_struct *file)
|
||||
{
|
||||
if (dlist_len == dlist_alloc_len) {
|
||||
dlist_alloc_len += 1024;
|
||||
delete_list = (struct delete_list *)Realloc(delete_list, sizeof(delete_list[0])*dlist_alloc_len);
|
||||
if (!delete_list) out_of_memory("add_delete_entry");
|
||||
}
|
||||
|
||||
delete_list[dlist_len].dev = file->dev;
|
||||
delete_list[dlist_len].inode = file->inode;
|
||||
dlist_len++;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"added %s to delete list\n", f_name(file));
|
||||
}
|
||||
|
||||
static void delete_one(struct file_struct *f)
|
||||
{
|
||||
if (!S_ISDIR(f->mode)) {
|
||||
if (do_unlink(f_name(f)) != 0) {
|
||||
rprintf(FERROR,"unlink %s : %s\n",f_name(f),strerror(errno));
|
||||
} else if (verbose) {
|
||||
rprintf(FINFO,"deleting %s\n",f_name(f));
|
||||
}
|
||||
} else {
|
||||
if (do_rmdir(f_name(f)) != 0) {
|
||||
if (errno != ENOTEMPTY && errno != EEXIST)
|
||||
rprintf(FERROR,"rmdir %s : %s\n",f_name(f),strerror(errno));
|
||||
} else if (verbose) {
|
||||
rprintf(FINFO,"deleting directory %s\n",f_name(f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* this deletes any files on the receiving side that are not present
|
||||
on the sending side. For version 1.6.4 I have changed the behaviour
|
||||
to match more closely what most people seem to expect of this option */
|
||||
static void delete_files(struct file_list *flist)
|
||||
{
|
||||
struct file_list *local_file_list;
|
||||
int i, j;
|
||||
char *name;
|
||||
|
||||
if (cvs_exclude)
|
||||
add_cvs_excludes();
|
||||
|
||||
if (io_error) {
|
||||
rprintf(FINFO,"IO error encountered - skipping file deletion\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (j=0;j<flist->count;j++) {
|
||||
if (!S_ISDIR(flist->files[j]->mode) ||
|
||||
!(flist->files[j]->flags & FLAG_DELETE)) continue;
|
||||
|
||||
if (remote_version < 19 &&
|
||||
delete_already_done(flist, j)) continue;
|
||||
|
||||
name = strdup(f_name(flist->files[j]));
|
||||
|
||||
if (!(local_file_list = send_file_list(-1,1,&name))) {
|
||||
free(name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO,"deleting in %s\n", name);
|
||||
|
||||
for (i=local_file_list->count-1;i>=0;i--) {
|
||||
if (!local_file_list->files[i]->basename) continue;
|
||||
if (remote_version < 19 &&
|
||||
S_ISDIR(local_file_list->files[i]->mode))
|
||||
add_delete_entry(local_file_list->files[i]);
|
||||
if (-1 == flist_find(flist,local_file_list->files[i])) {
|
||||
delete_one(local_file_list->files[i]);
|
||||
}
|
||||
}
|
||||
flist_free(local_file_list);
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int get_tmpname(char *fnametmp, char *fname)
|
||||
{
|
||||
char *f;
|
||||
|
||||
/* open tmp file */
|
||||
if (tmpdir) {
|
||||
f = strrchr(fname,'/');
|
||||
if (f == NULL)
|
||||
f = fname;
|
||||
else
|
||||
f++;
|
||||
if (strlen(tmpdir)+strlen(f)+10 > MAXPATHLEN) {
|
||||
rprintf(FERROR,"filename too long\n");
|
||||
return 0;
|
||||
}
|
||||
slprintf(fnametmp,MAXPATHLEN-1, "%s/.%s.XXXXXX",tmpdir,f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
f = strrchr(fname,'/');
|
||||
|
||||
if (strlen(fname)+9 > MAXPATHLEN) {
|
||||
rprintf(FERROR,"filename too long\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (f) {
|
||||
*f = 0;
|
||||
slprintf(fnametmp,MAXPATHLEN-1,"%s/.%s.XXXXXX",
|
||||
fname,f+1);
|
||||
*f = '/';
|
||||
} else {
|
||||
slprintf(fnametmp,MAXPATHLEN-1,".%s.XXXXXX",fname);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
|
||||
OFF_T total_size)
|
||||
{
|
||||
int i,n,remainder,len,count;
|
||||
OFF_T offset = 0;
|
||||
OFF_T offset2;
|
||||
char *data;
|
||||
static char file_sum1[MD4_SUM_LENGTH];
|
||||
static char file_sum2[MD4_SUM_LENGTH];
|
||||
char *map=NULL;
|
||||
|
||||
count = read_int(f_in);
|
||||
n = read_int(f_in);
|
||||
remainder = read_int(f_in);
|
||||
|
||||
sum_init();
|
||||
|
||||
for (i=recv_token(f_in,&data); i != 0; i=recv_token(f_in,&data)) {
|
||||
|
||||
show_progress(offset, total_size);
|
||||
|
||||
if (i > 0) {
|
||||
extern int cleanup_got_literal;
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO,"data recv %d at %d\n",
|
||||
i,(int)offset);
|
||||
}
|
||||
|
||||
stats.literal_data += i;
|
||||
cleanup_got_literal = 1;
|
||||
|
||||
sum_update(data,i);
|
||||
|
||||
if (fd != -1 && write_file(fd,data,i) != i) {
|
||||
rprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
offset += i;
|
||||
continue;
|
||||
}
|
||||
|
||||
i = -(i+1);
|
||||
offset2 = i*n;
|
||||
len = n;
|
||||
if (i == count-1 && remainder != 0)
|
||||
len = remainder;
|
||||
|
||||
stats.matched_data += len;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"chunk[%d] of size %d at %d offset=%d\n",
|
||||
i,len,(int)offset2,(int)offset);
|
||||
|
||||
map = map_ptr(buf,offset2,len);
|
||||
|
||||
see_token(map, len);
|
||||
sum_update(map,len);
|
||||
|
||||
if (fd != -1 && write_file(fd,map,len) != len) {
|
||||
rprintf(FERROR,"write failed on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
offset += len;
|
||||
}
|
||||
|
||||
end_progress();
|
||||
|
||||
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
|
||||
rprintf(FERROR,"write failed on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
sum_end(file_sum1);
|
||||
|
||||
if (remote_version >= 14) {
|
||||
read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"got file_sum\n");
|
||||
}
|
||||
if (fd != -1 &&
|
||||
memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
{
|
||||
int fd1,fd2;
|
||||
STRUCT_STAT st;
|
||||
char *fname;
|
||||
char fnametmp[MAXPATHLEN];
|
||||
struct map_struct *buf;
|
||||
int i;
|
||||
struct file_struct *file;
|
||||
int phase=0;
|
||||
int recv_ok;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
|
||||
}
|
||||
|
||||
if (recurse && delete_mode && !local_name && flist->count>0) {
|
||||
delete_files(flist);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
cleanup_disable();
|
||||
|
||||
i = read_int(f_in);
|
||||
if (i == -1) {
|
||||
if (phase==0 && remote_version >= 13) {
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files phase=%d\n",phase);
|
||||
write_int(f_gen,-1);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < 0 || i >= flist->count) {
|
||||
rprintf(FERROR,"Invalid file index %d in recv_files (count=%d)\n",
|
||||
i, flist->count);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
file = flist->files[i];
|
||||
fname = f_name(file);
|
||||
|
||||
stats.num_transferred_files++;
|
||||
stats.total_transferred_size += file->length;
|
||||
|
||||
if (local_name)
|
||||
fname = local_name;
|
||||
|
||||
if (dry_run) {
|
||||
if (!am_server && verbose)
|
||||
rprintf(FINFO,"%s\n",fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files(%s)\n",fname);
|
||||
|
||||
/* open the file */
|
||||
fd1 = open(fname,O_RDONLY);
|
||||
|
||||
if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
|
||||
rprintf(FERROR,"fstat %s : %s\n",fname,strerror(errno));
|
||||
receive_data(f_in,NULL,-1,NULL,file->length);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
|
||||
rprintf(FERROR,"%s : not a regular file (recv_files)\n",fname);
|
||||
receive_data(f_in,NULL,-1,NULL,file->length);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && st.st_size > 0) {
|
||||
buf = map_file(fd1,st.st_size);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv mapped %s of size %d\n",fname,(int)st.st_size);
|
||||
} else {
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (!get_tmpname(fnametmp,fname)) {
|
||||
if (buf) unmap_file(buf);
|
||||
if (fd1 != -1) close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NULL == do_mktemp(fnametmp)) {
|
||||
rprintf(FERROR,"mktemp %s failed\n",fnametmp);
|
||||
receive_data(f_in,buf,-1,NULL,file->length);
|
||||
if (buf) unmap_file(buf);
|
||||
if (fd1 != -1) close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we initially set the perms without the
|
||||
setuid/setgid bits to ensure that there is no race
|
||||
condition. They are then correctly updated after
|
||||
the lchown. Thanks to snabb@epipe.fi for pointing
|
||||
this out */
|
||||
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
|
||||
file->mode & ACCESSPERMS);
|
||||
|
||||
if (fd2 == -1 && relative_paths && errno == ENOENT &&
|
||||
create_directory_path(fnametmp) == 0) {
|
||||
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
|
||||
file->mode & ACCESSPERMS);
|
||||
}
|
||||
if (fd2 == -1) {
|
||||
rprintf(FERROR,"open %s : %s\n",fnametmp,strerror(errno));
|
||||
receive_data(f_in,buf,-1,NULL,file->length);
|
||||
if (buf) unmap_file(buf);
|
||||
if (fd1 != -1) close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
cleanup_set(fnametmp, fname, file, buf, fd1, fd2);
|
||||
|
||||
if (!am_server && verbose)
|
||||
rprintf(FINFO,"%s\n",fname);
|
||||
|
||||
/* recv file data */
|
||||
recv_ok = receive_data(f_in,buf,fd2,fname,file->length);
|
||||
|
||||
if (buf) unmap_file(buf);
|
||||
if (fd1 != -1) {
|
||||
close(fd1);
|
||||
}
|
||||
close(fd2);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
|
||||
|
||||
finish_transfer(fname, fnametmp, file);
|
||||
|
||||
cleanup_disable();
|
||||
|
||||
if (!recv_ok) {
|
||||
if (csum_length == SUM_LENGTH) {
|
||||
rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
|
||||
fname);
|
||||
} else {
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO,"redoing %s(%d)\n",fname,i);
|
||||
write_int(f_gen,i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (preserve_hard_links)
|
||||
do_hard_links(flist);
|
||||
|
||||
/* now we need to fix any directory permissions that were
|
||||
modified during the transfer */
|
||||
for (i = 0; i < flist->count; i++) {
|
||||
file = flist->files[i];
|
||||
if (!file->basename || !S_ISDIR(file->mode)) continue;
|
||||
recv_generator(f_name(file),flist,i,-1);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files finished\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
101
rsync.h
101
rsync.h
@@ -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
|
||||
@@ -91,10 +98,6 @@
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_COMPAT_H
|
||||
#include <compat.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
@@ -166,13 +169,7 @@
|
||||
#include "lib/fnmatch.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
#include <getopt.h>
|
||||
#else
|
||||
#include "lib/getopt.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GLOB
|
||||
#ifdef HAVE_GLOB_H
|
||||
#include <glob.h>
|
||||
#endif
|
||||
|
||||
@@ -187,6 +184,26 @@
|
||||
#include <syslog.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#if HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
#else
|
||||
# define dirent direct
|
||||
# if HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if HAVE_SYS_DIR_H
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if HAVE_NDIR_H
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_COMPAT_H
|
||||
#include <compat.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef S_IFLNK
|
||||
#define S_IFLNK 0120000
|
||||
#endif
|
||||
@@ -242,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
|
||||
@@ -267,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;
|
||||
@@ -280,17 +303,17 @@ struct file_struct {
|
||||
};
|
||||
|
||||
struct file_list {
|
||||
int count;
|
||||
int malloced;
|
||||
struct file_struct **files;
|
||||
int count;
|
||||
int malloced;
|
||||
struct file_struct **files;
|
||||
};
|
||||
|
||||
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 {
|
||||
@@ -316,6 +339,18 @@ struct exclude_struct {
|
||||
int local;
|
||||
};
|
||||
|
||||
struct stats {
|
||||
int64 total_size;
|
||||
int64 total_transferred_size;
|
||||
int64 total_written;
|
||||
int64 total_read;
|
||||
int64 literal_data;
|
||||
int64 matched_data;
|
||||
int flist_size;
|
||||
int num_files;
|
||||
int num_transferred_files;
|
||||
};
|
||||
|
||||
|
||||
/* we need this function because of the silly way in which duplicate
|
||||
entries are handled in the file lists - we can't change this
|
||||
@@ -326,21 +361,6 @@ static inline int flist_up(struct file_list *flist, int i)
|
||||
return i;
|
||||
}
|
||||
|
||||
#if HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
#else
|
||||
# define dirent direct
|
||||
# if HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if HAVE_SYS_DIR_H
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if HAVE_NDIR_H
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "byteorder.h"
|
||||
#include "version.h"
|
||||
#include "proto.h"
|
||||
@@ -360,14 +380,6 @@ extern char *sys_errlist[];
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_BCOPY
|
||||
#define bcopy(src,dest,n) memcpy(dest,src,n)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_BZERO
|
||||
#define bzero(buf,n) memset(buf,0,n)
|
||||
#endif
|
||||
|
||||
#define SUPPORT_LINKS HAVE_READLINK
|
||||
#define SUPPORT_HARD_LINKS HAVE_LINK
|
||||
|
||||
@@ -432,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
|
||||
|
||||
156
rsync.yo
156
rsync.yo
@@ -9,9 +9,9 @@ rsync [options] path [user@]host:path
|
||||
|
||||
rsync [options] path path
|
||||
|
||||
rsync [options] [user@]host::path path
|
||||
rsync [options] [user@]host::module[/path] path
|
||||
|
||||
rsync [options] path [user@]host::path
|
||||
rsync [options] path [user@]host::module[/path]
|
||||
|
||||
manpagedescription()
|
||||
|
||||
@@ -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
|
||||
@@ -217,9 +276,12 @@ explicitly checked on the receiver and any files of the same name
|
||||
which already exist and have the same checksum and size on the
|
||||
receiver are skipped. This option can be quite slow.
|
||||
|
||||
dit(bf(-a, --archive)) This is equivalent to -rlptDog. It is a quick way
|
||||
dit(bf(-a, --archive)) This is equivalent to -rlptDg. It is a quick way
|
||||
of saying I want recursion and want to preserve everything.
|
||||
|
||||
Note: if the user launching rsync is root then the -o option (preserve
|
||||
uid) is also implied.
|
||||
|
||||
dit(bf(-r, --recursive)) This tells rsync to copy directories recursively
|
||||
|
||||
dit(bf(-R, --relative)) Use relative paths. This means that the full path
|
||||
@@ -253,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.
|
||||
@@ -266,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.
|
||||
|
||||
@@ -289,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.
|
||||
@@ -385,7 +462,7 @@ dit(bf(--csum-length LENGTH)) By default the primary checksum used in
|
||||
rsync is a very strong 16 byte MD4 checksum. In most cases you will
|
||||
find that a truncated version of this checksum is quite efficient, and
|
||||
this will decrease the size of the checksum data sent over the link,
|
||||
making things faster.
|
||||
making things faster.
|
||||
|
||||
You can choose the number of bytes in the truncated checksum using the
|
||||
--csum-length option. Any value less than or equal to 16 is valid.
|
||||
@@ -395,6 +472,11 @@ with an incorrect target file. The risk with a value of 16 is
|
||||
microscopic and can be safely ignored (the universe will probably end
|
||||
before it fails) but with smaller values the risk is higher.
|
||||
|
||||
Current versions of rsync actually use an adaptive algorithm for the
|
||||
checksum length by default, using a 16 byte file checksum to determine
|
||||
if a 2nd pass is required with a longer block checksum. Only use this
|
||||
option if you have read the source code and know what you are doing.
|
||||
|
||||
dit(bf(-T, --temp-dir DIR)) This options instructs rsync to use DIR as a
|
||||
scratch directory when creating a temporary copies of the files
|
||||
transferred on the receiving side. The default behavior is to create
|
||||
@@ -422,9 +504,9 @@ option is not specified.
|
||||
If a user or group name does not exist on the destination system then
|
||||
the numeric id from the source system is used instead.
|
||||
|
||||
dit(bf(--timeout)) This option allows you to set a maximum IO timeout in
|
||||
seconds. If no data is transferred for the specified time then rsync
|
||||
will exit. The default is 0, which means no timeout.
|
||||
dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum IO
|
||||
timeout in seconds. If no data is transferred for the specified time
|
||||
then rsync will exit. The default is 0, which means no timeout.
|
||||
|
||||
dit(bf(--daemon)) This tells rsync that it is to run as a rsync
|
||||
daemon. If standard input is a socket then rsync will assume that it
|
||||
@@ -441,6 +523,15 @@ specified.
|
||||
dit(bf(--port PORT)) This specifies an alternate TCP port number to use
|
||||
rather than the default port 873.
|
||||
|
||||
dit(bf(--stats)) This tells rsync to print a verbose set of statistics
|
||||
on the file transfer, allowing you to tell how effective the rsync
|
||||
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)
|
||||
@@ -485,6 +576,9 @@ itemize(
|
||||
it() if the pattern starts with "- " (a minus followed by a space)
|
||||
then it is always considered a exclude pattern, even if specified as
|
||||
part of an include option. The "- " part is discarded before matching.
|
||||
|
||||
it() if the pattern is a single exclamation mark ! then the current
|
||||
exclude list is reset, removing all previous exclude patterns.
|
||||
)
|
||||
|
||||
The +/- rules are most useful in exclude lists, allowing you to have a
|
||||
@@ -500,6 +594,54 @@ 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()
|
||||
|
||||
dit(bf(CVSIGNORE)) The CVSIGNORE environment variable supplements any
|
||||
ignore patterns in .cvsignore files. See the --cvs-exclude option for
|
||||
more details.
|
||||
|
||||
dit(bf(RSYNC_RSH)) The RSYNC_RSH environment variable allows you to
|
||||
override the default shell used as the transport for rsync. This can
|
||||
be used instead of the -e option.
|
||||
|
||||
dit(bf(RSYNC_PASSWORD)) Setting RSYNC_PASSWORD to the required
|
||||
password allows you to run authenticated rsync connections to a rsync
|
||||
daemon without user intervention. Note that this does not supply a
|
||||
password to a shell transport such as ssh.
|
||||
|
||||
dit(bf(USER) or bf(LOGNAME)) The USER or LOGNAME environment variables
|
||||
are used to determine the default username sent to a rsync server.
|
||||
|
||||
dit(bf(HOME)) The HOME environment variable is used to find the users
|
||||
default .cvsignore file.
|
||||
|
||||
enddit()
|
||||
|
||||
manpagefiles()
|
||||
|
||||
/etc/rsyncd.conf
|
||||
|
||||
@@ -91,6 +91,11 @@ support the "max connections" option. The rsync server uses record
|
||||
locking on this file to ensure that the max connections limit is not
|
||||
exceeded. The default is tt(/var/run/rsyncd.lock).
|
||||
|
||||
dit(bf(log file)) The "log file" option tells the rsync daemon to log
|
||||
messages to that file rather than using syslog. This is particularly
|
||||
useful on systems (such as AIX) where syslog() doesn't work for
|
||||
chrooted programs like rsync.
|
||||
|
||||
dit(bf(syslog facility)) The "syslog facility" option allows you to
|
||||
specify the syslog facility name to use when logging messages from the
|
||||
rsync server. You may use any standard syslog facility name which is
|
||||
@@ -225,7 +230,7 @@ connect.
|
||||
|
||||
The default is no "hosts allow" option, which means all hosts can connect.
|
||||
|
||||
dit(bf(hosts allow)) The "hosts deny" option allows you to specify a
|
||||
dit(bf(hosts deny)) The "hosts deny" option allows you to specify a
|
||||
list of patterns that are matched against a connecting clients
|
||||
hostname and IP address. If the pattern matches then the connection is
|
||||
rejected. See the "hosts allow" option for more information.
|
||||
|
||||
220
sender.c
Normal file
220
sender.c
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int remote_version;
|
||||
extern int csum_length;
|
||||
extern struct stats stats;
|
||||
extern int io_error;
|
||||
extern int dry_run;
|
||||
extern int am_server;
|
||||
|
||||
|
||||
/*
|
||||
receive the checksums for a buffer
|
||||
*/
|
||||
static struct sum_struct *receive_sums(int f)
|
||||
{
|
||||
struct sum_struct *s;
|
||||
int i;
|
||||
OFF_T offset = 0;
|
||||
|
||||
s = (struct sum_struct *)malloc(sizeof(*s));
|
||||
if (!s) out_of_memory("receive_sums");
|
||||
|
||||
s->count = read_int(f);
|
||||
s->n = read_int(f);
|
||||
s->remainder = read_int(f);
|
||||
s->sums = NULL;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"count=%d n=%d rem=%d\n",
|
||||
s->count,s->n,s->remainder);
|
||||
|
||||
if (s->count == 0)
|
||||
return(s);
|
||||
|
||||
s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
|
||||
if (!s->sums) out_of_memory("receive_sums");
|
||||
|
||||
for (i=0;i<s->count;i++) {
|
||||
s->sums[i].sum1 = read_int(f);
|
||||
read_buf(f,s->sums[i].sum2,csum_length);
|
||||
|
||||
s->sums[i].offset = offset;
|
||||
s->sums[i].i = i;
|
||||
|
||||
if (i == s->count-1 && s->remainder != 0) {
|
||||
s->sums[i].len = s->remainder;
|
||||
} else {
|
||||
s->sums[i].len = s->n;
|
||||
}
|
||||
offset += s->sums[i].len;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"chunk[%d] len=%d offset=%d sum1=%08x\n",
|
||||
i,s->sums[i].len,(int)s->sums[i].offset,s->sums[i].sum1);
|
||||
}
|
||||
|
||||
s->flength = offset;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
{
|
||||
int fd;
|
||||
struct sum_struct *s;
|
||||
struct map_struct *buf;
|
||||
STRUCT_STAT st;
|
||||
char fname[MAXPATHLEN];
|
||||
int i;
|
||||
struct file_struct *file;
|
||||
int phase = 0;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files starting\n");
|
||||
|
||||
setup_readbuffer(f_in);
|
||||
|
||||
while (1) {
|
||||
int offset=0;
|
||||
|
||||
i = read_int(f_in);
|
||||
if (i == -1) {
|
||||
if (phase==0 && remote_version >= 13) {
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
write_int(f_out,-1);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files phase=%d\n",phase);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < 0 || i >= flist->count) {
|
||||
rprintf(FERROR,"Invalid file index %d (count=%d)\n",
|
||||
i, flist->count);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
file = flist->files[i];
|
||||
|
||||
stats.num_transferred_files++;
|
||||
stats.total_transferred_size += file->length;
|
||||
|
||||
fname[0] = 0;
|
||||
if (file->basedir) {
|
||||
strlcpy(fname,file->basedir,MAXPATHLEN-1);
|
||||
if (strlen(fname) == MAXPATHLEN-1) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR, "send_files failed on long-named directory %s\n",
|
||||
fname);
|
||||
return;
|
||||
}
|
||||
strlcat(fname,"/",MAXPATHLEN-1);
|
||||
offset = strlen(file->basedir)+1;
|
||||
}
|
||||
strlcat(fname,f_name(file),MAXPATHLEN-strlen(fname));
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files(%d,%s)\n",i,fname);
|
||||
|
||||
if (dry_run) {
|
||||
if (!am_server && verbose)
|
||||
rprintf(FINFO,"%s\n",fname);
|
||||
write_int(f_out,i);
|
||||
continue;
|
||||
}
|
||||
|
||||
s = receive_sums(f_in);
|
||||
if (!s) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"receive_sums failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fd = open(fname,O_RDONLY);
|
||||
if (fd == -1) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"send_files failed to open %s: %s\n",
|
||||
fname,strerror(errno));
|
||||
free_sums(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* map the local file */
|
||||
if (do_fstat(fd,&st) != 0) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"fstat failed : %s\n",strerror(errno));
|
||||
free_sums(s);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (st.st_size > 0) {
|
||||
buf = map_file(fd,st.st_size);
|
||||
} else {
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files mapped %s of size %d\n",
|
||||
fname,(int)st.st_size);
|
||||
|
||||
write_int(f_out,i);
|
||||
|
||||
write_int(f_out,s->count);
|
||||
write_int(f_out,s->n);
|
||||
write_int(f_out,s->remainder);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"calling match_sums %s\n",fname);
|
||||
|
||||
if (!am_server && verbose)
|
||||
rprintf(FINFO,"%s\n",fname+offset);
|
||||
|
||||
match_sums(f_out,s,buf,st.st_size);
|
||||
|
||||
if (buf) unmap_file(buf);
|
||||
close(fd);
|
||||
|
||||
free_sums(s);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"sender finished %s\n",fname);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send files finished\n");
|
||||
|
||||
match_report();
|
||||
|
||||
write_int(f_out,-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
48
socket.c
48
socket.c
@@ -54,6 +54,8 @@ int open_socket_out(char *host, int port)
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_nonblocking(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -81,7 +83,7 @@ static int open_socket_in(int type, int port)
|
||||
return -1;
|
||||
}
|
||||
|
||||
bzero((char *)&sock,sizeof(sock));
|
||||
memset((char *)&sock,0,sizeof(sock));
|
||||
memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
|
||||
sock.sin_port = htons(port);
|
||||
sock.sin_family = hp->h_addrtype;
|
||||
@@ -110,9 +112,9 @@ determine if a file descriptor is in fact a socket
|
||||
****************************************************************************/
|
||||
int is_a_socket(int fd)
|
||||
{
|
||||
int v,l;
|
||||
l = sizeof(int);
|
||||
return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
|
||||
int v,l;
|
||||
l = sizeof(int);
|
||||
return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -120,8 +122,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,9 +155,20 @@ 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);
|
||||
|
||||
set_nonblocking(fd);
|
||||
|
||||
_exit(fn(fd));
|
||||
}
|
||||
|
||||
@@ -274,27 +285,30 @@ become a daemon, discarding the controlling terminal
|
||||
****************************************************************************/
|
||||
void become_daemon(void)
|
||||
{
|
||||
if (fork())
|
||||
int i;
|
||||
|
||||
if (fork()) {
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
/* detach from the terminal */
|
||||
#ifdef HAVE_SETSID
|
||||
setsid();
|
||||
#else
|
||||
#ifdef TIOCNOTTY
|
||||
{
|
||||
int i = open("/dev/tty", O_RDWR);
|
||||
if (i >= 0)
|
||||
{
|
||||
ioctl(i, (int) TIOCNOTTY, (char *)0);
|
||||
close(i);
|
||||
}
|
||||
i = open("/dev/tty", O_RDWR);
|
||||
if (i >= 0) {
|
||||
ioctl(i, (int) TIOCNOTTY, (char *)0);
|
||||
close(i);
|
||||
}
|
||||
#endif /* TIOCNOTTY */
|
||||
#endif
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
/* make sure that stdin, stdout an stderr don't stuff things
|
||||
up (library functions, for example) */
|
||||
for (i=0;i<3;i++) {
|
||||
close(i);
|
||||
open("/dev/null", O_RDWR);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
||||
8
test.sh
8
test.sh
@@ -10,6 +10,14 @@
|
||||
#
|
||||
#
|
||||
|
||||
cat <<EOF
|
||||
|
||||
This set of tests is not completely portable. It is intended for developers
|
||||
not for end users. You may experience failures on some platforms that
|
||||
do not indicate a problem with rsync.
|
||||
|
||||
EOF
|
||||
|
||||
export PATH=.:$PATH
|
||||
TMP=/tmp/rsync-test.$$
|
||||
FROM=${TMP}/from
|
||||
|
||||
3
token.c
3
token.c
@@ -366,8 +366,7 @@ recv_deflated_token(int f, char **data)
|
||||
* put the data corresponding to a token that we've just returned
|
||||
* from recv_deflated_token into the decompressor's history buffer.
|
||||
*/
|
||||
void
|
||||
see_deflate_token(char *buf, int len)
|
||||
static void see_deflate_token(char *buf, int len)
|
||||
{
|
||||
int r, blklen;
|
||||
unsigned char hdr[5];
|
||||
|
||||
233
util.c
233
util.c
@@ -24,15 +24,33 @@
|
||||
*/
|
||||
#include "rsync.h"
|
||||
|
||||
int num_waiting(int fd)
|
||||
/****************************************************************************
|
||||
Set a fd into nonblocking mode. Uses POSIX O_NONBLOCK if available,
|
||||
else
|
||||
if SYSV use O_NDELAY
|
||||
if BSD use FNDELAY
|
||||
****************************************************************************/
|
||||
int set_nonblocking(int fd)
|
||||
{
|
||||
int len=0;
|
||||
ioctl(fd,FIONREAD,&len);
|
||||
return(len);
|
||||
int val;
|
||||
#ifdef O_NONBLOCK
|
||||
#define FLAG_TO_SET O_NONBLOCK
|
||||
#else
|
||||
#ifdef SYSV
|
||||
#define FLAG_TO_SET O_NDELAY
|
||||
#else /* BSD */
|
||||
#define FLAG_TO_SET FNDELAY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if((val = fcntl(fd, F_GETFL, 0)) == -1)
|
||||
return -1;
|
||||
val |= FLAG_TO_SET;
|
||||
return fcntl( fd, F_SETFL, val);
|
||||
#undef FLAG_TO_SET
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* this is taken from CVS */
|
||||
int piped_child(char **command,int *f_in,int *f_out)
|
||||
{
|
||||
@@ -80,6 +98,9 @@ int piped_child(char **command,int *f_in,int *f_out)
|
||||
|
||||
*f_in = from_child_pipe[0];
|
||||
*f_out = to_child_pipe[1];
|
||||
|
||||
set_nonblocking(*f_in);
|
||||
set_nonblocking(*f_out);
|
||||
|
||||
return pid;
|
||||
}
|
||||
@@ -206,7 +227,7 @@ int create_directory_path(char *fname)
|
||||
|
||||
derived from GNU C's cccp.c.
|
||||
*/
|
||||
int full_write(int desc, char *ptr, int len)
|
||||
static int full_write(int desc, char *ptr, int len)
|
||||
{
|
||||
int total_written;
|
||||
|
||||
@@ -232,7 +253,7 @@ int full_write(int desc, char *ptr, int len)
|
||||
for an error.
|
||||
|
||||
derived from GNU C's cccp.c. */
|
||||
int safe_read(int desc, char *ptr, int len)
|
||||
static int safe_read(int desc, char *ptr, int len)
|
||||
{
|
||||
int n_chars;
|
||||
|
||||
@@ -273,7 +294,7 @@ int copy_file(char *source, char *dest, mode_t mode)
|
||||
}
|
||||
|
||||
ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
|
||||
if (ofd < 0) {
|
||||
if (ofd == -1) {
|
||||
rprintf(FERROR,"open %s: %s\n",
|
||||
dest,strerror(errno));
|
||||
close(ifd);
|
||||
@@ -389,14 +410,6 @@ int name_to_gid(char *name, gid_t *gid)
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
check if a process exists.
|
||||
****************************************************************************/
|
||||
int process_exists(int pid)
|
||||
{
|
||||
return(kill(pid,0) == 0 || errno != ESRCH);
|
||||
}
|
||||
|
||||
/* lock a byte range in a open file */
|
||||
int lock_range(int fd, int offset, int len)
|
||||
{
|
||||
@@ -414,7 +427,7 @@ int lock_range(int fd, int offset, int len)
|
||||
|
||||
static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
|
||||
{
|
||||
#ifndef HAVE_GLOB
|
||||
#if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
|
||||
if (!*s) s = ".";
|
||||
argv[*argc] = strdup(s);
|
||||
(*argc)++;
|
||||
@@ -553,3 +566,189 @@ int slprintf(char *str, int n, char *format, ...)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void *Realloc(void *p, int size)
|
||||
{
|
||||
if (!p) return (void *)malloc(size);
|
||||
return (void *)realloc(p, size);
|
||||
}
|
||||
|
||||
|
||||
void clean_fname(char *name)
|
||||
{
|
||||
char *p;
|
||||
int l;
|
||||
int modified = 1;
|
||||
|
||||
if (!name) return;
|
||||
|
||||
while (modified) {
|
||||
modified = 0;
|
||||
|
||||
if ((p=strstr(name,"/./"))) {
|
||||
modified = 1;
|
||||
while (*p) {
|
||||
p[0] = p[2];
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((p=strstr(name,"//"))) {
|
||||
modified = 1;
|
||||
while (*p) {
|
||||
p[0] = p[1];
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(p=name,"./",2) == 0) {
|
||||
modified = 1;
|
||||
do {
|
||||
p[0] = p[2];
|
||||
} while (*p++);
|
||||
}
|
||||
|
||||
l = strlen(p=name);
|
||||
if (l > 1 && p[l-1] == '/') {
|
||||
modified = 1;
|
||||
p[l-1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char curr_dir[MAXPATHLEN];
|
||||
|
||||
/* like chdir() but can be reversed with pop_dir() if save is set. It
|
||||
is also much faster as it remembers where we have been */
|
||||
char *push_dir(char *dir, int save)
|
||||
{
|
||||
char *ret = curr_dir;
|
||||
static int initialised;
|
||||
|
||||
if (!initialised) {
|
||||
initialised = 1;
|
||||
getcwd(curr_dir, sizeof(curr_dir)-1);
|
||||
}
|
||||
|
||||
if (chdir(dir)) return NULL;
|
||||
|
||||
if (save) {
|
||||
ret = strdup(curr_dir);
|
||||
}
|
||||
|
||||
if (*dir == '/') {
|
||||
strlcpy(curr_dir, dir, sizeof(curr_dir)-1);
|
||||
} else {
|
||||
strlcat(curr_dir,"/", sizeof(curr_dir)-1);
|
||||
strlcat(curr_dir,dir, sizeof(curr_dir)-1);
|
||||
}
|
||||
|
||||
clean_fname(curr_dir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* reverse a push_dir call */
|
||||
int pop_dir(char *dir)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = chdir(dir);
|
||||
if (ret) {
|
||||
free(dir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
strlcpy(curr_dir, dir, sizeof(curr_dir)-1);
|
||||
|
||||
free(dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* we need to supply our own strcmp function for file list comparisons
|
||||
to ensure that signed/unsigned usage is consistent between machines. */
|
||||
int u_strcmp(const char *cs1, const char *cs2)
|
||||
{
|
||||
const uchar *s1 = (uchar *)cs1;
|
||||
const uchar *s2 = (uchar *)cs2;
|
||||
|
||||
while (*s1 && *s2 && (*s1 == *s2)) {
|
||||
s1++; s2++;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ int r;
|
||||
break;
|
||||
case 3: /* illegal */
|
||||
DUMPBITS(3)
|
||||
s->mode = BAD;
|
||||
s->mode = zBAD;
|
||||
z->msg = (char*)"invalid block type";
|
||||
r = Z_DATA_ERROR;
|
||||
LEAVE
|
||||
@@ -186,7 +186,7 @@ int r;
|
||||
NEEDBITS(32)
|
||||
if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
|
||||
{
|
||||
s->mode = BAD;
|
||||
s->mode = zBAD;
|
||||
z->msg = (char*)"invalid stored block lengths";
|
||||
r = Z_DATA_ERROR;
|
||||
LEAVE
|
||||
@@ -219,7 +219,7 @@ int r;
|
||||
#ifndef PKZIP_BUG_WORKAROUND
|
||||
if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
|
||||
{
|
||||
s->mode = BAD;
|
||||
s->mode = zBAD;
|
||||
z->msg = (char*)"too many length or distance symbols";
|
||||
r = Z_DATA_ERROR;
|
||||
LEAVE
|
||||
@@ -252,7 +252,7 @@ int r;
|
||||
ZFREE(z, s->sub.trees.blens);
|
||||
r = t;
|
||||
if (r == Z_DATA_ERROR)
|
||||
s->mode = BAD;
|
||||
s->mode = zBAD;
|
||||
LEAVE
|
||||
}
|
||||
s->sub.trees.index = 0;
|
||||
@@ -289,7 +289,7 @@ int r;
|
||||
(c == 16 && i < 1))
|
||||
{
|
||||
ZFREE(z, s->sub.trees.blens);
|
||||
s->mode = BAD;
|
||||
s->mode = zBAD;
|
||||
z->msg = (char*)"invalid bit length repeat";
|
||||
r = Z_DATA_ERROR;
|
||||
LEAVE
|
||||
@@ -317,7 +317,7 @@ int r;
|
||||
if (t != Z_OK)
|
||||
{
|
||||
if (t == (uInt)Z_DATA_ERROR)
|
||||
s->mode = BAD;
|
||||
s->mode = zBAD;
|
||||
r = t;
|
||||
LEAVE
|
||||
}
|
||||
@@ -361,7 +361,7 @@ int r;
|
||||
case DONE:
|
||||
r = Z_STREAM_END;
|
||||
LEAVE
|
||||
case BAD:
|
||||
case zBAD:
|
||||
r = Z_DATA_ERROR;
|
||||
LEAVE
|
||||
default:
|
||||
|
||||
@@ -22,7 +22,7 @@ typedef enum {
|
||||
CHECK2, /* two check bytes to go */
|
||||
CHECK1, /* one check byte to go */
|
||||
DONE, /* finished check, done */
|
||||
BAD} /* got an error--stay here */
|
||||
zBAD} /* got an error--stay here */
|
||||
inflate_mode;
|
||||
|
||||
/* inflate private state */
|
||||
@@ -38,7 +38,7 @@ struct internal_state {
|
||||
uLong was; /* computed check value */
|
||||
uLong need; /* stream check value */
|
||||
} check; /* if CHECK, check values to compare */
|
||||
uInt marker; /* if BAD, inflateSync's marker bytes count */
|
||||
uInt marker; /* if zBAD, inflateSync's marker bytes count */
|
||||
} sub; /* submode */
|
||||
|
||||
/* mode independent information */
|
||||
@@ -164,14 +164,14 @@ int f;
|
||||
NEEDBYTE
|
||||
if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
|
||||
{
|
||||
z->state->mode = BAD;
|
||||
z->state->mode = zBAD;
|
||||
z->msg = (char*)"unknown compression method";
|
||||
z->state->sub.marker = 5; /* can't try inflateSync */
|
||||
break;
|
||||
}
|
||||
if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
|
||||
{
|
||||
z->state->mode = BAD;
|
||||
z->state->mode = zBAD;
|
||||
z->msg = (char*)"invalid window size";
|
||||
z->state->sub.marker = 5; /* can't try inflateSync */
|
||||
break;
|
||||
@@ -182,7 +182,7 @@ int f;
|
||||
b = NEXTBYTE;
|
||||
if (((z->state->sub.method << 8) + b) % 31)
|
||||
{
|
||||
z->state->mode = BAD;
|
||||
z->state->mode = zBAD;
|
||||
z->msg = (char*)"incorrect header check";
|
||||
z->state->sub.marker = 5; /* can't try inflateSync */
|
||||
break;
|
||||
@@ -213,7 +213,7 @@ int f;
|
||||
z->state->mode = DICT0;
|
||||
return Z_NEED_DICT;
|
||||
case DICT0:
|
||||
z->state->mode = BAD;
|
||||
z->state->mode = zBAD;
|
||||
z->msg = (char*)"need dictionary";
|
||||
z->state->sub.marker = 0; /* can try inflateSync */
|
||||
return Z_STREAM_ERROR;
|
||||
@@ -221,7 +221,7 @@ int f;
|
||||
r = inflate_blocks(z->state->blocks, z, r);
|
||||
if (r == Z_DATA_ERROR)
|
||||
{
|
||||
z->state->mode = BAD;
|
||||
z->state->mode = zBAD;
|
||||
z->state->sub.marker = 0; /* can try inflateSync */
|
||||
break;
|
||||
}
|
||||
@@ -255,7 +255,7 @@ int f;
|
||||
|
||||
if (z->state->sub.check.was != z->state->sub.check.need)
|
||||
{
|
||||
z->state->mode = BAD;
|
||||
z->state->mode = zBAD;
|
||||
z->msg = (char*)"incorrect data check";
|
||||
z->state->sub.marker = 5; /* can't try inflateSync */
|
||||
break;
|
||||
@@ -264,7 +264,7 @@ int f;
|
||||
z->state->mode = DONE;
|
||||
case DONE:
|
||||
return Z_STREAM_END;
|
||||
case BAD:
|
||||
case zBAD:
|
||||
return Z_DATA_ERROR;
|
||||
default:
|
||||
return Z_STREAM_ERROR;
|
||||
@@ -310,9 +310,9 @@ z_streamp z;
|
||||
/* set up */
|
||||
if (z == Z_NULL || z->state == Z_NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
if (z->state->mode != BAD)
|
||||
if (z->state->mode != zBAD)
|
||||
{
|
||||
z->state->mode = BAD;
|
||||
z->state->mode = zBAD;
|
||||
z->state->sub.marker = 0;
|
||||
}
|
||||
if ((n = z->avail_in) == 0)
|
||||
|
||||
@@ -21,7 +21,7 @@ typedef enum {
|
||||
CODES, /* processing fixed or dynamic block */
|
||||
DRY, /* output remaining window bytes */
|
||||
DONE, /* finished last block, done */
|
||||
BAD} /* got a data error--stuck here */
|
||||
zBAD} /* got a data error--stuck here */
|
||||
inflate_block_mode;
|
||||
|
||||
/* inflate blocks semi-private state */
|
||||
|
||||
Reference in New Issue
Block a user