mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-24 23:05:52 -04:00
Compare commits
123 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5783c065ba | ||
|
|
adc19c987b | ||
|
|
3d38277706 | ||
|
|
64c704f0b9 | ||
|
|
69c6522734 | ||
|
|
0f8f98c8ff | ||
|
|
e384bfbdcb | ||
|
|
08e5094d7f | ||
|
|
4b3977bf00 | ||
|
|
c80ccabb0c | ||
|
|
ef5d23ebcd | ||
|
|
27b9a19be0 | ||
|
|
14175f1e77 | ||
|
|
269833af78 | ||
|
|
fca3ef06cd | ||
|
|
07a14ef8b2 | ||
|
|
21cde2888c | ||
|
|
4a7481889c | ||
|
|
0adb99b9dc | ||
|
|
36349ea0be | ||
|
|
ec3f7d1b61 | ||
|
|
f0359dd00d | ||
|
|
ef55c686bc | ||
|
|
5f7ce2041c | ||
|
|
328fcf113a | ||
|
|
24c857f1de | ||
|
|
a784e10d00 | ||
|
|
7eb6bf0397 | ||
|
|
49d6fdc036 | ||
|
|
8b35435f7c | ||
|
|
8ada751890 | ||
|
|
1a52e84874 | ||
|
|
53c5cbed23 | ||
|
|
4a81463880 | ||
|
|
09b7f5dbb1 | ||
|
|
6d7b6081ac | ||
|
|
31b7d79afe | ||
|
|
b2999e457f | ||
|
|
0f3203c312 | ||
|
|
a2edb26cd6 | ||
|
|
9bec528606 | ||
|
|
2f0e3b30a9 | ||
|
|
ff41a59f58 | ||
|
|
08f15335b5 | ||
|
|
bd36966bed | ||
|
|
f76933b149 | ||
|
|
378a074c82 | ||
|
|
c36cd31713 | ||
|
|
5e12ce1186 | ||
|
|
166aa72332 | ||
|
|
f9f6184f38 | ||
|
|
f625af9400 | ||
|
|
fc7952e7f3 | ||
|
|
cbce490e13 | ||
|
|
74a7f81d57 | ||
|
|
5b5591d8a8 | ||
|
|
c55f70218c | ||
|
|
6957ae33a9 | ||
|
|
8a5d6bba09 | ||
|
|
1d2c275fff | ||
|
|
d0fd26aa16 | ||
|
|
e20c5e9521 | ||
|
|
66203a982b | ||
|
|
b315601ce0 | ||
|
|
5f808dfbd7 | ||
|
|
0b73ca12fa | ||
|
|
03e2d0e329 | ||
|
|
182517e692 | ||
|
|
554e0a8dd0 | ||
|
|
b0f3f5784c | ||
|
|
3060d4aa1d | ||
|
|
1347d5126a | ||
|
|
5d1e1dcf4b | ||
|
|
74f5442401 | ||
|
|
c08bb0fb73 | ||
|
|
e30f065766 | ||
|
|
9dce9b45b3 | ||
|
|
60be6acf46 | ||
|
|
a5827a28d2 | ||
|
|
dcc875e41e | ||
|
|
128cf58433 | ||
|
|
7e0ca8e2f0 | ||
|
|
d79d1c69f7 | ||
|
|
a7d068abff | ||
|
|
7f931a0002 | ||
|
|
07b7c86c06 | ||
|
|
1f5c6343e6 | ||
|
|
290b615a16 | ||
|
|
57df171bc0 | ||
|
|
f08baea3dd | ||
|
|
2fb139c11b | ||
|
|
3420c8e6e0 | ||
|
|
b17bc22bb3 | ||
|
|
3adffb52e6 | ||
|
|
4df9f36841 | ||
|
|
5c9730a46c | ||
|
|
d9fcc198cf | ||
|
|
c831379436 | ||
|
|
d73ee7b70e | ||
|
|
cda2ae84b3 | ||
|
|
e7d6e0aa0c | ||
|
|
8c9fd200f9 | ||
|
|
79f118d859 | ||
|
|
7b10f91d8f | ||
|
|
3d19b4c83e | ||
|
|
79452d4693 | ||
|
|
cb13abfed0 | ||
|
|
0503f06089 | ||
|
|
f855a7d01a | ||
|
|
4c3b4b2557 | ||
|
|
79b5aa09a0 | ||
|
|
9bd6597666 | ||
|
|
6fe076b3d7 | ||
|
|
cec8aa7724 | ||
|
|
4c36a13ef2 | ||
|
|
24986abd07 | ||
|
|
8dfac376b5 | ||
|
|
e78733d975 | ||
|
|
dffba35e01 | ||
|
|
bd4ed7f719 | ||
|
|
752eaba41f | ||
|
|
ad517ce5b3 | ||
|
|
1f8413449d |
@@ -20,11 +20,13 @@ SHELL=/bin/sh
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
HEADS=byteorder.h config.h errcode.h proto.h rsync.h version.h \
|
||||
lib/fnmatch.h lib/getopt.h lib/mdfour.h
|
||||
LIBOBJ=lib/getopt.o lib/fnmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o
|
||||
ZLIBOBJ=zlib/deflate.o zlib/infblock.o zlib/infcodes.o zlib/inffast.o \
|
||||
zlib/inflate.o zlib/inftrees.o zlib/infutil.o zlib/trees.o \
|
||||
zlib/zutil.o zlib/adler32.o
|
||||
OBJS1=rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o main.o checksum.o match.o syscall.o log.o
|
||||
OBJS1=rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o main.o checksum.o match.o syscall.o log.o backup.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)
|
||||
@@ -53,6 +55,8 @@ install-strip:
|
||||
rsync: $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o rsync $(OBJS) $(LIBS)
|
||||
|
||||
$(OBJS): $(HEADS)
|
||||
|
||||
rsync.1: rsync.yo
|
||||
yodl2man -o rsync.1 rsync.yo
|
||||
|
||||
@@ -60,7 +64,7 @@ rsyncd.conf.5: rsyncd.conf.yo
|
||||
yodl2man -o rsyncd.conf.5 rsyncd.conf.yo
|
||||
|
||||
proto:
|
||||
cat *.c | awk -f mkproto.awk > proto.h
|
||||
cat *.c lib/compat.c | awk -f mkproto.awk > proto.h
|
||||
|
||||
clean:
|
||||
rm -f *~ $(OBJS) rsync
|
||||
|
||||
@@ -10,3 +10,6 @@
|
||||
#undef HAVE_SHORT_INO_T
|
||||
#undef HAVE_GETOPT_LONG
|
||||
#undef REPLACE_INET_NTOA
|
||||
#undef REPLACE_INET_ATON
|
||||
#undef HAVE_GETTIMEOFDAY_TZ
|
||||
#undef HAVE_SOCKETPAIR
|
||||
|
||||
@@ -56,7 +56,7 @@ static void gen_challenge(char *addr, char *challenge)
|
||||
memset(input, 0, sizeof(input));
|
||||
|
||||
strlcpy((char *)input, addr, 17);
|
||||
gettimeofday(&tv, NULL);
|
||||
sys_gettimeofday(&tv);
|
||||
SIVAL(input, 16, tv.tv_sec);
|
||||
SIVAL(input, 20, tv.tv_usec);
|
||||
SIVAL(input, 24, getpid());
|
||||
|
||||
288
backup.c
Normal file
288
backup.c
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1999
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/* backup handling code */
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern char *backup_suffix;
|
||||
extern char *backup_dir;
|
||||
|
||||
|
||||
extern int am_root;
|
||||
extern int preserve_devices;
|
||||
extern int preserve_links;
|
||||
extern int preserve_hard_links;
|
||||
|
||||
/* simple backup creates a backup with a suffix in the same directory */
|
||||
static int make_simple_backup(char *fname)
|
||||
{
|
||||
char fnamebak[MAXPATHLEN];
|
||||
if (strlen(fname) + strlen(backup_suffix) > (MAXPATHLEN-1)) {
|
||||
rprintf(FERROR,"backup filename too long\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
slprintf(fnamebak,sizeof(fnamebak),"%s%s",fname,backup_suffix);
|
||||
if (do_rename(fname,fnamebak) != 0) {
|
||||
/* cygwin (at least version b19) reports EINVAL */
|
||||
if (errno != ENOENT && errno != EINVAL) {
|
||||
rprintf(FERROR,"rename %s %s : %s\n",fname,fnamebak,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
} else if (verbose > 1) {
|
||||
rprintf(FINFO,"backed up %s to %s\n",fname,fnamebak);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* recursively make a directory path */
|
||||
static int make_dir(char *name, int mask)
|
||||
{
|
||||
char newdir [MAXPATHLEN];
|
||||
char *p, *d;
|
||||
|
||||
/* copy pathname over, look for last '/' */
|
||||
for (p = d = newdir; *name; *d++ = *name++)
|
||||
if (*name == '/')
|
||||
p = d;
|
||||
if (p == newdir)
|
||||
return 0;
|
||||
*p = 0;
|
||||
|
||||
/* make the new directory, if that fails then make its parent */
|
||||
while (do_mkdir (newdir, mask) != 0)
|
||||
if ((errno != ENOENT) || !make_dir (newdir, mask))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
} /* make_dir */
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Create a directory given an absolute path, perms based upon another directory
|
||||
path
|
||||
****************************************************************************/
|
||||
static int make_bak_dir(char *fname,char *bak_path)
|
||||
{
|
||||
STRUCT_STAT st;
|
||||
STRUCT_STAT *st2;
|
||||
char fullpath[MAXPATHLEN];
|
||||
extern int orig_umask;
|
||||
char *p;
|
||||
char *q;
|
||||
|
||||
while(strncmp(bak_path,"./",2)==0) bak_path += 2;
|
||||
|
||||
if(bak_path[strlen(bak_path)-1]!='/') {
|
||||
slprintf(fullpath,sizeof(fullpath),"%s/",bak_path);
|
||||
} else {
|
||||
slprintf(fullpath,sizeof(fullpath),"%s",bak_path);
|
||||
}
|
||||
p=fullpath;
|
||||
q=&fullpath[strlen(fullpath)]; /* End of bak_path string */
|
||||
strcat(fullpath,fname);
|
||||
|
||||
/* Make the directories */
|
||||
while ((p=strchr(p,'/'))) {
|
||||
*p = 0;
|
||||
if(do_lstat(fullpath,&st)!=0) {
|
||||
do_mkdir(fullpath,0777 & ~orig_umask);
|
||||
if(p>q) {
|
||||
if(do_lstat(q,&st)!=0) {
|
||||
rprintf(FERROR,"make_bak_dir stat %s : %s\n",fullpath,strerror(errno));
|
||||
} else {
|
||||
st2=&st;
|
||||
set_modtime(fullpath,st2->st_mtime);
|
||||
if(do_lchown(fullpath,st2->st_uid,st2->st_gid)!=0) {
|
||||
rprintf(FERROR,"make_bak_dir chown %s : %s\n",fullpath,strerror(errno));
|
||||
};
|
||||
if(do_chmod(fullpath,st2->st_mode)!=0) {
|
||||
rprintf(FERROR,"make_bak_dir failed to set permissions on %s : %s\n",fullpath,strerror(errno));
|
||||
};
|
||||
};
|
||||
}
|
||||
};
|
||||
*p = '/';
|
||||
p++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* robustly move a file, creating new directory structures if necessary */
|
||||
static int robust_move(char *src, char *dst)
|
||||
{
|
||||
int keep_trying = 4;
|
||||
int keep_path_extfs = 0;
|
||||
int failed;
|
||||
|
||||
while (keep_trying) {
|
||||
if (keep_path_extfs) {
|
||||
failed = copy_file(src, dst, 0755);
|
||||
if (!failed) {
|
||||
do_unlink(src);
|
||||
}
|
||||
} else {
|
||||
failed = robust_rename (src, dst);
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
if (verbose > 2)
|
||||
rprintf (FERROR, "robust_move failed: %s(%d)\n",
|
||||
strerror (errno), errno);
|
||||
switch (errno) {
|
||||
/* external filesystem */
|
||||
case EXDEV:
|
||||
keep_path_extfs = 1;
|
||||
keep_trying--;
|
||||
break;
|
||||
/* no directory to write to */
|
||||
case ENOENT:
|
||||
make_dir (dst, 0755);
|
||||
keep_trying--;
|
||||
break;
|
||||
default:
|
||||
keep_trying = 0;
|
||||
} /* switch */
|
||||
} else
|
||||
keep_trying = 0;
|
||||
} /* while */
|
||||
return (!failed);
|
||||
} /* robust_move */
|
||||
|
||||
|
||||
/* if we have a backup_dir, then we get here from make_backup().
|
||||
We will move the file to be deleted into a parallel directory tree */
|
||||
static int keep_backup(char *fname)
|
||||
{
|
||||
|
||||
static int initialised;
|
||||
|
||||
char keep_name [MAXPATHLEN];
|
||||
STRUCT_STAT st;
|
||||
struct file_struct *file;
|
||||
|
||||
int kept=0;
|
||||
int ret_code;
|
||||
|
||||
if (!initialised) {
|
||||
if (backup_dir[strlen(backup_dir) - 1] == '/')
|
||||
backup_dir[strlen(backup_dir) - 1] = 0;
|
||||
if (verbose > 0)
|
||||
rprintf (FINFO, "backup_dir is %s\n", backup_dir);
|
||||
initialised = 1;
|
||||
}
|
||||
|
||||
/* return if no file to keep */
|
||||
#if SUPPORT_LINKS
|
||||
if (do_lstat (fname, &st)) return 1;
|
||||
#else
|
||||
if (do_stat (fname, &st)) return 1;
|
||||
#endif
|
||||
|
||||
file = make_file (0, fname, 0);
|
||||
|
||||
/* make a complete pathname for backup file */
|
||||
if (strlen(backup_dir) + strlen(fname) > (MAXPATHLEN - 1)) {
|
||||
rprintf (FERROR, "keep_backup filename too long\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
slprintf(keep_name, sizeof (keep_name), "%s/%s", backup_dir, fname);
|
||||
|
||||
|
||||
#ifdef HAVE_MKNOD
|
||||
/* Check to see if this is a device file, or link */
|
||||
if(IS_DEVICE(file->mode)) {
|
||||
if(am_root && preserve_devices) {
|
||||
make_bak_dir(fname,backup_dir);
|
||||
if(do_mknod(keep_name,file->mode,file->rdev)!=0) {
|
||||
rprintf(FERROR,"mknod %s : %s\n",keep_name,strerror(errno));
|
||||
} else {
|
||||
if(verbose>2)
|
||||
rprintf(FINFO,"make_backup : DEVICE %s successful.\n",fname);
|
||||
};
|
||||
};
|
||||
kept=1;
|
||||
do_unlink(fname);
|
||||
};
|
||||
#endif
|
||||
|
||||
if(!kept && S_ISDIR(file->mode)) {
|
||||
/* make an empty directory */
|
||||
make_bak_dir(fname,backup_dir);
|
||||
do_mkdir(keep_name,file->mode);
|
||||
ret_code=do_rmdir(fname);
|
||||
if(verbose>2)
|
||||
rprintf(FINFO,"make_backup : RMDIR %s returns %i\n",fname,ret_code);
|
||||
kept=1;
|
||||
};
|
||||
|
||||
#if SUPPORT_LINKS
|
||||
if(!kept && preserve_links && S_ISLNK(file->mode)) {
|
||||
extern int safe_symlinks;
|
||||
if (safe_symlinks && unsafe_symlink(file->link, keep_name)) {
|
||||
if (verbose) {
|
||||
rprintf(FINFO,"ignoring unsafe symlink %s -> %s\n",
|
||||
keep_name,file->link);
|
||||
}
|
||||
kept=1;
|
||||
}
|
||||
make_bak_dir(fname,backup_dir);
|
||||
if(do_symlink(file->link,keep_name) != 0) {
|
||||
rprintf(FERROR,"link %s -> %s : %s\n",keep_name,file->link,strerror(errno));
|
||||
};
|
||||
do_unlink(fname);
|
||||
kept=1;
|
||||
};
|
||||
#endif
|
||||
if(!kept && preserve_hard_links && check_hard_link(file)) {
|
||||
if(verbose > 1) rprintf(FINFO,"%s is a hard link\n",f_name(file));
|
||||
};
|
||||
|
||||
if(!kept && !S_ISREG(file->mode)) {
|
||||
rprintf(FINFO,"make_bak: skipping non-regular file %s\n",fname);
|
||||
}
|
||||
|
||||
/* move to keep tree if a file */
|
||||
if(!kept) {
|
||||
if (!robust_move (fname, keep_name))
|
||||
rprintf(FERROR, "keep_backup failed %s -> %s : %s\n",
|
||||
fname, keep_name, strerror(errno));
|
||||
};
|
||||
set_perms (keep_name, file, NULL, 0);
|
||||
free_file (file);
|
||||
free (file);
|
||||
|
||||
if (verbose > 1)
|
||||
rprintf (FINFO, "keep_backup %s -> %s\n", fname, keep_name);
|
||||
return 1;
|
||||
} /* keep_backup */
|
||||
|
||||
|
||||
/* main backup switch routine */
|
||||
int make_backup(char *fname)
|
||||
{
|
||||
if (backup_dir)
|
||||
return (keep_backup(fname));
|
||||
else
|
||||
return (make_simple_backup(fname));
|
||||
}
|
||||
|
||||
@@ -91,9 +91,9 @@ void file_checksum(char *fname,char *sum,OFF_T size)
|
||||
char tmpchunk[CSUM_CHUNK];
|
||||
struct mdfour m;
|
||||
|
||||
memset(sum,0,csum_length);
|
||||
memset(sum,0,MD4_SUM_LENGTH);
|
||||
|
||||
fd = open(fname,O_RDONLY);
|
||||
fd = do_open(fname, O_RDONLY, 0);
|
||||
if (fd == -1) return;
|
||||
|
||||
buf = map_file(fd,size);
|
||||
|
||||
@@ -30,12 +30,16 @@ static struct file_struct *cleanup_file;
|
||||
static int cleanup_fd1, cleanup_fd2;
|
||||
static struct map_struct *cleanup_buf;
|
||||
static int cleanup_pid = 0;
|
||||
extern int io_error;
|
||||
|
||||
void _exit_cleanup(int code, const char *file, int line)
|
||||
{
|
||||
extern int keep_partial;
|
||||
|
||||
if (code == 0 && io_error) code = RERR_FILEIO;
|
||||
|
||||
signal(SIGUSR1, SIG_IGN);
|
||||
signal(SIGUSR2, SIG_IGN);
|
||||
|
||||
if (cleanup_got_literal && cleanup_fname && keep_partial) {
|
||||
char *fname = cleanup_fname;
|
||||
|
||||
@@ -25,6 +25,7 @@ extern int read_only;
|
||||
extern int verbose;
|
||||
extern int rsync_port;
|
||||
char *auth_user;
|
||||
int sanitize_paths = 0;
|
||||
|
||||
int start_socket_client(char *host, char *path, int argc, char *argv[])
|
||||
{
|
||||
@@ -35,6 +36,7 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
|
||||
char *p, *user=NULL;
|
||||
extern int remote_version;
|
||||
extern int am_sender;
|
||||
extern struct in_addr socket_address;
|
||||
|
||||
if (*path == '/') {
|
||||
rprintf(FERROR,"ERROR: The remote path must start with a module name\n");
|
||||
@@ -51,7 +53,7 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
|
||||
if (!user) user = getenv("USER");
|
||||
if (!user) user = getenv("LOGNAME");
|
||||
|
||||
fd = open_socket_out(host, rsync_port);
|
||||
fd = open_socket_out(host, rsync_port, &socket_address);
|
||||
if (fd == -1) {
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
@@ -99,8 +101,10 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
|
||||
}
|
||||
io_printf(fd,"\n");
|
||||
|
||||
if (remote_version > 17 && !am_sender)
|
||||
io_start_multiplex_in(fd);
|
||||
if (remote_version < 23) {
|
||||
if (remote_version == 22 || (remote_version > 17 && !am_sender))
|
||||
io_start_multiplex_in(fd);
|
||||
}
|
||||
|
||||
return client_run(fd, fd, -1, argc, argv);
|
||||
}
|
||||
@@ -161,9 +165,6 @@ static int rsync_module(int fd, int i)
|
||||
|
||||
module_id = i;
|
||||
|
||||
if (lp_read_only(i))
|
||||
read_only = 1;
|
||||
|
||||
am_root = (getuid() == 0);
|
||||
|
||||
if (am_root) {
|
||||
@@ -221,6 +222,7 @@ static int rsync_module(int fd, int i)
|
||||
io_printf(fd,"@ERROR: chdir failed\n");
|
||||
return -1;
|
||||
}
|
||||
sanitize_paths = 1;
|
||||
}
|
||||
|
||||
if (am_root) {
|
||||
@@ -262,7 +264,7 @@ static int rsync_module(int fd, int i)
|
||||
request = strdup(p);
|
||||
start_glob++;
|
||||
}
|
||||
glob_expand(name, argv, &argc, MAX_ARGS, !use_chroot);
|
||||
glob_expand(name, argv, &argc, MAX_ARGS);
|
||||
} else {
|
||||
argc++;
|
||||
}
|
||||
@@ -276,7 +278,7 @@ static int rsync_module(int fd, int i)
|
||||
}
|
||||
}
|
||||
|
||||
if (!use_chroot) {
|
||||
if (sanitize_paths) {
|
||||
/*
|
||||
* Note that this is applied to all parameters, whether or not
|
||||
* they are filenames, but no other legal parameters contain
|
||||
@@ -285,7 +287,7 @@ static int rsync_module(int fd, int i)
|
||||
* and which aren't.
|
||||
*/
|
||||
for (i = 1; i < argc; i++) {
|
||||
sanitize_path(argv[i]);
|
||||
sanitize_path(argv[i], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,8 +315,10 @@ static int rsync_module(int fd, int i)
|
||||
argp = argv + optind;
|
||||
optind = 0;
|
||||
|
||||
if (remote_version > 17 && am_sender)
|
||||
io_start_multiplex_out(fd);
|
||||
if (remote_version < 23) {
|
||||
if (remote_version == 22 || (remote_version > 17 && am_sender))
|
||||
io_start_multiplex_out(fd);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
option_error();
|
||||
@@ -359,7 +363,7 @@ static int start_daemon(int fd)
|
||||
|
||||
set_socket_options(fd,"SO_KEEPALIVE");
|
||||
set_socket_options(fd,lp_socket_options());
|
||||
|
||||
set_nonblocking(fd);
|
||||
|
||||
io_printf(fd,"@RSYNCD: %d\n", PROTOCOL_VERSION);
|
||||
|
||||
@@ -417,6 +421,7 @@ static int start_daemon(int fd)
|
||||
int daemon_main(void)
|
||||
{
|
||||
extern char *config_file;
|
||||
extern int orig_umask;
|
||||
char *pid_file;
|
||||
|
||||
if (is_a_socket(STDIN_FILENO)) {
|
||||
@@ -430,15 +435,12 @@ int daemon_main(void)
|
||||
open("/dev/null", O_RDWR);
|
||||
}
|
||||
|
||||
set_nonblocking(STDIN_FILENO);
|
||||
|
||||
return start_daemon(STDIN_FILENO);
|
||||
}
|
||||
|
||||
become_daemon();
|
||||
|
||||
if (!lp_load(config_file, 1)) {
|
||||
fprintf(stderr,"failed to load config file %s\n", config_file);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
@@ -447,16 +449,19 @@ int daemon_main(void)
|
||||
rprintf(FINFO,"rsyncd version %s starting\n",VERSION);
|
||||
|
||||
if (((pid_file = lp_pid_file()) != NULL) && (*pid_file != '\0')) {
|
||||
FILE *f;
|
||||
char pidbuf[16];
|
||||
int fd;
|
||||
int pid = (int) getpid();
|
||||
cleanup_set_pid(pid);
|
||||
if ((f = fopen(lp_pid_file(), "w")) == NULL) {
|
||||
if ((fd = do_open(lp_pid_file(), O_WRONLY|O_CREAT|O_TRUNC,
|
||||
0666 & ~orig_umask)) == -1) {
|
||||
cleanup_set_pid(0);
|
||||
fprintf(stderr,"failed to create pid file %s\n", pid_file);
|
||||
rprintf(FLOG,"failed to create pid file %s\n", pid_file);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
fprintf(f, "%d\n", pid);
|
||||
fclose(f);
|
||||
slprintf(pidbuf, sizeof(pidbuf), "%d\n", pid);
|
||||
write(fd, pidbuf, strlen(pidbuf));
|
||||
close(fd);
|
||||
}
|
||||
|
||||
start_accept_loop(rsync_port, start_daemon);
|
||||
|
||||
2
compat.c
2
compat.c
@@ -23,8 +23,6 @@
|
||||
|
||||
extern int am_server;
|
||||
|
||||
extern int csum_length;
|
||||
|
||||
extern int preserve_links;
|
||||
extern int preserve_perms;
|
||||
extern int preserve_devices;
|
||||
|
||||
286
config.guess
vendored
286
config.guess
vendored
@@ -1,6 +1,7 @@
|
||||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
@@ -23,6 +24,7 @@
|
||||
|
||||
# Written by Per Bothner <bothner@cygnus.com>.
|
||||
# The master version of this file is at the FSF in /home/gd/gnu/lib.
|
||||
# Please send patches to <autoconf-patches@gnu.org>.
|
||||
#
|
||||
# This script attempts to guess a canonical system name similar to
|
||||
# config.sub. If it succeeds, it prints the system name on stdout, and
|
||||
@@ -35,6 +37,20 @@
|
||||
# (but try to keep the structure clean).
|
||||
#
|
||||
|
||||
# Use $HOST_CC if defined. $CC may point to a cross-compiler
|
||||
if test x"$CC_FOR_BUILD" = x; then
|
||||
if test x"$HOST_CC" != x; then
|
||||
CC_FOR_BUILD="$HOST_CC"
|
||||
else
|
||||
if test x"$CC" != x; then
|
||||
CC_FOR_BUILD="$CC"
|
||||
else
|
||||
CC_FOR_BUILD=cc
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
|
||||
# (ghazi@noc.rutgers.edu 8/24/94.)
|
||||
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
|
||||
@@ -77,7 +93,7 @@ main:
|
||||
ret \$31,(\$26),1
|
||||
.end main
|
||||
EOF
|
||||
${CC-cc} $dummy.s -o $dummy 2>/dev/null
|
||||
$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
|
||||
if test "$?" = 0 ; then
|
||||
./$dummy
|
||||
case "$?" in
|
||||
@@ -99,7 +115,13 @@ EOF
|
||||
esac
|
||||
fi
|
||||
rm -f $dummy.s $dummy
|
||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]`
|
||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||
exit 0 ;;
|
||||
Alpha\ *:Windows_NT*:*)
|
||||
# How do we know it's Interix rather than the generic POSIX subsystem?
|
||||
# Should we change UNAME_MACHINE based on the output of uname instead
|
||||
# of the specific Alpha model?
|
||||
echo alpha-pc-interix
|
||||
exit 0 ;;
|
||||
21064:Windows_NT:50:3)
|
||||
echo alpha-dec-winnt3.5
|
||||
@@ -134,6 +156,9 @@ EOF
|
||||
wgrisc:OpenBSD:*:*)
|
||||
echo mipsel-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:OS/390:*:*)
|
||||
echo i370-ibm-openedition
|
||||
exit 0 ;;
|
||||
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
|
||||
echo arm-acorn-riscix${UNAME_RELEASE}
|
||||
exit 0;;
|
||||
@@ -143,7 +168,7 @@ EOF
|
||||
SR2?01:HI-UX/MPP:*:*)
|
||||
echo hppa1.1-hitachi-hiuxmpp
|
||||
exit 0;;
|
||||
Pyramid*:OSx*:*:*|MIS*:OSx*:*:*|MIS*:SMP_DC-OSx*:*:*)
|
||||
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
|
||||
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
|
||||
if test "`(/bin/universe) 2>/dev/null`" = att ; then
|
||||
echo pyramid-pyramid-sysv3
|
||||
@@ -151,7 +176,7 @@ EOF
|
||||
echo pyramid-pyramid-bsd
|
||||
fi
|
||||
exit 0 ;;
|
||||
NILE:*:*:dcosx)
|
||||
NILE*:*:*:dcosx)
|
||||
echo pyramid-pyramid-svr4
|
||||
exit 0 ;;
|
||||
sun4H:SunOS:5.*:*)
|
||||
@@ -202,6 +227,32 @@ EOF
|
||||
atari*:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
# The situation for MiNT is a little confusing. The machine name
|
||||
# can be virtually everything (everything which is not
|
||||
# "atarist" or "atariste" at least should have a processor
|
||||
# > m68000). The system name ranges from "MiNT" over "FreeMiNT"
|
||||
# to the lowercase version "mint" (or "freemint"). Finally
|
||||
# the system name "TOS" denotes a system which is actually not
|
||||
# MiNT. But MiNT is downward compatible to TOS, so this should
|
||||
# be no problem.
|
||||
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
|
||||
echo m68k-atari-mint${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
|
||||
echo m68k-atari-mint${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
|
||||
echo m68k-atari-mint${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
|
||||
echo m68k-milan-mint${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
|
||||
echo m68k-hades-mint${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
|
||||
echo m68k-unknown-mint${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sun3*:NetBSD:*:*)
|
||||
echo m68k-sun-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
@@ -235,12 +286,16 @@ EOF
|
||||
VAX*:ULTRIX*:*:*)
|
||||
echo vax-dec-ultrix${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
2020:CLIX:*:*)
|
||||
2020:CLIX:*:* | 2430:CLIX:*:*)
|
||||
echo clipper-intergraph-clix${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mips:*:*:UMIPS | mips:*:*:RISCos)
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
int main (argc, argv) int argc; char **argv; {
|
||||
#ifdef __cplusplus
|
||||
int main (int argc, char *argv[]) {
|
||||
#else
|
||||
int main (argc, argv) int argc; char *argv[]; {
|
||||
#endif
|
||||
#if defined (host_mips) && defined (MIPSEB)
|
||||
#if defined (SYSTYPE_SYSV)
|
||||
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
|
||||
@@ -255,7 +310,7 @@ EOF
|
||||
exit (-1);
|
||||
}
|
||||
EOF
|
||||
${CC-cc} $dummy.c -o $dummy \
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy \
|
||||
&& ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
|
||||
&& rm $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
@@ -276,15 +331,18 @@ EOF
|
||||
AViiON:dgux:*:*)
|
||||
# DG/UX returns AViiON for all architectures
|
||||
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
||||
if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
|
||||
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
|
||||
-o ${TARGET_BINARY_INTERFACE}x = x ] ; then
|
||||
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110]
|
||||
then
|
||||
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
|
||||
[ ${TARGET_BINARY_INTERFACE}x = x ]
|
||||
then
|
||||
echo m88k-dg-dgux${UNAME_RELEASE}
|
||||
else
|
||||
else
|
||||
echo m88k-dg-dguxbcs${UNAME_RELEASE}
|
||||
fi
|
||||
else
|
||||
echo i586-dg-dgux${UNAME_RELEASE}
|
||||
fi
|
||||
else echo i586-dg-dgux${UNAME_RELEASE}
|
||||
fi
|
||||
exit 0 ;;
|
||||
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
|
||||
echo m88k-dolphin-sysv3
|
||||
@@ -321,7 +379,7 @@ EOF
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
${CC-cc} $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
echo rs6000-ibm-aix3.2.5
|
||||
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
|
||||
@@ -369,25 +427,25 @@ EOF
|
||||
case "${UNAME_MACHINE}" in
|
||||
9000/31? ) HP_ARCH=m68000 ;;
|
||||
9000/[34]?? ) HP_ARCH=m68k ;;
|
||||
9000/6?? | 9000/7?? | 9000/80[24] | 9000/8?[13679] | 9000/892 )
|
||||
9000/[678][0-9][0-9])
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
int main ()
|
||||
{
|
||||
#if defined(_SC_KERNEL_BITS)
|
||||
long bits = sysconf(_SC_KERNEL_BITS);
|
||||
#endif
|
||||
#endif
|
||||
long cpu = sysconf (_SC_CPU_VERSION);
|
||||
|
||||
switch (cpu)
|
||||
|
||||
switch (cpu)
|
||||
{
|
||||
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
|
||||
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
|
||||
case CPU_PA_RISC2_0:
|
||||
case CPU_PA_RISC2_0:
|
||||
#if defined(_SC_KERNEL_BITS)
|
||||
switch (bits)
|
||||
switch (bits)
|
||||
{
|
||||
case 64: puts ("hppa2.0w"); break;
|
||||
case 32: puts ("hppa2.0n"); break;
|
||||
@@ -395,13 +453,13 @@ EOF
|
||||
} break;
|
||||
#else /* !defined(_SC_KERNEL_BITS) */
|
||||
puts ("hppa2.0"); break;
|
||||
#endif
|
||||
#endif
|
||||
default: puts ("hppa1.0"); break;
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
EOF
|
||||
(${CC-cc} $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
|
||||
(CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
|
||||
rm -f $dummy.c $dummy
|
||||
esac
|
||||
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
|
||||
@@ -433,7 +491,7 @@ EOF
|
||||
exit (0);
|
||||
}
|
||||
EOF
|
||||
${CC-cc} $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
echo unknown-hitachi-hiuxwe2
|
||||
exit 0 ;;
|
||||
@@ -443,6 +501,9 @@ EOF
|
||||
9000/8??:4.3bsd:*:*)
|
||||
echo hppa1.0-hp-bsd
|
||||
exit 0 ;;
|
||||
*9??*:MPE/iX:*:*)
|
||||
echo hppa1.0-hp-mpeix
|
||||
exit 0 ;;
|
||||
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
|
||||
echo hppa1.1-hp-osf
|
||||
exit 0 ;;
|
||||
@@ -459,6 +520,9 @@ EOF
|
||||
parisc*:Lites*:*:*)
|
||||
echo hppa1.1-hp-lites
|
||||
exit 0 ;;
|
||||
hppa*:OpenBSD:*:*)
|
||||
echo hppa-unknown-openbsd
|
||||
exit 0 ;;
|
||||
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
|
||||
echo c1-convex-bsd
|
||||
exit 0 ;;
|
||||
@@ -492,13 +556,13 @@ EOF
|
||||
echo t90-cray-unicos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
CRAY*T3E:*:*:*)
|
||||
echo t3e-cray-unicosmk${UNAME_RELEASE}
|
||||
echo alpha-cray-unicosmk${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
CRAY-2:*:*:*)
|
||||
echo cray2-cray-unicos
|
||||
exit 0 ;;
|
||||
F300:UNIX_System_V:*:*)
|
||||
FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
|
||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
|
||||
echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit 0 ;;
|
||||
@@ -511,20 +575,26 @@ EOF
|
||||
hp300:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sparc*:BSD/OS:*:*)
|
||||
echo sparc-unknown-bsdi${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
i?86:BSD/386:*:* | i?86:BSD/OS:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sparc*:BSD/OS:*:*)
|
||||
echo sparc-unknown-bsdi${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:BSD/OS:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:FreeBSD:*:*)
|
||||
if test -x /usr/bin/objformat; then
|
||||
if test "elf" = "`/usr/bin/objformat`"; then
|
||||
echo ${UNAME_MACHINE}-unknown-freebsdelf`echo ${UNAME_RELEASE}|sed -e 's/[-_].*//'`
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
|
||||
exit 0 ;;
|
||||
*:NetBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*//'`
|
||||
exit 0 ;;
|
||||
*:OpenBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
@@ -535,6 +605,15 @@ EOF
|
||||
i*:MINGW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-mingw32
|
||||
exit 0 ;;
|
||||
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
|
||||
# How do we know it's Interix rather than the generic POSIX subsystem?
|
||||
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
|
||||
# UNAME_MACHINE based on the output of uname instead of i386?
|
||||
echo i386-pc-interix
|
||||
exit 0 ;;
|
||||
i*:UWIN*:*)
|
||||
echo ${UNAME_MACHINE}-pc-uwin
|
||||
exit 0 ;;
|
||||
p*:CYGWIN*:*)
|
||||
echo powerpcle-unknown-cygwin
|
||||
exit 0 ;;
|
||||
@@ -545,15 +624,11 @@ EOF
|
||||
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
|
||||
exit 0 ;;
|
||||
*:Linux:*:*)
|
||||
# uname on the ARM produces all sorts of strangeness, and we need to
|
||||
# filter it out.
|
||||
case "$UNAME_MACHINE" in
|
||||
arm* | sa110*) UNAME_MACHINE="arm" ;;
|
||||
esac
|
||||
|
||||
# The BFD linker knows what the default object file format is, so
|
||||
# first see if it will tell us.
|
||||
ld_help_string=`ld --help 2>&1`
|
||||
# first see if it will tell us. cd to the root directory to prevent
|
||||
# problems with other programs or directories called `ld' in the path.
|
||||
ld_help_string=`cd /; ld --help 2>&1`
|
||||
ld_supported_emulations=`echo $ld_help_string \
|
||||
| sed -ne '/supported emulations:/!d
|
||||
s/[ ][ ]*/ /g
|
||||
@@ -561,12 +636,70 @@ EOF
|
||||
s/ .*//
|
||||
p'`
|
||||
case "$ld_supported_emulations" in
|
||||
i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;;
|
||||
i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;;
|
||||
sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
|
||||
armlinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
|
||||
m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
|
||||
elf32ppc) echo "powerpc-unknown-linux-gnu" ; exit 0 ;;
|
||||
*ia64)
|
||||
echo "${UNAME_MACHINE}-unknown-linux"
|
||||
exit 0
|
||||
;;
|
||||
i?86linux)
|
||||
echo "${UNAME_MACHINE}-pc-linux-gnuaout"
|
||||
exit 0
|
||||
;;
|
||||
i?86coff)
|
||||
echo "${UNAME_MACHINE}-pc-linux-gnucoff"
|
||||
exit 0
|
||||
;;
|
||||
sparclinux)
|
||||
echo "${UNAME_MACHINE}-unknown-linux-gnuaout"
|
||||
exit 0
|
||||
;;
|
||||
armlinux)
|
||||
echo "${UNAME_MACHINE}-unknown-linux-gnuaout"
|
||||
exit 0
|
||||
;;
|
||||
elf32arm*)
|
||||
echo "${UNAME_MACHINE}-unknown-linux-gnu"
|
||||
exit 0
|
||||
;;
|
||||
armelf_linux*)
|
||||
echo "${UNAME_MACHINE}-unknown-linux-gnu"
|
||||
exit 0
|
||||
;;
|
||||
m68klinux)
|
||||
echo "${UNAME_MACHINE}-unknown-linux-gnuaout"
|
||||
exit 0
|
||||
;;
|
||||
elf32ppc)
|
||||
# Determine Lib Version
|
||||
cat >$dummy.c <<EOF
|
||||
#include <features.h>
|
||||
#if defined(__GLIBC__)
|
||||
extern char __libc_version[];
|
||||
extern char __libc_release[];
|
||||
#endif
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
#if defined(__GLIBC__)
|
||||
printf("%s %s\n", __libc_version, __libc_release);
|
||||
#else
|
||||
printf("unkown\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
LIBC=""
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null
|
||||
if test "$?" = 0 ; then
|
||||
./$dummy | grep 1\.99 > /dev/null
|
||||
if test "$?" = 0 ; then
|
||||
LIBC="libc1"
|
||||
fi
|
||||
fi
|
||||
rm -f $dummy.c $dummy
|
||||
echo powerpc-unknown-linux-gnu${LIBC}
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
if test "${UNAME_MACHINE}" = "alpha" ; then
|
||||
@@ -588,7 +721,7 @@ EOF
|
||||
.end main
|
||||
EOF
|
||||
LIBC=""
|
||||
${CC-cc} $dummy.s -o $dummy 2>/dev/null
|
||||
$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
|
||||
if test "$?" = 0 ; then
|
||||
./$dummy
|
||||
case "$?" in
|
||||
@@ -607,22 +740,23 @@ EOF
|
||||
16)
|
||||
UNAME_MACHINE="alphaev6"
|
||||
;;
|
||||
esac
|
||||
esac
|
||||
|
||||
objdump --private-headers $dummy | \
|
||||
grep ld.so.1 > /dev/null
|
||||
if test "$?" = 0 ; then
|
||||
LIBC="libc1"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
rm -f $dummy.s $dummy
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
|
||||
elif test "${UNAME_MACHINE}" = "mips" ; then
|
||||
cat >$dummy.c <<EOF
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
#ifdef __cplusplus
|
||||
int main (int argc, char *argv[]) {
|
||||
#else
|
||||
int main (argc, argv) int argc; char *argv[]; {
|
||||
#endif
|
||||
#ifdef __MIPSEB__
|
||||
printf ("%s-unknown-linux-gnu\n", argv[1]);
|
||||
#endif
|
||||
@@ -632,7 +766,7 @@ main(argc, argv)
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
${CC-cc} $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
else
|
||||
# Either a pre-BFD a.out linker (linux-gnuoldld)
|
||||
@@ -654,10 +788,11 @@ EOF
|
||||
# Determine whether the default compiler is a.out or elf
|
||||
cat >$dummy.c <<EOF
|
||||
#include <features.h>
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
#ifdef __cplusplus
|
||||
int main (int argc, char *argv[]) {
|
||||
#else
|
||||
int main (argc, argv) int argc; char *argv[]; {
|
||||
#endif
|
||||
#ifdef __ELF__
|
||||
# ifdef __GLIBC__
|
||||
# if __GLIBC__ >= 2
|
||||
@@ -674,7 +809,7 @@ main(argc, argv)
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
${CC-cc} $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
fi ;;
|
||||
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
|
||||
@@ -691,10 +826,20 @@ EOF
|
||||
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
|
||||
exit 0 ;;
|
||||
i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
|
||||
UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
|
||||
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
|
||||
echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
|
||||
echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
|
||||
else
|
||||
echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
|
||||
echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
|
||||
fi
|
||||
exit 0 ;;
|
||||
i?86:*:5:7*)
|
||||
# Fixed at (any) Pentium or better
|
||||
UNAME_MACHINE=i586
|
||||
if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then
|
||||
echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION}
|
||||
else
|
||||
echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
|
||||
fi
|
||||
exit 0 ;;
|
||||
i?86:*:3.2:*)
|
||||
@@ -706,18 +851,15 @@ EOF
|
||||
(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
|
||||
(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
|
||||
&& UNAME_MACHINE=i586
|
||||
(/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
|
||||
&& UNAME_MACHINE=i686
|
||||
(/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
|
||||
&& UNAME_MACHINE=i686
|
||||
echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
|
||||
else
|
||||
echo ${UNAME_MACHINE}-pc-sysv32
|
||||
fi
|
||||
exit 0 ;;
|
||||
i?86:UnixWare:*:*)
|
||||
if /bin/uname -X 2>/dev/null >/dev/null ; then
|
||||
(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
|
||||
&& UNAME_MACHINE=i586
|
||||
fi
|
||||
echo ${UNAME_MACHINE}-unixware-${UNAME_RELEASE}-${UNAME_VERSION}
|
||||
exit 0 ;;
|
||||
pc:*:*:*)
|
||||
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
||||
# the processor, so we play safe by assuming i386.
|
||||
@@ -759,7 +901,7 @@ EOF
|
||||
mc68030:UNIX_System_V:4.*:*)
|
||||
echo m68k-atari-sysv4
|
||||
exit 0 ;;
|
||||
i?86:LynxOS:2.*:*)
|
||||
i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*)
|
||||
echo i386-unknown-lynxos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
TSUNAMI:LynxOS:2.*:*)
|
||||
@@ -771,6 +913,9 @@ EOF
|
||||
SM[BE]S:UNIX_SV:*:*)
|
||||
echo mips-dde-sysv${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
RM*:ReliantUNIX-*:*:*)
|
||||
echo mips-sni-sysv4
|
||||
exit 0 ;;
|
||||
RM*:SINIX-*:*:*)
|
||||
echo mips-sni-sysv4
|
||||
exit 0 ;;
|
||||
@@ -801,7 +946,7 @@ EOF
|
||||
news*:NEWS-OS:*:6*)
|
||||
echo mips-sony-newsos6
|
||||
exit 0 ;;
|
||||
R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R4000:UNIX_SV:*:*)
|
||||
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
|
||||
if [ -d /usr/nec ]; then
|
||||
echo mips-nec-sysv${UNAME_RELEASE}
|
||||
else
|
||||
@@ -829,6 +974,9 @@ EOF
|
||||
*:Rhapsody:*:*)
|
||||
echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:QNX:*:4*)
|
||||
echo i386-qnx-qnx${UNAME_VERSION}
|
||||
exit 0 ;;
|
||||
esac
|
||||
|
||||
#echo '(No uname command or uname output not recognized.)' 1>&2
|
||||
@@ -935,7 +1083,7 @@ main ()
|
||||
}
|
||||
EOF
|
||||
|
||||
${CC-cc} $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0
|
||||
$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0
|
||||
rm -f $dummy.c $dummy
|
||||
|
||||
# Apollos put the system type in the environment.
|
||||
|
||||
126
configure.in
126
configure.in
@@ -48,6 +48,50 @@ if test x"$rsync_cv_errno" = x"yes"; then
|
||||
AC_DEFINE(HAVE_ERRNO_DECL)
|
||||
fi
|
||||
|
||||
# The following test taken from the cvs sources
|
||||
# If we can't find connect, try looking in -lsocket, -lnsl, and -linet.
|
||||
# These need checks to be before checks for any other functions that
|
||||
# might be in the same libraries.
|
||||
# The Irix 5 libc.so has connect and gethostbyname, but Irix 5 also has
|
||||
# libsocket.so which has a bad implementation of gethostbyname (it
|
||||
# only looks in /etc/hosts), so we only look for -lsocket if we need
|
||||
# it.
|
||||
AC_CHECK_FUNCS(connect)
|
||||
if test x"$ac_cv_func_connect" = x"no"; then
|
||||
case "$LIBS" in
|
||||
*-lnsl*) ;;
|
||||
*) AC_CHECK_LIB(nsl_s, printf) ;;
|
||||
esac
|
||||
case "$LIBS" in
|
||||
*-lnsl*) ;;
|
||||
*) AC_CHECK_LIB(nsl, printf) ;;
|
||||
esac
|
||||
case "$LIBS" in
|
||||
*-lsocket*) ;;
|
||||
*) AC_CHECK_LIB(socket, connect) ;;
|
||||
esac
|
||||
case "$LIBS" in
|
||||
*-linet*) ;;
|
||||
*) AC_CHECK_LIB(inet, connect) ;;
|
||||
esac
|
||||
dnl We can't just call AC_CHECK_FUNCS(connect) here, because the value
|
||||
dnl has been cached.
|
||||
if test x"$ac_cv_lib_socket_connect" = x"yes" ||
|
||||
test x"$ac_cv_lib_inet_connect" = x"yes"; then
|
||||
# ac_cv_func_connect=yes
|
||||
# don't! it would cause AC_CHECK_FUNC to succeed next time configure is run
|
||||
AC_DEFINE(HAVE_CONNECT)
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# if we can't find strcasecmp, look in -lresolv (for Unixware at least)
|
||||
#
|
||||
AC_CHECK_FUNCS(strcasecmp)
|
||||
if test x"$ac_cv_func_strcasecmp" = x"no"; then
|
||||
AC_CHECK_LIB(resolv, strcasecmp)
|
||||
fi
|
||||
|
||||
AC_FUNC_MEMCMP
|
||||
AC_FUNC_UTIME_NULL
|
||||
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup strerror chown chmod mknod)
|
||||
@@ -55,9 +99,22 @@ AC_CHECK_FUNCS(fchmod fstat strchr readlink link utime utimes strftime)
|
||||
AC_CHECK_FUNCS(memmove lchown vsnprintf snprintf setsid glob strpbrk)
|
||||
AC_CHECK_FUNCS(strlcat strlcpy)
|
||||
|
||||
AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[
|
||||
AC_TRY_RUN([#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
main() {
|
||||
int fd[2];
|
||||
exit((socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != -1) ? 0 : 1);
|
||||
}],
|
||||
rsync_cv_HAVE_SOCKETPAIR=yes,rsync_cv_HAVE_SOCKETPAIR=no,rsync_cv_HAVE_SOCKETPAIR=cross)])
|
||||
if test x"$rsync_cv_HAVE_SOCKETPAIR" = x"yes"; then
|
||||
AC_DEFINE(HAVE_SOCKETPAIR)
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for working fnmatch],rsync_cv_HAVE_FNMATCH,[
|
||||
AC_TRY_RUN([#include <fnmatch.h>
|
||||
main() { exit(fnmatch("*.o", "x.o", FNM_PATHNAME) == 0? 0: 1); }],
|
||||
main() { exit((fnmatch("*.o", "x.o", FNM_PATHNAME) == 0 &&
|
||||
fnmatch("a/b/*", "a/b/c/d", FNM_PATHNAME) != 0) ? 0: 1); }],
|
||||
rsync_cv_HAVE_FNMATCH=yes,rsync_cv_HAVE_FNMATCH=no,rsync_cv_HAVE_FNMATCH=cross)])
|
||||
if test x"$rsync_cv_HAVE_FNMATCH" = x"yes"; then
|
||||
AC_DEFINE(HAVE_FNMATCH)
|
||||
@@ -134,6 +191,17 @@ if test x"$rsync_cv_HAVE_UTIMBUF" = x"yes"; then
|
||||
AC_DEFINE(HAVE_UTIMBUF)
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([if gettimeofday takes tz argument],rsync_cv_HAVE_GETTIMEOFDAY_TZ,[
|
||||
AC_TRY_RUN([
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
main() { struct timeval tv; exit(gettimeofday(&tv, NULL));}],
|
||||
rsync_cv_HAVE_GETTIMEOFDAY_TZ=yes,rsync_cv_HAVE_GETTIMEOFDAY_TZ=no,rsync_cv_HAVE_GETTIMEOFDAY_TZ=cross)])
|
||||
if test x"$rsync_cv_HAVE_GETTIMEOFDAY_TZ" = x"yes"; then
|
||||
AC_DEFINE(HAVE_GETTIMEOFDAY_TZ)
|
||||
fi
|
||||
|
||||
|
||||
AC_CACHE_CHECK([for broken inet_ntoa],rsync_cv_REPLACE_INET_NTOA,[
|
||||
AC_TRY_RUN([
|
||||
#include <stdio.h>
|
||||
@@ -142,53 +210,25 @@ AC_TRY_RUN([
|
||||
#include <arpa/inet.h>
|
||||
main() { struct in_addr ip; ip.s_addr = 0x12345678;
|
||||
if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
|
||||
strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(0); }
|
||||
exit(1);}],
|
||||
rsync_cv_REPLACE_INET_NTOA=yes,rsync_cv_REPLACE_INET_NTOA=no,rsync_cv_REPLACE_INET_NTOA=cross)])
|
||||
strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(1); }
|
||||
exit(0);}],
|
||||
rsync_cv_REPLACE_INET_NTOA=no,rsync_cv_REPLACE_INET_NTOA=yes,rsync_cv_REPLACE_INET_NTOA=cross)])
|
||||
if test x"$rsync_cv_REPLACE_INET_NTOA" = x"yes"; then
|
||||
AC_DEFINE(REPLACE_INET_NTOA)
|
||||
fi
|
||||
|
||||
# The following test taken from the cvs sources
|
||||
# If we can't find connect, try looking in -lsocket, -lnsl, and -linet.
|
||||
# The Irix 5 libc.so has connect and gethostbyname, but Irix 5 also has
|
||||
# libsocket.so which has a bad implementation of gethostbyname (it
|
||||
# only looks in /etc/hosts), so we only look for -lsocket if we need
|
||||
# it.
|
||||
AC_CHECK_FUNCS(connect)
|
||||
if test x"$ac_cv_func_connect" = x"no"; then
|
||||
case "$LIBS" in
|
||||
*-lnsl*) ;;
|
||||
*) AC_CHECK_LIB(nsl_s, printf) ;;
|
||||
esac
|
||||
case "$LIBS" in
|
||||
*-lnsl*) ;;
|
||||
*) AC_CHECK_LIB(nsl, printf) ;;
|
||||
esac
|
||||
case "$LIBS" in
|
||||
*-lsocket*) ;;
|
||||
*) AC_CHECK_LIB(socket, connect) ;;
|
||||
esac
|
||||
case "$LIBS" in
|
||||
*-linet*) ;;
|
||||
*) AC_CHECK_LIB(inet, connect) ;;
|
||||
esac
|
||||
dnl We can't just call AC_CHECK_FUNCS(connect) here, because the value
|
||||
dnl has been cached.
|
||||
if test x"$ac_cv_lib_socket_connect" = x"yes" ||
|
||||
test x"$ac_cv_lib_inet_connect" = x"yes"; then
|
||||
# ac_cv_func_connect=yes
|
||||
# don't! it would cause AC_CHECK_FUNC to succeed next time configure is run
|
||||
AC_DEFINE(HAVE_CONNECT)
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# if we can't find strcasecmp, look in -lresolv (for Unixware at least)
|
||||
#
|
||||
AC_CHECK_FUNCS(strcasecmp)
|
||||
if test x"$ac_cv_func_strcasecmp" = x"no"; then
|
||||
AC_CHECK_LIB(resolv, strcasecmp)
|
||||
AC_CACHE_CHECK([for broken inet_aton],rsync_cv_REPLACE_INET_ATON,[
|
||||
AC_TRY_RUN([
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
main() { struct in_addr ip;
|
||||
if (inet_aton("example", &ip) == 0) exit(0); exit(1);}],
|
||||
rsync_cv_REPLACE_INET_ATON=no,rsync_cv_REPLACE_INET_ATON=yes,rsync_cv_REPLACE_INET_ATON=cross)])
|
||||
if test x"$rsync_cv_REPLACE_INET_ATON" = x"yes"; then
|
||||
AC_DEFINE(REPLACE_INET_ATON)
|
||||
fi
|
||||
|
||||
#
|
||||
|
||||
76
exclude.c
76
exclude.c
@@ -27,50 +27,6 @@ extern int delete_mode;
|
||||
|
||||
static struct exclude_struct **exclude_list;
|
||||
|
||||
/*
|
||||
* Optimization for special case when all included files are explicitly
|
||||
* listed without wildcards in the "exclude" list followed by a "- *"
|
||||
* to exclude the rest.
|
||||
* Contributed by Dave Dykstra <dwd@bell-labs.com>
|
||||
*/
|
||||
static int only_included_files = 1;
|
||||
static struct exclude_struct *exclude_the_rest;
|
||||
|
||||
int send_included_file_names(int f,struct file_list *flist)
|
||||
{
|
||||
struct exclude_struct *ex, **ex_list;
|
||||
int n;
|
||||
char *p;
|
||||
|
||||
if (!only_included_files || (exclude_the_rest == NULL) || delete_mode)
|
||||
return 0;
|
||||
|
||||
if (verbose > 1) {
|
||||
rprintf(FINFO,"(using include-only optimization) ");
|
||||
}
|
||||
|
||||
/* set exclude_list to NULL temporarily so check_exclude */
|
||||
/* will always return true */
|
||||
ex_list = exclude_list;
|
||||
exclude_list = NULL;
|
||||
for (n=0; (ex = ex_list[n]) != NULL; n++) {
|
||||
if (ex == exclude_the_rest)
|
||||
break;
|
||||
p = ex->pattern;
|
||||
while (*p == '/') {
|
||||
/* skip the allowed beginning slashes */
|
||||
p++;
|
||||
}
|
||||
/* silently skip files that don't exist to
|
||||
be more like non-optimized case */
|
||||
if (access(p,0) == 0)
|
||||
send_file_name(f,flist,p,0,0);
|
||||
}
|
||||
exclude_list = ex_list;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* build an exclude structure given a exclude pattern */
|
||||
static struct exclude_struct *make_exclude(char *pattern, int include)
|
||||
{
|
||||
@@ -95,15 +51,18 @@ static struct exclude_struct *make_exclude(char *pattern, int include)
|
||||
if (!ret->pattern) out_of_memory("make_exclude");
|
||||
|
||||
if (strpbrk(pattern, "*[?")) {
|
||||
if (!ret->include && (*pattern == '*') && (*(pattern+1) == '\0')) {
|
||||
exclude_the_rest = ret;
|
||||
} else {
|
||||
only_included_files = 0;
|
||||
}
|
||||
ret->regular_exp = 1;
|
||||
ret->fnmatch_flags = strstr(pattern, "**") ? 0 : FNM_PATHNAME;
|
||||
} else if (!ret->include) {
|
||||
only_included_files = 0;
|
||||
ret->fnmatch_flags = FNM_PATHNAME;
|
||||
if (strstr(pattern, "**")) {
|
||||
static int tested;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (fnmatch("a/b/*", "a/b/c/d", FNM_PATHNAME)==0) {
|
||||
rprintf(FERROR,"WARNING: fnmatch FNM_PATHNAME is broken on your system\n");
|
||||
}
|
||||
}
|
||||
ret->fnmatch_flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(pattern) > 1 && pattern[strlen(pattern)-1] == '/') {
|
||||
@@ -145,15 +104,17 @@ static int check_one_exclude(char *name,struct exclude_struct *ex,
|
||||
}
|
||||
|
||||
if (ex->regular_exp) {
|
||||
if (fnmatch(pattern, name, ex->fnmatch_flags) == 0)
|
||||
if (fnmatch(pattern, name, ex->fnmatch_flags) == 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)] == '/')))
|
||||
(l1==l2 || (!match_start && name[l1-(l2+1)] == '/'))) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -199,8 +160,6 @@ void add_exclude_list(char *pattern,struct exclude_struct ***list, int include)
|
||||
}
|
||||
free((*list));
|
||||
*list = NULL;
|
||||
only_included_files = 1;
|
||||
exclude_the_rest = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -270,8 +229,11 @@ void send_exclude_list(int f)
|
||||
}
|
||||
|
||||
for (i=0;exclude_list[i];i++) {
|
||||
char *pattern = exclude_list[i]->pattern;
|
||||
int l;
|
||||
char pattern[MAXPATHLEN];
|
||||
|
||||
strlcpy(pattern,exclude_list[i]->pattern,sizeof(pattern));
|
||||
if (exclude_list[i]->directory) strlcat(pattern,"/", sizeof(pattern));
|
||||
|
||||
l = strlen(pattern);
|
||||
if (l == 0) continue;
|
||||
|
||||
178
flist.c
178
flist.c
@@ -23,8 +23,6 @@
|
||||
|
||||
extern struct stats stats;
|
||||
|
||||
extern int csum_length;
|
||||
|
||||
extern int verbose;
|
||||
extern int am_server;
|
||||
extern int always_checksum;
|
||||
@@ -47,13 +45,66 @@ extern int copy_links;
|
||||
extern int copy_unsafe_links;
|
||||
extern int remote_version;
|
||||
extern int io_error;
|
||||
extern int sanitize_paths;
|
||||
|
||||
static char topsrcname[MAXPATHLEN];
|
||||
|
||||
static struct exclude_struct **local_exclude_list;
|
||||
|
||||
static struct file_struct null_file;
|
||||
|
||||
static void clean_flist(struct file_list *flist, int strip_root);
|
||||
|
||||
struct string_area *string_area_new(int size)
|
||||
{
|
||||
struct string_area *a;
|
||||
|
||||
if (size <= 0) size = ARENA_SIZE;
|
||||
a = malloc(sizeof(*a));
|
||||
if (!a) out_of_memory("string_area_new");
|
||||
a->current = a->base = malloc(size);
|
||||
if (!a->current) out_of_memory("string_area_new buffer");
|
||||
a->end = a->base + size;
|
||||
a->next = 0;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void string_area_free(struct string_area *a)
|
||||
{
|
||||
struct string_area *next;
|
||||
|
||||
for ( ; a ; a = next) {
|
||||
next = a->next;
|
||||
free(a->base);
|
||||
}
|
||||
}
|
||||
|
||||
char *string_area_malloc(struct string_area **ap, int size)
|
||||
{
|
||||
char *p;
|
||||
struct string_area *a;
|
||||
|
||||
/* does the request fit into the current space? */
|
||||
a = *ap;
|
||||
if (a->current + size >= a->end) {
|
||||
/* no; get space, move new string_area to front of the list */
|
||||
a = string_area_new(size > ARENA_SIZE ? size : ARENA_SIZE);
|
||||
a->next = *ap;
|
||||
*ap = a;
|
||||
}
|
||||
|
||||
/* have space; do the "allocation." */
|
||||
p = a->current;
|
||||
a->current += size;
|
||||
return p;
|
||||
}
|
||||
|
||||
char *string_area_strdup(struct string_area **ap, const char *src)
|
||||
{
|
||||
char* dest = string_area_malloc(ap, strlen(src) + 1);
|
||||
return strcpy(dest, src);
|
||||
}
|
||||
|
||||
static void list_file_entry(struct file_struct *f)
|
||||
{
|
||||
@@ -254,7 +305,11 @@ static void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
|
||||
#endif
|
||||
|
||||
if (always_checksum) {
|
||||
write_buf(f,file->sum,csum_length);
|
||||
if (remote_version < 21) {
|
||||
write_buf(f,file->sum,2);
|
||||
} else {
|
||||
write_buf(f,file->sum,MD4_SUM_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
last_mode = file->mode;
|
||||
@@ -296,7 +351,11 @@ static void receive_file_entry(struct file_struct **fptr,
|
||||
memset((char *)file, 0, sizeof(*file));
|
||||
(*fptr) = file;
|
||||
|
||||
if (l2 >= MAXPATHLEN-l1) overflow("receive_file_entry");
|
||||
if (l2 >= MAXPATHLEN-l1) {
|
||||
rprintf(FERROR,"overflow: flags=0x%x l1=%d l2=%d lastname=%s\n",
|
||||
flags, l1, l2, lastname);
|
||||
overflow("receive_file_entry");
|
||||
}
|
||||
|
||||
strlcpy(thisname,lastname,l1+1);
|
||||
read_sbuf(f,&thisname[l1],l2);
|
||||
@@ -307,6 +366,10 @@ static void receive_file_entry(struct file_struct **fptr,
|
||||
|
||||
clean_fname(thisname);
|
||||
|
||||
if (sanitize_paths) {
|
||||
sanitize_path(thisname, NULL);
|
||||
}
|
||||
|
||||
if ((p = strrchr(thisname,'/'))) {
|
||||
static char *lastdir;
|
||||
*p = 0;
|
||||
@@ -341,6 +404,9 @@ static void receive_file_entry(struct file_struct **fptr,
|
||||
file->link = (char *)malloc(l+1);
|
||||
if (!file->link) out_of_memory("receive_file_entry 2");
|
||||
read_sbuf(f,file->link,l);
|
||||
if (sanitize_paths) {
|
||||
sanitize_path(file->link, file->dirname);
|
||||
}
|
||||
}
|
||||
|
||||
#if SUPPORT_HARD_LINKS
|
||||
@@ -353,7 +419,11 @@ static void receive_file_entry(struct file_struct **fptr,
|
||||
if (always_checksum) {
|
||||
file->sum = (char *)malloc(MD4_SUM_LENGTH);
|
||||
if (!file->sum) out_of_memory("md4 sum");
|
||||
read_buf(f,file->sum,csum_length);
|
||||
if (remote_version < 21) {
|
||||
read_buf(f,file->sum,2);
|
||||
} else {
|
||||
read_buf(f,file->sum,MD4_SUM_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
last_mode = file->mode;
|
||||
@@ -395,7 +465,11 @@ static int skip_filesystem(char *fname, STRUCT_STAT *st)
|
||||
return (st2.st_dev != filesystem_dev);
|
||||
}
|
||||
|
||||
static struct file_struct *make_file(int f, char *fname)
|
||||
#define STRDUP(ap, p) (ap ? string_area_strdup(ap, p) : strdup(p))
|
||||
#define MALLOC(ap, i) (ap ? string_area_malloc(ap, i) : malloc(i))
|
||||
|
||||
/* create a file_struct for a named file */
|
||||
struct file_struct *make_file(int f, char *fname, struct string_area **ap)
|
||||
{
|
||||
struct file_struct *file;
|
||||
STRUCT_STAT st;
|
||||
@@ -408,13 +482,16 @@ static struct file_struct *make_file(int f, char *fname)
|
||||
strlcpy(cleaned_name, fname, MAXPATHLEN);
|
||||
cleaned_name[MAXPATHLEN-1] = 0;
|
||||
clean_fname(cleaned_name);
|
||||
if (sanitize_paths) {
|
||||
sanitize_path(cleaned_name, NULL);
|
||||
}
|
||||
fname = cleaned_name;
|
||||
|
||||
memset(sum,0,SUM_LENGTH);
|
||||
|
||||
if (readlink_stat(fname,&st,linkbuf) != 0) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"%s: %s\n",
|
||||
rprintf(FERROR,"readlink %s: %s\n",
|
||||
fname,strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
@@ -446,14 +523,14 @@ static struct file_struct *make_file(int f, char *fname)
|
||||
if (lastdir && strcmp(fname, lastdir)==0) {
|
||||
file->dirname = lastdir;
|
||||
} else {
|
||||
file->dirname = strdup(fname);
|
||||
file->dirname = STRDUP(ap, fname);
|
||||
lastdir = file->dirname;
|
||||
}
|
||||
file->basename = strdup(p+1);
|
||||
file->basename = STRDUP(ap, p+1);
|
||||
*p = '/';
|
||||
} else {
|
||||
file->dirname = NULL;
|
||||
file->basename = strdup(fname);
|
||||
file->basename = STRDUP(ap, fname);
|
||||
}
|
||||
|
||||
file->modtime = st.st_mtime;
|
||||
@@ -469,12 +546,12 @@ static struct file_struct *make_file(int f, char *fname)
|
||||
|
||||
#if SUPPORT_LINKS
|
||||
if (S_ISLNK(st.st_mode)) {
|
||||
file->link = strdup(linkbuf);
|
||||
file->link = STRDUP(ap, linkbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (always_checksum) {
|
||||
file->sum = (char *)malloc(MD4_SUM_LENGTH);
|
||||
file->sum = (char *)MALLOC(ap, MD4_SUM_LENGTH);
|
||||
if (!file->sum) out_of_memory("md4 sum");
|
||||
/* drat. we have to provide a null checksum for non-regular
|
||||
files in order to be compatible with earlier versions
|
||||
@@ -491,7 +568,7 @@ static struct file_struct *make_file(int f, char *fname)
|
||||
if (lastdir && strcmp(lastdir, flist_dir)==0) {
|
||||
file->basedir = lastdir;
|
||||
} else {
|
||||
file->basedir = strdup(flist_dir);
|
||||
file->basedir = STRDUP(ap, flist_dir);
|
||||
lastdir = file->basedir;
|
||||
}
|
||||
} else {
|
||||
@@ -511,7 +588,7 @@ void send_file_name(int f,struct file_list *flist,char *fname,
|
||||
{
|
||||
struct file_struct *file;
|
||||
|
||||
file = make_file(f,fname);
|
||||
file = make_file(f,fname, &flist->string_area);
|
||||
|
||||
if (!file) return;
|
||||
|
||||
@@ -601,7 +678,6 @@ static void send_directory(int f,struct file_list *flist,char *dir)
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
{
|
||||
int i,l;
|
||||
@@ -618,14 +694,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
|
||||
start_write = stats.total_written;
|
||||
|
||||
flist = (struct file_list *)malloc(sizeof(flist[0]));
|
||||
if (!flist) out_of_memory("send_file_list");
|
||||
|
||||
flist->count=0;
|
||||
flist->malloced = 1000;
|
||||
flist->files = (struct file_struct **)malloc(sizeof(flist->files[0])*
|
||||
flist->malloced);
|
||||
if (!flist->files) out_of_memory("send_file_list");
|
||||
flist = flist_new();
|
||||
|
||||
if (f != -1) {
|
||||
io_start_buffering(f);
|
||||
@@ -651,8 +720,10 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
}
|
||||
|
||||
if (link_stat(fname,&st) != 0) {
|
||||
io_error=1;
|
||||
rprintf(FERROR,"%s : %s\n",fname,strerror(errno));
|
||||
if (f != -1) {
|
||||
io_error=1;
|
||||
rprintf(FERROR,"link_stat %s : %s\n",fname,strerror(errno));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -720,8 +791,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
if (one_file_system)
|
||||
set_filesystem(fname);
|
||||
|
||||
if (!recurse || !send_included_file_names(f,flist))
|
||||
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
|
||||
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
|
||||
|
||||
if (olddir != NULL) {
|
||||
flist_dir = NULL;
|
||||
@@ -752,7 +822,8 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
|
||||
/* if protocol version is >= 17 then send the io_error flag */
|
||||
if (f != -1 && remote_version >= 17) {
|
||||
write_int(f, io_error);
|
||||
extern int module_id;
|
||||
write_int(f, lp_ignore_errors(module_id)? 0 : io_error);
|
||||
}
|
||||
|
||||
if (f != -1) {
|
||||
@@ -837,7 +908,13 @@ struct file_list *recv_file_list(int f)
|
||||
|
||||
/* if protocol version is >= 17 then recv the io_error flag */
|
||||
if (f != -1 && remote_version >= 17) {
|
||||
io_error |= read_int(f);
|
||||
extern int module_id;
|
||||
extern int ignore_errors;
|
||||
if (lp_ignore_errors(module_id) || ignore_errors) {
|
||||
read_int(f);
|
||||
} else {
|
||||
io_error |= read_int(f);
|
||||
}
|
||||
}
|
||||
|
||||
if (list_only) {
|
||||
@@ -899,16 +976,38 @@ int flist_find(struct file_list *flist,struct file_struct *f)
|
||||
/*
|
||||
* free up one file
|
||||
*/
|
||||
static void free_file(struct file_struct *file)
|
||||
void free_file(struct file_struct *file)
|
||||
{
|
||||
if (!file) return;
|
||||
if (file->basename) free(file->basename);
|
||||
if (file->link) free(file->link);
|
||||
if (file->sum) free(file->sum);
|
||||
memset((char *)file, 0, sizeof(*file));
|
||||
*file = null_file;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* allocate a new file list
|
||||
*/
|
||||
struct file_list *flist_new()
|
||||
{
|
||||
struct file_list *flist;
|
||||
|
||||
flist = (struct file_list *)malloc(sizeof(flist[0]));
|
||||
if (!flist) out_of_memory("send_file_list");
|
||||
|
||||
flist->count=0;
|
||||
flist->malloced = 1000;
|
||||
flist->files = (struct file_struct **)malloc(sizeof(flist->files[0])*
|
||||
flist->malloced);
|
||||
if (!flist->files) out_of_memory("send_file_list");
|
||||
#if ARENA_SIZE > 0
|
||||
flist->string_area = string_area_new(0);
|
||||
#else
|
||||
flist->string_area = 0;
|
||||
#endif
|
||||
return flist;
|
||||
}
|
||||
/*
|
||||
* free up all elements in a flist
|
||||
*/
|
||||
@@ -916,11 +1015,14 @@ void flist_free(struct file_list *flist)
|
||||
{
|
||||
int i;
|
||||
for (i=1;i<flist->count;i++) {
|
||||
free_file(flist->files[i]);
|
||||
if (!flist->string_area)
|
||||
free_file(flist->files[i]);
|
||||
free(flist->files[i]);
|
||||
}
|
||||
memset((char *)flist->files, 0, sizeof(flist->files[0])*flist->count);
|
||||
free(flist->files);
|
||||
if (flist->string_area)
|
||||
string_area_free(flist->string_area);
|
||||
memset((char *)flist, 0, sizeof(*flist));
|
||||
free(flist);
|
||||
}
|
||||
@@ -949,7 +1051,13 @@ static void clean_flist(struct file_list *flist, int strip_root)
|
||||
if (verbose > 1 && !am_server)
|
||||
rprintf(FINFO,"removing duplicate name %s from file list %d\n",
|
||||
f_name(flist->files[i-1]),i-1);
|
||||
free_file(flist->files[i]);
|
||||
/* it's not great that the flist knows the semantics of the
|
||||
* file memory usage, but i'd rather not add a flag byte
|
||||
* to that struct. XXX can i use a bit in the flags field? */
|
||||
if (flist->string_area)
|
||||
flist->files[i][0] = null_file;
|
||||
else
|
||||
free_file(flist->files[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -976,12 +1084,12 @@ static void clean_flist(struct file_list *flist, int strip_root)
|
||||
if (verbose <= 3) return;
|
||||
|
||||
for (i=0;i<flist->count;i++) {
|
||||
rprintf(FINFO,"[%d] i=%d %s %s mode=0%o len=%d\n",
|
||||
rprintf(FINFO,"[%d] i=%d %s %s mode=0%o len=%.0f\n",
|
||||
getpid(), i,
|
||||
NS(flist->files[i]->dirname),
|
||||
NS(flist->files[i]->basename),
|
||||
flist->files[i]->mode,
|
||||
(int)flist->files[i]->length);
|
||||
(double)flist->files[i]->length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
66
generator.c
66
generator.c
@@ -50,7 +50,11 @@ static int skip_file(char *fname,
|
||||
if (always_checksum && S_ISREG(st->st_mode)) {
|
||||
char sum[MD4_SUM_LENGTH];
|
||||
file_checksum(fname,sum,st->st_size);
|
||||
return (memcmp(sum,file->sum,csum_length) == 0);
|
||||
if (remote_version < 21) {
|
||||
return (memcmp(sum,file->sum,2) == 0);
|
||||
} else {
|
||||
return (memcmp(sum,file->sum,MD4_SUM_LENGTH) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (size_only) {
|
||||
@@ -86,17 +90,19 @@ static int adapt_block_size(struct file_struct *file, int bsize)
|
||||
static void send_sums(struct sum_struct *s,int f_out)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* tell the other guy how many we are going to be doing and how many
|
||||
bytes there are in the last chunk */
|
||||
|
||||
/* tell the other guy how many we are going to be doing and how many
|
||||
bytes there are in the last chunk */
|
||||
write_int(f_out,s?s->count:0);
|
||||
write_int(f_out,s?s->n:block_size);
|
||||
write_int(f_out,s?s->remainder:0);
|
||||
if (s)
|
||||
for (i=0;i<s->count;i++) {
|
||||
write_int(f_out,s->sums[i].sum1);
|
||||
write_buf(f_out,s->sums[i].sum2,csum_length);
|
||||
}
|
||||
|
||||
if (!s) return;
|
||||
|
||||
for (i=0;i<s->count;i++) {
|
||||
write_int(f_out,s->sums[i].sum1);
|
||||
write_buf(f_out,s->sums[i].sum2,csum_length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -130,8 +136,8 @@ static struct sum_struct *generate_sums(struct map_struct *buf,OFF_T len,int n)
|
||||
}
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"count=%d rem=%d n=%d flength=%d\n",
|
||||
s->count,s->remainder,s->n,(int)s->flength);
|
||||
rprintf(FINFO,"count=%d rem=%d n=%d flength=%.0f\n",
|
||||
s->count,s->remainder,s->n,(double)s->flength);
|
||||
|
||||
s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
|
||||
if (!s->sums) out_of_memory("generate_sums");
|
||||
@@ -148,8 +154,8 @@ static struct sum_struct *generate_sums(struct map_struct *buf,OFF_T len,int n)
|
||||
s->sums[i].i = i;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"chunk[%d] offset=%d len=%d sum1=%08x\n",
|
||||
i,(int)s->sums[i].offset,s->sums[i].len,s->sums[i].sum1);
|
||||
rprintf(FINFO,"chunk[%d] offset=%.0f len=%d sum1=%08x\n",
|
||||
i,(double)s->sums[i].offset,s->sums[i].len,s->sums[i].sum1);
|
||||
|
||||
len -= n1;
|
||||
offset += n1;
|
||||
@@ -171,6 +177,8 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
char fnamecmpbuf[MAXPATHLEN];
|
||||
extern char *compare_dest;
|
||||
extern int list_only;
|
||||
extern int preserve_perms;
|
||||
extern int only_existing;
|
||||
|
||||
if (list_only) return;
|
||||
|
||||
@@ -179,6 +187,21 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
|
||||
statret = link_stat(fname,&st);
|
||||
|
||||
if (only_existing && statret == -1 && errno == ENOENT) {
|
||||
/* we only want to update existing files */
|
||||
if (verbose > 1) rprintf(FINFO,"not creating %s\n",fname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (statret == 0 &&
|
||||
!preserve_perms &&
|
||||
(S_ISDIR(st.st_mode) == S_ISDIR(file->mode))) {
|
||||
/* if the file exists already and we aren't perserving
|
||||
presmissions then act as though the remote end sent
|
||||
us the file permissions we already have */
|
||||
file->mode = (file->mode & _S_IFMT) | (st.st_mode & ~_S_IFMT);
|
||||
}
|
||||
|
||||
if (S_ISDIR(file->mode)) {
|
||||
if (dry_run) return;
|
||||
if (statret == 0 && !S_ISDIR(st.st_mode)) {
|
||||
@@ -223,10 +246,10 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
return;
|
||||
}
|
||||
}
|
||||
delete_file(fname);
|
||||
}
|
||||
delete_file(fname);
|
||||
if (do_symlink(file->link,fname) != 0) {
|
||||
rprintf(FERROR,"link %s -> %s : %s\n",
|
||||
rprintf(FERROR,"symlink %s -> %s : %s\n",
|
||||
fname,file->link,strerror(errno));
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
@@ -317,7 +340,8 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
}
|
||||
|
||||
if (skip_file(fname, file, &st)) {
|
||||
set_perms(fname,file,&st,1);
|
||||
if (fnamecmp == fname)
|
||||
set_perms(fname,file,&st,1);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -333,11 +357,13 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
}
|
||||
|
||||
/* open the file */
|
||||
fd = open(fnamecmp,O_RDONLY);
|
||||
fd = do_open(fnamecmp, O_RDONLY, 0);
|
||||
|
||||
if (fd == -1) {
|
||||
rprintf(FERROR,"failed to open %s : %s\n",fnamecmp,strerror(errno));
|
||||
rprintf(FERROR,"skipping %s\n",fname);
|
||||
rprintf(FERROR,"failed to open %s, continuing : %s\n",fnamecmp,strerror(errno));
|
||||
/* pretend the file didn't exist */
|
||||
write_int(f_out,i);
|
||||
send_sums(NULL,f_out);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -348,7 +374,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
}
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"gen mapped %s of size %d\n",fnamecmp,(int)st.st_size);
|
||||
rprintf(FINFO,"gen mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
|
||||
|
||||
s = generate_sums(buf,st.st_size,adapt_block_size(file, block_size));
|
||||
|
||||
|
||||
259
io.c
259
io.c
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
Utilities used in rsync
|
||||
socket and pipe IO utilities used in rsync
|
||||
|
||||
tridge, June 1996
|
||||
*/
|
||||
@@ -27,6 +27,8 @@
|
||||
/* if no timeout is specified then use a 60 second select timeout */
|
||||
#define SELECT_TIMEOUT 60
|
||||
|
||||
extern int bwlimit;
|
||||
|
||||
static int io_multiplexing_out;
|
||||
static int io_multiplexing_in;
|
||||
static int multiplex_in_fd;
|
||||
@@ -38,6 +40,9 @@ extern int io_timeout;
|
||||
extern struct stats stats;
|
||||
|
||||
static int buffer_f_in = -1;
|
||||
static int io_error_fd = -1;
|
||||
|
||||
static void read_loop(int fd, char *buf, int len);
|
||||
|
||||
void setup_readbuffer(int f_in)
|
||||
{
|
||||
@@ -46,6 +51,7 @@ void setup_readbuffer(int f_in)
|
||||
|
||||
static void check_timeout(void)
|
||||
{
|
||||
extern int am_server, am_daemon;
|
||||
time_t t;
|
||||
|
||||
if (!io_timeout) return;
|
||||
@@ -58,19 +64,50 @@ static void check_timeout(void)
|
||||
t = time(NULL);
|
||||
|
||||
if (last_io && io_timeout && (t-last_io) >= io_timeout) {
|
||||
rprintf(FERROR,"io timeout after %d second - exiting\n",
|
||||
(int)(t-last_io));
|
||||
if (!am_server && !am_daemon) {
|
||||
rprintf(FERROR,"io timeout after %d second - exiting\n",
|
||||
(int)(t-last_io));
|
||||
}
|
||||
exit_cleanup(RERR_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
/* setup the fd used to propogate errors */
|
||||
void io_set_error_fd(int fd)
|
||||
{
|
||||
io_error_fd = fd;
|
||||
}
|
||||
|
||||
/* read some data from the error fd and write it to the write log code */
|
||||
static void read_error_fd(void)
|
||||
{
|
||||
char buf[200];
|
||||
int n;
|
||||
int fd = io_error_fd;
|
||||
int tag, len;
|
||||
|
||||
io_error_fd = -1;
|
||||
|
||||
read_loop(fd, buf, 4);
|
||||
tag = IVAL(buf, 0);
|
||||
|
||||
len = tag & 0xFFFFFF;
|
||||
tag = tag >> 24;
|
||||
tag -= MPLEX_BASE;
|
||||
|
||||
while (len) {
|
||||
n = len;
|
||||
if (n > (sizeof(buf)-1)) n = sizeof(buf)-1;
|
||||
read_loop(fd, buf, n);
|
||||
rwrite((enum logcode)tag, buf, n);
|
||||
len -= n;
|
||||
}
|
||||
|
||||
io_error_fd = fd;
|
||||
}
|
||||
|
||||
|
||||
static char *read_buffer;
|
||||
static char *read_buffer_p;
|
||||
static int read_buffer_len;
|
||||
static int read_buffer_size;
|
||||
static int no_flush;
|
||||
static int no_flush_read;
|
||||
|
||||
/* read from a socket with IO timeout. return the number of
|
||||
bytes read. If no bytes can be read then exit, never return
|
||||
@@ -79,24 +116,39 @@ static int read_timeout(int fd, char *buf, int len)
|
||||
{
|
||||
int n, ret=0;
|
||||
|
||||
no_flush_read++;
|
||||
io_flush();
|
||||
no_flush_read--;
|
||||
|
||||
while (ret == 0) {
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
int fd_count = fd+1;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
if (io_error_fd != -1) {
|
||||
FD_SET(io_error_fd, &fds);
|
||||
if (io_error_fd > fd) fd_count = io_error_fd+1;
|
||||
}
|
||||
|
||||
tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (select(fd+1, &fds, NULL, NULL, &tv) != 1) {
|
||||
errno = 0;
|
||||
|
||||
if (select(fd_count, &fds, NULL, NULL, &tv) < 1) {
|
||||
if (errno == EBADF) {
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
check_timeout();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (io_error_fd != -1 && FD_ISSET(io_error_fd, &fds)) {
|
||||
read_error_fd();
|
||||
}
|
||||
|
||||
if (!FD_ISSET(fd, &fds)) continue;
|
||||
|
||||
n = read(fd, buf, len);
|
||||
|
||||
if (n > 0) {
|
||||
@@ -113,14 +165,11 @@ static int read_timeout(int fd, char *buf, int len)
|
||||
}
|
||||
|
||||
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);
|
||||
(errno == EWOULDBLOCK || errno == EAGAIN)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (n == 0) {
|
||||
if (eof_error) {
|
||||
rprintf(FERROR,"unexpected EOF in read_timeout\n");
|
||||
@@ -128,6 +177,9 @@ static int read_timeout(int fd, char *buf, int len)
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
|
||||
/* this prevents us trying to write errors on a dead socket */
|
||||
io_multiplexing_close();
|
||||
|
||||
rprintf(FERROR,"read error: %s\n", strerror(errno));
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
@@ -153,7 +205,6 @@ static void read_loop(int fd, char *buf, int len)
|
||||
static int read_unbuffered(int fd, char *buf, int len)
|
||||
{
|
||||
static int remaining;
|
||||
char ibuf[4];
|
||||
int tag, ret=0;
|
||||
char line[1024];
|
||||
|
||||
@@ -169,8 +220,8 @@ static int read_unbuffered(int fd, char *buf, int len)
|
||||
continue;
|
||||
}
|
||||
|
||||
read_loop(fd, ibuf, 4);
|
||||
tag = IVAL(ibuf, 0);
|
||||
read_loop(fd, line, 4);
|
||||
tag = IVAL(line, 0);
|
||||
|
||||
remaining = tag & 0xFFFFFF;
|
||||
tag = tag >> 24;
|
||||
@@ -193,7 +244,7 @@ static int read_unbuffered(int fd, char *buf, int len)
|
||||
read_loop(fd, line, remaining);
|
||||
line[remaining] = 0;
|
||||
|
||||
rprintf(tag,"%s", line);
|
||||
rprintf((enum logcode)tag,"%s", line);
|
||||
remaining = 0;
|
||||
}
|
||||
|
||||
@@ -201,40 +252,6 @@ 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 = 8192;
|
||||
|
||||
if (f == -1) return;
|
||||
|
||||
if (read_buffer_len == 0) {
|
||||
read_buffer_p = read_buffer;
|
||||
}
|
||||
|
||||
if (n > MAX_READ_BUFFER/4)
|
||||
n = MAX_READ_BUFFER/4;
|
||||
|
||||
if (read_buffer_p != read_buffer) {
|
||||
memmove(read_buffer,read_buffer_p,read_buffer_len);
|
||||
read_buffer_p = read_buffer;
|
||||
}
|
||||
|
||||
if (n > (read_buffer_size - read_buffer_len)) {
|
||||
read_buffer_size += n;
|
||||
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);
|
||||
read_buffer_len += 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)
|
||||
@@ -242,23 +259,8 @@ static void readfd(int fd,char *buffer,int N)
|
||||
int ret;
|
||||
int total=0;
|
||||
|
||||
if ((read_buffer_len < N) && (N < 1024)) {
|
||||
read_check(buffer_f_in);
|
||||
}
|
||||
|
||||
while (total < N) {
|
||||
if (read_buffer_len > 0 && buffer_f_in == fd) {
|
||||
ret = MIN(read_buffer_len,N-total);
|
||||
memcpy(buffer+total,read_buffer_p,ret);
|
||||
read_buffer_p += ret;
|
||||
read_buffer_len -= ret;
|
||||
total += ret;
|
||||
continue;
|
||||
}
|
||||
|
||||
no_flush_read++;
|
||||
io_flush();
|
||||
no_flush_read--;
|
||||
|
||||
ret = read_unbuffered(fd,buffer + total,N-total);
|
||||
total += ret;
|
||||
@@ -332,8 +334,6 @@ static void writefd_unbuffered(int fd,char *buf,int len)
|
||||
fd_set w_fds, r_fds;
|
||||
int fd_count, count;
|
||||
struct timeval tv;
|
||||
int reading=0;
|
||||
int blocked=0;
|
||||
|
||||
no_flush++;
|
||||
|
||||
@@ -341,46 +341,47 @@ static void writefd_unbuffered(int fd,char *buf,int len)
|
||||
FD_ZERO(&w_fds);
|
||||
FD_ZERO(&r_fds);
|
||||
FD_SET(fd,&w_fds);
|
||||
fd_count = fd+1;
|
||||
fd_count = fd;
|
||||
|
||||
if (!no_flush_read) {
|
||||
reading = (buffer_f_in != -1);
|
||||
}
|
||||
|
||||
if (reading) {
|
||||
FD_SET(buffer_f_in,&r_fds);
|
||||
if (buffer_f_in > fd)
|
||||
fd_count = buffer_f_in+1;
|
||||
if (io_error_fd != -1) {
|
||||
FD_SET(io_error_fd,&r_fds);
|
||||
if (io_error_fd > fd_count)
|
||||
fd_count = io_error_fd;
|
||||
}
|
||||
|
||||
tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
count = select(fd_count,
|
||||
reading?&r_fds:NULL,
|
||||
errno = 0;
|
||||
|
||||
count = select(fd_count+1,
|
||||
io_error_fd != -1?&r_fds:NULL,
|
||||
&w_fds,NULL,
|
||||
&tv);
|
||||
|
||||
if (count <= 0) {
|
||||
if (errno == EBADF) {
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
check_timeout();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (reading && FD_ISSET(buffer_f_in, &r_fds)) {
|
||||
read_check(buffer_f_in);
|
||||
if (io_error_fd != -1 && FD_ISSET(io_error_fd, &r_fds)) {
|
||||
read_error_fd();
|
||||
}
|
||||
|
||||
if (FD_ISSET(fd, &w_fds)) {
|
||||
int n = (len-total)>>blocked;
|
||||
int ret = write(fd,buf+total,n?n:1);
|
||||
int ret, n = len-total;
|
||||
|
||||
ret = write(fd,buf+total,n);
|
||||
|
||||
if (ret == -1 && errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret == -1 &&
|
||||
(errno == EAGAIN || errno == EWOULDBLOCK)) {
|
||||
blocked++;
|
||||
(errno == EWOULDBLOCK || errno == EAGAIN)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -389,7 +390,19 @@ static void writefd_unbuffered(int fd,char *buf,int len)
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
|
||||
blocked = 0;
|
||||
/* Sleep after writing to limit I/O bandwidth */
|
||||
if (bwlimit)
|
||||
{
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = ret * 1000 / bwlimit;
|
||||
while (tv.tv_usec > 1000000)
|
||||
{
|
||||
tv.tv_sec++;
|
||||
tv.tv_usec -= 1000000;
|
||||
}
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
}
|
||||
|
||||
total += ret;
|
||||
|
||||
if (io_timeout)
|
||||
@@ -408,22 +421,43 @@ void io_start_buffering(int fd)
|
||||
{
|
||||
if (io_buffer) return;
|
||||
multiplex_out_fd = fd;
|
||||
io_buffer = (char *)malloc(IO_BUFFER_SIZE+4);
|
||||
io_buffer = (char *)malloc(IO_BUFFER_SIZE);
|
||||
if (!io_buffer) out_of_memory("writefd");
|
||||
io_buffer_count = 0;
|
||||
|
||||
/* leave room for the multiplex header in case it's needed */
|
||||
io_buffer += 4;
|
||||
}
|
||||
|
||||
/* write an message to a multiplexed stream. If this fails then rsync
|
||||
exits */
|
||||
static void mplex_write(int fd, enum logcode code, char *buf, int len)
|
||||
{
|
||||
char buffer[4096];
|
||||
int n = len;
|
||||
|
||||
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
|
||||
|
||||
if (n > (sizeof(buffer)-4)) {
|
||||
n = sizeof(buffer)-4;
|
||||
}
|
||||
|
||||
memcpy(&buffer[4], buf, n);
|
||||
writefd_unbuffered(fd, buffer, n+4);
|
||||
|
||||
len -= n;
|
||||
buf += n;
|
||||
|
||||
if (len) {
|
||||
writefd_unbuffered(fd, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void io_flush(void)
|
||||
{
|
||||
int fd = multiplex_out_fd;
|
||||
if (!io_buffer_count || no_flush) return;
|
||||
|
||||
if (io_multiplexing_out) {
|
||||
SIVAL(io_buffer-4, 0, (MPLEX_BASE<<24) + io_buffer_count);
|
||||
writefd_unbuffered(fd, io_buffer-4, io_buffer_count+4);
|
||||
mplex_write(fd, FNONE, io_buffer, io_buffer_count);
|
||||
} else {
|
||||
writefd_unbuffered(fd, io_buffer, io_buffer_count);
|
||||
}
|
||||
@@ -434,7 +468,7 @@ void io_end_buffering(int fd)
|
||||
{
|
||||
io_flush();
|
||||
if (!io_multiplexing_out) {
|
||||
free(io_buffer-4);
|
||||
free(io_buffer);
|
||||
io_buffer = NULL;
|
||||
}
|
||||
}
|
||||
@@ -443,7 +477,7 @@ static void writefd(int fd,char *buf,int len)
|
||||
{
|
||||
stats.total_written += len;
|
||||
|
||||
if (!io_buffer) {
|
||||
if (!io_buffer || fd != multiplex_out_fd) {
|
||||
writefd_unbuffered(fd, buf, len);
|
||||
return;
|
||||
}
|
||||
@@ -561,31 +595,36 @@ void io_start_multiplex_in(int fd)
|
||||
{
|
||||
multiplex_in_fd = fd;
|
||||
io_flush();
|
||||
if (read_buffer_len) {
|
||||
fprintf(stderr,"ERROR: data in read buffer at mplx start\n");
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
|
||||
io_multiplexing_in = 1;
|
||||
}
|
||||
|
||||
/* write an message to the error stream */
|
||||
int io_multiplex_write(int f, char *buf, int len)
|
||||
/* write an message to the multiplexed error stream */
|
||||
int io_multiplex_write(enum logcode code, char *buf, int len)
|
||||
{
|
||||
if (!io_multiplexing_out) return 0;
|
||||
|
||||
io_flush();
|
||||
|
||||
SIVAL(io_buffer-4, 0, ((MPLEX_BASE + f)<<24) + len);
|
||||
memcpy(io_buffer, buf, len);
|
||||
|
||||
stats.total_written += (len+4);
|
||||
|
||||
writefd_unbuffered(multiplex_out_fd, io_buffer-4, len+4);
|
||||
mplex_write(multiplex_out_fd, code, buf, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* write a message to the special error fd */
|
||||
int io_error_write(int f, enum logcode code, char *buf, int len)
|
||||
{
|
||||
if (f == -1) return 0;
|
||||
mplex_write(f, code, buf, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* stop output multiplexing */
|
||||
void io_multiplexing_close(void)
|
||||
{
|
||||
io_multiplexing_out = 0;
|
||||
}
|
||||
|
||||
void io_close_input(int fd)
|
||||
{
|
||||
buffer_f_in = -1;
|
||||
}
|
||||
|
||||
|
||||
68
lib/compat.c
68
lib/compat.c
@@ -95,21 +95,6 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef REPLACE_INET_NTOA
|
||||
char *rep_inet_ntoa(struct in_addr ip)
|
||||
{
|
||||
unsigned char *p = (unsigned char *)&ip.s_addr;
|
||||
static char buf[18];
|
||||
#if WORDS_BIGENDIAN
|
||||
slprintf(buf, 18, "%d.%d.%d.%d",
|
||||
(int)p[0], (int)p[1], (int)p[2], (int)p[3]);
|
||||
#else
|
||||
slprintf(buf, 18, "%d.%d.%d.%d",
|
||||
(int)p[3], (int)p[2], (int)p[1], (int)p[0]);
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
/* like strncpy but does not 0 fill the buffer and always null
|
||||
@@ -145,3 +130,56 @@
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef REPLACE_INET_NTOA
|
||||
char *rep_inet_ntoa(struct in_addr ip)
|
||||
{
|
||||
unsigned char *p = (unsigned char *)&ip.s_addr;
|
||||
static char buf[18];
|
||||
#if WORDS_BIGENDIAN
|
||||
slprintf(buf, 18, "%d.%d.%d.%d",
|
||||
(int)p[0], (int)p[1], (int)p[2], (int)p[3]);
|
||||
#else
|
||||
slprintf(buf, 18, "%d.%d.%d.%d",
|
||||
(int)p[3], (int)p[2], (int)p[1], (int)p[0]);
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef REPLACE_INET_ATON
|
||||
int inet_aton(const char *cp, struct in_addr *inp)
|
||||
{
|
||||
unsigned int a1, a2, a3, a4;
|
||||
unsigned long ret;
|
||||
|
||||
if (strcmp(cp, "255.255.255.255") == 0) {
|
||||
inp->s_addr = (unsigned) -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sscanf(cp, "%u.%u.%u.%u", &a1, &a2, &a3, &a4) != 4 ||
|
||||
a1 > 255 || a2 > 255 || a3 > 255 || a4 > 255) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = (a1 << 24) | (a2 << 16) | (a3 << 8) | a4;
|
||||
|
||||
inp->s_addr = htonl(ret);
|
||||
|
||||
if (inp->s_addr == (unsigned) -1) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* some systems don't take the 2nd argument */
|
||||
int sys_gettimeofday(struct timeval *tv)
|
||||
{
|
||||
#if HAVE_GETTIMEOFDAY_TZ
|
||||
return gettimeofday(tv, NULL);
|
||||
#else
|
||||
return gettimeofday(tv);
|
||||
#endif
|
||||
}
|
||||
|
||||
434
lib/fnmatch.c
434
lib/fnmatch.c
@@ -1,33 +1,60 @@
|
||||
#include "../rsync.h"
|
||||
#ifndef HAVE_FNMATCH
|
||||
|
||||
/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
|
||||
/* ----- THE FOLLOWING UP TO 'END' is glibc-2.1.2 posix/fnmatch.c
|
||||
except for the parts with '#if 0' */
|
||||
|
||||
NOTE: The canonical source of this file is maintained with the GNU C Library.
|
||||
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
|
||||
/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
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, or (at your option) any
|
||||
later version.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library 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.
|
||||
This library 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
|
||||
Library 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if defined (STDC_HEADERS) || !defined (isascii)
|
||||
#define ISASCII(c) 1
|
||||
#else
|
||||
#define ISASCII(c) isascii(c)
|
||||
#if 0 /* header files included better by ../rsync.h */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#define ISUPPER(c) (ISASCII (c) && isupper (c))
|
||||
/* Enable GNU extensions in fnmatch.h. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if HAVE_STRING_H || defined _LIBC
|
||||
# include <string.h>
|
||||
#else
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#if defined STDC_HEADERS || defined _LIBC
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#endif /* 0 */
|
||||
/* For platform which support the ISO C amendement 1 functionality we
|
||||
support user defined character classes. */
|
||||
#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
|
||||
/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
|
||||
# include <wchar.h>
|
||||
# include <wctype.h>
|
||||
#endif
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
@@ -37,23 +64,95 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
|
||||
#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
|
||||
extern int errno;
|
||||
#if 1
|
||||
|
||||
# if defined STDC_HEADERS || !defined isascii
|
||||
# define ISASCII(c) 1
|
||||
# else
|
||||
# define ISASCII(c) isascii(c)
|
||||
# endif
|
||||
|
||||
#ifdef isblank
|
||||
# define ISBLANK(c) (ISASCII (c) && isblank (c))
|
||||
#else
|
||||
# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
|
||||
#endif
|
||||
#ifdef isgraph
|
||||
# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
|
||||
#else
|
||||
# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
|
||||
#endif
|
||||
|
||||
#define ISPRINT(c) (ISASCII (c) && isprint (c))
|
||||
#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
|
||||
#define ISALNUM(c) (ISASCII (c) && isalnum (c))
|
||||
#define ISALPHA(c) (ISASCII (c) && isalpha (c))
|
||||
#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
|
||||
#define ISLOWER(c) (ISASCII (c) && islower (c))
|
||||
#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
|
||||
#define ISSPACE(c) (ISASCII (c) && isspace (c))
|
||||
#define ISUPPER(c) (ISASCII (c) && isupper (c))
|
||||
#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
|
||||
|
||||
# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
|
||||
|
||||
# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
|
||||
/* The GNU C library provides support for user-defined character classes
|
||||
and the functions from ISO C amendement 1. */
|
||||
# ifdef CHARCLASS_NAME_MAX
|
||||
# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
|
||||
# else
|
||||
/* This shouldn't happen but some implementation might still have this
|
||||
problem. Use a reasonable default value. */
|
||||
# define CHAR_CLASS_MAX_LENGTH 256
|
||||
# endif
|
||||
|
||||
# ifdef _LIBC
|
||||
# define IS_CHAR_CLASS(string) __wctype (string)
|
||||
# else
|
||||
# define IS_CHAR_CLASS(string) wctype (string)
|
||||
# endif
|
||||
# else
|
||||
# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
|
||||
|
||||
# define IS_CHAR_CLASS(string) \
|
||||
(STREQ (string, "alpha") || STREQ (string, "upper") \
|
||||
|| STREQ (string, "lower") || STREQ (string, "digit") \
|
||||
|| STREQ (string, "alnum") || STREQ (string, "xdigit") \
|
||||
|| STREQ (string, "space") || STREQ (string, "print") \
|
||||
|| STREQ (string, "punct") || STREQ (string, "graph") \
|
||||
|| STREQ (string, "cntrl") || STREQ (string, "blank"))
|
||||
# endif
|
||||
|
||||
/* Avoid depending on library functions or files
|
||||
whose names are inconsistent. */
|
||||
|
||||
# if !defined _LIBC && !defined getenv
|
||||
extern char *getenv ();
|
||||
# endif
|
||||
|
||||
# ifndef errno
|
||||
extern int errno;
|
||||
# endif
|
||||
|
||||
/* Match STRING against the filename pattern PATTERN, returning zero if
|
||||
it matches, nonzero if not. */
|
||||
int
|
||||
fnmatch (pattern, string, flags)
|
||||
const char *pattern;
|
||||
const char *string;
|
||||
int flags;
|
||||
static int
|
||||
#ifdef _LIBC
|
||||
internal_function
|
||||
#endif
|
||||
internal_fnmatch (const char *pattern, const char *string,
|
||||
int no_leading_period, int flags)
|
||||
{
|
||||
register const char *p = pattern, *n = string;
|
||||
register char c;
|
||||
register unsigned char c;
|
||||
|
||||
/* Note that this evalutes C many times. */
|
||||
#define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
|
||||
/* Note that this evaluates C many times. */
|
||||
# ifdef _LIBC
|
||||
# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
|
||||
# else
|
||||
# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
|
||||
# endif
|
||||
|
||||
while ((c = *p++) != '\0')
|
||||
{
|
||||
@@ -64,10 +163,11 @@ fnmatch (pattern, string, flags)
|
||||
case '?':
|
||||
if (*n == '\0')
|
||||
return FNM_NOMATCH;
|
||||
else if ((flags & FNM_FILE_NAME) && *n == '/')
|
||||
else if (*n == '/' && (flags & FNM_FILE_NAME))
|
||||
return FNM_NOMATCH;
|
||||
else if ((flags & FNM_PERIOD) && *n == '.' &&
|
||||
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
|
||||
else if (*n == '.' && no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == '/' && (flags & FNM_FILE_NAME))))
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
@@ -75,95 +175,245 @@ fnmatch (pattern, string, flags)
|
||||
if (!(flags & FNM_NOESCAPE))
|
||||
{
|
||||
c = *p++;
|
||||
if (c == '\0')
|
||||
/* Trailing \ loses. */
|
||||
return FNM_NOMATCH;
|
||||
c = FOLD (c);
|
||||
}
|
||||
if (FOLD (*n) != c)
|
||||
if (FOLD ((unsigned char) *n) != c)
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
if ((flags & FNM_PERIOD) && *n == '.' &&
|
||||
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
|
||||
if (*n == '.' && no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == '/' && (flags & FNM_FILE_NAME))))
|
||||
return FNM_NOMATCH;
|
||||
|
||||
for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
|
||||
if (((flags & FNM_FILE_NAME) && *n == '/') ||
|
||||
(c == '?' && *n == '\0'))
|
||||
return FNM_NOMATCH;
|
||||
for (c = *p++; c == '?' || c == '*'; c = *p++)
|
||||
{
|
||||
if (*n == '/' && (flags & FNM_FILE_NAME))
|
||||
/* A slash does not match a wildcard under FNM_FILE_NAME. */
|
||||
return FNM_NOMATCH;
|
||||
else if (c == '?')
|
||||
{
|
||||
/* A ? needs to match one character. */
|
||||
if (*n == '\0')
|
||||
/* There isn't another character; no match. */
|
||||
return FNM_NOMATCH;
|
||||
else
|
||||
/* One character of the string is consumed in matching
|
||||
this ? wildcard, so *??? won't match if there are
|
||||
less than three characters. */
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == '\0')
|
||||
return 0;
|
||||
/* The wildcard(s) is/are the last element of the pattern.
|
||||
If the name is a file name and contains another slash
|
||||
this does mean it cannot match. */
|
||||
return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL
|
||||
? FNM_NOMATCH : 0);
|
||||
else
|
||||
{
|
||||
const char *endp;
|
||||
|
||||
{
|
||||
char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
|
||||
c1 = FOLD (c1);
|
||||
for (--p; *n != '\0'; ++n)
|
||||
if ((c == '[' || FOLD (*n) == c1) &&
|
||||
fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
|
||||
return 0;
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
#if 0
|
||||
endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
|
||||
#else
|
||||
/* replace call to internal glibc function with equivalent */
|
||||
if (!(flags & FNM_FILE_NAME) || ((endp = strchr(n, '/')) == NULL))
|
||||
endp = n + strlen(n);
|
||||
#endif
|
||||
|
||||
if (c == '[')
|
||||
{
|
||||
int flags2 = ((flags & FNM_FILE_NAME)
|
||||
? flags : (flags & ~FNM_PERIOD));
|
||||
|
||||
for (--p; n < endp; ++n)
|
||||
if (internal_fnmatch (p, n,
|
||||
(no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == '/'
|
||||
&& (flags
|
||||
& FNM_FILE_NAME)))),
|
||||
flags2)
|
||||
== 0)
|
||||
return 0;
|
||||
}
|
||||
else if (c == '/' && (flags & FNM_FILE_NAME))
|
||||
{
|
||||
while (*n != '\0' && *n != '/')
|
||||
++n;
|
||||
if (*n == '/'
|
||||
&& (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
|
||||
flags) == 0))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int flags2 = ((flags & FNM_FILE_NAME)
|
||||
? flags : (flags & ~FNM_PERIOD));
|
||||
|
||||
if (c == '\\' && !(flags & FNM_NOESCAPE))
|
||||
c = *p;
|
||||
c = FOLD (c);
|
||||
for (--p; n < endp; ++n)
|
||||
if (FOLD ((unsigned char) *n) == c
|
||||
&& (internal_fnmatch (p, n,
|
||||
(no_leading_period
|
||||
&& (n == string
|
||||
|| (n[-1] == '/'
|
||||
&& (flags
|
||||
& FNM_FILE_NAME)))),
|
||||
flags2) == 0))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we come here no match is possible with the wildcard. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
case '[':
|
||||
{
|
||||
/* Nonzero if the sense of the character class is inverted. */
|
||||
static int posixly_correct;
|
||||
register int not;
|
||||
char cold;
|
||||
|
||||
if (posixly_correct == 0)
|
||||
posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
|
||||
|
||||
if (*n == '\0')
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if ((flags & FNM_PERIOD) && *n == '.' &&
|
||||
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
|
||||
if (*n == '.' && no_leading_period && (n == string
|
||||
|| (n[-1] == '/'
|
||||
&& (flags
|
||||
& FNM_FILE_NAME))))
|
||||
return FNM_NOMATCH;
|
||||
|
||||
not = (*p == '!' || *p == '^');
|
||||
if (*n == '/' && (flags & FNM_FILE_NAME))
|
||||
/* `/' cannot be matched. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
|
||||
if (not)
|
||||
++p;
|
||||
|
||||
c = *p++;
|
||||
for (;;)
|
||||
{
|
||||
register char cstart = c, cend = c;
|
||||
unsigned char fn = FOLD ((unsigned char) *n);
|
||||
|
||||
if (!(flags & FNM_NOESCAPE) && c == '\\')
|
||||
cstart = cend = *p++;
|
||||
{
|
||||
if (*p == '\0')
|
||||
return FNM_NOMATCH;
|
||||
c = FOLD ((unsigned char) *p);
|
||||
++p;
|
||||
|
||||
cstart = cend = FOLD (cstart);
|
||||
if (c == fn)
|
||||
goto matched;
|
||||
}
|
||||
else if (c == '[' && *p == ':')
|
||||
{
|
||||
/* Leave room for the null. */
|
||||
char str[CHAR_CLASS_MAX_LENGTH + 1];
|
||||
size_t c1 = 0;
|
||||
# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
|
||||
wctype_t wt;
|
||||
# endif
|
||||
const char *startp = p;
|
||||
|
||||
if (c == '\0')
|
||||
for (;;)
|
||||
{
|
||||
if (c1 == CHAR_CLASS_MAX_LENGTH)
|
||||
/* The name is too long and therefore the pattern
|
||||
is ill-formed. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
c = *++p;
|
||||
if (c == ':' && p[1] == ']')
|
||||
{
|
||||
p += 2;
|
||||
break;
|
||||
}
|
||||
if (c < 'a' || c >= 'z')
|
||||
{
|
||||
/* This cannot possibly be a character class name.
|
||||
Match it as a normal range. */
|
||||
p = startp;
|
||||
c = '[';
|
||||
goto normal_bracket;
|
||||
}
|
||||
str[c1++] = c;
|
||||
}
|
||||
str[c1] = '\0';
|
||||
|
||||
# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
|
||||
wt = IS_CHAR_CLASS (str);
|
||||
if (wt == 0)
|
||||
/* Invalid character class name. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (__iswctype (__btowc ((unsigned char) *n), wt))
|
||||
goto matched;
|
||||
# else
|
||||
if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
|
||||
|| (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
|
||||
|| (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
|
||||
|| (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
|
||||
|| (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
|
||||
|| (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
|
||||
|| (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
|
||||
|| (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
|
||||
|| (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
|
||||
|| (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
|
||||
|| (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
|
||||
|| (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
|
||||
goto matched;
|
||||
# endif
|
||||
}
|
||||
else if (c == '\0')
|
||||
/* [ (unterminated) loses. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
c = *p++;
|
||||
c = FOLD (c);
|
||||
|
||||
if ((flags & FNM_FILE_NAME) && c == '/')
|
||||
/* [/] can never match. */
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (c == '-' && *p != ']')
|
||||
else
|
||||
{
|
||||
cend = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && cend == '\\')
|
||||
cend = *p++;
|
||||
if (cend == '\0')
|
||||
return FNM_NOMATCH;
|
||||
cend = FOLD (cend);
|
||||
normal_bracket:
|
||||
if (FOLD (c) == fn)
|
||||
goto matched;
|
||||
|
||||
cold = c;
|
||||
c = *p++;
|
||||
}
|
||||
|
||||
if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
|
||||
goto matched;
|
||||
if (c == '-' && *p != ']')
|
||||
{
|
||||
/* It is a range. */
|
||||
unsigned char cend = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && cend == '\\')
|
||||
cend = *p++;
|
||||
if (cend == '\0')
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (cold <= fn && fn <= FOLD (cend))
|
||||
goto matched;
|
||||
|
||||
c = *p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == ']')
|
||||
break;
|
||||
}
|
||||
|
||||
if (!not)
|
||||
return FNM_NOMATCH;
|
||||
break;
|
||||
|
||||
matched:;
|
||||
matched:
|
||||
/* Skip the rest of the [...] that already matched. */
|
||||
while (c != ']')
|
||||
{
|
||||
@@ -173,8 +423,21 @@ fnmatch (pattern, string, flags)
|
||||
|
||||
c = *p++;
|
||||
if (!(flags & FNM_NOESCAPE) && c == '\\')
|
||||
/* XXX 1003.2d11 is unclear if this is right. */
|
||||
++p;
|
||||
{
|
||||
if (*p == '\0')
|
||||
return FNM_NOMATCH;
|
||||
/* XXX 1003.2d11 is unclear if this is right. */
|
||||
++p;
|
||||
}
|
||||
else if (c == '[' && *p == ':')
|
||||
{
|
||||
do
|
||||
if (*++p == '\0')
|
||||
return FNM_NOMATCH;
|
||||
while (*p != ':' || p[1] == ']');
|
||||
p += 2;
|
||||
c = *p;
|
||||
}
|
||||
}
|
||||
if (not)
|
||||
return FNM_NOMATCH;
|
||||
@@ -182,7 +445,7 @@ fnmatch (pattern, string, flags)
|
||||
break;
|
||||
|
||||
default:
|
||||
if (c != FOLD (*n))
|
||||
if (c != FOLD ((unsigned char) *n))
|
||||
return FNM_NOMATCH;
|
||||
}
|
||||
|
||||
@@ -197,8 +460,23 @@ fnmatch (pattern, string, flags)
|
||||
return 0;
|
||||
|
||||
return FNM_NOMATCH;
|
||||
|
||||
# undef FOLD
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fnmatch (pattern, string, flags)
|
||||
const char *pattern;
|
||||
const char *string;
|
||||
int flags;
|
||||
{
|
||||
return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
|
||||
}
|
||||
|
||||
#endif /* _LIBC or not __GNU_LIBRARY__. */
|
||||
/* ----- END glibc-2.1.2 posix/fnmatch.c */
|
||||
|
||||
#else /* HAVE_FNMATCH */
|
||||
void fnmatch_dummy(void) {}
|
||||
#endif
|
||||
|
||||
@@ -1,41 +1,48 @@
|
||||
/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1991, 92, 93, 96, 97, 98 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
NOTE: The canonical source of this file is maintained with the GNU C Library.
|
||||
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library 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 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, or (at your option) any
|
||||
later version.
|
||||
The GNU C Library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _FNMATCH_H
|
||||
|
||||
#define _FNMATCH_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
|
||||
#undef __P
|
||||
#define __P(protos) protos
|
||||
#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
|
||||
# if !defined __GLIBC__ || !defined __P
|
||||
# undef __P
|
||||
# define __P(protos) protos
|
||||
# endif
|
||||
#else /* Not C++ or ANSI C. */
|
||||
#undef __P
|
||||
#define __P(protos) ()
|
||||
# undef __P
|
||||
# define __P(protos) ()
|
||||
/* We can get away without defining `const' here only because in this file
|
||||
it is used only inside the prototype for `fnmatch', which is elided in
|
||||
non-ANSI C where `const' is problematical. */
|
||||
#endif /* C++ or ANSI C. */
|
||||
|
||||
#ifndef const
|
||||
# if (defined __STDC__ && __STDC__) || defined __cplusplus
|
||||
# define __const const
|
||||
# else
|
||||
# define __const
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* We #undef these before defining them because some losing systems
|
||||
(HP-UX A.08.07 for example) define these in <unistd.h>. */
|
||||
@@ -48,18 +55,30 @@ extern "C" {
|
||||
#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */
|
||||
#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */
|
||||
|
||||
#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_GNU_SOURCE)
|
||||
#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
|
||||
#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
|
||||
#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
|
||||
#ifndef FNM_FILE_NAME
|
||||
# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
|
||||
#endif
|
||||
#ifndef FNM_LEADING_DIR
|
||||
# define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
|
||||
#endif
|
||||
#ifndef FNM_CASEFOLD
|
||||
# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
|
||||
#endif
|
||||
|
||||
/* Value returned by `fnmatch' if STRING does not match PATTERN. */
|
||||
#define FNM_NOMATCH 1
|
||||
|
||||
/* This value is returned if the implementation does not support
|
||||
`fnmatch'. Since this is not the case here it will never be
|
||||
returned but the conformance test suites still require the symbol
|
||||
to be defined. */
|
||||
#ifdef _XOPEN_SOURCE
|
||||
# define FNM_NOSYS (-1)
|
||||
#endif
|
||||
|
||||
/* Match STRING against the filename pattern PATTERN,
|
||||
returning zero if it matches, FNM_NOMATCH if not. */
|
||||
extern int fnmatch __P ((const char *__pattern, const char *__string,
|
||||
extern int fnmatch __P ((__const char *__pattern, __const char *__string,
|
||||
int __flags));
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -37,9 +37,9 @@ static struct mdfour *m;
|
||||
#define lshift(x,s) (((x)<<(s)) | ((x)>>(32-(s))))
|
||||
#endif
|
||||
|
||||
#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)
|
||||
#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + 0x5A827999,s)
|
||||
#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + 0x6ED9EBA1,s)
|
||||
#define ROUND1(a,b,c,d,k,s) a = lshift((uint32)(a + F(b,c,d) + X[k]), s)
|
||||
#define ROUND2(a,b,c,d,k,s) a = lshift((uint32)(a + G(b,c,d) + X[k] + 0x5A827999),s)
|
||||
#define ROUND3(a,b,c,d,k,s) a = lshift((uint32)(a + H(b,c,d) + X[k] + 0x6ED9EBA1),s)
|
||||
|
||||
/* this applies md4 to 64 byte chunks */
|
||||
static void mdfour64(uint32 *M)
|
||||
|
||||
@@ -117,6 +117,7 @@ typedef struct
|
||||
BOOL list;
|
||||
BOOL use_chroot;
|
||||
BOOL transfer_logging;
|
||||
BOOL ignore_errors;
|
||||
char *uid;
|
||||
char *gid;
|
||||
char *hosts_allow;
|
||||
@@ -147,6 +148,7 @@ static service sDefault =
|
||||
True, /* list */
|
||||
True, /* use chroot */
|
||||
False, /* transfer logging */
|
||||
False, /* ignore errors */
|
||||
"nobody",/* uid */
|
||||
"nobody",/* gid */
|
||||
NULL, /* hosts allow */
|
||||
@@ -160,7 +162,7 @@ static service sDefault =
|
||||
NULL, /* include from */
|
||||
"%o %h [%a] %m (%u) %f %l", /* log format */
|
||||
NULL, /* refuse options */
|
||||
"*.gz *.tgz *.zip *.z *.rpm *.deb", /* dont compress */
|
||||
"*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz", /* dont compress */
|
||||
0, /* timeout */
|
||||
0 /* max connections */
|
||||
};
|
||||
@@ -272,6 +274,7 @@ static struct parm_struct parm_table[] =
|
||||
{"include", P_STRING, P_LOCAL, &sDefault.include, NULL, 0},
|
||||
{"include from", P_STRING, P_LOCAL, &sDefault.include_from,NULL, 0},
|
||||
{"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging,NULL,0},
|
||||
{"ignore errors", P_BOOL, P_LOCAL, &sDefault.ignore_errors,NULL,0},
|
||||
{"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL, 0},
|
||||
{"refuse options", P_STRING, P_LOCAL, &sDefault.refuse_options,NULL, 0},
|
||||
{"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress,NULL, 0},
|
||||
@@ -336,6 +339,7 @@ FN_LOCAL_BOOL(lp_read_only, read_only)
|
||||
FN_LOCAL_BOOL(lp_list, list)
|
||||
FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
|
||||
FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
|
||||
FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
|
||||
FN_LOCAL_STRING(lp_uid, uid)
|
||||
FN_LOCAL_STRING(lp_gid, gid)
|
||||
FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
|
||||
|
||||
79
log.c
79
log.c
@@ -24,7 +24,7 @@
|
||||
#include "rsync.h"
|
||||
|
||||
static FILE *logfile;
|
||||
|
||||
static int log_error_fd = -1;
|
||||
|
||||
static void logit(int priority, char *buf)
|
||||
{
|
||||
@@ -77,60 +77,66 @@ void log_open(void)
|
||||
logit(LOG_INFO,"rsyncd started\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* this is the rsync debugging function. Call it with FINFO, FERROR or FLOG */
|
||||
void rprintf(int fd, const char *format, ...)
|
||||
/* setup the error file descriptor - used when we are a server
|
||||
that is receiving files */
|
||||
void set_error_fd(int fd)
|
||||
{
|
||||
log_error_fd = fd;
|
||||
}
|
||||
|
||||
/* this is the underlying (unformatted) rsync debugging function. Call
|
||||
it with FINFO, FERROR or FLOG */
|
||||
void rwrite(enum logcode code, char *buf, int len)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
int len;
|
||||
FILE *f=NULL;
|
||||
extern int am_daemon;
|
||||
extern int am_server;
|
||||
extern int quiet;
|
||||
/* recursion can happen with certain fatal conditions */
|
||||
|
||||
if (quiet != 0 && fd == FINFO) return;
|
||||
|
||||
va_start(ap, format);
|
||||
len = vslprintf(buf, sizeof(buf), format, ap);
|
||||
va_end(ap);
|
||||
if (quiet && code == FINFO) return;
|
||||
|
||||
if (len < 0) exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
if (len > sizeof(buf)-1) exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
buf[len] = 0;
|
||||
|
||||
if (fd == FLOG) {
|
||||
if (code == FLOG) {
|
||||
if (am_daemon) logit(LOG_INFO, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* first try to pass it off the our sibling */
|
||||
if (am_server && io_error_write(log_error_fd, code, buf, len)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* then try to pass it to the other end */
|
||||
if (am_server && io_multiplex_write(code, buf, len)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (am_daemon) {
|
||||
static int depth;
|
||||
int priority = LOG_INFO;
|
||||
if (fd == FERROR) priority = LOG_WARNING;
|
||||
if (code == FERROR) priority = LOG_WARNING;
|
||||
|
||||
if (depth) return;
|
||||
|
||||
depth++;
|
||||
|
||||
log_open();
|
||||
if (!io_multiplex_write(fd, buf, strlen(buf))) {
|
||||
logit(priority, buf);
|
||||
}
|
||||
logit(priority, buf);
|
||||
|
||||
depth--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (fd == FERROR) {
|
||||
if (code == FERROR) {
|
||||
f = stderr;
|
||||
}
|
||||
|
||||
if (fd == FINFO) {
|
||||
extern int am_server;
|
||||
if (code == FINFO) {
|
||||
if (am_server)
|
||||
f = stderr;
|
||||
else
|
||||
@@ -143,8 +149,25 @@ void log_open(void)
|
||||
|
||||
if (buf[len-1] == '\r' || buf[len-1] == '\n') fflush(f);
|
||||
}
|
||||
|
||||
|
||||
void rflush(int fd)
|
||||
/* this is the rsync debugging function. Call it with FINFO, FERROR or FLOG */
|
||||
void rprintf(enum logcode code, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
int len;
|
||||
|
||||
va_start(ap, format);
|
||||
len = vslprintf(buf, sizeof(buf), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len > sizeof(buf)-1) exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
rwrite(code, buf, len);
|
||||
}
|
||||
|
||||
void rflush(enum logcode code)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
extern int am_daemon;
|
||||
@@ -153,15 +176,15 @@ void rflush(int fd)
|
||||
return;
|
||||
}
|
||||
|
||||
if (fd == FLOG) {
|
||||
if (code == FLOG) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fd == FERROR) {
|
||||
if (code == FERROR) {
|
||||
f = stderr;
|
||||
}
|
||||
|
||||
if (fd == FINFO) {
|
||||
if (code == FINFO) {
|
||||
extern int am_server;
|
||||
if (am_server)
|
||||
f = stderr;
|
||||
@@ -177,7 +200,7 @@ void rflush(int fd)
|
||||
|
||||
/* a generic logging routine for send/recv, with parameter
|
||||
substitiution */
|
||||
static void log_formatted(int fd,
|
||||
static void log_formatted(enum logcode code,
|
||||
char *format, char *op, struct file_struct *file,
|
||||
struct stats *initial_stats)
|
||||
{
|
||||
@@ -267,7 +290,7 @@ static void log_formatted(int fd,
|
||||
s = p+l;
|
||||
}
|
||||
|
||||
rprintf(fd,"%s\n", buf);
|
||||
rprintf(code,"%s\n", buf);
|
||||
}
|
||||
|
||||
/* log the outgoing transfer of a file */
|
||||
|
||||
119
main.c
119
main.c
@@ -23,8 +23,6 @@ time_t starttime = 0;
|
||||
|
||||
struct stats stats;
|
||||
|
||||
extern int csum_length;
|
||||
|
||||
extern int verbose;
|
||||
|
||||
static void report(int f)
|
||||
@@ -114,6 +112,7 @@ static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f
|
||||
char *tok,*dir=NULL;
|
||||
extern int local_server;
|
||||
extern char *rsync_path;
|
||||
extern int blocking_io;
|
||||
|
||||
if (!local_server) {
|
||||
if (!cmd)
|
||||
@@ -146,6 +145,9 @@ static int do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f
|
||||
args[argc++] = rsync_path;
|
||||
|
||||
server_options(args,&argc);
|
||||
|
||||
|
||||
if (strcmp(cmd, RSYNC_RSH) == 0) blocking_io = 1;
|
||||
}
|
||||
|
||||
args[argc++] = ".";
|
||||
@@ -208,7 +210,7 @@ static char *get_local_name(struct file_list *flist,char *name)
|
||||
return name;
|
||||
}
|
||||
|
||||
if (flist->count == 1)
|
||||
if (flist->count <= 1)
|
||||
return name;
|
||||
|
||||
if (do_mkdir(name,0777 & ~orig_umask) != 0) {
|
||||
@@ -238,6 +240,7 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
|
||||
char *dir = argv[0];
|
||||
extern int relative_paths;
|
||||
extern int recurse;
|
||||
extern int remote_version;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
|
||||
@@ -263,17 +266,18 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
|
||||
argv[0] = ".";
|
||||
}
|
||||
|
||||
set_nonblocking(f_out);
|
||||
if (f_in != f_out)
|
||||
set_nonblocking(f_in);
|
||||
|
||||
flist = send_file_list(f_out,argc,argv);
|
||||
if (!flist || flist->count == 0) {
|
||||
exit_cleanup(0);
|
||||
}
|
||||
|
||||
send_files(flist,f_out,f_in);
|
||||
io_flush();
|
||||
report(f_out);
|
||||
if (remote_version >= 24) {
|
||||
/* final goodbye message */
|
||||
read_int(f_in);
|
||||
}
|
||||
io_flush();
|
||||
exit_cleanup(0);
|
||||
}
|
||||
@@ -284,45 +288,80 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
int pid;
|
||||
int status=0;
|
||||
int recv_pipe[2];
|
||||
int error_pipe[2];
|
||||
extern int preserve_hard_links;
|
||||
extern int delete_after;
|
||||
extern int recurse;
|
||||
extern int delete_mode;
|
||||
extern int remote_version;
|
||||
|
||||
if (preserve_hard_links)
|
||||
init_hard_links(flist);
|
||||
|
||||
if (pipe(recv_pipe) < 0) {
|
||||
if (!delete_after) {
|
||||
/* I moved this here from recv_files() to prevent a race condition */
|
||||
if (recurse && delete_mode && !local_name && flist->count>0) {
|
||||
delete_files(flist);
|
||||
}
|
||||
}
|
||||
|
||||
if (fd_pair(recv_pipe) < 0) {
|
||||
rprintf(FERROR,"pipe failed in do_recv\n");
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
|
||||
if (fd_pair(error_pipe) < 0) {
|
||||
rprintf(FERROR,"error pipe failed in do_recv\n");
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
|
||||
io_flush();
|
||||
|
||||
if ((pid=do_fork()) == 0) {
|
||||
close(recv_pipe[0]);
|
||||
close(error_pipe[0]);
|
||||
if (f_in != f_out) close(f_out);
|
||||
|
||||
set_nonblocking(f_in);
|
||||
set_nonblocking(recv_pipe[1]);
|
||||
/* we can't let two processes write to the socket at one time */
|
||||
io_multiplexing_close();
|
||||
|
||||
/* set place to send errors */
|
||||
set_error_fd(error_pipe[1]);
|
||||
|
||||
recv_files(f_in,flist,local_name,recv_pipe[1]);
|
||||
io_flush();
|
||||
report(f_in);
|
||||
|
||||
write_int(recv_pipe[1],1);
|
||||
close(recv_pipe[1]);
|
||||
io_flush();
|
||||
_exit(0);
|
||||
/* finally we go to sleep until our parent kills us
|
||||
with a USR2 signal. We sleepp for a short time as on
|
||||
some OSes a signal won't interrupt a sleep! */
|
||||
while (1) sleep(1);
|
||||
}
|
||||
|
||||
close(recv_pipe[1]);
|
||||
close(error_pipe[1]);
|
||||
io_close_input(f_in);
|
||||
if (f_in != f_out) close(f_in);
|
||||
|
||||
set_nonblocking(f_out);
|
||||
set_nonblocking(recv_pipe[0]);
|
||||
|
||||
io_start_buffering(f_out);
|
||||
|
||||
io_set_error_fd(error_pipe[0]);
|
||||
|
||||
generate_files(f_out,flist,local_name,recv_pipe[0]);
|
||||
|
||||
read_int(recv_pipe[0]);
|
||||
close(recv_pipe[0]);
|
||||
if (remote_version >= 24) {
|
||||
/* send a final goodbye message */
|
||||
write_int(f_out, -1);
|
||||
}
|
||||
io_flush();
|
||||
waitpid(pid, &status, 0);
|
||||
|
||||
kill(pid, SIGUSR2);
|
||||
wait_process(pid, &status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -336,9 +375,18 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
|
||||
extern int delete_mode;
|
||||
extern int delete_excluded;
|
||||
extern int am_daemon;
|
||||
extern int module_id;
|
||||
extern int am_sender;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
|
||||
|
||||
if (am_daemon && lp_read_only(module_id) && !am_sender) {
|
||||
rprintf(FERROR,"ERROR: module is read only\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (argc > 0) {
|
||||
dir = argv[0];
|
||||
@@ -355,8 +403,8 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
|
||||
recv_exclude_list(f_in);
|
||||
|
||||
flist = recv_file_list(f_in);
|
||||
if (!flist || flist->count == 0) {
|
||||
rprintf(FERROR,"server_recv: nothing to do\n");
|
||||
if (!flist) {
|
||||
rprintf(FERROR,"server_recv: recv_file_list error\n");
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
|
||||
@@ -377,13 +425,16 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
|
||||
{
|
||||
extern int cvs_exclude;
|
||||
extern int am_sender;
|
||||
extern int remote_version;
|
||||
|
||||
set_nonblocking(f_out);
|
||||
if (f_in != f_out)
|
||||
set_nonblocking(f_in);
|
||||
|
||||
setup_protocol(f_out, f_in);
|
||||
|
||||
set_nonblocking(f_in);
|
||||
set_nonblocking(f_out);
|
||||
|
||||
if (remote_version >= 23)
|
||||
io_start_multiplex_out(f_out);
|
||||
|
||||
if (am_sender) {
|
||||
recv_exclude_list(f_in);
|
||||
if (cvs_exclude)
|
||||
@@ -402,8 +453,15 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
|
||||
char *local_name = NULL;
|
||||
extern int am_sender;
|
||||
extern int list_only;
|
||||
extern int remote_version;
|
||||
|
||||
set_nonblocking(f_in);
|
||||
set_nonblocking(f_out);
|
||||
|
||||
setup_protocol(f_out,f_in);
|
||||
|
||||
if (remote_version >= 23)
|
||||
io_start_multiplex_in(f_in);
|
||||
|
||||
if (am_sender) {
|
||||
extern int cvs_exclude;
|
||||
@@ -417,16 +475,16 @@ int client_run(int f_in, int f_out, int pid, int argc, char *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)
|
||||
rprintf(FINFO,"client_run waiting on %d\n",pid);
|
||||
io_flush();
|
||||
waitpid(pid, &status, 0);
|
||||
wait_process(pid, &status);
|
||||
}
|
||||
if (remote_version >= 24) {
|
||||
/* final goodbye message */
|
||||
read_int(f_in);
|
||||
}
|
||||
report(-1);
|
||||
exit_cleanup(status);
|
||||
@@ -450,7 +508,7 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"client_run2 waiting on %d\n",pid);
|
||||
io_flush();
|
||||
waitpid(pid, &status, 0);
|
||||
wait_process(pid, &status);
|
||||
}
|
||||
|
||||
return status | status2;
|
||||
@@ -586,6 +644,10 @@ static RETSIGTYPE sigusr1_handler(int val) {
|
||||
exit_cleanup(RERR_SIGNAL);
|
||||
}
|
||||
|
||||
static RETSIGTYPE sigusr2_handler(int val) {
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
extern int am_root;
|
||||
@@ -595,6 +657,7 @@ int main(int argc,char *argv[])
|
||||
extern int am_server;
|
||||
|
||||
signal(SIGUSR1, sigusr1_handler);
|
||||
signal(SIGUSR2, sigusr2_handler);
|
||||
|
||||
starttime = time(NULL);
|
||||
am_root = (getuid() == 0);
|
||||
@@ -650,6 +713,8 @@ int main(int argc,char *argv[])
|
||||
#endif
|
||||
|
||||
if (am_server) {
|
||||
set_nonblocking(STDIN_FILENO);
|
||||
set_nonblocking(STDOUT_FILENO);
|
||||
start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
24
match.c
24
match.c
@@ -97,8 +97,8 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
|
||||
OFF_T j;
|
||||
|
||||
if (verbose > 2 && i >= 0)
|
||||
rprintf(FINFO,"match at %d last_match=%d j=%d len=%d n=%d\n",
|
||||
(int)offset,(int)last_match,i,(int)s->sums[i].len,(int)n);
|
||||
rprintf(FINFO,"match at %.0f last_match=%.0f j=%d len=%d n=%.0f\n",
|
||||
(double)offset,(double)last_match,i,s->sums[i].len,(double)n);
|
||||
|
||||
send_token(f,i,buf,last_match,n,i<0?0:s->sums[i].len);
|
||||
data_transfer += n;
|
||||
@@ -119,19 +119,19 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
|
||||
else
|
||||
last_match = offset;
|
||||
|
||||
if (buf)
|
||||
if (buf) {
|
||||
show_progress(last_match, buf->file_size);
|
||||
|
||||
if (i == -1) end_progress();
|
||||
if (i == -1) end_progress(buf->file_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void hash_search(int f,struct sum_struct *s,
|
||||
struct map_struct *buf,OFF_T len)
|
||||
{
|
||||
OFF_T offset;
|
||||
OFF_T offset, end;
|
||||
int j,k, last_i;
|
||||
int end;
|
||||
char sum2[SUM_LENGTH];
|
||||
uint32 s1, s2, sum;
|
||||
schar *map;
|
||||
@@ -141,7 +141,7 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
last_i = -1;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"hash search b=%d len=%d\n",s->n,(int)len);
|
||||
rprintf(FINFO,"hash search b=%d len=%.0f\n",s->n,(double)len);
|
||||
|
||||
k = MIN(len, s->n);
|
||||
|
||||
@@ -158,8 +158,8 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
end = len + 1 - s->sums[s->count-1].len;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"hash search s->n=%d len=%d count=%d\n",
|
||||
s->n,(int)len,s->count);
|
||||
rprintf(FINFO,"hash search s->n=%d len=%.0f count=%d\n",
|
||||
s->n,(double)len,s->count);
|
||||
|
||||
do {
|
||||
tag t = gettag2(s1,s2);
|
||||
@@ -167,7 +167,7 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
|
||||
j = tag_table[t];
|
||||
if (verbose > 4)
|
||||
rprintf(FINFO,"offset=%d sum=%08x\n",(int)offset,sum);
|
||||
rprintf(FINFO,"offset=%.0f sum=%08x\n",(double)offset,sum);
|
||||
|
||||
if (j == NULL_TAG) {
|
||||
goto null_tag;
|
||||
@@ -185,8 +185,8 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
if (l != s->sums[i].len) continue;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"potential match at %d target=%d %d sum=%08x\n",
|
||||
(int)offset,j,i,sum);
|
||||
rprintf(FINFO,"potential match at %.0f target=%d %d sum=%08x\n",
|
||||
(double)offset,j,i,sum);
|
||||
|
||||
if (!done_csum2) {
|
||||
map = (schar *)map_ptr(buf,offset,l);
|
||||
|
||||
263
md4.c
263
md4.c
@@ -1,263 +0,0 @@
|
||||
/*
|
||||
This code is from rfc1186.
|
||||
|
||||
It has been modified to use the SIVAL() macro to make it
|
||||
byte order and length independent, so we don't need the LOWBYTEFIRST define
|
||||
*/
|
||||
|
||||
/*
|
||||
** ********************************************************************
|
||||
** md4.c -- Implementation of MD4 Message Digest Algorithm **
|
||||
** Updated: 2/16/90 by Ronald L. Rivest **
|
||||
** (C) 1990 RSA Data Security, Inc. **
|
||||
** ********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
** To use MD4:
|
||||
** -- Include md4.h in your program
|
||||
** -- Declare an MDstruct MD to hold the state of the digest
|
||||
** computation.
|
||||
** -- Initialize MD using MDbegin(&MD)
|
||||
** -- For each full block (64 bytes) X you wish to process, call
|
||||
** MDupdate(&MD,X,512)
|
||||
** (512 is the number of bits in a full block.)
|
||||
** -- For the last block (less than 64 bytes) you wish to process,
|
||||
** MDupdate(&MD,X,n)
|
||||
** where n is the number of bits in the partial block. A partial
|
||||
** block terminates the computation, so every MD computation
|
||||
** should terminate by processing a partial block, even if it
|
||||
** has n = 0.
|
||||
** -- The message digest is available in MD.buffer[0] ...
|
||||
** MD.buffer[3]. (Least-significant byte of each word
|
||||
** should be output first.)
|
||||
** -- You can print out the digest using MDprint(&MD)
|
||||
*/
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
/* Compile-time includes
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
/* Compile-time declarations of MD4 "magic constants".
|
||||
*/
|
||||
#define I0 0x67452301 /* Initial values for MD buffer */
|
||||
#define I1 0xefcdab89
|
||||
#define I2 0x98badcfe
|
||||
#define I3 0x10325476
|
||||
#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */
|
||||
#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */
|
||||
/* C2 and C3 are from Knuth, The Art of Programming, Volume 2
|
||||
** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
|
||||
** Table 2, page 660.
|
||||
*/
|
||||
|
||||
#define fs1 3 /* round 1 shift amounts */
|
||||
#define fs2 7
|
||||
#define fs3 11
|
||||
#define fs4 19
|
||||
#define gs1 3 /* round 2 shift amounts */
|
||||
#define gs2 5
|
||||
#define gs3 9
|
||||
#define gs4 13
|
||||
#define hs1 3 /* round 3 shift amounts */
|
||||
#define hs2 9
|
||||
#define hs3 11
|
||||
#define hs4 15
|
||||
|
||||
/* Compile-time macro declarations for MD4.
|
||||
** Note: The "rot" operator uses the variable "tmp".
|
||||
** It assumes tmp is declared as unsigned int, so that the >>
|
||||
** operator will shift in zeros rather than extending the sign bit.
|
||||
*/
|
||||
#define f(X,Y,Z) ((X&Y) | ((~X)&Z))
|
||||
#define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z))
|
||||
#define h(X,Y,Z) (X^Y^Z)
|
||||
#define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S)))
|
||||
#define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s)
|
||||
#define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s)
|
||||
#define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s)
|
||||
|
||||
/* MDbegin(MDp)
|
||||
** Initialize message digest buffer MDp.
|
||||
** This is a user-callable routine.
|
||||
*/
|
||||
void
|
||||
MDbegin(MDp)
|
||||
MDptr MDp;
|
||||
{ int i;
|
||||
MDp->buffer[0] = I0;
|
||||
MDp->buffer[1] = I1;
|
||||
MDp->buffer[2] = I2;
|
||||
MDp->buffer[3] = I3;
|
||||
for (i=0;i<8;i++) MDp->count[i] = 0;
|
||||
MDp->done = 0;
|
||||
}
|
||||
|
||||
/* MDreverse(X)
|
||||
** Reverse the byte-ordering of every int in X.
|
||||
** Assumes X is an array of 16 ints.
|
||||
** The macro revx reverses the byte-ordering of the next word of X.
|
||||
*/
|
||||
static void MDreverse(X)
|
||||
unsigned int32 *X;
|
||||
{ register unsigned int32 t;
|
||||
register unsigned int i;
|
||||
|
||||
for(i = 0; i < 16; i++) {
|
||||
t = X[i];
|
||||
SIVAL(X,i*4,t);
|
||||
}
|
||||
}
|
||||
|
||||
/* MDblock(MDp,X)
|
||||
** Update message digest buffer MDp->buffer using 16-word data block X.
|
||||
** Assumes all 16 words of X are full of data.
|
||||
** Does not update MDp->count.
|
||||
** This routine is not user-callable.
|
||||
*/
|
||||
static void
|
||||
MDblock(MDp,X)
|
||||
MDptr MDp;
|
||||
unsigned int32 *X;
|
||||
{
|
||||
register unsigned int32 tmp, A, B, C, D;
|
||||
MDreverse(X);
|
||||
A = MDp->buffer[0];
|
||||
B = MDp->buffer[1];
|
||||
C = MDp->buffer[2];
|
||||
D = MDp->buffer[3];
|
||||
/* Update the message digest buffer */
|
||||
ff(A , B , C , D , 0 , fs1); /* Round 1 */
|
||||
ff(D , A , B , C , 1 , fs2);
|
||||
ff(C , D , A , B , 2 , fs3);
|
||||
ff(B , C , D , A , 3 , fs4);
|
||||
ff(A , B , C , D , 4 , fs1);
|
||||
ff(D , A , B , C , 5 , fs2);
|
||||
ff(C , D , A , B , 6 , fs3);
|
||||
ff(B , C , D , A , 7 , fs4);
|
||||
ff(A , B , C , D , 8 , fs1);
|
||||
ff(D , A , B , C , 9 , fs2);
|
||||
ff(C , D , A , B , 10 , fs3);
|
||||
ff(B , C , D , A , 11 , fs4);
|
||||
ff(A , B , C , D , 12 , fs1);
|
||||
ff(D , A , B , C , 13 , fs2);
|
||||
ff(C , D , A , B , 14 , fs3);
|
||||
ff(B , C , D , A , 15 , fs4);
|
||||
gg(A , B , C , D , 0 , gs1); /* Round 2 */
|
||||
gg(D , A , B , C , 4 , gs2);
|
||||
gg(C , D , A , B , 8 , gs3);
|
||||
gg(B , C , D , A , 12 , gs4);
|
||||
gg(A , B , C , D , 1 , gs1);
|
||||
gg(D , A , B , C , 5 , gs2);
|
||||
gg(C , D , A , B , 9 , gs3);
|
||||
gg(B , C , D , A , 13 , gs4);
|
||||
gg(A , B , C , D , 2 , gs1);
|
||||
gg(D , A , B , C , 6 , gs2);
|
||||
gg(C , D , A , B , 10 , gs3);
|
||||
gg(B , C , D , A , 14 , gs4);
|
||||
gg(A , B , C , D , 3 , gs1);
|
||||
gg(D , A , B , C , 7 , gs2);
|
||||
gg(C , D , A , B , 11 , gs3);
|
||||
gg(B , C , D , A , 15 , gs4);
|
||||
hh(A , B , C , D , 0 , hs1); /* Round 3 */
|
||||
hh(D , A , B , C , 8 , hs2);
|
||||
hh(C , D , A , B , 4 , hs3);
|
||||
hh(B , C , D , A , 12 , hs4);
|
||||
hh(A , B , C , D , 2 , hs1);
|
||||
hh(D , A , B , C , 10 , hs2);
|
||||
hh(C , D , A , B , 6 , hs3);
|
||||
hh(B , C , D , A , 14 , hs4);
|
||||
hh(A , B , C , D , 1 , hs1);
|
||||
hh(D , A , B , C , 9 , hs2);
|
||||
hh(C , D , A , B , 5 , hs3);
|
||||
hh(B , C , D , A , 13 , hs4);
|
||||
hh(A , B , C , D , 3 , hs1);
|
||||
hh(D , A , B , C , 11 , hs2);
|
||||
hh(C , D , A , B , 7 , hs3);
|
||||
hh(B , C , D , A , 15 , hs4);
|
||||
MDp->buffer[0] += A;
|
||||
MDp->buffer[1] += B;
|
||||
MDp->buffer[2] += C;
|
||||
MDp->buffer[3] += D;
|
||||
}
|
||||
|
||||
/* MDupdate(MDp,X,count)
|
||||
** Input: MDp -- an MDptr
|
||||
** X -- a pointer to an array of unsigned characters.
|
||||
** count -- the number of bits of X to use.
|
||||
** (if not a multiple of 8, uses high bits of last byte.)
|
||||
** Update MDp using the number of bits of X given by count.
|
||||
** This is the basic input routine for an MD4 user.
|
||||
** The routine completes the MD computation when count < 512, so
|
||||
** every MD computation should end with one call to MDupdate with a
|
||||
** count less than 512. A call with count 0 will be ignored if the
|
||||
** MD has already been terminated (done != 0), so an extra call with
|
||||
** count 0 can be given as a "courtesy close" to force termination
|
||||
** if desired.
|
||||
*/
|
||||
void
|
||||
MDupdate(MDp,X,count)
|
||||
MDptr MDp;
|
||||
unsigned char *X;
|
||||
unsigned int count;
|
||||
{ unsigned int32 i, tmp, bit, byte, mask;
|
||||
unsigned char XX[64];
|
||||
unsigned char *p;
|
||||
/* return with no error if this is a courtesy close with count
|
||||
** zero and MDp->done is true.
|
||||
*/
|
||||
if (count == 0 && MDp->done) return;
|
||||
/* check to see if MD is already done and report error */
|
||||
if (MDp->done)
|
||||
{ rprintf(FERROR,"\nError: MDupdate MD already done."); return; }
|
||||
/* Add count to MDp->count */
|
||||
tmp = count;
|
||||
p = MDp->count;
|
||||
while (tmp)
|
||||
{ tmp += *p;
|
||||
*p++ = tmp;
|
||||
tmp = tmp >> 8;
|
||||
}
|
||||
/* Process data */
|
||||
if (count == 512)
|
||||
{ /* Full block of data to handle */
|
||||
MDblock(MDp,(unsigned int32 *)X);
|
||||
}
|
||||
else if (count > 512) /* Check for count too large */
|
||||
{ rprintf(FERROR,"\nError: MDupdate called with illegal count value %d."
|
||||
,count);
|
||||
return;
|
||||
}
|
||||
else /* partial block -- must be last block so finish up */
|
||||
{ /* Find out how many bytes and residual bits there are */
|
||||
byte = count >> 3;
|
||||
bit = count & 7;
|
||||
/* Copy X into XX since we need to modify it */
|
||||
for (i=0;i<=byte;i++) XX[i] = X[i];
|
||||
for (i=byte+1;i<64;i++) XX[i] = 0;
|
||||
/* Add padding '1' bit and low-order zeros in last byte */
|
||||
mask = 1 << (7 - bit);
|
||||
XX[byte] = (XX[byte] | mask) & ~( mask - 1);
|
||||
/* If room for bit count, finish up with this block */
|
||||
if (byte <= 55)
|
||||
{ for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
|
||||
MDblock(MDp,(unsigned int32 *)XX);
|
||||
}
|
||||
else /* need to do two blocks to finish up */
|
||||
{ MDblock(MDp,(unsigned int32 *)XX);
|
||||
for (i=0;i<56;i++) XX[i] = 0;
|
||||
for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
|
||||
MDblock(MDp,(unsigned int32 *)XX);
|
||||
}
|
||||
/* Set flag saying we're done with MD computation */
|
||||
MDp->done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** End of md4.c
|
||||
*/
|
||||
49
md4.h
49
md4.h
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
This code is from rfc1186.
|
||||
*/
|
||||
|
||||
/*
|
||||
** ********************************************************************
|
||||
** md4.h -- Header file for implementation of **
|
||||
** MD4 Message Digest Algorithm **
|
||||
** Updated: 2/13/90 by Ronald L. Rivest **
|
||||
** (C) 1990 RSA Data Security, Inc. **
|
||||
** ********************************************************************
|
||||
*/
|
||||
|
||||
/* MDstruct is the data structure for a message digest computation.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int32 buffer[4]; /* Holds 4-word result of MD computation */
|
||||
unsigned char count[8]; /* Number of bits processed so far */
|
||||
unsigned int done; /* Nonzero means MD computation finished */
|
||||
} MDstruct, *MDptr;
|
||||
|
||||
/* MDbegin(MD)
|
||||
|
||||
|
||||
|
||||
** Input: MD -- an MDptr
|
||||
** Initialize the MDstruct prepatory to doing a message digest
|
||||
** computation.
|
||||
*/
|
||||
extern void MDbegin();
|
||||
|
||||
/* MDupdate(MD,X,count)
|
||||
** Input: MD -- an MDptr
|
||||
** X -- a pointer to an array of unsigned characters.
|
||||
** count -- the number of bits of X to use (an unsigned int).
|
||||
** Updates MD using the first "count" bits of X.
|
||||
** The array pointed to by X is not modified.
|
||||
** If count is not a multiple of 8, MDupdate uses high bits of
|
||||
** last byte.
|
||||
** This is the basic input routine for a user.
|
||||
** The routine terminates the MD computation when count < 512, so
|
||||
** every MD computation should end with one call to MDupdate with a
|
||||
** count less than 512. Zero is OK for a count.
|
||||
*/
|
||||
extern void MDupdate();
|
||||
|
||||
/*
|
||||
** End of md4.h
|
||||
*/
|
||||
118
options.c
118
options.c
@@ -62,6 +62,12 @@ int safe_symlinks=0;
|
||||
int copy_unsafe_links=0;
|
||||
int block_size=BLOCK_SIZE;
|
||||
int size_only=0;
|
||||
int bwlimit=0;
|
||||
int delete_after=0;
|
||||
int only_existing=0;
|
||||
int max_delete=0;
|
||||
int ignore_errors=0;
|
||||
int blocking_io=0;
|
||||
|
||||
char *backup_suffix = BACKUP_SUFFIX;
|
||||
char *tmpdir = NULL;
|
||||
@@ -71,6 +77,7 @@ char *shell_cmd = NULL;
|
||||
char *log_format = NULL;
|
||||
char *password_file = NULL;
|
||||
char *rsync_path = RSYNC_NAME;
|
||||
char *backup_dir = NULL;
|
||||
int rsync_port = RSYNC_PORT;
|
||||
|
||||
int verbose = 0;
|
||||
@@ -78,7 +85,9 @@ int quiet = 0;
|
||||
int always_checksum = 0;
|
||||
int list_only = 0;
|
||||
|
||||
void usage(int F)
|
||||
struct in_addr socket_address = {INADDR_ANY};
|
||||
|
||||
void usage(enum logcode F)
|
||||
{
|
||||
rprintf(F,"rsync version %s Copyright Andrew Tridgell and Paul Mackerras\n\n",
|
||||
VERSION);
|
||||
@@ -102,6 +111,7 @@ void usage(int F)
|
||||
rprintf(F," -r, --recursive recurse into directories\n");
|
||||
rprintf(F," -R, --relative use relative path names\n");
|
||||
rprintf(F," -b, --backup make backups (default %s suffix)\n",BACKUP_SUFFIX);
|
||||
rprintf(F," --backup-dir make backups into this directory\n");
|
||||
rprintf(F," --suffix=SUFFIX override backup suffix\n");
|
||||
rprintf(F," -u, --update update only (don't overwrite newer files)\n");
|
||||
rprintf(F," -l, --links preserve soft links\n");
|
||||
@@ -122,8 +132,12 @@ void usage(int F)
|
||||
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," --existing only update files that already exist\n");
|
||||
rprintf(F," --delete delete files that don't exist on the sending side\n");
|
||||
rprintf(F," --delete-excluded also delete excluded files on the receiving side\n");
|
||||
rprintf(F," --delete-after delete after transferring, not before\n");
|
||||
rprintf(F," --ignore-errors delete even if there are IO errors\n");
|
||||
rprintf(F," --max-delete=NUM don't delete more than NUM files\n");
|
||||
rprintf(F," --partial keep partially transferred files\n");
|
||||
rprintf(F," --force force deletion of directories even if not empty\n");
|
||||
rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
|
||||
@@ -132,6 +146,7 @@ void usage(int F)
|
||||
rprintf(F," --size-only only use file size when determining if a file should be transferred\n");
|
||||
rprintf(F," -T --temp-dir=DIR create temporary files in directory DIR\n");
|
||||
rprintf(F," --compare-dest=DIR also compare destination files relative to DIR\n");
|
||||
rprintf(F," -P equivalent to --partial --progress\n");
|
||||
rprintf(F," -z, --compress compress file data\n");
|
||||
rprintf(F," --exclude=PATTERN exclude files matching PATTERN\n");
|
||||
rprintf(F," --exclude-from=FILE exclude patterns listed in FILE\n");
|
||||
@@ -139,12 +154,15 @@ void usage(int F)
|
||||
rprintf(F," --include-from=FILE don't exclude patterns listed in FILE\n");
|
||||
rprintf(F," --version print version number\n");
|
||||
rprintf(F," --daemon run as a rsync daemon\n");
|
||||
rprintf(F," --address bind to the specified address\n");
|
||||
rprintf(F," --config=FILE specify alternate rsyncd.conf file\n");
|
||||
rprintf(F," --port=PORT specify alternate rsyncd port number\n");
|
||||
rprintf(F," --blocking-io use blocking IO for the remote shell\n");
|
||||
rprintf(F," --stats give some file transfer stats\n");
|
||||
rprintf(F," --progress show progress during transfer\n");
|
||||
rprintf(F," --log-format=FORMAT log file transfers using specified format\n");
|
||||
rprintf(F," --password-file=FILE get password from FILE\n");
|
||||
rprintf(F," --bwlimit=KBPS limit I/O bandwidth, KBytes per second\n");
|
||||
rprintf(F," -h, --help show this help screen\n");
|
||||
|
||||
rprintf(F,"\n");
|
||||
@@ -158,14 +176,17 @@ enum {OPT_VERSION, OPT_SUFFIX, OPT_SENDER, OPT_SERVER, OPT_EXCLUDE,
|
||||
OPT_RSYNC_PATH, OPT_FORCE, OPT_TIMEOUT, OPT_DAEMON, OPT_CONFIG, OPT_PORT,
|
||||
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS, OPT_PARTIAL, OPT_PROGRESS,
|
||||
OPT_COPY_UNSAFE_LINKS, OPT_SAFE_LINKS, OPT_COMPARE_DEST,
|
||||
OPT_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY};
|
||||
OPT_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY, OPT_ADDRESS,
|
||||
OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR,
|
||||
OPT_IGNORE_ERRORS, OPT_BWLIMIT, OPT_BLOCKING_IO};
|
||||
|
||||
static char *short_options = "oblLWHpguDCtcahvqrRIxnSe:B:T:z";
|
||||
static char *short_options = "oblLWHpguDCtcahvqrRIxnSe:B:T:zP";
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"version", 0, 0, OPT_VERSION},
|
||||
{"server", 0, 0, OPT_SERVER},
|
||||
{"sender", 0, 0, OPT_SENDER},
|
||||
{"existing", 0, 0, OPT_EXISTING},
|
||||
{"delete", 0, 0, OPT_DELETE},
|
||||
{"delete-excluded", 0, 0, OPT_DELETE_EXCLUDED},
|
||||
{"force", 0, 0, OPT_FORCE},
|
||||
@@ -213,9 +234,16 @@ static struct option long_options[] = {
|
||||
{"stats", 0, 0, OPT_STATS},
|
||||
{"progress", 0, 0, OPT_PROGRESS},
|
||||
{"partial", 0, 0, OPT_PARTIAL},
|
||||
{"delete-after",0, 0, OPT_DELETE_AFTER},
|
||||
{"ignore-errors",0, 0, OPT_IGNORE_ERRORS},
|
||||
{"blocking-io" ,0, 0, OPT_BLOCKING_IO},
|
||||
{"config", 1, 0, OPT_CONFIG},
|
||||
{"port", 1, 0, OPT_PORT},
|
||||
{"log-format", 1, 0, OPT_LOG_FORMAT},
|
||||
{"bwlimit", 1, 0, OPT_BWLIMIT},
|
||||
{"address", 1, 0, OPT_ADDRESS},
|
||||
{"max-delete", 1, 0, OPT_MAX_DELETE},
|
||||
{"backup-dir", 1, 0, OPT_BACKUP_DIR},
|
||||
{0,0,0,0}};
|
||||
|
||||
|
||||
@@ -311,6 +339,14 @@ int parse_arguments(int argc, char *argv[], int frommain)
|
||||
delete_mode = 1;
|
||||
break;
|
||||
|
||||
case OPT_EXISTING:
|
||||
only_existing = 1;
|
||||
break;
|
||||
|
||||
case OPT_DELETE_AFTER:
|
||||
delete_after = 1;
|
||||
break;
|
||||
|
||||
case OPT_DELETE_EXCLUDED:
|
||||
delete_excluded = 1;
|
||||
delete_mode = 1;
|
||||
@@ -434,10 +470,8 @@ int parse_arguments(int argc, char *argv[], int frommain)
|
||||
preserve_perms=1;
|
||||
preserve_times=1;
|
||||
preserve_gid=1;
|
||||
if (am_root) {
|
||||
preserve_devices=1;
|
||||
preserve_uid=1;
|
||||
}
|
||||
preserve_uid=1;
|
||||
preserve_devices=1;
|
||||
break;
|
||||
|
||||
case OPT_SERVER:
|
||||
@@ -468,6 +502,10 @@ int parse_arguments(int argc, char *argv[], int frommain)
|
||||
block_size = atoi(optarg);
|
||||
break;
|
||||
|
||||
case OPT_MAX_DELETE:
|
||||
max_delete = atoi(optarg);
|
||||
break;
|
||||
|
||||
case OPT_TIMEOUT:
|
||||
io_timeout = atoi(optarg);
|
||||
break;
|
||||
@@ -500,6 +538,19 @@ int parse_arguments(int argc, char *argv[], int frommain)
|
||||
keep_partial = 1;
|
||||
break;
|
||||
|
||||
case OPT_IGNORE_ERRORS:
|
||||
ignore_errors = 1;
|
||||
break;
|
||||
|
||||
case OPT_BLOCKING_IO:
|
||||
blocking_io = 1;
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
do_progress = 1;
|
||||
keep_partial = 1;
|
||||
break;
|
||||
|
||||
case OPT_CONFIG:
|
||||
config_file = optarg;
|
||||
break;
|
||||
@@ -511,6 +562,23 @@ int parse_arguments(int argc, char *argv[], int frommain)
|
||||
case OPT_LOG_FORMAT:
|
||||
log_format = optarg;
|
||||
break;
|
||||
|
||||
case OPT_BWLIMIT:
|
||||
bwlimit = atoi(optarg);
|
||||
break;
|
||||
|
||||
case OPT_ADDRESS:
|
||||
{
|
||||
struct in_addr *ia;
|
||||
if ((ia = ip_address(optarg))) {
|
||||
socket_address = *ia;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_BACKUP_DIR:
|
||||
backup_dir = optarg;
|
||||
break;
|
||||
|
||||
default:
|
||||
slprintf(err_buf,sizeof(err_buf),"unrecognised option\n");
|
||||
@@ -521,12 +589,17 @@ int parse_arguments(int argc, char *argv[], int frommain)
|
||||
}
|
||||
|
||||
|
||||
/* need to pass all the valid options from the client to the server */
|
||||
|
||||
void server_options(char **args,int *argc)
|
||||
{
|
||||
int ac = *argc;
|
||||
static char argstr[50];
|
||||
static char bsize[30];
|
||||
static char iotime[30];
|
||||
static char mdelete[30];
|
||||
static char bw[50];
|
||||
|
||||
int i, x;
|
||||
|
||||
args[ac++] = "--server";
|
||||
@@ -584,15 +657,25 @@ void server_options(char **args,int *argc)
|
||||
if (x != 1) args[ac++] = argstr;
|
||||
|
||||
if (block_size != BLOCK_SIZE) {
|
||||
sprintf(bsize,"-B%d",block_size);
|
||||
slprintf(bsize,sizeof(bsize),"-B%d",block_size);
|
||||
args[ac++] = bsize;
|
||||
}
|
||||
|
||||
if (max_delete && am_sender) {
|
||||
slprintf(mdelete,sizeof(mdelete),"--max-delete=%d",max_delete);
|
||||
args[ac++] = mdelete;
|
||||
}
|
||||
|
||||
if (io_timeout) {
|
||||
sprintf(iotime,"--timeout=%d",io_timeout);
|
||||
slprintf(iotime,sizeof(iotime),"--timeout=%d",io_timeout);
|
||||
args[ac++] = iotime;
|
||||
}
|
||||
|
||||
if (bwlimit) {
|
||||
slprintf(bw,sizeof(bw),"--bwlimit=%d",bwlimit);
|
||||
args[ac++] = bw;
|
||||
}
|
||||
|
||||
if (strcmp(backup_suffix, BACKUP_SUFFIX)) {
|
||||
args[ac++] = "--suffix";
|
||||
args[ac++] = backup_suffix;
|
||||
@@ -613,6 +696,12 @@ void server_options(char **args,int *argc)
|
||||
if (force_delete)
|
||||
args[ac++] = "--force";
|
||||
|
||||
if (delete_after)
|
||||
args[ac++] = "--delete-after";
|
||||
|
||||
if (ignore_errors)
|
||||
args[ac++] = "--ignore-errors";
|
||||
|
||||
if (copy_unsafe_links)
|
||||
args[ac++] = "--copy-unsafe-links";
|
||||
|
||||
@@ -622,11 +711,22 @@ void server_options(char **args,int *argc)
|
||||
if (numeric_ids)
|
||||
args[ac++] = "--numeric-ids";
|
||||
|
||||
if (only_existing && am_sender)
|
||||
args[ac++] = "--existing";
|
||||
|
||||
if (tmpdir) {
|
||||
args[ac++] = "--temp-dir";
|
||||
args[ac++] = tmpdir;
|
||||
}
|
||||
|
||||
if (backup_dir && am_sender) {
|
||||
/* only the receiver needs this option, if we are the sender
|
||||
* then we need to send it to the receiver.
|
||||
*/
|
||||
args[ac++] = "--backup-dir";
|
||||
args[ac++] = backup_dir;
|
||||
}
|
||||
|
||||
if (compare_dest && am_sender) {
|
||||
/* the server only needs this option if it is not the sender,
|
||||
* and it may be an older version that doesn't know this
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.3.0
|
||||
Version: 2.4.4
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.3.0.tar.gz
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.4.4.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
@@ -21,6 +21,8 @@ A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* Mon Jan 25 1999 Stefan Hornburg <racke@linuxia.de>
|
||||
quoted RPM_OPT_FLAGS for the sake of robustness
|
||||
* Mon May 18 1998 Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
reworked for auto-building when I release rsync (tridge@samba.anu.edu.au)
|
||||
|
||||
@@ -58,7 +60,7 @@ previous package(s).)
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
make CFLAGS=$RPM_OPT_FLAGS
|
||||
make CFLAGS="$RPM_OPT_FLAGS"
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
|
||||
@@ -21,6 +21,8 @@ A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* Mon Jan 25 1999 Stefan Hornburg <racke@linuxia.de>
|
||||
quoted RPM_OPT_FLAGS for the sake of robustness
|
||||
* Mon May 18 1998 Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
reworked for auto-building when I release rsync (tridge@samba.anu.edu.au)
|
||||
|
||||
@@ -58,7 +60,7 @@ previous package(s).)
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
make CFLAGS=$RPM_OPT_FLAGS
|
||||
make CFLAGS="$RPM_OPT_FLAGS"
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
|
||||
67
receiver.c
67
receiver.c
@@ -36,14 +36,12 @@ extern char *compare_dest;
|
||||
extern int make_backups;
|
||||
extern char *backup_suffix;
|
||||
|
||||
|
||||
static struct delete_list {
|
||||
dev_t dev;
|
||||
INO_T inode;
|
||||
} *delete_list;
|
||||
static int dlist_len, dlist_alloc_len;
|
||||
|
||||
|
||||
/* yuck! This function wouldn't have been necessary if I had the sorting
|
||||
algorithm right. Unfortunately fixing the sorting algorithm would introduce
|
||||
a backward incompatibility as file list indexes are sent over the link.
|
||||
@@ -104,16 +102,20 @@ static void delete_one(struct file_struct *f)
|
||||
/* this deletes any files on the receiving side that are not present
|
||||
on the sending side. For version 1.6.4 I have changed the behaviour
|
||||
to match more closely what most people seem to expect of this option */
|
||||
static void delete_files(struct file_list *flist)
|
||||
void delete_files(struct file_list *flist)
|
||||
{
|
||||
struct file_list *local_file_list;
|
||||
int i, j;
|
||||
char *name;
|
||||
extern int module_id;
|
||||
extern int ignore_errors;
|
||||
extern int max_delete;
|
||||
static int deletion_count;
|
||||
|
||||
if (cvs_exclude)
|
||||
add_cvs_excludes();
|
||||
|
||||
if (io_error) {
|
||||
if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) {
|
||||
rprintf(FINFO,"IO error encountered - skipping file deletion\n");
|
||||
return;
|
||||
}
|
||||
@@ -136,6 +138,7 @@ static void delete_files(struct file_list *flist)
|
||||
rprintf(FINFO,"deleting in %s\n", name);
|
||||
|
||||
for (i=local_file_list->count-1;i>=0;i--) {
|
||||
if (max_delete && deletion_count > max_delete) break;
|
||||
if (!local_file_list->files[i]->basename) continue;
|
||||
if (remote_version < 19 &&
|
||||
S_ISDIR(local_file_list->files[i]->mode))
|
||||
@@ -143,10 +146,12 @@ static void delete_files(struct file_list *flist)
|
||||
if (-1 == flist_find(flist,local_file_list->files[i])) {
|
||||
char *f = f_name(local_file_list->files[i]);
|
||||
int k = strlen(f) - strlen(backup_suffix);
|
||||
/* Hi Andrew, do we really need to play with backup_suffix here? */
|
||||
if (make_backups && ((k <= 0) ||
|
||||
(strcmp(f+k,backup_suffix) != 0))) {
|
||||
(void) make_backup(f);
|
||||
} else {
|
||||
deletion_count++;
|
||||
delete_one(local_file_list->files[i]);
|
||||
}
|
||||
}
|
||||
@@ -221,8 +226,8 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
|
||||
extern int cleanup_got_literal;
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO,"data recv %d at %d\n",
|
||||
i,(int)offset);
|
||||
rprintf(FINFO,"data recv %d at %.0f\n",
|
||||
i,(double)offset);
|
||||
}
|
||||
|
||||
stats.literal_data += i;
|
||||
@@ -239,7 +244,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
|
||||
}
|
||||
|
||||
i = -(i+1);
|
||||
offset2 = i*n;
|
||||
offset2 = i*(OFF_T)n;
|
||||
len = n;
|
||||
if (i == count-1 && remainder != 0)
|
||||
len = remainder;
|
||||
@@ -247,13 +252,15 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
|
||||
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);
|
||||
rprintf(FINFO,"chunk[%d] of size %d at %.0f offset=%.0f\n",
|
||||
i,len,(double)offset2,(double)offset);
|
||||
|
||||
map = map_ptr(buf,offset2,len);
|
||||
if (buf) {
|
||||
map = map_ptr(buf,offset2,len);
|
||||
|
||||
see_token(map, len);
|
||||
sum_update(map,len);
|
||||
see_token(map, len);
|
||||
sum_update(map,len);
|
||||
}
|
||||
|
||||
if (fd != -1 && write_file(fd,map,len) != len) {
|
||||
rprintf(FERROR,"write failed on %s : %s\n",
|
||||
@@ -263,7 +270,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
|
||||
offset += len;
|
||||
}
|
||||
|
||||
end_progress();
|
||||
end_progress(total_size);
|
||||
|
||||
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
|
||||
rprintf(FERROR,"write failed on %s : %s\n",
|
||||
@@ -287,6 +294,8 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
|
||||
}
|
||||
|
||||
|
||||
/* main routine for receiver process. Receiver process runs on the
|
||||
same host as the generator process. */
|
||||
|
||||
int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
{
|
||||
@@ -302,16 +311,14 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
int phase=0;
|
||||
int recv_ok;
|
||||
extern struct stats stats;
|
||||
extern int preserve_perms;
|
||||
extern int delete_after;
|
||||
struct stats initial_stats;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
|
||||
}
|
||||
|
||||
if (recurse && delete_mode && !local_name && flist->count>0) {
|
||||
delete_files(flist);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
cleanup_disable();
|
||||
|
||||
@@ -358,14 +365,14 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
fnamecmp = fname;
|
||||
|
||||
/* open the file */
|
||||
fd1 = open(fnamecmp,O_RDONLY);
|
||||
fd1 = do_open(fnamecmp, O_RDONLY, 0);
|
||||
|
||||
if ((fd1 == -1) && (compare_dest != NULL)) {
|
||||
/* try the file at compare_dest instead */
|
||||
slprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",
|
||||
compare_dest,fname);
|
||||
fnamecmp = fnamecmpbuf;
|
||||
fd1 = open(fnamecmp,O_RDONLY);
|
||||
fd1 = do_open(fnamecmp, O_RDONLY, 0);
|
||||
}
|
||||
|
||||
if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
|
||||
@@ -382,10 +389,17 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && !preserve_perms) {
|
||||
/* if the file exists already and we aren't perserving
|
||||
presmissions then act as though the remote end sent
|
||||
us the file permissions we already have */
|
||||
file->mode = st.st_mode;
|
||||
}
|
||||
|
||||
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",fnamecmp,(int)st.st_size);
|
||||
rprintf(FINFO,"recv mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
|
||||
} else {
|
||||
buf = NULL;
|
||||
}
|
||||
@@ -417,6 +431,9 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
|
||||
file->mode & INITACCESSPERMS);
|
||||
|
||||
/* in most cases parent directories will already exist
|
||||
because their information should have been previously
|
||||
transferred, but that may not be the case with -R */
|
||||
if (fd2 == -1 && relative_paths && errno == ENOENT &&
|
||||
create_directory_path(fnametmp) == 0) {
|
||||
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
|
||||
@@ -453,7 +470,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
finish_transfer(fname, fnametmp, file);
|
||||
|
||||
cleanup_disable();
|
||||
|
||||
|
||||
if (!recv_ok) {
|
||||
if (csum_length == SUM_LENGTH) {
|
||||
rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
|
||||
@@ -466,6 +483,12 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
}
|
||||
}
|
||||
|
||||
if (delete_after) {
|
||||
if (recurse && delete_mode && !local_name && flist->count>0) {
|
||||
delete_files(flist);
|
||||
}
|
||||
}
|
||||
|
||||
if (preserve_hard_links)
|
||||
do_hard_links(flist);
|
||||
|
||||
@@ -474,7 +497,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
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);
|
||||
recv_generator(local_name?local_name:f_name(file),flist,i,-1);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
|
||||
44
rsync.c
44
rsync.c
@@ -30,7 +30,6 @@ extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
extern int preserve_perms;
|
||||
extern int make_backups;
|
||||
extern char *backup_suffix;
|
||||
|
||||
|
||||
/*
|
||||
@@ -57,8 +56,6 @@ int delete_file(char *fname)
|
||||
int ret;
|
||||
extern int recurse;
|
||||
|
||||
if (robust_unlink(fname) == 0 || errno == ENOENT) return 0;
|
||||
|
||||
#if SUPPORT_LINKS
|
||||
ret = do_lstat(fname, &st);
|
||||
#else
|
||||
@@ -70,6 +67,7 @@ int delete_file(char *fname)
|
||||
}
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
if (robust_unlink(fname) == 0 || errno == ENOENT) return 0;
|
||||
rprintf(FERROR,"unlink(%s) : %s\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
@@ -153,7 +151,6 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
int updated = 0;
|
||||
STRUCT_STAT st2;
|
||||
int change_uid, change_gid;
|
||||
extern int am_daemon;
|
||||
|
||||
if (dry_run) return 0;
|
||||
|
||||
@@ -180,7 +177,7 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
}
|
||||
|
||||
change_uid = am_root && preserve_uid && st->st_uid != file->uid;
|
||||
change_gid = !am_daemon && preserve_gid && file->gid != (gid_t) -1 && \
|
||||
change_gid = preserve_gid && file->gid != (gid_t) -1 && \
|
||||
st->st_gid != file->gid;
|
||||
if (change_gid && !am_root) {
|
||||
/* enforce bsd-style group semantics: non-root can only
|
||||
@@ -196,19 +193,20 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
rprintf(FERROR,"chown %s : %s\n", fname,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
/* a lchown had been done - we have to re-stat if the
|
||||
destination had the setuid or setgid bits set due
|
||||
to the side effect of the chown call */
|
||||
if (st->st_mode & (S_ISUID | S_ISGID)) {
|
||||
link_stat(fname, st);
|
||||
}
|
||||
updated = 1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CHMOD
|
||||
if (!S_ISLNK(st->st_mode)) {
|
||||
int file_mode;
|
||||
if (preserve_perms)
|
||||
file_mode = file->mode;
|
||||
else
|
||||
file_mode = file->mode & ACCESSPERMS;
|
||||
if (st->st_mode != file->mode) {
|
||||
updated = 1;
|
||||
if (do_chmod(fname,file_mode) != 0) {
|
||||
if (do_chmod(fname,file->mode) != 0) {
|
||||
rprintf(FERROR,"failed to set permissions on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
return 0;
|
||||
@@ -232,27 +230,6 @@ void sig_int(void)
|
||||
exit_cleanup(RERR_SIGNAL);
|
||||
}
|
||||
|
||||
int make_backup(char *fname)
|
||||
{
|
||||
char fnamebak[MAXPATHLEN];
|
||||
if (strlen(fname) + strlen(backup_suffix) > (MAXPATHLEN-1)) {
|
||||
rprintf(FERROR,"backup filename too long\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
slprintf(fnamebak,sizeof(fnamebak),"%s%s",fname,backup_suffix);
|
||||
if (do_rename(fname,fnamebak) != 0) {
|
||||
/* cygwin (at least version b19) reports EINVAL */
|
||||
if (errno != ENOENT && errno != EINVAL) {
|
||||
rprintf(FERROR,"rename %s %s : %s\n",fname,fnamebak,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
} else if (verbose > 1) {
|
||||
rprintf(FINFO,"backed up %s to %s\n",fname,fnamebak);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* finish off a file transfer, renaming the file and setting the permissions
|
||||
and ownership */
|
||||
@@ -281,6 +258,3 @@ void finish_transfer(char *fname, char *fnametmp, struct file_struct *file)
|
||||
set_perms(fname,file,NULL,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
31
rsync.h
31
rsync.h
@@ -47,8 +47,8 @@
|
||||
#define SAME_TIME (1<<7)
|
||||
|
||||
/* update this if you make incompatible changes */
|
||||
#define PROTOCOL_VERSION 20
|
||||
#define MIN_PROTOCOL_VERSION 11
|
||||
#define PROTOCOL_VERSION 24
|
||||
#define MIN_PROTOCOL_VERSION 15
|
||||
#define MAX_PROTOCOL_VERSION 30
|
||||
|
||||
#define RSYNC_PORT 873
|
||||
@@ -58,14 +58,12 @@
|
||||
#define CHUNK_SIZE (32*1024)
|
||||
#define MAX_MAP_SIZE (256*1024)
|
||||
#define IO_BUFFER_SIZE (4092)
|
||||
#define MAX_READ_BUFFER (1024*1024)
|
||||
|
||||
#define MAX_ARGS 1000
|
||||
|
||||
#define MPLEX_BASE 7
|
||||
#define FERROR 1
|
||||
#define FINFO 2
|
||||
#define FLOG 3
|
||||
|
||||
enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3};
|
||||
|
||||
#include "errcode.h"
|
||||
|
||||
@@ -307,10 +305,20 @@ struct file_struct {
|
||||
};
|
||||
|
||||
|
||||
#define ARENA_SIZE (32 * 1024)
|
||||
|
||||
struct string_area {
|
||||
char *base;
|
||||
char *end;
|
||||
char *current;
|
||||
struct string_area *next;
|
||||
};
|
||||
|
||||
struct file_list {
|
||||
int count;
|
||||
int malloced;
|
||||
struct file_struct **files;
|
||||
struct string_area *string_area;
|
||||
};
|
||||
|
||||
struct sum_buf {
|
||||
@@ -459,6 +467,15 @@ extern int errno;
|
||||
#define S_ISREG(mode) (((mode) & (_S_IFMT)) == (_S_IFREG))
|
||||
#endif
|
||||
|
||||
/* work out what fcntl flag to use for non-blocking */
|
||||
#ifdef O_NONBLOCK
|
||||
# define NONBLOCK_FLAG O_NONBLOCK
|
||||
#elif defined(SYSV)
|
||||
# define NONBLOCK_FLAG O_NDELAY
|
||||
#else
|
||||
# define NONBLOCK_FLAG FNDELAY
|
||||
#endif
|
||||
|
||||
|
||||
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) || S_ISFIFO(mode))
|
||||
|
||||
@@ -474,7 +491,7 @@ extern int errno;
|
||||
#define NS(s) ((s)?(s):"<NULL>")
|
||||
|
||||
/* use magic gcc attributes to catch format errors */
|
||||
void rprintf(int , const char *, ...)
|
||||
void rprintf(enum logcode , const char *, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((format (printf, 2, 3)))
|
||||
#endif
|
||||
|
||||
146
rsync.yo
146
rsync.yo
@@ -139,6 +139,11 @@ It is also possible to use rsync without using rsh or ssh as the
|
||||
transport. In this case you will connect to a remote rsync server
|
||||
running on TCP port 873.
|
||||
|
||||
You may establish the connetcion via a web proxy by setting the
|
||||
environment variable RSYNC_PROXY to a hostname:port pair pointing to
|
||||
your web proxy. Note that your web proxy must allow proxying to port
|
||||
873, this must be configured in your proxy servers ruleset.
|
||||
|
||||
Using rsync in this way is the same as using it with rsh or ssh except
|
||||
that:
|
||||
|
||||
@@ -211,17 +216,6 @@ Here is a short summary of the options available in rsync. Please refer
|
||||
to the detailed description below for a complete description.
|
||||
|
||||
verb(
|
||||
Usage: rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST
|
||||
or rsync [OPTION]... [USER@]HOST:SRC DEST
|
||||
or rsync [OPTION]... SRC [SRC]... DEST
|
||||
or rsync [OPTION]... [USER@]HOST::SRC [DEST]
|
||||
or rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST
|
||||
or rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]
|
||||
SRC on single-colon remote HOST will be expanded by remote shell
|
||||
SRC on server remote HOST may contain shell wildcards or multiple
|
||||
sources separated by space as long as they have same top-level
|
||||
|
||||
Options
|
||||
-v, --verbose increase verbosity
|
||||
-q, --quiet decrease verbosity
|
||||
-c, --checksum always checksum
|
||||
@@ -229,6 +223,7 @@ Options
|
||||
-r, --recursive recurse into directories
|
||||
-R, --relative use relative path names
|
||||
-b, --backup make backups (default ~ suffix)
|
||||
--backup-dir=DIR put backups in the specified directory
|
||||
--suffix=SUFFIX override backup suffix
|
||||
-u, --update update only (don't overwrite newer files)
|
||||
-l, --links preserve soft links
|
||||
@@ -249,8 +244,12 @@ Options
|
||||
-e, --rsh=COMMAND specify rsh replacement
|
||||
--rsync-path=PATH specify path to rsync on the remote machine
|
||||
-C, --cvs-exclude auto ignore files in the same way CVS does
|
||||
--existing only update files that already exist
|
||||
--delete delete files that don't exist on the sending side
|
||||
--delete-excluded also delete excluded files on the receiving side
|
||||
--delete-after delete after transferring, not before
|
||||
--ignore-errors delete even if there are IO errors
|
||||
--max-delete=NUM don't delete more than NUM files
|
||||
--partial keep partially transferred files
|
||||
--force force deletion of directories even if not empty
|
||||
--numeric-ids don't map uid/gid values by user/group name
|
||||
@@ -259,6 +258,7 @@ Options
|
||||
--size-only only use file size when determining if a file should be transferred
|
||||
-T --temp-dir=DIR create temporary files in directory DIR
|
||||
--compare-dest=DIR also compare destination files relative to DIR
|
||||
-P equivalent to --partial --progress
|
||||
-z, --compress compress file data
|
||||
--exclude=PATTERN exclude files matching PATTERN
|
||||
--exclude-from=FILE exclude patterns listed in FILE
|
||||
@@ -266,12 +266,15 @@ Options
|
||||
--include-from=FILE don't exclude patterns listed in FILE
|
||||
--version print version number
|
||||
--daemon run as a rsync daemon
|
||||
--address bind to the specified address
|
||||
--config=FILE specify alternate rsyncd.conf file
|
||||
--port=PORT specify alternate rsyncd port number
|
||||
--blocking-io use blocking IO for the remote shell
|
||||
--stats give some file transfer stats
|
||||
--progress show progress during transfer
|
||||
--log-format=FORMAT log file transfers using specified format
|
||||
--password-file=FILE get password from FILE
|
||||
--bwlimit=KBPS limit I/O bandwidth, KBytes per second
|
||||
-h, --help show this help screen
|
||||
)
|
||||
|
||||
@@ -306,7 +309,7 @@ dit(bf(-I, --ignore-times)) Normally rsync will skip any files that are
|
||||
already the same length and have the same time-stamp. This option turns
|
||||
off this behavior.
|
||||
|
||||
dit(bf(-I, --size-only)) Normally rsync will skip any files that are
|
||||
dit(bf(--size-only)) Normally rsync will skip any files that are
|
||||
already the same length and have the same time-stamp. With the
|
||||
--size-only option files will be skipped if they have the same size,
|
||||
regardless of timestamp. This is useful when starting to use rsync
|
||||
@@ -319,13 +322,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 -rlptg. It is a quick way
|
||||
dit(bf(-a, --archive)) This is equivalent to -rlptgoD. It is a quick way
|
||||
of saying you want recursion and want to preserve everything.
|
||||
|
||||
Note: if the user launching rsync is root then the -o (preserve
|
||||
uid) and -D (preserve devices) options are also implied.
|
||||
|
||||
dit(bf(-r, --recursive)) This tells rsync to copy directories recursively.
|
||||
dit(bf(-r, --recursive)) This tells rsync to copy directories
|
||||
recursively. If you don't specify this then rsync won't copy
|
||||
directories at all.
|
||||
|
||||
dit(bf(-R, --relative)) Use relative paths. This means that the full path
|
||||
names specified on the command line are sent to the server rather than
|
||||
@@ -347,6 +349,10 @@ dit(bf(-b, --backup)) With this option preexisting destination files are
|
||||
renamed with a ~ extension as each file is transferred. You can
|
||||
control the backup suffix using the --suffix option.
|
||||
|
||||
dit(bf(--backup-dir=DIR)) In combination with the --backup option, this
|
||||
tells rsync to store all backups in the specified directory. This is
|
||||
very useful for incremental backups.
|
||||
|
||||
dit(bf(--suffix=SUFFIX)) This option allows you to override the default
|
||||
backup suffix used with the -b option. The default is a ~.
|
||||
|
||||
@@ -384,12 +390,6 @@ dit(bf(-W, --whole-file)) With this option the incremental rsync algorithm
|
||||
is not used and the whole file is sent as-is instead. This may be
|
||||
useful when using rsync with a local machine.
|
||||
|
||||
dit(bf(--partial)) By default, rsync will delete any partially
|
||||
transferred file if the transfer is interrupted. In some circumstances
|
||||
it is more desirable to keep partially transferred files. Using the
|
||||
--partial option tells rsync to keep the partial file which should
|
||||
make a subsequent transfer of the rest of the file much faster.
|
||||
|
||||
dit(bf(-p, --perms)) This option causes rsync to update the remote
|
||||
permissions to be the same as the local permissions.
|
||||
|
||||
@@ -430,23 +430,23 @@ dit(bf(-x, --one-file-system)) This tells rsync not to cross filesystem
|
||||
boundaries when recursing. This is useful for transferring the
|
||||
contents of only one filesystem.
|
||||
|
||||
dit(bf(--existing)) This tells rsync not to create any new files -
|
||||
only update files that already exist on the destination.
|
||||
|
||||
dit(bf(--max-delete=NUM)) This tells rsync not to delete more than NUM
|
||||
files or directories. This is useful when mirroring very large trees
|
||||
to prevent disasters.
|
||||
|
||||
dit(bf(--delete)) This tells rsync to delete any files on the receiving
|
||||
side that aren't on the sending side. Files that are excluded from
|
||||
transfer are excluded from being deleted unless you use --delete-excluded.
|
||||
|
||||
This option has no effect if directory recursion is not selected.
|
||||
|
||||
This option can be dangerous if used incorrectly! It is a very good idea
|
||||
to run first using the dry run option (-n) to see what files would be
|
||||
deleted to make sure important files aren't listed.
|
||||
|
||||
rsync 1.6.4 changed the behavior of --delete to make it less
|
||||
dangerous. rsync now only scans directories on the receiving side
|
||||
that are explicitly transferred from the sending side. Only files in
|
||||
these directories are deleted.
|
||||
|
||||
Still, it is probably easy to get burnt with this option. The moral
|
||||
of the story is to use the -n option until you get used to the
|
||||
behavior of --delete.
|
||||
|
||||
If the sending side detects any IO errors then the deletion of any
|
||||
files at the destination will be automatically disabled. This is to
|
||||
prevent temporary filesystem failures (such as NFS errors) on the
|
||||
@@ -457,6 +457,11 @@ dit(bf(--delete-excluded)) In addition to deleting the files on the
|
||||
receiving side that are not on the sending side, this tells rsync to also
|
||||
delete any files on the receiving side that are excluded (see --exclude).
|
||||
|
||||
dit(bf(--delete-after)) By default rsync does file deletions before
|
||||
transferring files to try to ensure that there is sufficient space on
|
||||
the receiving filesystem. If you want to delete after transferring
|
||||
then use the --delete-after switch.
|
||||
|
||||
dit(bf(--force)) This options tells rsync to delete directories even if
|
||||
they are not empty. This applies to both the --delete option and to
|
||||
cases where rsync tries to copy a normal file but the destination
|
||||
@@ -477,7 +482,9 @@ You can also choose the remote shell program using the RSYNC_RSH
|
||||
environment variable.
|
||||
|
||||
dit(bf(--rsync-path=PATH)) Use this to specify the path to the copy of
|
||||
rsync on the remote machine. Useful when it's not in your path.
|
||||
rsync on the remote machine. Useful when it's not in your path. Note
|
||||
that this is the full path to the binary, not just the directory that
|
||||
the binary is in.
|
||||
|
||||
dit(bf(--exclude=PATTERN)) This option allows you to selectively exclude
|
||||
certain files from the list of files to be transferred. This is most
|
||||
@@ -592,6 +599,12 @@ config file (/etc/rsyncd.conf) on each connect made by a client and
|
||||
respond to requests accordingly. See the rsyncd.conf(5) man page for more
|
||||
details.
|
||||
|
||||
dit(bf(--address)) By default rsync will bind to the wildcard address
|
||||
when run as a daemon with the --daemon option or when connecting to a
|
||||
rsync server. The --address option allows you to specify a specific IP
|
||||
address (or hostname) to bind to. This makes virtual hosting possible
|
||||
in conjunction with the --config option.
|
||||
|
||||
dit(bf(--config=FILE)) This specifies an alternate config file than
|
||||
the default /etc/rsyncd.conf. This is only relevant when --daemon is
|
||||
specified.
|
||||
@@ -599,6 +612,11 @@ specified.
|
||||
dit(bf(--port=PORT)) This specifies an alternate TCP port number to use
|
||||
rather than the default port 873.
|
||||
|
||||
dit(bf(--blocking-io)) This specifies whether rsync will use blocking
|
||||
IO when launching a remote shell transport. You may find this is
|
||||
needed for some remote shells that can't handle the default
|
||||
non-blocking IO.
|
||||
|
||||
dit(bf(--log-format=FORMAT)) This allows you to specify exactly what the
|
||||
rsync client logs to stdout on a per-file basis. The log format is
|
||||
specified using the same format conventions as the log format option in
|
||||
@@ -608,15 +626,37 @@ 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.
|
||||
|
||||
dit(bf(--partial)) By default, rsync will delete any partially
|
||||
transferred file if the transfer is interrupted. In some circumstances
|
||||
it is more desirable to keep partially transferred files. Using the
|
||||
--partial option tells rsync to keep the partial file which should
|
||||
make a subsequent transfer of the rest of the file much faster.
|
||||
|
||||
dit(bf(--progress)) This option tells rsync to print information
|
||||
showing the progress of the transfer. This gives a bored user
|
||||
something to watch.
|
||||
|
||||
This option is normally combined with -v. Using this option without
|
||||
the -v option will produce weird results on your display.
|
||||
|
||||
dit(bf(-P)) The -P option is equivalent to --partial --progress. I
|
||||
found myself typing that combination quite often so I created an
|
||||
option to make it easier.
|
||||
|
||||
dit(bf(--password-file)) This option allows you to provide a password
|
||||
in a file for accessing a remote rsync server. Note that this option
|
||||
is only useful when accessing a rsync server using the built in
|
||||
transport, not when using a remote shell as the transport. The file
|
||||
must not be world readable.
|
||||
must not be world readable. It should contain just the password as a
|
||||
single line.
|
||||
|
||||
dit(bf(--bwlimit=KBPS)) This option allows you to specify a maximum
|
||||
transfer rate in kilobytes per second. This option is most effective when
|
||||
using rsync with large files (several megabytes and up). Due to the nature
|
||||
of rsync transfers, blocks of data are sent, then if rsync determines the
|
||||
transfer was too fast, it will wait before sending the next data block. The
|
||||
result is an average transfer rate equalling the specified limit. A value
|
||||
of zero specifies no limit.
|
||||
|
||||
enddit()
|
||||
|
||||
@@ -633,14 +673,24 @@ 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.
|
||||
|
||||
Note that when used with -r (which is implied by -a), every subcomponent of
|
||||
every path is visited from top down, so include/exclude patterns get
|
||||
applied recursively to each subcomponent.
|
||||
|
||||
Note also that the --include and --exclude options take one pattern
|
||||
each. To add multiple patterns use the --include-from and
|
||||
--exclude-from options or multiple --include and --exclude options.
|
||||
|
||||
The patterns 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.
|
||||
the filename. Thus "/foo" would match a file called "foo" at the base of
|
||||
the tree. On the other hand, "foo" would match any file called "foo"
|
||||
anywhere in the tree because the algorithm is applied recursively from
|
||||
top down; it behaves as if each path component gets a turn at being the
|
||||
end of the file name.
|
||||
|
||||
it() if the pattern ends with a / then it will only match a
|
||||
directory, not a file, link or device.
|
||||
@@ -649,12 +699,15 @@ itemize(
|
||||
*?[ then expression matching is applied using the shell filename
|
||||
matching rules. Otherwise a simple string match is used.
|
||||
|
||||
it() if the pattern includes a double asterisk "**" then all wildcards in
|
||||
the pattern will match slashes, otherwise they will stop at slashes.
|
||||
|
||||
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. Furthermore, if
|
||||
the pattern includes a double asterisk "**" then all wildcards in
|
||||
the pattern will match slashes, otherwise they will stop at slashes.
|
||||
only against the final component of the filename. Again, remember
|
||||
that the algorithm is applied recursively so "full filename" can
|
||||
actually be any portion of a path.
|
||||
|
||||
it() if the pattern starts with "+ " (a plus followed by a space)
|
||||
then it is always considered an include pattern, even if specified as
|
||||
@@ -671,7 +724,14 @@ itemize(
|
||||
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:
|
||||
If you end an exclude list with --exclude '*', note that since the
|
||||
algorithm is applied recursively that unless you explicitly include
|
||||
parent directories of files you want to include then the algorithm
|
||||
will stop at the parent directories and never see the files below
|
||||
them. To include all directories, use --include '*/' before the
|
||||
--exclude '*'.
|
||||
|
||||
Here are some exclude/include examples:
|
||||
|
||||
itemize(
|
||||
it() --exclude "*.o" would exclude all filenames matching *.o
|
||||
@@ -723,6 +783,10 @@ 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_PROXY)) The RSYNC_PROXY environment variable allows you to
|
||||
redirect your rsync client to use a web proxy when connecting to a
|
||||
rsync daemon. You should set RSYNC_PROXY to a hostname:port pair.
|
||||
|
||||
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
|
||||
|
||||
@@ -58,8 +58,9 @@ and a single line something like this to /etc/inetd.conf:
|
||||
|
||||
quote(rsync stream tcp nowait root /usr/bin/rsync rsyncd --daemon)
|
||||
|
||||
You will then need to send inetd a HUP signal to tell it to reread its
|
||||
config file.
|
||||
Replace "/usr/bin/rsync" with the path to where you have rsync installed on
|
||||
your system. You will then need to send inetd a HUP signal to tell it to
|
||||
reread its config file.
|
||||
|
||||
Note that you should not send the rsync server a HUP signal to force
|
||||
it to reread the tt(/etc/rsyncd.conf). The file is re-read on each client
|
||||
@@ -127,8 +128,11 @@ dit(bf(use chroot)) If "use chroot" is true, the rsync server will chroot
|
||||
to the "path" before starting the file transfer with the client. This has
|
||||
the advantage of extra protection against possible implementation security
|
||||
holes, but it has the disadvantages of requiring super-user privileges and
|
||||
of not being able to follow symbolic links outside of the new root path.
|
||||
The default is to use chroot.
|
||||
of not being able to follow symbolic links outside of the new root path
|
||||
when reading. For writing when "use chroot" is false, for security reasons
|
||||
symlinks may only be relative paths pointing to other files within the
|
||||
root path, and leading slashes are removed from absolute paths. The
|
||||
default for "use chroot" is true.
|
||||
|
||||
dit(bf(max connections)) The "max connections" option allows you to
|
||||
specify the maximum number of simultaneous connections you will allow
|
||||
@@ -163,10 +167,12 @@ was run as root. This complements the "uid" option. The default is the
|
||||
group "nobody".
|
||||
|
||||
dit(bf(exclude)) The "exclude" option allows you to specify a space
|
||||
separated list of patterns to add to the exclude list. This is equivalent
|
||||
to the client specifying these patterns with the --exclude option. Only
|
||||
one "exclude" option may be specified, but you can use "-" and "+" before
|
||||
patterns to specify exclude/include.
|
||||
separated list of patterns to add to the exclude list. This is
|
||||
equivalent to the client specifying these patterns with the --exclude
|
||||
option except that the exclude list is not passed to the client and
|
||||
thus only apply on the server. Only one "exclude" option may be
|
||||
specified, but you can use "-" and "+" before patterns to specify
|
||||
exclude/include.
|
||||
|
||||
Note that this option is not designed with strong security in
|
||||
mind, it is quite possible that a client may find a way to bypass this
|
||||
@@ -177,8 +183,9 @@ file permissions.
|
||||
dit(bf(exclude from)) The "exclude from" option specifies a filename
|
||||
on the server that contains exclude patterns, one per line. This is
|
||||
equivalent to the client specifying the --exclude-from option with a
|
||||
equivalent file. See also the note about security for the exclude
|
||||
option above.
|
||||
equivalent file except that the resulting exclude patterns are not
|
||||
passed to the client and thus only apply on the server. See also the
|
||||
note about security for the exclude option above.
|
||||
|
||||
dit(bf(include)) The "include" option allows you to specify a space
|
||||
separated list of patterns which rsync should not exclude. This is
|
||||
@@ -270,6 +277,14 @@ rejected. See the "hosts allow" option for more information.
|
||||
|
||||
The default is no "hosts deny" option, which means all hosts can connect.
|
||||
|
||||
dit(bf(ignore errors)) The "ignore errors" option tells rsyncd to
|
||||
ignore IO errors on the server when deciding whether to run the delete
|
||||
phase of the transfer. Normally rsync skips the --delete step if any
|
||||
IO errors have occurred in order to prevent disasterous deletion due
|
||||
to a temporary resource shortage or other IO error. In some cases this
|
||||
test is counter productive so you can use this option to turn off this
|
||||
behaviour.
|
||||
|
||||
dit(bf(transfer logging)) The "transfer logging" option enables per-file
|
||||
logging of downloads and uploads in a format somewhat similar to that
|
||||
used by ftp daemons. If you want to customize the log formats look at
|
||||
@@ -330,7 +345,7 @@ The "dont compress" option takes a space separated list of
|
||||
case-insensitive wildcard patterns. Any source filename matching one
|
||||
of the patterns will not be compressed during transfer.
|
||||
|
||||
The default setting is verb(*.gz *.tgz *.zip *.z *.rpm *.deb)
|
||||
The default setting is verb(*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz)
|
||||
|
||||
enddit()
|
||||
|
||||
|
||||
10
sender.c
10
sender.c
@@ -70,8 +70,8 @@ static struct sum_struct *receive_sums(int f)
|
||||
offset += s->sums[i].len;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"chunk[%d] len=%d offset=%d sum1=%08x\n",
|
||||
i,s->sums[i].len,(int)s->sums[i].offset,s->sums[i].sum1);
|
||||
rprintf(FINFO,"chunk[%d] len=%d offset=%.0f sum1=%08x\n",
|
||||
i,s->sums[i].len,(double)s->sums[i].offset,s->sums[i].sum1);
|
||||
}
|
||||
|
||||
s->flength = offset;
|
||||
@@ -160,7 +160,7 @@ void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
return;
|
||||
}
|
||||
|
||||
fd = open(fname,O_RDONLY);
|
||||
fd = do_open(fname, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"send_files failed to open %s: %s\n",
|
||||
@@ -185,8 +185,8 @@ void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files mapped %s of size %d\n",
|
||||
fname,(int)st.st_size);
|
||||
rprintf(FINFO,"send_files mapped %s of size %.0f\n",
|
||||
fname,(double)st.st_size);
|
||||
|
||||
write_int(f_out,i);
|
||||
|
||||
|
||||
167
socket.c
167
socket.c
@@ -23,38 +23,138 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
|
||||
/* establish a proxy connection on an open socket to a web roxy by using the CONNECT
|
||||
method */
|
||||
static int establish_proxy_connection(int fd, char *host, int port)
|
||||
{
|
||||
char buffer[1024];
|
||||
char *cp;
|
||||
|
||||
slprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
|
||||
if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) {
|
||||
rprintf(FERROR, "failed to write to proxy - %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (cp = buffer; cp < &buffer[sizeof(buffer) - 1]; cp++) {
|
||||
if (read(fd, cp, 1) != 1) {
|
||||
rprintf(FERROR, "failed to read from proxy\n");
|
||||
return -1;
|
||||
}
|
||||
if (*cp == '\n')
|
||||
break;
|
||||
}
|
||||
|
||||
if (*cp != '\n')
|
||||
cp++;
|
||||
*cp-- = '\0';
|
||||
if (*cp == '\r')
|
||||
*cp = '\0';
|
||||
if (strncmp(buffer, "HTTP/", 5) != 0) {
|
||||
rprintf(FERROR, "bad response from proxy - %s\n",
|
||||
buffer);
|
||||
return -1;
|
||||
}
|
||||
for (cp = &buffer[5]; isdigit(*cp) || (*cp == '.'); cp++)
|
||||
;
|
||||
while (*cp == ' ')
|
||||
cp++;
|
||||
if (*cp != '2') {
|
||||
rprintf(FERROR, "bad response from proxy - %s\n",
|
||||
buffer);
|
||||
return -1;
|
||||
}
|
||||
/* throw away the rest of the HTTP header */
|
||||
while (1) {
|
||||
for (cp = buffer; cp < &buffer[sizeof(buffer) - 1];
|
||||
cp++) {
|
||||
if (read(fd, cp, 1) != 1) {
|
||||
rprintf(FERROR, "failed to read from proxy\n");
|
||||
return -1;
|
||||
}
|
||||
if (*cp == '\n')
|
||||
break;
|
||||
}
|
||||
if ((cp > buffer) && (*cp == '\n'))
|
||||
cp--;
|
||||
if ((cp == buffer) && ((*cp == '\n') || (*cp == '\r')))
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* open a socket to a tcp remote host with the specified port
|
||||
based on code from Warren */
|
||||
int open_socket_out(char *host, int port)
|
||||
based on code from Warren
|
||||
proxy support by Stephen Rothwell */
|
||||
int open_socket_out(char *host, int port, struct in_addr *address)
|
||||
{
|
||||
int type = SOCK_STREAM;
|
||||
struct sockaddr_in sock_out;
|
||||
struct sockaddr_in sock;
|
||||
int res;
|
||||
struct hostent *hp;
|
||||
|
||||
char *h;
|
||||
unsigned p;
|
||||
int proxied = 0;
|
||||
char buffer[1024];
|
||||
char *cp;
|
||||
|
||||
/* if we have a RSYNC_PROXY env variable then redirect our connetcion via a web proxy
|
||||
at the given address. The format is hostname:port */
|
||||
h = getenv("RSYNC_PROXY");
|
||||
proxied = (h != NULL) && (*h != '\0');
|
||||
|
||||
if (proxied) {
|
||||
strlcpy(buffer, h, sizeof(buffer));
|
||||
cp = strchr(buffer, ':');
|
||||
if (cp == NULL) {
|
||||
rprintf(FERROR, "invalid proxy specification\n");
|
||||
return -1;
|
||||
}
|
||||
*cp++ = '\0';
|
||||
p = atoi(cp);
|
||||
h = buffer;
|
||||
} else {
|
||||
h = host;
|
||||
p = port;
|
||||
}
|
||||
|
||||
res = socket(PF_INET, type, 0);
|
||||
if (res == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
hp = gethostbyname(host);
|
||||
hp = gethostbyname(h);
|
||||
if (!hp) {
|
||||
rprintf(FERROR,"unknown host: %s\n", host);
|
||||
rprintf(FERROR,"unknown host: %s\n", h);
|
||||
close(res);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
|
||||
sock_out.sin_port = htons(port);
|
||||
sock_out.sin_port = htons(p);
|
||||
sock_out.sin_family = PF_INET;
|
||||
|
||||
if (address) {
|
||||
sock.sin_addr = *address;
|
||||
sock.sin_port = 0;
|
||||
sock.sin_family = hp->h_addrtype;
|
||||
bind(res, (struct sockaddr * ) &sock,sizeof(sock));
|
||||
}
|
||||
|
||||
if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
|
||||
rprintf(FERROR,"failed to connect to %s - %s\n", h, strerror(errno));
|
||||
close(res);
|
||||
rprintf(FERROR,"failed to connect to %s - %s\n", host, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_nonblocking(res);
|
||||
if (proxied && establish_proxy_connection(res, host, port) != 0) {
|
||||
close(res);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -63,7 +163,7 @@ int open_socket_out(char *host, int port)
|
||||
/****************************************************************************
|
||||
open a socket of the specified type, port and address for incoming data
|
||||
****************************************************************************/
|
||||
static int open_socket_in(int type, int port)
|
||||
static int open_socket_in(int type, int port, struct in_addr *address)
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in sock;
|
||||
@@ -87,7 +187,11 @@ static int open_socket_in(int type, int port)
|
||||
memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
|
||||
sock.sin_port = htons(port);
|
||||
sock.sin_family = hp->h_addrtype;
|
||||
sock.sin_addr.s_addr = INADDR_ANY;
|
||||
if (address) {
|
||||
sock.sin_addr = *address;
|
||||
} else {
|
||||
sock.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
res = socket(hp->h_addrtype, type, 0);
|
||||
if (res == -1) {
|
||||
rprintf(FERROR,"socket failed\n");
|
||||
@@ -121,9 +225,10 @@ int is_a_socket(int fd)
|
||||
void start_accept_loop(int port, int (*fn)(int ))
|
||||
{
|
||||
int s;
|
||||
extern struct in_addr socket_address;
|
||||
|
||||
/* open an incoming socket */
|
||||
s = open_socket_in(SOCK_STREAM, port);
|
||||
s = open_socket_in(SOCK_STREAM, port, &socket_address);
|
||||
if (s == -1)
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
|
||||
@@ -161,14 +266,12 @@ void start_accept_loop(int port, int (*fn)(int ))
|
||||
but I have had reports that on Digital Unix zombies
|
||||
are produced, so this ensures that they are reaped */
|
||||
#ifdef WNOHANG
|
||||
waitpid(-1, NULL, WNOHANG);
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||
#endif
|
||||
|
||||
if (fork()==0) {
|
||||
close(s);
|
||||
|
||||
set_nonblocking(fd);
|
||||
|
||||
_exit(fn(fd));
|
||||
}
|
||||
|
||||
@@ -386,3 +489,39 @@ char *client_name(int fd)
|
||||
|
||||
return name_buf;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
convert a string to an IP address. The string can be a name or
|
||||
dotted decimal number
|
||||
******************************************************************/
|
||||
struct in_addr *ip_address(const char *str)
|
||||
{
|
||||
static struct in_addr ret;
|
||||
struct hostent *hp;
|
||||
|
||||
/* try as an IP address */
|
||||
if (inet_aton(str, &ret) != 0) {
|
||||
return &ret;
|
||||
}
|
||||
|
||||
/* otherwise assume it's a network name of some sort and use
|
||||
gethostbyname */
|
||||
if ((hp = gethostbyname(str)) == 0) {
|
||||
rprintf(FERROR, "gethostbyname: Unknown host. %s\n",str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (hp->h_addr == NULL) {
|
||||
rprintf(FERROR, "gethostbyname: host address is invalid for host %s\n",str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (hp->h_length > sizeof(ret)) {
|
||||
rprintf(FERROR, "gethostbyname: host address is too large\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(&ret.s_addr, hp->h_addr, hp->h_length);
|
||||
|
||||
return(&ret);
|
||||
}
|
||||
|
||||
@@ -76,12 +76,17 @@ int do_rmdir(char *pathname)
|
||||
|
||||
int do_open(char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
if (dry_run) return -1;
|
||||
if (flags != O_RDONLY) {
|
||||
if (dry_run) return -1;
|
||||
CHECK_RO
|
||||
}
|
||||
#ifdef O_BINARY
|
||||
/* for Windows */
|
||||
flags |= O_BINARY;
|
||||
#endif
|
||||
CHECK_RO
|
||||
/* some systems can't handle a double / */
|
||||
if (pathname[0] == '/' && pathname[1] == '/') pathname++;
|
||||
|
||||
return open(pathname, flags, mode);
|
||||
}
|
||||
|
||||
|
||||
111
test.sh
111
test.sh
@@ -1,7 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright (C) 1998 Philip Hands <http://www.hands.com/~phil/>
|
||||
# Copyright (C) 1998,1999 Philip Hands <phil@hands.com>
|
||||
#
|
||||
# This program is distributable under the terms of the GNU GPL (see COPYING)
|
||||
#
|
||||
@@ -10,7 +9,15 @@
|
||||
#
|
||||
#
|
||||
|
||||
cat <<EOF
|
||||
# check if we are running under debian-test, and change behaviour to suit
|
||||
if test -n "${DEBIANTEST_LIB}" ; then
|
||||
# make sure rsync is installed
|
||||
test -e /usr/bin/rsync || exit 0
|
||||
|
||||
. ${DEBIANTEST_LIB}/functions.sh
|
||||
Debian=1
|
||||
else
|
||||
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
|
||||
@@ -18,7 +25,19 @@ do not indicate a problem with rsync.
|
||||
|
||||
EOF
|
||||
|
||||
export PATH=.:$PATH
|
||||
RSYNC=`pwd`/rsync
|
||||
|
||||
runtest() {
|
||||
echo -n "Test $1: "
|
||||
eval "$2"
|
||||
}
|
||||
printmsg() {
|
||||
echo ""
|
||||
echo "**** ${1}^G ****"
|
||||
echo ""
|
||||
}
|
||||
fi
|
||||
|
||||
TMP=/tmp/rsync-test.$$
|
||||
FROM=${TMP}/from
|
||||
TO=${TMP}/to
|
||||
@@ -38,34 +57,53 @@ ln -s nolf ${FROM}/nolf-symlink
|
||||
cat /etc/inittab /etc/services /etc/resolv.conf > ${FROM}/${F1}
|
||||
mkdir ${FROM}/dir
|
||||
cp ${FROM}/${F1} ${FROM}/dir
|
||||
mkdir ${FROM}/dir/subdir
|
||||
mkdir ${FROM}/dir/subdir/subsubdir
|
||||
ls -ltr /etc > ${FROM}/dir/subdir/subsubdir/etc-ltr-list
|
||||
mkdir ${FROM}/dir/subdir/subsubdir2
|
||||
ls -lt /bin > ${FROM}/dir/subdir/subsubdir2/bin-lt-list
|
||||
|
||||
checkit() {
|
||||
echo -n "Test $4: $5:"
|
||||
log=${LOG}.$4
|
||||
testnum=`expr 0${testnum} + 1`
|
||||
log=${LOG}.${testnum}
|
||||
failed=
|
||||
echo "Running: \"$1\"" >${log}
|
||||
echo "">>${log}
|
||||
eval "$1 || failed=YES" >>${log} 2>&1
|
||||
|
||||
eval "$1" >>${log} 2>&1
|
||||
status=$?
|
||||
if [ $status != 0 ]; then
|
||||
failed="YES";
|
||||
fi
|
||||
echo "-------------">>${log}
|
||||
echo "check how the files compare with diff:">>${log}
|
||||
echo "">>${log}
|
||||
diff -ur $2 $3 >>${log} || failed=YES
|
||||
diff -ur $2 $3 >>${log} 2>&1 || failed=YES
|
||||
echo "-------------">>${log}
|
||||
echo "check how the directory listings compare with diff:">>${log}
|
||||
echo "">>${log}
|
||||
ls -la $2 > ${TMP}/ls-from
|
||||
ls -la $3 > ${TMP}/ls-to
|
||||
diff -u ${TMP}/ls-from ${TMP}/ls-to >>${log} || failed=YES
|
||||
( cd $2 ; ls -laR ) > ${TMP}/ls-from 2>>${log}
|
||||
( cd $3 ; ls -laR ) > ${TMP}/ls-to 2>>${log}
|
||||
diff -u ${TMP}/ls-from ${TMP}/ls-to >>${log} 2>&1 || failed=YES
|
||||
if [ -z "${failed}" ] ; then
|
||||
echo " done."
|
||||
test -z "${Debian}" && echo " done."
|
||||
rm $log
|
||||
return 0
|
||||
else
|
||||
echo " FAILED."
|
||||
if test -n "${Debian}" ; then
|
||||
cat ${log}
|
||||
rm ${log}
|
||||
else
|
||||
echo " FAILED (test # ${testnum} status=$status)."
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
checkforlogs() {
|
||||
# skip it if we're under debian-test
|
||||
if test -n "${Debian}" ; then return 0 ; fi
|
||||
|
||||
if [ -f $1 ] ; then
|
||||
cat <<EOF
|
||||
|
||||
@@ -87,44 +125,45 @@ EOF
|
||||
|
||||
# Main script starts here
|
||||
|
||||
checkit "rsync -av ${FROM}/ ${TO}" ${FROM}/ ${TO} \
|
||||
1 "basic operation"
|
||||
runtest "basic operation" 'checkit "$RSYNC -av ${FROM}/ ${TO}" ${FROM}/ ${TO}'
|
||||
|
||||
ln ${FROM}/pslist ${FROM}/dir
|
||||
checkit "rsync -avH ${FROM}/ ${TO}" ${FROM}/ ${TO} \
|
||||
2 "hard links"
|
||||
runtest "hard links" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
|
||||
|
||||
rm ${TO}/${F1}
|
||||
checkit "rsync -avH ${FROM}/ ${TO}" ${FROM}/ ${TO} \
|
||||
3 "one file"
|
||||
runtest "one file" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
|
||||
|
||||
echo "extra line" >> ${TO}/${F1}
|
||||
checkit "rsync -avH ${FROM}/ ${TO}" ${FROM}/ ${TO} \
|
||||
4 "extra data"
|
||||
runtest "extra data" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
|
||||
|
||||
cp ${FROM}/${F1} ${TO}/ThisShouldGo
|
||||
checkit "rsync --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO} \
|
||||
5 " --delete"
|
||||
runtest " --delete" 'checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
|
||||
|
||||
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"
|
||||
runtest "long paths" 'checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
|
||||
|
||||
if type ssh >/dev/null ; then
|
||||
rm -rf ${TO}
|
||||
checkit "rsync -avH -e ssh ${FROM}/ localhost:${TO}" ${FROM}/ ${TO} \
|
||||
7 "ssh: basic test"
|
||||
if type ssh >/dev/null 2>&1; then
|
||||
if [ "`ssh -o'BatchMode yes' localhost echo yes 2>/dev/null`" = "yes" ]; then
|
||||
rm -rf ${TO}
|
||||
runtest "ssh: basic test" 'checkit "$RSYNC -avH -e ssh --rsync-path=$RSYNC ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}'
|
||||
|
||||
mv ${TO}/${F1} ${TO}/ThisShouldGo
|
||||
checkit "rsync --delete -avH -e ssh ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}\
|
||||
8 "ssh: renamed file"
|
||||
mv ${TO}/${F1} ${TO}/ThisShouldGo
|
||||
runtest "ssh: renamed file" 'checkit "$RSYNC --delete -avH -e ssh --rsync-path=$RSYNC ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}'
|
||||
else
|
||||
printmsg "Skipping SSH tests because ssh conection to localhost not authorised"
|
||||
fi
|
||||
else
|
||||
echo ""
|
||||
echo "**** Skipping SSH tests because ssh is not in the path ****"
|
||||
echo ""
|
||||
printmsg "Skipping SSH tests because ssh is not in the path"
|
||||
fi
|
||||
|
||||
rm -rf ${TO}
|
||||
mkdir -p ${FROM}2/dir/subdir
|
||||
cp -a ${FROM}/dir/subdir/subsubdir ${FROM}2/dir/subdir
|
||||
cp ${FROM}/dir/* ${FROM}2/dir 2>/dev/null
|
||||
runtest "excludes" 'checkit "$RSYNC -vv -Hlrt --delete --include /dir/ --include /dir/\* --include /dir/\*/subsubdir --include /dir/\*/subsubdir/\*\* --exclude \*\* ${FROM}/dir ${TO}" ${FROM}2/ ${TO}'
|
||||
rm -r ${FROM}2
|
||||
|
||||
checkforlogs ${LOG}.?
|
||||
|
||||
260
util.c
260
util.c
@@ -26,42 +26,81 @@
|
||||
|
||||
extern int verbose;
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Set a fd into nonblocking mode. Uses POSIX O_NONBLOCK if available,
|
||||
else
|
||||
if SYSV use O_NDELAY
|
||||
if BSD use FNDELAY
|
||||
Set a fd into nonblocking mode
|
||||
****************************************************************************/
|
||||
int set_nonblocking(int fd)
|
||||
void set_nonblocking(int fd)
|
||||
{
|
||||
int val;
|
||||
#ifdef O_NONBLOCK
|
||||
#define FLAG_TO_SET O_NONBLOCK
|
||||
#else
|
||||
#ifdef SYSV
|
||||
#define FLAG_TO_SET O_NDELAY
|
||||
#else /* BSD */
|
||||
#define FLAG_TO_SET FNDELAY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
if((val = fcntl(fd, F_GETFL, 0)) == -1)
|
||||
return -1;
|
||||
val |= FLAG_TO_SET;
|
||||
return fcntl( fd, F_SETFL, val);
|
||||
#undef FLAG_TO_SET
|
||||
return;
|
||||
if (!(val & NONBLOCK_FLAG)) {
|
||||
val |= NONBLOCK_FLAG;
|
||||
fcntl(fd, F_SETFL, val);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Set a fd into blocking mode
|
||||
****************************************************************************/
|
||||
void set_blocking(int fd)
|
||||
{
|
||||
int val;
|
||||
|
||||
if((val = fcntl(fd, F_GETFL, 0)) == -1)
|
||||
return;
|
||||
if (val & NONBLOCK_FLAG) {
|
||||
val &= ~NONBLOCK_FLAG;
|
||||
fcntl(fd, F_SETFL, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* this is taken from CVS */
|
||||
/* create a file descriptor pair - like pipe() but use socketpair if
|
||||
possible (because of blocking issues on pipes)
|
||||
|
||||
always set non-blocking
|
||||
*/
|
||||
int fd_pair(int fd[2])
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if HAVE_SOCKETPAIR
|
||||
ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
|
||||
#else
|
||||
ret = pipe(fd);
|
||||
#endif
|
||||
|
||||
if (ret == 0) {
|
||||
set_nonblocking(fd[0]);
|
||||
set_nonblocking(fd[1]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* this is derived from CVS code
|
||||
|
||||
note that in the child STDIN is set to blocking and STDOUT
|
||||
is set to non-blocking. This is necessary as rsh relies on stdin being blocking
|
||||
and ssh relies on stdout being non-blocking
|
||||
|
||||
if blocking_io is set then use blocking io on both fds. That can be
|
||||
used to cope with badly broken rsh implementations like the one on
|
||||
solaris.
|
||||
*/
|
||||
int piped_child(char **command,int *f_in,int *f_out)
|
||||
{
|
||||
int pid;
|
||||
int to_child_pipe[2];
|
||||
int from_child_pipe[2];
|
||||
extern int blocking_io;
|
||||
|
||||
if (pipe(to_child_pipe) < 0 ||
|
||||
pipe(from_child_pipe) < 0) {
|
||||
if (fd_pair(to_child_pipe) < 0 ||
|
||||
fd_pair(from_child_pipe) < 0) {
|
||||
rprintf(FERROR,"pipe: %s\n",strerror(errno));
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
@@ -86,6 +125,10 @@ int piped_child(char **command,int *f_in,int *f_out)
|
||||
if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
|
||||
if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
|
||||
umask(orig_umask);
|
||||
set_blocking(STDIN_FILENO);
|
||||
if (blocking_io) {
|
||||
set_blocking(STDOUT_FILENO);
|
||||
}
|
||||
execvp(command[0], command);
|
||||
rprintf(FERROR,"Failed to exec %s : %s\n",
|
||||
command[0],strerror(errno));
|
||||
@@ -101,9 +144,6 @@ int piped_child(char **command,int *f_in,int *f_out)
|
||||
*f_in = from_child_pipe[0];
|
||||
*f_out = to_child_pipe[1];
|
||||
|
||||
set_nonblocking(*f_in);
|
||||
set_nonblocking(*f_out);
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
@@ -113,8 +153,8 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
|
||||
int to_child_pipe[2];
|
||||
int from_child_pipe[2];
|
||||
|
||||
if (pipe(to_child_pipe) < 0 ||
|
||||
pipe(from_child_pipe) < 0) {
|
||||
if (fd_pair(to_child_pipe) < 0 ||
|
||||
fd_pair(from_child_pipe) < 0) {
|
||||
rprintf(FERROR,"pipe: %s\n",strerror(errno));
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
@@ -282,7 +322,7 @@ int copy_file(char *source, char *dest, mode_t mode)
|
||||
char buf[1024 * 8];
|
||||
int len; /* Number of bytes read into `buf'. */
|
||||
|
||||
ifd = open(source, O_RDONLY);
|
||||
ifd = do_open(source, O_RDONLY, 0);
|
||||
if (ifd == -1) {
|
||||
rprintf(FERROR,"open %s: %s\n",
|
||||
source,strerror(errno));
|
||||
@@ -397,17 +437,6 @@ int robust_rename(char *from, char *to)
|
||||
return -1;
|
||||
return do_rename(from, to);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* sleep for a while via select */
|
||||
void u_sleep(int usec)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = usec;
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
}
|
||||
|
||||
|
||||
@@ -477,7 +506,7 @@ int lock_range(int fd, int offset, int len)
|
||||
}
|
||||
|
||||
|
||||
static void glob_expand_one(char *s, char **argv, int *argc, int maxargs, int sanitize_paths)
|
||||
static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
|
||||
{
|
||||
#if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
|
||||
if (!*s) s = ".";
|
||||
@@ -485,14 +514,16 @@ static void glob_expand_one(char *s, char **argv, int *argc, int maxargs, int sa
|
||||
(*argc)++;
|
||||
return;
|
||||
#else
|
||||
extern int sanitize_paths;
|
||||
glob_t globbuf;
|
||||
int i;
|
||||
|
||||
if (!*s) s = ".";
|
||||
|
||||
s = strdup(s);
|
||||
sanitize_path(s);
|
||||
argv[*argc] = s;
|
||||
argv[*argc] = strdup(s);
|
||||
if (sanitize_paths) {
|
||||
sanitize_path(argv[*argc], NULL);
|
||||
}
|
||||
|
||||
memset(&globbuf, 0, sizeof(globbuf));
|
||||
glob(argv[*argc], 0, NULL, &globbuf);
|
||||
@@ -511,7 +542,7 @@ static void glob_expand_one(char *s, char **argv, int *argc, int maxargs, int sa
|
||||
#endif
|
||||
}
|
||||
|
||||
void glob_expand(char *base1, char **argv, int *argc, int maxargs, int sanitize_paths)
|
||||
void glob_expand(char *base1, char **argv, int *argc, int maxargs)
|
||||
{
|
||||
char *s = argv[*argc];
|
||||
char *p, *q;
|
||||
@@ -535,11 +566,11 @@ void glob_expand(char *base1, char **argv, int *argc, int maxargs, int sanitize_
|
||||
while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
|
||||
/* split it at this point */
|
||||
*p = 0;
|
||||
glob_expand_one(q, argv, argc, maxargs, sanitize_paths);
|
||||
glob_expand_one(q, argv, argc, maxargs);
|
||||
q = p+strlen(base);
|
||||
}
|
||||
|
||||
if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs, sanitize_paths);
|
||||
if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs);
|
||||
|
||||
free(s);
|
||||
free(base);
|
||||
@@ -635,19 +666,37 @@ void clean_fname(char *name)
|
||||
/*
|
||||
* Make path appear as if a chroot had occurred:
|
||||
* 1. remove leading "/" (or replace with "." if at end)
|
||||
* 2. remove leading ".." components
|
||||
* 2. remove leading ".." components (except those allowed by "reldir")
|
||||
* 3. delete any other "<dir>/.." (recursively)
|
||||
* Can only shrink paths, so sanitizes in place.
|
||||
* While we're at it, remove double slashes and "." components like
|
||||
* clean_fname does(), but DON'T remove a trailing slash because that
|
||||
* is sometimes significant on command line arguments.
|
||||
* Can only shrink paths, so sanitizes in place.
|
||||
* If "reldir" is non-null, it is a sanitized directory that the path will be
|
||||
* relative to, so allow as many ".." at the beginning of the path as
|
||||
* there are components in reldir. This is used for symbolic link targets.
|
||||
* If reldir is non-null and the path began with "/", to be completely like
|
||||
* a chroot we should add in depth levels of ".." at the beginning of the
|
||||
* path, but that would blow the assumption that the path doesn't grow and
|
||||
* it is not likely to end up being a valid symlink anyway, so just do
|
||||
* the normal removal of the leading "/" instead.
|
||||
* Contributed by Dave Dykstra <dwd@bell-labs.com>
|
||||
*/
|
||||
|
||||
void sanitize_path(char *p)
|
||||
void sanitize_path(char *p, char *reldir)
|
||||
{
|
||||
char *start, *sanp;
|
||||
int depth = 0;
|
||||
int allowdotdot = 0;
|
||||
|
||||
if (reldir) {
|
||||
depth++;
|
||||
while (*reldir) {
|
||||
if (*reldir++ == '/') {
|
||||
depth++;
|
||||
}
|
||||
}
|
||||
}
|
||||
start = p;
|
||||
sanp = p;
|
||||
while (*p == '/') {
|
||||
@@ -665,36 +714,55 @@ void sanitize_path(char *p)
|
||||
/* skip following slashes */
|
||||
;
|
||||
}
|
||||
} else if ((*p == '.') && (*(p+1) == '.') &&
|
||||
continue;
|
||||
}
|
||||
allowdotdot = 0;
|
||||
if ((*p == '.') && (*(p+1) == '.') &&
|
||||
((*(p+2) == '/') || (*(p+2) == '\0'))) {
|
||||
/* skip ".." component followed by slash or end */
|
||||
p += 2;
|
||||
if (*p == '/')
|
||||
p++;
|
||||
if (sanp != start) {
|
||||
/* back up sanp one level */
|
||||
--sanp; /* now pointing at slash */
|
||||
while ((sanp > start) && (*(sanp - 1) != '/')) {
|
||||
/* skip back up to slash */
|
||||
sanp--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (1) {
|
||||
/* copy one component through next slash */
|
||||
*sanp++ = *p++;
|
||||
if ((*p == '\0') || (*(p-1) == '/')) {
|
||||
while (*p == '/') {
|
||||
/* skip multiple slashes */
|
||||
p++;
|
||||
/* ".." component followed by slash or end */
|
||||
if ((depth > 0) && (sanp == start)) {
|
||||
/* allow depth levels of .. at the beginning */
|
||||
--depth;
|
||||
allowdotdot = 1;
|
||||
} else {
|
||||
p += 2;
|
||||
if (*p == '/')
|
||||
p++;
|
||||
if (sanp != start) {
|
||||
/* back up sanp one level */
|
||||
--sanp; /* now pointing at slash */
|
||||
while ((sanp > start) && (*(sanp - 1) != '/')) {
|
||||
/* skip back up to slash */
|
||||
sanp--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
while (1) {
|
||||
/* copy one component through next slash */
|
||||
*sanp++ = *p++;
|
||||
if ((*p == '\0') || (*(p-1) == '/')) {
|
||||
while (*p == '/') {
|
||||
/* skip multiple slashes */
|
||||
p++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allowdotdot) {
|
||||
/* move the virtual beginning to leave the .. alone */
|
||||
start = sanp;
|
||||
}
|
||||
}
|
||||
if (sanp == start) {
|
||||
if ((sanp == start) && !allowdotdot) {
|
||||
/* ended up with nothing, so put in "." component */
|
||||
/*
|
||||
* note that the !allowdotdot doesn't prevent this from
|
||||
* happening in all allowed ".." situations, but I didn't
|
||||
* think it was worth putting in an extra variable to ensure
|
||||
* it since an extra "." won't hurt in those situations.
|
||||
*/
|
||||
*sanp++ = '.';
|
||||
}
|
||||
*sanp = '\0';
|
||||
@@ -769,12 +837,12 @@ int u_strcmp(const char *cs1, const char *cs2)
|
||||
|
||||
static OFF_T last_ofs;
|
||||
|
||||
void end_progress(void)
|
||||
void end_progress(OFF_T size)
|
||||
{
|
||||
extern int do_progress, am_server;
|
||||
|
||||
if (do_progress && !am_server) {
|
||||
rprintf(FINFO,"\n");
|
||||
rprintf(FINFO,"%.0f (100%%)\n", (double)size);
|
||||
}
|
||||
last_ofs = 0;
|
||||
}
|
||||
@@ -861,3 +929,47 @@ char *timestring(time_t t)
|
||||
return(TimeBuf);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
like waitpid but does the WEXITSTATUS
|
||||
****************************************************************************/
|
||||
#ifndef WEXITSTATUS
|
||||
#define WEXITSTATUS(stat) ((int)(((stat)>>8)&0xFF))
|
||||
#endif
|
||||
void wait_process(pid_t pid, int *status)
|
||||
{
|
||||
waitpid(pid, status, 0);
|
||||
*status = WEXITSTATUS(*status);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __INSURE__
|
||||
#include <dlfcn.h>
|
||||
|
||||
/*******************************************************************
|
||||
This routine is a trick to immediately catch errors when debugging
|
||||
with insure. A xterm with a gdb is popped up when insure catches
|
||||
a error. It is Linux specific.
|
||||
********************************************************************/
|
||||
int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
|
||||
{
|
||||
static int (*fn)();
|
||||
int ret;
|
||||
char cmd[1024];
|
||||
|
||||
sprintf(cmd, "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; gdb /proc/%d/exe %d'",
|
||||
getpid(), getpid(), getpid());
|
||||
|
||||
if (!fn) {
|
||||
static void *h;
|
||||
h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
|
||||
fn = dlsym(h, "_Insure_trap_error");
|
||||
}
|
||||
|
||||
ret = fn(a1, a2, a3, a4, a5, a6);
|
||||
|
||||
system(cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user