mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-25 07:15:35 -04:00
Compare commits
77 Commits
v2.6.1pre1
...
v2.6.1pre2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0484b5b0b7 | ||
|
|
f01b6368a5 | ||
|
|
40d38dc0be | ||
|
|
33a2361cc2 | ||
|
|
4124540d61 | ||
|
|
5f38126817 | ||
|
|
b05b3c9b48 | ||
|
|
a03a9f4efe | ||
|
|
3e55030372 | ||
|
|
273c0420d0 | ||
|
|
5774786fa5 | ||
|
|
1a9ec1fd1c | ||
|
|
b2aa573b1c | ||
|
|
63d0331991 | ||
|
|
bf6dcd1713 | ||
|
|
495723bb26 | ||
|
|
911cb0662c | ||
|
|
5387514eaf | ||
|
|
61414c83ce | ||
|
|
43a9d0e7c2 | ||
|
|
df5cd107a5 | ||
|
|
abca4eba67 | ||
|
|
96d3590a08 | ||
|
|
8429aa9e0e | ||
|
|
79d4053048 | ||
|
|
753b6b4692 | ||
|
|
f8f726449b | ||
|
|
357406ecb2 | ||
|
|
3915fd7583 | ||
|
|
9c5e91f848 | ||
|
|
af107f6c08 | ||
|
|
a3dbb20a0e | ||
|
|
a3779426b6 | ||
|
|
2f5ca63d92 | ||
|
|
0e1d98ae92 | ||
|
|
04575bcab5 | ||
|
|
71b291d71b | ||
|
|
decba3ae73 | ||
|
|
f8ed564c9f | ||
|
|
47ba39bef6 | ||
|
|
71f7051489 | ||
|
|
3c3791e8be | ||
|
|
c39d6514ab | ||
|
|
1cb6f3bf4d | ||
|
|
f09dc86ab6 | ||
|
|
f26ac1e8cb | ||
|
|
84a3efa0ab | ||
|
|
00ed4b5bf3 | ||
|
|
e2e053bbd7 | ||
|
|
f8b33ab379 | ||
|
|
5df1fcf245 | ||
|
|
b1ad6a3260 | ||
|
|
6442ccc606 | ||
|
|
b21813060c | ||
|
|
706c75307a | ||
|
|
2b284ee33d | ||
|
|
4cfa6156e3 | ||
|
|
c1e7217fcb | ||
|
|
4b2f6a7c37 | ||
|
|
a8726d2a06 | ||
|
|
b5ebe6d9c7 | ||
|
|
ef383c0d32 | ||
|
|
8dcf93356e | ||
|
|
ce5f2732e4 | ||
|
|
3e89da86df | ||
|
|
f5450e791d | ||
|
|
cb984e620e | ||
|
|
be92ac6c36 | ||
|
|
5dc6e9c9ca | ||
|
|
0b79c324ca | ||
|
|
f39b6638f6 | ||
|
|
a4b6f30579 | ||
|
|
7be73df4e7 | ||
|
|
14b61c63f0 | ||
|
|
75a64762c2 | ||
|
|
028fdddb49 | ||
|
|
f86b0f2e7b |
@@ -21,4 +21,3 @@ tls
|
||||
trimslash
|
||||
t_unsafe
|
||||
wildtest
|
||||
zlib/dummy
|
||||
|
||||
61
NEWS
61
NEWS
@@ -13,10 +13,9 @@ Changes since 2.6.0:
|
||||
|
||||
* The --progress output now mentions how far along in the
|
||||
transfer we are, including both a count of files transferred
|
||||
and a percentage of the total file-count that we're processed.
|
||||
It was also improved to better show the current rate of
|
||||
transfer (which is used to estimate the remaining transfer
|
||||
time).
|
||||
and a percentage of the total file-count that we've processed.
|
||||
It also shows better current-rate-of-transfer and remaining-
|
||||
transfer-time values.
|
||||
|
||||
* The configure script now accepts --with-rsyncd-conf=PATH
|
||||
to override the default value of the /etc/rsyncd.conf file.
|
||||
@@ -28,7 +27,7 @@ Changes since 2.6.0:
|
||||
|
||||
* When -x (--one-file-system) is combined with -L (--copy-links)
|
||||
or --copy-unsafe-links, no symlinked files are skipped, even
|
||||
if the referant file is on a different filesystem.
|
||||
if the referent file is on a different filesystem.
|
||||
|
||||
* The --link-dest code now works properly for a non-root user
|
||||
when (1) the UIDs of the source and destination differ and -o
|
||||
@@ -54,11 +53,9 @@ Changes since 2.6.0:
|
||||
|
||||
* When using --cvs-exclude, the exclude items we get from a
|
||||
directory's .cvsignore file once again only affect that one
|
||||
directory (and not all following directories too).
|
||||
|
||||
* When transferring a file that has group 0 with -g specified
|
||||
(typically via -a) and not enough privs to retain the group,
|
||||
rsync no longer complains about "chown" failing.
|
||||
directory (and not all following directories too). The
|
||||
items are also now properly word-split and parsed without
|
||||
any +/- prefix munging.
|
||||
|
||||
* When specifying the USER@HOST: prefix for a file, the USER
|
||||
part can now contain an '@', if needed (i.e. the last '@'
|
||||
@@ -76,9 +73,9 @@ Changes since 2.6.0:
|
||||
* Improved the -x (--one-file-system) flag's handling of any
|
||||
mount-point directories we encounter. It is both more optimal
|
||||
(in that it no longer does a useless scan of the contents of
|
||||
the mount-point dirs) and also fixes a bug where a remaped
|
||||
mount of the original filesystem could get discovered on a
|
||||
disk we should be ignoring.
|
||||
the mount-point dirs) and also fixes a bug where a remapped
|
||||
mount of the original filesystem could get discovered in a
|
||||
subdir we should be ignoring.
|
||||
|
||||
* Rsync no longer discards a double-slash at the start of a filename
|
||||
when trying to open the file. It also no longer constructs names
|
||||
@@ -87,6 +84,17 @@ Changes since 2.6.0:
|
||||
* Fixed compilation problem on Tru64 Unix (having to do with
|
||||
sockaddr.sa_len and sockaddr.sin_len).
|
||||
|
||||
* Fixed a compatibility problem interacting with older rsync
|
||||
versions that might send us an empty suffix without telling us
|
||||
about the backup-dir.
|
||||
|
||||
* The "hosts allow" option for a daemon-over-remote-shell
|
||||
process now has improved support for IPv6 addresses and a fix
|
||||
for systems that have a length field in their socket structs.
|
||||
|
||||
* Fixed the ability to request an empty backup suffix when
|
||||
sending files to an rsync daemon.
|
||||
|
||||
INTERNAL:
|
||||
|
||||
* Most of the I/O is now buffered, which results in a pretty
|
||||
@@ -124,9 +132,18 @@ Changes since 2.6.0:
|
||||
|
||||
* Less memory is used in the file list (a per-file savings).
|
||||
|
||||
* The generator is now better about not modifying the file list
|
||||
during the transfer in order to avoid a copy-on-write memory
|
||||
bifurcation (on systems where fork() uses shared memory).
|
||||
Previously, rsync's shared memory would slowly become unshared,
|
||||
resulting in real memory usage nearly doubling on the receiving
|
||||
side by the end of the transfer. Now, as long as permissions
|
||||
are being preserved, the shared memory should remain that way
|
||||
for the entire transfer.
|
||||
|
||||
* Changed hardlink info and file_struct + strings to use
|
||||
allocation pools. This reduces memory use for large
|
||||
filesets and permits freeing memory to the OS. (J.W. Schultz)
|
||||
allocation pools. This reduces memory use for large file-
|
||||
sets and permits freeing memory to the OS. (J.W. Schultz)
|
||||
|
||||
* The 2 pipes used between the receiver and generator processes
|
||||
(which are forked on the same machine) were reduced to 1 pipe
|
||||
@@ -136,9 +153,21 @@ Changes since 2.6.0:
|
||||
the generator over to the sender (the latter mainly affected
|
||||
hard-link messages and verbose --stats output).
|
||||
|
||||
* The reading & writing of the file list in batch-mode is now
|
||||
* The reading & writing of the file-list in batch-mode is now
|
||||
handled by the same code that sends & receives the list over
|
||||
the wire. This makes it much easier to maintain.
|
||||
|
||||
* Improved the internal uid/gid code to be more portable and
|
||||
a little more optimized.
|
||||
|
||||
* Device numbers are now sent as separate major/minor values
|
||||
with 32-bit accuracy for each one (protocol 28). Previously
|
||||
hard-link device data was sent as a single 64-bit number, and
|
||||
copied devices were sent as a single 32-bit number. This will
|
||||
make inter-operation of 64-bit binaries more compatible with
|
||||
their 32-bit brethren. Note that optimizations in the binary
|
||||
protocol often sends the device data using fewer bytes than
|
||||
before, even though more precision is now available.
|
||||
|
||||
* Some cleanup of the exclude/include structures and its code
|
||||
made things clearer, simpler, and more efficient.
|
||||
|
||||
@@ -269,7 +269,8 @@ void auth_client(int fd, char *user, char *challenge)
|
||||
char pass2[30];
|
||||
extern char *password_file;
|
||||
|
||||
if (!user || !*user) return;
|
||||
if (!user || !*user)
|
||||
user = "nobody";
|
||||
|
||||
if (!(pass=getpassf(password_file)) && !(pass=getenv("RSYNC_PASSWORD"))) {
|
||||
/* XXX: cyeoh says that getpass is deprecated, because
|
||||
|
||||
127
clientname.c
127
clientname.c
@@ -1,20 +1,20 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
|
||||
rsync -- fast file replication program
|
||||
|
||||
|
||||
Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
|
||||
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.
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
/**
|
||||
* @file clientname.c
|
||||
*
|
||||
*
|
||||
* Functions for looking up the remote name or addr of a socket.
|
||||
*
|
||||
* This file is now converted to use the new-style getaddrinfo()
|
||||
@@ -39,7 +39,7 @@ extern int am_server;
|
||||
|
||||
|
||||
/**
|
||||
* Return the IP addr of the client as a string
|
||||
* Return the IP addr of the client as a string
|
||||
**/
|
||||
char *client_addr(int fd)
|
||||
{
|
||||
@@ -50,19 +50,18 @@ char *client_addr(int fd)
|
||||
static char addr_buf[100];
|
||||
static int initialised;
|
||||
|
||||
if (initialised) return addr_buf;
|
||||
if (initialised)
|
||||
return addr_buf;
|
||||
|
||||
initialised = 1;
|
||||
|
||||
if (am_server) {
|
||||
/* daemon over --rsh mode */
|
||||
if (am_server) { /* daemon over --rsh mode */
|
||||
strcpy(addr_buf, "0.0.0.0");
|
||||
if ((ssh_client = getenv("SSH_CLIENT")) != NULL) {
|
||||
/* truncate SSH_CLIENT to just IP address */
|
||||
p = strchr(ssh_client, ' ');
|
||||
if (p) {
|
||||
len = MIN((unsigned int) (p - ssh_client),
|
||||
sizeof(addr_buf) - 1);
|
||||
if ((p = strchr(ssh_client, ' ')) != NULL) {
|
||||
len = MIN((unsigned int) (p - ssh_client),
|
||||
sizeof addr_buf - 1);
|
||||
strncpy(addr_buf, ssh_client, len);
|
||||
*(addr_buf + len) = '\0';
|
||||
}
|
||||
@@ -101,58 +100,54 @@ char *client_name(int fd)
|
||||
static char name_buf[100];
|
||||
static char port_buf[100];
|
||||
static int initialised;
|
||||
struct sockaddr_storage ss, *ssp;
|
||||
struct sockaddr_in sin;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 sin6;
|
||||
#endif
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t ss_len;
|
||||
|
||||
if (initialised) return name_buf;
|
||||
if (initialised)
|
||||
return name_buf;
|
||||
|
||||
strcpy(name_buf, default_name);
|
||||
initialised = 1;
|
||||
|
||||
if (am_server) {
|
||||
/* daemon over --rsh mode */
|
||||
memset(&ss, 0, sizeof ss);
|
||||
|
||||
if (am_server) { /* daemon over --rsh mode */
|
||||
char *addr = client_addr(fd);
|
||||
struct addrinfo hint, *answer;
|
||||
int err;
|
||||
|
||||
memset(&hint, 0, sizeof hint);
|
||||
|
||||
hint.ai_flags = AI_NUMERICHOST;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if ((err = getaddrinfo(addr, NULL, &hint, &answer)) != 0) {
|
||||
rprintf(FERROR, RSYNC_NAME ": malformed address %s: %s\n",
|
||||
addr, gai_strerror(err));
|
||||
return name_buf;
|
||||
}
|
||||
|
||||
switch (answer->ai_family) {
|
||||
case AF_INET:
|
||||
ss_len = sizeof (struct sockaddr_in);
|
||||
memcpy(&ss, answer->ai_addr, ss_len);
|
||||
break;
|
||||
#ifdef INET6
|
||||
int dots = 0;
|
||||
char *p;
|
||||
|
||||
for (p = addr; *p && (dots <= 3); p++) {
|
||||
if (*p == '.')
|
||||
dots++;
|
||||
}
|
||||
if (dots > 3) {
|
||||
/* more than 4 parts to IP address, must be ipv6 */
|
||||
ssp = (struct sockaddr_storage *) &sin6;
|
||||
ss_len = sizeof sin6;
|
||||
memset(ssp, 0, ss_len);
|
||||
inet_pton(AF_INET6, addr, &sin6.sin6_addr);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
} else
|
||||
case AF_INET6:
|
||||
ss_len = sizeof (struct sockaddr_in6);
|
||||
memcpy(&ss, answer->ai_addr, ss_len);
|
||||
break;
|
||||
#endif
|
||||
{
|
||||
ssp = (struct sockaddr_storage *) &sin;
|
||||
ss_len = sizeof sin;
|
||||
memset(ssp, 0, ss_len);
|
||||
inet_pton(AF_INET, addr, &sin.sin_addr);
|
||||
sin.sin_family = AF_INET;
|
||||
}
|
||||
|
||||
freeaddrinfo(answer);
|
||||
} else {
|
||||
ss_len = sizeof ss;
|
||||
ssp = &ss;
|
||||
|
||||
client_sockaddr(fd, &ss, &ss_len);
|
||||
|
||||
}
|
||||
|
||||
if (!lookup_name(fd, ssp, ss_len, name_buf, sizeof name_buf,
|
||||
if (!lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
|
||||
port_buf, sizeof port_buf))
|
||||
check_name(fd, ssp, name_buf);
|
||||
check_name(fd, &ss, name_buf);
|
||||
|
||||
return name_buf;
|
||||
}
|
||||
@@ -169,7 +164,7 @@ void client_sockaddr(int fd,
|
||||
struct sockaddr_storage *ss,
|
||||
socklen_t *ss_len)
|
||||
{
|
||||
memset(ss, 0, sizeof(*ss));
|
||||
memset(ss, 0, sizeof *ss);
|
||||
|
||||
if (getpeername(fd, (struct sockaddr *) ss, ss_len)) {
|
||||
/* FIXME: Can we really not continue? */
|
||||
@@ -179,7 +174,7 @@ void client_sockaddr(int fd,
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
if (get_sockaddr_family(ss) == AF_INET6 &&
|
||||
if (get_sockaddr_family(ss) == AF_INET6 &&
|
||||
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) {
|
||||
/* OK, so ss is in the IPv6 family, but it is really
|
||||
* an IPv4 address: something like
|
||||
@@ -190,11 +185,11 @@ void client_sockaddr(int fd,
|
||||
struct sockaddr_in6 sin6;
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
memcpy(&sin6, ss, sizeof(sin6));
|
||||
memcpy(&sin6, ss, sizeof sin6);
|
||||
sin = (struct sockaddr_in *)ss;
|
||||
memset(sin, 0, sizeof(*sin));
|
||||
memset(sin, 0, sizeof *sin);
|
||||
sin->sin_family = AF_INET;
|
||||
*ss_len = sizeof(struct sockaddr_in);
|
||||
*ss_len = sizeof (struct sockaddr_in);
|
||||
#if HAVE_SOCKADDR_IN_LEN
|
||||
sin->sin_len = *ss_len;
|
||||
#endif
|
||||
@@ -204,8 +199,8 @@ void client_sockaddr(int fd,
|
||||
* (IN6_V4MAPPED_TO_SINADDR ?), but it does not seem
|
||||
* to be present in the Linux headers. */
|
||||
memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
|
||||
sizeof(sin->sin_addr));
|
||||
}
|
||||
sizeof sin->sin_addr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -221,7 +216,7 @@ int lookup_name(int fd, const struct sockaddr_storage *ss,
|
||||
char *port_buf, size_t port_buf_len)
|
||||
{
|
||||
int name_err;
|
||||
|
||||
|
||||
/* reverse lookup */
|
||||
name_err = getnameinfo((struct sockaddr *) ss, ss_len,
|
||||
name_buf, name_buf_len,
|
||||
@@ -250,7 +245,7 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
|
||||
{
|
||||
int ss_family = get_sockaddr_family(ss);
|
||||
const char fn[] = "compare_addrinfo_sockaddr";
|
||||
|
||||
|
||||
if (ai->ai_family != ss_family) {
|
||||
rprintf(FERROR,
|
||||
"%s: response family %d != %d\n",
|
||||
@@ -264,18 +259,19 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
|
||||
|
||||
sin1 = (const struct sockaddr_in *) ss;
|
||||
sin2 = (const struct sockaddr_in *) ai->ai_addr;
|
||||
|
||||
|
||||
return memcmp(&sin1->sin_addr, &sin2->sin_addr,
|
||||
sizeof sin1->sin_addr);
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
else if (ss_family == AF_INET6) {
|
||||
if (ss_family == AF_INET6) {
|
||||
const struct sockaddr_in6 *sin1, *sin2;
|
||||
|
||||
sin1 = (const struct sockaddr_in6 *) ss;
|
||||
sin2 = (const struct sockaddr_in6 *) ai->ai_addr;
|
||||
|
||||
if (ai->ai_addrlen < sizeof(struct sockaddr_in6)) {
|
||||
if (ai->ai_addrlen < sizeof (struct sockaddr_in6)) {
|
||||
rprintf(FERROR,
|
||||
"%s: too short sockaddr_in6; length=%d\n",
|
||||
fn, ai->ai_addrlen);
|
||||
@@ -293,10 +289,9 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
|
||||
return 0;
|
||||
}
|
||||
#endif /* INET6 */
|
||||
else {
|
||||
/* don't know */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* don't know */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -318,7 +313,7 @@ int check_name(int fd,
|
||||
int error;
|
||||
int ss_family = get_sockaddr_family(ss);
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = ss_family;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
@@ -47,7 +47,7 @@ extern int orig_umask;
|
||||
extern int no_detach;
|
||||
extern int default_af_hint;
|
||||
extern char *bind_address;
|
||||
extern struct exclude_struct **server_exclude_list;
|
||||
extern struct exclude_list_struct server_exclude_list;
|
||||
extern char *exclude_path_prefix;
|
||||
extern char *config_file;
|
||||
|
||||
@@ -87,18 +87,10 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
if (verbose >= 2) {
|
||||
/* FIXME: If we're going to use a socket program for
|
||||
* testing, then this message is wrong. We need to
|
||||
* say something like "(except really using %s)" */
|
||||
rprintf(FINFO, "opening tcp connection to %s port %d\n",
|
||||
host, rsync_port);
|
||||
}
|
||||
fd = open_socket_out_wrapped(host, rsync_port, bind_address,
|
||||
default_af_hint);
|
||||
if (fd == -1) {
|
||||
if (fd == -1)
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
|
||||
ret = start_inband_exchange(user, path, fd, fd, argc);
|
||||
|
||||
@@ -302,16 +294,19 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
exclude_path_prefix = "";
|
||||
|
||||
p = lp_include_from(i);
|
||||
add_exclude_file(&server_exclude_list, p, MISSING_FATAL, ADD_INCLUDE);
|
||||
add_exclude_file(&server_exclude_list, p,
|
||||
XFLG_FATAL_ERRORS | XFLG_DEF_INCLUDE);
|
||||
|
||||
p = lp_include(i);
|
||||
add_exclude_line(&server_exclude_list, p, ADD_INCLUDE);
|
||||
add_exclude(&server_exclude_list, p,
|
||||
XFLG_WORD_SPLIT | XFLG_DEF_INCLUDE);
|
||||
|
||||
p = lp_exclude_from(i);
|
||||
add_exclude_file(&server_exclude_list, p, MISSING_FATAL, ADD_EXCLUDE);
|
||||
add_exclude_file(&server_exclude_list, p,
|
||||
XFLG_FATAL_ERRORS);
|
||||
|
||||
p = lp_exclude(i);
|
||||
add_exclude_line(&server_exclude_list, p, ADD_EXCLUDE);
|
||||
add_exclude(&server_exclude_list, p, XFLG_WORD_SPLIT);
|
||||
|
||||
exclude_path_prefix = NULL;
|
||||
|
||||
@@ -423,19 +418,6 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
}
|
||||
}
|
||||
|
||||
if (sanitize_paths) {
|
||||
/*
|
||||
* Note that this is applied to all parameters, whether or not
|
||||
* they are filenames, but no other legal parameters contain
|
||||
* the forms that need to be sanitized so it doesn't hurt;
|
||||
* it is not known at this point which parameters are files
|
||||
* and which aren't.
|
||||
*/
|
||||
for (i = 1; i < argc; i++) {
|
||||
sanitize_path(argv[i], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
argp = argv;
|
||||
ret = parse_arguments(&argc, (const char ***) &argp, 0);
|
||||
|
||||
|
||||
15
configure.in
15
configure.in
@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ(2.52)
|
||||
|
||||
RSYNC_VERSION=2.6.1pre-1
|
||||
RSYNC_VERSION=2.6.1pre-2
|
||||
AC_SUBST(RSYNC_VERSION)
|
||||
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
|
||||
|
||||
@@ -279,13 +279,12 @@ AC_C_BIGENDIAN
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_TIME
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h unistd.h utime.h grp.h)
|
||||
AC_CHECK_HEADERS(compat.h sys/param.h ctype.h sys/wait.h sys/ioctl.h)
|
||||
AC_CHECK_HEADERS(sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h sys/un.h)
|
||||
AC_CHECK_HEADERS(glob.h mcheck.h sys/sysctl.h arpa/inet.h arpa/nameser.h)
|
||||
AC_CHECK_HEADERS(netdb.h)
|
||||
AC_CHECK_HEADERS(malloc.h)
|
||||
AC_CHECK_HEADERS(float.h)
|
||||
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
|
||||
unistd.h utime.h grp.h compat.h sys/param.h ctype.h sys/wait.h \
|
||||
sys/ioctl.h sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h \
|
||||
sys/un.h glob.h mcheck.h sys/sysctl.h arpa/inet.h arpa/nameser.h \
|
||||
netdb.h malloc.h float.h)
|
||||
AC_HEADER_MAJOR
|
||||
|
||||
AC_CHECK_SIZEOF(int)
|
||||
AC_CHECK_SIZEOF(long)
|
||||
|
||||
348
exclude.c
348
exclude.c
@@ -27,57 +27,56 @@
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int eol_nulls;
|
||||
extern int list_only;
|
||||
extern int recurse;
|
||||
|
||||
struct exclude_struct **exclude_list;
|
||||
struct exclude_struct **local_exclude_list;
|
||||
struct exclude_struct **server_exclude_list;
|
||||
extern char curr_dir[];
|
||||
|
||||
struct exclude_list_struct exclude_list;
|
||||
struct exclude_list_struct local_exclude_list;
|
||||
struct exclude_list_struct server_exclude_list;
|
||||
char *exclude_path_prefix = NULL;
|
||||
|
||||
/** Build an exclude structure given a exclude pattern */
|
||||
static struct exclude_struct *make_exclude(const char *pattern, int include)
|
||||
static void make_exclude(struct exclude_list_struct *listp, const char *pattern,
|
||||
int pat_len, int include)
|
||||
{
|
||||
struct exclude_struct *ret;
|
||||
char *cp;
|
||||
int pat_len;
|
||||
const char *cp;
|
||||
int ex_len;
|
||||
|
||||
ret = new(struct exclude_struct);
|
||||
if (!ret) out_of_memory("make_exclude");
|
||||
if (!ret)
|
||||
out_of_memory("make_exclude");
|
||||
|
||||
memset(ret, 0, sizeof ret[0]);
|
||||
|
||||
if (strncmp(pattern,"- ",2) == 0) {
|
||||
pattern += 2;
|
||||
} else if (strncmp(pattern,"+ ",2) == 0) {
|
||||
ret->include = 1;
|
||||
pattern += 2;
|
||||
} else {
|
||||
ret->include = include;
|
||||
}
|
||||
ret->include = include;
|
||||
|
||||
if (exclude_path_prefix)
|
||||
ret->match_flags |= MATCHFLG_ABS_PATH;
|
||||
if (exclude_path_prefix && *pattern == '/') {
|
||||
ret->pattern = new_array(char,
|
||||
strlen(exclude_path_prefix) + strlen(pattern) + 1);
|
||||
if (!ret->pattern) out_of_memory("make_exclude");
|
||||
sprintf(ret->pattern, "%s%s", exclude_path_prefix, pattern);
|
||||
}
|
||||
else {
|
||||
ret->pattern = strdup(pattern);
|
||||
if (!ret->pattern) out_of_memory("make_exclude");
|
||||
}
|
||||
if (exclude_path_prefix && *pattern == '/')
|
||||
ex_len = strlen(exclude_path_prefix);
|
||||
else
|
||||
ex_len = 0;
|
||||
ret->pattern = new_array(char, ex_len + pat_len + 1);
|
||||
if (!ret->pattern)
|
||||
out_of_memory("make_exclude");
|
||||
if (ex_len)
|
||||
memcpy(ret->pattern, exclude_path_prefix, ex_len);
|
||||
strlcpy(ret->pattern + ex_len, pattern, pat_len + 1);
|
||||
pat_len += ex_len;
|
||||
|
||||
if (strpbrk(pattern, "*[?")) {
|
||||
if (strpbrk(ret->pattern, "*[?")) {
|
||||
ret->match_flags |= MATCHFLG_WILD;
|
||||
if (strstr(pattern, "**")) {
|
||||
if ((cp = strstr(ret->pattern, "**")) != NULL) {
|
||||
ret->match_flags |= MATCHFLG_WILD2;
|
||||
/* If the pattern starts with **, note that. */
|
||||
if (*pattern == '*' && pattern[1] == '*')
|
||||
if (cp == ret->pattern)
|
||||
ret->match_flags |= MATCHFLG_WILD2_PREFIX;
|
||||
}
|
||||
}
|
||||
|
||||
pat_len = strlen(ret->pattern);
|
||||
if (pat_len > 1 && ret->pattern[pat_len-1] == '/') {
|
||||
ret->pattern[pat_len-1] = 0;
|
||||
ret->directory = 1;
|
||||
@@ -86,32 +85,33 @@ static struct exclude_struct *make_exclude(const char *pattern, int include)
|
||||
for (cp = ret->pattern; (cp = strchr(cp, '/')) != NULL; cp++)
|
||||
ret->slash_cnt++;
|
||||
|
||||
return ret;
|
||||
if (!listp->tail)
|
||||
listp->head = listp->tail = ret;
|
||||
else {
|
||||
listp->tail->next = ret;
|
||||
listp->tail = ret;
|
||||
}
|
||||
}
|
||||
|
||||
static void free_exclude(struct exclude_struct *ex)
|
||||
{
|
||||
free(ex->pattern);
|
||||
memset(ex, 0, sizeof ex[0]);
|
||||
free(ex);
|
||||
}
|
||||
|
||||
|
||||
void free_exclude_list(struct exclude_struct ***listp)
|
||||
void free_exclude_list(struct exclude_list_struct *listp)
|
||||
{
|
||||
struct exclude_struct **list = *listp;
|
||||
struct exclude_struct *ent, *next;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "[%s] clearing exclude list\n", who_am_i());
|
||||
|
||||
if (!list)
|
||||
return;
|
||||
for (ent = listp->head; ent; ent = next) {
|
||||
next = ent->next;
|
||||
free_exclude(ent);
|
||||
}
|
||||
|
||||
while (*list)
|
||||
free_exclude(*list++);
|
||||
|
||||
free(*listp);
|
||||
*listp = NULL;
|
||||
memset(listp, 0, sizeof listp[0]);
|
||||
}
|
||||
|
||||
static int check_one_exclude(char *name, struct exclude_struct *ex,
|
||||
@@ -130,7 +130,6 @@ static int check_one_exclude(char *name, struct exclude_struct *ex,
|
||||
}
|
||||
else if ((ex->match_flags & MATCHFLG_ABS_PATH) && *name != '/') {
|
||||
static char full_name[MAXPATHLEN];
|
||||
extern char curr_dir[];
|
||||
int plus = curr_dir[1] == '\0'? 1 : 0;
|
||||
pathjoin(full_name, sizeof full_name, curr_dir+plus, name);
|
||||
name = full_name;
|
||||
@@ -197,34 +196,33 @@ static int check_one_exclude(char *name, struct exclude_struct *ex,
|
||||
|
||||
static void report_exclude_result(char const *name,
|
||||
struct exclude_struct const *ent,
|
||||
int name_is_dir)
|
||||
int name_is_dir, const char *type)
|
||||
{
|
||||
/* If a trailing slash is present to match only directories,
|
||||
* then it is stripped out by make_exclude. So as a special
|
||||
* case we add it back in here. */
|
||||
|
||||
if (verbose >= 2) {
|
||||
rprintf(FINFO, "[%s] %s %s %s because of pattern %s%s\n",
|
||||
who_am_i(),
|
||||
ent->include ? "including" : "excluding",
|
||||
name_is_dir ? "directory" : "file",
|
||||
name, ent->pattern,
|
||||
ent->directory ? "/" : "");
|
||||
rprintf(FINFO, "[%s] %scluding %s %s because of %s %s%s\n",
|
||||
who_am_i(), ent->include ? "in" : "ex",
|
||||
name_is_dir ? "directory" : "file", name, type,
|
||||
ent->pattern, ent->directory ? "/" : "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return true if file NAME is defined to be excluded by either
|
||||
* LOCAL_EXCLUDE_LIST or the globals EXCLUDE_LIST.
|
||||
* Return true if file NAME is defined to be excluded by the specified
|
||||
* exclude list.
|
||||
*/
|
||||
int check_exclude(struct exclude_struct **list, char *name, int name_is_dir)
|
||||
int check_exclude(struct exclude_list_struct *listp, char *name, int name_is_dir,
|
||||
const char *type)
|
||||
{
|
||||
struct exclude_struct *ent;
|
||||
|
||||
while ((ent = *list++) != NULL) {
|
||||
for (ent = listp->head; ent; ent = ent->next) {
|
||||
if (check_one_exclude(name, ent, name_is_dir)) {
|
||||
report_exclude_result(name, ent, name_is_dir);
|
||||
report_exclude_result(name, ent, name_is_dir, type);
|
||||
return !ent->include;
|
||||
}
|
||||
}
|
||||
@@ -233,41 +231,91 @@ int check_exclude(struct exclude_struct **list, char *name, int name_is_dir)
|
||||
}
|
||||
|
||||
|
||||
void add_exclude(struct exclude_struct ***listp, const char *pattern, int include)
|
||||
/* Get the next include/exclude arg from the string. The token will not
|
||||
* be '\0' terminated, so use the returned length to limit the string.
|
||||
* Also, be sure to add this length to the returned pointer before passing
|
||||
* it back to ask for the next token. This routine will not split off a
|
||||
* prefix of "+ " or "- " unless xflags contains XFLG_NO_PREFIXES. The
|
||||
* *incl_ptr value will be 1 for an include, 0 for an exclude, and -1 for
|
||||
* the list-clearing "!" token.
|
||||
*/
|
||||
static const char *get_exclude_tok(const char *p, int *len_ptr, int *incl_ptr,
|
||||
int xflags)
|
||||
{
|
||||
struct exclude_struct **list = *listp;
|
||||
int len = 0;
|
||||
const unsigned char *s = (const unsigned char *)p;
|
||||
int len;
|
||||
|
||||
if (*pattern == '!' && !pattern[1]) {
|
||||
free_exclude_list(listp);
|
||||
return;
|
||||
if (xflags & XFLG_WORD_SPLIT) {
|
||||
/* Skip over any initial whitespace. */
|
||||
while (isspace(*s))
|
||||
s++;
|
||||
/* Update for "!" check. */
|
||||
p = (const char *)s;
|
||||
}
|
||||
|
||||
if (list)
|
||||
for (; list[len]; len++) {}
|
||||
/* Is this a '+' or '-' followed by a space (not whitespace)? */
|
||||
if (!(xflags & XFLG_NO_PREFIXES)
|
||||
&& (*s == '-' || *s == '+') && s[1] == ' ') {
|
||||
*incl_ptr = *s == '+';
|
||||
s += 2;
|
||||
} else
|
||||
*incl_ptr = xflags & XFLG_DEF_INCLUDE;
|
||||
|
||||
list = *listp = realloc_array(list, struct exclude_struct *, len+2);
|
||||
if (xflags & XFLG_WORD_SPLIT) {
|
||||
const unsigned char *cp = s;
|
||||
/* Token ends at whitespace or the end of the string. */
|
||||
while (!isspace(*cp) && *cp != '\0')
|
||||
cp++;
|
||||
len = cp - s;
|
||||
} else
|
||||
len = strlen(s);
|
||||
|
||||
if (!list || !(list[len] = make_exclude(pattern, include)))
|
||||
out_of_memory("add_exclude");
|
||||
if (*p == '!' && len == 1 && !(xflags & XFLG_NO_PREFIXES))
|
||||
*incl_ptr = -1;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "[%s] add_exclude(%s,%s)\n",
|
||||
who_am_i(), pattern,
|
||||
include ? "include" : "exclude");
|
||||
}
|
||||
|
||||
list[len+1] = NULL;
|
||||
*len_ptr = len;
|
||||
return (const char *)s;
|
||||
}
|
||||
|
||||
|
||||
void add_exclude_file(struct exclude_struct ***listp, const char *fname,
|
||||
int fatal, int include)
|
||||
void add_exclude(struct exclude_list_struct *listp, const char *pattern,
|
||||
int xflags)
|
||||
{
|
||||
int pat_len, incl;
|
||||
const char *cp;
|
||||
|
||||
if (!pattern)
|
||||
return;
|
||||
|
||||
cp = pattern;
|
||||
pat_len = 0;
|
||||
while (1) {
|
||||
cp = get_exclude_tok(cp + pat_len, &pat_len, &incl, xflags);
|
||||
if (!pat_len)
|
||||
break;
|
||||
/* If we got the special "!" token, clear the list. */
|
||||
if (incl < 0)
|
||||
free_exclude_list(listp);
|
||||
else {
|
||||
make_exclude(listp, cp, pat_len, incl);
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "[%s] add_exclude(%s,%s)\n",
|
||||
who_am_i(), cp,
|
||||
incl ? "include" : "exclude");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void add_exclude_file(struct exclude_list_struct *listp, const char *fname,
|
||||
int xflags)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[MAXPATHLEN];
|
||||
char *eob = line + MAXPATHLEN - 1;
|
||||
extern int eol_nulls;
|
||||
int word_split = xflags & XFLG_WORD_SPLIT;
|
||||
|
||||
if (!fname || !*fname)
|
||||
return;
|
||||
@@ -277,10 +325,10 @@ void add_exclude_file(struct exclude_struct ***listp, const char *fname,
|
||||
else
|
||||
fp = stdin;
|
||||
if (!fp) {
|
||||
if (fatal) {
|
||||
if (xflags & XFLG_FATAL_ERRORS) {
|
||||
rsyserr(FERROR, errno,
|
||||
"failed to open %s file %s",
|
||||
include ? "include" : "exclude",
|
||||
xflags & XFLG_DEF_INCLUDE ? "include" : "exclude",
|
||||
fname);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
@@ -296,18 +344,17 @@ void add_exclude_file(struct exclude_struct ***listp, const char *fname,
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (word_split && isspace(ch))
|
||||
break;
|
||||
if (eol_nulls? !ch : (ch == '\n' || ch == '\r'))
|
||||
break;
|
||||
if (s < eob)
|
||||
*s++ = ch;
|
||||
}
|
||||
*s = '\0';
|
||||
if (*line && *line != ';' && *line != '#') {
|
||||
/* Skip lines starting with semicolon or pound.
|
||||
* It probably wouldn't cause any harm to not skip
|
||||
* them but there's no need to save them. */
|
||||
add_exclude(listp, line, include);
|
||||
}
|
||||
/* Skip lines starting with semicolon or pound. */
|
||||
if (*line && *line != ';' && *line != '#')
|
||||
add_exclude(listp, line, xflags);
|
||||
if (ch == EOF)
|
||||
break;
|
||||
}
|
||||
@@ -317,43 +364,39 @@ void add_exclude_file(struct exclude_struct ***listp, const char *fname,
|
||||
|
||||
void send_exclude_list(int f)
|
||||
{
|
||||
int i;
|
||||
extern int list_only, recurse;
|
||||
struct exclude_struct *ent;
|
||||
|
||||
/* This is a complete hack - blame Rusty.
|
||||
*
|
||||
* FIXME: This pattern shows up in the output of
|
||||
* report_exclude_result(), which is not ideal. */
|
||||
if (list_only && !recurse)
|
||||
add_exclude(&exclude_list, "/*/*", ADD_EXCLUDE);
|
||||
add_exclude(&exclude_list, "/*/*", 0);
|
||||
|
||||
if (!exclude_list) {
|
||||
write_int(f,0);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; exclude_list[i]; i++) {
|
||||
for (ent = exclude_list.head; ent; ent = ent->next) {
|
||||
unsigned int l;
|
||||
char pattern[MAXPATHLEN+1];
|
||||
char p[MAXPATHLEN+1];
|
||||
|
||||
l = strlcpy(pattern, exclude_list[i]->pattern, sizeof pattern);
|
||||
l = strlcpy(p, ent->pattern, sizeof p);
|
||||
if (l == 0 || l >= MAXPATHLEN)
|
||||
continue;
|
||||
if (exclude_list[i]->directory) {
|
||||
pattern[l++] = '/';
|
||||
pattern[l] = '\0';
|
||||
if (ent->directory) {
|
||||
p[l++] = '/';
|
||||
p[l] = '\0';
|
||||
}
|
||||
|
||||
if (exclude_list[i]->include) {
|
||||
write_int(f,l+2);
|
||||
write_buf(f,"+ ",2);
|
||||
} else {
|
||||
write_int(f,l);
|
||||
}
|
||||
write_buf(f,pattern,l);
|
||||
if (ent->include) {
|
||||
write_int(f, l + 2);
|
||||
write_buf(f, "+ ", 2);
|
||||
} else if ((*p == '-' || *p == '+') && p[1] == ' ') {
|
||||
write_int(f, l + 2);
|
||||
write_buf(f, "- ", 2);
|
||||
} else
|
||||
write_int(f, l);
|
||||
write_buf(f, p, l);
|
||||
}
|
||||
|
||||
write_int(f,0);
|
||||
write_int(f, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -366,92 +409,35 @@ void recv_exclude_list(int f)
|
||||
if (l >= sizeof line)
|
||||
overflow("recv_exclude_list");
|
||||
read_sbuf(f, line, l);
|
||||
add_exclude(&exclude_list, line, ADD_EXCLUDE);
|
||||
add_exclude(&exclude_list, line, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the next include/exclude arg from the string. It works in a similar way
|
||||
** to strtok - initially an arg is sent over, from then on NULL. This
|
||||
** routine takes into account any +/- in the strings and does not
|
||||
** consider the space following it as a delimeter.
|
||||
*/
|
||||
char *get_exclude_tok(char *p)
|
||||
{
|
||||
static char *s;
|
||||
static int more;
|
||||
char *t;
|
||||
|
||||
if (p) {
|
||||
s=p;
|
||||
if (*p)
|
||||
more=1;
|
||||
}
|
||||
|
||||
if (!more)
|
||||
return(NULL);
|
||||
|
||||
/* Skip over any initial spaces */
|
||||
while (isspace(* (unsigned char *) s))
|
||||
s++;
|
||||
|
||||
/* Are we at the end of the string? */
|
||||
if (*s) {
|
||||
/* remember the beginning of the token */
|
||||
t=s;
|
||||
|
||||
/* Is this a '+' or '-' followed by a space (not whitespace)? */
|
||||
if ((*s=='+' || *s=='-') && *(s+1)==' ')
|
||||
s+=2;
|
||||
|
||||
/* Skip to the next space or the end of the string */
|
||||
while (!isspace(* (unsigned char *) s) && *s != '\0')
|
||||
s++;
|
||||
} else {
|
||||
t=NULL;
|
||||
}
|
||||
|
||||
/* Have we reached the end of the string? */
|
||||
if (*s)
|
||||
*s++='\0';
|
||||
else
|
||||
more=0;
|
||||
return(t);
|
||||
}
|
||||
|
||||
|
||||
void add_exclude_line(struct exclude_struct ***listp,
|
||||
const char *line, int include)
|
||||
{
|
||||
char *tok, *p;
|
||||
if (!line || !*line) return;
|
||||
p = strdup(line);
|
||||
if (!p) out_of_memory("add_exclude_line");
|
||||
for (tok=get_exclude_tok(p); tok; tok=get_exclude_tok(NULL))
|
||||
add_exclude(listp, tok, include);
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
||||
static char *cvs_ignore_list[] = {
|
||||
"RCS/", "SCCS/", "CVS/", ".svn/", "CVS.adm", "RCSLOG", "cvslog.*",
|
||||
"tags", "TAGS", ".make.state", ".nse_depinfo",
|
||||
"*~", "#*", ".#*", ", *", "*.old", "*.bak", "*.BAK", "*.orig",
|
||||
"*.rej", ".del-*", "*.a", "*.o", "*.obj", "*.so", "*.Z", "*.elc", "*.ln",
|
||||
"core", NULL};
|
||||
|
||||
static char default_cvsignore[] =
|
||||
/* These default ignored items come from the CVS manual. */
|
||||
"RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS"
|
||||
" .make.state .nse_depinfo *~ #* .#* ,* _$* *$"
|
||||
" *.old *.bak *.BAK *.orig *.rej .del-*"
|
||||
" *.a *.olb *.o *.obj *.so *.exe"
|
||||
" *.Z *.elc *.ln core"
|
||||
/* The rest we added to suit ourself. */
|
||||
" .svn/";
|
||||
|
||||
void add_cvs_excludes(void)
|
||||
{
|
||||
char fname[MAXPATHLEN];
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
for (i=0; cvs_ignore_list[i]; i++)
|
||||
add_exclude(&exclude_list, cvs_ignore_list[i], ADD_EXCLUDE);
|
||||
add_exclude(&exclude_list, default_cvsignore,
|
||||
XFLG_WORD_SPLIT | XFLG_NO_PREFIXES);
|
||||
|
||||
if ((p = getenv("HOME"))
|
||||
&& pathjoin(fname, sizeof fname, p, ".cvsignore") < sizeof fname)
|
||||
add_exclude_file(&exclude_list, fname, MISSING_OK, ADD_EXCLUDE);
|
||||
&& pathjoin(fname, sizeof fname, p, ".cvsignore") < sizeof fname) {
|
||||
add_exclude_file(&exclude_list, fname,
|
||||
XFLG_WORD_SPLIT | XFLG_NO_PREFIXES);
|
||||
}
|
||||
|
||||
add_exclude_line(&exclude_list, getenv("CVSIGNORE"), ADD_EXCLUDE);
|
||||
add_exclude(&exclude_list, getenv("CVSIGNORE"),
|
||||
XFLG_WORD_SPLIT | XFLG_NO_PREFIXES);
|
||||
}
|
||||
|
||||
133
flist.c
133
flist.c
@@ -33,6 +33,7 @@ extern int verbose;
|
||||
extern int do_progress;
|
||||
extern int am_root;
|
||||
extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int always_checksum;
|
||||
extern int module_id;
|
||||
extern int ignore_errors;
|
||||
@@ -63,9 +64,9 @@ extern int sanitize_paths;
|
||||
extern int read_batch;
|
||||
extern int write_batch;
|
||||
|
||||
extern struct exclude_struct **exclude_list;
|
||||
extern struct exclude_struct **server_exclude_list;
|
||||
extern struct exclude_struct **local_exclude_list;
|
||||
extern struct exclude_list_struct exclude_list;
|
||||
extern struct exclude_list_struct server_exclude_list;
|
||||
extern struct exclude_list_struct local_exclude_list;
|
||||
|
||||
int io_error;
|
||||
|
||||
@@ -225,15 +226,18 @@ static int check_exclude_file(char *fname, int is_dir, int exclude_level)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (server_exclude_list
|
||||
&& check_exclude(server_exclude_list, fname, is_dir))
|
||||
if (server_exclude_list.head
|
||||
&& check_exclude(&server_exclude_list, fname, is_dir,
|
||||
"server pattern"))
|
||||
return 1;
|
||||
if (exclude_level != ALL_EXCLUDES)
|
||||
return 0;
|
||||
if (exclude_list && check_exclude(exclude_list, fname, is_dir))
|
||||
if (exclude_list.head
|
||||
&& check_exclude(&exclude_list, fname, is_dir, "pattern"))
|
||||
return 1;
|
||||
if (local_exclude_list
|
||||
&& check_exclude(local_exclude_list, fname, is_dir))
|
||||
if (local_exclude_list.head
|
||||
&& check_exclude(&local_exclude_list, fname, is_dir,
|
||||
"local-cvsignore"))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -323,8 +327,9 @@ void send_file_entry(struct file_struct *file, int f, unsigned short base_flags)
|
||||
unsigned short flags;
|
||||
static time_t modtime;
|
||||
static mode_t mode;
|
||||
static DEV64_T rdev, rdev_high;
|
||||
static DEV64_T dev;
|
||||
static uint64 dev;
|
||||
static dev_t rdev;
|
||||
static uint32 rdev_major;
|
||||
static uid_t uid;
|
||||
static gid_t gid;
|
||||
static char lastname[MAXPATHLEN];
|
||||
@@ -337,7 +342,8 @@ void send_file_entry(struct file_struct *file, int f, unsigned short base_flags)
|
||||
if (!file) {
|
||||
write_byte(f, 0);
|
||||
modtime = 0, mode = 0;
|
||||
rdev = 0, rdev_high = 0, dev = 0;
|
||||
dev = 0, rdev = makedev(0, 0);
|
||||
rdev_major = 0;
|
||||
uid = 0, gid = 0;
|
||||
*lastname = '\0';
|
||||
return;
|
||||
@@ -356,22 +362,20 @@ void send_file_entry(struct file_struct *file, int f, unsigned short base_flags)
|
||||
if (preserve_devices) {
|
||||
if (protocol_version < 28) {
|
||||
if (IS_DEVICE(mode)) {
|
||||
if (file->u.rdev == rdev) {
|
||||
/* Set both flags to simplify the test
|
||||
* when writing the data. */
|
||||
flags |= XMIT_SAME_RDEV_pre28
|
||||
| XMIT_SAME_HIGH_RDEV;
|
||||
} else
|
||||
if (file->u.rdev == rdev)
|
||||
flags |= XMIT_SAME_RDEV_pre28;
|
||||
else
|
||||
rdev = file->u.rdev;
|
||||
} else
|
||||
rdev = 0;
|
||||
rdev = makedev(0, 0);
|
||||
} else if (IS_DEVICE(mode)) {
|
||||
if ((file->u.rdev & ~0xFF) == rdev_high)
|
||||
flags |= XMIT_SAME_HIGH_RDEV;
|
||||
else {
|
||||
rdev = file->u.rdev;
|
||||
rdev_high = rdev & ~0xFF;
|
||||
}
|
||||
rdev = file->u.rdev;
|
||||
if ((uint32)major(rdev) == rdev_major)
|
||||
flags |= XMIT_SAME_RDEV_MAJOR;
|
||||
else
|
||||
rdev_major = major(rdev);
|
||||
if ((uint32)minor(rdev) <= 0xFFu)
|
||||
flags |= XMIT_RDEV_MINOR_IS_SMALL;
|
||||
}
|
||||
}
|
||||
if (file->uid == uid)
|
||||
@@ -452,12 +456,17 @@ void send_file_entry(struct file_struct *file, int f, unsigned short base_flags)
|
||||
write_int(f, gid);
|
||||
}
|
||||
if (preserve_devices && IS_DEVICE(mode)) {
|
||||
/* If XMIT_SAME_HIGH_RDEV is off, XMIT_SAME_RDEV_pre28 is
|
||||
* also off. */
|
||||
if (!(flags & XMIT_SAME_HIGH_RDEV))
|
||||
write_int(f, rdev);
|
||||
else if (protocol_version >= 28)
|
||||
write_byte(f, rdev);
|
||||
if (protocol_version < 28) {
|
||||
if (!(flags & XMIT_SAME_RDEV_pre28))
|
||||
write_int(f, (int)rdev);
|
||||
} else {
|
||||
if (!(flags & XMIT_SAME_RDEV_MAJOR))
|
||||
write_int(f, major(rdev));
|
||||
if (flags & XMIT_RDEV_MINOR_IS_SMALL)
|
||||
write_byte(f, minor(rdev));
|
||||
else
|
||||
write_int(f, minor(rdev));
|
||||
}
|
||||
}
|
||||
|
||||
#if SUPPORT_LINKS
|
||||
@@ -510,8 +519,9 @@ void receive_file_entry(struct file_struct **fptr, unsigned short flags,
|
||||
{
|
||||
static time_t modtime;
|
||||
static mode_t mode;
|
||||
static DEV64_T rdev, rdev_high;
|
||||
static DEV64_T dev;
|
||||
static uint64 dev;
|
||||
static dev_t rdev;
|
||||
static uint32 rdev_major;
|
||||
static uid_t uid;
|
||||
static gid_t gid;
|
||||
static char lastname[MAXPATHLEN], *lastdir;
|
||||
@@ -525,7 +535,8 @@ void receive_file_entry(struct file_struct **fptr, unsigned short flags,
|
||||
|
||||
if (!fptr) {
|
||||
modtime = 0, mode = 0;
|
||||
rdev = 0, rdev_high = 0, dev = 0;
|
||||
dev = 0, rdev = makedev(0, 0);
|
||||
rdev_major = 0;
|
||||
uid = 0, gid = 0;
|
||||
*lastname = '\0';
|
||||
return;
|
||||
@@ -587,15 +598,18 @@ void receive_file_entry(struct file_struct **fptr, unsigned short flags,
|
||||
if (protocol_version < 28) {
|
||||
if (IS_DEVICE(mode)) {
|
||||
if (!(flags & XMIT_SAME_RDEV_pre28))
|
||||
rdev = (DEV64_T)read_int(f);
|
||||
rdev = (dev_t)read_int(f);
|
||||
} else
|
||||
rdev = 0;
|
||||
rdev = makedev(0, 0);
|
||||
} else if (IS_DEVICE(mode)) {
|
||||
if (!(flags & XMIT_SAME_HIGH_RDEV)) {
|
||||
rdev = (DEV64_T)read_int(f);
|
||||
rdev_high = rdev & ~0xFF;
|
||||
} else
|
||||
rdev = rdev_high | (DEV64_T)read_byte(f);
|
||||
uint32 rdev_minor;
|
||||
if (!(flags & XMIT_SAME_RDEV_MAJOR))
|
||||
rdev_major = read_int(f);
|
||||
if (flags & XMIT_RDEV_MINOR_IS_SMALL)
|
||||
rdev_minor = read_byte(f);
|
||||
else
|
||||
rdev_minor = read_int(f);
|
||||
rdev = makedev(rdev_major, rdev_minor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,7 +673,7 @@ void receive_file_entry(struct file_struct **fptr, unsigned short flags,
|
||||
if (preserve_hard_links && protocol_version < 28 && S_ISREG(mode))
|
||||
flags |= XMIT_HAS_IDEV_DATA;
|
||||
if (flags & XMIT_HAS_IDEV_DATA) {
|
||||
INO64_T inode;
|
||||
uint64 inode;
|
||||
if (protocol_version < 26) {
|
||||
dev = read_int(f);
|
||||
inode = read_int(f);
|
||||
@@ -747,18 +761,26 @@ struct file_struct *make_file(char *fname,
|
||||
|
||||
if (readlink_stat(thisname, &st, linkname) != 0) {
|
||||
int save_errno = errno;
|
||||
if (errno == ENOENT && exclude_level != NO_EXCLUDES) {
|
||||
if (errno == ENOENT) {
|
||||
enum logcode c = am_daemon && protocol_version < 28
|
||||
? FERROR : FINFO;
|
||||
/* either symlink pointing nowhere or file that
|
||||
* was removed during rsync run; see if excluded
|
||||
* before reporting an error */
|
||||
if (check_exclude_file(thisname, 0, exclude_level)) {
|
||||
if (exclude_level != NO_EXCLUDES
|
||||
&& check_exclude_file(thisname, 0, exclude_level)) {
|
||||
/* file is excluded anyway, ignore silently */
|
||||
return NULL;
|
||||
}
|
||||
io_error |= IOERR_VANISHED;
|
||||
rprintf(c, "file has vanished: %s\n",
|
||||
full_fname(thisname));
|
||||
}
|
||||
else {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "readlink %s failed: %s\n",
|
||||
full_fname(thisname), strerror(save_errno));
|
||||
}
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "readlink %s failed: %s\n",
|
||||
full_fname(thisname), strerror(save_errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -924,10 +946,11 @@ void send_file_name(int f, struct file_list *flist, char *fname,
|
||||
|
||||
if (recursive && S_ISDIR(file->mode)
|
||||
&& !(file->flags & FLAG_MOUNT_POINT)) {
|
||||
struct exclude_struct **last_exclude_list = local_exclude_list;
|
||||
struct exclude_list_struct last_list = local_exclude_list;
|
||||
memset(&local_exclude_list, 0, sizeof local_exclude_list);
|
||||
send_directory(f, flist, f_name_to(file, fbuf));
|
||||
local_exclude_list = last_exclude_list;
|
||||
return;
|
||||
free_exclude_list(&local_exclude_list);
|
||||
local_exclude_list = last_list;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -962,13 +985,12 @@ static void send_directory(int f, struct file_list *flist, char *dir)
|
||||
offset++;
|
||||
}
|
||||
|
||||
local_exclude_list = NULL;
|
||||
|
||||
if (cvs_exclude) {
|
||||
if (strlcpy(p, ".cvsignore", MAXPATHLEN - offset)
|
||||
< MAXPATHLEN - offset)
|
||||
add_exclude_file(&local_exclude_list,fname,MISSING_OK,ADD_EXCLUDE);
|
||||
else {
|
||||
< MAXPATHLEN - offset) {
|
||||
add_exclude_file(&local_exclude_list, fname,
|
||||
XFLG_WORD_SPLIT | XFLG_NO_PREFIXES);
|
||||
} else {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FINFO,
|
||||
"cannot cvs-exclude in long-named directory %s\n",
|
||||
@@ -996,9 +1018,6 @@ static void send_directory(int f, struct file_list *flist, char *dir)
|
||||
dir, errno, strerror(errno));
|
||||
}
|
||||
|
||||
if (local_exclude_list)
|
||||
free_exclude_list(&local_exclude_list); /* Zeros pointer too */
|
||||
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
|
||||
18
generator.c
18
generator.c
@@ -43,6 +43,13 @@ extern int protocol_version;
|
||||
extern int always_checksum;
|
||||
extern char *compare_dest;
|
||||
extern int link_dest;
|
||||
extern int whole_file;
|
||||
extern int local_server;
|
||||
extern int write_batch;
|
||||
extern int list_only;
|
||||
extern int only_existing;
|
||||
extern int orig_umask;
|
||||
extern int safe_symlinks;
|
||||
|
||||
|
||||
/* choose whether to skip a particular file */
|
||||
@@ -204,10 +211,6 @@ static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
|
||||
* Whew. */
|
||||
static BOOL disable_deltas_p(void)
|
||||
{
|
||||
extern int whole_file;
|
||||
extern int local_server;
|
||||
extern int write_batch;
|
||||
|
||||
if (whole_file > 0)
|
||||
return True;
|
||||
if (whole_file == 0 || write_batch)
|
||||
@@ -270,10 +273,6 @@ void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
|
||||
int statret;
|
||||
char *fnamecmp;
|
||||
char fnamecmpbuf[MAXPATHLEN];
|
||||
extern char *compare_dest;
|
||||
extern int list_only;
|
||||
extern int only_existing;
|
||||
extern int orig_umask;
|
||||
|
||||
if (list_only)
|
||||
return;
|
||||
@@ -335,7 +334,6 @@ void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
|
||||
#if SUPPORT_LINKS
|
||||
char lnk[MAXPATHLEN];
|
||||
int l;
|
||||
extern int safe_symlinks;
|
||||
|
||||
if (safe_symlinks && unsafe_symlink(file->u.link, fname)) {
|
||||
if (verbose) {
|
||||
@@ -378,7 +376,7 @@ void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
|
||||
if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
|
||||
if (statret != 0 ||
|
||||
st.st_mode != file->mode ||
|
||||
(DEV64_T)st.st_rdev != file->u.rdev) {
|
||||
st.st_rdev != file->u.rdev) {
|
||||
delete_file(fname);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
|
||||
|
||||
2
hlink.c
2
hlink.c
@@ -135,7 +135,7 @@ void init_hard_links(struct file_list *flist)
|
||||
|
||||
int hard_link_check(struct file_struct *file, int skip)
|
||||
{
|
||||
if (!file->link_u.links)
|
||||
if (!hlink_list || !file->link_u.links)
|
||||
return 0;
|
||||
if (skip && !(file->flags & FLAG_HLINK_EOL))
|
||||
hlink_list[file->F_HLINDEX] = file->F_NEXT;
|
||||
|
||||
@@ -39,6 +39,10 @@ struct align_test {
|
||||
|
||||
#define MINALIGN offsetof(struct align_test, bar)
|
||||
|
||||
/* Temporarily cast a void* var into a char* var when adding an offset (to
|
||||
* keep some compilers from complaining about the pointer arithmetic). */
|
||||
#define PTR_ADD(b,o) ( (void*) ((char*)(b) + (o)) )
|
||||
|
||||
alloc_pool_t
|
||||
pool_create(size_t size, size_t quantum,
|
||||
void (*bomb)(char *), int flags)
|
||||
@@ -134,14 +138,14 @@ pool_alloc(alloc_pool_t p, size_t len, char *bomb)
|
||||
|
||||
if (pool->flags & POOL_APPEND)
|
||||
{
|
||||
pool->live = start + free;
|
||||
pool->live = PTR_ADD(start, free);
|
||||
}
|
||||
else if (!(pool->live = (struct pool_extent *) malloc(sizeof (struct pool_extent))))
|
||||
{
|
||||
goto bomb;
|
||||
}
|
||||
if (pool->flags & POOL_QALIGN && pool->quantum > 1
|
||||
&& (sqew = (size_t)(start + free) % pool->quantum))
|
||||
&& (sqew = (size_t)PTR_ADD(start, free) % pool->quantum))
|
||||
{
|
||||
bound += sqew;
|
||||
free -= sqew;
|
||||
@@ -159,7 +163,7 @@ pool_alloc(alloc_pool_t p, size_t len, char *bomb)
|
||||
|
||||
pool->live->free -= len;
|
||||
|
||||
return pool->live->start + pool->live->free;
|
||||
return PTR_ADD(pool->live->start, pool->live->free);
|
||||
|
||||
bomb:
|
||||
if (pool->bomb)
|
||||
@@ -195,9 +199,9 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
|
||||
cur = pool->live;
|
||||
if (cur
|
||||
&& addr >= cur->start
|
||||
&& addr < cur->start + pool->size)
|
||||
&& addr < PTR_ADD(cur->start, pool->size))
|
||||
{
|
||||
if (addr == cur->start + cur->free)
|
||||
if (addr == PTR_ADD(cur->start, cur->free))
|
||||
{
|
||||
if (pool->flags & POOL_CLEAR)
|
||||
memset(addr, 0, len);
|
||||
@@ -212,7 +216,7 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
|
||||
cur->free = pool->size;
|
||||
cur->bound = 0;
|
||||
if (pool->flags & POOL_QALIGN && pool->quantum > 1
|
||||
&& (sqew = (size_t)(cur->start + cur->free) % pool->quantum))
|
||||
&& (sqew = (size_t)PTR_ADD(cur->start, cur->free) % pool->quantum))
|
||||
{
|
||||
cur->bound += sqew;
|
||||
cur->free -= sqew;
|
||||
@@ -223,7 +227,7 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
|
||||
for (prev = NULL, cur = pool->free; cur; prev = cur, cur = cur->next)
|
||||
{
|
||||
if (addr >= cur->start
|
||||
&& addr < cur->start + pool->size)
|
||||
&& addr < PTR_ADD(cur->start, pool->size))
|
||||
break;
|
||||
}
|
||||
if (!cur)
|
||||
|
||||
75
options.c
75
options.c
@@ -21,7 +21,9 @@
|
||||
#include "rsync.h"
|
||||
#include "popt.h"
|
||||
|
||||
extern struct exclude_struct **exclude_list;
|
||||
extern int sanitize_paths;
|
||||
extern char curr_dir[MAXPATHLEN];
|
||||
extern struct exclude_list_struct exclude_list;
|
||||
|
||||
int make_backups = 0;
|
||||
|
||||
@@ -181,7 +183,7 @@ static void print_rsync_version(enum logcode f)
|
||||
rprintf(f, " %sIPv6, %d-bit system inums, %d-bit internal inums\n",
|
||||
ipv6,
|
||||
(int) (sizeof dumstat->st_ino * 8),
|
||||
(int) (sizeof (INO64_T) * 8));
|
||||
(int) (sizeof (uint64) * 8));
|
||||
#ifdef MAINTAINER_MODE
|
||||
rprintf(f, " panic action: \"%s\"\n",
|
||||
get_panic_action());
|
||||
@@ -359,7 +361,7 @@ static struct poptOption long_options[] = {
|
||||
{"timeout", 0, POPT_ARG_INT, &io_timeout, 0, 0, 0 },
|
||||
{"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
|
||||
{"compare-dest", 0, POPT_ARG_STRING, &compare_dest, 0, 0, 0 },
|
||||
{"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
|
||||
{"link-dest", 0, POPT_ARG_STRING, &compare_dest, OPT_LINK_DEST, 0, 0 },
|
||||
/* TODO: Should this take an optional int giving the compression level? */
|
||||
{"compress", 'z', POPT_ARG_NONE, &do_compression, 0, 0, 0 },
|
||||
{"daemon", 0, POPT_ARG_NONE, &daemon_opt, 0, 0, 0 },
|
||||
@@ -469,6 +471,7 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
{
|
||||
int opt;
|
||||
char *ref = lp_refuse_options(module_id);
|
||||
const char *arg;
|
||||
poptContext pc;
|
||||
|
||||
if (ref && *ref)
|
||||
@@ -507,23 +510,28 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
break;
|
||||
|
||||
case OPT_EXCLUDE:
|
||||
add_exclude(&exclude_list, poptGetOptArg(pc),
|
||||
ADD_EXCLUDE);
|
||||
add_exclude(&exclude_list, poptGetOptArg(pc), 0);
|
||||
break;
|
||||
|
||||
case OPT_INCLUDE:
|
||||
add_exclude(&exclude_list, poptGetOptArg(pc),
|
||||
ADD_INCLUDE);
|
||||
XFLG_DEF_INCLUDE);
|
||||
break;
|
||||
|
||||
case OPT_EXCLUDE_FROM:
|
||||
add_exclude_file(&exclude_list, poptGetOptArg(pc),
|
||||
MISSING_FATAL, ADD_EXCLUDE);
|
||||
arg = poptGetOptArg(pc);
|
||||
if (sanitize_paths)
|
||||
arg = alloc_sanitize_path(arg, curr_dir);
|
||||
add_exclude_file(&exclude_list, arg,
|
||||
XFLG_FATAL_ERRORS);
|
||||
break;
|
||||
|
||||
case OPT_INCLUDE_FROM:
|
||||
add_exclude_file(&exclude_list, poptGetOptArg(pc),
|
||||
MISSING_FATAL, ADD_INCLUDE);
|
||||
arg = poptGetOptArg(pc);
|
||||
if (sanitize_paths)
|
||||
arg = alloc_sanitize_path(arg, curr_dir);
|
||||
add_exclude_file(&exclude_list, arg,
|
||||
XFLG_FATAL_ERRORS | XFLG_DEF_INCLUDE);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
@@ -566,7 +574,6 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
|
||||
case OPT_LINK_DEST:
|
||||
#if HAVE_LINK
|
||||
compare_dest = (char *)poptGetOptArg(pc);
|
||||
link_dest = 1;
|
||||
break;
|
||||
#else
|
||||
@@ -660,6 +667,32 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
if (relative_paths < 0)
|
||||
relative_paths = files_from? 1 : 0;
|
||||
|
||||
*argv = poptGetArgs(pc);
|
||||
if (*argv)
|
||||
*argc = count_args(*argv);
|
||||
else
|
||||
*argc = 0;
|
||||
|
||||
if (sanitize_paths) {
|
||||
int i;
|
||||
for (i = *argc; i-- > 0; )
|
||||
(*argv)[i] = alloc_sanitize_path((*argv)[i], NULL);
|
||||
if (tmpdir)
|
||||
tmpdir = alloc_sanitize_path(tmpdir, curr_dir);
|
||||
if (compare_dest)
|
||||
compare_dest = alloc_sanitize_path(compare_dest, curr_dir);
|
||||
if (backup_dir)
|
||||
backup_dir = alloc_sanitize_path(backup_dir, curr_dir);
|
||||
if (files_from)
|
||||
files_from = alloc_sanitize_path(files_from, curr_dir);
|
||||
}
|
||||
|
||||
if (daemon_opt) {
|
||||
daemon_opt = 0;
|
||||
am_daemon = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!backup_suffix)
|
||||
backup_suffix = backup_dir ? "" : BACKUP_SUFFIX;
|
||||
backup_suffix_len = strlen(backup_suffix);
|
||||
@@ -679,9 +712,9 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
backup_dir_buf[backup_dir_len++] = '/';
|
||||
backup_dir_buf[backup_dir_len] = '\0';
|
||||
}
|
||||
if (verbose > 1)
|
||||
if (verbose > 1 && !am_sender)
|
||||
rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
|
||||
} else if (!backup_suffix_len) {
|
||||
} else if (!backup_suffix_len && (!am_server || !am_sender)) {
|
||||
rprintf(FERROR,
|
||||
"--suffix cannot be a null string without --backup-dir\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
@@ -690,15 +723,9 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
if (do_progress && !verbose)
|
||||
verbose = 1;
|
||||
|
||||
*argv = poptGetArgs(pc);
|
||||
if (*argv)
|
||||
*argc = count_args(*argv);
|
||||
else
|
||||
*argc = 0;
|
||||
|
||||
if (files_from) {
|
||||
char *colon;
|
||||
if (*argc != 2) {
|
||||
if (*argc != 2 && !(am_server && am_sender && *argc == 1)) {
|
||||
usage(FERROR);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
@@ -718,11 +745,6 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
} else {
|
||||
extern int sanitize_paths;
|
||||
if (sanitize_paths) {
|
||||
files_from = strdup(files_from);
|
||||
sanitize_path(files_from, NULL);
|
||||
}
|
||||
filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
|
||||
if (filesfrom_fd < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
@@ -733,9 +755,6 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
}
|
||||
}
|
||||
|
||||
if (daemon_opt)
|
||||
am_daemon = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.6.1pre-1
|
||||
Version: 2.6.1pre-2
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
|
||||
@@ -5,5 +5,3 @@ config.h
|
||||
config.log
|
||||
config.status
|
||||
dummy
|
||||
rsync
|
||||
zlib/dummy
|
||||
|
||||
54
rsync.h
54
rsync.h
@@ -50,9 +50,10 @@
|
||||
#define XMIT_SAME_NAME (1<<5)
|
||||
#define XMIT_LONG_NAME (1<<6)
|
||||
#define XMIT_SAME_TIME (1<<7)
|
||||
#define XMIT_SAME_HIGH_RDEV (1<<8)
|
||||
#define XMIT_SAME_RDEV_MAJOR (1<<8)
|
||||
#define XMIT_HAS_IDEV_DATA (1<<9)
|
||||
#define XMIT_SAME_DEV (1<<10)
|
||||
#define XMIT_RDEV_MINOR_IS_SMALL (1<<11)
|
||||
|
||||
/* These flags are used in the live flist data. */
|
||||
|
||||
@@ -103,11 +104,10 @@
|
||||
#define SERVER_EXCLUDES 1
|
||||
#define ALL_EXCLUDES 2
|
||||
|
||||
#define MISSING_OK 0
|
||||
#define MISSING_FATAL 1
|
||||
|
||||
#define ADD_INCLUDE 1
|
||||
#define ADD_EXCLUDE 0
|
||||
#define XFLG_FATAL_ERRORS (1<<0)
|
||||
#define XFLG_DEF_INCLUDE (1<<1)
|
||||
#define XFLG_NO_PREFIXES (1<<2)
|
||||
#define XFLG_WORD_SPLIT (1<<3)
|
||||
|
||||
#define FULL_FLUSH 1
|
||||
#define NORMAL_FLUSH 0
|
||||
@@ -246,6 +246,12 @@ enum msgcode {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if MAJOR_IN_MKDEV
|
||||
#include <sys/mkdev.h>
|
||||
#elif MAJOR_IN_SYSMACROS
|
||||
#include <sys/sysmacros.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_COMPAT_H
|
||||
#include <compat.h>
|
||||
#endif
|
||||
@@ -339,17 +345,14 @@ enum msgcode {
|
||||
* device numbers will be truncated. But it's a kind of silly thing
|
||||
* to do anyhow.
|
||||
*
|
||||
* FIXME: In future, we should probable split the device number into
|
||||
* major/minor, and transfer the two parts as 32-bit ints. That gives
|
||||
* you somewhat more of a chance that they'll come from a big machine
|
||||
* to a little one in a useful way.
|
||||
*
|
||||
* FIXME: Really we need an unsigned type, and we perhaps ought to
|
||||
* cope with platforms on which this is an unsigned int or even a
|
||||
* struct. Later.
|
||||
* FIXME: I don't think the code in flist.c has ever worked on a system
|
||||
* where dev_t is a struct.
|
||||
*/
|
||||
#define INO64_T uint64
|
||||
#define DEV64_T uint64
|
||||
|
||||
struct idev {
|
||||
uint64 inode;
|
||||
uint64 dev;
|
||||
};
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
@@ -395,11 +398,6 @@ struct hlink {
|
||||
struct file_struct *next;
|
||||
};
|
||||
|
||||
struct idev {
|
||||
INO64_T inode;
|
||||
DEV64_T dev;
|
||||
};
|
||||
|
||||
#define F_DEV link_u.idev->dev
|
||||
#define F_INODE link_u.idev->inode
|
||||
|
||||
@@ -408,9 +406,9 @@ struct idev {
|
||||
|
||||
struct file_struct {
|
||||
union {
|
||||
DEV64_T rdev; /* The device number, if this is a device */
|
||||
dev_t rdev; /* The device number, if this is a device */
|
||||
char *sum; /* Only a normal file can have a checksum */
|
||||
char *link; /* Holds symlink string, if a symlink */
|
||||
char *link; /* Points to symlink string, if a symlink */
|
||||
} u;
|
||||
OFF_T length;
|
||||
char *basename;
|
||||
@@ -493,6 +491,7 @@ struct map_struct {
|
||||
#define MATCHFLG_WILD2_PREFIX (1<<2) /* pattern starts with '**' */
|
||||
#define MATCHFLG_ABS_PATH (1<<3) /* path-match on absolute path */
|
||||
struct exclude_struct {
|
||||
struct exclude_struct *next;
|
||||
char *pattern;
|
||||
int match_flags;
|
||||
int include;
|
||||
@@ -500,6 +499,11 @@ struct exclude_struct {
|
||||
int slash_cnt;
|
||||
};
|
||||
|
||||
struct exclude_list_struct {
|
||||
struct exclude_struct *head;
|
||||
struct exclude_struct *tail;
|
||||
};
|
||||
|
||||
struct stats {
|
||||
int64 total_size;
|
||||
int64 total_transferred_size;
|
||||
@@ -756,6 +760,10 @@ int inet_pton(int af, const char *src, void *dst);
|
||||
const char *get_panic_action(void);
|
||||
#endif
|
||||
|
||||
#if !(defined(__hpux) || defined(_hpux) || defined (hpux))
|
||||
#define UNUSED(x) x __attribute__((__unused__))
|
||||
#else
|
||||
#define UNUSED(x) x
|
||||
#endif
|
||||
|
||||
extern const char *io_write_phase, *io_read_phase;
|
||||
|
||||
121
rsync.yo
121
rsync.yo
@@ -1,5 +1,5 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsync)(1)(24 Mar 2004)()()
|
||||
manpage(rsync)(1)(17 Apr 2004)()()
|
||||
manpagename(rsync)(faster, flexible replacement for rcp)
|
||||
manpagesynopsis()
|
||||
|
||||
@@ -384,9 +384,9 @@ dit(bf(-I, --ignore-times)) Normally rsync will skip any files that are
|
||||
already the same size and have the same modification time-stamp.
|
||||
This option turns off this "quick check" behavior.
|
||||
|
||||
dit(bf(--size-only)) Normally rsync will skip any files that are
|
||||
dit(bf(--size-only)) Normally rsync will not transfer any files that are
|
||||
already the same size and have the same modification time-stamp. With the
|
||||
--size-only option files will be skipped if they have the same size,
|
||||
--size-only option, files will not be transferred if they have the same size,
|
||||
regardless of timestamp. This is useful when starting to use rsync
|
||||
after using another mirroring system which may not preserve timestamps
|
||||
exactly.
|
||||
@@ -402,7 +402,7 @@ dit(bf(-c, --checksum)) This forces the sender to checksum all files using
|
||||
a 128-bit MD4 checksum before transfer. The checksum is then
|
||||
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.
|
||||
receiver are not transferred. This option can be quite slow.
|
||||
|
||||
dit(bf(-a, --archive)) This is equivalent to -rlptgoD. It is a quick
|
||||
way of saying you want recursion and want to preserve almost
|
||||
@@ -458,6 +458,8 @@ very useful for incremental backups. You can additionally
|
||||
specify a backup suffix using the --suffix option
|
||||
(otherwise the files backed up in the specified directory
|
||||
will keep their original filenames).
|
||||
If DIR is a relative path, it is relative to the destination directory
|
||||
(which changes in a recursive transfer).
|
||||
|
||||
dit(bf(--suffix=SUFFIX)) This option allows you to override the default
|
||||
backup suffix used with the --backup (-b) option. The default suffix is a ~
|
||||
@@ -710,6 +712,8 @@ was located on the remote "src" host.
|
||||
dit(bf(-0, --from0)) This tells rsync that the filenames it reads from a
|
||||
file are terminated by a null ('\0') character, not a NL, CR, or CR+LF.
|
||||
This affects --exclude-from, --include-from, and --files-from.
|
||||
It does not affect --cvs-exclude (since all names read from a .cvsignore
|
||||
file are split on whitespace).
|
||||
|
||||
dit(bf(-T, --temp-dir=DIR)) This option instructs rsync to use DIR as a
|
||||
scratch directory when creating temporary copies of the files
|
||||
@@ -727,14 +731,19 @@ although this skips files that haven't changed; see also --link-dest).
|
||||
This option increases the usefulness of --partial because partially
|
||||
transferred files will remain in the new temporary destination until they
|
||||
have a chance to be completed. If DIR is a relative path, it is relative
|
||||
to the destination directory.
|
||||
to the destination directory (which changes in a recursive transfer).
|
||||
|
||||
dit(bf(--link-dest=DIR)) This option behaves like bf(--compare-dest) but
|
||||
also will create hard links from em(DIR) to the destination directory for
|
||||
unchanged files. Files with changed ownership or permissions will not be
|
||||
linked.
|
||||
Like bf(--compare-dest) if DIR is a relative path, it is relative
|
||||
to the destination directory.
|
||||
to the destination directory (which changes in a recursive transfer).
|
||||
An example:
|
||||
|
||||
verb(
|
||||
rsync -av --link-dest=$PWD/prior_dir host:src_dir/ new_dir/
|
||||
)
|
||||
|
||||
dit(bf(-z, --compress)) With this option, rsync compresses any data from
|
||||
the files that it sends to the destination machine. This
|
||||
@@ -887,7 +896,7 @@ manpagesection(EXCLUDE PATTERNS)
|
||||
The exclude and include patterns specified to rsync allow for flexible
|
||||
selection of which files to transfer and which files to skip.
|
||||
|
||||
rsync builds an ordered list of include/exclude options as specified on
|
||||
Rsync builds an ordered list of include/exclude options as specified on
|
||||
the command line. Rsync checks each file and directory
|
||||
name against each exclude/include pattern in turn. The first matching
|
||||
pattern is acted on. If it is an exclude pattern, then that file is
|
||||
@@ -895,15 +904,55 @@ skipped. If it is an include pattern then that filename is not
|
||||
skipped. If no matching include/exclude pattern is found then the
|
||||
filename is not skipped.
|
||||
|
||||
The filenames matched against the exclude/include patterns
|
||||
are relative to the destination directory, or "top
|
||||
directory", so patterns should not include the path elements
|
||||
of the source or destination directories. The only way in
|
||||
which a pattern will match the absolute path of a file or
|
||||
directory is if the source path is the root directory.
|
||||
The filenames matched against the exclude/include patterns are relative
|
||||
to the "root of the transfer". If you think of the transfer as a
|
||||
subtree of names that are being sent from sender to receiver, the root
|
||||
is where the tree starts to be duplicated in the destination directory.
|
||||
This root governs where patterns that start with a / match (see below).
|
||||
|
||||
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
|
||||
Because the matching is relative to the transfer-root, changing the
|
||||
trailing slash on the source path or changing your use of the --relative
|
||||
option affects the path you need to use in your matching (in addition to
|
||||
changing how much of the file tree is duplicated on the destination
|
||||
system). The following examples demonstrate this.
|
||||
|
||||
Let's say that we want to match two source files, one with an absolute
|
||||
path of "/home/me/foo/bar", and one with a path of "/home/you/bar/baz".
|
||||
Here is how the various command choices differ for a 2-source transfer:
|
||||
|
||||
verb(
|
||||
Example cmd: rsync -a /home/me /home/you /dest
|
||||
+/- pattern: /me/foo/bar
|
||||
+/- pattern: /you/bar/baz
|
||||
Target file: /dest/me/foo/bar
|
||||
Target file: /dest/you/bar/baz
|
||||
|
||||
Example cmd: rsync -a /home/me/ /home/you/ /dest
|
||||
+/- pattern: /foo/bar (note missing "me")
|
||||
+/- pattern: /bar/baz (note missing "you")
|
||||
Target file: /dest/foo/bar
|
||||
Target file: /dest/bar/baz
|
||||
|
||||
Example cmd: rsync -a --relative /home/me/ /home/you /dest
|
||||
+/- pattern: /home/me/foo/bar (note full path)
|
||||
+/- pattern: /home/you/bar/baz (ditto)
|
||||
Target file: /dest/home/me/foo/bar
|
||||
Target file: /dest/home/you/bar/baz
|
||||
|
||||
Example cmd: cd /home; rsync -a --relative me/foo you/ /dest
|
||||
+/- pattern: /me/foo/bar (starts at specified path)
|
||||
+/- pattern: /you/bar/baz (ditto)
|
||||
Target file: /dest/me/foo/bar
|
||||
Target file: /dest/you/bar/baz
|
||||
)
|
||||
|
||||
The easiest way to see what name you should include/exclude is to just
|
||||
look at the output when using --verbose and put a / in front of the name
|
||||
(use the --dry-run option if you're not yet ready to copy any files).
|
||||
|
||||
Note that, when using the --recursive (-r) option (which is implied by -a),
|
||||
every subcomponent of
|
||||
every path is visited from the top down, so include/exclude patterns get
|
||||
applied recursively to each subcomponent.
|
||||
|
||||
Note also that the --include and --exclude options take one pattern
|
||||
@@ -918,16 +967,15 @@ itemize(
|
||||
start of the filename, otherwise it is matched against the end of
|
||||
the filename.
|
||||
This is the equivalent of a leading ^ in regular expressions.
|
||||
Thus "/foo" would match a file called "foo" at the top of the
|
||||
transferred tree.
|
||||
Thus "/foo" would match a file called "foo" at the transfer-root
|
||||
(see above for how this is different from the filesystem-root).
|
||||
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.
|
||||
The leading / does not make the pattern an absolute pathname.
|
||||
|
||||
it() if the pattern ends with a / then it will only match a
|
||||
directory, not a file, link or device.
|
||||
directory, not a file, link, or device.
|
||||
|
||||
it() if the pattern contains a wildcard character from the set
|
||||
*?[ then expression matching is applied using the shell filename
|
||||
@@ -945,11 +993,11 @@ itemize(
|
||||
|
||||
it() if the pattern starts with "+ " (a plus followed by a space)
|
||||
then it is always considered an include pattern, even if specified as
|
||||
part of an exclude option. The "+ " part is discarded before matching.
|
||||
part of an exclude option. The prefix is discarded before matching.
|
||||
|
||||
it() if the pattern starts with "- " (a minus followed by a space)
|
||||
then it is always considered an exclude pattern, even if specified as
|
||||
part of an include option. The "- " part is discarded before matching.
|
||||
part of an include option. The prefix is discarded before matching.
|
||||
|
||||
it() if the pattern is a single exclamation mark ! then the current
|
||||
include/exclude list is reset, removing all previously defined patterns.
|
||||
@@ -970,12 +1018,12 @@ Here are some exclude/include examples:
|
||||
|
||||
itemize(
|
||||
it() --exclude "*.o" would exclude all filenames matching *.o
|
||||
it() --exclude "/foo" would exclude a file called foo in the top directory
|
||||
it() --exclude "/foo" would exclude a file called foo in the transfer-root directory
|
||||
it() --exclude "foo/" would exclude any directory called foo
|
||||
it() --exclude "/foo/*/bar" would exclude any file called bar two
|
||||
levels below a directory called foo in the top directory
|
||||
levels below a directory called foo in the transfer-root directory
|
||||
it() --exclude "/foo/**/bar" would exclude any file called bar two
|
||||
or more levels below a directory called foo in the top directory
|
||||
or more levels below a directory called foo in the transfer-root directory
|
||||
it() --include "*/" --include "*.c" --exclude "*" would include all
|
||||
directories and C source files
|
||||
it() --include "foo/" --include "foo/bar.c" --exclude "*" would include
|
||||
@@ -1029,11 +1077,11 @@ once, instead of sending the same data to every host individually.
|
||||
Example:
|
||||
|
||||
verb(
|
||||
$ rsync --write-batch=pfx -a /source/dir/ /adest/dir/
|
||||
$ rcp pfx.rsync_* remote:
|
||||
$ ssh remote rsync --read-batch=pfx -a /bdest/dir/
|
||||
# or alternatively
|
||||
$ ssh remote ./pfx.rsync_argvs /bdest/dir/
|
||||
$ rsync --write-batch=pfx -a /source/dir/ /adest/dir/
|
||||
$ rcp pfx.rsync_* remote:
|
||||
$ ssh remote rsync --read-batch=pfx -a /bdest/dir/
|
||||
# or alternatively
|
||||
$ ssh remote ./pfx.rsync_argvs /bdest/dir/
|
||||
)
|
||||
|
||||
In this example, rsync is used to update /adest/dir/ with /source/dir/
|
||||
@@ -1168,6 +1216,7 @@ password to a shell transport such as ssh.
|
||||
|
||||
dit(bf(USER) or bf(LOGNAME)) The USER or LOGNAME environment variables
|
||||
are used to determine the default username sent to an rsync server.
|
||||
If neither is set, the username defaults to "nobody".
|
||||
|
||||
dit(bf(HOME)) The HOME environment variable is used to find the user's
|
||||
default .cvsignore file.
|
||||
@@ -1224,19 +1273,13 @@ Thanks to Richard Brent, Brendan Mackay, Bill Waite, Stephen Rothwell
|
||||
and David Bell for helpful suggestions, patches and testing of rsync.
|
||||
I've probably missed some people, my apologies if I have.
|
||||
|
||||
Especial thanks also to: David Dykstra, Jos Backus, Sebastian Krahmer.
|
||||
|
||||
Especial thanks also to: David Dykstra, Jos Backus, Sebastian Krahmer,
|
||||
Martin Pool, Wayne Davison.
|
||||
|
||||
manpageauthor()
|
||||
|
||||
rsync was written by Andrew Tridgell <tridge@samba.org> and Paul
|
||||
Mackerras.
|
||||
|
||||
rsync is now maintained by Martin Pool <mbp@samba.org>.
|
||||
rsync was originally written by Andrew Tridgell and Paul Mackerras.
|
||||
Many people have later contributed to it.
|
||||
|
||||
Mailing lists for support and development are available at
|
||||
url(http://lists.samba.org)(lists.samba.org)
|
||||
|
||||
If you suspect you have found a security vulnerability in rsync,
|
||||
please send it directly to Martin Pool and Andrew Tridgell. For other
|
||||
enquiries, please use the mailing list.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsyncd.conf)(5)(24 Mar 2004)()()
|
||||
manpage(rsyncd.conf)(5)(17 Apr 2004)()()
|
||||
manpagename(rsyncd.conf)(configuration file for rsync server)
|
||||
manpagesynopsis()
|
||||
|
||||
@@ -138,8 +138,10 @@ of not being able to follow symbolic links outside of the new root path
|
||||
when reading, and of complicating the preservation of usernames and groups
|
||||
(see below). 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.
|
||||
path, and leading slashes are removed from most absolute paths (options
|
||||
such as --backup-dir, --compare-dest, etc. interpret an absolute path as
|
||||
rooted in the module's "path" dir, just as if chroot was specified).
|
||||
The default for "use chroot" is true.
|
||||
|
||||
In order to preserve usernames and groupnames, rsync needs to be able to
|
||||
use the standard library functions for looking up names and IDs (i.e.
|
||||
|
||||
19
socket.c
19
socket.c
@@ -299,9 +299,14 @@ int open_socket_out(char *host, int port, const char *bind_address,
|
||||
int open_socket_out_wrapped(char *host, int port, const char *bind_address,
|
||||
int af_hint)
|
||||
{
|
||||
char *prog;
|
||||
char *prog = getenv("RSYNC_CONNECT_PROG");
|
||||
|
||||
if ((prog = getenv("RSYNC_CONNECT_PROG")) != NULL)
|
||||
if (verbose >= 2) {
|
||||
rprintf(FINFO, "%sopening tcp connection to %s port %d\n",
|
||||
prog ? "Using RSYNC_CONNECT_PROG instead of " : "",
|
||||
host, port);
|
||||
}
|
||||
if (prog)
|
||||
return sock_exec(prog);
|
||||
return open_socket_out(host, port, bind_address, af_hint);
|
||||
}
|
||||
@@ -431,10 +436,10 @@ int is_a_socket(int fd)
|
||||
|
||||
static RETSIGTYPE sigchld_handler(UNUSED(int val))
|
||||
{
|
||||
signal(SIGCHLD, sigchld_handler);
|
||||
#ifdef WNOHANG
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0) {}
|
||||
#endif
|
||||
signal(SIGCHLD, sigchld_handler);
|
||||
}
|
||||
|
||||
|
||||
@@ -769,18 +774,14 @@ int sock_exec(const char *prog)
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (verbose >= 2)
|
||||
rprintf(FINFO, "Running socket program: \"%s\"\n", prog);
|
||||
if (fork() == 0) {
|
||||
close(fd[0]);
|
||||
close(0);
|
||||
close(1);
|
||||
dup(fd[1]);
|
||||
dup(fd[1]);
|
||||
if (verbose > 3) {
|
||||
/* Can't use rprintf because we've forked. */
|
||||
fprintf(stderr,
|
||||
RSYNC_NAME ": execute socket program \"%s\"\n",
|
||||
prog);
|
||||
}
|
||||
exit(system(prog));
|
||||
}
|
||||
close(fd[1]);
|
||||
|
||||
6
t_stub.c
6
t_stub.c
@@ -28,7 +28,7 @@
|
||||
|
||||
int modify_window = 0;
|
||||
int module_id = -1;
|
||||
struct exclude_struct **server_exclude_list;
|
||||
struct exclude_list_struct server_exclude_list;
|
||||
|
||||
void rprintf(UNUSED(enum logcode code), const char *format, ...)
|
||||
{
|
||||
@@ -45,8 +45,8 @@ struct exclude_struct **server_exclude_list;
|
||||
exit(code);
|
||||
}
|
||||
|
||||
int check_exclude(UNUSED(struct exclude_struct **list), UNUSED(char *name),
|
||||
UNUSED(int name_is_dir))
|
||||
int check_exclude(UNUSED(struct exclude_list_struct *listp), UNUSED(char *name),
|
||||
UNUSED(int name_is_dir), UNUSED(const char *type))
|
||||
{
|
||||
/* This function doesn't really get called in this test context, so
|
||||
* just return 0. */
|
||||
|
||||
@@ -16,10 +16,18 @@ set -x
|
||||
fromdir="$scratchdir/from"
|
||||
todir="$scratchdir/to"
|
||||
|
||||
case `id -u` in
|
||||
'') ;; # If "id" failed, try to continue...
|
||||
0) ;;
|
||||
*) test_skipped "Rsync won't copy devices unless we're root" ;;
|
||||
esac
|
||||
|
||||
# TODO: Need to test whether hardlinks are possible on this OS/filesystem
|
||||
|
||||
mkdir "$fromdir"
|
||||
mknod "$fromdir/char" c 42 69 || test_skipped "Can't create char device node unless root"
|
||||
mknod "$fromdir/char" c 41 67 || test_skipped "Can't create char device node unless root"
|
||||
mknod "$fromdir/char2" c 42 68 || test_skipped "Can't create char device node unless root"
|
||||
mknod "$fromdir/char3" c 42 69 || test_skipped "Can't create char device node unless root"
|
||||
mknod "$fromdir/block" b 42 69 || test_skipped "Can't create block device node unless root"
|
||||
mknod "$fromdir/block2" b 42 73 || test_skipped "Can't create block device node unless root"
|
||||
mknod "$fromdir/block3" b 105 73 || test_skipped "Can't create block device node unless root"
|
||||
|
||||
@@ -14,23 +14,36 @@
|
||||
|
||||
set -x
|
||||
|
||||
HOME="$scratchdir"
|
||||
CVSIGNORE='*.junk'
|
||||
export HOME CVSIGNORE
|
||||
|
||||
# Build some files/dirs/links to copy
|
||||
|
||||
fromdir="$scratchdir/from"
|
||||
todir="$scratchdir/to"
|
||||
chkdir="$scratchdir/chk"
|
||||
|
||||
echo home-cvs-exclude >"$scratchdir"/.cvsignore
|
||||
makepath "$fromdir/foo/down/to/you"
|
||||
makepath "$fromdir/bar/down/to/foo/too"
|
||||
makepath "$fromdir/mid/for/foo/and/that/is/who"
|
||||
echo kept >"$fromdir/foo/file1"
|
||||
echo removed >"$fromdir/foo/file2"
|
||||
echo cvsout >"$fromdir/foo/file2.old"
|
||||
echo keeper >"$fromdir/bar/down/to/foo/file1"
|
||||
echo cvsout >"$fromdir/bar/down/to/foo/file1.bak"
|
||||
echo gone >"$fromdir/bar/down/to/foo/file3"
|
||||
echo lost >"$fromdir/bar/down/to/foo/file4"
|
||||
echo cvsout >"$fromdir/bar/down/to/foo/file4.junk"
|
||||
echo smashed >"$fromdir/bar/down/to/foo/to"
|
||||
echo cvsout >"$fromdir/bar/down/to/home-cvs-exclude"
|
||||
echo cvsout >"$fromdir/mid/one-in-one-out"
|
||||
echo one-in-one-out >"$fromdir/mid/.cvsignore"
|
||||
echo cvsin >"$fromdir/mid/one-for-all"
|
||||
echo expunged >"$fromdir/mid/for/foo/extra"
|
||||
echo retained >"$fromdir/mid/for/foo/keep"
|
||||
echo cvsin >"$fromdir/mid/for/one-in-one-out"
|
||||
ln -s too "$fromdir/bar/down/to/foo/sym"
|
||||
|
||||
# Setup our test exclude/include file.
|
||||
@@ -72,5 +85,21 @@ $RSYNC -av --existing --include='*/' --exclude='*' "$fromdir/" "$chkdir/"
|
||||
|
||||
checkit "$RSYNC -avv --exclude-from=$excl \"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
|
||||
|
||||
# Modify the chk dir by removing cvs-ignored files and then tweaking the dir times.
|
||||
|
||||
rm "$chkdir"/foo/*.old
|
||||
rm "$chkdir"/bar/down/to/foo/*.bak
|
||||
rm "$chkdir"/bar/down/to/foo/*.junk
|
||||
rm "$chkdir"/bar/down/to/home-cvs-exclude
|
||||
rm "$chkdir"/mid/one-in-one-out
|
||||
|
||||
$RSYNC -av --existing --include='*/' --exclude='*' "$fromdir/" "$chkdir/"
|
||||
|
||||
# Now, test if rsync excludes the same files, this time with --cvs-exclude
|
||||
# and --delete-excluded.
|
||||
|
||||
checkit "$RSYNC -avvC --delete-excluded --exclude-from=$excl \
|
||||
\"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
|
||||
29
tls.c
29
tls.c
@@ -1,16 +1,16 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
*
|
||||
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -86,7 +86,7 @@ static void list_file (const char *fname)
|
||||
strcpy(linkbuf, " -> ");
|
||||
/* const-cast required for silly UNICOS headers */
|
||||
len = readlink((char *) fname, linkbuf+4, sizeof(linkbuf) - 4);
|
||||
if (len == -1)
|
||||
if (len == -1)
|
||||
failed("readlink", fname);
|
||||
else
|
||||
/* it's not nul-terminated */
|
||||
@@ -99,7 +99,7 @@ static void list_file (const char *fname)
|
||||
|
||||
if (buf.st_mtime) {
|
||||
mt = gmtime(&buf.st_mtime);
|
||||
|
||||
|
||||
sprintf(datebuf, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||
mt->tm_year + 1900,
|
||||
mt->tm_mon + 1,
|
||||
@@ -110,15 +110,18 @@ static void list_file (const char *fname)
|
||||
} else {
|
||||
strcpy(datebuf, " ");
|
||||
}
|
||||
|
||||
|
||||
/* TODO: Perhaps escape special characters in fname? */
|
||||
|
||||
|
||||
/* NB: need to pass size as a double because it might be be
|
||||
* too large for a long. */
|
||||
printf("%s %12.0f %6ld.%-6ld %6ld %s %s%s\n",
|
||||
permbuf, (double)buf.st_size, (long)buf.st_uid,
|
||||
(long)buf.st_gid, (long)buf.st_nlink,
|
||||
|
||||
printf("%s ", permbuf);
|
||||
if (IS_DEVICE(buf.st_mode)) {
|
||||
printf("%5ld,%6ld",
|
||||
(long)major(buf.st_rdev),
|
||||
(long)minor(buf.st_rdev));
|
||||
} else /* NB: use double for size since it might not fit in a long. */
|
||||
printf("%12.0f", (double)buf.st_size);
|
||||
printf(" %6ld.%-6ld %6ld %s %s%s\n",
|
||||
(long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
|
||||
datebuf, fname, linkbuf);
|
||||
}
|
||||
|
||||
|
||||
41
util.c
41
util.c
@@ -28,6 +28,7 @@
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern struct exclude_list_struct server_exclude_list;
|
||||
|
||||
int sanitize_paths = 0;
|
||||
|
||||
@@ -471,12 +472,12 @@ int lock_range(int fd, int offset, int len)
|
||||
static int exclude_server_path(char *arg)
|
||||
{
|
||||
char *s;
|
||||
extern struct exclude_struct **server_exclude_list;
|
||||
|
||||
if (server_exclude_list) {
|
||||
if (server_exclude_list.head) {
|
||||
for (s = arg; (s = strchr(s, '/')) != NULL; ) {
|
||||
*s = '\0';
|
||||
if (check_exclude(server_exclude_list, arg, 1)) {
|
||||
if (check_exclude(&server_exclude_list, arg, 1,
|
||||
"server pattern")) {
|
||||
/* We must leave arg truncated! */
|
||||
return 1;
|
||||
}
|
||||
@@ -775,6 +776,40 @@ void sanitize_path(char *p, char *reldir)
|
||||
*sanp = '\0';
|
||||
}
|
||||
|
||||
/* Works much like sanitize_path(), with these differences: (1) a new buffer
|
||||
* is allocated for the sanitized path rather than modifying it in-place; (2)
|
||||
* a leading slash gets transformed into the rootdir value (which can be empty
|
||||
* or NULL if you just want the slash to get dropped); (3) no "reldir" can be
|
||||
* specified. */
|
||||
char *alloc_sanitize_path(const char *path, const char *rootdir)
|
||||
{
|
||||
char *buf;
|
||||
int rlen, plen = strlen(path);
|
||||
|
||||
if (*path == '/' && rootdir) {
|
||||
rlen = strlen(rootdir);
|
||||
if (rlen == 1)
|
||||
path++;
|
||||
} else
|
||||
rlen = 0;
|
||||
if (!(buf = new_array(char, rlen + plen + 1)))
|
||||
out_of_memory("alloc_sanitize_path");
|
||||
if (rlen)
|
||||
memcpy(buf, rootdir, rlen);
|
||||
memcpy(buf + rlen, path, plen + 1);
|
||||
|
||||
if (rlen > 1)
|
||||
rlen++;
|
||||
sanitize_path(buf + rlen, NULL);
|
||||
if (rlen && buf[rlen] == '.' && buf[rlen+1] == '\0') {
|
||||
if (rlen > 1)
|
||||
rlen--;
|
||||
buf[rlen] = '\0';
|
||||
}
|
||||
fprintf(stderr, "p:`%s'\n", buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
char curr_dir[MAXPATHLEN];
|
||||
unsigned int curr_dir_len;
|
||||
|
||||
Reference in New Issue
Block a user