+++ /dev/null
-diff -urbBN rsync-2.6.6.org/cleanup.c rsync-2.6.6/cleanup.c
---- rsync-2.6.6.org/cleanup.c 2005-03-05 19:58:38.000000000 +0100
-+++ rsync-2.6.6/cleanup.c 2005-11-14 16:49:56.182884500 +0100
-@@ -22,6 +22,9 @@
- #include "rsync.h"
-
- extern int io_error;
-+#if HAVE_OPENSSL
-+extern int use_ssl;
-+#endif
- extern int keep_partial;
- extern int log_got_error;
- extern char *partial_dir;
-@@ -97,6 +100,11 @@
- signal(SIGUSR1, SIG_IGN);
- signal(SIGUSR2, SIG_IGN);
-
-+#if HAVE_OPENSSL
-+ if (use_ssl)
-+ end_tls();
-+#endif
-+
- if (verbose > 3) {
- rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",
- code, safe_fname(file), line);
-diff -urbBN rsync-2.6.6.org/clientserver.c rsync-2.6.6/clientserver.c
---- rsync-2.6.6.org/clientserver.c 2005-06-10 18:57:43.000000000 +0200
-+++ rsync-2.6.6/clientserver.c 2005-11-14 16:49:56.182884500 +0100
-@@ -44,6 +44,9 @@
- extern int orig_umask;
- extern int no_detach;
- extern int default_af_hint;
-+#if HAVE_OPENSSL
-+extern int use_ssl;
-+#endif
- extern char *bind_address;
- extern struct filter_list_struct server_filter_list;
- extern char *config_file;
-@@ -98,8 +101,18 @@
- exit_cleanup(RERR_SOCKETIO);
-
- ret = start_inband_exchange(user, path, fd, fd, argc);
-+ if (ret)
-+ return ret;
-+
-+#if HAVE_OPENSSL
-+ if (use_ssl) {
-+ int f_in = get_tls_rfd();
-+ int f_out = get_tls_wfd();
-+ return client_run(f_in, f_out, -1, argc, argv);
-+ }
-+#endif
-
-- return ret ? ret : client_run(fd, fd, -1, argc, argv);
-+ return client_run(fd, fd, -1, argc, argv);
- }
-
- int start_inband_exchange(char *user, char *path, int f_in, int f_out,
-@@ -160,6 +173,33 @@
- if (verbose > 1)
- print_child_argv(sargs);
-
-+#if HAVE_OPENSSL
-+ if (use_ssl) {
-+ io_printf(f_out, "#starttls\n");
-+ while (1) {
-+ if (!read_line(f_in, line, sizeof(line)-1)) {
-+ rprintf(FERROR, "rsync: did not receive reply to #starttls\n");
-+ return -1;
-+ }
-+ if (strncmp(line, "@ERROR", 6) == 0) {
-+ rprintf(FERROR, "%s\n", line);
-+ return -1;
-+ }
-+ if (strcmp(line, "@RSYNCD: starttls") == 0) {
-+ break;
-+ }
-+ rprintf(FINFO, "%s\n", line);
-+ }
-+ if (start_tls(f_in, f_out)) {
-+ rprintf(FERROR, "rsync: error during SSL handshake: %s\n",
-+ get_ssl_error());
-+ return -1;
-+ }
-+ f_in = get_tls_rfd();
-+ f_out = get_tls_wfd();
-+ }
-+#endif
-+
- p = strchr(path,'/');
- if (p) *p = 0;
- io_printf(f_out, "%s\n", path);
-@@ -188,6 +228,10 @@
- * server to terminate the listing of modules.
- * We don't want to go on and transfer
- * anything; just exit. */
-+#if HAVE_OPENSSL
-+ if (use_ssl)
-+ end_tls();
-+#endif
- exit(0);
- }
-
-@@ -195,6 +239,10 @@
- rprintf(FERROR, "%s\n", line);
- /* This is always fatal; the server will now
- * close the socket. */
-+#if HAVE_OPENSSL
-+ if (use_ssl)
-+ end_tls();
-+#endif
- return -1;
- }
-
-@@ -590,6 +639,9 @@
- if (protocol_version > remote_protocol)
- protocol_version = remote_protocol;
-
-+#if HAVE_OPENSSL
-+retry:
-+#endif
- line[0] = 0;
- if (!read_line(f_in, line, sizeof line - 1))
- return -1;
-@@ -599,6 +651,20 @@
- return -1;
- }
-
-+#if HAVE_OPENSSL
-+ if (use_ssl && strcmp(line, "#starttls") == 0) {
-+ io_printf(f_out, "@RSYNCD: starttls\n");
-+ if (start_tls(f_in, f_out)) {
-+ rprintf(FLOG, "SSL connection failed: %s\n",
-+ get_ssl_error());
-+ return -1;
-+ }
-+ f_in = get_tls_rfd();
-+ f_out = get_tls_wfd();
-+ goto retry;
-+ }
-+#endif
-+
- if (*line == '#') {
- /* it's some sort of command that I don't understand */
- io_printf(f_out, "@ERROR: Unknown command '%s'\n", line);
-diff -urbBN rsync-2.6.6.org/configure.in rsync-2.6.6/configure.in
---- rsync-2.6.6.org/configure.in 2005-07-28 21:31:05.000000000 +0200
-+++ rsync-2.6.6/configure.in 2005-11-14 16:49:56.186884750 +0100
-@@ -293,6 +293,21 @@
- AC_SEARCH_LIBS(getaddrinfo, inet6)
- fi
-
-+AC_ARG_ENABLE(openssl,
-+ AC_HELP_STRING([--enable-openssl], [compile SSL support with OpenSSL.]))
-+
-+if test "x$enable_openssl" != xno
-+then
-+ have_ssl=yes
-+ AC_CHECK_LIB(ssl, SSL_library_init, , [have_ssl=no])
-+ if test "x$have_ssl" = xyes
-+ then
-+ AC_DEFINE(HAVE_OPENSSL, 1, [true if you want to use SSL.])
-+ SSL_OBJS=ssl.o
-+ AC_SUBST(SSL_OBJS)
-+ fi
-+fi
-+
- AC_MSG_CHECKING([whether to call shutdown on all sockets])
- case $host_os in
- *cygwin* ) AC_MSG_RESULT(yes)
-diff -urbBN rsync-2.6.6.org/Makefile.in rsync-2.6.6/Makefile.in
---- rsync-2.6.6.org/Makefile.in 2005-07-07 23:29:57.000000000 +0200
-+++ rsync-2.6.6/Makefile.in 2005-11-14 16:49:56.182884500 +0100
-@@ -38,7 +38,7 @@
- DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
- popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
- popt/popthelp.o popt/poptparse.o
--OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
-+OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@ @SSL_OBJS@
-
- TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o
-
-diff -urbBN rsync-2.6.6.org/options.c rsync-2.6.6/options.c
---- rsync-2.6.6.org/options.c 2005-05-19 10:52:17.000000000 +0200
-+++ rsync-2.6.6/options.c 2005-11-14 16:50:48.190134750 +0100
-@@ -157,6 +157,14 @@
- int always_checksum = 0;
- int list_only = 0;
-
-+#if HAVE_OPENSSL
-+int use_ssl = 0;
-+char *ssl_cert_path = NULL;
-+char *ssl_key_path = NULL;
-+char *ssl_key_passwd = NULL;
-+char *ssl_ca_path = NULL;
-+#endif
-+
- #define MAX_BATCH_NAME_LEN 256 /* Must be less than MAXPATHLEN-13 */
- char *batch_name = NULL;
-
-@@ -182,6 +190,7 @@
- char const *hardlinks = "no ";
- char const *links = "no ";
- char const *ipv6 = "no ";
-+ char const *ssl = "no ";
- STRUCT_STAT *dumstat;
-
- #ifdef HAVE_SOCKETPAIR
-@@ -204,6 +213,10 @@
- ipv6 = "";
- #endif
-
-+#if HAVE_OPENSSL
-+ ssl = "";
-+#endif
-+
- rprintf(f, "%s version %s protocol version %d\n",
- RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION);
- rprintf(f,
-@@ -217,10 +230,10 @@
- /* Note that this field may not have type ino_t. It depends
- * on the complicated interaction between largefile feature
- * macros. */
-- rprintf(f, " %sinplace, %sIPv6, %d-bit system inums, %d-bit internal inums\n",
-+ rprintf(f, " %sinplace, %sIPv6, %d-bit system inums, %d-bit internal inums, %sssl\n",
- have_inplace, ipv6,
- (int) (sizeof dumstat->st_ino * 8),
-- (int) (sizeof (int64) * 8));
-+ (int) (sizeof (int64) * 8), ssl);
- #ifdef MAINTAINER_MODE
- rprintf(f, " panic action: \"%s\"\n",
- get_panic_action());
-@@ -352,6 +365,13 @@
- rprintf(F," -4, --ipv4 prefer IPv4\n");
- rprintf(F," -6, --ipv6 prefer IPv6\n");
- #endif
-+#if HAVE_OPENSSL
-+ rprintf(F," --ssl allow socket connections to use SSL\n");
-+ rprintf(F," --ssl-cert=FILE path to daemon's SSL certificate\n");
-+ rprintf(F," --ssl-key=FILE path to daemon's SSL private key\n");
-+ rprintf(F," --ssl-key-passwd=PASS password for PEM-encoded private key\n");
-+ rprintf(F," --ssl-ca-certs=FILE path to trusted CA certificates\n");
-+#endif
- rprintf(F," --version print version number\n");
- rprintf(F," -h, --help show this help screen\n");
-
-@@ -362,7 +382,7 @@
-
- enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
- OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST,
-- OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
-+ OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_USE_SSL,
- OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
- OPT_REFUSED_BASE = 9000};
-
-@@ -464,6 +484,13 @@
- {"ipv4", '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 },
- {"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
- #endif
-+#if HAVE_OPENSSL
-+ {"ssl", 0, POPT_ARG_NONE, 0, OPT_USE_SSL, 0, 0},
-+ {"ssl-cert", 0, POPT_ARG_STRING, &ssl_cert_path, OPT_USE_SSL, 0, 0},
-+ {"ssl-key", 0, POPT_ARG_STRING, &ssl_key_path, OPT_USE_SSL, 0, 0},
-+ {"ssl-key-passwd", 0, POPT_ARG_STRING, &ssl_key_passwd, OPT_USE_SSL, 0, 0},
-+ {"ssl-ca-certs", 0, POPT_ARG_STRING, &ssl_ca_path, OPT_USE_SSL, 0, 0},
-+#endif
- /* All these options switch us into daemon-mode option-parsing. */
- {"config", 0, POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
- {"daemon", 0, POPT_ARG_NONE, 0, OPT_DAEMON, 0, 0 },
-@@ -508,6 +535,13 @@
- {"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 },
- {"protocol", 0, POPT_ARG_INT, &protocol_version, 0, 0, 0 },
- {"server", 0, POPT_ARG_NONE, &am_server, 0, 0, 0 },
-+#if HAVE_OPENSSL
-+ {"ssl", 0, POPT_ARG_NONE, 0, OPT_USE_SSL, 0, 0},
-+ {"ssl-cert", 0, POPT_ARG_STRING, &ssl_cert_path, OPT_USE_SSL, 0, 0},
-+ {"ssl-key", 0, POPT_ARG_STRING, &ssl_key_path, OPT_USE_SSL, 0, 0},
-+ {"ssl-key-passwd", 0, POPT_ARG_STRING, &ssl_key_passwd, OPT_USE_SSL, 0, 0},
-+ {"ssl-ca-certs", 0, POPT_ARG_STRING, &ssl_ca_path, OPT_USE_SSL, 0, 0},
-+#endif
- {"verbose", 'v', POPT_ARG_NONE, 0, 'v', 0, 0 },
- {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0 },
- {0,0,0,0, 0, 0, 0}
-@@ -876,6 +910,12 @@
- basis_dir[basis_dir_cnt++] = (char *)arg;
- break;
-
-+ case OPT_USE_SSL:
-+#if HAVE_OPENSSL
-+ use_ssl = 1;
-+#endif
-+ break;
-+
- default:
- /* A large opt value means that set_refuse_options()
- * turned this option off. */
-@@ -1129,6 +1169,17 @@
- if (delay_updates && !partial_dir)
- partial_dir = partialdir_for_delayupdate;
-
-+#if HAVE_OPENSSL
-+ if (use_ssl) {
-+ if (init_tls()) {
-+ snprintf(err_buf, sizeof(err_buf),
-+ "Openssl error: %s\n",
-+ get_ssl_error());
-+ return 0;
-+ }
-+ }
-+#endif
-+
- if (inplace) {
- #ifdef HAVE_FTRUNCATE
- if (partial_dir) {
-@@ -1498,11 +1549,28 @@
- {
- char *p;
- int not_host;
-+ int url_prefix_len = sizeof URL_PREFIX - 1;
-
-- if (port_ptr && strncasecmp(URL_PREFIX, s, strlen(URL_PREFIX)) == 0) {
-+ if (!port_ptr)
-+ url_prefix_len = 0;
-+ else if (strncasecmp(URL_PREFIX, s, url_prefix_len) != 0) {
-+#if HAVE_OPENSSL
-+ url_prefix_len = sizeof SSL_URL_PREFIX - 1;
-+ if (strncasecmp(SSL_URL_PREFIX, s, url_prefix_len) != 0)
-+ url_prefix_len = 0;
-+ else {
-+ if (!use_ssl)
-+ init_tls();
-+ use_ssl = 1;
-+ }
-+#else
-+ url_prefix_len = 0;
-+#endif
-+ }
-+ if (url_prefix_len) {
- char *path;
- int hostlen;
-- s += strlen(URL_PREFIX);
-+ s += url_prefix_len;
- if ((p = strchr(s, '/')) != NULL) {
- hostlen = p - s;
- path = p + 1;
-diff -urbBN rsync-2.6.6.org/rsync.h rsync-2.6.6/rsync.h
---- rsync-2.6.6.org/rsync.h 2005-05-03 19:00:47.000000000 +0200
-+++ rsync-2.6.6/rsync.h 2005-11-14 16:49:56.190885000 +0100
-@@ -32,6 +32,7 @@
-
- #define DEFAULT_LOCK_FILE "/var/run/rsyncd.lock"
- #define URL_PREFIX "rsync://"
-+#define SSL_URL_PREFIX "rsyncs://"
-
- #define BACKUP_SUFFIX "~"
-
-@@ -410,6 +411,11 @@
- # define SIZEOF_INT64 SIZEOF_OFF_T
- #endif
-
-+#if HAVE_OPENSSL
-+#include <openssl/ssl.h>
-+#include <openssl/err.h>
-+#endif
-+
- /* Starting from protocol version 26, we always use 64-bit
- * ino_t and dev_t internally, even if this platform does not
- * allow files to have 64-bit inums. That's because the
-diff -urbBN rsync-2.6.6.org/ssl.c rsync-2.6.6/ssl.c
---- rsync-2.6.6.org/ssl.c 1970-01-01 01:00:00.000000000 +0100
-+++ rsync-2.6.6/ssl.c 2005-11-14 16:49:56.190885000 +0100
-@@ -0,0 +1,366 @@
-+/* -*- c-file-style: "linux" -*-
-+ * ssl.c: operations for negotiating SSL rsync connections.
-+ *
-+ * Copyright (C) 2003 Casey Marshall <rsdio@metastatic.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.
-+ */
-+
-+#include "rsync.h"
-+
-+#if HAVE_SYS_SELECT_H
-+#include <sys/select.h>
-+#else
-+#include <sys/time.h>
-+#include <sys/types.h>
-+#include <unistd.h>
-+#endif
-+#include <string.h>
-+
-+#define BUF_SIZE 1024
-+
-+extern int verbose;
-+extern int am_daemon;
-+extern int am_server;
-+
-+extern char *ssl_cert_path;
-+extern char *ssl_key_path;
-+extern char *ssl_key_passwd;
-+extern char *ssl_ca_path;
-+
-+static SSL_CTX *ssl_ctx;
-+static SSL *ssl;
-+static int tls_read[2] = { -1, -1 };
-+static int tls_write[2] = { -1, -1 };
-+static int ssl_running;
-+static int ssl_pid = -1;
-+
-+/**
-+ * A non-interactive callback to be passed to SSL_CTX_set_default_password_cb,
-+ * which merely copies the value of ssl_key_passwd into buf. This is
-+ * used for when the private key password is supplied via an option.
-+ */
-+static int default_password_cb(char *buf, int n, UNUSED(int f), UNUSED(void *u))
-+{
-+ if (ssl_key_passwd == NULL || n < (int)strlen(ssl_key_passwd))
-+ return 0;
-+ strncpy(buf, ssl_key_passwd, n-1);
-+ return strlen(ssl_key_passwd);
-+}
-+
-+/**
-+ * If verbose, this method traces the status of the SSL handshake.
-+ */
-+static void info_callback(const SSL *ssl, int cb, int val)
-+{
-+ char buf[128];
-+ char *cbs;
-+
-+ switch (cb) {
-+ case SSL_CB_LOOP:
-+ cbs = "SSL_CB_LOOP";
-+ break;
-+ case SSL_CB_EXIT:
-+ cbs = "SSL_CB_EXIT";
-+ break;
-+ case SSL_CB_READ:
-+ cbs = "SSL_CB_READ";
-+ break;
-+ case SSL_CB_WRITE:
-+ cbs = "SSL_CB_WRITE";
-+ break;
-+ case SSL_CB_ALERT:
-+ cbs = "SSL_CB_ALERT";
-+ break;
-+ case SSL_CB_READ_ALERT:
-+ cbs = "SSL_CB_READ_ALERT";
-+ break;
-+ case SSL_CB_WRITE_ALERT:
-+ cbs = "SSL_CB_WRITE_ALERT";
-+ break;
-+ case SSL_CB_ACCEPT_LOOP:
-+ cbs = "SSL_CB_ACCEPT_LOOP";
-+ break;
-+ case SSL_CB_ACCEPT_EXIT:
-+ cbs = "SSL_CB_ACCEPT_EXIT";
-+ break;
-+ case SSL_CB_CONNECT_LOOP:
-+ cbs = "SSL_CB_CONNECT_LOOP";
-+ break;
-+ case SSL_CB_CONNECT_EXIT:
-+ cbs = "SSL_CB_CONNECT_EXIT";
-+ break;
-+ case SSL_CB_HANDSHAKE_START:
-+ cbs = "SSL_CB_HANDSHAKE_START";
-+ break;
-+ case SSL_CB_HANDSHAKE_DONE:
-+ cbs = "SSL_CB_HANDSHAKE_DONE";
-+ break;
-+ default:
-+ snprintf(buf, sizeof buf, "??? (%d)", cb);
-+ cbs = buf;
-+ break;
-+ }
-+ if (verbose > 2) {
-+ rprintf(FLOG, "SSL: info_callback(%p,%s,%d)\n", ssl, cbs, val);
-+ if (cb == SSL_CB_HANDSHAKE_DONE) {
-+ SSL_CIPHER_description(SSL_get_current_cipher((SSL*)ssl),
-+ buf, sizeof buf);
-+ rprintf(FLOG, "SSL: cipher: %s", buf);
-+ }
-+ }
-+}
-+
-+/**
-+ * Initializes the SSL context for TLSv1 connections; returns zero on
-+ * success.
-+ */
-+int init_tls(void)
-+{
-+ if (ssl_ctx)
-+ return 0;
-+ SSL_library_init();
-+ SSL_load_error_strings();
-+ ssl_ctx = SSL_CTX_new(TLSv1_method());
-+ if (!ssl_ctx)
-+ return 1;
-+ SSL_CTX_set_info_callback(ssl_ctx, info_callback);
-+
-+ /* Sets the certificate sent to the other party. */
-+ if (ssl_cert_path != NULL
-+ && SSL_CTX_use_certificate_file(ssl_ctx, ssl_cert_path,
-+ SSL_FILETYPE_PEM) != 1)
-+ return 1;
-+ /* Set up the simple non-interactive callback if the password
-+ * was supplied on the command line. */
-+ if (ssl_key_passwd != NULL)
-+ SSL_CTX_set_default_passwd_cb(ssl_ctx, default_password_cb);
-+ /* Sets the private key that matches the public certificate. */
-+ if (ssl_key_path != NULL) {
-+ if (SSL_CTX_use_PrivateKey_file(ssl_ctx, ssl_key_path,
-+ SSL_FILETYPE_PEM) != 1)
-+ return 1;
-+ if (SSL_CTX_check_private_key(ssl_ctx) != 1)
-+ return 1;
-+ }
-+ if (ssl_ca_path != NULL
-+ && !SSL_CTX_load_verify_locations(ssl_ctx, ssl_ca_path, NULL))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/**
-+ * Returns the error string for the current SSL error, if any.
-+ */
-+char *get_ssl_error(void)
-+{
-+ return ERR_error_string(ERR_get_error(), NULL);
-+}
-+
-+/**
-+ * Returns the input file descriptor for the SSL connection.
-+ */
-+int get_tls_rfd(void)
-+{
-+ return tls_read[0];
-+}
-+
-+/**
-+ * Returns the output file descriptor for the SSL connection.
-+ */
-+int get_tls_wfd(void)
-+{
-+ return tls_write[1];
-+}
-+
-+/**
-+ * Signal handler that ends the SSL connection.
-+ */
-+static RETSIGTYPE tls_sigusr1(int UNUSED(val))
-+{
-+ if (ssl) {
-+ SSL_shutdown(ssl);
-+ SSL_free(ssl);
-+ ssl = NULL;
-+ }
-+ ssl_running = 0;
-+}
-+
-+/**
-+ * Negotiates the TLS connection, creates a socket pair for communicating
-+ * with the rsync process, then forks into a new process that will handle
-+ * the communication.
-+ *
-+ * 0 is returned on success.
-+ */
-+int start_tls(int f_in, int f_out)
-+{
-+ int tls_fd;
-+ int n = 0, r;
-+ unsigned char buf1[BUF_SIZE], buf2[BUF_SIZE];
-+ int avail1 = 0, avail2 = 0, write1 = 0, write2 = 0;
-+ fd_set rd, wd;
-+
-+ if (fd_pair(tls_read))
-+ return 1;
-+ if (fd_pair(tls_write))
-+ return 1;
-+
-+ set_blocking(tls_read[0]);
-+ set_blocking(tls_read[1]);
-+ set_blocking(tls_write[0]);
-+ set_blocking(tls_write[1]);
-+ set_blocking(f_in);
-+ set_blocking(f_out);
-+
-+ ssl_pid = do_fork();
-+ if (ssl_pid < 0)
-+ return -1;
-+ if (ssl_pid != 0) {
-+ close(tls_write[0]);
-+ close(tls_read[1]);
-+ return 0;
-+ }
-+
-+ signal(SIGUSR1, tls_sigusr1);
-+ ssl = SSL_new(ssl_ctx);
-+ if (!ssl)
-+ goto closed;
-+ if (am_daemon || am_server)
-+ SSL_set_accept_state(ssl);
-+ else
-+ SSL_set_connect_state(ssl);
-+ SSL_set_rfd(ssl, f_in);
-+ SSL_set_wfd(ssl, f_out);
-+
-+ tls_fd = SSL_get_fd(ssl);
-+ n = tls_write[0];
-+ n = MAX(tls_read[1], n);
-+ n = MAX(tls_fd, n) + 1;
-+
-+ ssl_running = 1;
-+ while (ssl_running) {
-+ FD_ZERO(&rd);
-+ FD_ZERO(&wd);
-+ FD_SET(tls_write[0], &rd);
-+ FD_SET(tls_read[1], &wd);
-+ FD_SET(tls_fd, &rd);
-+ FD_SET(tls_fd, &wd);
-+
-+ r = select(n, &rd, &wd, NULL, NULL);
-+
-+ if (r == -1 && errno == EINTR)
-+ continue;
-+ if (FD_ISSET(tls_write[0], &rd)) {
-+ r = read(tls_write[0], buf1+avail1, BUF_SIZE-avail1);
-+ if (r >= 0)
-+ avail1 += r;
-+ else {
-+ rprintf(FERROR, "pipe read error: %s\n",
-+ strerror(errno));
-+ break;
-+ }
-+ }
-+ if (FD_ISSET(tls_fd, &rd)) {
-+ r = SSL_read(ssl, buf2+avail2, BUF_SIZE-avail2);
-+ if (r > 0)
-+ avail2 += r;
-+ else {
-+ switch (SSL_get_error(ssl, r)) {
-+ case SSL_ERROR_ZERO_RETURN:
-+ goto closed;
-+ case SSL_ERROR_WANT_READ:
-+ case SSL_ERROR_WANT_WRITE:
-+ break;
-+ case SSL_ERROR_SYSCALL:
-+ if (r == 0)
-+ rprintf(FERROR, "SSL spurious EOF\n");
-+ else
-+ rprintf(FERROR, "SSL I/O error: %s\n",
-+ strerror(errno));
-+ goto closed;
-+ case SSL_ERROR_SSL:
-+ rprintf(FERROR, "SSL: %s\n",
-+ ERR_error_string(ERR_get_error(), NULL));
-+ goto closed;
-+ default:
-+ rprintf(FERROR, "unexpected ssl error %d\n", r);
-+ goto closed;
-+ }
-+ }
-+ }
-+ if (FD_ISSET(tls_read[1], &wd) && write2 < avail2) {
-+ r = write(tls_read[1], buf2+write2, avail2-write2);
-+ if (r >= 0)
-+ write2 += r;
-+ else {
-+ rprintf(FERROR, "pipe write error: %s\n",
-+ strerror(errno));
-+ break;
-+ }
-+ }
-+ if (FD_ISSET(tls_fd, &wd) && write1 < avail1) {
-+ r = SSL_write(ssl, buf1+write1, avail1-write1);
-+ if (r > 0)
-+ write1 += r;
-+ else {
-+ switch (SSL_get_error(ssl, r)) {
-+ case SSL_ERROR_ZERO_RETURN:
-+ goto closed;
-+ case SSL_ERROR_WANT_READ:
-+ case SSL_ERROR_WANT_WRITE:
-+ break;
-+ case SSL_ERROR_SYSCALL:
-+ if (r == 0)
-+ rprintf(FERROR, "SSL: spurious EOF\n");
-+ else
-+ rprintf(FERROR, "SSL: I/O error: %s\n",
-+ strerror(errno));
-+ goto closed;
-+ case SSL_ERROR_SSL:
-+ rprintf(FERROR, "SSL: %s\n",
-+ ERR_error_string(ERR_get_error(), NULL));
-+ goto closed;
-+ default:
-+ rprintf(FERROR, "unexpected ssl error %d\n", r);
-+ goto closed;
-+ }
-+ }
-+ }
-+ if (avail1 == write1)
-+ avail1 = write1 = 0;
-+ if (avail2 == write2)
-+ avail2 = write2 = 0;
-+ }
-+
-+ /* XXX I'm pretty sure that there is a lot that I am not considering
-+ here. Bugs? Yes, probably. */
-+
-+ /* We're finished. */
-+ closed:
-+ close(tls_read[1]);
-+ close(tls_write[0]);
-+ exit(0);
-+}
-+
-+/**
-+ * Ends the TLS connection.
-+ */
-+void end_tls(void)
-+{
-+ if (ssl_pid > 0)
-+ kill(ssl_pid, SIGUSR1);
-+}
+++ /dev/null
-Common subdirectories: rsync-2.6.4pre2-prexattr/autom4te.cache and rsync-2.6.4pre2/autom4te.cache
-diff -u -N rsync-2.6.4pre2-prexattr/backup.c rsync-2.6.4pre2/backup.c
---- rsync-2.6.4pre2-prexattr/backup.c 2005-03-02 20:15:48.000000000 -0500
-+++ rsync-2.6.4pre2/backup.c 2005-03-02 20:20:46.000000000 -0500
-@@ -136,6 +136,7 @@
- do_lchown(fullpath, st.st_uid, st.st_gid);
- do_chmod(fullpath, st.st_mode);
- (void)DUP_ACL(end, fullpath, st.st_mode);
-+ (void)DUP_XATTR(end, fullpath );
- }
- }
- *p = '/';
-@@ -189,6 +190,7 @@
- return 0;
-
- PUSH_KEEP_BACKUP_ACL(file, fname, buf);
-+ PUSH_KEEP_BACKUP_XATTR( file, fname, buf );
-
- /* Check to see if this is a device file, or link */
- if (IS_DEVICE(file->mode)) {
-@@ -264,6 +266,7 @@
- }
- set_perms(buf, file, NULL, 0);
- CLEANUP_KEEP_BACKUP_ACL();
-+ CLEANUP_KEEP_BACKUP_XATTR();
- free(file);
-
- if (verbose > 1) {
-diff -u -N rsync-2.6.4pre2-prexattr/configure.in rsync-2.6.4pre2/configure.in
---- rsync-2.6.4pre2-prexattr/configure.in 2005-03-02 20:15:48.000000000 -0500
-+++ rsync-2.6.4pre2/configure.in 2005-03-02 20:20:46.000000000 -0500
-@@ -789,6 +789,30 @@
- AC_MSG_RESULT(no)
- )
-
-+AC_CHECK_HEADERS(attr/xattr.h)
-++AC_MSG_CHECKING(whether to support extended attributes)
-+AC_ARG_WITH(xattr-support,
-+[ --with-xattr-support Include extended attribute support (default=no)],
-+[ case "$withval" in
-+ yes)
-+ case "$host_os" in
-+ *linux*)
-+ AC_MSG_RESULT(Using Linux xattrs)
-+ AC_DEFINE(HAVE_LINUX_XATTRS, 1, [True if you have Linux xattrs])
-+ ;;
-+ *)
-+ AC_MSG_RESULT(Xattrs requested but not linux. Good luck)
-+ ;;
-+ esac
-+ ;;
-+ *)
-+ AC_MSG_RESULT(no)
-+ AC_DEFINE(HAVE_NA_XATTRS, 1, [True if you don't have extended attributes])
-+ esac ],
-+ AC_MSG_RESULT(no)
-+ AC_DEFINE(HAVE_NO_XATTRL, 1, [True if you don't have extended attributes])
-+)
-+
- AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
- AC_OUTPUT
-
-diff -u -N rsync-2.6.4pre2-prexattr/options.c rsync-2.6.4pre2/options.c
---- rsync-2.6.4pre2-prexattr/options.c 2005-03-02 20:15:48.000000000 -0500
-+++ rsync-2.6.4pre2/options.c 2005-03-02 20:31:22.000000000 -0500
-@@ -45,6 +45,7 @@
- int preserve_links = 0;
- int preserve_hard_links = 0;
- int preserve_acls = 0;
-+int preserve_xattrs = 0;
- int preserve_perms = 0;
- int preserve_devices = 0;
- int preserve_uid = 0;
-@@ -180,6 +181,7 @@
- char const *have_inplace = "no ";
- char const *hardlinks = "no ";
- char const *acls = "no ";
-+ char const *xattrs = "no ";
- char const *links = "no ";
- char const *ipv6 = "no ";
- STRUCT_STAT *dumstat;
-@@ -199,7 +201,9 @@
- #ifdef SUPPORT_ACLS
- acls = "";
- #endif
--
-+#if SUPPORT_XATTRS
-+ xattrs = "";
-+#endif
- #ifdef SUPPORT_LINKS
- links = "";
- #endif
-@@ -214,9 +218,9 @@
- "Copyright (C) 1996-2005 by Andrew Tridgell and others\n");
- rprintf(f, "<http://rsync.samba.org/>\n");
- rprintf(f, "Capabilities: %d-bit files, %ssocketpairs, "
-- "%shard links, %sACLs, %ssymlinks, batchfiles, \n",
-+ "%shard links, %sACLs, %sxattrs, %ssymlinks, batchfiles, \n",
- (int) (sizeof (OFF_T) * 8),
-- got_socketpair, hardlinks, acls, links);
-+ got_socketpair, hardlinks, acls, xattrs, links);
-
- /* Note that this field may not have type ino_t. It depends
- * on the complicated interaction between largefile feature
-@@ -287,6 +291,7 @@
- rprintf(F," -K, --keep-dirlinks treat symlinked dir on receiver as dir\n");
- rprintf(F," -p, --perms preserve permissions\n");
- rprintf(F," -A, --acls preserve ACLs (implies --perms)\n");
-+ rprintf(F," -X, --xattrs preserve extended attributes (implies --perms)\n");
- rprintf(F," -o, --owner preserve owner (root only)\n");
- rprintf(F," -g, --group preserve group\n");
- rprintf(F," -D, --devices preserve devices (root only)\n");
-@@ -410,6 +415,7 @@
- {"copy-unsafe-links",0, POPT_ARG_NONE, ©_unsafe_links, 0, 0, 0 },
- {"perms", 'p', POPT_ARG_NONE, &preserve_perms, 0, 0, 0 },
- {"acls", 'A', POPT_ARG_NONE, 0, 'A', 0, 0 },
-+ {"xattrs", 'X', POPT_ARG_NONE, 0, 'X', 0, 0 },
- {"owner", 'o', POPT_ARG_NONE, &preserve_uid, 0, 0, 0 },
- {"group", 'g', POPT_ARG_NONE, &preserve_gid, 0, 0, 0 },
- {"devices", 'D', POPT_ARG_NONE, &preserve_devices, 0, 0, 0 },
-@@ -879,6 +885,17 @@
- #endif /* SUPPORT_ACLS */
- break;
-
-+ case 'X':
-+#if SUPPORT_XATTRS
-+ preserve_xattrs = 1;
-+ preserve_perms = 1;
-+#else
-+ snprintf(err_buf,sizeof(err_buf),
-+ "extended attributes are not supported on this %s\n",
-+ am_server ? "server" : "client");
-+ return 0;
-+#endif /* SUPPORT_XATTRS */
-+ break;
-
- default:
- /* A large opt value means that set_refuse_options()
-@@ -1289,6 +1306,8 @@
- argstr[x++] = 'H';
- if (preserve_acls)
- argstr[x++] = 'A';
-+ if ( preserve_xattrs )
-+ argstr[x++] = 'X';
- if (preserve_uid)
- argstr[x++] = 'o';
- if (preserve_gid)
-Common subdirectories: rsync-2.6.4pre2-prexattr/packaging and rsync-2.6.4pre2/packaging
-Common subdirectories: rsync-2.6.4pre2-prexattr/patches and rsync-2.6.4pre2/patches
-Common subdirectories: rsync-2.6.4pre2-prexattr/popt and rsync-2.6.4pre2/popt
-diff -u -N rsync-2.6.4pre2-prexattr/rsync.c rsync-2.6.4pre2/rsync.c
---- rsync-2.6.4pre2-prexattr/rsync.c 2005-03-02 20:15:48.000000000 -0500
-+++ rsync-2.6.4pre2/rsync.c 2005-03-02 20:31:22.000000000 -0500
-@@ -145,6 +145,14 @@
- if (SET_ACL(fname, file) == 0)
- updated = 1;
- }
-+ /* If this is a directory, SET_XATTR() will be called on the cleanup
-+ * receive_generator() pass--if we called it here, we might clobber
-+ * writability on the directory (SELinux security contexts are stored
-+ * in xattrs). everything else is OK to do now. */
-+ if (!S_ISDIR(st->st_mode)) {
-+ if (SET_XATTR(fname, file) == 0)
-+ updated = 1;
-+ }
-
- if (verbose > 1 && flags & PERMS_REPORT) {
- enum logcode code = daemon_log_format_has_i || dry_run
-diff -u -N rsync-2.6.4pre2-prexattr/rsync.h rsync-2.6.4pre2/rsync.h
---- rsync-2.6.4pre2-prexattr/rsync.h 2005-03-02 20:15:48.000000000 -0500
-+++ rsync-2.6.4pre2/rsync.h 2005-03-02 20:32:39.000000000 -0500
-@@ -662,6 +662,36 @@
- #endif /* SUPPORT_ACLS */
- #include "smb_acls.h"
-
-+#define SUPPORT_XATTRS HAVE_LINUX_XATTRS
-+
-+#if SUPPORT_XATTRS
-+#ifdef HAVE_ATTR_XATTR_H
-+#include <attr/xattr.h>
-+#endif
-+#define MAKE_XATTR(file, fname) make_xattr(file, fname)
-+#define SEND_XATTR(file, f) send_xattr(file, f)
-+#define RECEIVE_XATTR(file, f) receive_xattr(file, f)
-+#define SORT_FILE_XATTR_INDEX_LISTS() sort_file_xattr_index_lists()
-+#define SET_XATTR(fname, file) set_xattr(fname, file)
-+#define NEXT_XATTR_UID() next_xattr_uid()
-+#define XATTR_UID_MAP(uid) xattr_uid_map(uid)
-+#define PUSH_KEEP_BACKUP_XATTR(file, orig, dest) \
-+ push_keep_backup_xattr(file, orig, dest)
-+#define CLEANUP_KEEP_BACKUP_XATTR() cleanup_keep_backup_xattr()
-+#define DUP_XATTR(orig, dest) dup_xattr(orig, dest)
-+#else /* SUPPORT_XATTRS */
-+#define MAKE_XATTR(file, fname) 1 /* checked return value */
-+#define SEND_XATTR(file, f)
-+#define RECEIVE_XATTR(file, f)
-+#define SORT_FILE_XATTR_INDEX_LISTS()
-+#define SET_XATTR(fname, file) 0 /* checked return value */
-+#define NEXT_XATTR_UID()
-+#define XATTR_UID_MAP(uid)
-+#define PUSH_KEEP_BACKUP_XATTR(file, orig, dest)
-+#define CLEANUP_KEEP_BACKUP_XATTR()
-+#define DUP_XATTR(src, orig) 0 /* checked return value */
-+#endif /* SUPPORT_XATTRS */
-+
- #include "proto.h"
-
- /* We have replacement versions of these if they're missing. */
-diff -u -N rsync-2.6.4pre2-prexattr/rsync.yo rsync-2.6.4pre2/rsync.yo
---- rsync-2.6.4pre2-prexattr/rsync.yo 2005-03-02 20:15:48.000000000 -0500
-+++ rsync-2.6.4pre2/rsync.yo 2005-03-02 20:33:53.000000000 -0500
-@@ -318,6 +318,7 @@
- -K, --keep-dirlinks treat symlinked dir on receiver as dir
- -p, --perms preserve permissions
- -A, --acls preserve ACLs (implies -p) [local option]
-+ -X, --xattrs preserve extended attributes (implies -p) [local option]
- -o, --owner preserve owner (root only)
- -g, --group preserve group
- -D, --devices preserve devices (root only)
-@@ -630,6 +631,11 @@
- remote machine's rsync supports this option also. This is a non-standard
- option.
-
-+dit(bf(-X, --xattrs)) This option causes rsync to update the remote
-+extended attributes to be the same as the local ones. This will work
-+only if the remote machine's rsync supports this option also. This is
-+a non-standard option.
-+
- dit(bf(-o, --owner)) This option causes rsync to set the owner of the
- destination file to be the same as the source file. On most systems,
- only the super-user can set file ownership. By default, the preservation
-Common subdirectories: rsync-2.6.4pre2-prexattr/support and rsync-2.6.4pre2/support
-diff -u -N rsync-2.6.4pre2-prexattr/lib/sysxattr.c rsync-2.6.4pre2/sysxattr.c
---- rsync-2.6.4pre2-prexattr/lib/sysxattr.c 1969-12-31 19:00:00.000000000 -0500
-+++ rsync-2.6.4pre2/lib/sysxattr.c 2005-03-02 20:34:10.000000000 -0500
-@@ -0,0 +1,41 @@
-+/* Extended attribute support for rsync. */
-+/* This file Copyright (C) 2004 Red Hat, Inc. */
-+/* Written by Jay Fenlason */
-+
-+/* 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.
-+*/
-+
-+#include "rsync.h"
-+
-+#if defined(HAVE_LINUX_XATTRS)
-+
-+ssize_t sys_lgetxattr ( const char *path, const char *name, void *value, size_t size )
-+{
-+ return lgetxattr ( path, name, value, size );
-+}
-+
-+int sys_lsetxattr ( const char *path, const char *name, const void *value, size_t size, int flags )
-+{
-+ return lsetxattr ( path, name, value, size, flags );
-+}
-+
-+ssize_t sys_llistxattr ( const char *path, char *list, size_t size )
-+{
-+ return llistxattr ( path, list, size );
-+}
-+
-+#else
-+
-+#endif /* No xattrs */
-Common subdirectories: rsync-2.6.4pre2-prexattr/testhelp and rsync-2.6.4pre2/testhelp
-Common subdirectories: rsync-2.6.4pre2-prexattr/testsuite and rsync-2.6.4pre2/testsuite
-diff -u -N rsync-2.6.4pre2-prexattr/xattr.c rsync-2.6.4pre2/xattr.c
---- rsync-2.6.4pre2-prexattr/xattr.c 1969-12-31 19:00:00.000000000 -0500
-+++ rsync-2.6.4pre2/xattr.c 2005-03-02 20:34:47.000000000 -0500
-@@ -0,0 +1,556 @@
-+/* Extended Attribute support for rsync */
-+/* Copyright (C) 2004 Red Hat, Inc */
-+/* Written by Jay Fenlason, vaguely based on the ACLs patch */
-+
-+/* 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.
-+*/
-+
-+#include "rsync.h"
-+
-+#if SUPPORT_XATTRS
-+
-+extern int preserve_xattrs;
-+extern int dry_run;
-+
-+#define RSYNC_XAL_INITIAL 5
-+#define RSYNC_XAL_LIST_INITIAL 100
-+
-+
-+typedef struct {
-+ size_t name_len;
-+ char *name;
-+ size_t datum_len;
-+ char *datum;
-+} rsync_xa;
-+
-+typedef struct {
-+ size_t count;
-+ size_t alloc;
-+ rsync_xa *rxas;
-+} rsync_xal;
-+
-+typedef struct {
-+ size_t count;
-+ size_t alloc;
-+ rsync_xal *rxals;
-+} rsync_xal_list;
-+
-+static size_t namebuf_len = 0;
-+static char *namebuf = NULL;
-+
-+static size_t datumbuf_len = 0;
-+static char *datumbuf = NULL;
-+
-+static rsync_xal curr_rsync_xal = { 0, 0, NULL };
-+static rsync_xal_list rsync_xal_l = { 0, 0, NULL };
-+
-+
-+/* ------------------------------------------------------------------------- */
-+\f
-+/* the below stuff is only used by the receiver */
-+
-+/* structure to hold index to rsync_xal_l member corresponding to
-+ * flist->files[i] */
-+
-+typedef struct {
-+ const struct file_struct *file;
-+ int xalidx;
-+} file_xal_index;
-+
-+typedef struct {
-+ size_t count;
-+ size_t alloc;
-+ file_xal_index *filexalidxs;
-+} file_xal_index_list;
-+
-+static file_xal_index_list fxil = {0, 0, NULL };
-+
-+/* stuff for redirecting calls to set_acl() from set_perms()
-+ * for keep_backup() */
-+static const struct file_struct *backup_orig_file = NULL;
-+static const char null_string[] = "";
-+static const char *backup_orig_fname = null_string;
-+static const char *backup_dest_fname = null_string;
-+static rsync_xal backup_xal;
-+
-+/* ------------------------------------------------------------------------- */
-+
-+static void rsync_xal_free ( rsync_xal *x ) {
-+ size_t i;
-+
-+ for ( i = 0; i < x->count; i++ ) {
-+ free ( x->rxas[i].name );
-+ /* free ( x->rxas[i].value ); */
-+ }
-+ x->count = 0;
-+}
-+
-+static int rsync_xal_compare_names ( const void *x1, const void *x2 ) {
-+ const rsync_xa *xa1;
-+ const rsync_xa *xa2;
-+
-+ xa1 = x1;
-+ xa2 = x2;
-+ return strcmp ( xa1->name, xa2->name );
-+}
-+
-+static BOOL rsync_xal_get ( const char *fname, rsync_xal *x ) {
-+ ssize_t name_size;
-+ ssize_t datum_size;
-+ ssize_t left;
-+ char *name;
-+ size_t len;
-+ char *ptr;
-+
-+ if ( ! namebuf ) {
-+ namebuf_len = 100;
-+ namebuf = malloc ( 100 );
-+ datumbuf_len = 100;
-+ datumbuf = malloc ( 100 );
-+ if ( ! namebuf || ! datumbuf ) {
-+ rprintf(FERROR, "%s: rsync_xal_get: allocate intial buffers failed: %s\n",
-+ fname, strerror(errno));
-+ return False;
-+ }
-+ }
-+
-+ name_size = sys_llistxattr ( fname, namebuf, namebuf_len );
-+ if ( name_size > namebuf_len ) {
-+ name_size = -1;
-+ errno = ERANGE;
-+ }
-+ if ( name_size < 0 ) {
-+ if ( errno == ENOTSUP )
-+ return False;
-+ if ( errno == ERANGE ) {
-+ name_size = sys_llistxattr ( fname, NULL, 0 );
-+ if ( name_size < 0 ) {
-+ rprintf ( FERROR, "%s: rsync_xal_get: llistxattr: %s\n",
-+ fname, strerror(errno) );
-+ return False;
-+ }
-+ namebuf = realloc ( namebuf, name_size + 1 );
-+ if ( ! namebuf ) {
-+ rprintf ( FERROR, "%s: rsync_xal_get: reallocate namebuf to %lu failed: %s\n",
-+ fname, (unsigned long)name_size, strerror(errno) );
-+ return False;
-+ }
-+ namebuf_len = name_size;
-+ name_size = sys_llistxattr ( fname, namebuf, namebuf_len );
-+ if ( name_size < 0 ) {
-+ rprintf ( FERROR, "%s: rsync_xal_get: re-llistxattr failed: %s\n",
-+ fname, strerror(errno) );
-+ return False;
-+ }
-+ } else {
-+ rprintf(FERROR, "%s: rsync_xal_get: llistxattr failed: %s\n",
-+ fname, strerror(errno));
-+ return False;
-+ }
-+ }
-+ rsync_xal_free ( x );
-+ if ( name_size == 0 )
-+ return True;
-+ for ( left = name_size, name = namebuf; left > 0 ; left -= len, name += len ) {
-+ len = strlen ( name ) + 1;
-+
-+ if ( x->count >= x->alloc ) {
-+ size_t new_alloc;
-+ size_t new_size;
-+ rsync_xa *new_rxas;
-+
-+ new_alloc = ( x->alloc < RSYNC_XAL_INITIAL ) ? RSYNC_XAL_INITIAL : x->alloc * 2;
-+ new_size = new_alloc * sizeof(rsync_xa);
-+ new_rxas = x->alloc ? realloc ( x->rxas, new_size ) : malloc ( new_size );
-+ if ( new_rxas == NULL ) {
-+ rprintf(FERROR, "%s: rsync_xal_get: allocate %lufailed: %s\n",
-+ fname, (unsigned long)new_size, strerror(errno));
-+ return False;
-+ }
-+ x->alloc = new_alloc;
-+ x->rxas = new_rxas;
-+ }
-+ datum_size = sys_lgetxattr ( fname, name, datumbuf, datumbuf_len );
-+ if ( datum_size > datumbuf_len ) {
-+ datum_size = -1;
-+ errno = ERANGE;
-+ }
-+ if ( datum_size < 0 ) {
-+ if ( errno == ENOTSUP )
-+ return False;
-+ if ( errno == ERANGE ) {
-+ datum_size = sys_lgetxattr ( fname, name, NULL, 0 );
-+ if ( datum_size < 0 ) {
-+ rprintf ( FERROR, "%s: rsync_xal_get: lgetxattr %s failed: %s\n",
-+ fname, name, strerror(errno) );
-+ return False;
-+ }
-+ datumbuf = realloc ( datumbuf, datum_size + 1 );
-+ if ( ! datumbuf ) {
-+ rprintf(FERROR, "%s: rsync_xal_get: allocate %lu for datumbuf failed: %s\n",
-+ fname, (unsigned long)(datum_size + 1), strerror(errno));
-+ return False;
-+ }
-+ datumbuf_len = datum_size;
-+ datum_size = sys_lgetxattr ( fname, name, datumbuf, datumbuf_len );
-+ if ( datum_size < 0 ) {
-+ rprintf ( FERROR, "%s: rsync_xal_get: re-lgetxattr of %s failed: %s\n",
-+ name, fname, strerror(errno) );
-+ return False;
-+ }
-+ } else {
-+ rprintf(FERROR, "%s: rsync_xal_get: lgetxattr %s failed: %s\n",
-+ fname, name, strerror(errno));
-+ return False;
-+ }
-+ }
-+ ptr = malloc ( len + datum_size );
-+ strcpy ( ptr, name );
-+ if ( datum_size )
-+ memcpy ( ptr + len, datumbuf, datum_size );
-+ x->rxas[curr_rsync_xal.count].name_len = len;
-+ x->rxas[curr_rsync_xal.count].name = ptr;
-+ x->rxas[curr_rsync_xal.count].datum_len = datum_size;
-+ x->rxas[curr_rsync_xal.count].datum = ptr + len;
-+ x->count++;
-+ }
-+ if ( x->count > 1 ) {
-+ qsort ( x->rxas, x->count, sizeof(rsync_xa), rsync_xal_compare_names );
-+ }
-+ return True;
-+}
-+
-+
-+/* generate the xattr(s) for this flist entry;
-+ * xattr(s) are either sent or cleaned-up by send_xattr() below */
-+
-+BOOL make_xattr(const struct file_struct *file, const char *fname)
-+{
-+ if (!preserve_xattrs)
-+ return True;
-+
-+ rsync_xal_get ( fname, &curr_rsync_xal );
-+ return True;
-+}
-+
-+static ssize_t rsync_xal_find_matching ( void ) {
-+ size_t i;
-+ size_t j;
-+
-+ for ( i = 0; i < rsync_xal_l.count; i++ ) {
-+ /* Wrong number of elements? */
-+ if ( rsync_xal_l.rxals[i].count != curr_rsync_xal.count )
-+ continue;
-+ /* any elements different? */
-+ for ( j = 0; j < curr_rsync_xal.count; j++ ) {
-+ if (
-+ rsync_xal_l.rxals[i].rxas[j].name_len != curr_rsync_xal.rxas[j].name_len
-+ || rsync_xal_l.rxals[i].rxas[j].datum_len != curr_rsync_xal.rxas[j].datum_len
-+ || strcmp ( rsync_xal_l.rxals[i].rxas[j].name, curr_rsync_xal.rxas[j].name )
-+ || memcmp ( rsync_xal_l.rxals[i].rxas[j].datum, curr_rsync_xal.rxas[j].datum, curr_rsync_xal.rxas[j].datum_len ) )
-+ break;
-+ }
-+ /* no differences found. This is The One! */
-+ if ( j == curr_rsync_xal.count )
-+ break;
-+ }
-+ if ( i < rsync_xal_l.count )
-+ return i;
-+ return (ssize_t)-1;
-+}
-+
-+/* Store curr_rsync_xal on the end of rsync_xal_l */
-+static void rsync_xal_store ( void ) {
-+ if ( rsync_xal_l.count <= rsync_xal_l.alloc ) {
-+ size_t new_alloc;
-+ size_t new_size;
-+ void *new_xal;
-+
-+ new_alloc = ( rsync_xal_l.count < RSYNC_XAL_LIST_INITIAL ) ? RSYNC_XAL_LIST_INITIAL : rsync_xal_l.count * 2;
-+ new_size = new_alloc * sizeof(rsync_xal);
-+ new_xal = rsync_xal_l.count ? realloc ( rsync_xal_l.rxals, new_size ) : malloc ( new_size );
-+ if ( new_xal == NULL ) {
-+ rprintf ( FERROR, "rsync_xal_store: allocate %lu for new_xal failed\n", (unsigned long)new_size );
-+ exit_cleanup(RERR_STREAMIO );
-+ }
-+ rsync_xal_l.alloc = new_alloc;
-+ rsync_xal_l.rxals = new_xal;
-+ }
-+ rsync_xal_l.rxals[rsync_xal_l.count] = curr_rsync_xal;
-+ rsync_xal_l.count++;
-+ curr_rsync_xal.count = 0;
-+ curr_rsync_xal.alloc = 0;
-+}
-+
-+/* send the make_xattr()-generated xattr list for this flist entry,
-+ * or clean up after an flist entry that's not being sent (f == -1) */
-+
-+void send_xattr ( const struct file_struct *file, int f )
-+{
-+ ssize_t index;
-+
-+ if ( ! preserve_xattrs )
-+ return;
-+
-+ if (f == -1) {
-+ rsync_xal_free ( &curr_rsync_xal );
-+ return;
-+ }
-+ index = rsync_xal_find_matching ( );
-+ if ( index != -1) {
-+ write_byte(f, 'x' );
-+ write_int(f, index);
-+ rsync_xal_free ( &curr_rsync_xal );
-+ } else {
-+ rsync_xa *rxa;
-+ size_t count;
-+
-+ count = curr_rsync_xal.count;
-+ write_byte(f, 'X' );
-+ write_int(f, count);
-+ for (rxa = curr_rsync_xal.rxas; count--; rxa++) {
-+ write_int( f, rxa->name_len );
-+ write_int ( f, rxa->datum_len );
-+ write_buf ( f, rxa->name, rxa->name_len );
-+ write_buf ( f, rxa->datum, rxa->datum_len );
-+ }
-+ rsync_xal_store();
-+ }
-+}
-+
-+
-+/* ------------------------------------------------------------------------- */
-+/* receive and build the rsync_xattr_lists */
-+
-+void receive_xattr(struct file_struct *file, int f)
-+{
-+ char *fname;
-+ int tag;
-+
-+ if ( ! preserve_xattrs )
-+ return;
-+ fname = f_name(file);
-+ tag = read_byte(f);
-+ if (tag != 'X' && tag != 'x') {
-+ rprintf(FERROR, "%s: receive_xattr: unknown extended attribute type tag: %c\n",
-+ fname, tag);
-+ exit_cleanup(RERR_STREAMIO);
-+ }
-+
-+ if ( fxil.alloc <= fxil.count) {
-+ void *new_ptr;
-+ size_t new_alloc;
-+ size_t new_size;
-+
-+ if ( fxil.count < RSYNC_XAL_LIST_INITIAL )
-+ new_alloc = fxil.alloc + RSYNC_XAL_LIST_INITIAL;
-+ else
-+ new_alloc = fxil.alloc * 2;
-+ new_size = new_alloc * sizeof(file_xal_index);
-+ if ( fxil.alloc )
-+ new_ptr = realloc ( fxil.filexalidxs, new_size );
-+ else
-+ new_ptr = malloc ( new_size );
-+ if (!new_ptr)
-+ out_of_memory("receive_xattr");
-+ if (verbose >= 3) {
-+ rprintf(FINFO, "receive_xattr to %lu bytes, %s move\n",
-+ (unsigned long) new_size,
-+ fxil.filexalidxs == new_ptr ? "did not" : "did");
-+ }
-+
-+ fxil.filexalidxs = new_ptr;
-+ fxil.alloc = new_alloc;
-+ }
-+
-+ fxil.filexalidxs[fxil.count].file = file;
-+ if (tag == 'X' ) {
-+ size_t count;
-+ size_t i;
-+
-+ fxil.filexalidxs[fxil.count].xalidx = rsync_xal_l.count;
-+
-+ count = read_int ( f );
-+ curr_rsync_xal.count = count;
-+ curr_rsync_xal.alloc = count;
-+ curr_rsync_xal.rxas = malloc ( count * sizeof(rsync_xa) );
-+ if ( curr_rsync_xal.rxas == NULL ) {
-+ rprintf(FERROR, "%s: receive_xattr: allocate %lu xas failed\n",
-+ fname, (unsigned long)count );
-+ exit_cleanup(RERR_STREAMIO);
-+ }
-+ for ( i = 0; i < count; i++ ) {
-+ size_t name_len;
-+ size_t datum_len;
-+ char *ptr;
-+
-+ name_len = read_int ( f );
-+ datum_len = read_int ( f );
-+ ptr = malloc ( name_len + datum_len );
-+ read_buf ( f, ptr, name_len );
-+ read_buf ( f, ptr + name_len, datum_len );
-+ curr_rsync_xal.rxas[i].name_len = name_len;
-+ curr_rsync_xal.rxas[i].datum_len = datum_len;
-+ curr_rsync_xal.rxas[i].name = ptr;
-+ curr_rsync_xal.rxas[i].datum = ptr + name_len;
-+ }
-+ rsync_xal_store();
-+ } else {
-+ size_t index;
-+
-+ index = read_int(f);
-+ if ( index >= rsync_xal_l.count) {
-+ rprintf(FERROR, "%s: receive_xattr: xa index %lu out of range\n",
-+fname, (unsigned long)index );
-+ exit_cleanup(RERR_STREAMIO);
-+ }
-+ fxil.filexalidxs[fxil.count].xalidx = index;
-+ }
-+ fxil.count++;
-+}
-+
-+static BOOL rsync_xal_set ( const char *fname, rsync_xal *x ) {
-+ size_t i;
-+ int status;
-+ BOOL ret;
-+
-+ ret = True;
-+ for ( i = 0; i < x->count; i++ ) {
-+ status = sys_lsetxattr ( fname, x->rxas[i].name, x->rxas[i].datum, x->rxas[i].datum_len, 0 );
-+ if ( status < 0 ) {
-+ rprintf(FERROR, "%s: rsync_xal_set: lsetxattr %s failed: %s\n",
-+ fname, x->rxas[i].name, strerror(errno));
-+ ret = False;
-+ }
-+ }
-+ return ret;
-+}
-+
-+/* for duplicating xattrs on backups when using backup_dir */
-+
-+int dup_xattr ( const char *orig, const char *bak )
-+{
-+ int ret;
-+
-+ ret = 0;
-+ if (!preserve_xattrs)
-+ return ret;
-+
-+ ret = rsync_xal_get ( orig, &backup_xal );
-+ if ( ret == True )
-+ ret = rsync_xal_set ( bak, &backup_xal );
-+ rsync_xal_free ( &backup_xal );
-+ return ret;
-+}
-+
-+void push_keep_backup_xattr ( const struct file_struct *file, const char *orig, const char *dest )
-+{
-+ if ( ! preserve_xattrs )
-+ return;
-+
-+ backup_orig_file = file;
-+ backup_orig_fname = orig;
-+ backup_dest_fname = dest;
-+ rsync_xal_get ( orig, &backup_xal );
-+}
-+
-+static int set_keep_backup_xal ( void ) {
-+ if ( ! preserve_xattrs )
-+ return 0;
-+ return rsync_xal_set ( backup_dest_fname, &backup_xal );
-+}
-+
-+void cleanup_keep_backup_xattr ( void )
-+{
-+ if ( ! preserve_xattrs)
-+ return;
-+
-+ backup_orig_file = NULL;
-+ backup_orig_fname = null_string;
-+ backup_dest_fname = null_string;
-+ rsync_xal_free ( &backup_xal );
-+}
-+
-+static int file_xal_index_compare ( const void *x1, const void *x2 ) {
-+ const file_xal_index *xa1;
-+ const file_xal_index *xa2;
-+
-+ xa1 = x1;
-+ xa2 = x2;
-+ return ( xa1->file == xa2->file) ? 0 :
-+ ( ( xa1->file < xa2->file ) ? -1: 1 );
-+}
-+void sort_file_xattr_index_lists ( void )
-+{
-+ if ( ! preserve_xattrs )
-+ return;
-+ qsort ( fxil.filexalidxs, fxil.count, sizeof(file_xal_index),
-+ file_xal_index_compare );
-+}
-+
-+
-+static int find_file_xal_index( const struct file_struct *file) {
-+ int low = 0, high = fxil.count;
-+ const struct file_struct *file_mid;
-+
-+ if ( ! high-- ) {
-+ rprintf(FERROR, "find_file_xal_index: no entries\n");
-+ exit_cleanup(RERR_STREAMIO);
-+ return -1;
-+ }
-+ do {
-+ int mid = (high + low) / 2;
-+ file_mid = fxil.filexalidxs[mid].file;
-+ if (file_mid == file)
-+ return fxil.filexalidxs[mid].xalidx;
-+ if (file_mid > file)
-+ high = mid - 1;
-+ else
-+ low = mid + 1;
-+ } while (low < high);
-+ if (low == high) {
-+ file_mid = fxil.filexalidxs[low].file;
-+ if (file_mid == file)
-+ return fxil.filexalidxs[low].xalidx;
-+ }
-+ rprintf(FERROR,
-+ "find_file_xal_index: can't find entry for file in list\n");
-+ exit_cleanup(RERR_STREAMIO);
-+ return -1;
-+}
-+
-+
-+/* set extended attributes on rsync-ed or keep_backup-ed file */
-+
-+int set_xattr ( const char *fname, const struct file_struct *file )
-+{
-+ int updated;
-+ int xalidx;
-+ rsync_xal *x;
-+
-+ updated = 0;
-+ if ( dry_run || ! preserve_xattrs )
-+ return 0;
-+ if (file == backup_orig_file) {
-+ if (!strcmp(fname, backup_dest_fname))
-+ return set_keep_backup_xal();
-+ }
-+ xalidx = find_file_xal_index( file );
-+ x = &(rsync_xal_l.rxals[xalidx]);
-+ updated = rsync_xal_set ( fname, x );
-+ return updated;
-+}
-+
-+#endif /* SUPPORT_XATTRS */
-Common subdirectories: rsync-2.6.4pre2-prexattr/zlib and rsync-2.6.4pre2/zlib
---- rsync-2.6.4/generator.c.xattr 2005-03-31 09:49:39.000000000 -0500
-+++ rsync-2.6.4/generator.c 2005-03-31 09:59:22.000000000 -0500
-@@ -715,6 +715,10 @@
- if (f_out == -1)
- SET_ACL(fname, file);
- #endif
-+#if SUPPORT_XATTRS
-+ if ( f_out == -1 )
-+ SET_XATTR( fname, file );
-+#endif
- if (delete_during && f_out != -1 && !phase && dry_run < 2
- && (file->flags & FLAG_DEL_HERE))
- delete_in_dir(the_file_list, fname, file);
---- rsync-2.6.5/flist.c.xattr 2005-06-02 14:26:25.000000000 -0400
-+++ rsync-2.6.5/flist.c 2005-06-02 14:33:02.000000000 -0400
-@@ -976,6 +976,8 @@
- return NULL;
- if (!MAKE_ACL(file, fname))
- return NULL;
-+ if ( ! MAKE_XATTR(file, fname ) )
-+ return;
-
- maybe_emit_filelist_progress(flist->count + flist_count_offset);
-
-@@ -985,9 +987,11 @@
- flist->files[flist->count++] = file;
- send_file_entry(file, f, base_flags);
- SEND_ACL(file, f);
-+ SEND_XATTR ( file, f );
- } else {
- /* Cleanup unsent ACL(s). */
- SEND_ACL(file, -1);
-+ SEND_XATTR( file, -1 );
- }
- return file;
- }
-@@ -1325,6 +1329,7 @@
- file = receive_file_entry(flist, flags, f);
-
- RECEIVE_ACL(file, f);
-+ RECEIVE_XATTR(file, f );
-
- if (S_ISREG(file->mode))
- stats.total_size += file->length;
-@@ -1349,6 +1354,7 @@
- clean_flist(flist, relative_paths, 1);
-
- SORT_FILE_ACL_INDEX_LISTS();
-+ SORT_FILE_XATTR_INDEX_LISTS();
-
- if (f >= 0) {
- /* Now send the uid/gid list. This was introduced in
---- rsync-2.6.6/Makefile.in.xattr 2005-07-28 16:16:07.000000000 -0400
-+++ rsync-2.6.6/Makefile.in 2005-07-28 16:18:13.000000000 -0400
-@@ -27,13 +27,13 @@
-
- HEADERS=byteorder.h config.h errcode.h proto.h rsync.h smb_acls.h lib/pool_alloc.h
- LIBOBJ=lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o \
-- lib/permstring.o lib/pool_alloc.o lib/sysacls.o @LIBOBJS@
-+ lib/permstring.o lib/pool_alloc.o lib/sysacls.o lib/sysxattr.o @LIBOBJS@
- ZLIBOBJ=zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o \
- zlib/trees.o zlib/zutil.o zlib/adler32.o zlib/compress.o zlib/crc32.o
- OBJS1=rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o \
- main.o checksum.o match.o syscall.o log.o backup.o
- OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o \
-- fileio.o batch.o clientname.o acls.o
-+ fileio.o batch.o clientname.o acls.o xattr.o
- OBJS3=progress.o pipe.o
- DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
- popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \