mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-25 15:25:30 -04:00
Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
143384f367 | ||
|
|
8c3b04730b | ||
|
|
aa9b77a56c | ||
|
|
b72f24c719 | ||
|
|
a800434a82 | ||
|
|
3b3c3d4390 | ||
|
|
d846b09874 | ||
|
|
1d3754aede | ||
|
|
e44f9a12c4 | ||
|
|
5243c216d6 | ||
|
|
79a51e7ee6 | ||
|
|
cad2bba7d8 | ||
|
|
fe8c0a9824 | ||
|
|
6cdc6b1344 | ||
|
|
05848a2cc7 | ||
|
|
528bfcd79a | ||
|
|
a1e13a937c | ||
|
|
e3fe383aaa | ||
|
|
43bd68e5dd | ||
|
|
ea2111d10a | ||
|
|
4c36ddbeec | ||
|
|
2b6b4d539b | ||
|
|
35f69d8ad9 | ||
|
|
7b1ce0d746 | ||
|
|
54816348d1 | ||
|
|
49d11b78c1 | ||
|
|
bb0f7089fe | ||
|
|
1ff5450d31 | ||
|
|
2f7512b006 | ||
|
|
943882a289 | ||
|
|
6c82f74b6f | ||
|
|
8a5b8b263b | ||
|
|
d47a7fcf0f | ||
|
|
e24c850818 | ||
|
|
6c612747e3 | ||
|
|
505c7ea2bc | ||
|
|
9add51f18e | ||
|
|
f7bd44eb32 | ||
|
|
e3ac52f2e1 | ||
|
|
06e27ef78e | ||
|
|
23e43fceeb | ||
|
|
f900f5fe71 | ||
|
|
db199cfae0 | ||
|
|
5914bf15d2 | ||
|
|
45f133b976 | ||
|
|
c5eb365011 | ||
|
|
2f326946a1 | ||
|
|
754d120c98 | ||
|
|
8e9871303b | ||
|
|
de5fb3744d |
@@ -20,11 +20,14 @@ SHELL=/bin/sh
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
LIBOBJ=lib/getopt.o lib/fnmatch.o lib/zlib.o lib/compat.o
|
||||
LIBOBJ=lib/getopt.o lib/fnmatch.o lib/compat.o
|
||||
ZLIBOBJ=zlib/deflate.o zlib/infblock.o zlib/infcodes.o zlib/inffast.o \
|
||||
zlib/inflate.o zlib/inftrees.o zlib/infutil.o zlib/trees.o \
|
||||
zlib/zutil.o zlib/adler32.o
|
||||
OBJS1=rsync.o exclude.o util.o md4.o main.o checksum.o match.o syscall.o log.o
|
||||
OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o
|
||||
OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o fileio.o
|
||||
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
|
||||
OBJS=$(OBJS1) $(OBJS2) $(DAEMON_OBJ) $(LIBOBJ)
|
||||
OBJS=$(OBJS1) $(OBJS2) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ)
|
||||
|
||||
# note that the -I. is needed to handle config.h when using VPATH
|
||||
.c.o:
|
||||
|
||||
2
access.c
2
access.c
@@ -34,7 +34,7 @@ static int match_hostname(char *host, char *tok)
|
||||
static int match_address(char *addr, char *tok)
|
||||
{
|
||||
char *p;
|
||||
unsigned long a, t, mask = ~0;
|
||||
unsigned long a, t, mask = (unsigned long)~0;
|
||||
|
||||
if (!addr || !*addr) return 0;
|
||||
|
||||
|
||||
@@ -121,6 +121,7 @@ static int rsync_module(int fd, int i)
|
||||
char *request=NULL;
|
||||
extern int am_sender;
|
||||
extern int remote_version;
|
||||
extern int am_root;
|
||||
|
||||
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
|
||||
rprintf(FERROR,"rsync denied on module %s from %s (%s)\n",
|
||||
@@ -173,7 +174,7 @@ static int rsync_module(int fd, int i)
|
||||
}
|
||||
|
||||
p = lp_exclude_from(i);
|
||||
add_exclude_file(p, 1);
|
||||
add_exclude_file(p, 1, 0);
|
||||
|
||||
p = lp_exclude(i);
|
||||
add_exclude_line(p);
|
||||
@@ -204,6 +205,8 @@ static int rsync_module(int fd, int i)
|
||||
return -1;
|
||||
}
|
||||
|
||||
am_root = (getuid() == 0);
|
||||
|
||||
io_printf(fd,"@RSYNCD: OK\n");
|
||||
|
||||
argv[argc++] = "rsyncd";
|
||||
@@ -359,6 +362,11 @@ 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 */
|
||||
return start_daemon(STDIN_FILENO);
|
||||
|
||||
2
compat.c
2
compat.c
@@ -44,10 +44,8 @@ void setup_protocol(int f_out,int f_in)
|
||||
if (am_server) {
|
||||
remote_version = read_int(f_in);
|
||||
write_int(f_out,PROTOCOL_VERSION);
|
||||
write_flush(f_out);
|
||||
} else {
|
||||
write_int(f_out,PROTOCOL_VERSION);
|
||||
write_flush(f_out);
|
||||
remote_version = read_int(f_in);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,11 +38,10 @@ echo yes; AC_DEFINE(HAVE_ERRNO_DECL),
|
||||
echo no)
|
||||
|
||||
AC_FUNC_MEMCMP
|
||||
AC_FUNC_MMAP
|
||||
AC_FUNC_UTIME_NULL
|
||||
AC_CHECK_FUNCS(waitpid strtok pipe getcwd mkdir strdup strerror chown chmod mknod)
|
||||
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)
|
||||
AC_CHECK_FUNCS(memmove getopt_long lchown setlinebuf vsnprintf setsid glob strpbrk)
|
||||
|
||||
echo $ac_n "checking for working fnmatch... $ac_c"
|
||||
AC_TRY_RUN([#include <fnmatch.h>
|
||||
@@ -117,4 +116,4 @@ if test "$ac_cv_lib_socket_connect" = "yes" ||
|
||||
fi])
|
||||
|
||||
|
||||
AC_OUTPUT(Makefile lib/dummy)
|
||||
AC_OUTPUT(Makefile lib/dummy zlib/dummy)
|
||||
|
||||
325
exclude.c
325
exclude.c
@@ -17,160 +17,229 @@
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
a lot of this stuff was derived from GNU tar
|
||||
*/
|
||||
/* a lot of this stuff was originally derived from GNU tar, although
|
||||
it has now changed so much that it is hard to tell :) */
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
|
||||
static char **exclude_list;
|
||||
static struct exclude_struct **exclude_list;
|
||||
|
||||
static int is_regex(char *str)
|
||||
/* build an exclude structure given a exclude pattern */
|
||||
static struct exclude_struct *make_exclude(char *pattern, int include)
|
||||
{
|
||||
return strchr(str, '*') || strchr(str, '[') || strchr(str, '?');
|
||||
struct exclude_struct *ret;
|
||||
|
||||
ret = (struct exclude_struct *)malloc(sizeof(*ret));
|
||||
if (!ret) out_of_memory("make_exclude");
|
||||
|
||||
memset(ret, 0, sizeof(*ret));
|
||||
|
||||
ret->orig = strdup(pattern);
|
||||
|
||||
if (strncmp(pattern,"- ",2) == 0) {
|
||||
pattern += 2;
|
||||
} else if (strncmp(pattern,"+ ",2) == 0) {
|
||||
ret->include = 1;
|
||||
pattern += 2;
|
||||
} else {
|
||||
ret->include = include;
|
||||
}
|
||||
|
||||
ret->pattern = strdup(pattern);
|
||||
|
||||
if (!ret->orig || !ret->pattern) out_of_memory("make_exclude");
|
||||
|
||||
if (strpbrk(pattern, "*[?")) ret->regular_exp = 1;
|
||||
|
||||
if (strlen(pattern) > 1 && pattern[strlen(pattern)-1] == '/') {
|
||||
ret->pattern[strlen(pattern)-1] = 0;
|
||||
ret->directory = 1;
|
||||
}
|
||||
|
||||
if (!strchr(ret->pattern,'/')) {
|
||||
ret->local = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void free_exclude(struct exclude_struct *ex)
|
||||
{
|
||||
free(ex->orig);
|
||||
free(ex->pattern);
|
||||
memset(ex,0,sizeof(*ex));
|
||||
free(ex);
|
||||
}
|
||||
|
||||
static int check_one_exclude(char *name,struct exclude_struct *ex,
|
||||
STRUCT_STAT *st)
|
||||
{
|
||||
char *p;
|
||||
int match_start=0;
|
||||
char *pattern = ex->pattern;
|
||||
|
||||
if (ex->local && (p=strrchr(name,'/')))
|
||||
name = p+1;
|
||||
|
||||
if (!name[0]) return 0;
|
||||
|
||||
if (ex->directory && !S_ISDIR(st->st_mode)) return 0;
|
||||
|
||||
if (*pattern == '/' && *name != '/') {
|
||||
match_start = 1;
|
||||
pattern++;
|
||||
}
|
||||
|
||||
if (ex->regular_exp) {
|
||||
if (fnmatch(pattern, name, 0) == 0)
|
||||
return 1;
|
||||
} else {
|
||||
int l1 = strlen(name);
|
||||
int l2 = strlen(pattern);
|
||||
if (l2 <= l1 &&
|
||||
strcmp(name+(l1-l2),pattern) == 0 &&
|
||||
(l1==l2 || (!match_start && name[l1-(l2+1)] == '/')))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int check_one_exclude(char *name,char *pattern)
|
||||
int check_exclude(char *name,struct exclude_struct **local_exclude_list,
|
||||
STRUCT_STAT *st)
|
||||
{
|
||||
char *p;
|
||||
int n;
|
||||
|
||||
if (!strchr(pattern,'/') && (p=strrchr(name,'/')))
|
||||
name = p+1;
|
||||
if (exclude_list) {
|
||||
for (n=0; exclude_list[n]; n++)
|
||||
if (check_one_exclude(name,exclude_list[n],st))
|
||||
return !exclude_list[n]->include;
|
||||
}
|
||||
|
||||
if (!name[0]) return 0;
|
||||
if (local_exclude_list) {
|
||||
for (n=0; local_exclude_list[n]; n++)
|
||||
if (check_one_exclude(name,local_exclude_list[n],st))
|
||||
return !local_exclude_list[n]->include;
|
||||
}
|
||||
|
||||
if (*pattern == '/' && *name != '/') pattern++;
|
||||
|
||||
if (is_regex(pattern)) {
|
||||
if (fnmatch(pattern, name, 0) == 0)
|
||||
return 1;
|
||||
} else {
|
||||
int l1 = strlen(name);
|
||||
int l2 = strlen(pattern);
|
||||
if (l2 <= l1 &&
|
||||
strcmp(name+(l1-l2),pattern) == 0 &&
|
||||
(l1==l2 || name[l1-(l2+1)] == '/'))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int check_exclude(char *name,char **local_exclude_list)
|
||||
void add_exclude_list(char *pattern,struct exclude_struct ***list, int include)
|
||||
{
|
||||
int n;
|
||||
int len=0;
|
||||
if (list && *list)
|
||||
for (; (*list)[len]; len++) ;
|
||||
|
||||
if (exclude_list) {
|
||||
for (n=0; exclude_list[n]; n++)
|
||||
if (check_one_exclude(name,exclude_list[n]))
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(pattern,"!") == 0) {
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"clearing exclude list\n");
|
||||
while ((len)--) {
|
||||
free_exclude((*list)[len]);
|
||||
}
|
||||
free((*list));
|
||||
*list = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (local_exclude_list) {
|
||||
for (n=0; local_exclude_list[n]; n++)
|
||||
if (check_one_exclude(name,local_exclude_list[n]))
|
||||
return 1;
|
||||
}
|
||||
*list = (struct exclude_struct **)Realloc(*list,sizeof(struct exclude_struct *)*(len+2));
|
||||
|
||||
if (!*list || !((*list)[len] = make_exclude(pattern, include)))
|
||||
out_of_memory("add_exclude");
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"add_exclude(%s)\n",pattern);
|
||||
|
||||
(*list)[len+1] = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
void add_exclude(char *pattern, int include)
|
||||
{
|
||||
add_exclude_list(pattern,&exclude_list, include);
|
||||
}
|
||||
|
||||
struct exclude_struct **make_exclude_list(char *fname,
|
||||
struct exclude_struct **list1,
|
||||
int fatal, int include)
|
||||
{
|
||||
struct exclude_struct **list=list1;
|
||||
FILE *f = fopen(fname,"r");
|
||||
char line[MAXPATHLEN];
|
||||
if (!f) {
|
||||
if (fatal) {
|
||||
rprintf(FERROR,"%s : %s\n",fname,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
while (fgets(line,MAXPATHLEN,f)) {
|
||||
int l = strlen(line);
|
||||
if (l && line[l-1] == '\n') l--;
|
||||
line[l] = 0;
|
||||
if (line[0]) add_exclude_list(line,&list,include);
|
||||
}
|
||||
fclose(f);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
void add_exclude_list(char *pattern,char ***list)
|
||||
{
|
||||
int len=0;
|
||||
if (list && *list)
|
||||
for (; (*list)[len]; len++) ;
|
||||
|
||||
if (strcmp(pattern,"!") == 0) {
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"clearing exclude list\n");
|
||||
while ((len)--)
|
||||
free((*list)[len]);
|
||||
free((*list));
|
||||
*list = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!*list) {
|
||||
*list = (char **)malloc(sizeof(char *)*2);
|
||||
} else {
|
||||
*list = (char **)realloc(*list,sizeof(char *)*(len+2));
|
||||
}
|
||||
|
||||
if (!*list || !((*list)[len] = strdup(pattern)))
|
||||
out_of_memory("add_exclude");
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"add_exclude(%s)\n",pattern);
|
||||
|
||||
(*list)[len+1] = NULL;
|
||||
}
|
||||
|
||||
void add_exclude(char *pattern)
|
||||
{
|
||||
add_exclude_list(pattern,&exclude_list);
|
||||
}
|
||||
|
||||
char **make_exclude_list(char *fname,char **list1,int fatal)
|
||||
{
|
||||
char **list=list1;
|
||||
FILE *f = fopen(fname,"r");
|
||||
char line[MAXPATHLEN];
|
||||
if (!f) {
|
||||
if (fatal) {
|
||||
rprintf(FERROR,"%s : %s\n",fname,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
while (fgets(line,MAXPATHLEN,f)) {
|
||||
int l = strlen(line);
|
||||
if (l && line[l-1] == '\n') l--;
|
||||
line[l] = 0;
|
||||
if (line[0]) add_exclude_list(line,&list);
|
||||
}
|
||||
fclose(f);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
void add_exclude_file(char *fname,int fatal)
|
||||
void add_exclude_file(char *fname,int fatal,int include)
|
||||
{
|
||||
if (!fname || !*fname) return;
|
||||
|
||||
exclude_list = make_exclude_list(fname,exclude_list,fatal);
|
||||
exclude_list = make_exclude_list(fname,exclude_list,fatal,include);
|
||||
}
|
||||
|
||||
|
||||
void send_exclude_list(int f)
|
||||
{
|
||||
int i;
|
||||
if (exclude_list)
|
||||
for (i=0;exclude_list[i];i++) {
|
||||
int l = strlen(exclude_list[i]);
|
||||
if (l == 0) continue;
|
||||
write_int(f,l);
|
||||
write_buf(f,exclude_list[i],l);
|
||||
}
|
||||
write_int(f,0);
|
||||
int i;
|
||||
extern int remote_version;
|
||||
|
||||
if (!exclude_list) {
|
||||
write_int(f,0);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0;exclude_list[i];i++) {
|
||||
char *pattern = exclude_list[i]->orig;
|
||||
int l;
|
||||
|
||||
if (remote_version < 19) {
|
||||
if (strncmp(pattern,"+ ", 2)==0) {
|
||||
rprintf(FERROR,"remote rsync does not support include syntax - aborting\n");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
if (strncmp(pattern,"- ", 2) == 0) {
|
||||
pattern += 2;
|
||||
}
|
||||
}
|
||||
|
||||
l = strlen(pattern);
|
||||
if (l == 0) continue;
|
||||
write_int(f,l);
|
||||
write_buf(f,pattern,l);
|
||||
}
|
||||
|
||||
write_int(f,0);
|
||||
}
|
||||
|
||||
|
||||
void recv_exclude_list(int f)
|
||||
{
|
||||
char line[MAXPATHLEN];
|
||||
int l;
|
||||
while ((l=read_int(f))) {
|
||||
if (l >= MAXPATHLEN) overflow("recv_exclude_list");
|
||||
read_sbuf(f,line,l);
|
||||
add_exclude(line);
|
||||
}
|
||||
char line[MAXPATHLEN];
|
||||
int l;
|
||||
while ((l=read_int(f))) {
|
||||
if (l >= MAXPATHLEN) overflow("recv_exclude_list");
|
||||
read_sbuf(f,line,l);
|
||||
add_exclude(line,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -181,7 +250,7 @@ void add_exclude_line(char *p)
|
||||
p = strdup(p);
|
||||
if (!p) out_of_memory("add_exclude_line");
|
||||
for (tok=strtok(p," "); tok; tok=strtok(NULL," "))
|
||||
add_exclude(tok);
|
||||
add_exclude(tok, 0);
|
||||
free(p);
|
||||
}
|
||||
|
||||
@@ -197,17 +266,17 @@ static char *cvs_ignore_list[] = {
|
||||
|
||||
void add_cvs_excludes(void)
|
||||
{
|
||||
char fname[MAXPATHLEN];
|
||||
char *p;
|
||||
int i;
|
||||
char fname[MAXPATHLEN];
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
for (i=0; cvs_ignore_list[i]; i++)
|
||||
add_exclude(cvs_ignore_list[i]);
|
||||
for (i=0; cvs_ignore_list[i]; i++)
|
||||
add_exclude(cvs_ignore_list[i], 0);
|
||||
|
||||
if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
|
||||
slprintf(fname,sizeof(fname)-1, "%s/.cvsignore",p);
|
||||
add_exclude_file(fname,0);
|
||||
}
|
||||
if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
|
||||
slprintf(fname,sizeof(fname)-1, "%s/.cvsignore",p);
|
||||
add_exclude_file(fname,0,0);
|
||||
}
|
||||
|
||||
add_exclude_line(getenv("CVSIGNORE"));
|
||||
add_exclude_line(getenv("CVSIGNORE"));
|
||||
}
|
||||
|
||||
218
fileio.c
Normal file
218
fileio.c
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1998
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
File IO utilities used in rsync
|
||||
*/
|
||||
#include "rsync.h"
|
||||
|
||||
static char last_byte;
|
||||
static int last_sparse;
|
||||
extern int sparse_files;
|
||||
|
||||
int sparse_end(int f)
|
||||
{
|
||||
if (last_sparse) {
|
||||
do_lseek(f,-1,SEEK_CUR);
|
||||
return (write(f,&last_byte,1) == 1 ? 0 : -1);
|
||||
}
|
||||
last_sparse = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int write_sparse(int f,char *buf,int len)
|
||||
{
|
||||
int l1=0,l2=0;
|
||||
int ret;
|
||||
|
||||
for (l1=0;l1<len && buf[l1]==0;l1++) ;
|
||||
for (l2=0;l2<(len-l1) && buf[len-(l2+1)]==0;l2++) ;
|
||||
|
||||
last_byte = buf[len-1];
|
||||
|
||||
if (l1 == len || l2 > 0)
|
||||
last_sparse=1;
|
||||
|
||||
if (l1 > 0)
|
||||
do_lseek(f,l1,SEEK_CUR);
|
||||
|
||||
if (l1 == len)
|
||||
return len;
|
||||
|
||||
if ((ret=write(f,buf+l1,len-(l1+l2))) != len-(l1+l2)) {
|
||||
if (ret == -1 || ret == 0) return ret;
|
||||
return (l1+ret);
|
||||
}
|
||||
|
||||
if (l2 > 0)
|
||||
do_lseek(f,l2,SEEK_CUR);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int write_file(int f,char *buf,int len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!sparse_files)
|
||||
return write(f,buf,len);
|
||||
|
||||
while (len>0) {
|
||||
int len1 = MIN(len, SPARSE_WRITE_SIZE);
|
||||
int r1 = write_sparse(f, buf, len1);
|
||||
if (r1 <= 0) {
|
||||
if (ret > 0) return ret;
|
||||
return r1;
|
||||
}
|
||||
len -= r1;
|
||||
buf += r1;
|
||||
ret += r1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct map_struct *map_file(int fd,OFF_T len)
|
||||
{
|
||||
struct map_struct *ret;
|
||||
ret = (struct map_struct *)malloc(sizeof(*ret));
|
||||
if (!ret) out_of_memory("map_file");
|
||||
|
||||
ret->map = NULL;
|
||||
ret->fd = fd;
|
||||
ret->size = len;
|
||||
ret->p = NULL;
|
||||
ret->p_size = 0;
|
||||
ret->p_offset = 0;
|
||||
ret->p_len = 0;
|
||||
|
||||
#ifdef USE_MMAP
|
||||
len = MIN(len, MAX_MAP_SIZE);
|
||||
ret->map = (char *)do_mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0);
|
||||
if (ret->map == (char *)-1) {
|
||||
ret->map = NULL;
|
||||
} else {
|
||||
ret->p_len = len;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
char *map_ptr(struct map_struct *map,OFF_T offset,int len)
|
||||
{
|
||||
int nread;
|
||||
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
|
||||
if (len > (map->size-offset))
|
||||
len = map->size-offset;
|
||||
|
||||
#ifdef USE_MMAP
|
||||
if (map->map) {
|
||||
if (offset >= map->p_offset &&
|
||||
offset+len <= map->p_offset+map->p_len) {
|
||||
return (map->map + (offset - map->p_offset));
|
||||
}
|
||||
if (munmap(map->map, map->p_len) != 0) {
|
||||
rprintf(FERROR,"munmap failed : %s\n", strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
/* align the mmap region on a nice boundary back a bit from
|
||||
where it is asked for to allow for some seeking */
|
||||
if (offset > 2*CHUNK_SIZE) {
|
||||
map->p_offset = offset - 2*CHUNK_SIZE;
|
||||
map->p_offset &= ~((OFF_T)(CHUNK_SIZE-1));
|
||||
} else {
|
||||
map->p_offset = 0;
|
||||
}
|
||||
|
||||
/* map up to MAX_MAP_SIZE */
|
||||
map->p_len = MAX(len, MAX_MAP_SIZE);
|
||||
map->p_len = MIN(map->p_len, map->size - map->p_offset);
|
||||
|
||||
map->map = (char *)do_mmap(NULL,map->p_len,PROT_READ,
|
||||
MAP_SHARED,map->fd,map->p_offset);
|
||||
|
||||
if (map->map == (char *)-1) {
|
||||
map->map = NULL;
|
||||
map->p_len = 0;
|
||||
map->p_offset = 0;
|
||||
} else {
|
||||
return (map->map + (offset - map->p_offset));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (offset >= map->p_offset &&
|
||||
offset+len <= map->p_offset+map->p_len) {
|
||||
return (map->p + (offset - map->p_offset));
|
||||
}
|
||||
|
||||
len = MAX(len,CHUNK_SIZE);
|
||||
if (len > (map->size-offset))
|
||||
len = map->size-offset;
|
||||
|
||||
if (len > map->p_size) {
|
||||
if (map->p) free(map->p);
|
||||
map->p = (char *)malloc(len);
|
||||
if (!map->p) out_of_memory("map_ptr");
|
||||
map->p_size = len;
|
||||
}
|
||||
|
||||
map->p_offset = offset;
|
||||
map->p_len = len;
|
||||
|
||||
if (do_lseek(map->fd,offset,SEEK_SET) != offset) {
|
||||
rprintf(FERROR,"lseek failed in map_ptr\n");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
if ((nread=read(map->fd,map->p,len)) != len) {
|
||||
if (nread < 0) nread = 0;
|
||||
/* the best we can do is zero the buffer - the file
|
||||
has changed mid transfer! */
|
||||
memset(map->p+nread, 0, len - nread);
|
||||
}
|
||||
|
||||
return map->p;
|
||||
}
|
||||
|
||||
|
||||
void unmap_file(struct map_struct *map)
|
||||
{
|
||||
#ifdef USE_MMAP
|
||||
if (map->map) {
|
||||
munmap(map->map,map->p_len);
|
||||
map->map = NULL;
|
||||
}
|
||||
#endif
|
||||
if (map->p) {
|
||||
free(map->p);
|
||||
map->p = NULL;
|
||||
}
|
||||
memset(map, 0, sizeof(*map));
|
||||
free(map);
|
||||
}
|
||||
|
||||
112
flist.c
112
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;
|
||||
|
||||
@@ -46,7 +47,7 @@ extern int copy_links;
|
||||
extern int remote_version;
|
||||
extern int io_error;
|
||||
|
||||
static char **local_exclude_list;
|
||||
static struct exclude_struct **local_exclude_list;
|
||||
|
||||
int link_stat(const char *Path, STRUCT_STAT *Buffer)
|
||||
{
|
||||
@@ -67,7 +68,7 @@ int link_stat(const char *Path, STRUCT_STAT *Buffer)
|
||||
*/
|
||||
static int match_file_name(char *fname,STRUCT_STAT *st)
|
||||
{
|
||||
if (check_exclude(fname,local_exclude_list)) {
|
||||
if (check_exclude(fname,local_exclude_list,st)) {
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"excluding file %s\n",fname);
|
||||
return 0;
|
||||
@@ -90,49 +91,6 @@ 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)
|
||||
{
|
||||
@@ -163,12 +121,17 @@ void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
|
||||
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++) ;
|
||||
for (l1=0;lastname[l1] && (fname[l1] == lastname[l1]) && (l1 < 255);l1++) ;
|
||||
l2 = strlen(fname) - l1;
|
||||
|
||||
if (l1 > 0) flags |= SAME_NAME;
|
||||
if (l2 > 255) flags |= LONG_NAME;
|
||||
|
||||
/* we must make sure we don't send a zero flags byte or the other
|
||||
end will terminate the flist transfer */
|
||||
if (flags == 0 && !S_ISDIR(file->mode)) flags |= FLAG_DELETE;
|
||||
if (flags == 0) flags |= LONG_NAME;
|
||||
|
||||
write_byte(f,flags);
|
||||
if (flags & SAME_NAME)
|
||||
write_byte(f,l1);
|
||||
@@ -459,7 +422,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;
|
||||
}
|
||||
@@ -493,10 +456,10 @@ static void send_file_name(int f,struct file_list *flist,char *fname,
|
||||
}
|
||||
|
||||
if (S_ISDIR(file->mode) && recursive) {
|
||||
char **last_exclude_list = local_exclude_list;
|
||||
send_directory(f,flist,f_name(file));
|
||||
local_exclude_list = last_exclude_list;
|
||||
return;
|
||||
struct exclude_struct **last_exclude_list = local_exclude_list;
|
||||
send_directory(f,flist,f_name(file));
|
||||
local_exclude_list = last_exclude_list;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -513,7 +476,7 @@ static void send_directory(int f,struct file_list *flist,char *dir)
|
||||
d = opendir(dir);
|
||||
if (!d) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"%s: %s\n",
|
||||
rprintf(FERROR,"opendir(%s): %s\n",
|
||||
dir,strerror(errno));
|
||||
return;
|
||||
}
|
||||
@@ -535,7 +498,7 @@ static void send_directory(int f,struct file_list *flist,char *dir)
|
||||
if (cvs_exclude) {
|
||||
if (strlen(fname) + strlen(".cvsignore") <= MAXPATHLEN-1) {
|
||||
strcpy(p,".cvsignore");
|
||||
local_exclude_list = make_exclude_list(fname,NULL,0);
|
||||
local_exclude_list = make_exclude_list(fname,NULL,0,0);
|
||||
} else {
|
||||
io_error = 1;
|
||||
rprintf(FINFO,"cannot cvs-exclude in long-named directory %s\n",fname);
|
||||
@@ -548,7 +511,7 @@ static void send_directory(int f,struct file_list *flist,char *dir)
|
||||
strcmp(dname,"..")==0)
|
||||
continue;
|
||||
strlcpy(p,dname,MAXPATHLEN-(l+1));
|
||||
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
|
||||
send_file_name(f,flist,fname,recurse,0);
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
@@ -561,15 +524,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");
|
||||
|
||||
@@ -625,8 +590,11 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
strlcpy(lastpath, fname, sizeof(lastpath)-1);
|
||||
*p = '/';
|
||||
for (p=fname+1; (p=strchr(p,'/')); p++) {
|
||||
int copy_links_saved = copy_links;
|
||||
*p = 0;
|
||||
copy_links = 0;
|
||||
send_file_name(f, flist, fname, 0, 0);
|
||||
copy_links = copy_links_saved;
|
||||
*p = '/';
|
||||
}
|
||||
} else {
|
||||
@@ -638,24 +606,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;
|
||||
@@ -688,7 +655,8 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
|
||||
if (f != -1) {
|
||||
io_end_buffering(f);
|
||||
write_flush(f);
|
||||
stats.flist_size = stats.total_written - start_write;
|
||||
stats.num_files = flist->count;
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
@@ -702,12 +670,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;
|
||||
@@ -738,7 +709,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++;
|
||||
|
||||
@@ -769,6 +740,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:
|
||||
@@ -783,8 +757,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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
415
io.c
415
io.c
@@ -24,34 +24,20 @@
|
||||
*/
|
||||
#include "rsync.h"
|
||||
|
||||
static int64 total_written;
|
||||
static int64 total_read;
|
||||
|
||||
static int io_multiplexing_out;
|
||||
static int io_multiplexing_in;
|
||||
static int multiplex_in_fd;
|
||||
static int multiplex_out_fd;
|
||||
static time_t last_io;
|
||||
|
||||
static int eof_error=1;
|
||||
extern int verbose;
|
||||
extern int sparse_files;
|
||||
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;
|
||||
|
||||
void setup_nonblocking(int f_in,int f_out)
|
||||
void setup_readbuffer(int f_in)
|
||||
{
|
||||
set_blocking(f_out,0);
|
||||
buffer_f_in = f_in;
|
||||
}
|
||||
|
||||
@@ -80,45 +66,77 @@ static char *read_buffer;
|
||||
static char *read_buffer_p;
|
||||
static int read_buffer_len;
|
||||
static int read_buffer_size;
|
||||
static int no_flush;
|
||||
|
||||
/* read from a socket with IO timeout. return the number of
|
||||
bytes read. If no bytes can be read then exit, never return
|
||||
a number <= 0 */
|
||||
static int read_timeout(int fd, char *buf, int len)
|
||||
{
|
||||
int n, ret=0;
|
||||
|
||||
io_flush();
|
||||
|
||||
while (ret == 0) {
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
tv.tv_sec = io_timeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (select(fd+1, &fds, NULL, NULL,
|
||||
io_timeout?&tv:NULL) != 1) {
|
||||
check_timeout();
|
||||
continue;
|
||||
}
|
||||
|
||||
n = read(fd, buf, len);
|
||||
|
||||
if (n > 0) {
|
||||
stats.total_read += n;
|
||||
buf += n;
|
||||
len -= n;
|
||||
ret += n;
|
||||
if (io_timeout)
|
||||
last_io = time(NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n == -1 && errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
if (eof_error) {
|
||||
rprintf(FERROR,"EOF in read_timeout\n");
|
||||
}
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
rprintf(FERROR,"read error: %s\n", strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* continue trying to read len bytes - don't return until len
|
||||
has been read */
|
||||
static void read_loop(int fd, char *buf, int len)
|
||||
{
|
||||
while (len) {
|
||||
int n = read(fd, buf, len);
|
||||
if (n > 0) {
|
||||
buf += n;
|
||||
len -= n;
|
||||
}
|
||||
if (n == 0) {
|
||||
rprintf(FERROR,"EOF in read_loop\n");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
if (n == -1) {
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
int n = read_timeout(fd, buf, len);
|
||||
|
||||
if (errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
rprintf(FERROR,"io error: %s\n",
|
||||
strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
tv.tv_sec = io_timeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (select(fd+1, &fds, NULL, NULL,
|
||||
io_timeout?&tv:NULL) != 1) {
|
||||
check_timeout();
|
||||
}
|
||||
}
|
||||
buf += n;
|
||||
len -= n;
|
||||
}
|
||||
}
|
||||
|
||||
/* read from the file descriptor handling multiplexing -
|
||||
return number of bytes read
|
||||
never return <= 0 */
|
||||
static int read_unbuffered(int fd, char *buf, int len)
|
||||
{
|
||||
static int remaining;
|
||||
@@ -127,7 +145,7 @@ static int read_unbuffered(int fd, char *buf, int len)
|
||||
char line[1024];
|
||||
|
||||
if (!io_multiplexing_in || fd != multiplex_in_fd)
|
||||
return read(fd, buf, len);
|
||||
return read_timeout(fd, buf, len);
|
||||
|
||||
while (ret == 0) {
|
||||
if (remaining) {
|
||||
@@ -170,12 +188,13 @@ static int read_unbuffered(int fd, char *buf, int len)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This function was added to overcome a deadlock problem when using
|
||||
* ssh. It looks like we can't allow our receive queue to get full or
|
||||
* ssh will clag up. Uggh. */
|
||||
static void read_check(int f)
|
||||
{
|
||||
int n;
|
||||
int n = 8192;
|
||||
|
||||
if (f == -1) return;
|
||||
|
||||
@@ -183,12 +202,6 @@ static void read_check(int f)
|
||||
read_buffer_p = read_buffer;
|
||||
}
|
||||
|
||||
if ((n=num_waiting(f)) <= 0)
|
||||
return;
|
||||
|
||||
/* things could deteriorate if we read in really small chunks */
|
||||
if (n < 10) n = 1024;
|
||||
|
||||
if (n > MAX_READ_BUFFER/4)
|
||||
n = MAX_READ_BUFFER/4;
|
||||
|
||||
@@ -199,28 +212,26 @@ static void read_check(int f)
|
||||
|
||||
if (n > (read_buffer_size - read_buffer_len)) {
|
||||
read_buffer_size += n;
|
||||
if (!read_buffer)
|
||||
read_buffer = (char *)malloc(read_buffer_size);
|
||||
else
|
||||
read_buffer = (char *)realloc(read_buffer,read_buffer_size);
|
||||
read_buffer = (char *)Realloc(read_buffer,read_buffer_size);
|
||||
if (!read_buffer) out_of_memory("read check");
|
||||
read_buffer_p = read_buffer;
|
||||
}
|
||||
|
||||
n = read_unbuffered(f,read_buffer+read_buffer_len,n);
|
||||
if (n > 0) {
|
||||
read_buffer_len += n;
|
||||
}
|
||||
read_buffer_len += n;
|
||||
}
|
||||
|
||||
static int readfd(int fd,char *buffer,int N)
|
||||
|
||||
/* do a buffered read from fd. don't return until all N bytes
|
||||
have been read. If all N can't be read then exit with an error */
|
||||
static void readfd(int fd,char *buffer,int N)
|
||||
{
|
||||
int ret;
|
||||
int total=0;
|
||||
struct timeval tv;
|
||||
|
||||
if (read_buffer_len < N)
|
||||
if (read_buffer_len < N && N < 1024) {
|
||||
read_check(buffer_f_in);
|
||||
}
|
||||
|
||||
while (total < N) {
|
||||
if (read_buffer_len > 0 && buffer_f_in == fd) {
|
||||
@@ -234,45 +245,17 @@ static int readfd(int fd,char *buffer,int N)
|
||||
|
||||
io_flush();
|
||||
|
||||
while ((ret = read_unbuffered(fd,buffer + total,N-total)) == -1) {
|
||||
fd_set fds;
|
||||
|
||||
if (errno != EAGAIN && errno != EWOULDBLOCK)
|
||||
return -1;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
tv.tv_sec = io_timeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (select(fd+1, &fds, NULL, NULL,
|
||||
io_timeout?&tv:NULL) != 1) {
|
||||
check_timeout();
|
||||
}
|
||||
}
|
||||
|
||||
if (ret <= 0)
|
||||
return total;
|
||||
ret = read_unbuffered(fd,buffer + total,N-total);
|
||||
total += ret;
|
||||
}
|
||||
|
||||
if (io_timeout)
|
||||
last_io = time(NULL);
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
int32 read_int(int f)
|
||||
{
|
||||
int ret;
|
||||
char b[4];
|
||||
if ((ret=readfd(f,b,4)) != 4) {
|
||||
if (verbose > 1)
|
||||
rprintf(FERROR,"(%d) read_int: Error reading %d bytes : %s\n",
|
||||
getpid(),4,ret==-1?strerror(errno):"EOF");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
total_read += 4;
|
||||
return IVAL(b,0);
|
||||
char b[4];
|
||||
readfd(f,b,4);
|
||||
return IVAL(b,0);
|
||||
}
|
||||
|
||||
int64 read_longint(int f)
|
||||
@@ -289,13 +272,7 @@ int64 read_longint(int f)
|
||||
exit_cleanup(1);
|
||||
#else
|
||||
if (remote_version >= 16) {
|
||||
if ((ret=readfd(f,b,8)) != 8) {
|
||||
if (verbose > 1)
|
||||
rprintf(FERROR,"(%d) read_longint: Error reading %d bytes : %s\n",
|
||||
getpid(),8,ret==-1?strerror(errno):"EOF");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
total_read += 8;
|
||||
readfd(f,b,8);
|
||||
ret = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
|
||||
}
|
||||
#endif
|
||||
@@ -305,14 +282,7 @@ int64 read_longint(int f)
|
||||
|
||||
void read_buf(int f,char *buf,int len)
|
||||
{
|
||||
int ret;
|
||||
if ((ret=readfd(f,buf,len)) != len) {
|
||||
if (verbose > 1)
|
||||
rprintf(FERROR,"(%d) read_buf: Error reading %d bytes : %s\n",
|
||||
getpid(),len,ret==-1?strerror(errno):"EOF");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
total_read += len;
|
||||
readfd(f,buf,len);
|
||||
}
|
||||
|
||||
void read_sbuf(int f,char *buf,int len)
|
||||
@@ -323,149 +293,79 @@ void read_sbuf(int f,char *buf,int len)
|
||||
|
||||
unsigned char read_byte(int f)
|
||||
{
|
||||
unsigned char c;
|
||||
read_buf(f,(char *)&c,1);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
static char last_byte;
|
||||
static int last_sparse;
|
||||
|
||||
int sparse_end(int f)
|
||||
{
|
||||
if (last_sparse) {
|
||||
do_lseek(f,-1,SEEK_CUR);
|
||||
return (write(f,&last_byte,1) == 1 ? 0 : -1);
|
||||
}
|
||||
last_sparse = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int write_sparse(int f,char *buf,int len)
|
||||
{
|
||||
int l1=0,l2=0;
|
||||
int ret;
|
||||
|
||||
for (l1=0;l1<len && buf[l1]==0;l1++) ;
|
||||
for (l2=0;l2<(len-l1) && buf[len-(l2+1)]==0;l2++) ;
|
||||
|
||||
last_byte = buf[len-1];
|
||||
|
||||
if (l1 == len || l2 > 0)
|
||||
last_sparse=1;
|
||||
|
||||
if (l1 > 0)
|
||||
do_lseek(f,l1,SEEK_CUR);
|
||||
|
||||
if (l1 == len)
|
||||
return len;
|
||||
|
||||
if ((ret=write(f,buf+l1,len-(l1+l2))) != len-(l1+l2)) {
|
||||
if (ret == -1 || ret == 0) return ret;
|
||||
return (l1+ret);
|
||||
}
|
||||
|
||||
if (l2 > 0)
|
||||
do_lseek(f,l2,SEEK_CUR);
|
||||
|
||||
return len;
|
||||
unsigned char c;
|
||||
read_buf(f,(char *)&c,1);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int write_file(int f,char *buf,int len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!sparse_files)
|
||||
return write(f,buf,len);
|
||||
|
||||
while (len>0) {
|
||||
int len1 = MIN(len, SPARSE_WRITE_SIZE);
|
||||
int r1 = write_sparse(f, buf, len1);
|
||||
if (r1 <= 0) {
|
||||
if (ret > 0) return ret;
|
||||
return r1;
|
||||
}
|
||||
len -= r1;
|
||||
buf += r1;
|
||||
ret += r1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int writefd_unbuffered(int fd,char *buf,int len)
|
||||
/* write len bytes to fd, possibly reading from buffer_f_in if set
|
||||
in order to unclog the pipe. don't return until all len
|
||||
bytes have been written */
|
||||
static void writefd_unbuffered(int fd,char *buf,int len)
|
||||
{
|
||||
int total = 0;
|
||||
fd_set w_fds, r_fds;
|
||||
int fd_count, count, got_select=0;
|
||||
int fd_count, count;
|
||||
struct timeval tv;
|
||||
int reading;
|
||||
|
||||
no_flush++;
|
||||
|
||||
reading = (buffer_f_in != -1 && read_buffer_len < MAX_READ_BUFFER);
|
||||
|
||||
while (total < len) {
|
||||
int ret = write(fd,buf+total,len-total);
|
||||
|
||||
if (ret == 0) return total;
|
||||
|
||||
if (ret == -1 && !(errno == EWOULDBLOCK || errno == EAGAIN))
|
||||
return -1;
|
||||
|
||||
if (ret == -1 && got_select) {
|
||||
/* hmmm, we got a write select on the fd and
|
||||
then failed to write. Why doesn't that
|
||||
mean that the fd is dead? It doesn't on
|
||||
some systems it seems (eg. IRIX) */
|
||||
u_sleep(1000);
|
||||
}
|
||||
|
||||
got_select = 0;
|
||||
|
||||
|
||||
if (ret != -1) {
|
||||
total += ret;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (read_buffer_len < MAX_READ_BUFFER && buffer_f_in != -1)
|
||||
read_check(buffer_f_in);
|
||||
|
||||
fd_count = fd+1;
|
||||
FD_ZERO(&w_fds);
|
||||
FD_ZERO(&r_fds);
|
||||
FD_SET(fd,&w_fds);
|
||||
if (buffer_f_in != -1) {
|
||||
fd_count = fd+1;
|
||||
|
||||
if (reading) {
|
||||
FD_SET(buffer_f_in,&r_fds);
|
||||
if (buffer_f_in > fd)
|
||||
fd_count = buffer_f_in+1;
|
||||
}
|
||||
|
||||
tv.tv_sec = BLOCKING_TIMEOUT;
|
||||
tv.tv_sec = io_timeout;
|
||||
tv.tv_usec = 0;
|
||||
count = select(fd_count,buffer_f_in == -1? NULL: &r_fds,
|
||||
&w_fds,NULL,&tv);
|
||||
|
||||
if (count == -1 && errno != EINTR) {
|
||||
if (verbose > 1)
|
||||
rprintf(FERROR,"select error: %s\n", strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
|
||||
count = select(fd_count,
|
||||
reading?&r_fds:NULL,
|
||||
&w_fds,NULL,
|
||||
io_timeout?&tv:NULL);
|
||||
|
||||
if (count <= 0) {
|
||||
check_timeout();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (FD_ISSET(fd, &w_fds)) {
|
||||
got_select = 1;
|
||||
int ret = write(fd,buf+total,len-total);
|
||||
|
||||
if (ret == -1 && errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret <= 0) {
|
||||
rprintf(FERROR,"erroring writing %d bytes - exiting\n", len);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (io_timeout)
|
||||
last_io = time(NULL);
|
||||
|
||||
return total;
|
||||
no_flush--;
|
||||
}
|
||||
|
||||
|
||||
@@ -487,21 +387,13 @@ 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);
|
||||
if (writefd_unbuffered(fd, io_buffer-4, io_buffer_count+4) !=
|
||||
io_buffer_count+4) {
|
||||
rprintf(FERROR,"write failed\n");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
writefd_unbuffered(fd, io_buffer-4, io_buffer_count+4);
|
||||
} else {
|
||||
if (writefd_unbuffered(fd, io_buffer, io_buffer_count) !=
|
||||
io_buffer_count) {
|
||||
rprintf(FERROR,"write failed\n");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
writefd_unbuffered(fd, io_buffer, io_buffer_count);
|
||||
}
|
||||
io_buffer_count = 0;
|
||||
}
|
||||
@@ -515,11 +407,12 @@ void io_end_buffering(int fd)
|
||||
}
|
||||
}
|
||||
|
||||
static int writefd(int fd,char *buf,int len1)
|
||||
static void writefd(int fd,char *buf,int len)
|
||||
{
|
||||
int len = len1;
|
||||
|
||||
if (!io_buffer) return writefd_unbuffered(fd, buf, len);
|
||||
if (!io_buffer) {
|
||||
writefd_unbuffered(fd, buf, len);
|
||||
return;
|
||||
}
|
||||
|
||||
while (len) {
|
||||
int n = MIN(len, IO_BUFFER_SIZE-io_buffer_count);
|
||||
@@ -532,29 +425,20 @@ static int writefd(int fd,char *buf,int len1)
|
||||
|
||||
if (io_buffer_count == IO_BUFFER_SIZE) io_flush();
|
||||
}
|
||||
|
||||
return len1;
|
||||
}
|
||||
|
||||
|
||||
void write_int(int f,int32 x)
|
||||
{
|
||||
int ret;
|
||||
char b[4];
|
||||
SIVAL(b,0,x);
|
||||
if ((ret=writefd(f,b,4)) != 4) {
|
||||
rprintf(FERROR,"write_int failed : %s\n",
|
||||
ret==-1?strerror(errno):"EOF");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
total_written += 4;
|
||||
writefd(f,b,4);
|
||||
}
|
||||
|
||||
void write_longint(int f, int64 x)
|
||||
{
|
||||
extern int remote_version;
|
||||
char b[8];
|
||||
int ret;
|
||||
|
||||
if (remote_version < 16 || x <= 0x7FFFFFFF) {
|
||||
write_int(f, (int)x);
|
||||
@@ -565,23 +449,12 @@ void write_longint(int f, int64 x)
|
||||
SIVAL(b,0,(x&0xFFFFFFFF));
|
||||
SIVAL(b,4,((x>>32)&0xFFFFFFFF));
|
||||
|
||||
if ((ret=writefd(f,b,8)) != 8) {
|
||||
rprintf(FERROR,"write_longint failed : %s\n",
|
||||
ret==-1?strerror(errno):"EOF");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
total_written += 8;
|
||||
writefd(f,b,8);
|
||||
}
|
||||
|
||||
void write_buf(int f,char *buf,int len)
|
||||
{
|
||||
int ret;
|
||||
if ((ret=writefd(f,buf,len)) != len) {
|
||||
rprintf(FERROR,"write_buf failed : %s\n",
|
||||
ret==-1?strerror(errno):"EOF");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
total_written += len;
|
||||
writefd(f,buf,len);
|
||||
}
|
||||
|
||||
/* write a string to the connection */
|
||||
@@ -596,15 +469,14 @@ void write_byte(int f,unsigned char c)
|
||||
write_buf(f,(char *)&c,1);
|
||||
}
|
||||
|
||||
void write_flush(int f)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int read_line(int f, char *buf, int maxlen)
|
||||
{
|
||||
eof_error = 0;
|
||||
|
||||
while (maxlen) {
|
||||
buf[0] = 0;
|
||||
read_buf(f, buf, 1);
|
||||
if (buf[0] == 0) return 0;
|
||||
if (buf[0] == '\n') {
|
||||
buf[0] = 0;
|
||||
break;
|
||||
@@ -618,6 +490,9 @@ int read_line(int f, char *buf, int maxlen)
|
||||
*buf = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
eof_error = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
18
lib/compat.c
18
lib/compat.c
@@ -58,3 +58,21 @@ void *memmove(void *dest, const void *src, size_t n)
|
||||
return dest;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRPBRK
|
||||
/* Find the first ocurrence in S of any character in ACCEPT.
|
||||
derived from glibc
|
||||
*/
|
||||
char *strpbrk(const char *s, const char *accept)
|
||||
{
|
||||
while (*s != '\0') {
|
||||
const char *a = accept;
|
||||
while (*a != '\0') {
|
||||
if (*a++ == *s) return (char *)s;
|
||||
}
|
||||
++s;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
4601
lib/zlib.c
4601
lib/zlib.c
File diff suppressed because it is too large
Load Diff
632
lib/zlib.h
632
lib/zlib.h
@@ -1,632 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This file is derived from zlib.h and zconf.h from the zlib-0.95
|
||||
* distribution by Jean-loup Gailly and Mark Adler, with some additions
|
||||
* by Paul Mackerras to aid in implementing Deflate compression and
|
||||
* decompression for PPP packets.
|
||||
*/
|
||||
|
||||
/* zlib.h -- interface of the 'zlib' general purpose compression library
|
||||
version 0.95, Aug 16th, 1995.
|
||||
|
||||
Copyright (C) 1995 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
gzip@prep.ai.mit.edu madler@alumni.caltech.edu
|
||||
*/
|
||||
|
||||
#ifndef _ZLIB_H
|
||||
#define _ZLIB_H
|
||||
|
||||
/* #include "zconf.h" */ /* included directly here */
|
||||
|
||||
/* zconf.h -- configuration of the zlib compression library
|
||||
* Copyright (C) 1995 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */
|
||||
|
||||
/*
|
||||
The library does not install any signal handler. It is recommended to
|
||||
add at least a handler for SIGSEGV when decompressing; the library checks
|
||||
the consistency of the input data whenever possible but may go nuts
|
||||
for some forms of corrupted input.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
|
||||
* than 64k bytes at a time (needed on systems with 16-bit int).
|
||||
* Compile with -DUNALIGNED_OK if it is OK to access shorts or ints
|
||||
* at addresses which are not a multiple of their size.
|
||||
* Under DOS, -DFAR=far or -DFAR=__far may be needed.
|
||||
*/
|
||||
|
||||
#ifndef STDC
|
||||
# if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus)
|
||||
# define STDC
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */
|
||||
# include <unix.h>
|
||||
#endif
|
||||
|
||||
/* Maximum value for memLevel in deflateInit2 */
|
||||
#ifndef MAX_MEM_LEVEL
|
||||
# ifdef MAXSEG_64K
|
||||
# define MAX_MEM_LEVEL 8
|
||||
# else
|
||||
# define MAX_MEM_LEVEL 9
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef FAR
|
||||
# define FAR
|
||||
#endif
|
||||
|
||||
/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
|
||||
#ifndef MAX_WBITS
|
||||
# define MAX_WBITS 15 /* 32K LZ77 window */
|
||||
#endif
|
||||
|
||||
/* The memory requirements for deflate are (in bytes):
|
||||
1 << (windowBits+2) + 1 << (memLevel+9)
|
||||
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
|
||||
plus a few kilobytes for small objects. For example, if you want to reduce
|
||||
the default memory requirements from 256K to 128K, compile with
|
||||
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
|
||||
Of course this will generally degrade compression (there's no free lunch).
|
||||
|
||||
The memory requirements for inflate are (in bytes) 1 << windowBits
|
||||
that is, 32K for windowBits=15 (default value) plus a few kilobytes
|
||||
for small objects.
|
||||
*/
|
||||
|
||||
/* Type declarations */
|
||||
|
||||
#ifndef OF /* function prototypes */
|
||||
# ifdef STDC
|
||||
# define OF(args) args
|
||||
# else
|
||||
# define OF(args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef unsigned char Byte; /* 8 bits */
|
||||
typedef unsigned int uInt; /* 16 bits or more */
|
||||
typedef int32 Long; /* 32 bits or more */
|
||||
typedef uint32 uLong; /* 32 bits or more */
|
||||
|
||||
typedef Byte FAR Bytef;
|
||||
typedef char FAR charf;
|
||||
typedef int FAR intf;
|
||||
typedef uInt FAR uIntf;
|
||||
typedef uLong FAR uLongf;
|
||||
|
||||
#ifdef STDC
|
||||
typedef void FAR *voidpf;
|
||||
typedef void *voidp;
|
||||
#else
|
||||
typedef Byte FAR *voidpf;
|
||||
typedef Byte *voidp;
|
||||
#endif
|
||||
|
||||
/* end of original zconf.h */
|
||||
|
||||
#define ZLIB_VERSION "0.95P"
|
||||
|
||||
/*
|
||||
The 'zlib' compression library provides in-memory compression and
|
||||
decompression functions, including integrity checks of the uncompressed
|
||||
data. This version of the library supports only one compression method
|
||||
(deflation) but other algorithms may be added later and will have the same
|
||||
stream interface.
|
||||
|
||||
For compression the application must provide the output buffer and
|
||||
may optionally provide the input buffer for optimization. For decompression,
|
||||
the application must provide the input buffer and may optionally provide
|
||||
the output buffer for optimization.
|
||||
|
||||
Compression can be done in a single step if the buffers are large
|
||||
enough (for example if an input file is mmap'ed), or can be done by
|
||||
repeated calls of the compression function. In the latter case, the
|
||||
application must provide more input and/or consume the output
|
||||
(providing more output space) before each call.
|
||||
*/
|
||||
|
||||
typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
|
||||
typedef void (*free_func) OF((voidpf opaque, voidpf address, uInt nbytes));
|
||||
|
||||
struct internal_state;
|
||||
|
||||
typedef struct z_stream_s {
|
||||
Bytef *next_in; /* next input byte */
|
||||
uInt avail_in; /* number of bytes available at next_in */
|
||||
uLong total_in; /* total nb of input bytes read so far */
|
||||
|
||||
Bytef *next_out; /* next output byte should be put there */
|
||||
uInt avail_out; /* remaining free space at next_out */
|
||||
uLong total_out; /* total nb of bytes output so far */
|
||||
|
||||
char *msg; /* last error message, NULL if no error */
|
||||
struct internal_state FAR *state; /* not visible by applications */
|
||||
|
||||
alloc_func zalloc; /* used to allocate the internal state */
|
||||
free_func zfree; /* used to free the internal state */
|
||||
voidp opaque; /* private data object passed to zalloc and zfree */
|
||||
|
||||
Byte data_type; /* best guess about the data type: ascii or binary */
|
||||
|
||||
} z_stream;
|
||||
|
||||
/*
|
||||
The application must update next_in and avail_in when avail_in has
|
||||
dropped to zero. It must update next_out and avail_out when avail_out
|
||||
has dropped to zero. The application must initialize zalloc, zfree and
|
||||
opaque before calling the init function. All other fields are set by the
|
||||
compression library and must not be updated by the application.
|
||||
|
||||
The opaque value provided by the application will be passed as the first
|
||||
parameter for calls of zalloc and zfree. This can be useful for custom
|
||||
memory management. The compression library attaches no meaning to the
|
||||
opaque value.
|
||||
|
||||
zalloc must return Z_NULL if there is not enough memory for the object.
|
||||
On 16-bit systems, the functions zalloc and zfree must be able to allocate
|
||||
exactly 65536 bytes, but will not be required to allocate more than this
|
||||
if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
|
||||
pointers returned by zalloc for objects of exactly 65536 bytes *must*
|
||||
have their offset normalized to zero. The default allocation function
|
||||
provided by this library ensures this (see zutil.c). To reduce memory
|
||||
requirements and avoid any allocation of 64K objects, at the expense of
|
||||
compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
|
||||
|
||||
The fields total_in and total_out can be used for statistics or
|
||||
progress reports. After compression, total_in holds the total size of
|
||||
the uncompressed data and may be saved for use in the decompressor
|
||||
(particularly if the decompressor wants to decompress everything in
|
||||
a single step).
|
||||
*/
|
||||
|
||||
/* constants */
|
||||
|
||||
#define Z_NO_FLUSH 0
|
||||
#define Z_PARTIAL_FLUSH 1
|
||||
#define Z_FULL_FLUSH 2
|
||||
#define Z_SYNC_FLUSH 3 /* experimental: partial_flush + byte align */
|
||||
#define Z_FINISH 4
|
||||
#define Z_PACKET_FLUSH 5
|
||||
#define Z_INSERT_ONLY 6 /* update hash table etc., produce no output */
|
||||
/* See deflate() below for the usage of these constants */
|
||||
|
||||
#define Z_OK 0
|
||||
#define Z_STREAM_END 1
|
||||
#define Z_ERRNO (-1)
|
||||
#define Z_STREAM_ERROR (-2)
|
||||
#define Z_DATA_ERROR (-3)
|
||||
#define Z_MEM_ERROR (-4)
|
||||
#define Z_BUF_ERROR (-5)
|
||||
/* error codes for the compression/decompression functions */
|
||||
|
||||
#define Z_BEST_SPEED 1
|
||||
#define Z_BEST_COMPRESSION 9
|
||||
#define Z_DEFAULT_COMPRESSION (-1)
|
||||
/* compression levels */
|
||||
|
||||
#define Z_FILTERED 1
|
||||
#define Z_HUFFMAN_ONLY 2
|
||||
#define Z_DEFAULT_STRATEGY 0
|
||||
|
||||
#define Z_BINARY 0
|
||||
#define Z_ASCII 1
|
||||
#define Z_UNKNOWN 2
|
||||
/* Used to set the data_type field */
|
||||
|
||||
#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
|
||||
|
||||
extern char *zlib_version;
|
||||
/* The application can compare zlib_version and ZLIB_VERSION for consistency.
|
||||
If the first character differs, the library code actually used is
|
||||
not compatible with the zlib.h header file used by the application.
|
||||
*/
|
||||
|
||||
/* basic functions */
|
||||
|
||||
extern int deflateInit OF((z_stream *strm, int level));
|
||||
/*
|
||||
Initializes the internal stream state for compression. The fields
|
||||
zalloc, zfree and opaque must be initialized before by the caller.
|
||||
If zalloc and zfree are set to Z_NULL, deflateInit updates them to
|
||||
use default allocation functions.
|
||||
|
||||
The compression level must be Z_DEFAULT_COMPRESSION, or between 1 and 9:
|
||||
1 gives best speed, 9 gives best compression. Z_DEFAULT_COMPRESSION requests
|
||||
a default compromise between speed and compression (currently equivalent
|
||||
to level 6).
|
||||
|
||||
deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||
enough memory, Z_STREAM_ERROR if level is not a valid compression level.
|
||||
msg is set to null if there is no error message. deflateInit does not
|
||||
perform any compression: this will be done by deflate().
|
||||
*/
|
||||
|
||||
|
||||
extern int deflate OF((z_stream *strm, int flush));
|
||||
/*
|
||||
Performs one or both of the following actions:
|
||||
|
||||
- Compress more input starting at next_in and update next_in and avail_in
|
||||
accordingly. If not all input can be processed (because there is not
|
||||
enough room in the output buffer), next_in and avail_in are updated and
|
||||
processing will resume at this point for the next call of deflate().
|
||||
|
||||
- Provide more output starting at next_out and update next_out and avail_out
|
||||
accordingly. This action is forced if the parameter flush is non zero.
|
||||
Forcing flush frequently degrades the compression ratio, so this parameter
|
||||
should be set only when necessary (in interactive applications).
|
||||
Some output may be provided even if flush is not set.
|
||||
|
||||
Before the call of deflate(), the application should ensure that at least
|
||||
one of the actions is possible, by providing more input and/or consuming
|
||||
more output, and updating avail_in or avail_out accordingly; avail_out
|
||||
should never be zero before the call. The application can consume the
|
||||
compressed output when it wants, for example when the output buffer is full
|
||||
(avail_out == 0), or after each call of deflate().
|
||||
|
||||
If the parameter flush is set to Z_PARTIAL_FLUSH, the current compression
|
||||
block is terminated and flushed to the output buffer so that the
|
||||
decompressor can get all input data available so far. For method 9, a future
|
||||
variant on method 8, the current block will be flushed but not terminated.
|
||||
If flush is set to Z_FULL_FLUSH, the compression block is terminated, a
|
||||
special marker is output and the compression dictionary is discarded; this
|
||||
is useful to allow the decompressor to synchronize if one compressed block
|
||||
has been damaged (see inflateSync below). Flushing degrades compression and
|
||||
so should be used only when necessary. Using Z_FULL_FLUSH too often can
|
||||
seriously degrade the compression. If deflate returns with avail_out == 0,
|
||||
this function must be called again with the same value of the flush
|
||||
parameter and more output space (updated avail_out), until the flush is
|
||||
complete (deflate returns with non-zero avail_out).
|
||||
|
||||
If the parameter flush is set to Z_PACKET_FLUSH, the compression
|
||||
block is terminated, and a zero-length stored block is output,
|
||||
omitting the length bytes (the effect of this is that the 3-bit type
|
||||
code 000 for a stored block is output, and the output is then
|
||||
byte-aligned). This is designed for use at the end of a PPP packet.
|
||||
In addition, if the current compression block contains all the data
|
||||
since the last Z_PACKET_FLUSH, it is never output as a stored block.
|
||||
If the current compression block output as a static or dynamic block
|
||||
would not be at least `minCompression' bytes smaller than the
|
||||
original data, then nothing is output for that block. (The type
|
||||
code for the zero-length stored block is still output, resulting in
|
||||
a single zero byte being output for the whole packet.)
|
||||
`MinCompression' is a parameter to deflateInit2, or 0 if deflateInit
|
||||
is used.
|
||||
|
||||
If the parameter flush is set to Z_FINISH, all pending input is processed,
|
||||
all pending output is flushed and deflate returns with Z_STREAM_END if there
|
||||
was enough output space; if deflate returns with Z_OK, this function must be
|
||||
called again with Z_FINISH and more output space (updated avail_out) but no
|
||||
more input data, until it returns with Z_STREAM_END or an error. After
|
||||
deflate has returned Z_STREAM_END, the only possible operations on the
|
||||
stream are deflateReset or deflateEnd.
|
||||
|
||||
Z_FINISH can be used immediately after deflateInit if all the compression
|
||||
is to be done in a single step. In this case, avail_out must be at least
|
||||
0.1% larger than avail_in plus 12 bytes. If deflate does not return
|
||||
Z_STREAM_END, then it must be called again as described above.
|
||||
|
||||
deflate() may update data_type if it can make a good guess about
|
||||
the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
|
||||
binary. This field is only for information purposes and does not affect
|
||||
the compression algorithm in any manner.
|
||||
|
||||
deflate() returns Z_OK if some progress has been made (more input
|
||||
processed or more output produced), Z_STREAM_END if all input has been
|
||||
consumed and all output has been produced (only when flush is set to
|
||||
Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
|
||||
if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible.
|
||||
*/
|
||||
|
||||
|
||||
extern int deflateEnd OF((z_stream *strm));
|
||||
/*
|
||||
All dynamically allocated data structures for this stream are freed.
|
||||
This function discards any unprocessed input and does not flush any
|
||||
pending output.
|
||||
|
||||
deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
|
||||
stream state was inconsistent. In the error case, msg may be set
|
||||
but then points to a static string (which must not be deallocated).
|
||||
*/
|
||||
|
||||
|
||||
extern int inflateInit OF((z_stream *strm));
|
||||
/*
|
||||
Initializes the internal stream state for decompression. The fields
|
||||
zalloc and zfree must be initialized before by the caller. If zalloc and
|
||||
zfree are set to Z_NULL, inflateInit updates them to use default allocation
|
||||
functions.
|
||||
|
||||
inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||
enough memory. msg is set to null if there is no error message.
|
||||
inflateInit does not perform any decompression: this will be done by
|
||||
inflate().
|
||||
*/
|
||||
|
||||
|
||||
extern int inflate OF((z_stream *strm, int flush));
|
||||
/*
|
||||
Performs one or both of the following actions:
|
||||
|
||||
- Decompress more input starting at next_in and update next_in and avail_in
|
||||
accordingly. If not all input can be processed (because there is not
|
||||
enough room in the output buffer), next_in is updated and processing
|
||||
will resume at this point for the next call of inflate().
|
||||
|
||||
- Provide more output starting at next_out and update next_out and avail_out
|
||||
accordingly. inflate() always provides as much output as possible
|
||||
(until there is no more input data or no more space in the output buffer).
|
||||
|
||||
Before the call of inflate(), the application should ensure that at least
|
||||
one of the actions is possible, by providing more input and/or consuming
|
||||
more output, and updating the next_* and avail_* values accordingly.
|
||||
The application can consume the uncompressed output when it wants, for
|
||||
example when the output buffer is full (avail_out == 0), or after each
|
||||
call of inflate().
|
||||
|
||||
If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
|
||||
inflate flushes as much output as possible to the output buffer. The
|
||||
flushing behavior of inflate is not specified for values of the flush
|
||||
parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
|
||||
current implementation actually flushes as much output as possible
|
||||
anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data
|
||||
has been consumed, it is expecting to see the length field of a stored
|
||||
block; if not, it returns Z_DATA_ERROR.
|
||||
|
||||
inflate() should normally be called until it returns Z_STREAM_END or an
|
||||
error. However if all decompression is to be performed in a single step
|
||||
(a single call of inflate), the parameter flush should be set to
|
||||
Z_FINISH. In this case all pending input is processed and all pending
|
||||
output is flushed; avail_out must be large enough to hold all the
|
||||
uncompressed data. (The size of the uncompressed data may have been saved
|
||||
by the compressor for this purpose.) The next operation on this stream must
|
||||
be inflateEnd to deallocate the decompression state. The use of Z_FINISH
|
||||
is never required, but can be used to inform inflate that a faster routine
|
||||
may be used for the single inflate() call.
|
||||
|
||||
inflate() returns Z_OK if some progress has been made (more input
|
||||
processed or more output produced), Z_STREAM_END if the end of the
|
||||
compressed data has been reached and all uncompressed output has been
|
||||
produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if
|
||||
the stream structure was inconsistent (for example if next_in or next_out
|
||||
was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no
|
||||
progress is possible or if there was not enough room in the output buffer
|
||||
when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then
|
||||
call inflateSync to look for a good compression block. */
|
||||
|
||||
|
||||
extern int inflateEnd OF((z_stream *strm));
|
||||
/*
|
||||
All dynamically allocated data structures for this stream are freed.
|
||||
This function discards any unprocessed input and does not flush any
|
||||
pending output.
|
||||
|
||||
inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
|
||||
was inconsistent. In the error case, msg may be set but then points to a
|
||||
static string (which must not be deallocated).
|
||||
*/
|
||||
|
||||
/* advanced functions */
|
||||
|
||||
/*
|
||||
The following functions are needed only in some special applications.
|
||||
*/
|
||||
|
||||
extern int deflateInit2 OF((z_stream *strm,
|
||||
int level,
|
||||
int method,
|
||||
int windowBits,
|
||||
int memLevel,
|
||||
int strategy));
|
||||
/*
|
||||
This is another version of deflateInit with more compression options. The
|
||||
fields next_in, zalloc and zfree must be initialized before by the caller.
|
||||
|
||||
The method parameter is the compression method. It must be 8 in this
|
||||
version of the library. (Method 9 will allow a 64K history buffer and
|
||||
partial block flushes.)
|
||||
|
||||
The windowBits parameter is the base two logarithm of the window size
|
||||
(the size of the history buffer). It should be in the range 8..15 for this
|
||||
version of the library (the value 16 will be allowed for method 9). Larger
|
||||
values of this parameter result in better compression at the expense of
|
||||
memory usage. The default value is 15 if deflateInit is used instead.
|
||||
|
||||
The memLevel parameter specifies how much memory should be allocated
|
||||
for the internal compression state. memLevel=1 uses minimum memory but
|
||||
is slow and reduces compression ratio; memLevel=9 uses maximum memory
|
||||
for optimal speed. The default value is 8. See zconf.h for total memory
|
||||
usage as a function of windowBits and memLevel.
|
||||
|
||||
The strategy parameter is used to tune the compression algorithm. Use
|
||||
the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data
|
||||
produced by a filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman
|
||||
encoding only (no string match). Filtered data consists mostly of small
|
||||
values with a somewhat random distribution. In this case, the
|
||||
compression algorithm is tuned to compress them better. The strategy
|
||||
parameter only affects the compression ratio but not the correctness of
|
||||
the compressed output even if it is not set appropriately.
|
||||
|
||||
The minCompression parameter specifies the minimum reduction in size
|
||||
required for a compressed block to be output when Z_PACKET_FLUSH is
|
||||
used (see the description of deflate above).
|
||||
|
||||
If next_in is not null, the library will use this buffer to hold also
|
||||
some history information; the buffer must either hold the entire input
|
||||
data, or have at least 1<<(windowBits+1) bytes and be writable. If next_in
|
||||
is null, the library will allocate its own history buffer (and leave next_in
|
||||
null). next_out need not be provided here but must be provided by the
|
||||
application for the next call of deflate().
|
||||
|
||||
If the history buffer is provided by the application, next_in must
|
||||
must never be changed by the application since the compressor maintains
|
||||
information inside this buffer from call to call; the application
|
||||
must provide more input only by increasing avail_in. next_in is always
|
||||
reset by the library in this case.
|
||||
|
||||
deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
|
||||
not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
|
||||
an invalid method). msg is set to null if there is no error message.
|
||||
deflateInit2 does not perform any compression: this will be done by
|
||||
deflate().
|
||||
*/
|
||||
|
||||
extern int deflateCopy OF((z_stream *dest,
|
||||
z_stream *source));
|
||||
/*
|
||||
Sets the destination stream as a complete copy of the source stream. If
|
||||
the source stream is using an application-supplied history buffer, a new
|
||||
buffer is allocated for the destination stream. The compressed output
|
||||
buffer is always application-supplied. It's the responsibility of the
|
||||
application to provide the correct values of next_out and avail_out for the
|
||||
next call of deflate.
|
||||
|
||||
This function is useful when several compression strategies will be
|
||||
tried, for example when there are several ways of pre-processing the input
|
||||
data with a filter. The streams that will be discarded should then be freed
|
||||
by calling deflateEnd. Note that deflateCopy duplicates the internal
|
||||
compression state which can be quite large, so this strategy is slow and
|
||||
can consume lots of memory.
|
||||
|
||||
deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||
enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
|
||||
(such as zalloc being NULL). msg is left unchanged in both source and
|
||||
destination.
|
||||
*/
|
||||
|
||||
extern int deflateReset OF((z_stream *strm));
|
||||
/*
|
||||
This function is equivalent to deflateEnd followed by deflateInit,
|
||||
but does not free and reallocate all the internal compression state.
|
||||
The stream will keep the same compression level and any other attributes
|
||||
that may have been set by deflateInit2.
|
||||
|
||||
deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
|
||||
stream state was inconsistent (such as zalloc or state being NULL).
|
||||
*/
|
||||
|
||||
extern int inflateInit2 OF((z_stream *strm,
|
||||
int windowBits));
|
||||
/*
|
||||
This is another version of inflateInit with more compression options. The
|
||||
fields next_out, zalloc and zfree must be initialized before by the caller.
|
||||
|
||||
The windowBits parameter is the base two logarithm of the maximum window
|
||||
size (the size of the history buffer). It should be in the range 8..15 for
|
||||
this version of the library (the value 16 will be allowed soon). The
|
||||
default value is 15 if inflateInit is used instead. If a compressed stream
|
||||
with a larger window size is given as input, inflate() will return with
|
||||
the error code Z_DATA_ERROR instead of trying to allocate a larger window.
|
||||
|
||||
If next_out is not null, the library will use this buffer for the history
|
||||
buffer; the buffer must either be large enough to hold the entire output
|
||||
data, or have at least 1<<windowBits bytes. If next_out is null, the
|
||||
library will allocate its own buffer (and leave next_out null). next_in
|
||||
need not be provided here but must be provided by the application for the
|
||||
next call of inflate().
|
||||
|
||||
If the history buffer is provided by the application, next_out must
|
||||
never be changed by the application since the decompressor maintains
|
||||
history information inside this buffer from call to call; the application
|
||||
can only reset next_out to the beginning of the history buffer when
|
||||
avail_out is zero and all output has been consumed.
|
||||
|
||||
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
|
||||
not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
|
||||
windowBits < 8). msg is set to null if there is no error message.
|
||||
inflateInit2 does not perform any decompression: this will be done by
|
||||
inflate().
|
||||
*/
|
||||
|
||||
extern int inflateSync OF((z_stream *strm));
|
||||
/*
|
||||
Skips invalid compressed data until the special marker (see deflate()
|
||||
above) can be found, or until all available input is skipped. No output
|
||||
is provided.
|
||||
|
||||
inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
|
||||
if no more input was provided, Z_DATA_ERROR if no marker has been found,
|
||||
or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
|
||||
case, the application may save the current current value of total_in which
|
||||
indicates where valid compressed data was found. In the error case, the
|
||||
application may repeatedly call inflateSync, providing more input each time,
|
||||
until success or end of the input data.
|
||||
*/
|
||||
|
||||
extern int inflateReset OF((z_stream *strm));
|
||||
/*
|
||||
This function is equivalent to inflateEnd followed by inflateInit,
|
||||
but does not free and reallocate all the internal decompression state.
|
||||
The stream will keep attributes that may have been set by inflateInit2.
|
||||
|
||||
inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
|
||||
stream state was inconsistent (such as zalloc or state being NULL).
|
||||
*/
|
||||
|
||||
extern int inflateIncomp OF((z_stream *strm));
|
||||
/*
|
||||
This function adds the data at next_in (avail_in bytes) to the output
|
||||
history without performing any output. There must be no pending output,
|
||||
and the decompressor must be expecting to see the start of a block.
|
||||
Calling this function is equivalent to decompressing a stored block
|
||||
containing the data at next_in (except that the data is not output).
|
||||
*/
|
||||
|
||||
/* checksum functions */
|
||||
|
||||
/*
|
||||
This function is not related to compression but is exported
|
||||
anyway because it might be useful in applications using the
|
||||
compression library.
|
||||
*/
|
||||
|
||||
extern uLong adler32 OF((uLong adler, Bytef *buf, uInt len));
|
||||
|
||||
/*
|
||||
Update a running Adler-32 checksum with the bytes buf[0..len-1] and
|
||||
return the updated checksum. If buf is NULL, this function returns
|
||||
the required initial value for the checksum.
|
||||
An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
|
||||
much faster. Usage example:
|
||||
|
||||
uLong adler = adler32(0L, Z_NULL, 0);
|
||||
|
||||
while (read_buffer(buffer, length) != EOF) {
|
||||
adler = adler32(adler, buffer, length);
|
||||
}
|
||||
if (adler != original_adler) error();
|
||||
*/
|
||||
|
||||
#ifndef _Z_UTIL_H
|
||||
struct internal_state {int dummy;}; /* hack for buggy compilers */
|
||||
#endif
|
||||
|
||||
#endif /* _ZLIB_H */
|
||||
@@ -47,7 +47,6 @@
|
||||
#define BOOL int
|
||||
#define False 0
|
||||
#define True 1
|
||||
#define Realloc realloc
|
||||
#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2)))
|
||||
#define strequal(a,b) (strcasecmp(a,b)==0)
|
||||
#define BOOLSTR(b) ((b) ? "Yes" : "No")
|
||||
@@ -368,6 +367,7 @@ static int add_a_service(service *pservice, char *name)
|
||||
i = iNumServices;
|
||||
|
||||
ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
|
||||
|
||||
if (ServicePtrs)
|
||||
pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
|
||||
|
||||
|
||||
127
main.c
127
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,27 +48,46 @@ 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_flush(f);
|
||||
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) {
|
||||
printf("\nNumber of files: %d\n", stats.num_files);
|
||||
printf("Number of files transferred: %d\n",
|
||||
stats.num_transferred_files);
|
||||
printf("Total file size: %.0f bytes\n",
|
||||
(double)stats.total_size);
|
||||
printf("Total transferred file size: %.0f bytes\n",
|
||||
(double)stats.total_transferred_size);
|
||||
printf("Literal data: %.0f bytes\n",
|
||||
(double)stats.literal_data);
|
||||
printf("Matched data: %.0f bytes\n",
|
||||
(double)stats.matched_data);
|
||||
printf("File list size: %d\n", stats.flist_size);
|
||||
printf("Total bytes written: %.0f\n",
|
||||
(double)stats.total_written);
|
||||
printf("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)));
|
||||
(double)stats.total_written,
|
||||
(double)stats.total_read,
|
||||
(stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
|
||||
printf("total size is %.0f speedup is %.2f\n",
|
||||
(double)tsize,(1.0*tsize)/(in+out));
|
||||
(double)stats.total_size,
|
||||
(1.0*stats.total_size)/(stats.total_written+stats.total_read));
|
||||
}
|
||||
|
||||
|
||||
@@ -148,40 +169,42 @@ static char *get_local_name(struct file_list *flist,char *name)
|
||||
STRUCT_STAT st;
|
||||
extern int orig_umask;
|
||||
|
||||
if (do_stat(name,&st) == 0) {
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
if (chdir(name) != 0) {
|
||||
rprintf(FERROR,"chdir %s : %s (1)\n",name,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (flist->count > 1) {
|
||||
rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
if (do_stat(name,&st) == 0) {
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
if (!push_dir(name, 0)) {
|
||||
rprintf(FERROR,"push_dir %s : %s (1)\n",
|
||||
name,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (flist->count > 1) {
|
||||
rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
if (flist->count == 1)
|
||||
return name;
|
||||
if (flist->count == 1)
|
||||
return name;
|
||||
|
||||
if (!name)
|
||||
return NULL;
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
if (do_mkdir(name,0777 & ~orig_umask) != 0) {
|
||||
rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
} else {
|
||||
rprintf(FINFO,"created directory %s\n",name);
|
||||
}
|
||||
if (do_mkdir(name,0777 & ~orig_umask) != 0) {
|
||||
rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
} else {
|
||||
rprintf(FINFO,"created directory %s\n",name);
|
||||
}
|
||||
|
||||
if (chdir(name) != 0) {
|
||||
rprintf(FERROR,"chdir %s : %s (2)\n",name,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
if (!push_dir(name, 0)) {
|
||||
rprintf(FERROR,"push_dir %s : %s (2)\n",
|
||||
name,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -198,8 +221,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--;
|
||||
@@ -289,8 +312,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);
|
||||
}
|
||||
@@ -497,6 +520,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);
|
||||
|
||||
32
match.c
32
match.c
@@ -34,13 +34,13 @@ typedef unsigned short tag;
|
||||
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;
|
||||
@@ -100,14 +100,13 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
|
||||
rprintf(FINFO,"match at %d last_match=%d j=%d len=%d n=%d\n",
|
||||
(int)offset,(int)last_match,i,(int)s->sums[i].len,(int)n);
|
||||
|
||||
send_token(f,i,buf,last_match,n,i==-1?0:s->sums[i].len);
|
||||
send_token(f,i,buf,last_match,n,i<0?0:s->sums[i].len);
|
||||
data_transfer += n;
|
||||
|
||||
if (n > 0)
|
||||
write_flush(f);
|
||||
|
||||
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);
|
||||
@@ -212,7 +211,17 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
} else {
|
||||
--k;
|
||||
}
|
||||
|
||||
|
||||
/* By matching early we avoid re-reading the
|
||||
data 3 times in the case where a token
|
||||
match comes a long way after last
|
||||
match. The 3 reads are caused by the
|
||||
running match, the checksum update and the
|
||||
literal send. */
|
||||
if (offset-last_match >= CHUNK_SIZE+s->n &&
|
||||
(end-offset > CHUNK_SIZE)) {
|
||||
matched(f,s,buf,offset - s->n, -2);
|
||||
}
|
||||
} while (++offset < end);
|
||||
|
||||
matched(f,s,buf,len,-1);
|
||||
@@ -266,7 +275,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)
|
||||
@@ -275,7 +284,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);
|
||||
}
|
||||
|
||||
42
options.c
42
options.c
@@ -55,6 +55,7 @@ int am_sender=0;
|
||||
int recurse = 0;
|
||||
int am_daemon=0;
|
||||
int am_client=0;
|
||||
int do_stats=0;
|
||||
|
||||
int block_size=BLOCK_SIZE;
|
||||
|
||||
@@ -74,12 +75,15 @@ 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,"Usage:\t%s [options] src user@host:dest\n",RSYNC_NAME);
|
||||
rprintf(F,"OR\t%s [options] user@host:src dest\n",RSYNC_NAME);
|
||||
rprintf(F,"OR\t%s [options] src dest\n",RSYNC_NAME);
|
||||
rprintf(F,"OR\t%s [options] user@host::src dest\n",RSYNC_NAME);
|
||||
rprintf(F,"OR\t%s [options] src user@host::dest\n",RSYNC_NAME);
|
||||
rprintf(F,"\nOptions:\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,"-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");
|
||||
@@ -109,20 +113,27 @@ void usage(int F)
|
||||
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," --port PORT specify alternate rsyncd port number\n");
|
||||
rprintf(F," --stats give some file transfer stats\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_FORCE,OPT_TIMEOUT,OPT_DAEMON,OPT_CONFIG,OPT_PORT,
|
||||
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS};
|
||||
|
||||
static char *short_options = "oblLWHpguDCtcahvrRIxnSe:B:T:z";
|
||||
|
||||
@@ -135,6 +146,8 @@ static struct option long_options[] = {
|
||||
{"numeric-ids", 0, 0, OPT_NUMERIC_IDS},
|
||||
{"exclude", 1, 0, OPT_EXCLUDE},
|
||||
{"exclude-from",1, 0, OPT_EXCLUDE_FROM},
|
||||
{"include", 1, 0, OPT_INCLUDE},
|
||||
{"include-from",1, 0, OPT_INCLUDE_FROM},
|
||||
{"rsync-path", 1, 0, OPT_RSYNC_PATH},
|
||||
{"one-file-system",0, 0, 'x'},
|
||||
{"ignore-times",0, 0, 'I'},
|
||||
@@ -165,6 +178,7 @@ static struct option long_options[] = {
|
||||
{"temp-dir", 1, 0, 'T'},
|
||||
{"compress", 0, 0, 'z'},
|
||||
{"daemon", 0, 0, OPT_DAEMON},
|
||||
{"stats", 0, 0, OPT_STATS},
|
||||
{"config", 1, 0, OPT_CONFIG},
|
||||
{"port", 1, 0, OPT_PORT},
|
||||
{0,0,0,0}};
|
||||
@@ -213,11 +227,19 @@ void parse_arguments(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case OPT_EXCLUDE:
|
||||
add_exclude(optarg);
|
||||
add_exclude(optarg, 0);
|
||||
break;
|
||||
|
||||
case OPT_INCLUDE:
|
||||
add_exclude(optarg, 1);
|
||||
break;
|
||||
|
||||
case OPT_EXCLUDE_FROM:
|
||||
add_exclude_file(optarg,1);
|
||||
add_exclude_file(optarg,1, 0);
|
||||
break;
|
||||
|
||||
case OPT_INCLUDE_FROM:
|
||||
add_exclude_file(optarg,1, 1);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
@@ -351,6 +373,10 @@ void parse_arguments(int argc, char *argv[])
|
||||
am_daemon = 1;
|
||||
break;
|
||||
|
||||
case OPT_STATS:
|
||||
do_stats = 1;
|
||||
break;
|
||||
|
||||
case OPT_CONFIG:
|
||||
config_file = optarg;
|
||||
break;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.0.10
|
||||
Version: 2.0.16
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.0.10.tar.gz
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.0.16.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
1
params.c
1
params.c
@@ -77,7 +77,6 @@
|
||||
#define BOOL int
|
||||
#define False 0
|
||||
#define True 1
|
||||
#define Realloc realloc
|
||||
|
||||
/* -------------------------------------------------------------------------- **
|
||||
* Constants...
|
||||
|
||||
448
rsync.c
448
rsync.c
@@ -51,6 +51,7 @@ extern int am_root;
|
||||
extern int relative_paths;
|
||||
extern int io_timeout;
|
||||
extern int io_error;
|
||||
extern struct stats stats;
|
||||
|
||||
/*
|
||||
free a sums struct
|
||||
@@ -74,6 +75,7 @@ static int delete_file(char *fname)
|
||||
extern int force_delete;
|
||||
STRUCT_STAT st;
|
||||
int ret;
|
||||
extern int recurse;
|
||||
|
||||
if (do_unlink(fname) == 0 || errno == ENOENT) return 0;
|
||||
|
||||
@@ -93,7 +95,8 @@ static int delete_file(char *fname)
|
||||
}
|
||||
|
||||
if (do_rmdir(fname) == 0 || errno == ENOENT) return 0;
|
||||
if (!force_delete || (errno != ENOTEMPTY && errno != EEXIST)) {
|
||||
if (!force_delete || !recurse ||
|
||||
(errno != ENOTEMPTY && errno != EEXIST)) {
|
||||
rprintf(FERROR,"rmdir(%s) : %s\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
@@ -147,7 +150,6 @@ static void send_sums(struct sum_struct *s,int f_out)
|
||||
write_int(f_out,s->sums[i].sum1);
|
||||
write_buf(f_out,s->sums[i].sum2,csum_length);
|
||||
}
|
||||
write_flush(f_out);
|
||||
}
|
||||
|
||||
|
||||
@@ -267,6 +269,7 @@ static int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
{
|
||||
int updated = 0;
|
||||
STRUCT_STAT st2;
|
||||
extern int am_daemon;
|
||||
|
||||
if (dry_run) return 0;
|
||||
|
||||
@@ -300,8 +303,9 @@ static int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((am_root && preserve_uid && st->st_uid != file->uid) ||
|
||||
(preserve_gid && st->st_gid != file->gid)) {
|
||||
if ((am_root || !am_daemon) &&
|
||||
((am_root && preserve_uid && st->st_uid != file->uid) ||
|
||||
(preserve_gid && st->st_gid != file->gid))) {
|
||||
if (do_lchown(fname,
|
||||
(am_root&&preserve_uid)?file->uid:-1,
|
||||
preserve_gid?file->gid:-1) != 0) {
|
||||
@@ -526,7 +530,6 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
|
||||
write_int(f_out,i);
|
||||
send_sums(s,f_out);
|
||||
write_flush(f_out);
|
||||
|
||||
close(fd);
|
||||
if (buf) unmap_file(buf);
|
||||
@@ -557,6 +560,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname)
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"data recv %d at %d\n",i,(int)offset);
|
||||
|
||||
stats.literal_data += i;
|
||||
sum_update(data,i);
|
||||
|
||||
if (fd != -1 && write_file(fd,data,i) != i) {
|
||||
@@ -571,6 +575,8 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname)
|
||||
if (i == count-1 && remainder != 0)
|
||||
len = remainder;
|
||||
|
||||
stats.matched_data += len;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"chunk[%d] of size %d at %d offset=%d\n",
|
||||
i,len,(int)offset2,(int)offset);
|
||||
@@ -636,11 +642,7 @@ static void add_delete_entry(struct file_struct *file)
|
||||
{
|
||||
if (dlist_len == dlist_alloc_len) {
|
||||
dlist_alloc_len += 1024;
|
||||
if (!delete_list) {
|
||||
delete_list = (struct delete_list *)malloc(sizeof(delete_list[0])*dlist_alloc_len);
|
||||
} else {
|
||||
delete_list = (struct delete_list *)realloc(delete_list, sizeof(delete_list[0])*dlist_alloc_len);
|
||||
}
|
||||
delete_list = (struct delete_list *)Realloc(delete_list, sizeof(delete_list[0])*dlist_alloc_len);
|
||||
if (!delete_list) out_of_memory("add_delete_entry");
|
||||
}
|
||||
|
||||
@@ -694,7 +696,8 @@ static void delete_files(struct file_list *flist)
|
||||
if (!S_ISDIR(flist->files[j]->mode) ||
|
||||
!(flist->files[j]->flags & FLAG_DELETE)) continue;
|
||||
|
||||
if (delete_already_done(flist, j)) continue;
|
||||
if (remote_version < 19 &&
|
||||
delete_already_done(flist, j)) continue;
|
||||
|
||||
name = strdup(f_name(flist->files[j]));
|
||||
|
||||
@@ -708,7 +711,8 @@ static void delete_files(struct file_list *flist)
|
||||
|
||||
for (i=local_file_list->count-1;i>=0;i--) {
|
||||
if (!local_file_list->files[i]->basename) continue;
|
||||
if (S_ISDIR(local_file_list->files[i]->mode))
|
||||
if (remote_version < 19 &&
|
||||
S_ISDIR(local_file_list->files[i]->mode))
|
||||
add_delete_entry(local_file_list->files[i]);
|
||||
if (-1 == flist_find(flist,local_file_list->files[i])) {
|
||||
delete_one(local_file_list->files[i]);
|
||||
@@ -739,216 +743,237 @@ void sig_int(void)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int get_tmpname(char *fnametmp, char *fname)
|
||||
{
|
||||
char *f;
|
||||
|
||||
/* open tmp file */
|
||||
if (tmpdir) {
|
||||
f = strrchr(fname,'/');
|
||||
if (f == NULL)
|
||||
f = fname;
|
||||
else
|
||||
f++;
|
||||
if (strlen(tmpdir)+strlen(f)+10 > MAXPATHLEN) {
|
||||
rprintf(FERROR,"filename too long\n");
|
||||
return 0;
|
||||
}
|
||||
slprintf(fnametmp,MAXPATHLEN-1, "%s/.%s.XXXXXX",tmpdir,f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
f = strrchr(fname,'/');
|
||||
|
||||
if (strlen(fname)+9 > MAXPATHLEN) {
|
||||
rprintf(FERROR,"filename too long\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (f) {
|
||||
*f = 0;
|
||||
slprintf(fnametmp,MAXPATHLEN-1,"%s/.%s.XXXXXX",
|
||||
fname,f+1);
|
||||
*f = '/';
|
||||
} else {
|
||||
slprintf(fnametmp,MAXPATHLEN-1,".%s.XXXXXX",fname);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
{
|
||||
int fd1,fd2;
|
||||
STRUCT_STAT st;
|
||||
char *fname;
|
||||
char fnametmp[MAXPATHLEN];
|
||||
struct map_struct *buf;
|
||||
int i;
|
||||
struct file_struct *file;
|
||||
int phase=0;
|
||||
int recv_ok;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
|
||||
}
|
||||
|
||||
if (recurse && delete_mode && !local_name && flist->count>0) {
|
||||
delete_files(flist);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
i = read_int(f_in);
|
||||
if (i == -1) {
|
||||
if (phase==0 && remote_version >= 13) {
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files phase=%d\n",phase);
|
||||
write_int(f_gen,-1);
|
||||
write_flush(f_gen);
|
||||
continue;
|
||||
int fd1,fd2;
|
||||
STRUCT_STAT st;
|
||||
char *fname;
|
||||
char fnametmp[MAXPATHLEN];
|
||||
struct map_struct *buf;
|
||||
int i;
|
||||
struct file_struct *file;
|
||||
int phase=0;
|
||||
int recv_ok;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
file = flist->files[i];
|
||||
fname = f_name(file);
|
||||
if (recurse && delete_mode && !local_name && flist->count>0) {
|
||||
delete_files(flist);
|
||||
}
|
||||
|
||||
if (local_name)
|
||||
fname = local_name;
|
||||
while (1) {
|
||||
i = read_int(f_in);
|
||||
if (i == -1) {
|
||||
if (phase==0 && remote_version >= 13) {
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files phase=%d\n",phase);
|
||||
write_int(f_gen,-1);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (dry_run) {
|
||||
if (!am_server && verbose)
|
||||
printf("%s\n",fname);
|
||||
continue;
|
||||
}
|
||||
if (i < 0 || i >= flist->count) {
|
||||
rprintf(FERROR,"Invalid file index %d in recv_files (count=%d)\n",
|
||||
i, flist->count);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files(%s)\n",fname);
|
||||
file = flist->files[i];
|
||||
fname = f_name(file);
|
||||
|
||||
/* open the file */
|
||||
fd1 = open(fname,O_RDONLY);
|
||||
stats.num_transferred_files++;
|
||||
stats.total_transferred_size += file->length;
|
||||
|
||||
if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
|
||||
rprintf(FERROR,"fstat %s : %s\n",fname,strerror(errno));
|
||||
receive_data(f_in,NULL,-1,NULL);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
if (local_name)
|
||||
fname = local_name;
|
||||
|
||||
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
|
||||
rprintf(FERROR,"%s : not a regular file (recv_files)\n",fname);
|
||||
receive_data(f_in,NULL,-1,NULL);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
if (dry_run) {
|
||||
if (!am_server && verbose)
|
||||
printf("%s\n",fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && st.st_size > 0) {
|
||||
buf = map_file(fd1,st.st_size);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv mapped %s of size %d\n",fname,(int)st.st_size);
|
||||
} else {
|
||||
buf = NULL;
|
||||
}
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files(%s)\n",fname);
|
||||
|
||||
/* open tmp file */
|
||||
if (tmpdir) {
|
||||
char *f;
|
||||
f = strrchr(fname,'/');
|
||||
if (f == NULL)
|
||||
f = fname;
|
||||
else
|
||||
f++;
|
||||
if (strlen(tmpdir)+strlen(f)+10 > MAXPATHLEN) {
|
||||
rprintf(FERROR,"filename too long\n");
|
||||
if (buf) unmap_file(buf);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
slprintf(fnametmp,sizeof(fnametmp)-1, "%s/.%s.XXXXXX",tmpdir,f);
|
||||
} else {
|
||||
char *f = strrchr(fname,'/');
|
||||
/* open the file */
|
||||
fd1 = open(fname,O_RDONLY);
|
||||
|
||||
if (strlen(fname)+9 > MAXPATHLEN) {
|
||||
rprintf(FERROR,"filename too long\n");
|
||||
if (buf) unmap_file(buf);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
|
||||
rprintf(FERROR,"fstat %s : %s\n",fname,strerror(errno));
|
||||
receive_data(f_in,NULL,-1,NULL);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (f) {
|
||||
*f = 0;
|
||||
slprintf(fnametmp,sizeof(fnametmp)-1,"%s/.%s.XXXXXX",fname,f+1);
|
||||
*f = '/';
|
||||
} else {
|
||||
slprintf(fnametmp,sizeof(fnametmp)-1,".%s.XXXXXX",fname);
|
||||
}
|
||||
}
|
||||
if (NULL == do_mktemp(fnametmp)) {
|
||||
rprintf(FERROR,"mktemp %s failed\n",fnametmp);
|
||||
receive_data(f_in,buf,-1,NULL);
|
||||
if (buf) unmap_file(buf);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,file->mode);
|
||||
if (fd2 == -1 && relative_paths && errno == ENOENT &&
|
||||
create_directory_path(fnametmp) == 0) {
|
||||
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,file->mode);
|
||||
}
|
||||
if (fd2 == -1) {
|
||||
rprintf(FERROR,"open %s : %s\n",fnametmp,strerror(errno));
|
||||
receive_data(f_in,buf,-1,NULL);
|
||||
if (buf) unmap_file(buf);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
|
||||
rprintf(FERROR,"%s : not a regular file (recv_files)\n",fname);
|
||||
receive_data(f_in,NULL,-1,NULL);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && st.st_size > 0) {
|
||||
buf = map_file(fd1,st.st_size);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv mapped %s of size %d\n",fname,(int)st.st_size);
|
||||
} else {
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (!get_tmpname(fnametmp,fname)) {
|
||||
if (buf) unmap_file(buf);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NULL == do_mktemp(fnametmp)) {
|
||||
rprintf(FERROR,"mktemp %s failed\n",fnametmp);
|
||||
receive_data(f_in,buf,-1,NULL);
|
||||
if (buf) unmap_file(buf);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,file->mode);
|
||||
if (fd2 == -1 && relative_paths && errno == ENOENT &&
|
||||
create_directory_path(fnametmp) == 0) {
|
||||
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,file->mode);
|
||||
}
|
||||
if (fd2 == -1) {
|
||||
rprintf(FERROR,"open %s : %s\n",fnametmp,strerror(errno));
|
||||
receive_data(f_in,buf,-1,NULL);
|
||||
if (buf) unmap_file(buf);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
cleanup_fname = fnametmp;
|
||||
cleanup_fname = fnametmp;
|
||||
|
||||
if (!am_server && verbose)
|
||||
printf("%s\n",fname);
|
||||
if (!am_server && verbose)
|
||||
printf("%s\n",fname);
|
||||
|
||||
/* recv file data */
|
||||
recv_ok = receive_data(f_in,buf,fd2,fname);
|
||||
|
||||
if (buf) unmap_file(buf);
|
||||
if (fd1 != -1) {
|
||||
close(fd1);
|
||||
}
|
||||
close(fd2);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
|
||||
|
||||
if (make_backups) {
|
||||
char fnamebak[MAXPATHLEN];
|
||||
if (strlen(fname) + strlen(backup_suffix) > (MAXPATHLEN-1)) {
|
||||
rprintf(FERROR,"backup filename too long\n");
|
||||
continue;
|
||||
}
|
||||
slprintf(fnamebak,sizeof(fnamebak)-1,"%s%s",fname,backup_suffix);
|
||||
if (do_rename(fname,fnamebak) != 0 && errno != ENOENT) {
|
||||
rprintf(FERROR,"rename %s %s : %s\n",fname,fnamebak,strerror(errno));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* recv file data */
|
||||
recv_ok = receive_data(f_in,buf,fd2,fname);
|
||||
/* move tmp file over real file */
|
||||
if (do_rename(fnametmp,fname) != 0) {
|
||||
if (errno == EXDEV) {
|
||||
/* rename failed on cross-filesystem link.
|
||||
Copy the file instead. */
|
||||
if (copy_file(fnametmp,fname, file->mode)) {
|
||||
rprintf(FERROR,"copy %s -> %s : %s\n",
|
||||
fnametmp,fname,strerror(errno));
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
}
|
||||
do_unlink(fnametmp);
|
||||
} else {
|
||||
rprintf(FERROR,"rename %s -> %s : %s\n",
|
||||
fnametmp,fname,strerror(errno));
|
||||
do_unlink(fnametmp);
|
||||
}
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
}
|
||||
|
||||
if (buf) unmap_file(buf);
|
||||
if (fd1 != -1) {
|
||||
close(fd1);
|
||||
}
|
||||
close(fd2);
|
||||
cleanup_fname = NULL;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
|
||||
|
||||
if (make_backups) {
|
||||
char fnamebak[MAXPATHLEN];
|
||||
if (strlen(fname) + strlen(backup_suffix) > (MAXPATHLEN-1)) {
|
||||
rprintf(FERROR,"backup filename too long\n");
|
||||
continue;
|
||||
|
||||
if (!recv_ok) {
|
||||
if (csum_length == SUM_LENGTH) {
|
||||
rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
|
||||
fname);
|
||||
} else {
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO,"redoing %s(%d)\n",fname,i);
|
||||
write_int(f_gen,i);
|
||||
}
|
||||
}
|
||||
}
|
||||
slprintf(fnamebak,sizeof(fnamebak)-1,"%s%s",fname,backup_suffix);
|
||||
if (do_rename(fname,fnamebak) != 0 && errno != ENOENT) {
|
||||
rprintf(FERROR,"rename %s %s : %s\n",fname,fnamebak,strerror(errno));
|
||||
continue;
|
||||
|
||||
if (preserve_hard_links)
|
||||
do_hard_links(flist);
|
||||
|
||||
/* now we need to fix any directory permissions that were
|
||||
modified during the transfer */
|
||||
for (i = 0; i < flist->count; i++) {
|
||||
file = flist->files[i];
|
||||
if (!file->basename || !S_ISDIR(file->mode)) continue;
|
||||
recv_generator(f_name(file),flist,i,-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* move tmp file over real file */
|
||||
if (do_rename(fnametmp,fname) != 0) {
|
||||
if (errno == EXDEV) {
|
||||
/* rename failed on cross-filesystem link.
|
||||
Copy the file instead. */
|
||||
if (copy_file(fnametmp,fname, file->mode)) {
|
||||
rprintf(FERROR,"copy %s -> %s : %s\n",
|
||||
fnametmp,fname,strerror(errno));
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
}
|
||||
do_unlink(fnametmp);
|
||||
} else {
|
||||
rprintf(FERROR,"rename %s -> %s : %s\n",
|
||||
fnametmp,fname,strerror(errno));
|
||||
do_unlink(fnametmp);
|
||||
}
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
}
|
||||
|
||||
cleanup_fname = NULL;
|
||||
|
||||
|
||||
if (!recv_ok) {
|
||||
if (csum_length == SUM_LENGTH) {
|
||||
rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
|
||||
fname);
|
||||
} else {
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO,"redoing %s(%d)\n",fname,i);
|
||||
write_int(f_gen,i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (preserve_hard_links)
|
||||
do_hard_links(flist);
|
||||
|
||||
/* now we need to fix any directory permissions that were
|
||||
modified during the transfer */
|
||||
for (i = 0; i < flist->count; i++) {
|
||||
struct file_struct *file = flist->files[i];
|
||||
if (!file->basename || !S_ISDIR(file->mode)) continue;
|
||||
recv_generator(f_name(file),flist,i,-1);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files finished\n");
|
||||
|
||||
return 0;
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files finished\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -963,21 +988,21 @@ void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
int i;
|
||||
struct file_struct *file;
|
||||
int phase = 0;
|
||||
int offset=0;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files starting\n");
|
||||
|
||||
setup_nonblocking(f_in,f_out);
|
||||
setup_readbuffer(f_in);
|
||||
|
||||
while (1) {
|
||||
int offset=0;
|
||||
|
||||
i = read_int(f_in);
|
||||
if (i == -1) {
|
||||
if (phase==0 && remote_version >= 13) {
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
write_int(f_out,-1);
|
||||
write_flush(f_out);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files phase=%d\n",phase);
|
||||
continue;
|
||||
@@ -985,8 +1010,17 @@ void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < 0 || i >= flist->count) {
|
||||
rprintf(FERROR,"Invalid file index %d (count=%d)\n",
|
||||
i, flist->count);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
file = flist->files[i];
|
||||
|
||||
stats.num_transferred_files++;
|
||||
stats.total_transferred_size += file->length;
|
||||
|
||||
fname[0] = 0;
|
||||
if (file->basedir) {
|
||||
strlcpy(fname,file->basedir,MAXPATHLEN-1);
|
||||
@@ -1059,7 +1093,6 @@ void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
printf("%s\n",fname+offset);
|
||||
|
||||
match_sums(f_out,s,buf,st.st_size);
|
||||
write_flush(f_out);
|
||||
|
||||
if (buf) unmap_file(buf);
|
||||
close(fd);
|
||||
@@ -1076,7 +1109,6 @@ void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
match_report();
|
||||
|
||||
write_int(f_out,-1);
|
||||
write_flush(f_out);
|
||||
}
|
||||
|
||||
|
||||
@@ -1116,7 +1148,6 @@ void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
|
||||
rprintf(FINFO,"generate_files phase=%d\n",phase);
|
||||
|
||||
write_int(f,-1);
|
||||
write_flush(f);
|
||||
|
||||
/* we expect to just sit around now, so don't exit on a timeout. If we
|
||||
really get a timeout then the other process should exit */
|
||||
@@ -1136,12 +1167,7 @@ void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
|
||||
rprintf(FINFO,"generate_files phase=%d\n",phase);
|
||||
|
||||
write_int(f,-1);
|
||||
write_flush(f);
|
||||
}
|
||||
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"generator wrote %ld\n",(long)write_total());
|
||||
}
|
||||
|
||||
|
||||
|
||||
39
rsync.h
39
rsync.h
@@ -41,7 +41,7 @@
|
||||
#define SAME_TIME (1<<7)
|
||||
|
||||
/* update this if you make incompatible changes */
|
||||
#define PROTOCOL_VERSION 18
|
||||
#define PROTOCOL_VERSION 19
|
||||
#define MIN_PROTOCOL_VERSION 11
|
||||
#define MAX_PROTOCOL_VERSION 30
|
||||
|
||||
@@ -50,14 +50,12 @@
|
||||
#define SPARSE_WRITE_SIZE (1024)
|
||||
#define WRITE_SIZE (32*1024)
|
||||
#define CHUNK_SIZE (32*1024)
|
||||
#define MAX_MAP_SIZE (4*1024*1024)
|
||||
#define IO_BUFFER_SIZE (4096)
|
||||
#define MAX_MAP_SIZE (1*1024*1024)
|
||||
#define IO_BUFFER_SIZE (4092)
|
||||
#define MAX_READ_BUFFER (1024*1024)
|
||||
|
||||
#define MAX_ARGS 1000
|
||||
|
||||
#define BLOCKING_TIMEOUT 10
|
||||
|
||||
#define MPLEX_BASE 7
|
||||
#define FERROR 1
|
||||
#define FINFO 2
|
||||
@@ -142,8 +140,9 @@
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
#if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
|
||||
#include <sys/mman.h>
|
||||
#define USE_MMAP 1
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UTIME_H
|
||||
@@ -281,9 +280,9 @@ 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 {
|
||||
@@ -308,6 +307,28 @@ struct map_struct {
|
||||
OFF_T size, p_offset;
|
||||
};
|
||||
|
||||
struct exclude_struct {
|
||||
char *orig;
|
||||
char *pattern;
|
||||
int regular_exp;
|
||||
int include;
|
||||
int directory;
|
||||
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
|
||||
without breaking existing versions */
|
||||
|
||||
88
rsync.yo
88
rsync.yo
@@ -81,6 +81,9 @@ command line option, or by setting the RSYNC_RSH environment variable.
|
||||
One common substitute is to use ssh, which offers a high degree of
|
||||
security.
|
||||
|
||||
Note that rsync must be installed on both the source and destination
|
||||
machines.
|
||||
|
||||
manpagesection(USAGE)
|
||||
|
||||
You use rsync in the same way you use rcp. You must specify a source
|
||||
@@ -214,9 +217,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
|
||||
@@ -334,23 +340,30 @@ environment variable.
|
||||
dit(bf(--rsync-path PATH)) Use this to specify the path to the copy of
|
||||
rsync on the remote machine. Useful when its not in your path.
|
||||
|
||||
dit(bf(--exclude FILE)) This option allows you to selectively exclude
|
||||
dit(bf(--exclude pattern)) This option allows you to selectively exclude
|
||||
certain files from the list of files to be transferred. This is most
|
||||
useful in combination with a recursive transfer.
|
||||
|
||||
The option FILE can either be a file name or a shell wildcard
|
||||
expression. If it is a directory name then rsync will not recurse into
|
||||
directories of that name.
|
||||
|
||||
You may use as many --exclude options on the command line as you like
|
||||
to build up the list of files to exclude.
|
||||
|
||||
If the filename is a single ! then the exclude list is reset.
|
||||
See the section of exclude patterns for information on the syntax of
|
||||
this option.
|
||||
|
||||
dit(bf(--exclude-from FILE)) This option is similar to the --exclude
|
||||
option, but instead it adds all filenames listed in the file FILE to
|
||||
the exclude list.
|
||||
|
||||
dit(bf(--include pattern)) This option tells rsync to not exclude the
|
||||
specified pattern of filenames. This is useful as it allows you to
|
||||
build up quite complex exclude/include rules.
|
||||
|
||||
See the section of exclude patterns for information on the syntax of
|
||||
this option.
|
||||
|
||||
dit(bf(--include-from FILE)) This specifies a list of include patterns
|
||||
from a file.
|
||||
|
||||
dit(bf(-C, --cvs-exclude)) This is a useful shorthand for excluding a
|
||||
broad range of files that you often don't want to transfer between
|
||||
systems. It uses the same algorithm that CVS uses to determine if
|
||||
@@ -431,8 +444,69 @@ 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.
|
||||
|
||||
enddit()
|
||||
|
||||
manpagesection(EXCLUDE PATTERNS)
|
||||
|
||||
The exclude and include patterns specified to rsync allow for flexible
|
||||
selection of what files to transfer and what files to skip.
|
||||
|
||||
rsync build a ordered list of include/exclude options as specified on
|
||||
the command line. When a filename is encountered rsync then checks the
|
||||
name against each exclude/include pattern in turn. The first matching
|
||||
pattern is acted on. If it is an exclude pattern than that file is
|
||||
skipped. If it is an include pattern then that filename is not
|
||||
skipped. If no matching include/exclude pattern is found then the
|
||||
filename is not skipped.
|
||||
|
||||
The patterns themselves can take several forms. The rules are:
|
||||
|
||||
itemize(
|
||||
it() if the pattern starts with a / then it is matched against the
|
||||
start of the filename, otherwise it is matched against the end of
|
||||
the filename. Thus /foo would match a file called foo
|
||||
at the base of the tree whereas foo would match any file
|
||||
called foo anywhere in the tree.
|
||||
|
||||
it() if the pattern ends with a / then it will only match a
|
||||
directory, not a file, link or device.
|
||||
|
||||
it() if the pattern contains a wildcard character from the set
|
||||
*?[ then regular expression matching is applied using the
|
||||
normal shell filename matching rules. Otherwise a simple string
|
||||
match is used.
|
||||
|
||||
it() if the pattern contains a / (not counting a trailing /) then it
|
||||
is matched against the full filename, including any leading
|
||||
directory. If the pattern doesn't contain a / then it is matched
|
||||
only against the final component of the filename.
|
||||
|
||||
it() if the pattern starts with "+ " (a plus followed by a space)
|
||||
then it is always considered a include pattern, even if specified as
|
||||
part of an exclude option. The "+ " part is discarded before matching.
|
||||
|
||||
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.
|
||||
)
|
||||
|
||||
The +/- rules are most useful in exclude lists, allowing you to have a
|
||||
single exclude list that contains both include and exclude options.
|
||||
|
||||
Here are some examples:
|
||||
|
||||
itemize(
|
||||
it() --exclude "*.o" would exclude all filenames matching *.o
|
||||
it() --exclude "/foo" would exclude a file in the base directory called foo
|
||||
it() --exclude "foo/" would exclude any directory called foo
|
||||
it() --include "*/" --include "*.c" --exclude "*" would include all
|
||||
directories and C source files.
|
||||
)
|
||||
|
||||
manpagefiles()
|
||||
|
||||
/etc/rsyncd.conf
|
||||
|
||||
22
socket.c
22
socket.c
@@ -327,8 +327,10 @@ char *client_name(int fd)
|
||||
int length = sizeof(sa);
|
||||
static char name_buf[100];
|
||||
struct hostent *hp;
|
||||
char **p;
|
||||
char *def = "UNKNOWN";
|
||||
|
||||
strcpy(name_buf,"UNKNOWN");
|
||||
strcpy(name_buf,def);
|
||||
|
||||
if (getpeername(fd, &sa, &length)) {
|
||||
exit_cleanup(1);
|
||||
@@ -341,5 +343,23 @@ char *client_name(int fd)
|
||||
strlcpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1);
|
||||
}
|
||||
|
||||
|
||||
/* do a forward lookup as well to prevent spoofing */
|
||||
hp = gethostbyname(name_buf);
|
||||
if (!hp) {
|
||||
strcpy(name_buf,def);
|
||||
rprintf(FERROR,"reverse name lookup failed\n");
|
||||
} else {
|
||||
for (p=hp->h_addr_list;*p;p++) {
|
||||
if (memcmp(*p, &sockin->sin_addr, hp->h_length) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!*p) {
|
||||
strcpy(name_buf,def);
|
||||
rprintf(FERROR,"reverse name lookup mismatch - spoofed address?\n");
|
||||
}
|
||||
}
|
||||
|
||||
return name_buf;
|
||||
}
|
||||
|
||||
11
syscall.c
11
syscall.c
@@ -149,6 +149,17 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_MMAP
|
||||
void *do_mmap(void *start, int len, int prot, int flags, int fd, OFF_T offset)
|
||||
{
|
||||
#if HAVE_OFF64_T
|
||||
return mmap64(start, len, prot, flags, fd, offset);
|
||||
#else
|
||||
return mmap(start, len, prot, flags, fd, offset);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
char *d_name(struct dirent *di)
|
||||
{
|
||||
#if HAVE_BROKEN_READDIR
|
||||
|
||||
20
test.sh
20
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
|
||||
@@ -98,14 +106,21 @@ cp ${FROM}/${F1} ${TO}/ThisShouldGo
|
||||
checkit "rsync --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO} \
|
||||
5 " --delete"
|
||||
|
||||
LONGDIR=${FROM}/This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job/This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job/This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job
|
||||
mkdir -p ${LONGDIR}
|
||||
date > ${LONGDIR}/1
|
||||
ls -la / > ${LONGDIR}/2
|
||||
checkit "rsync --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO} \
|
||||
6 "long paths"
|
||||
|
||||
if type ssh >/dev/null ; then
|
||||
rm -rf ${TO}
|
||||
checkit "rsync -avH -e ssh ${FROM}/ localhost:${TO}" ${FROM}/ ${TO} \
|
||||
6 "ssh: basic test"
|
||||
7 "ssh: basic test"
|
||||
|
||||
mv ${TO}/${F1} ${TO}/ThisShouldGo
|
||||
checkit "rsync --delete -avH -e ssh ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}\
|
||||
7 "ssh: renamed file"
|
||||
8 "ssh: renamed file"
|
||||
else
|
||||
echo ""
|
||||
echo "**** Skipping SSH tests because ssh is not in the path ****"
|
||||
@@ -113,4 +128,3 @@ else
|
||||
fi
|
||||
|
||||
checkforlogs ${LOG}.?
|
||||
|
||||
|
||||
575
token.c
575
token.c
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
#include "lib/zlib.h"
|
||||
#include "zlib/zlib.h"
|
||||
|
||||
extern int do_compression;
|
||||
|
||||
@@ -26,60 +26,49 @@ extern int do_compression;
|
||||
/* non-compressing recv token */
|
||||
static int simple_recv_token(int f,char **data)
|
||||
{
|
||||
static int residue;
|
||||
static char *buf;
|
||||
int n;
|
||||
static int residue;
|
||||
static char *buf;
|
||||
int n;
|
||||
|
||||
if (!buf) {
|
||||
buf = (char *)malloc(CHUNK_SIZE);
|
||||
if (!buf) out_of_memory("simple_recv_token");
|
||||
}
|
||||
if (!buf) {
|
||||
buf = (char *)malloc(CHUNK_SIZE);
|
||||
if (!buf) out_of_memory("simple_recv_token");
|
||||
}
|
||||
|
||||
if (residue == 0) {
|
||||
int i = read_int(f);
|
||||
if (i <= 0) return i;
|
||||
residue = i;
|
||||
}
|
||||
|
||||
if (residue == 0) {
|
||||
int i = read_int(f);
|
||||
if (i <= 0) return i;
|
||||
residue = i;
|
||||
}
|
||||
|
||||
*data = buf;
|
||||
n = MIN(CHUNK_SIZE,residue);
|
||||
residue -= n;
|
||||
read_buf(f,buf,n);
|
||||
return n;
|
||||
*data = buf;
|
||||
n = MIN(CHUNK_SIZE,residue);
|
||||
residue -= n;
|
||||
read_buf(f,buf,n);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/* non-compressing send token */
|
||||
static void simple_send_token(int f,int token,
|
||||
struct map_struct *buf,int offset,int n)
|
||||
struct map_struct *buf,OFF_T offset,int n)
|
||||
{
|
||||
if (n > 0) {
|
||||
int l = 0;
|
||||
while (l < n) {
|
||||
int n1 = MIN(CHUNK_SIZE,n-l);
|
||||
write_int(f,n1);
|
||||
write_buf(f,map_ptr(buf,offset+l,n1),n1);
|
||||
l += n1;
|
||||
}
|
||||
}
|
||||
write_int(f,-(token+1));
|
||||
if (n > 0) {
|
||||
int l = 0;
|
||||
while (l < n) {
|
||||
int n1 = MIN(CHUNK_SIZE,n-l);
|
||||
write_int(f,n1);
|
||||
write_buf(f,map_ptr(buf,offset+l,n1),n1);
|
||||
l += n1;
|
||||
}
|
||||
}
|
||||
/* a -2 token means to send data only and no token */
|
||||
if (token != -2) {
|
||||
write_int(f,-(token+1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Memory allocation/freeing routines, called by zlib stuff. */
|
||||
static void *
|
||||
z_alloc(void *opaque, uInt items, uInt size)
|
||||
{
|
||||
return malloc(items * size);
|
||||
}
|
||||
|
||||
static void
|
||||
z_free(void *opaque, void *adrs, uInt nbytes)
|
||||
{
|
||||
free(adrs);
|
||||
}
|
||||
|
||||
/* Flag bytes in compressed stream are encoded as follows: */
|
||||
#define END_FLAG 0 /* that's all folks */
|
||||
#define TOKEN_LONG 0x20 /* followed by 32-bit token number */
|
||||
@@ -104,102 +93,131 @@ static char *obuf;
|
||||
/* Send a deflated token */
|
||||
static void
|
||||
send_deflated_token(int f, int token,
|
||||
struct map_struct *buf, int offset, int nb, int toklen)
|
||||
struct map_struct *buf, OFF_T offset, int nb, int toklen)
|
||||
{
|
||||
int n, r;
|
||||
static int init_done;
|
||||
int n, r;
|
||||
static int init_done, flush_pending;
|
||||
|
||||
if (last_token == -1) {
|
||||
/* initialization */
|
||||
if (!init_done) {
|
||||
tx_strm.next_in = NULL;
|
||||
tx_strm.zalloc = z_alloc;
|
||||
tx_strm.zfree = z_free;
|
||||
if (deflateInit2(&tx_strm, Z_DEFAULT_COMPRESSION, 8,
|
||||
-15, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
|
||||
rprintf(FERROR, "compression init failed\n");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
if ((obuf = malloc(MAX_DATA_COUNT+2)) == NULL)
|
||||
out_of_memory("send_deflated_token");
|
||||
init_done = 1;
|
||||
} else
|
||||
deflateReset(&tx_strm);
|
||||
run_start = token;
|
||||
last_run_end = 0;
|
||||
if (last_token == -1) {
|
||||
/* initialization */
|
||||
if (!init_done) {
|
||||
tx_strm.next_in = NULL;
|
||||
tx_strm.zalloc = NULL;
|
||||
tx_strm.zfree = NULL;
|
||||
if (deflateInit2(&tx_strm, Z_DEFAULT_COMPRESSION,
|
||||
Z_DEFLATED, -15, 8,
|
||||
Z_DEFAULT_STRATEGY) != Z_OK) {
|
||||
rprintf(FERROR, "compression init failed\n");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
if ((obuf = malloc(MAX_DATA_COUNT+2)) == NULL)
|
||||
out_of_memory("send_deflated_token");
|
||||
init_done = 1;
|
||||
} else
|
||||
deflateReset(&tx_strm);
|
||||
last_run_end = 0;
|
||||
run_start = token;
|
||||
flush_pending = 0;
|
||||
|
||||
} else if (nb != 0 || token != last_token + 1
|
||||
|| token >= run_start + 65536) {
|
||||
/* output previous run */
|
||||
r = run_start - last_run_end;
|
||||
n = last_token - run_start;
|
||||
if (r >= 0 && r <= 63) {
|
||||
write_byte(f, (n==0? TOKEN_REL: TOKENRUN_REL) + r);
|
||||
} else {
|
||||
write_byte(f, (n==0? TOKEN_LONG: TOKENRUN_LONG));
|
||||
write_int(f, run_start);
|
||||
}
|
||||
if (n != 0) {
|
||||
write_byte(f, n);
|
||||
write_byte(f, n >> 8);
|
||||
}
|
||||
last_run_end = last_token;
|
||||
run_start = token;
|
||||
}
|
||||
} else if (last_token == -2) {
|
||||
run_start = token;
|
||||
|
||||
last_token = token;
|
||||
|
||||
if (nb != 0) {
|
||||
/* deflate the data starting at offset */
|
||||
tx_strm.avail_in = 0;
|
||||
tx_strm.avail_out = 0;
|
||||
do {
|
||||
if (tx_strm.avail_in == 0 && nb != 0) {
|
||||
/* give it some more input */
|
||||
n = MIN(nb, CHUNK_SIZE);
|
||||
tx_strm.next_in = (Bytef *)map_ptr(buf, offset, n);
|
||||
tx_strm.avail_in = n;
|
||||
nb -= n;
|
||||
offset += n;
|
||||
}
|
||||
if (tx_strm.avail_out == 0) {
|
||||
tx_strm.next_out = (Bytef *)(obuf + 2);
|
||||
tx_strm.avail_out = MAX_DATA_COUNT;
|
||||
}
|
||||
r = deflate(&tx_strm, nb? Z_NO_FLUSH: Z_PACKET_FLUSH);
|
||||
if (r != Z_OK) {
|
||||
rprintf(FERROR, "deflate returned %d\n", r);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
if (nb == 0 || tx_strm.avail_out == 0) {
|
||||
n = MAX_DATA_COUNT - tx_strm.avail_out;
|
||||
if (n > 0) {
|
||||
obuf[0] = DEFLATED_DATA + (n >> 8);
|
||||
obuf[1] = n;
|
||||
write_buf(f, obuf, n+2);
|
||||
} else if (nb != 0 || token != last_token + 1
|
||||
|| token >= run_start + 65536) {
|
||||
/* output previous run */
|
||||
r = run_start - last_run_end;
|
||||
n = last_token - run_start;
|
||||
if (r >= 0 && r <= 63) {
|
||||
write_byte(f, (n==0? TOKEN_REL: TOKENRUN_REL) + r);
|
||||
} else {
|
||||
write_byte(f, (n==0? TOKEN_LONG: TOKENRUN_LONG));
|
||||
write_int(f, run_start);
|
||||
}
|
||||
}
|
||||
} while (nb != 0 || tx_strm.avail_out == 0);
|
||||
}
|
||||
|
||||
if (token != -1) {
|
||||
/* add the data in the current block to the compressor's
|
||||
history and hash table */
|
||||
tx_strm.next_in = (Bytef *)map_ptr(buf, offset, toklen);
|
||||
tx_strm.avail_in = toklen;
|
||||
tx_strm.next_out = NULL;
|
||||
tx_strm.avail_out = 2 * toklen;
|
||||
r = deflate(&tx_strm, Z_INSERT_ONLY);
|
||||
if (r != Z_OK || tx_strm.avail_in != 0) {
|
||||
rprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
|
||||
r, tx_strm.avail_in);
|
||||
exit_cleanup(1);
|
||||
if (n != 0) {
|
||||
write_byte(f, n);
|
||||
write_byte(f, n >> 8);
|
||||
}
|
||||
last_run_end = last_token;
|
||||
run_start = token;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* end of file - clean up */
|
||||
write_byte(f, END_FLAG);
|
||||
}
|
||||
last_token = token;
|
||||
|
||||
if (nb != 0 || flush_pending) {
|
||||
/* deflate the data starting at offset */
|
||||
int flush = Z_NO_FLUSH;
|
||||
tx_strm.avail_in = 0;
|
||||
tx_strm.avail_out = 0;
|
||||
do {
|
||||
if (tx_strm.avail_in == 0 && nb != 0) {
|
||||
/* give it some more input */
|
||||
n = MIN(nb, CHUNK_SIZE);
|
||||
tx_strm.next_in = (Bytef *)
|
||||
map_ptr(buf, offset, n);
|
||||
tx_strm.avail_in = n;
|
||||
nb -= n;
|
||||
offset += n;
|
||||
}
|
||||
if (tx_strm.avail_out == 0) {
|
||||
tx_strm.next_out = (Bytef *)(obuf + 2);
|
||||
tx_strm.avail_out = MAX_DATA_COUNT;
|
||||
if (flush != Z_NO_FLUSH) {
|
||||
/*
|
||||
* We left the last 4 bytes in the
|
||||
* buffer, in case they are the
|
||||
* last 4. Move them to the front.
|
||||
*/
|
||||
memcpy(tx_strm.next_out,
|
||||
obuf+MAX_DATA_COUNT-2, 4);
|
||||
tx_strm.next_out += 4;
|
||||
tx_strm.avail_out -= 4;
|
||||
}
|
||||
}
|
||||
if (nb == 0 && token != -2)
|
||||
flush = Z_SYNC_FLUSH;
|
||||
r = deflate(&tx_strm, flush);
|
||||
if (r != Z_OK) {
|
||||
rprintf(FERROR, "deflate returned %d\n", r);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
if (nb == 0 || tx_strm.avail_out == 0) {
|
||||
n = MAX_DATA_COUNT - tx_strm.avail_out;
|
||||
if (flush != Z_NO_FLUSH) {
|
||||
/*
|
||||
* We have to trim off the last 4
|
||||
* bytes of output when flushing
|
||||
* (they are just 0, 0, ff, ff).
|
||||
*/
|
||||
n -= 4;
|
||||
}
|
||||
if (n > 0) {
|
||||
obuf[0] = DEFLATED_DATA + (n >> 8);
|
||||
obuf[1] = n;
|
||||
write_buf(f, obuf, n+2);
|
||||
}
|
||||
}
|
||||
} while (nb != 0 || tx_strm.avail_out == 0);
|
||||
flush_pending = token == -2;
|
||||
}
|
||||
|
||||
if (token == -1) {
|
||||
/* end of file - clean up */
|
||||
write_byte(f, END_FLAG);
|
||||
|
||||
} else if (token != -2) {
|
||||
/* add the data in the current block to the compressor's
|
||||
history and hash table */
|
||||
tx_strm.next_in = (Bytef *) map_ptr(buf, offset, toklen);
|
||||
tx_strm.avail_in = toklen;
|
||||
tx_strm.next_out = (Bytef *) obuf;
|
||||
tx_strm.avail_out = MAX_DATA_COUNT;
|
||||
r = deflate(&tx_strm, Z_INSERT_ONLY);
|
||||
if (r != Z_OK || tx_strm.avail_in != 0) {
|
||||
rprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
|
||||
r, tx_strm.avail_in);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -219,113 +237,129 @@ static int rx_run;
|
||||
static int
|
||||
recv_deflated_token(int f, char **data)
|
||||
{
|
||||
int n, r, flag;
|
||||
static int init_done;
|
||||
static int saved_flag;
|
||||
int n, r, flag;
|
||||
static int init_done;
|
||||
static int saved_flag;
|
||||
|
||||
for (;;) {
|
||||
switch (recv_state) {
|
||||
case r_init:
|
||||
if (!init_done) {
|
||||
rx_strm.next_out = NULL;
|
||||
rx_strm.zalloc = z_alloc;
|
||||
rx_strm.zfree = z_free;
|
||||
if (inflateInit2(&rx_strm, -15) != Z_OK) {
|
||||
rprintf(FERROR, "inflate init failed\n");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
if ((cbuf = malloc(MAX_DATA_COUNT)) == NULL
|
||||
|| (dbuf = malloc(CHUNK_SIZE)) == NULL)
|
||||
out_of_memory("recv_deflated_token");
|
||||
init_done = 1;
|
||||
} else {
|
||||
inflateReset(&rx_strm);
|
||||
}
|
||||
recv_state = r_idle;
|
||||
rx_token = 0;
|
||||
break;
|
||||
|
||||
case r_idle:
|
||||
case r_inflated:
|
||||
if (saved_flag) {
|
||||
flag = saved_flag & 0xff;
|
||||
saved_flag = 0;
|
||||
} else
|
||||
flag = read_byte(f);
|
||||
if ((flag & 0xC0) == DEFLATED_DATA) {
|
||||
n = ((flag & 0x3f) << 8) + read_byte(f);
|
||||
read_buf(f, cbuf, n);
|
||||
rx_strm.next_in = (Bytef *)cbuf;
|
||||
rx_strm.avail_in = n;
|
||||
recv_state = r_inflating;
|
||||
break;
|
||||
}
|
||||
if (recv_state == r_inflated) {
|
||||
/* check previous inflated stuff ended correctly */
|
||||
rx_strm.avail_in = 0;
|
||||
rx_strm.next_out = (Bytef *)dbuf;
|
||||
rx_strm.avail_out = CHUNK_SIZE;
|
||||
r = inflate(&rx_strm, Z_PACKET_FLUSH);
|
||||
n = CHUNK_SIZE - rx_strm.avail_out;
|
||||
if (r != Z_OK) {
|
||||
rprintf(FERROR, "inflate flush returned %d (%d bytes)\n",
|
||||
r, n);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
if (n != 0) {
|
||||
/* have to return some more data and
|
||||
save the flag for later. */
|
||||
saved_flag = flag + 0x10000;
|
||||
if (rx_strm.avail_out != 0)
|
||||
for (;;) {
|
||||
switch (recv_state) {
|
||||
case r_init:
|
||||
if (!init_done) {
|
||||
rx_strm.next_out = NULL;
|
||||
rx_strm.zalloc = NULL;
|
||||
rx_strm.zfree = NULL;
|
||||
if (inflateInit2(&rx_strm, -15) != Z_OK) {
|
||||
rprintf(FERROR, "inflate init failed\n");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
if ((cbuf = malloc(MAX_DATA_COUNT)) == NULL
|
||||
|| (dbuf = malloc(CHUNK_SIZE)) == NULL)
|
||||
out_of_memory("recv_deflated_token");
|
||||
init_done = 1;
|
||||
} else {
|
||||
inflateReset(&rx_strm);
|
||||
}
|
||||
recv_state = r_idle;
|
||||
*data = dbuf;
|
||||
return n;
|
||||
rx_token = 0;
|
||||
break;
|
||||
|
||||
case r_idle:
|
||||
case r_inflated:
|
||||
if (saved_flag) {
|
||||
flag = saved_flag & 0xff;
|
||||
saved_flag = 0;
|
||||
} else
|
||||
flag = read_byte(f);
|
||||
if ((flag & 0xC0) == DEFLATED_DATA) {
|
||||
n = ((flag & 0x3f) << 8) + read_byte(f);
|
||||
read_buf(f, cbuf, n);
|
||||
rx_strm.next_in = (Bytef *)cbuf;
|
||||
rx_strm.avail_in = n;
|
||||
recv_state = r_inflating;
|
||||
break;
|
||||
}
|
||||
if (recv_state == r_inflated) {
|
||||
/* check previous inflated stuff ended correctly */
|
||||
rx_strm.avail_in = 0;
|
||||
rx_strm.next_out = (Bytef *)dbuf;
|
||||
rx_strm.avail_out = CHUNK_SIZE;
|
||||
r = inflate(&rx_strm, Z_SYNC_FLUSH);
|
||||
n = CHUNK_SIZE - rx_strm.avail_out;
|
||||
/*
|
||||
* Z_BUF_ERROR just means no progress was
|
||||
* made, i.e. the decompressor didn't have
|
||||
* any pending output for us.
|
||||
*/
|
||||
if (r != Z_OK && r != Z_BUF_ERROR) {
|
||||
rprintf(FERROR, "inflate flush returned %d (%d bytes)\n",
|
||||
r, n);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
if (n != 0 && r != Z_BUF_ERROR) {
|
||||
/* have to return some more data and
|
||||
save the flag for later. */
|
||||
saved_flag = flag + 0x10000;
|
||||
*data = dbuf;
|
||||
return n;
|
||||
}
|
||||
/*
|
||||
* At this point the decompressor should
|
||||
* be expecting to see the 0, 0, ff, ff bytes.
|
||||
*/
|
||||
if (!inflateSyncPoint(&rx_strm)) {
|
||||
rprintf(FERROR, "decompressor lost sync!\n");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
rx_strm.avail_in = 4;
|
||||
rx_strm.next_in = (Bytef *)cbuf;
|
||||
cbuf[0] = cbuf[1] = 0;
|
||||
cbuf[2] = cbuf[3] = 0xff;
|
||||
inflate(&rx_strm, Z_SYNC_FLUSH);
|
||||
recv_state = r_idle;
|
||||
}
|
||||
if (flag == END_FLAG) {
|
||||
/* that's all folks */
|
||||
recv_state = r_init;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* here we have a token of some kind */
|
||||
if (flag & TOKEN_REL) {
|
||||
rx_token += flag & 0x3f;
|
||||
flag >>= 6;
|
||||
} else
|
||||
rx_token = read_int(f);
|
||||
if (flag & 1) {
|
||||
rx_run = read_byte(f);
|
||||
rx_run += read_byte(f) << 8;
|
||||
recv_state = r_running;
|
||||
}
|
||||
return -1 - rx_token;
|
||||
|
||||
case r_inflating:
|
||||
rx_strm.next_out = (Bytef *)dbuf;
|
||||
rx_strm.avail_out = CHUNK_SIZE;
|
||||
r = inflate(&rx_strm, Z_NO_FLUSH);
|
||||
n = CHUNK_SIZE - rx_strm.avail_out;
|
||||
if (r != Z_OK) {
|
||||
rprintf(FERROR, "inflate returned %d (%d bytes)\n", r, n);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
if (rx_strm.avail_in == 0)
|
||||
recv_state = r_inflated;
|
||||
if (n != 0) {
|
||||
*data = dbuf;
|
||||
return n;
|
||||
}
|
||||
break;
|
||||
|
||||
case r_running:
|
||||
++rx_token;
|
||||
if (--rx_run == 0)
|
||||
recv_state = r_idle;
|
||||
return -1 - rx_token;
|
||||
}
|
||||
recv_state = r_idle;
|
||||
}
|
||||
if (flag == END_FLAG) {
|
||||
/* that's all folks */
|
||||
recv_state = r_init;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* here we have a token of some kind */
|
||||
if (flag & TOKEN_REL) {
|
||||
rx_token += flag & 0x3f;
|
||||
flag >>= 6;
|
||||
} else
|
||||
rx_token = read_int(f);
|
||||
if (flag & 1) {
|
||||
rx_run = read_byte(f);
|
||||
rx_run += read_byte(f) << 8;
|
||||
recv_state = r_running;
|
||||
}
|
||||
return -1 - rx_token;
|
||||
|
||||
case r_inflating:
|
||||
rx_strm.next_out = (Bytef *)dbuf;
|
||||
rx_strm.avail_out = CHUNK_SIZE;
|
||||
r = inflate(&rx_strm, Z_NO_FLUSH);
|
||||
n = CHUNK_SIZE - rx_strm.avail_out;
|
||||
if (r != Z_OK) {
|
||||
rprintf(FERROR, "inflate returned %d (%d bytes)\n", r, n);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
if (rx_strm.avail_in == 0)
|
||||
recv_state = r_inflated;
|
||||
if (n != 0) {
|
||||
*data = dbuf;
|
||||
return n;
|
||||
}
|
||||
break;
|
||||
|
||||
case r_running:
|
||||
++rx_token;
|
||||
if (--rx_run == 0)
|
||||
recv_state = r_idle;
|
||||
return -1 - rx_token;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -335,15 +369,40 @@ recv_deflated_token(int f, char **data)
|
||||
void
|
||||
see_deflate_token(char *buf, int len)
|
||||
{
|
||||
int r;
|
||||
int r, blklen;
|
||||
unsigned char hdr[5];
|
||||
|
||||
rx_strm.next_in = (Bytef *)buf;
|
||||
rx_strm.avail_in = len;
|
||||
r = inflateIncomp(&rx_strm);
|
||||
if (r != Z_OK) {
|
||||
rprintf(FERROR, "inflateIncomp returned %d\n", r);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
rx_strm.avail_in = 0;
|
||||
blklen = 0;
|
||||
hdr[0] = 0;
|
||||
do {
|
||||
if (rx_strm.avail_in == 0 && len != 0) {
|
||||
if (blklen == 0) {
|
||||
/* Give it a fake stored-block header. */
|
||||
rx_strm.next_in = (Bytef *)hdr;
|
||||
rx_strm.avail_in = 5;
|
||||
blklen = len;
|
||||
if (blklen > 0xffff)
|
||||
blklen = 0xffff;
|
||||
hdr[1] = blklen;
|
||||
hdr[2] = blklen >> 8;
|
||||
hdr[3] = ~hdr[1];
|
||||
hdr[4] = ~hdr[2];
|
||||
} else {
|
||||
rx_strm.next_in = (Bytef *)buf;
|
||||
rx_strm.avail_in = blklen;
|
||||
len -= blklen;
|
||||
blklen = 0;
|
||||
}
|
||||
}
|
||||
rx_strm.next_out = (Bytef *)dbuf;
|
||||
rx_strm.avail_out = CHUNK_SIZE;
|
||||
r = inflate(&rx_strm, Z_SYNC_FLUSH);
|
||||
if (r != Z_OK) {
|
||||
rprintf(FERROR, "inflate (token) returned %d\n", r);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
} while (len || rx_strm.avail_out == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -351,14 +410,14 @@ see_deflate_token(char *buf, int len)
|
||||
* If token == -1 then we have reached EOF
|
||||
* If n == 0 then don't send a buffer
|
||||
*/
|
||||
void send_token(int f,int token,struct map_struct *buf,int offset,
|
||||
void send_token(int f,int token,struct map_struct *buf,OFF_T offset,
|
||||
int n,int toklen)
|
||||
{
|
||||
if (!do_compression) {
|
||||
simple_send_token(f,token,buf,offset,n);
|
||||
} else {
|
||||
send_deflated_token(f, token, buf, offset, n, toklen);
|
||||
}
|
||||
if (!do_compression) {
|
||||
simple_send_token(f,token,buf,offset,n);
|
||||
} else {
|
||||
send_deflated_token(f, token, buf, offset, n, toklen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -370,14 +429,14 @@ void send_token(int f,int token,struct map_struct *buf,int offset,
|
||||
*/
|
||||
int recv_token(int f,char **data)
|
||||
{
|
||||
int tok;
|
||||
int tok;
|
||||
|
||||
if (!do_compression) {
|
||||
tok = simple_recv_token(f,data);
|
||||
} else {
|
||||
tok = recv_deflated_token(f, data);
|
||||
}
|
||||
return tok;
|
||||
if (!do_compression) {
|
||||
tok = simple_recv_token(f,data);
|
||||
} else {
|
||||
tok = recv_deflated_token(f, data);
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -385,6 +444,6 @@ int recv_token(int f,char **data)
|
||||
*/
|
||||
void see_token(char *data, int toklen)
|
||||
{
|
||||
if (do_compression)
|
||||
see_deflate_token(data, toklen);
|
||||
if (do_compression)
|
||||
see_deflate_token(data, toklen);
|
||||
}
|
||||
|
||||
228
util.c
228
util.c
@@ -32,90 +32,6 @@ int num_waiting(int fd)
|
||||
}
|
||||
|
||||
|
||||
struct map_struct *map_file(int fd,OFF_T len)
|
||||
{
|
||||
struct map_struct *ret;
|
||||
ret = (struct map_struct *)malloc(sizeof(*ret));
|
||||
if (!ret) out_of_memory("map_file");
|
||||
|
||||
ret->map = NULL;
|
||||
ret->fd = fd;
|
||||
ret->size = len;
|
||||
ret->p = NULL;
|
||||
ret->p_size = 0;
|
||||
ret->p_offset = 0;
|
||||
ret->p_len = 0;
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
if (len < MAX_MAP_SIZE) {
|
||||
ret->map = (char *)mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0);
|
||||
if (ret->map == (char *)-1) {
|
||||
ret->map = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
char *map_ptr(struct map_struct *map,OFF_T offset,int len)
|
||||
{
|
||||
int nread;
|
||||
|
||||
if (map->map)
|
||||
return map->map+offset;
|
||||
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
|
||||
if (len > (map->size-offset))
|
||||
len = map->size-offset;
|
||||
|
||||
if (offset >= map->p_offset &&
|
||||
offset+len <= map->p_offset+map->p_len) {
|
||||
return (map->p + (offset - map->p_offset));
|
||||
}
|
||||
|
||||
len = MAX(len,CHUNK_SIZE);
|
||||
if (len > (map->size-offset))
|
||||
len = map->size-offset;
|
||||
|
||||
if (len > map->p_size) {
|
||||
if (map->p) free(map->p);
|
||||
map->p = (char *)malloc(len);
|
||||
if (!map->p) out_of_memory("map_ptr");
|
||||
map->p_size = len;
|
||||
}
|
||||
|
||||
map->p_offset = offset;
|
||||
map->p_len = len;
|
||||
|
||||
if (do_lseek(map->fd,offset,SEEK_SET) != offset) {
|
||||
rprintf(FERROR,"lseek failed in map_ptr\n");
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
if ((nread=read(map->fd,map->p,len)) != len) {
|
||||
if (nread < 0) nread = 0;
|
||||
/* the best we can do is zero the buffer - the file
|
||||
has changed mid transfer! */
|
||||
memset(map->p+nread, 0, len - nread);
|
||||
}
|
||||
|
||||
return map->p;
|
||||
}
|
||||
|
||||
|
||||
void unmap_file(struct map_struct *map)
|
||||
{
|
||||
#ifdef HAVE_MMAP
|
||||
if (map->map)
|
||||
munmap(map->map,map->size);
|
||||
#endif
|
||||
if (map->p) free(map->p);
|
||||
free(map);
|
||||
}
|
||||
|
||||
|
||||
/* this is taken from CVS */
|
||||
int piped_child(char **command,int *f_in,int *f_out)
|
||||
@@ -261,36 +177,6 @@ int set_modtime(char *fname,time_t modtime)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
|
||||
else
|
||||
if SYSV use O_NDELAY
|
||||
if BSD use FNDELAY
|
||||
****************************************************************************/
|
||||
int set_blocking(int fd, int set)
|
||||
{
|
||||
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;
|
||||
if(set) /* Turn blocking on - ie. clear nonblock flag */
|
||||
val &= ~FLAG_TO_SET;
|
||||
else
|
||||
val |= FLAG_TO_SET;
|
||||
return fcntl( fd, F_SETFL, val);
|
||||
#undef FLAG_TO_SET
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
create any necessary directories in fname. Unfortunately we don't know
|
||||
what perms to give the directory when this is called so we need to rely
|
||||
@@ -667,3 +553,117 @@ int slprintf(char *str, int n, char *format, ...)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void *Realloc(void *p, int size)
|
||||
{
|
||||
if (!p) return (void *)malloc(size);
|
||||
return (void *)realloc(p, size);
|
||||
}
|
||||
|
||||
|
||||
void clean_fname(char *name)
|
||||
{
|
||||
char *p;
|
||||
int l;
|
||||
int modified = 1;
|
||||
|
||||
if (!name) return;
|
||||
|
||||
while (modified) {
|
||||
modified = 0;
|
||||
|
||||
if ((p=strstr(name,"/./"))) {
|
||||
modified = 1;
|
||||
while (*p) {
|
||||
p[0] = p[2];
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((p=strstr(name,"//"))) {
|
||||
modified = 1;
|
||||
while (*p) {
|
||||
p[0] = p[1];
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(p=name,"./",2) == 0) {
|
||||
modified = 1;
|
||||
do {
|
||||
p[0] = p[2];
|
||||
} while (*p++);
|
||||
}
|
||||
|
||||
l = strlen(p=name);
|
||||
if (l > 1 && p[l-1] == '/') {
|
||||
modified = 1;
|
||||
p[l-1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char curr_dir[MAXPATHLEN];
|
||||
|
||||
/* like chdir() but can be reversed with pop_dir() if save is set. It
|
||||
is also much faster as it remembers where we have been */
|
||||
char *push_dir(char *dir, int save)
|
||||
{
|
||||
char *ret = curr_dir;
|
||||
static int initialised;
|
||||
|
||||
if (!initialised) {
|
||||
initialised = 1;
|
||||
getcwd(curr_dir, sizeof(curr_dir)-1);
|
||||
}
|
||||
|
||||
if (chdir(dir)) return NULL;
|
||||
|
||||
if (save) {
|
||||
ret = strdup(curr_dir);
|
||||
}
|
||||
|
||||
if (*dir == '/') {
|
||||
strlcpy(curr_dir, dir, sizeof(curr_dir)-1);
|
||||
} else {
|
||||
strlcat(curr_dir,"/", sizeof(curr_dir)-1);
|
||||
strlcat(curr_dir,dir, sizeof(curr_dir)-1);
|
||||
}
|
||||
|
||||
clean_fname(curr_dir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* reverse a push_dir call */
|
||||
int pop_dir(char *dir)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = chdir(dir);
|
||||
if (ret) {
|
||||
free(dir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
strlcpy(curr_dir, dir, sizeof(curr_dir)-1);
|
||||
|
||||
free(dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* we need to supply our own strcmp function for file list comparisons
|
||||
to ensure that signed/unsigned usage is consistent between machines. */
|
||||
int u_strcmp(const char *cs1, const char *cs2)
|
||||
{
|
||||
const uchar *s1 = (uchar *)cs1;
|
||||
const uchar *s2 = (uchar *)cs2;
|
||||
|
||||
while (*s1 && *s2 && (*s1 == *s2)) {
|
||||
s1++; s2++;
|
||||
}
|
||||
|
||||
return (int)*s1 - (int)*s2;
|
||||
}
|
||||
|
||||
19
zlib/README.rsync
Normal file
19
zlib/README.rsync
Normal file
@@ -0,0 +1,19 @@
|
||||
zlib has been adapted slightly for use in rsync. Please don't bother
|
||||
the zlib authors with problems related to the use of zlib in rsync as
|
||||
any bugs are likely to be our fault and not theirs.
|
||||
|
||||
Specific changes that have been made to zlib for rsync include:
|
||||
|
||||
- add Z_INSERT_ONLY to allow for efficient history updating without
|
||||
actually emitting any data. This is used to compress the matched
|
||||
blocks that don't cross the wire, which gives better compression
|
||||
ratios on the literal data.
|
||||
|
||||
- fixed a number of minor compilation issues. (redefinition of MAX and
|
||||
other such trivial things)
|
||||
|
||||
- include rsync.h to ensure that we get a consistent set of includes
|
||||
for all C code in rsync and to take advantage of autoconf
|
||||
|
||||
--
|
||||
Paul Mackerras and Andrew Tridgell
|
||||
@@ -80,7 +80,7 @@ local block_state deflate_slow OF((deflate_state *s, int flush));
|
||||
local void lm_init OF((deflate_state *s));
|
||||
local void putShortMSB OF((deflate_state *s, uInt b));
|
||||
local void flush_pending OF((z_streamp strm));
|
||||
local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size));
|
||||
local int dread_buf OF((z_streamp strm, Bytef *buf, unsigned size));
|
||||
#ifdef ASMV
|
||||
void match_init OF((void)); /* asm code initialization */
|
||||
uInt longest_match OF((deflate_state *s, IPos cur_match));
|
||||
@@ -411,7 +411,7 @@ local void putShortMSB (s, b)
|
||||
* Flush as much pending output as possible. All deflate() output goes
|
||||
* through this function so some applications may wish to modify it
|
||||
* to avoid allocating a large strm->next_out buffer and copying into it.
|
||||
* (See also read_buf()).
|
||||
* (See also dread_buf()).
|
||||
*/
|
||||
local void flush_pending(strm)
|
||||
z_streamp strm;
|
||||
@@ -441,7 +441,7 @@ int ZEXPORT deflate (strm, flush)
|
||||
deflate_state *s;
|
||||
|
||||
if (strm == Z_NULL || strm->state == Z_NULL ||
|
||||
flush > Z_FINISH || flush < 0) {
|
||||
flush > Z_INSERT_ONLY || flush < 0) {
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
s = strm->state;
|
||||
@@ -657,7 +657,7 @@ int ZEXPORT deflateCopy (dest, source)
|
||||
* allocating a large strm->next_in buffer and copying from it.
|
||||
* (See also flush_pending()).
|
||||
*/
|
||||
local int read_buf(strm, buf, size)
|
||||
local int dread_buf(strm, buf, size)
|
||||
z_streamp strm;
|
||||
Bytef *buf;
|
||||
unsigned size;
|
||||
@@ -1028,7 +1028,7 @@ local void fill_window(s)
|
||||
*/
|
||||
Assert(more >= 2, "more < 2");
|
||||
|
||||
n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
|
||||
n = dread_buf(s->strm, s->window + s->strstart + s->lookahead, more);
|
||||
s->lookahead += n;
|
||||
|
||||
/* Initialize the hash value now that we have some input: */
|
||||
@@ -1162,6 +1162,12 @@ local block_state deflate_fast(s, flush)
|
||||
INSERT_STRING(s, s->strstart, hash_head);
|
||||
}
|
||||
|
||||
if (flush == Z_INSERT_ONLY) {
|
||||
s->strstart++;
|
||||
s->lookahead--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find the longest match, discarding those <= prev_length.
|
||||
* At this point we have always match_length < MIN_MATCH
|
||||
*/
|
||||
@@ -1221,6 +1227,10 @@ local block_state deflate_fast(s, flush)
|
||||
}
|
||||
if (bflush) FLUSH_BLOCK(s, 0);
|
||||
}
|
||||
if (flush == Z_INSERT_ONLY) {
|
||||
s->block_start = s->strstart;
|
||||
return need_more;
|
||||
}
|
||||
FLUSH_BLOCK(s, flush == Z_FINISH);
|
||||
return flush == Z_FINISH ? finish_done : block_done;
|
||||
}
|
||||
@@ -1259,6 +1269,12 @@ local block_state deflate_slow(s, flush)
|
||||
INSERT_STRING(s, s->strstart, hash_head);
|
||||
}
|
||||
|
||||
if (flush == Z_INSERT_ONLY) {
|
||||
s->strstart++;
|
||||
s->lookahead--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find the longest match, discarding those <= prev_length.
|
||||
*/
|
||||
s->prev_length = s->match_length, s->prev_match = s->match_start;
|
||||
@@ -1337,6 +1353,10 @@ local block_state deflate_slow(s, flush)
|
||||
s->lookahead--;
|
||||
}
|
||||
}
|
||||
if (flush == Z_INSERT_ONLY) {
|
||||
s->block_start = s->strstart;
|
||||
return need_more;
|
||||
}
|
||||
Assert (flush != Z_NO_FLUSH, "no flush?");
|
||||
if (s->match_available) {
|
||||
Tracevv((stderr,"%c", s->window[s->strstart-1]));
|
||||
|
||||
@@ -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 */
|
||||
@@ -77,9 +77,9 @@ struct inflate_blocks_state {
|
||||
/* output bytes */
|
||||
#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
|
||||
#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
|
||||
#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
|
||||
#define ZWRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
|
||||
#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
|
||||
#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
|
||||
#define NEEDOUT {if(m==0){ZWRAP if(m==0){FLUSH ZWRAP if(m==0) LEAVE}}r=Z_OK;}
|
||||
#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
|
||||
/* load local pointers */
|
||||
#define LOAD {LOADIN LOADOUT}
|
||||
|
||||
14
zlib/trees.c
14
zlib/trees.c
@@ -230,7 +230,9 @@ local void send_bits(s, value, length)
|
||||
#endif /* DEBUG */
|
||||
|
||||
|
||||
#define MAX(a,b) (a >= b ? a : b)
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a) >= (b) ? (a) : (b))
|
||||
#endif
|
||||
/* the arguments must not have side effects */
|
||||
|
||||
/* ===========================================================================
|
||||
@@ -497,7 +499,7 @@ local void gen_bitlen(s, desc)
|
||||
int bits; /* bit length */
|
||||
int xbits; /* extra bits */
|
||||
ush f; /* frequency */
|
||||
int overflow = 0; /* number of elements with bit length too large */
|
||||
int Overflow = 0; /* number of elements with bit length too large */
|
||||
|
||||
for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
|
||||
|
||||
@@ -509,7 +511,7 @@ local void gen_bitlen(s, desc)
|
||||
for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
|
||||
n = s->heap[h];
|
||||
bits = tree[tree[n].Dad].Len + 1;
|
||||
if (bits > max_length) bits = max_length, overflow++;
|
||||
if (bits > max_length) bits = max_length, Overflow++;
|
||||
tree[n].Len = (ush)bits;
|
||||
/* We overwrite tree[n].Dad which is no longer needed */
|
||||
|
||||
@@ -522,7 +524,7 @@ local void gen_bitlen(s, desc)
|
||||
s->opt_len += (ulg)f * (bits + xbits);
|
||||
if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
|
||||
}
|
||||
if (overflow == 0) return;
|
||||
if (Overflow == 0) return;
|
||||
|
||||
Trace((stderr,"\nbit length overflow\n"));
|
||||
/* This happens for example on obj2 and pic of the Calgary corpus */
|
||||
@@ -537,8 +539,8 @@ local void gen_bitlen(s, desc)
|
||||
/* The brother of the overflow item also moves one step up,
|
||||
* but this does not affect bl_count[max_length]
|
||||
*/
|
||||
overflow -= 2;
|
||||
} while (overflow > 0);
|
||||
Overflow -= 2;
|
||||
} while (Overflow > 0);
|
||||
|
||||
/* Now recompute all bit lengths, scanning in increasing frequency.
|
||||
* h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
|
||||
|
||||
@@ -127,6 +127,7 @@ typedef z_stream FAR *z_streamp;
|
||||
#define Z_SYNC_FLUSH 2
|
||||
#define Z_FULL_FLUSH 3
|
||||
#define Z_FINISH 4
|
||||
#define Z_INSERT_ONLY 5
|
||||
/* Allowed flush values; see deflate() below for details */
|
||||
|
||||
#define Z_OK 0
|
||||
|
||||
@@ -200,11 +200,6 @@ void zcfree (voidpf opaque, voidpf ptr)
|
||||
|
||||
#ifndef MY_ZCALLOC /* Any system without a special alloc function */
|
||||
|
||||
#ifndef STDC
|
||||
extern voidp calloc OF((uInt items, uInt size));
|
||||
extern void free OF((voidpf ptr));
|
||||
#endif
|
||||
|
||||
voidpf zcalloc (opaque, items, size)
|
||||
voidpf opaque;
|
||||
unsigned items;
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
#ifndef _Z_UTIL_H
|
||||
#define _Z_UTIL_H
|
||||
|
||||
#include "../rsync.h"
|
||||
#include "zlib.h"
|
||||
|
||||
#if 0
|
||||
#ifdef STDC
|
||||
# include <stddef.h>
|
||||
# include <string.h>
|
||||
@@ -25,6 +27,7 @@
|
||||
#else
|
||||
# include <errno.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef local
|
||||
# define local static
|
||||
|
||||
Reference in New Issue
Block a user