* Copyright (C) 1996, 2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
- * Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
+ * Copyright (C) 2003-2007 Wayne Davison
*
* 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.
+ * 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
#define XMIT_TOP_DIR (1<<0)
#define XMIT_SAME_MODE (1<<1)
-#define XMIT_EXTENDED_FLAGS (1<<2)
-#define XMIT_SAME_RDEV_pre28 XMIT_EXTENDED_FLAGS /* Only in protocols < 28 */
+#define XMIT_SAME_RDEV_pre28 (1<<2) /* protocols 20 - 27 */
+#define XMIT_EXTENDED_FLAGS (1<<2) /* protocols 28 - NOW */
#define XMIT_SAME_UID (1<<3)
#define XMIT_SAME_GID (1<<4)
#define XMIT_SAME_NAME (1<<5)
#define XMIT_LONG_NAME (1<<6)
#define XMIT_SAME_TIME (1<<7)
-#define XMIT_SAME_RDEV_MAJOR (1<<8)
-#define XMIT_HLINKED (1<<9)
-#define XMIT_SAME_DEV (1<<10)
-#define XMIT_RDEV_MINOR_IS_SMALL (1<<11)
+#define XMIT_SAME_RDEV_MAJOR (1<<8) /* protocols 28 - NOW */
+#define XMIT_HLINKED (1<<9) /* protocols 28 - NOW */
+#define XMIT_SAME_DEV_pre30 (1<<10) /* protocols 28 - 29 */
+#define XMIT_USER_NAME_FOLLOWS (1<<10) /* protocols 30 - NOW */
+#define XMIT_RDEV_MINOR_8_pre30 (1<<11) /* protocols 28 - 29 */
+#define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - NOW */
+#define XMIT_HLINK_FIRST (1<<12) /* protocols 30 - NOW */
/* These flags are used in the live flist data. */
#define FLAG_TOP_DIR (1<<0) /* sender/receiver/generator */
-#define FLAG_SENT (1<<1) /* sender/generator */
+#define FLAG_FILE_SENT (1<<1) /* sender/receiver/generator */
+#define FLAG_DIR_CHANGED (1<<1) /* generator */
#define FLAG_XFER_DIR (1<<2) /* sender/receiver/generator */
#define FLAG_MOUNT_DIR (1<<3) /* sender/generator */
+#define FLAG_DUPLICATE (1<<4) /* sender */
#define FLAG_MISSING_DIR (1<<4) /* generator */
#define FLAG_HLINKED (1<<5) /* receiver/generator */
#define FLAG_HLINK_FIRST (1<<6) /* receiver/generator */
#define FLAG_HLINK_LAST (1<<7) /* receiver/generator */
#define FLAG_HLINK_DONE (1<<8) /* receiver/generator */
#define FLAG_LENGTH64 (1<<9) /* sender/receiver/generator */
+#define FLAG_SKIP_GROUP (1<<10) /* receiver/generator */
+
+/* These flags are passed to functions but not stored. */
+
+#define FLAG_DIVERT_DIRS (1<<16)/* sender */
#define BITS_SET(val,bits) (((val) & (bits)) == (bits))
#define BITS_SETnUNSET(val,onbits,offbits) (((val) & ((onbits)|(offbits))) == (onbits))
/* update this if you make incompatible changes */
#define PROTOCOL_VERSION 30
+/* This is used when working on a new protocol version in CVS, and should
+ * be a new non-zero value for each CVS change that affects the protocol.
+ * It must ALWAYS be 0 when the protocol goes final! */
+#define SUBPROTOCOL_VERSION 3
+
/* We refuse to interoperate with versions that are not in this range.
* Note that we assume we'll work with later versions: the onus is on
* people writing them to make sure that they don't send us anything
#define OLD_PROTOCOL_VERSION 25
#define MAX_PROTOCOL_VERSION 40
+#define FILECNT_LOOKAHEAD 1000
+
#define RSYNC_PORT 873
#define SPARSE_WRITE_SIZE (1024)
MSG_ERROR=FERROR, MSG_INFO=FINFO, /* remote logging */
MSG_LOG=FLOG, MSG_CLIENT=FCLIENT, MSG_SOCKERR=FSOCKERR, /* sibling logging */
MSG_REDO=9, /* reprocess indicated flist index */
+ MSG_FLIST=20, /* extra file list over sibling socket */
+ MSG_FLIST_EOF=21,/* we've transmitted all the file lists */
+ MSG_IO_ERROR=22,/* the sending side had an I/O error */
+ MSG_NOOP=42, /* a do-nothing message */
MSG_SUCCESS=100,/* successfully updated indicated flist index */
MSG_DELETED=101,/* successfully deleted a file on receiving side */
+ MSG_NO_SEND=102,/* sender failed to open a file we wanted */
MSG_DONE=86 /* current phase is done */
};
#define NDX_DONE -1
+#define NDX_FLIST_EOF -2
+#define NDX_FLIST_OFFSET -101
#include "errcode.h"
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
# include <limits.h>
#endif
+#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
+#include <iconv.h>
+#ifndef ICONV_CONST
+#define ICONV_CONST
+#endif
+#elif defined ICONV_CONST
+#undef ICONV_CONST
+#endif
+
#include <assert.h>
#include "lib/pool_alloc.h"
#define schar char
#endif
+#ifndef int16
+#if SIZEOF_INT16_T == 2
+# define int16 int16_t
+#else
+# define int16 short
+#endif
+#endif
+
+#ifndef uint16
+#if SIZEOF_UINT16_T == 2
+# define uint16 uint16_t
+#else
+# define uint16 unsigned int16
+#endif
+#endif
+
/* Find a variable that is either exactly 32-bits or longer.
* If some code depends on 32-bit truncation, it will need to
* take special action in a "#if SIZEOF_INT32 > 4" section. */
#ifndef int32
-#if SIZEOF_INT == 4
+#if SIZEOF_INT32_T == 4
+# define int32 int32_t
+# define SIZEOF_INT32 4
+#elif SIZEOF_INT == 4
# define int32 int
# define SIZEOF_INT32 4
#elif SIZEOF_LONG == 4
#endif
#ifndef uint32
-#define uint32 unsigned int32
+#if SIZEOF_UINT32_T == 4
+# define uint32 uint32_t
+#else
+# define uint32 unsigned int32
+#endif
#endif
#if SIZEOF_OFF_T == 8 || !SIZEOF_OFF64_T || !defined HAVE_STRUCT_STAT64
* to ensure that any code that really requires a 64-bit integer has
* it (e.g. the checksum code uses two 32-bit integers for its 64-bit
* counter). */
-#if SIZEOF_LONG == 8
+#if SIZEOF_INT64_T == 8
+# define int64 int64_t
+# define SIZEOF_INT64 8
+#elif SIZEOF_LONG == 8
# define int64 long
# define SIZEOF_INT64 8
#elif SIZEOF_INT == 8
* where dev_t is a struct.
*/
-struct idev {
- int64 ino;
- int64 dev;
+struct idev_node {
+ int64 key;
+ void *data;
};
#ifndef MIN
#define MAXHOSTNAMELEN 256
#endif
-/* the length of the md4 checksum */
-#define MD4_SUM_LENGTH 16
#define SUM_LENGTH 16
#define SHORT_SUM_LENGTH 2
#define BLOCKSUM_BIAS 10
#define IN_LOOPBACKNET 127
#endif
-#define GID_NONE ((gid_t)-1)
+#if HAVE_UNIXWARE_ACLS|HAVE_SOLARIS_ACLS|HAVE_HPUX_ACLS
+#define ACLS_NEED_MASK 1
+#endif
+
+union file_extras {
+ int32 num;
+ uint32 unum;
+};
struct file_struct {
- union flist_extras {
- uid_t uid; /* The user ID number */
- uid_t gid; /* The group ID number or GID_NONE */
- struct idev *idev; /* The hard-link info during matching */
- int32 num; /* A signed number */
- uint32 unum; /* An unsigned number */
- } extras[1];
- time_t modtime; /* When the item was last modified */
- const char *dirname; /* The dir info inside the transfer */
- union {
- const char *root; /* Sender-side dir info outside transfer */
- int32 depth; /* Receiver-side directory depth info */
- } dir;
- uint32 len32; /* Lowest 32 bits of the file's length */
- unsigned short mode; /* The item's type and permissions */
- unsigned short flags; /* This item MUST remain last! */
+ const char *dirname; /* The dir info inside the transfer */
+ time_t modtime; /* When the item was last modified */
+ uint32 len32; /* Lowest 32 bits of the file's length */
+ uint16 mode; /* The item's type and permissions */
+ uint16 flags; /* The FLAG_* bits for this item */
+ const char basename[1]; /* The basename (AKA filename) follows */
};
-extern int flist_extra_cnt;
+extern int file_extra_cnt;
extern int preserve_uid;
extern int preserve_gid;
+extern int preserve_acls;
+extern int preserve_xattrs;
-#define FILE_STRUCT_LEN (offsetof(struct file_struct, flags) \
- + sizeof (unsigned short))
-#define EXTRA_LEN (sizeof (union flist_extras))
-#define SUM_EXTRA_CNT ((MD4_SUM_LENGTH + EXTRA_LEN - 1) / EXTRA_LEN)
+#define FILE_STRUCT_LEN (offsetof(struct file_struct, basename))
+#define EXTRA_LEN (sizeof (union file_extras))
+#define PTR_EXTRA_LEN ((sizeof (char *) + EXTRA_LEN - 1) / EXTRA_LEN)
+#define SUM_EXTRA_CNT ((MAX_DIGEST_LEN + EXTRA_LEN - 1) / EXTRA_LEN)
-#define REQ_EXTRA(f,ndx) ((f)->extras - (ndx - 1))
-#define OPT_EXTRA(f,bump) ((f)->extras - flist_extra_cnt - (bump))
+#define REQ_EXTRA(f,ndx) ((union file_extras*)(f) - (ndx))
+#define OPT_EXTRA(f,bump) ((union file_extras*)(f) - file_extra_cnt - 1 - (bump))
#define LEN64_BUMP(f) ((f)->flags & FLAG_LENGTH64 ? 1 : 0)
#define HLINK_BUMP(f) (F_IS_HLINKED(f) ? 1 : 0)
-/* Basename (AKA filename) and length applies to all items */
-#define F_BASENAME(f) ((const char*)(f) + FILE_STRUCT_LEN)
+/* The length applies to all items. */
#if SIZEOF_INT64 < 8
#define F_LENGTH(f) ((int64)(f)->len32)
#else
#endif
/* If there is a symlink string, it is always right after the basename */
-#define F_SYMLINK(f) (F_BASENAME(f) + strlen(F_BASENAME(f)) + 1)
+#define F_SYMLINK(f) ((f)->basename + strlen((f)->basename) + 1)
+
+/* The sending side always has this available: */
+#define F_PATHNAME(f) (*(const char**)REQ_EXTRA(f, PTR_EXTRA_LEN))
+
+/* The receiving side always has this available: */
+#define F_DEPTH(f) REQ_EXTRA(f, 1)->num
/* When the associated option is on, all entries will have these present: */
-#define F_UID(f) REQ_EXTRA(f, preserve_uid)->uid
-#define F_GID(f) REQ_EXTRA(f, preserve_gid)->gid
+#define F_OWNER(f) REQ_EXTRA(f, preserve_uid)->unum
+#define F_GROUP(f) REQ_EXTRA(f, preserve_gid)->unum
+#define F_ACL(f) REQ_EXTRA(f, preserve_acls)->num
+#define F_XATTR(f) REQ_EXTRA(f, preserve_xattrs)->num
+#define F_NDX(f) REQ_EXTRA(f, ic_ndx)->num
/* These items are per-entry optional and mutally exclusive: */
-#define F_HL_IDEV(f) OPT_EXTRA(f, LEN64_BUMP(f))->idev
+#define F_HL_GNUM(f) OPT_EXTRA(f, LEN64_BUMP(f))->num
#define F_HL_PREV(f) OPT_EXTRA(f, LEN64_BUMP(f))->num
+#define F_DEF_ACL(f) OPT_EXTRA(f, LEN64_BUMP(f))->unum
+#define F_DIRDEV_P(f) (&OPT_EXTRA(f, LEN64_BUMP(f) + 2 - 1)->unum)
+#define F_DIRNODE_P(f) (&OPT_EXTRA(f, LEN64_BUMP(f) + 3 - 1)->num)
/* This optional item might follow an F_HL_*() item.
* (Note: a device doesn't need to check LEN64_BUMP(f).) */
+ SUM_EXTRA_CNT - 1))
/* Some utility defines: */
-#define F_IS_ACTIVE(f) F_BASENAME(f)[0]
+#define F_IS_ACTIVE(f) (f)->basename[0]
#define F_IS_HLINKED(f) ((f)->flags & FLAG_HLINKED)
+
#define F_HLINK_NOT_FIRST(f) BITS_SETnUNSET((f)->flags, FLAG_HLINKED, FLAG_HLINK_FIRST)
#define F_HLINK_NOT_LAST(f) BITS_SETnUNSET((f)->flags, FLAG_HLINKED, FLAG_HLINK_LAST)
#define DEV_MAJOR(a) (a)[0]
#define DEV_MINOR(a) (a)[1]
+#define DIR_PARENT(a) (a)[0]
+#define DIR_FIRST_CHILD(a) (a)[1]
+#define DIR_NEXT_SIBLING(a) (a)[2]
+
/*
* Start the flist array at FLIST_START entries and grow it
* by doubling until FLIST_LINEAR then grow by FLIST_LINEAR
#define FILE_EXTENT (256 * 1024)
#define HLINK_EXTENT (128 * 1024)
+#define FLIST_TEMP (1<<1)
+
struct file_list {
- struct file_struct **files;
+ struct file_list *next, *prev;
+ struct file_struct **files, **sorted;
alloc_pool_t file_pool;
int count, malloced;
int low, high; /* 0-relative index values excluding empties */
+ int ndx_start; /* the start offset for inc_recurse mode */
+ int parent_ndx; /* dir_flist index of parent directory */
+ int in_progress, to_redo;
};
#define SUMFLG_SAME_OFFSET (1<<0)
struct chmod_mode_struct;
+#define EMPTY_ITEM_LIST {NULL, 0, 0}
+
+typedef struct {
+ void *items;
+ size_t count;
+ size_t malloced;
+} item_list;
+
+#define EXPAND_ITEM_LIST(lp, type, incr) \
+ (type*)expand_item_list(lp, sizeof (type), #type, incr)
+
#include "byteorder.h"
-#include "lib/mdfour.h"
+#include "lib/mdigest.h"
#include "lib/wildmatch.h"
#include "lib/permstring.h"
#include "lib/addrinfo.h"
#ifndef __GNUC__
#define __attribute__(x)
+#else
# if __GNUC__ <= 2
# define NORETURN
# endif
#define NORETURN __attribute__((__noreturn__))
#endif
+typedef struct {
+ STRUCT_STAT st;
+#ifdef SUPPORT_ACLS
+ struct rsync_acl *acc_acl; /* access ACL */
+ struct rsync_acl *def_acl; /* default ACL */
+#endif
+#ifdef SUPPORT_XATTRS
+ item_list *xattr;
+#endif
+} statx;
+
+#define ACL_READY(sx) ((sx).acc_acl != NULL)
+#define XATTR_READY(sx) ((sx).xattr != NULL)
+
#include "proto.h"
+#ifndef SUPPORT_XATTRS
+#define x_stat(fn,fst,xst) do_stat(fn,fst)
+#define x_lstat(fn,fst,xst) do_lstat(fn,fst)
+#define x_fstat(fd,fst,xst) do_fstat(fd,fst)
+#endif
+
/* We have replacement versions of these if they're missing. */
#ifndef HAVE_ASPRINTF
int asprintf(char **ptr, const char *format, ...);
const char *get_panic_action(void);
#endif
+static inline int to_wire_mode(mode_t mode)
+{
+#ifdef SUPPORT_LINKS
+#if _S_IFLNK != 0120000
+ if (S_ISLNK(mode))
+ return (mode & ~(_S_IFMT)) | 0120000;
+#endif
+#endif
+ return mode;
+}
+
+static inline mode_t from_wire_mode(int mode)
+{
+#if _S_IFLNK != 0120000
+ if ((mode & (_S_IFMT)) == 0120000)
+ return (mode & ~(_S_IFMT)) | _S_IFLNK;
+#endif
+ return mode;
+}
+
static inline int
isDigit(const char *ptr)
{