Compare commits

...

77 Commits

Author SHA1 Message Date
Wayne Davison
0484b5b0b7 Preparing for release of 2.6.1pre-2 2004-04-17 18:40:16 +00:00
Wayne Davison
f01b6368a5 Mention that --from0 does not affect --cvs-exclude's reading of the
.cvsignore files.
2004-04-17 18:12:33 +00:00
Wayne Davison
40d38dc0be In add_exclude_file(), if we're word-splitting, stop reading a "line"
at any whitespace (so that we don't overflow the line buffer).
2004-04-17 17:55:45 +00:00
Wayne Davison
33a2361cc2 The inode and dev values in the idev struct are now uint64. 2004-04-17 17:14:16 +00:00
Wayne Davison
4124540d61 Changed the dev handling for -H back to using an opaque 64-bit
integer instead of trying to transfer it as separate major & minor
values.  Since the value is not interpreted by the receiving side
(just compared for equality), this is a safer way to go.
2004-04-17 17:14:12 +00:00
Wayne Davison
5f38126817 Use "uint64" instead of INO64_T (which is now gone). 2004-04-17 17:07:23 +00:00
Wayne Davison
b05b3c9b48 Fixed alloc_sanitize_path()'s handling of a rootdir == "/" (the old
code would generate a string that started with "//" instead of "/").
2004-04-17 17:06:03 +00:00
Wayne Davison
a03a9f4efe Don't say "skipped" if the file is just not being transferred (i.e.
when other updates, such as owner/permissions/etc. might be made).
2004-04-15 18:32:24 +00:00
Wayne Davison
3e55030372 Mention exclude improvements. 2004-04-15 18:23:52 +00:00
Wayne Davison
273c0420d0 Got rid of a couple useless lines. 2004-04-15 18:22:56 +00:00
Wayne Davison
5774786fa5 Moved some externs. 2004-04-15 16:55:23 +00:00
Wayne Davison
1a9ec1fd1c Got rid of zlib/dummy ("dummy" is in the zlib .cvsignore, where it
should be).
2004-04-15 06:54:14 +00:00
Wayne Davison
b2aa573b1c Our exclude lists are now comprised of a base structure with a head
and a tail pointer pointing to a linked list of items (rather than
an array of pointers that has to be reallocated all the time).
2004-04-14 23:33:40 +00:00
Wayne Davison
63d0331991 Added a "next" pointer to "exclude_struct" and added a new structure
for exclude lists, exclude_list_struct, that holds the head/tail
pointers for the list.
2004-04-14 23:33:37 +00:00
Wayne Davison
bf6dcd1713 Updated the exclude-list code to handle the new linked-list
structure format.
2004-04-14 23:33:34 +00:00
Wayne Davison
495723bb26 Updated the exclude-list code to handle the new linked-list
structure format.
2004-04-14 23:33:34 +00:00
Wayne Davison
911cb0662c Updated stub version of check_exclude(). 2004-04-14 22:49:54 +00:00
Wayne Davison
5387514eaf Added a description arg to check_exclude(). 2004-04-14 21:59:45 +00:00
Wayne Davison
61414c83ce The check_exclude() and report_exclude_result() functions now take a
description string that describes what kind of an include/exclude is
happening (which only gets output when verbose is set to 2 or more).
2004-04-14 21:59:41 +00:00
Wayne Davison
43a9d0e7c2 Improved the exclude testing by adding tests that exercise --cvs-exclude
and --delete-excluded.
2004-04-14 20:50:32 +00:00
Wayne Davison
df5cd107a5 Moved (and expanded) a verbose message from clientserver.c to socket.c
to solve an old FIXME comment.
2004-04-14 16:51:48 +00:00
Wayne Davison
abca4eba67 Fixed a potential problem parsing the "!" token from a word-split string. 2004-04-13 19:07:21 +00:00
Wayne Davison
96d3590a08 A few more improvements to get_exclude_tok() and add_exclude(). 2004-04-13 18:35:08 +00:00
Wayne Davison
8429aa9e0e Added an example for --link-dest. 2004-04-13 00:32:58 +00:00
Wayne Davison
79d4053048 Updated with latest news and some spelling mistakes corrected. 2004-04-12 18:03:08 +00:00
Wayne Davison
753b6b4692 Replaced MISSING_OK, MISSING_FATAL, ADD_INCLUDE, and ADD_EXCLUDE with
some new XFLG_* values (for the add_exclude*() function).
2004-04-12 17:42:35 +00:00
Wayne Davison
f8f726449b - add_exclude() now takes a flag int and can optionally word-split
items and/or ignore +/- prefixes.
- add_exclude_file() changed to take the same flags as add_exclude().
- add_exclude_line() was removed since add_exclude() can now do its job.
- make_exclude() now takes a size-limited string without a +/- prefix.
- add_cvs_excludes() was changed to word-split the items that come from
  a .cvsignore file, and to ignore all +/- prefixes in all the ignore
  sources.  Since CVS doesn't check if its ignore items are directories,
  the dir-names (e.g. SCCS, CVS, etc.) no longer have a trailing slash
  (making our excludes match CVS's ignores more exactly).
2004-04-12 17:42:32 +00:00
Wayne Davison
357406ecb2 Use the new XFLG_* flags to call the add_exclude*() functions. 2004-04-12 17:42:29 +00:00
Wayne Davison
3915fd7583 No need to cast st.st_rdev to DEV64_T anymore. 2004-04-12 16:52:43 +00:00
Wayne Davison
9c5e91f848 - Use dev_t instead of DEV64_T.
- Changed rdev_high to rdev_major.
- Use major(), minor(), and makedev() to manipulate device numbers.
- Send the major and minor values separately in protocol 28 and beyond.
2004-04-12 16:52:40 +00:00
Wayne Davison
af107f6c08 - Got rid of DEV64_T and changed the internal device variables to dev_t.
- Changed XMIT_SAME_HIGH_RDEV to XMIT_SAME_RDEV_MAJOR.
- Added XMIT_RDEV_MINOR_IS_SMALL.
2004-04-12 16:52:37 +00:00
Wayne Davison
a3dbb20a0e Fixed a bug where an exclude name that got sent over the wire could get
an extra "- " or "+ " parsed off the start of the name (i.e. we have to
quote excluded names that start with those strings with an extra "- "
at the start).
2004-04-10 10:31:11 +00:00
Wayne Davison
a3779426b6 UNUSED() misbehaves on HP-UX, not AIX. 2004-04-09 22:25:33 +00:00
Wayne Davison
2f5ca63d92 AIX doesn't like our UNUSED() macro, so let's eliminate it for them. 2004-04-09 21:51:34 +00:00
Wayne Davison
0e1d98ae92 Silence compiler warnings on Solaris. 2004-04-09 20:22:44 +00:00
Wayne Davison
04575bcab5 Missed one void-pointer-arithmetic case. 2004-04-09 20:17:01 +00:00
Wayne Davison
71b291d71b AIX's cc was complaining about the void* arithmetic. 2004-04-09 19:53:50 +00:00
Wayne Davison
decba3ae73 Removed debug code. 2004-04-09 19:18:34 +00:00
Wayne Davison
f8ed564c9f Changed sysmacros.h to sys/sysmacros.h. 2004-04-09 19:04:03 +00:00
Wayne Davison
47ba39bef6 Added some test code to assist in the remote debugging of the build
farm's Solaris machines.
2004-04-09 18:36:01 +00:00
Wayne Davison
71f7051489 Use MAJOR_IN_MKDEV and MAJOR_IN_SYSMACROS. 2004-04-09 18:10:03 +00:00
Wayne Davison
3c3791e8be Use AC_HEADER_MAJOR for better makedev/major/minor determination. 2004-04-09 18:09:16 +00:00
Wayne Davison
c39d6514ab Include <sys/mkdev.h> if it exists. 2004-04-09 17:59:50 +00:00
Wayne Davison
1cb6f3bf4d Added sys/mkdev.h to the searched-for headers. 2004-04-09 17:56:58 +00:00
Wayne Davison
f09dc86ab6 Added a couple extra character devices to be copied. 2004-04-09 00:36:45 +00:00
Wayne Davison
f26ac1e8cb If we're listing a device, output the major and minor device numbers. 2004-04-09 00:33:34 +00:00
Wayne Davison
84a3efa0ab Simplify the setting of rdev & rdev_high in send_file_entry(). 2004-04-08 23:15:39 +00:00
Wayne Davison
00ed4b5bf3 Fixed a bug in the sending of rdev when the high-bits match. 2004-04-08 23:05:36 +00:00
Wayne Davison
e2e053bbd7 Explicitly cast our ~0xFF mask using ~(DEV64_T)0xFF, just to be sure
(sign-extention would have probably made the former work OK).
2004-04-08 21:51:49 +00:00
Wayne Davison
f8b33ab379 Mention the rsync-daemon fix for --sufix=''. 2004-04-07 23:13:02 +00:00
Wayne Davison
5df1fcf245 If --daemon was specified, exit the option-parsing code before
adjusting various default values (the real defaults will get
set when the client's options arrive).
2004-04-07 23:09:14 +00:00
Wayne Davison
b1ad6a3260 Added a couple missing items. 2004-04-05 15:05:46 +00:00
Wayne Davison
6442ccc606 Decided against "Source root" in the exclude/include examples. 2004-04-03 20:47:54 +00:00
Wayne Davison
b21813060c Mentioned the CoW improvement and got rid of a bug-fix mention that
was for a bug introduced during the 2.6.1 developement.
2004-04-03 18:13:51 +00:00
Wayne Davison
706c75307a Use getaddrinfo() to figure out if a numeric address is IPv4 or IPv6. 2004-04-01 21:39:35 +00:00
Wayne Davison
2b284ee33d Last of the cleanup before the patching starts. 2004-04-01 21:08:24 +00:00
Wayne Davison
4cfa6156e3 A couple more minor twiddles. 2004-04-01 20:56:50 +00:00
Wayne Davison
c1e7217fcb Updated the sizeof syntax and trimmed some trailing whitespace. 2004-04-01 20:53:39 +00:00
Wayne Davison
4b2f6a7c37 Decided to use "nobody" instead of "guest". 2004-04-01 18:05:40 +00:00
Wayne Davison
a8726d2a06 Some more IOERR_VANISHED support. 2004-04-01 18:04:59 +00:00
Wayne Davison
b5ebe6d9c7 Improved the include/exclude example section some more. Document
the new username default of "guest" if neither USER or LOGNAME is
set in the environment.
2004-03-31 18:53:57 +00:00
Wayne Davison
ef383c0d32 The auth_client function must not return without outputting something
on the socket, so a NULL or empty username now defaults to "guest".
2004-03-31 18:52:38 +00:00
Wayne Davison
8dcf93356e Don't complain about a null --suffix if we're the server/sender (since
we might not have received the --backup-dir path from the client).
2004-03-31 17:02:22 +00:00
Martin Pool
ce5f2732e4 I'm no longer maintaining this. Tell people to use the lists instead. 2004-03-31 02:48:47 +00:00
Wayne Davison
3e89da86df The --files-from option needs to allow a server-sender to sometimes
have just 1 arg on the command-line.
2004-03-30 02:08:07 +00:00
Wayne Davison
f5450e791d Try to avoid running on a system that allows us to create devices
without being root (like cygwin) because rsync won't copy the
devices if it is not root.
2004-03-29 17:02:31 +00:00
Wayne Davison
cb984e620e In sigchild_handler(), finish with waitpid() before reinitializing
the SIGCHLD handling.
2004-03-29 16:30:53 +00:00
Wayne Davison
be92ac6c36 Added one more example to the new include/exclude section to show how
--relative works with a non-absolute path.
2004-03-27 20:04:04 +00:00
Wayne Davison
5dc6e9c9ca Mention that certain options treat an absolute path as relative to the
module's "path" dir, even when chroot is off.
2004-03-27 19:47:27 +00:00
Wayne Davison
0b79c324ca Improved the "relative to the destination dir" description for
several options.
2004-03-27 19:46:28 +00:00
Wayne Davison
f39b6638f6 Got rid of debug-output statement. 2004-03-27 19:42:13 +00:00
Wayne Davison
a4b6f30579 Try to make the complexities of includes/excludes a little more clear. 2004-03-27 18:25:41 +00:00
Wayne Davison
7be73df4e7 Optionally sanitize the args in parse_arguments() using the new
alloc_sanitize_path() function.
2004-03-27 09:46:42 +00:00
Wayne Davison
14b61c63f0 Added alloc_sanitize_path(). 2004-03-27 09:44:49 +00:00
Wayne Davison
75a64762c2 The args are now sanitized in parse_arguments() instead of here. 2004-03-27 09:44:01 +00:00
Wayne Davison
028fdddb49 Fixed a crash bug when hlink_list is NULL and a link_u.links
pointer in one of the file_struct nodes is not.
2004-03-26 16:46:20 +00:00
Wayne Davison
f86b0f2e7b Fixed a typo and made a sentence read better. 2004-03-26 15:51:51 +00:00
23 changed files with 658 additions and 500 deletions

View File

@@ -21,4 +21,3 @@ tls
trimslash
t_unsafe
wildtest
zlib/dummy

61
NEWS
View File

@@ -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.

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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
View File

@@ -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
View File

@@ -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);
}

View File

@@ -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",

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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

View File

@@ -5,5 +5,3 @@ config.h
config.log
config.status
dummy
rsync
zlib/dummy

54
rsync.h
View File

@@ -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
View File

@@ -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.

View File

@@ -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.

View File

@@ -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]);

View File

@@ -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. */

View File

@@ -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"

View File

@@ -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
View File

@@ -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
View File

@@ -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;