mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-25 07:15:35 -04:00
Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
@@ -46,7 +46,7 @@ install: all
|
||||
${INSTALLCMD} -m 644 $(srcdir)/rsyncd.conf.5 ${INSTALL_MAN}/man5
|
||||
|
||||
rsync: $(OBJS)
|
||||
$(CC) $(CFLAGS) -o rsync $(OBJS) $(LIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o rsync $(OBJS) $(LIBS)
|
||||
|
||||
rsync.1: rsync.yo
|
||||
yodl2man -o rsync.1 rsync.yo
|
||||
@@ -60,10 +60,3 @@ proto:
|
||||
clean:
|
||||
rm -f *~ $(OBJS) rsync config.cache config.log config.status
|
||||
|
||||
dist:
|
||||
tar --exclude-from .ignore -czf dist.tar.gz .
|
||||
-mkdir rsync-$(VERSION)
|
||||
(cd rsync-$(VERSION) ; tar xzf ../dist.tar.gz)
|
||||
tar -czf rsync-$(VERSION).tar.gz rsync-$(VERSION)
|
||||
rm -f dist.tar.gz
|
||||
echo rsync-$(VERSION) >> .cvsignore
|
||||
|
||||
@@ -7,3 +7,4 @@
|
||||
#undef HAVE_UTIMBUF
|
||||
#undef ino_t
|
||||
#undef HAVE_CONNECT
|
||||
#undef HAVE_SHORT_INO_T
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -118,6 +118,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 +133,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 +252,7 @@ static int rsync_module(int fd, int i)
|
||||
}
|
||||
}
|
||||
|
||||
parse_arguments(argc, argv);
|
||||
ret = parse_arguments(argc, argv);
|
||||
|
||||
if (request) {
|
||||
if (*user) {
|
||||
@@ -269,6 +277,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 +375,21 @@ 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
12
configure.in
12
configure.in
@@ -40,8 +40,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)
|
||||
AC_CHECK_FUNCS(memmove getopt_long lchown vsnprintf setsid glob strpbrk)
|
||||
|
||||
echo $ac_n "checking for working fnmatch... $ac_c"
|
||||
AC_TRY_RUN([#include <fnmatch.h>
|
||||
@@ -62,6 +62,14 @@ main() { struct stat64 st; off64_t s; if (sizeof(off_t) == sizeof(off64_t)) retu
|
||||
echo yes;AC_DEFINE(HAVE_OFF64_T),
|
||||
echo no)
|
||||
|
||||
echo $ac_n "checking for short ino_t ... $ac_c"
|
||||
AC_TRY_RUN([#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
main() { if (sizeof(ino_t) < sizeof(unsigned int)) return 0; return 1; }],
|
||||
echo yes;AC_DEFINE(HAVE_SHORT_INO_T),
|
||||
echo no)
|
||||
|
||||
echo $ac_n "checking for unsigned char ... $ac_c"
|
||||
AC_TRY_RUN([#include <stdio.h>
|
||||
main() { char c; c=250; exit((c > 0)?0:1); }],
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
394
flist.c
394
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;
|
||||
|
||||
@@ -90,141 +91,98 @@ static void send_directory(int f,struct file_list *flist,char *dir);
|
||||
|
||||
static char *flist_dir;
|
||||
|
||||
static 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
|
||||
{
|
||||
unsigned char flags;
|
||||
static time_t last_time;
|
||||
static mode_t last_mode;
|
||||
static dev_t last_rdev;
|
||||
static uid_t last_uid;
|
||||
static gid_t last_gid;
|
||||
static char lastname[MAXPATHLEN];
|
||||
char *fname;
|
||||
int l1,l2;
|
||||
unsigned char flags;
|
||||
static time_t last_time;
|
||||
static mode_t last_mode;
|
||||
static dev_t last_rdev;
|
||||
static uid_t last_uid;
|
||||
static gid_t last_gid;
|
||||
static char lastname[MAXPATHLEN];
|
||||
char *fname;
|
||||
int l1,l2;
|
||||
|
||||
if (f == -1) return;
|
||||
if (f == -1) return;
|
||||
|
||||
if (!file) {
|
||||
write_byte(f,0);
|
||||
return;
|
||||
}
|
||||
if (!file) {
|
||||
write_byte(f,0);
|
||||
return;
|
||||
}
|
||||
|
||||
fname = f_name(file);
|
||||
fname = f_name(file);
|
||||
|
||||
flags = base_flags;
|
||||
flags = base_flags;
|
||||
|
||||
if (file->mode == last_mode) flags |= SAME_MODE;
|
||||
if (file->rdev == last_rdev) flags |= SAME_RDEV;
|
||||
if (file->uid == last_uid) flags |= SAME_UID;
|
||||
if (file->gid == last_gid) flags |= SAME_GID;
|
||||
if (file->modtime == last_time) flags |= SAME_TIME;
|
||||
if (file->mode == last_mode) flags |= SAME_MODE;
|
||||
if (file->rdev == last_rdev) flags |= SAME_RDEV;
|
||||
if (file->uid == last_uid) flags |= SAME_UID;
|
||||
if (file->gid == last_gid) flags |= SAME_GID;
|
||||
if (file->modtime == last_time) flags |= SAME_TIME;
|
||||
|
||||
for (l1=0;lastname[l1] && (fname[l1] == lastname[l1]) && (l1 < 255);l1++) ;
|
||||
l2 = strlen(fname) - l1;
|
||||
for (l1=0;lastname[l1] && (fname[l1] == lastname[l1]) && (l1 < 255);l1++) ;
|
||||
l2 = strlen(fname) - l1;
|
||||
|
||||
if (l1 > 0) flags |= SAME_NAME;
|
||||
if (l2 > 255) flags |= LONG_NAME;
|
||||
if (l1 > 0) flags |= SAME_NAME;
|
||||
if (l2 > 255) flags |= LONG_NAME;
|
||||
|
||||
/* we must make sure we don't send a zero flags byte or the other
|
||||
end will terminate the flist transfer */
|
||||
if (flags == 0 && !S_ISDIR(file->mode)) flags |= FLAG_DELETE;
|
||||
if (flags == 0) flags |= LONG_NAME;
|
||||
/* we must make sure we don't send a zero flags byte or the other
|
||||
end will terminate the flist transfer */
|
||||
if (flags == 0 && !S_ISDIR(file->mode)) flags |= FLAG_DELETE;
|
||||
if (flags == 0) flags |= LONG_NAME;
|
||||
|
||||
write_byte(f,flags);
|
||||
if (flags & SAME_NAME)
|
||||
write_byte(f,l1);
|
||||
if (flags & LONG_NAME)
|
||||
write_int(f,l2);
|
||||
else
|
||||
write_byte(f,l2);
|
||||
write_buf(f,fname+l1,l2);
|
||||
write_byte(f,flags);
|
||||
if (flags & SAME_NAME)
|
||||
write_byte(f,l1);
|
||||
if (flags & LONG_NAME)
|
||||
write_int(f,l2);
|
||||
else
|
||||
write_byte(f,l2);
|
||||
write_buf(f,fname+l1,l2);
|
||||
|
||||
write_longint(f,file->length);
|
||||
if (!(flags & SAME_TIME))
|
||||
write_int(f,(int)file->modtime);
|
||||
if (!(flags & SAME_MODE))
|
||||
write_int(f,(int)file->mode);
|
||||
if (preserve_uid && !(flags & SAME_UID)) {
|
||||
add_uid(file->uid);
|
||||
write_int(f,(int)file->uid);
|
||||
}
|
||||
if (preserve_gid && !(flags & SAME_GID)) {
|
||||
add_gid(file->gid);
|
||||
write_int(f,(int)file->gid);
|
||||
}
|
||||
if (preserve_devices && IS_DEVICE(file->mode) && !(flags & SAME_RDEV))
|
||||
write_int(f,(int)file->rdev);
|
||||
write_longint(f,file->length);
|
||||
if (!(flags & SAME_TIME))
|
||||
write_int(f,(int)file->modtime);
|
||||
if (!(flags & SAME_MODE))
|
||||
write_int(f,(int)file->mode);
|
||||
if (preserve_uid && !(flags & SAME_UID)) {
|
||||
add_uid(file->uid);
|
||||
write_int(f,(int)file->uid);
|
||||
}
|
||||
if (preserve_gid && !(flags & SAME_GID)) {
|
||||
add_gid(file->gid);
|
||||
write_int(f,(int)file->gid);
|
||||
}
|
||||
if (preserve_devices && IS_DEVICE(file->mode) && !(flags & SAME_RDEV))
|
||||
write_int(f,(int)file->rdev);
|
||||
|
||||
#if SUPPORT_LINKS
|
||||
if (preserve_links && S_ISLNK(file->mode)) {
|
||||
write_int(f,strlen(file->link));
|
||||
write_buf(f,file->link,strlen(file->link));
|
||||
}
|
||||
if (preserve_links && S_ISLNK(file->mode)) {
|
||||
write_int(f,strlen(file->link));
|
||||
write_buf(f,file->link,strlen(file->link));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SUPPORT_HARD_LINKS
|
||||
if (preserve_hard_links && S_ISREG(file->mode)) {
|
||||
write_int(f,(int)file->dev);
|
||||
write_int(f,(int)file->inode);
|
||||
}
|
||||
if (preserve_hard_links && S_ISREG(file->mode)) {
|
||||
write_int(f,(int)file->dev);
|
||||
write_int(f,(int)file->inode);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (always_checksum) {
|
||||
write_buf(f,file->sum,csum_length);
|
||||
}
|
||||
if (always_checksum) {
|
||||
write_buf(f,file->sum,csum_length);
|
||||
}
|
||||
|
||||
last_mode = file->mode;
|
||||
last_rdev = file->rdev;
|
||||
last_uid = file->uid;
|
||||
last_gid = file->gid;
|
||||
last_time = file->modtime;
|
||||
last_mode = file->mode;
|
||||
last_rdev = file->rdev;
|
||||
last_uid = file->uid;
|
||||
last_gid = file->gid;
|
||||
last_time = file->modtime;
|
||||
|
||||
strlcpy(lastname,fname,MAXPATHLEN-1);
|
||||
lastname[MAXPATHLEN-1] = 0;
|
||||
strlcpy(lastname,fname,MAXPATHLEN-1);
|
||||
lastname[MAXPATHLEN-1] = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -232,101 +190,108 @@ void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
|
||||
static void receive_file_entry(struct file_struct **fptr,
|
||||
unsigned flags,int f)
|
||||
{
|
||||
static time_t last_time;
|
||||
static mode_t last_mode;
|
||||
static dev_t last_rdev;
|
||||
static uid_t last_uid;
|
||||
static gid_t last_gid;
|
||||
static char lastname[MAXPATHLEN];
|
||||
char thisname[MAXPATHLEN];
|
||||
int l1=0,l2=0;
|
||||
char *p;
|
||||
struct file_struct *file;
|
||||
static time_t last_time;
|
||||
static mode_t last_mode;
|
||||
static dev_t last_rdev;
|
||||
static uid_t last_uid;
|
||||
static gid_t last_gid;
|
||||
static char lastname[MAXPATHLEN];
|
||||
char thisname[MAXPATHLEN];
|
||||
int l1=0,l2=0;
|
||||
char *p;
|
||||
struct file_struct *file;
|
||||
|
||||
if (flags & SAME_NAME)
|
||||
l1 = read_byte(f);
|
||||
if (flags & SAME_NAME)
|
||||
l1 = read_byte(f);
|
||||
|
||||
if (flags & LONG_NAME)
|
||||
l2 = read_int(f);
|
||||
else
|
||||
l2 = read_byte(f);
|
||||
if (flags & LONG_NAME)
|
||||
l2 = read_int(f);
|
||||
else
|
||||
l2 = read_byte(f);
|
||||
|
||||
file = (struct file_struct *)malloc(sizeof(*file));
|
||||
if (!file) out_of_memory("receive_file_entry");
|
||||
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 (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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -367,7 +332,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;
|
||||
@@ -394,7 +359,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;
|
||||
@@ -464,7 +429,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;
|
||||
}
|
||||
@@ -566,15 +531,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");
|
||||
|
||||
@@ -646,24 +613,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;
|
||||
@@ -696,6 +662,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)
|
||||
@@ -709,12 +677,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;
|
||||
@@ -745,7 +716,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++;
|
||||
|
||||
@@ -776,6 +747,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:
|
||||
@@ -790,8 +764,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));
|
||||
}
|
||||
|
||||
|
||||
@@ -827,7 +801,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));
|
||||
}
|
||||
|
||||
|
||||
@@ -841,9 +815,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);
|
||||
}
|
||||
|
||||
|
||||
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]),
|
||||
|
||||
90
io.c
90
io.c
@@ -24,8 +24,8 @@
|
||||
*/
|
||||
#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;
|
||||
@@ -35,17 +35,7 @@ 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;
|
||||
|
||||
@@ -67,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);
|
||||
}
|
||||
@@ -79,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
|
||||
@@ -87,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;
|
||||
@@ -95,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;
|
||||
}
|
||||
@@ -107,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;
|
||||
@@ -119,9 +113,18 @@ 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) {
|
||||
if (eof_error) {
|
||||
rprintf(FERROR,"EOF in read_timeout\n");
|
||||
rprintf(FERROR,"unexpected EOF in read_timeout\n");
|
||||
}
|
||||
exit_cleanup(1);
|
||||
}
|
||||
@@ -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,63 @@ 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 &&
|
||||
read_buffer_len < MAX_READ_BUFFER);
|
||||
}
|
||||
|
||||
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 +414,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 +460,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,13 +477,11 @@ 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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -329,7 +329,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);
|
||||
}
|
||||
|
||||
|
||||
9
log.c
9
log.c
@@ -28,6 +28,7 @@ void log_open(void)
|
||||
{
|
||||
static int initialised;
|
||||
int options = LOG_PID;
|
||||
time_t t;
|
||||
|
||||
if (initialised) return;
|
||||
initialised = 1;
|
||||
@@ -45,6 +46,12 @@ void log_open(void)
|
||||
#ifndef LOG_NDELAY
|
||||
syslog(LOG_INFO,"rsyncd started\n");
|
||||
#endif
|
||||
|
||||
/* this looks pointless, but it is needed in order for the
|
||||
C library on some systems to fetch the timezone info
|
||||
before the chroot */
|
||||
t = time(NULL);
|
||||
localtime(&t);
|
||||
}
|
||||
|
||||
|
||||
@@ -102,6 +109,8 @@ void rprintf(int fd, const char *format, ...)
|
||||
|
||||
if (fwrite(buf, len, 1, f) != 1) exit_cleanup(1);
|
||||
|
||||
if (buf[len-1] == '\r' || buf[len-1] == '\n') fflush(f);
|
||||
|
||||
depth--;
|
||||
}
|
||||
|
||||
|
||||
144
main.c
144
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--;
|
||||
@@ -224,6 +255,10 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
|
||||
exit_cleanup(0);
|
||||
}
|
||||
|
||||
set_nonblocking(f_out);
|
||||
if (f_in != f_out)
|
||||
set_nonblocking(f_in);
|
||||
|
||||
send_files(flist,f_out,f_in);
|
||||
report(f_out);
|
||||
io_flush();
|
||||
@@ -252,12 +287,11 @@ 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);
|
||||
|
||||
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 +299,11 @@ 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);
|
||||
|
||||
io_start_buffering(f_out);
|
||||
|
||||
generate_files(f_out,flist,local_name,recv_pipe[0]);
|
||||
|
||||
io_flush();
|
||||
@@ -289,8 +328,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);
|
||||
}
|
||||
@@ -355,6 +394,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 +432,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 +481,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,12 +529,12 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -497,6 +555,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 +566,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);
|
||||
}
|
||||
|
||||
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=PATTERN exclude files listed in FILE\n");
|
||||
rprintf(F," --include=PATTERN don't exclude file FILE\n");
|
||||
rprintf(F," --include-from=PATTERN 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," --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.14
|
||||
Version: 2.1.0
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.0.14.tar.gz
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.1.0.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
99
rsync.h
99
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,12 +169,6 @@
|
||||
#include "lib/fnmatch.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
#include <getopt.h>
|
||||
#else
|
||||
#include "lib/getopt.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GLOB
|
||||
#include <glob.h>
|
||||
#endif
|
||||
@@ -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
|
||||
|
||||
152
rsync.yo
152
rsync.yo
@@ -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
|
||||
|
||||
@@ -225,7 +225,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.
|
||||
|
||||
38
socket.c
38
socket.c
@@ -81,7 +81,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;
|
||||
@@ -120,8 +120,6 @@ void start_accept_loop(int port, int (*fn)(int ))
|
||||
{
|
||||
int s;
|
||||
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
|
||||
/* open an incoming socket */
|
||||
s = open_socket_in(SOCK_STREAM, port);
|
||||
if (s == -1)
|
||||
@@ -155,6 +153,15 @@ void start_accept_loop(int port, int (*fn)(int ))
|
||||
|
||||
if (fd == -1) continue;
|
||||
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
|
||||
/* we shouldn't have any children left hanging around
|
||||
but I have had reports that on Digital Unix zombies
|
||||
are produced, so this ensures that they are reaped */
|
||||
#ifdef WNOHANG
|
||||
waitpid(-1, NULL, WNOHANG);
|
||||
#endif
|
||||
|
||||
if (fork()==0) {
|
||||
close(s);
|
||||
|
||||
@@ -274,27 +281,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
|
||||
|
||||
212
util.c
212
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)
|
||||
{
|
||||
@@ -206,7 +224,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;
|
||||
|
||||
@@ -273,7 +291,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);
|
||||
@@ -559,3 +577,183 @@ 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