mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-25 15:25:30 -04:00
Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a03f68a5a | ||
|
|
e81da93e86 | ||
|
|
f578043391 | ||
|
|
e8f5b936ad | ||
|
|
667e72a195 | ||
|
|
e1b3d5c4be | ||
|
|
f7b9377863 | ||
|
|
a5343e765b | ||
|
|
704f908eae | ||
|
|
de2fd20eb7 | ||
|
|
100e5241b0 | ||
|
|
ddecf7060b | ||
|
|
56cdbccb92 | ||
|
|
fc8a6b9705 | ||
|
|
143384f367 | ||
|
|
8c3b04730b | ||
|
|
aa9b77a56c | ||
|
|
b72f24c719 | ||
|
|
a800434a82 | ||
|
|
3b3c3d4390 | ||
|
|
d846b09874 | ||
|
|
1d3754aede | ||
|
|
e44f9a12c4 | ||
|
|
5243c216d6 | ||
|
|
79a51e7ee6 | ||
|
|
cad2bba7d8 | ||
|
|
fe8c0a9824 | ||
|
|
6cdc6b1344 | ||
|
|
05848a2cc7 | ||
|
|
528bfcd79a | ||
|
|
a1e13a937c | ||
|
|
e3fe383aaa | ||
|
|
43bd68e5dd | ||
|
|
ea2111d10a | ||
|
|
4c36ddbeec | ||
|
|
2b6b4d539b | ||
|
|
35f69d8ad9 | ||
|
|
7b1ce0d746 |
@@ -25,7 +25,7 @@ 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) $(ZLIBOBJ)
|
||||
|
||||
|
||||
16
checksum.c
16
checksum.c
@@ -77,7 +77,7 @@ void get_checksum2(char *buf,int len,char *sum)
|
||||
|
||||
MDbegin(&MD);
|
||||
|
||||
bcopy(buf,buf1,len);
|
||||
memcpy(buf1,buf,len);
|
||||
if (checksum_seed) {
|
||||
SIVAL(buf1,len,checksum_seed);
|
||||
len += 4;
|
||||
@@ -102,7 +102,7 @@ void file_checksum(char *fname,char *sum,OFF_T size)
|
||||
OFF_T len = size;
|
||||
char tmpchunk[CSUM_CHUNK];
|
||||
|
||||
bzero(sum,csum_length);
|
||||
memset(sum,0,csum_length);
|
||||
|
||||
fd = open(fname,O_RDONLY);
|
||||
if (fd == -1) return;
|
||||
@@ -112,12 +112,12 @@ void file_checksum(char *fname,char *sum,OFF_T size)
|
||||
MDbegin(&MD);
|
||||
|
||||
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
|
||||
bcopy(map_ptr(buf,i,CSUM_CHUNK),tmpchunk,CSUM_CHUNK);
|
||||
memcpy(tmpchunk, map_ptr(buf,i,CSUM_CHUNK), CSUM_CHUNK);
|
||||
MDupdate(&MD, tmpchunk, CSUM_CHUNK*8);
|
||||
}
|
||||
|
||||
if (len - i > 0) {
|
||||
bcopy(map_ptr(buf,i,len-i),tmpchunk,len-i);
|
||||
memcpy(tmpchunk, map_ptr(buf,i,len-i), len-i);
|
||||
MDupdate(&MD, tmpchunk, (len-i)*8);
|
||||
}
|
||||
|
||||
@@ -155,27 +155,27 @@ void sum_update(char *p,int len)
|
||||
{
|
||||
int i;
|
||||
if (len + sumresidue < CSUM_CHUNK) {
|
||||
bcopy(p,sumrbuf+sumresidue,len);
|
||||
memcpy(sumrbuf+sumresidue, p, len);
|
||||
sumresidue += len;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sumresidue) {
|
||||
i = MIN(CSUM_CHUNK-sumresidue,len);
|
||||
bcopy(p,sumrbuf+sumresidue,i);
|
||||
memcpy(sumrbuf+sumresidue,p,i);
|
||||
MDupdate(&sumMD, sumrbuf, (i+sumresidue)*8);
|
||||
len -= i;
|
||||
p += i;
|
||||
}
|
||||
|
||||
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
|
||||
bcopy(p+i,sumrbuf,CSUM_CHUNK);
|
||||
memcpy(sumrbuf,p+i,CSUM_CHUNK);
|
||||
MDupdate(&sumMD, sumrbuf, CSUM_CHUNK*8);
|
||||
}
|
||||
|
||||
if (len - i > 0) {
|
||||
sumresidue = len-i;
|
||||
bcopy(p+i,sumrbuf,sumresidue);
|
||||
memcpy(sumrbuf,p+i,sumresidue);
|
||||
} else {
|
||||
sumresidue = 0;
|
||||
}
|
||||
|
||||
@@ -174,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);
|
||||
@@ -362,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ echo no)
|
||||
AC_FUNC_MEMCMP
|
||||
AC_FUNC_UTIME_NULL
|
||||
AC_CHECK_FUNCS(mmap munmap waitpid getcwd strdup strerror chown chmod mknod)
|
||||
AC_CHECK_FUNCS(fchmod fstat strchr bcopy bzero readlink link utime utimes)
|
||||
AC_CHECK_FUNCS(memmove getopt_long lchown setlinebuf vsnprintf setsid glob)
|
||||
AC_CHECK_FUNCS(fchmod fstat strchr readlink link utime utimes)
|
||||
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>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
117
flist.c
117
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)
|
||||
{
|
||||
@@ -169,6 +127,11 @@ void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
|
||||
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);
|
||||
@@ -248,7 +211,7 @@ static void receive_file_entry(struct file_struct **fptr,
|
||||
|
||||
file = (struct file_struct *)malloc(sizeof(*file));
|
||||
if (!file) out_of_memory("receive_file_entry");
|
||||
bzero((char *)file,sizeof(*file));
|
||||
memset((char *)file, 0, sizeof(*file));
|
||||
(*fptr) = file;
|
||||
|
||||
if (l2 >= MAXPATHLEN-l1) overflow("receive_file_entry");
|
||||
@@ -362,7 +325,7 @@ static struct file_struct *make_file(char *fname)
|
||||
clean_fname(cleaned_name);
|
||||
fname = cleaned_name;
|
||||
|
||||
bzero(sum,SUM_LENGTH);
|
||||
memset(sum,0,SUM_LENGTH);
|
||||
|
||||
if (link_stat(fname,&st) != 0) {
|
||||
io_error = 1;
|
||||
@@ -389,7 +352,7 @@ static struct file_struct *make_file(char *fname)
|
||||
|
||||
file = (struct file_struct *)malloc(sizeof(*file));
|
||||
if (!file) out_of_memory("make_file");
|
||||
bzero((char *)file,sizeof(*file));
|
||||
memset((char *)file,0,sizeof(*file));
|
||||
|
||||
if ((p = strrchr(fname,'/'))) {
|
||||
static char *lastdir;
|
||||
@@ -459,7 +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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -641,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;
|
||||
@@ -691,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)
|
||||
@@ -705,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;
|
||||
@@ -741,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++;
|
||||
|
||||
@@ -772,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:
|
||||
@@ -786,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));
|
||||
}
|
||||
|
||||
|
||||
@@ -823,7 +794,7 @@ static void free_file(struct file_struct *file)
|
||||
if (file->basename) free(file->basename);
|
||||
if (file->link) free(file->link);
|
||||
if (file->sum) free(file->sum);
|
||||
bzero((char *)file, sizeof(*file));
|
||||
memset((char *)file, 0, sizeof(*file));
|
||||
}
|
||||
|
||||
|
||||
@@ -837,9 +808,9 @@ void flist_free(struct file_list *flist)
|
||||
free_file(flist->files[i]);
|
||||
free(flist->files[i]);
|
||||
}
|
||||
bzero((char *)flist->files, sizeof(flist->files[0])*flist->count);
|
||||
memset((char *)flist->files, 0, sizeof(flist->files[0])*flist->count);
|
||||
free(flist->files);
|
||||
bzero((char *)flist, sizeof(*flist));
|
||||
memset((char *)flist, 0, sizeof(*flist));
|
||||
free(flist);
|
||||
}
|
||||
|
||||
|
||||
2
hlink.c
2
hlink.c
@@ -56,7 +56,7 @@ void init_hard_links(struct file_list *flist)
|
||||
out_of_memory("init_hard_links");
|
||||
|
||||
for (i = 0; i < flist->count; i++)
|
||||
bcopy(flist->files[i], &hlink_list[i], sizeof(hlink_list[0]));
|
||||
memcpy(&hlink_list[i], flist->files[i], sizeof(hlink_list[0]));
|
||||
|
||||
qsort(hlink_list,flist->count,
|
||||
sizeof(hlink_list[0]),
|
||||
|
||||
433
io.c
433
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,86 @@ 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 == -1 &&
|
||||
(errno == EAGAIN || errno == EWOULDBLOCK)) {
|
||||
/* this shouldn't happen, if it does then
|
||||
sleep for a short time to prevent us
|
||||
chewing too much CPU */
|
||||
u_sleep(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
if (eof_error) {
|
||||
rprintf(FERROR,"EOF in read_timeout\n");
|
||||
}
|
||||
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 +154,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 +197,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 +211,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 +221,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 +254,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 +281,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 +291,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 +302,88 @@ 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 == -1 &&
|
||||
(errno == EAGAIN || errno == EWOULDBLOCK)) {
|
||||
/* this shouldn't happen, if it does then
|
||||
sleep for a short time to prevent us
|
||||
chewing too much CPU */
|
||||
u_sleep(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (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 +405,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 +425,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 +443,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 +467,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 +487,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 +508,9 @@ int read_line(int f, char *buf, int maxlen)
|
||||
*buf = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
eof_error = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
20
lib/compat.c
20
lib/compat.c
@@ -54,7 +54,25 @@ pid_t waitpid(pid_t pid, int *statptr, int options)
|
||||
#ifndef HAVE_MEMMOVE
|
||||
void *memmove(void *dest, const void *src, size_t n)
|
||||
{
|
||||
bcopy(src, dest, n);
|
||||
memcpy(dest, src, n);
|
||||
return dest;
|
||||
}
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
@@ -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")
|
||||
@@ -330,7 +329,7 @@ initialise a service to the defaults
|
||||
***************************************************************************/
|
||||
static void init_service(service *pservice)
|
||||
{
|
||||
bzero((char *)pservice,sizeof(service));
|
||||
memset((char *)pservice,0,sizeof(service));
|
||||
copy_service(pservice,&sDefault);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
104
main.c
104
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,49 @@ static void report(int f)
|
||||
if (am_server && !am_sender) return;
|
||||
|
||||
if (am_server && am_sender) {
|
||||
write_longint(f,read_total());
|
||||
write_longint(f,write_total());
|
||||
write_longint(f,total_size);
|
||||
write_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));
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
|
||||
@@ -150,8 +174,8 @@ static char *get_local_name(struct file_list *flist,char *name)
|
||||
|
||||
if (do_stat(name,&st) == 0) {
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
if (chdir(name) != 0) {
|
||||
rprintf(FERROR,"chdir %s : %s (1)\n",
|
||||
if (!push_dir(name, 0)) {
|
||||
rprintf(FERROR,"push_dir %s : %s (1)\n",
|
||||
name,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
@@ -177,8 +201,9 @@ static char *get_local_name(struct file_list *flist,char *name)
|
||||
rprintf(FINFO,"created directory %s\n",name);
|
||||
}
|
||||
|
||||
if (chdir(name) != 0) {
|
||||
rprintf(FERROR,"chdir %s : %s (2)\n",name,strerror(errno));
|
||||
if (!push_dir(name, 0)) {
|
||||
rprintf(FERROR,"push_dir %s : %s (2)\n",
|
||||
name,strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
@@ -199,8 +224,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--;
|
||||
@@ -225,6 +250,10 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
|
||||
exit_cleanup(0);
|
||||
}
|
||||
|
||||
set_nonblocking(f_out);
|
||||
if (f_in != f_out)
|
||||
set_nonblocking(f_in);
|
||||
|
||||
send_files(flist,f_out,f_in);
|
||||
report(f_out);
|
||||
io_flush();
|
||||
@@ -253,6 +282,8 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
close(recv_pipe[0]);
|
||||
if (f_in != f_out) close(f_out);
|
||||
|
||||
set_nonblocking(f_in);
|
||||
|
||||
recv_files(f_in,flist,local_name,recv_pipe[1]);
|
||||
report(f_in);
|
||||
|
||||
@@ -266,6 +297,9 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
close(recv_pipe[1]);
|
||||
io_close_input(f_in);
|
||||
if (f_in != f_out) close(f_in);
|
||||
|
||||
set_nonblocking(f_out);
|
||||
|
||||
generate_files(f_out,flist,local_name,recv_pipe[0]);
|
||||
|
||||
io_flush();
|
||||
@@ -290,8 +324,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);
|
||||
}
|
||||
@@ -356,6 +390,11 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
|
||||
flist = send_file_list(f_out,argc,argv);
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"file list sent\n");
|
||||
|
||||
set_nonblocking(f_out);
|
||||
if (f_in != f_out)
|
||||
set_nonblocking(f_in);
|
||||
|
||||
send_files(flist,f_out,f_in);
|
||||
if (pid != -1) {
|
||||
if (verbose > 3)
|
||||
@@ -390,13 +429,13 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
|
||||
}
|
||||
|
||||
|
||||
int start_client(int argc, char *argv[])
|
||||
static int start_client(int argc, char *argv[])
|
||||
{
|
||||
char *p;
|
||||
char *shell_machine = NULL;
|
||||
char *shell_path = NULL;
|
||||
char *shell_user = NULL;
|
||||
int pid;
|
||||
int pid, ret;
|
||||
int f_in,f_out;
|
||||
extern int local_server;
|
||||
extern int am_sender;
|
||||
@@ -477,7 +516,12 @@ int start_client(int argc, char *argv[])
|
||||
setlinebuf(stderr);
|
||||
#endif
|
||||
|
||||
return client_run(f_in, f_out, pid, argc, argv);
|
||||
ret = client_run(f_in, f_out, pid, argc, argv);
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -498,6 +542,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);
|
||||
|
||||
24
match.c
24
match.c
@@ -29,18 +29,18 @@ extern int remote_version;
|
||||
typedef unsigned short tag;
|
||||
|
||||
#define TABLESIZE (1<<16)
|
||||
#define NULL_TAG ((tag)-1)
|
||||
#define NULL_TAG (-1)
|
||||
|
||||
static int false_alarms;
|
||||
static int tag_hits;
|
||||
static int matches;
|
||||
static int data_transfer;
|
||||
static int64 data_transfer;
|
||||
|
||||
static int total_false_alarms;
|
||||
static int total_tag_hits;
|
||||
static int total_matches;
|
||||
static int64 total_data_transfer;
|
||||
|
||||
extern struct stats stats;
|
||||
|
||||
struct target {
|
||||
tag t;
|
||||
@@ -49,7 +49,7 @@ struct target {
|
||||
|
||||
static struct target *targets;
|
||||
|
||||
static tag *tag_table;
|
||||
static int *tag_table;
|
||||
|
||||
#define gettag2(s1,s2) (((s1) + (s2)) & 0xFFFF)
|
||||
#define gettag(sum) gettag2((sum)&0xFFFF,(sum)>>16)
|
||||
@@ -65,7 +65,7 @@ static void build_hash_table(struct sum_struct *s)
|
||||
int i;
|
||||
|
||||
if (!tag_table)
|
||||
tag_table = (tag *)malloc(sizeof(tag)*TABLESIZE);
|
||||
tag_table = (int *)malloc(sizeof(tag_table[0])*TABLESIZE);
|
||||
|
||||
targets = (struct target *)malloc(sizeof(targets[0])*s->count);
|
||||
if (!tag_table || !targets)
|
||||
@@ -103,11 +103,10 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
|
||||
send_token(f,i,buf,last_match,n,i<0?0:s->sums[i].len);
|
||||
data_transfer += n;
|
||||
|
||||
if (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);
|
||||
@@ -276,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)
|
||||
@@ -285,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);
|
||||
}
|
||||
|
||||
119
options.c
119
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,55 +75,69 @@ void usage(int F)
|
||||
{
|
||||
rprintf(F,"rsync version %s Copyright Andrew Tridgell and Paul Mackerras\n\n",
|
||||
VERSION);
|
||||
rprintf(F,"Usage:\t%s [options] src user@host:dest\nOR",RSYNC_NAME);
|
||||
rprintf(F,"\t%s [options] user@host:src dest\n\n",RSYNC_NAME);
|
||||
rprintf(F,"Options:\n");
|
||||
rprintf(F,"-v, --verbose increase verbosity\n");
|
||||
rprintf(F,"-c, --checksum always checksum\n");
|
||||
rprintf(F,"-a, --archive archive mode (same as -rlptDog)\n");
|
||||
rprintf(F,"-r, --recursive recurse into directories\n");
|
||||
rprintf(F,"-R, --relative use relative path names\n");
|
||||
rprintf(F,"-b, --backup make backups (default ~ extension)\n");
|
||||
rprintf(F,"-u, --update update only (don't overwrite newer files)\n");
|
||||
rprintf(F,"-l, --links preserve soft links\n");
|
||||
rprintf(F,"-L, --copy-links treat soft links like regular files\n");
|
||||
rprintf(F,"-H, --hard-links preserve hard links\n");
|
||||
rprintf(F,"-p, --perms preserve permissions\n");
|
||||
rprintf(F,"-o, --owner preserve owner (root only)\n");
|
||||
rprintf(F,"-g, --group preserve group\n");
|
||||
rprintf(F,"-D, --devices preserve devices (root only)\n");
|
||||
rprintf(F,"-t, --times preserve times\n");
|
||||
rprintf(F,"-S, --sparse handle sparse files efficiently\n");
|
||||
rprintf(F,"-n, --dry-run show what would have been transferred\n");
|
||||
rprintf(F,"-W, --whole-file copy whole files, no incremental checks\n");
|
||||
rprintf(F,"-x, --one-file-system don't cross filesystem boundaries\n");
|
||||
rprintf(F,"-B, --block-size SIZE checksum blocking size\n");
|
||||
rprintf(F,"-e, --rsh COMMAND specify rsh replacement\n");
|
||||
rprintf(F," --rsync-path PATH specify path to rsync on the remote machine\n");
|
||||
rprintf(F,"-C, --cvs-exclude auto ignore files in the same way CVS does\n");
|
||||
rprintf(F," --delete delete files that don't exist on the sending side\n");
|
||||
rprintf(F," --force force deletion of directories even if not empty\n");
|
||||
rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
|
||||
rprintf(F," --timeout TIME set IO timeout in seconds\n");
|
||||
rprintf(F,"-I, --ignore-times don't exclude files that match length and time\n");
|
||||
rprintf(F,"-T --temp-dir DIR create temporary files in directory DIR\n");
|
||||
rprintf(F,"-z, --compress compress file data\n");
|
||||
rprintf(F," --exclude FILE exclude file FILE\n");
|
||||
rprintf(F," --exclude-from FILE exclude files listed in FILE\n");
|
||||
rprintf(F," --suffix SUFFIX override backup suffix\n");
|
||||
rprintf(F," --version print version number\n");
|
||||
rprintf(F," --daemon run as a rsync daemon\n");
|
||||
rprintf(F," --config FILE specify alternate rsyncd.conf file\n");
|
||||
rprintf(F," --port PORT specify alternate rsyncd port number\n");
|
||||
|
||||
rprintf(F,"rsync is a file transfer program capable of efficient remote update\nvia a fast differencing algorithm.\n\n");
|
||||
|
||||
rprintf(F,"Usage: rsync [OPTION]... SRC [USER@]HOST:DEST\n");
|
||||
rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC DEST\n");
|
||||
rprintf(F," or rsync [OPTION]... SRC DEST\n");
|
||||
rprintf(F," or rsync [OPTION]... [USER@]HOST::SRC DEST\n");
|
||||
rprintf(F," or rsync [OPTION]... SRC [USER@]HOST::DEST\n");
|
||||
rprintf(F,"\nOptions\n");
|
||||
rprintf(F," -v, --verbose increase verbosity\n");
|
||||
rprintf(F," -c, --checksum always checksum\n");
|
||||
rprintf(F," -a, --archive archive mode\n");
|
||||
rprintf(F," -r, --recursive recurse into directories\n");
|
||||
rprintf(F," -R, --relative use relative path names\n");
|
||||
rprintf(F," -b, --backup make backups (default ~ extension)\n");
|
||||
rprintf(F," -u, --update update only (don't overwrite newer files)\n");
|
||||
rprintf(F," -l, --links preserve soft links\n");
|
||||
rprintf(F," -L, --copy-links treat soft links like regular files\n");
|
||||
rprintf(F," -H, --hard-links preserve hard links\n");
|
||||
rprintf(F," -p, --perms preserve permissions\n");
|
||||
rprintf(F," -o, --owner preserve owner (root only)\n");
|
||||
rprintf(F," -g, --group preserve group\n");
|
||||
rprintf(F," -D, --devices preserve devices (root only)\n");
|
||||
rprintf(F," -t, --times preserve times\n");
|
||||
rprintf(F," -S, --sparse handle sparse files efficiently\n");
|
||||
rprintf(F," -n, --dry-run show what would have been transferred\n");
|
||||
rprintf(F," -W, --whole-file copy whole files, no incremental checks\n");
|
||||
rprintf(F," -x, --one-file-system don't cross filesystem boundaries\n");
|
||||
rprintf(F," -B, --block-size=SIZE checksum blocking size\n");
|
||||
rprintf(F," -e, --rsh=COMMAND specify rsh replacement\n");
|
||||
rprintf(F," --rsync-path=PATH specify path to rsync on the remote machine\n");
|
||||
rprintf(F," -C, --cvs-exclude auto ignore files in the same way CVS does\n");
|
||||
rprintf(F," --delete delete files that don't exist on the sending side\n");
|
||||
rprintf(F," --force force deletion of directories even if not empty\n");
|
||||
rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
|
||||
rprintf(F," --timeout=TIME set IO timeout in seconds\n");
|
||||
rprintf(F," -I, --ignore-times don't exclude files that match length and time\n");
|
||||
rprintf(F," -T --temp-dir=DIR create temporary files in directory DIR\n");
|
||||
rprintf(F," -z, --compress compress file data\n");
|
||||
rprintf(F," --exclude=PATTERN exclude file FILE\n");
|
||||
rprintf(F," --exclude-from=PATTERN exclude files listed in FILE\n");
|
||||
rprintf(F," --include=PATTERN don't exclude file FILE\n");
|
||||
rprintf(F," --include-from=PATTERN don't exclude files listed in FILE\n");
|
||||
rprintf(F," --suffix=SUFFIX override backup suffix\n");
|
||||
rprintf(F," --version print version number\n");
|
||||
rprintf(F," --daemon run as a rsync daemon\n");
|
||||
rprintf(F," --config=FILE specify alternate rsyncd.conf file\n");
|
||||
rprintf(F," --port=PORT specify alternate rsyncd port number\n");
|
||||
rprintf(F," --stats give some file transfer stats\n");
|
||||
rprintf(F," -h, --help show this help screen\n");
|
||||
|
||||
rprintf(F,"\n");
|
||||
rprintf(F,"the backup suffix defaults to %s\n",BACKUP_SUFFIX);
|
||||
rprintf(F,"the block size defaults to %d\n",BLOCK_SIZE);
|
||||
|
||||
rprintf(F,"\nPlease see the rsync(1) and rsyncd.conf(5) man pages for full documentation\n");
|
||||
rprintf(F,"See http://samba.anu.edu.au/rsync/ for updates and bug reports\n");
|
||||
}
|
||||
|
||||
enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE,
|
||||
OPT_EXCLUDE_FROM,OPT_DELETE,OPT_NUMERIC_IDS,OPT_RSYNC_PATH,
|
||||
OPT_FORCE,OPT_TIMEOUT,OPT_DAEMON,OPT_CONFIG,OPT_PORT};
|
||||
OPT_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 +150,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 +182,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}};
|
||||
@@ -180,8 +198,9 @@ void parse_arguments(int argc, char *argv[])
|
||||
switch (opt)
|
||||
{
|
||||
case OPT_VERSION:
|
||||
printf("rsync version %s protocol version %d\n",
|
||||
printf("rsync version %s protocol version %d\n\n",
|
||||
VERSION,PROTOCOL_VERSION);
|
||||
printf("Written by Andrew Tridgell and Paul Mackerras\n");
|
||||
exit_cleanup(0);
|
||||
|
||||
case OPT_SUFFIX:
|
||||
@@ -213,11 +232,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 +378,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.12
|
||||
Version: 2.0.17
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.0.12.tar.gz
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.0.17.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...
|
||||
|
||||
554
rsync.c
554
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -265,65 +267,67 @@ static struct sum_struct *receive_sums(int f)
|
||||
static int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
int report)
|
||||
{
|
||||
int updated = 0;
|
||||
STRUCT_STAT st2;
|
||||
extern int am_daemon;
|
||||
int updated = 0;
|
||||
STRUCT_STAT st2;
|
||||
extern int am_daemon;
|
||||
|
||||
if (dry_run) return 0;
|
||||
if (dry_run) return 0;
|
||||
|
||||
if (!st) {
|
||||
if (link_stat(fname,&st2) != 0) {
|
||||
rprintf(FERROR,"stat %s : %s\n",fname,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
st = &st2;
|
||||
}
|
||||
if (!st) {
|
||||
if (link_stat(fname,&st2) != 0) {
|
||||
rprintf(FERROR,"stat %s : %s\n",fname,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
st = &st2;
|
||||
}
|
||||
|
||||
if (preserve_times && !S_ISLNK(st->st_mode) &&
|
||||
st->st_mtime != file->modtime) {
|
||||
updated = 1;
|
||||
if (set_modtime(fname,file->modtime) != 0) {
|
||||
rprintf(FERROR,"failed to set times on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (preserve_times && !S_ISLNK(st->st_mode) &&
|
||||
st->st_mtime != file->modtime) {
|
||||
updated = 1;
|
||||
if (set_modtime(fname,file->modtime) != 0) {
|
||||
rprintf(FERROR,"failed to set times on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
if (preserve_uid && st->st_uid != file->uid)
|
||||
updated = 1;
|
||||
if (verbose>1 || preserve_uid) {
|
||||
rprintf(FERROR,"chown %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
updated = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_CHMOD
|
||||
if (preserve_perms && !S_ISLNK(st->st_mode) &&
|
||||
st->st_mode != file->mode) {
|
||||
updated = 1;
|
||||
if (do_chmod(fname,file->mode) != 0) {
|
||||
rprintf(FERROR,"failed to set permissions on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (preserve_perms && !S_ISLNK(st->st_mode) &&
|
||||
st->st_mode != file->mode) {
|
||||
updated = 1;
|
||||
if (do_chmod(fname,file->mode) != 0) {
|
||||
rprintf(FERROR,"failed to set permissions on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
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) {
|
||||
if (preserve_uid && st->st_uid != file->uid)
|
||||
updated = 1;
|
||||
if (verbose>1 || preserve_uid)
|
||||
rprintf(FERROR,"chown %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
return updated;
|
||||
}
|
||||
updated = 1;
|
||||
}
|
||||
|
||||
if (verbose > 1 && report) {
|
||||
if (updated)
|
||||
rprintf(FINFO,"%s\n",fname);
|
||||
else
|
||||
rprintf(FINFO,"%s is uptodate\n",fname);
|
||||
}
|
||||
return updated;
|
||||
if (verbose > 1 && report) {
|
||||
if (updated)
|
||||
rprintf(FINFO,"%s\n",fname);
|
||||
else
|
||||
rprintf(FINFO,"%s is uptodate\n",fname);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
|
||||
@@ -354,7 +358,11 @@ static int skip_file(char *fname,
|
||||
/* use a larger block size for really big files */
|
||||
int adapt_block_size(struct file_struct *file, int bsize)
|
||||
{
|
||||
int ret = file->length / (10000); /* rough heuristic */
|
||||
int ret;
|
||||
|
||||
if (bsize != BLOCK_SIZE) return bsize;
|
||||
|
||||
ret = file->length / (10000); /* rough heuristic */
|
||||
ret = ret & ~15; /* multiple of 16 */
|
||||
if (ret < bsize) ret = bsize;
|
||||
if (ret > CHUNK_SIZE/2) ret = CHUNK_SIZE/2;
|
||||
@@ -528,7 +536,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);
|
||||
@@ -559,6 +566,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) {
|
||||
@@ -573,6 +581,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);
|
||||
@@ -638,11 +648,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");
|
||||
}
|
||||
|
||||
@@ -696,7 +702,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]));
|
||||
|
||||
@@ -710,7 +717,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]);
|
||||
@@ -741,216 +749,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++) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -965,21 +994,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;
|
||||
@@ -987,8 +1016,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);
|
||||
@@ -1061,7 +1099,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);
|
||||
@@ -1078,7 +1115,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1118,7 +1154,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 */
|
||||
@@ -1138,12 +1173,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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
81
rsync.h
81
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
|
||||
|
||||
@@ -51,13 +51,11 @@
|
||||
#define WRITE_SIZE (32*1024)
|
||||
#define CHUNK_SIZE (32*1024)
|
||||
#define MAX_MAP_SIZE (1*1024*1024)
|
||||
#define IO_BUFFER_SIZE (4096)
|
||||
#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
|
||||
@@ -93,10 +91,6 @@
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_COMPAT_H
|
||||
#include <compat.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
@@ -189,6 +183,26 @@
|
||||
#include <syslog.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#if HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
#else
|
||||
# define dirent direct
|
||||
# if HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if HAVE_SYS_DIR_H
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if HAVE_NDIR_H
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_COMPAT_H
|
||||
#include <compat.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef S_IFLNK
|
||||
#define S_IFLNK 0120000
|
||||
#endif
|
||||
@@ -282,9 +296,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 {
|
||||
@@ -309,6 +323,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 */
|
||||
@@ -318,21 +354,6 @@ static inline int flist_up(struct file_list *flist, int i)
|
||||
return i;
|
||||
}
|
||||
|
||||
#if HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
#else
|
||||
# define dirent direct
|
||||
# if HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if HAVE_SYS_DIR_H
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if HAVE_NDIR_H
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "byteorder.h"
|
||||
#include "version.h"
|
||||
#include "proto.h"
|
||||
@@ -352,14 +373,6 @@ extern char *sys_errlist[];
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_BCOPY
|
||||
#define bcopy(src,dest,n) memcpy(dest,src,n)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_BZERO
|
||||
#define bzero(buf,n) memset(buf,0,n)
|
||||
#endif
|
||||
|
||||
#define SUPPORT_LINKS HAVE_READLINK
|
||||
#define SUPPORT_HARD_LINKS HAVE_LINK
|
||||
|
||||
|
||||
127
rsync.yo
127
rsync.yo
@@ -217,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
|
||||
@@ -337,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
|
||||
@@ -378,7 +388,7 @@ dit(bf(--csum-length LENGTH)) By default the primary checksum used in
|
||||
rsync is a very strong 16 byte MD4 checksum. In most cases you will
|
||||
find that a truncated version of this checksum is quite efficient, and
|
||||
this will decrease the size of the checksum data sent over the link,
|
||||
making things faster.
|
||||
making things faster.
|
||||
|
||||
You can choose the number of bytes in the truncated checksum using the
|
||||
--csum-length option. Any value less than or equal to 16 is valid.
|
||||
@@ -388,6 +398,11 @@ with an incorrect target file. The risk with a value of 16 is
|
||||
microscopic and can be safely ignored (the universe will probably end
|
||||
before it fails) but with smaller values the risk is higher.
|
||||
|
||||
Current versions of rsync actually use an adaptive algorithm for the
|
||||
checksum length by default, using a 16 byte file checksum to determine
|
||||
if a 2nd pass is required with a longer block checksum. Only use this
|
||||
option if you have read the source code and know what you are doing.
|
||||
|
||||
dit(bf(-T, --temp-dir DIR)) This options instructs rsync to use DIR as a
|
||||
scratch directory when creating a temporary copies of the files
|
||||
transferred on the receiving side. The default behavior is to create
|
||||
@@ -415,9 +430,9 @@ option is not specified.
|
||||
If a user or group name does not exist on the destination system then
|
||||
the numeric id from the source system is used instead.
|
||||
|
||||
dit(bf(--timeout)) This option allows you to set a maximum IO timeout in
|
||||
seconds. If no data is transferred for the specified time then rsync
|
||||
will exit. The default is 0, which means no timeout.
|
||||
dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum IO
|
||||
timeout in seconds. If no data is transferred for the specified time
|
||||
then rsync will exit. The default is 0, which means no timeout.
|
||||
|
||||
dit(bf(--daemon)) This tells rsync that it is to run as a rsync
|
||||
daemon. If standard input is a socket then rsync will assume that it
|
||||
@@ -434,6 +449,96 @@ specified.
|
||||
dit(bf(--port PORT)) This specifies an alternate TCP port number to use
|
||||
rather than the default port 873.
|
||||
|
||||
dit(bf(--stats)) This tells rsync to print a verbose set of statistics
|
||||
on the file transfer, allowing you to tell how effective the rsync
|
||||
algorithm is for your data. This option only works in conjunction with
|
||||
the -v (verbose) option.
|
||||
|
||||
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.
|
||||
|
||||
it() if the pattern is a single exclamation mark ! then the current
|
||||
exclude list is reset, removing all previous exclude patterns.
|
||||
)
|
||||
|
||||
The +/- rules are most useful in exclude lists, allowing you to have a
|
||||
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.
|
||||
)
|
||||
|
||||
manpagesection(ENVIRONMENT VARIABLES)
|
||||
|
||||
startdit()
|
||||
|
||||
dit(bf(CVSIGNORE)) The CVSIGNORE environment variable supplements any
|
||||
ignore patterns in .cvsignore files. See the --cvs-exclude option for
|
||||
more details.
|
||||
|
||||
dit(bf(RSYNC_RSH)) The RSYNC_RSH environment variable allows you to
|
||||
override the default shell used as the transport for rsync. This can
|
||||
be used instead of the -e option.
|
||||
|
||||
dit(bf(RSYNC_PASSWORD)) Setting RSYNC_PASSWORD to the required
|
||||
password allows you to run authenticated rsync connections to a rsync
|
||||
daemon without user intervention. Note that this does not supply a
|
||||
password to a shell transport such as ssh.
|
||||
|
||||
dit(bf(USER) or bf(LOGNAME)) The USER or LOGNAME environment variables
|
||||
are used to determine the default username sent to a rsync server.
|
||||
|
||||
dit(bf(HOME)) The HOME environment variable is used to find the users
|
||||
default .cvsignore file.
|
||||
|
||||
enddit()
|
||||
|
||||
manpagefiles()
|
||||
|
||||
@@ -225,7 +225,7 @@ connect.
|
||||
|
||||
The default is no "hosts allow" option, which means all hosts can connect.
|
||||
|
||||
dit(bf(hosts allow)) The "hosts deny" option allows you to specify a
|
||||
dit(bf(hosts deny)) The "hosts deny" option allows you to specify a
|
||||
list of patterns that are matched against a connecting clients
|
||||
hostname and IP address. If the pattern matches then the connection is
|
||||
rejected. See the "hosts allow" option for more information.
|
||||
|
||||
2
socket.c
2
socket.c
@@ -81,7 +81,7 @@ static int open_socket_in(int type, int port)
|
||||
return -1;
|
||||
}
|
||||
|
||||
bzero((char *)&sock,sizeof(sock));
|
||||
memset((char *)&sock,0,sizeof(sock));
|
||||
memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
|
||||
sock.sin_port = htons(port);
|
||||
sock.sin_family = hp->h_addrtype;
|
||||
|
||||
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}.?
|
||||
|
||||
|
||||
295
util.c
295
util.c
@@ -24,137 +24,30 @@
|
||||
*/
|
||||
#include "rsync.h"
|
||||
|
||||
int num_waiting(int fd)
|
||||
/****************************************************************************
|
||||
Set a fd into nonblocking mode. Uses POSIX O_NONBLOCK if available,
|
||||
else
|
||||
if SYSV use O_NDELAY
|
||||
if BSD use FNDELAY
|
||||
****************************************************************************/
|
||||
int set_nonblocking(int fd)
|
||||
{
|
||||
int len=0;
|
||||
ioctl(fd,FIONREAD,&len);
|
||||
return(len);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
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
|
||||
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);
|
||||
|
||||
if((val = fcntl(fd, F_GETFL, 0)) == -1)
|
||||
return -1;
|
||||
val |= FLAG_TO_SET;
|
||||
return fcntl( fd, F_SETFL, val);
|
||||
#undef FLAG_TO_SET
|
||||
}
|
||||
|
||||
|
||||
@@ -302,36 +195,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
|
||||
@@ -361,7 +224,7 @@ int create_directory_path(char *fname)
|
||||
|
||||
derived from GNU C's cccp.c.
|
||||
*/
|
||||
int full_write(int desc, char *ptr, int len)
|
||||
static int full_write(int desc, char *ptr, int len)
|
||||
{
|
||||
int total_written;
|
||||
|
||||
@@ -708,3 +571,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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user