mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-26 07:45:33 -04:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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)
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ AC_FUNC_MEMCMP
|
||||
AC_FUNC_UTIME_NULL
|
||||
AC_CHECK_FUNCS(mmap munmap waitpid getcwd strdup strerror chown chmod mknod)
|
||||
AC_CHECK_FUNCS(fchmod fstat strchr bcopy bzero readlink link utime utimes)
|
||||
AC_CHECK_FUNCS(memmove getopt_long lchown setlinebuf vsnprintf setsid glob)
|
||||
AC_CHECK_FUNCS(memmove getopt_long lchown setlinebuf vsnprintf setsid glob strpbrk)
|
||||
|
||||
echo $ac_n "checking for working fnmatch... $ac_c"
|
||||
AC_TRY_RUN([#include <fnmatch.h>
|
||||
|
||||
329
exclude.c
329
exclude.c
@@ -17,160 +17,233 @@
|
||||
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;
|
||||
}
|
||||
if (!*list) {
|
||||
*list = (struct exclude_struct **)malloc(sizeof(struct exclude_struct *)*2);
|
||||
} else {
|
||||
*list = (struct exclude_struct **)realloc(*list,sizeof(struct exclude_struct *)*(len+2));
|
||||
}
|
||||
|
||||
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 +254,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 +270,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);
|
||||
}
|
||||
|
||||
17
flist.c
17
flist.c
@@ -46,7 +46,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 +67,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;
|
||||
@@ -493,10 +493,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 +535,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 +548,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);
|
||||
@@ -691,7 +691,6 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
|
||||
if (f != -1) {
|
||||
io_end_buffering(f);
|
||||
write_flush(f);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
|
||||
375
io.c
375
io.c
@@ -34,7 +34,6 @@ static int multiplex_out_fd;
|
||||
static time_t last_io;
|
||||
|
||||
extern int verbose;
|
||||
extern int sparse_files;
|
||||
extern int io_timeout;
|
||||
|
||||
int64 write_total(void)
|
||||
@@ -49,9 +48,8 @@ int64 read_total(void)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -81,44 +79,72 @@ static char *read_buffer_p;
|
||||
static int read_buffer_len;
|
||||
static int read_buffer_size;
|
||||
|
||||
/* 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) {
|
||||
buf += n;
|
||||
len -= n;
|
||||
ret += n;
|
||||
if (io_timeout)
|
||||
last_io = time(NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n == -1 && errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
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 handing multiplexing -
|
||||
return number of bytes read
|
||||
never return <= 0 */
|
||||
static int read_unbuffered(int fd, char *buf, int len)
|
||||
{
|
||||
static int remaining;
|
||||
@@ -127,7 +153,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 +196,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 +210,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;
|
||||
|
||||
@@ -208,19 +229,20 @@ static void read_check(int f)
|
||||
}
|
||||
|
||||
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 +256,18 @@ 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);
|
||||
total_read += 4;
|
||||
return IVAL(b,0);
|
||||
}
|
||||
|
||||
int64 read_longint(int f)
|
||||
@@ -289,12 +284,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);
|
||||
}
|
||||
readfd(f,b,8);
|
||||
total_read += 8;
|
||||
ret = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
|
||||
}
|
||||
@@ -305,14 +295,8 @@ 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);
|
||||
total_read += len;
|
||||
}
|
||||
|
||||
void read_sbuf(int f,char *buf,int len)
|
||||
@@ -323,149 +307,73 @@ 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;
|
||||
|
||||
reading = (buffer_f_in != -1 && read_buffer_len < MAX_READ_BUFFER);
|
||||
|
||||
while (total < len) {
|
||||
int ret = write(fd,buf+total,len-total);
|
||||
|
||||
if (ret == 0) return total;
|
||||
|
||||
if (ret == -1 && !(errno == EWOULDBLOCK || errno == EAGAIN))
|
||||
return -1;
|
||||
|
||||
if (ret == -1 && got_select) {
|
||||
/* hmmm, we got a write select on the fd and
|
||||
then failed to write. Why doesn't that
|
||||
mean that the fd is dead? It doesn't on
|
||||
some systems it seems (eg. IRIX) */
|
||||
u_sleep(1000);
|
||||
}
|
||||
|
||||
got_select = 0;
|
||||
|
||||
|
||||
if (ret != -1) {
|
||||
total += ret;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (read_buffer_len < MAX_READ_BUFFER && buffer_f_in != -1)
|
||||
read_check(buffer_f_in);
|
||||
|
||||
fd_count = fd+1;
|
||||
FD_ZERO(&w_fds);
|
||||
FD_ZERO(&r_fds);
|
||||
FD_SET(fd,&w_fds);
|
||||
if (buffer_f_in != -1) {
|
||||
fd_count = fd+1;
|
||||
|
||||
if (reading) {
|
||||
FD_SET(buffer_f_in,&r_fds);
|
||||
if (buffer_f_in > fd)
|
||||
fd_count = buffer_f_in+1;
|
||||
}
|
||||
|
||||
tv.tv_sec = BLOCKING_TIMEOUT;
|
||||
tv.tv_sec = io_timeout;
|
||||
tv.tv_usec = 0;
|
||||
count = select(fd_count,buffer_f_in == -1? NULL: &r_fds,
|
||||
&w_fds,NULL,&tv);
|
||||
|
||||
if (count == -1 && errno != EINTR) {
|
||||
if (verbose > 1)
|
||||
rprintf(FERROR,"select error: %s\n", strerror(errno));
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
|
||||
count = select(fd_count,
|
||||
reading?&r_fds:NULL,
|
||||
&w_fds,NULL,
|
||||
io_timeout?&tv:NULL);
|
||||
|
||||
if (count <= 0) {
|
||||
check_timeout();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (FD_ISSET(fd, &w_fds)) {
|
||||
got_select = 1;
|
||||
int ret = write(fd,buf+total,len-total);
|
||||
|
||||
if (ret == -1 && errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret <= 0) {
|
||||
rprintf(FERROR,"erroring writing %d bytes - exiting\n", len);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
total += ret;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -491,17 +399,9 @@ void io_flush(void)
|
||||
|
||||
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 +415,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,21 +433,14 @@ 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);
|
||||
}
|
||||
writefd(f,b,4);
|
||||
total_written += 4;
|
||||
}
|
||||
|
||||
@@ -554,7 +448,6 @@ 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,22 +458,13 @@ 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);
|
||||
}
|
||||
writefd(f,b,8);
|
||||
total_written += 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);
|
||||
}
|
||||
writefd(f,buf,len);
|
||||
total_written += len;
|
||||
}
|
||||
|
||||
@@ -596,11 +480,6 @@ 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)
|
||||
{
|
||||
while (maxlen) {
|
||||
|
||||
18
lib/compat.c
18
lib/compat.c
@@ -58,3 +58,21 @@ void *memmove(void *dest, const void *src, size_t n)
|
||||
return dest;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRPBRK
|
||||
/* Find the first ocurrence in S of any character in ACCEPT.
|
||||
derived from glibc
|
||||
*/
|
||||
char *strpbrk(const char *s, const char *accept)
|
||||
{
|
||||
while (*s != '\0') {
|
||||
const char *a = accept;
|
||||
while (*a != '\0') {
|
||||
if (*a++ == *s) return (char *)s;
|
||||
}
|
||||
++s;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
1
main.c
1
main.c
@@ -49,7 +49,6 @@ static void report(int f)
|
||||
write_longint(f,read_total());
|
||||
write_longint(f,write_total());
|
||||
write_longint(f,total_size);
|
||||
write_flush(f);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
3
match.c
3
match.c
@@ -103,9 +103,6 @@ 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)
|
||||
n += s->sums[i].len;
|
||||
|
||||
|
||||
19
options.c
19
options.c
@@ -109,6 +109,8 @@ void usage(int F)
|
||||
rprintf(F,"-z, --compress compress file data\n");
|
||||
rprintf(F," --exclude FILE exclude file FILE\n");
|
||||
rprintf(F," --exclude-from FILE exclude files listed in FILE\n");
|
||||
rprintf(F," --include FILE don't exclude file FILE\n");
|
||||
rprintf(F," --include-from FILE don't exclude files listed in FILE\n");
|
||||
rprintf(F," --suffix SUFFIX override backup suffix\n");
|
||||
rprintf(F," --version print version number\n");
|
||||
rprintf(F," --daemon run as a rsync daemon\n");
|
||||
@@ -122,7 +124,8 @@ void usage(int F)
|
||||
|
||||
enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE,
|
||||
OPT_EXCLUDE_FROM,OPT_DELETE,OPT_NUMERIC_IDS,OPT_RSYNC_PATH,
|
||||
OPT_FORCE,OPT_TIMEOUT,OPT_DAEMON,OPT_CONFIG,OPT_PORT};
|
||||
OPT_FORCE,OPT_TIMEOUT,OPT_DAEMON,OPT_CONFIG,OPT_PORT,
|
||||
OPT_INCLUDE, OPT_INCLUDE_FROM};
|
||||
|
||||
static char *short_options = "oblLWHpguDCtcahvrRIxnSe:B:T:z";
|
||||
|
||||
@@ -135,6 +138,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'},
|
||||
@@ -213,11 +218,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':
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.0.12
|
||||
Version: 2.0.13
|
||||
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.13.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
16
rsync.c
16
rsync.c
@@ -147,7 +147,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -528,7 +527,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);
|
||||
@@ -696,7 +694,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 +709,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]);
|
||||
@@ -771,7 +771,6 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files phase=%d\n",phase);
|
||||
write_int(f_gen,-1);
|
||||
write_flush(f_gen);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
@@ -970,7 +969,7 @@ void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files starting\n");
|
||||
|
||||
setup_nonblocking(f_in,f_out);
|
||||
setup_readbuffer(f_in);
|
||||
|
||||
while (1) {
|
||||
i = read_int(f_in);
|
||||
@@ -979,7 +978,6 @@ void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
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;
|
||||
@@ -1061,7 +1059,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 +1075,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 +1114,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,7 +1133,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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
16
rsync.h
16
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
|
||||
@@ -309,6 +307,16 @@ struct map_struct {
|
||||
OFF_T size, p_offset;
|
||||
};
|
||||
|
||||
struct exclude_struct {
|
||||
char *orig;
|
||||
char *pattern;
|
||||
int regular_exp;
|
||||
int include;
|
||||
int directory;
|
||||
int local;
|
||||
};
|
||||
|
||||
|
||||
/* 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 */
|
||||
|
||||
76
rsync.yo
76
rsync.yo
@@ -337,23 +337,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
|
||||
@@ -436,6 +443,63 @@ rather than the default port 873.
|
||||
|
||||
enddit()
|
||||
|
||||
manpagesection(EXCLUDE PATTERNS)
|
||||
|
||||
The exclude and include patterns specified to rsync allow for flexible
|
||||
selection of what files to transfer and what files to skip.
|
||||
|
||||
rsync build a ordered list of include/exclude options as specified on
|
||||
the command line. When a filename is encountered rsync then checks the
|
||||
name against each exclude/include pattern in turn. The first matching
|
||||
pattern is acted on. If it is an exclude pattern than that file is
|
||||
skipped. If it is an include pattern then that filename is not
|
||||
skipped. If no matching include/exclude pattern is found then the
|
||||
filename is not skipped.
|
||||
|
||||
The patterns themselves can take several forms. The rules are:
|
||||
|
||||
itemize(
|
||||
it() if the pattern starts with a / then it is matched against the
|
||||
start of the filename, otherwise it is matched against the end of
|
||||
the filename. Thus /foo would match a file called foo
|
||||
at the base of the tree whereas foo would match any file
|
||||
called foo anywhere in the tree.
|
||||
|
||||
it() if the pattern ends with a / then it will only match a
|
||||
directory, not a file, link or device.
|
||||
|
||||
it() if the pattern contains a wildcard character from the set
|
||||
*?[ then regular expression matching is applied using the
|
||||
normal shell filename matching rules. Otherwise a simple string
|
||||
match is used.
|
||||
|
||||
it() if the pattern contains a / (not counting a trailing /) then it
|
||||
is matched against the full filename, including any leading
|
||||
directory. If the pattern doesn't contain a / then it is matched
|
||||
only against the final component of the filename.
|
||||
|
||||
it() if the pattern starts with "+ " (a plus followed by a space)
|
||||
then it is always considered a include pattern, even if specified as
|
||||
part of an exclude option. The "+ " part is discarded before matching.
|
||||
|
||||
it() if the pattern starts with "- " (a minus followed by a space)
|
||||
then it is always considered a exclude pattern, even if specified as
|
||||
part of an include option. The "- " part is discarded before matching.
|
||||
)
|
||||
|
||||
The +/- rules are most useful in exclude lists, allowing you to have a
|
||||
single exclude list that contains both include and exclude options.
|
||||
|
||||
Here are some examples:
|
||||
|
||||
itemize(
|
||||
it() --exclude "*.o" would exclude all filenames matching *.o
|
||||
it() --exclude "/foo" would exclude a file in the base directory called foo
|
||||
it() --exclude "foo/" would exclude any directory called foo
|
||||
it() --include "*/" --include "*.c" --exclude "*" would include all
|
||||
directories and C source files.
|
||||
)
|
||||
|
||||
manpagefiles()
|
||||
|
||||
/etc/rsyncd.conf
|
||||
|
||||
12
test.sh
12
test.sh
@@ -98,14 +98,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 +120,3 @@ else
|
||||
fi
|
||||
|
||||
checkforlogs ${LOG}.?
|
||||
|
||||
|
||||
155
util.c
155
util.c
@@ -32,131 +32,6 @@ int num_waiting(int fd)
|
||||
}
|
||||
|
||||
|
||||
struct map_struct *map_file(int fd,OFF_T len)
|
||||
{
|
||||
struct map_struct *ret;
|
||||
ret = (struct map_struct *)malloc(sizeof(*ret));
|
||||
if (!ret) out_of_memory("map_file");
|
||||
|
||||
ret->map = NULL;
|
||||
ret->fd = fd;
|
||||
ret->size = len;
|
||||
ret->p = NULL;
|
||||
ret->p_size = 0;
|
||||
ret->p_offset = 0;
|
||||
ret->p_len = 0;
|
||||
|
||||
#ifdef 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);
|
||||
}
|
||||
|
||||
|
||||
/* this is taken from CVS */
|
||||
int piped_child(char **command,int *f_in,int *f_out)
|
||||
@@ -302,36 +177,6 @@ int set_modtime(char *fname,time_t modtime)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
|
||||
else
|
||||
if SYSV use O_NDELAY
|
||||
if BSD use FNDELAY
|
||||
****************************************************************************/
|
||||
int set_blocking(int fd, int set)
|
||||
{
|
||||
int val;
|
||||
#ifdef O_NONBLOCK
|
||||
#define FLAG_TO_SET O_NONBLOCK
|
||||
#else
|
||||
#ifdef SYSV
|
||||
#define FLAG_TO_SET O_NDELAY
|
||||
#else /* BSD */
|
||||
#define FLAG_TO_SET FNDELAY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if((val = fcntl(fd, F_GETFL, 0)) == -1)
|
||||
return -1;
|
||||
if(set) /* Turn blocking on - ie. clear nonblock flag */
|
||||
val &= ~FLAG_TO_SET;
|
||||
else
|
||||
val |= FLAG_TO_SET;
|
||||
return fcntl( fd, F_SETFL, val);
|
||||
#undef FLAG_TO_SET
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
create any necessary directories in fname. Unfortunately we don't know
|
||||
what perms to give the directory when this is called so we need to rely
|
||||
|
||||
@@ -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