popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
--- old/acls.c
+++ new/acls.c
-@@ -0,0 +1,1202 @@
+@@ -0,0 +1,1230 @@
+/* -*- c-file-style: "linux" -*-
+ Copyright (C) Andrew Tridgell 1996
+ Copyright (C) Paul Mackerras 1996
+} rsync_acl;
+
+static const rsync_acl rsync_acl_initializer = { 0, 0, NULL };
++static SMB_ACL_TYPE_T types[] = {SMB_ACL_TYPE_ACCESS, SMB_ACL_TYPE_DEFAULT};
+
+static void expand_rsync_acl(rsync_acl *racl)
+{
+ break;
+ default:
+ rprintf(FERROR,
-+ "send_rsync_acl: unknown tag_type (%0x) on ACE; disregarding\n",
++ "send_rsync_acl: unknown tag_type (%02x) on ACE; disregarding\n",
+ race->tag_type);
+ continue;
+ }
+ "unknown SMB_ACL_TYPE_T";
+}
+
++/*
++ * Overwrite racl with a new three-entry ACL from the given permissions.
++ */
++static void perms_to_acl(int perms, rsync_acl *racl)
++{
++ racl->count = 0;
++ expand_rsync_acl(racl);
++ racl->races[racl->count].tag_type = SMB_ACL_USER_OBJ;
++ racl->races[racl->count++].access = (perms >> 6) & 7;
++ expand_rsync_acl(racl);
++ racl->races[racl->count].tag_type = SMB_ACL_GROUP_OBJ;
++ racl->races[racl->count++].access = (perms >> 3) & 7;
++ expand_rsync_acl(racl);
++ racl->races[racl->count].tag_type = SMB_ACL_OTHER;
++ racl->races[racl->count++].access = (perms >> 0) & 7;
++}
++
+/* Generate the ACL(s) for this flist entry;
+ * ACL(s) are either sent or cleaned-up by send_acl() below. */
+
+int make_acl(const struct file_struct *file, const char *fname)
+{
-+ SMB_ACL_TYPE_T *type,
-+ types[] = {SMB_ACL_TYPE_ACCESS, SMB_ACL_TYPE_DEFAULT};
++ SMB_ACL_TYPE_T *type;
+ rsync_acl *curr_racl;
++
+ if (!preserve_acls || S_ISLNK(file->mode))
+ return 1;
+ for (type = &types[0], curr_racl = &_curr_rsync_acls[0];
+ SMB_ACL_T sacl;
+ BOOL ok;
+ *curr_racl = rsync_acl_initializer;
-+ if (!(sacl = sys_acl_get_file(fname, *type))) {
++ if ((sacl = sys_acl_get_file(fname, *type)) != 0) {
++ ok = unpack_smb_acl(curr_racl, sacl);
++ sys_acl_free_acl(sacl);
++ if (!ok)
++ return -1;
++ } else if (errno == ENOTSUP) {
++ /* ACLs are not supported. Invent an access ACL from
++ * permissions; let the default ACL default to empty. */
++ if (*type == SMB_ACL_TYPE_ACCESS)
++ perms_to_acl(file->mode & ACCESSPERMS, curr_racl);
++ } else {
+ rprintf(FERROR, "send_acl: sys_acl_get_file(%s, %s): %s\n",
+ fname, str_acl_type(*type), strerror(errno));
+ return -1;
+ }
-+ ok = unpack_smb_acl(curr_racl, sacl);
-+ sys_acl_free_acl(sacl);
-+ if (!ok)
-+ return -1;
+ }
+ return 0;
+}
+
+void send_acl(const struct file_struct *file, int f)
+{
-+ SMB_ACL_TYPE_T *type,
-+ types[] = {SMB_ACL_TYPE_ACCESS, SMB_ACL_TYPE_DEFAULT};
++ SMB_ACL_TYPE_T *type;
+ rsync_acl *curr_racl;
++
+ if (!preserve_acls || S_ISLNK(file->mode))
+ return;
+ for (type = &types[0], curr_racl = &_curr_rsync_acls[0];
+
+void receive_acl(struct file_struct *file, int f)
+{
-+ SMB_ACL_TYPE_T *type,
-+ types[] = {SMB_ACL_TYPE_ACCESS, SMB_ACL_TYPE_DEFAULT};
++ SMB_ACL_TYPE_T *type;
+ char *fname;
++
+ if (!preserve_acls || S_ISLNK(file->mode))
+ return;
++
+ fname = f_name(file, NULL);
+ for (type = &types[0];
+ type < &types[0] + sizeof types / sizeof types[0]
+
+void sort_file_acl_index_lists()
+{
-+ SMB_ACL_TYPE_T *type,
-+ types[] = {SMB_ACL_TYPE_ACCESS, SMB_ACL_TYPE_DEFAULT};
++ SMB_ACL_TYPE_T *type;
++
+ if (!preserve_acls)
+ return;
++
+ for (type = &types[0];
+ type < &types[0] + sizeof types / sizeof types[0];
-+ type++)
-+ {
++ type++) {
+ file_acl_index_list *fileaclidx_list =
+ file_acl_index_lists(*type);
+ if (!fileaclidx_list->count)
+
+int dup_acl(const char *orig, const char *bak, mode_t mode)
+{
-+ SMB_ACL_TYPE_T *type,
-+ types[] = {SMB_ACL_TYPE_ACCESS, SMB_ACL_TYPE_DEFAULT};
++ SMB_ACL_TYPE_T *type;
+ int ret = 0;
++
+ if (!preserve_acls)
+ return 1;
++
+ for (type = &types[0];
+ type < &types[0] + sizeof types / sizeof types[0]
+ && (*type == SMB_ACL_TYPE_ACCESS || S_ISDIR(mode));
+ ; /* presume they're unequal */
+ }
+ if (*type == SMB_ACL_TYPE_DEFAULT && !racl_orig.count) {
-+ if (-1 == sys_acl_delete_def_file(bak)) {
++ if (sys_acl_delete_def_file(bak) < 0) {
+ rprintf(FERROR, "dup_acl: sys_acl_delete_def_file(%s): %s\n",
+ bak, strerror(errno));
+ ret = -1;
+ }
-+ } else if (-1 == sys_acl_set_file(bak, *type, sacl_bak)) {
++ } else if (sys_acl_set_file(bak, *type, sacl_bak) < 0) {
+ rprintf(FERROR, "dup_acl: sys_acl_set_file(%s, %s): %s\n",
+ bak, str_acl_type(*type), strerror(errno));
+ ret = -1;
+ const char *orig, const char *dest)
+{
+ if (preserve_acls) {
-+ SMB_ACL_TYPE_T *type,
-+ types[] = {SMB_ACL_TYPE_ACCESS, SMB_ACL_TYPE_DEFAULT};
++ SMB_ACL_TYPE_T *type;
+ SMB_ACL_T *sacl;
++
+ backup_orig_file = file;
+ backup_orig_fname = orig;
+ backup_dest_fname = dest;
++
+ for (type = &types[0], sacl = &_backup_sacl[0];
+ type < &types[0] + sizeof types / sizeof types[0];
+ type++) {
+static int set_keep_backup_acl()
+{
+ if (preserve_acls) {
-+ SMB_ACL_TYPE_T *type,
-+ types[] = {SMB_ACL_TYPE_ACCESS, SMB_ACL_TYPE_DEFAULT};
++ SMB_ACL_TYPE_T *type;
+ SMB_ACL_T *sacl;
+ int ret = 0;
++
+ for (type = &types[0], sacl = &_backup_sacl[0];
+ type < &types[0] + sizeof types / sizeof types[0];
+ type++) {
+ if (*sacl) {
-+ if (-1 == sys_acl_set_file(backup_dest_fname,
-+ *type, *sacl))
-+ {
++ if (sys_acl_set_file(backup_dest_fname,
++ *type, *sacl) < 0) {
+ rprintf(FERROR, "push_keep_backup_acl: sys_acl_get_file(%s, %s): %s\n",
+ backup_dest_fname,
+ str_acl_type(*type),
+void cleanup_keep_backup_acl()
+{
+ if (preserve_acls) {
-+ SMB_ACL_TYPE_T *type,
-+ types[] = {SMB_ACL_TYPE_ACCESS, SMB_ACL_TYPE_DEFAULT};
++ SMB_ACL_TYPE_T *type;
+ SMB_ACL_T *sacl;
++
+ backup_orig_file = NULL;
+ backup_orig_fname = null_string;
+ backup_dest_fname = null_string;
++
+ for (type = &types[0], sacl = &_backup_sacl[0];
+ type < &types[0] + sizeof types / sizeof types[0];
+ type++) {
+
+int set_acl(const char *fname, const struct file_struct *file)
+{
-+ int updated = 0;
-+ SMB_ACL_TYPE_T *type,
-+ types[] = {SMB_ACL_TYPE_ACCESS, SMB_ACL_TYPE_DEFAULT};
++ int unchanged = 1;
++ SMB_ACL_TYPE_T *type;
++
+ if (dry_run || !preserve_acls || S_ISLNK(file->mode))
+ return 1;
++
+ if (file == backup_orig_file) {
+ if (!strcmp(fname, backup_dest_fname))
+ return set_keep_backup_acl();
+ if (!sacl_orig) {
+ rprintf(FERROR, "set_acl: sys_acl_get_file(%s, %s): %s\n",
+ fname, str_acl_type(*type), strerror(errno));
-+ updated = -1;
++ unchanged = -1;
+ continue;
+ }
+ ok = unpack_smb_acl(&racl_orig, sacl_orig);
+ sys_acl_free_acl(sacl_orig);
+ if (!ok) {
-+ updated = -1;
++ unchanged = -1;
+ continue;
+ }
+ ok = rsync_acls_equal(&racl_orig, racl_new);
+ if (ok)
+ continue;
+ if (*type == SMB_ACL_TYPE_DEFAULT && !racl_new->count) {
-+ if (-1 == sys_acl_delete_def_file(fname)) {
++ if (sys_acl_delete_def_file(fname) < 0) {
+ rprintf(FERROR, "set_acl: sys_acl_delete_def_file(%s): %s\n",
+ fname, strerror(errno));
-+ updated = -1;
++ unchanged = -1;
+ continue;
+ }
+ } else {
+ if (!*sacl_new)
+ if (!pack_smb_acl(sacl_new, racl_new)) {
-+ updated = -1;
++ unchanged = -1;
+ continue;
+ }
-+ if (-1 == sys_acl_set_file(fname, *type, *sacl_new)) {
++ if (sys_acl_set_file(fname, *type, *sacl_new) < 0) {
+ rprintf(FERROR, "set_acl: sys_acl_set_file(%s, %s): %s\n",
+ fname, str_acl_type(*type),
+ strerror(errno));
-+ updated = -1;
++ unchanged = -1;
+ continue;
+ }
+ }
-+ if (!updated)
-+ updated = 1;
++ if (unchanged == 1)
++ unchanged = 0;
+ }
-+ return updated;
++ return unchanged;
+}
+
+/* Enumeration functions for uid mapping: */
+#endif /* SUPPORT_ACLS */
--- old/backup.c
+++ new/backup.c
-@@ -135,6 +135,7 @@ static int make_bak_dir(char *fullpath)
+@@ -132,6 +132,9 @@ static int make_bak_dir(char *fullpath)
} else {
do_lchown(fullpath, st.st_uid, st.st_gid);
do_chmod(fullpath, st.st_mode);
-+ (void)DUP_ACL(end, fullpath, st.st_mode);
++#ifdef SUPPORT_ACLS
++ dup_acl(end, fullpath, st.st_mode);
++#endif
}
}
*p = '/';
-@@ -188,6 +189,8 @@ static int keep_backup(char *fname)
+@@ -185,6 +188,10 @@ static int keep_backup(char *fname)
if (!(buf = get_backup_name(fname)))
return 0;
-+ PUSH_KEEP_BACKUP_ACL(file, fname, buf);
++#ifdef SUPPORT_ACLS
++ push_keep_backup_acl(file, fname, buf);
++#endif
+
/* Check to see if this is a device file, or link */
if ((am_root && preserve_devices && IS_DEVICE(file->mode))
|| (preserve_specials && IS_SPECIAL(file->mode))) {
-@@ -263,6 +266,7 @@ static int keep_backup(char *fname)
+@@ -260,6 +267,9 @@ static int keep_backup(char *fname)
}
}
set_file_attrs(buf, file, NULL, 0);
-+ CLEANUP_KEEP_BACKUP_ACL();
++#ifdef SUPPORT_ACLS
++ cleanup_keep_backup_acl();
++#endif
free(file);
if (verbose > 1) {
--- old/configure.in
+++ new/configure.in
-@@ -478,6 +478,11 @@ if test x"$ac_cv_func_strcasecmp" = x"no
+@@ -482,6 +482,11 @@ if test x"$ac_cv_func_strcasecmp" = x"no
AC_CHECK_LIB(resolv, strcasecmp)
fi
dnl At the moment we don't test for a broken memcmp(), because all we
dnl need to do is test for equality, not comparison, and it seems that
dnl every platform has a memcmp that can do at least that.
-@@ -734,6 +739,77 @@ AC_SUBST(OBJ_RESTORE)
+@@ -738,6 +743,77 @@ AC_SUBST(OBJ_RESTORE)
AC_SUBST(CC_SHOBJ_FLAG)
AC_SUBST(BUILD_POPT)
--- old/flist.c
+++ new/flist.c
-@@ -967,6 +967,8 @@ static struct file_struct *send_file_nam
+@@ -966,6 +966,10 @@ static struct file_struct *send_file_nam
f == -2 ? SERVER_FILTERS : ALL_FILTERS);
if (!file)
return NULL;
-+ if (MAKE_ACL(file, fname) < 0)
++#ifdef SUPPORT_ACLS
++ if (make_acl(file, fname) < 0)
+ return NULL;
++#endif
if (chmod_modes && !S_ISLNK(file->mode))
file->mode = tweak_mode(file->mode, chmod_modes);
-@@ -978,6 +980,10 @@ static struct file_struct *send_file_nam
+@@ -977,6 +981,12 @@ static struct file_struct *send_file_nam
if (file->basename[0]) {
flist->files[flist->count++] = file;
send_file_entry(file, f);
-+ SEND_ACL(file, f);
++#ifdef SUPPORT_ACLS
++ send_acl(file, f);
+ } else {
+ /* Cleanup unsent ACL(s). */
-+ SEND_ACL(file, -1);
++ send_acl(file, -1);
++#endif
}
return file;
}
-@@ -1366,6 +1372,8 @@ struct file_list *recv_file_list(int f)
+@@ -1365,6 +1375,10 @@ struct file_list *recv_file_list(int f)
flags |= read_byte(f) << 8;
file = receive_file_entry(flist, flags, f);
-+ RECEIVE_ACL(file, f);
++#ifdef SUPPORT_ACLS
++ receive_acl(file, f);
++#endif
+
- if (S_ISREG(file->mode))
+ if (S_ISREG(file->mode) || S_ISLNK(file->mode))
stats.total_size += file->length;
-@@ -1388,6 +1396,8 @@ struct file_list *recv_file_list(int f)
+@@ -1387,6 +1401,10 @@ struct file_list *recv_file_list(int f)
clean_flist(flist, relative_paths, 1);
-+ SORT_FILE_ACL_INDEX_LISTS();
++#ifdef SUPPORT_ACLS
++ sort_file_acl_index_lists();
++#endif
+
if (f >= 0) {
recv_uid_list(f, flist);
--- old/generator.c
+++ new/generator.c
-@@ -754,6 +754,7 @@ static int try_dests_non(struct file_str
+@@ -85,6 +85,7 @@ extern long block_size; /* "long" becaus
+ extern int max_delete;
+ extern int force_delete;
+ extern int one_file_system;
++extern mode_t orig_umask;
+ extern struct stats stats;
+ extern dev_t filesystem_dev;
+ extern char *backup_dir;
+@@ -753,6 +754,7 @@ static int try_dests_non(struct file_str
}
static int phase = 0;
/* Acts on the_file_list->file's ndx'th item, whose name is fname. If a dir,
* make sure it exists, and has the right permissions/timestamp info. For
-@@ -770,7 +771,7 @@ static void recv_generator(char *fname,
- enum logcode code, int f_out)
- {
- static int missing_below = -1, excluded_below = -1;
-- static char *fuzzy_dirname = "";
-+ static char *parent_dirname = "";
- static struct file_list *fuzzy_dirlist = NULL;
- struct file_struct *fuzzy_file = NULL;
- int fd = -1, f_copy = -1;
-@@ -789,12 +790,12 @@ static void recv_generator(char *fname,
- if (fuzzy_dirlist) {
- flist_free(fuzzy_dirlist);
- fuzzy_dirlist = NULL;
-- fuzzy_dirname = "";
- }
- if (missing_below >= 0) {
- dry_run--;
- missing_below = -1;
- }
-+ parent_dirname = "";
- return;
- }
-
-@@ -829,15 +830,24 @@ static void recv_generator(char *fname,
- statret = -1;
- stat_errno = ENOENT;
- } else {
-- if (fuzzy_basis && S_ISREG(file->mode)) {
-+ if ((fuzzy_basis && S_ISREG(file->mode))
-+#ifdef SUPPORT_ACLS
-+ || !preserve_perms
-+#endif
-+ ) {
- char *dn = file->dirname ? file->dirname : ".";
-- if (fuzzy_dirname != dn
-- && strcmp(fuzzy_dirname, dn) != 0) {
-+ if (parent_dirname != dn
-+ && strcmp(parent_dirname, dn) != 0) {
- if (fuzzy_dirlist)
- flist_free(fuzzy_dirlist);
-- fuzzy_dirlist = get_dirlist(dn, -1, 1);
-+ if (fuzzy_basis && S_ISREG(file->mode))
-+ fuzzy_dirlist = get_dirlist(dn, -1, 1);
+@@ -844,6 +846,10 @@ static void recv_generator(char *fname,
+ }
+ if (fuzzy_basis)
+ need_fuzzy_dirlist = 1;
+#ifdef SUPPORT_ACLS
-+ if (!preserve_perms)
-+ dflt_perms = default_perms_for_dir(dn);
++ if (!preserve_perms)
++ dflt_perms = default_perms_for_dir(dn);
+#endif
- }
-- fuzzy_dirname = dn;
-+ parent_dirname = dn;
}
+ parent_dirname = dn;
- statret = link_stat(fname, &st,
-@@ -859,7 +869,8 @@ static void recv_generator(char *fname,
+@@ -871,7 +877,8 @@ static void recv_generator(char *fname,
if (!preserve_perms) {
int exists = statret == 0
&& S_ISDIR(st.st_mode) == S_ISDIR(file->mode);
}
if (S_ISDIR(file->mode)) {
-@@ -893,6 +904,10 @@ static void recv_generator(char *fname,
- if (set_file_attrs(fname, file, statret ? NULL : &st, 0)
- && verbose && code && f_out != -1)
- rprintf(code, "%s/\n", fname);
-+#ifdef SUPPORT_ACLS
-+ if (f_out == -1)
-+ SET_ACL(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, &st);
-@@ -1328,6 +1343,8 @@ void generate_files(int f_out, struct fi
+@@ -1342,6 +1349,8 @@ void generate_files(int f_out, struct fi
* notice that and let us know via the redo pipe (or its closing). */
ignore_timeout = 1;
--- old/options.c
+++ new/options.c
-@@ -44,6 +44,7 @@ int keep_dirlinks = 0;
+@@ -45,6 +45,7 @@ int copy_dirlinks = 0;
int copy_links = 0;
int preserve_links = 0;
int preserve_hard_links = 0;
int preserve_perms = 0;
int preserve_executability = 0;
int preserve_devices = 0;
-@@ -193,6 +194,7 @@ static void print_rsync_version(enum log
+@@ -194,6 +195,7 @@ static void print_rsync_version(enum log
char const *got_socketpair = "no ";
char const *have_inplace = "no ";
char const *hardlinks = "no ";
char const *links = "no ";
char const *ipv6 = "no ";
STRUCT_STAT *dumstat;
-@@ -209,6 +211,10 @@ static void print_rsync_version(enum log
+@@ -210,6 +212,10 @@ static void print_rsync_version(enum log
hardlinks = "";
#endif
#ifdef SUPPORT_LINKS
links = "";
#endif
-@@ -222,9 +228,9 @@ static void print_rsync_version(enum log
+@@ -223,9 +229,9 @@ static void print_rsync_version(enum log
rprintf(f, "Copyright (C) 1996-2006 by Andrew Tridgell, Wayne Davison, and others.\n");
rprintf(f, "<http://rsync.samba.org/>\n");
rprintf(f, "Capabilities: %d-bit files, %ssocketpairs, "
/* Note that this field may not have type ino_t. It depends
* on the complicated interaction between largefile feature
-@@ -293,6 +299,9 @@ void usage(enum logcode F)
- rprintf(F," -K, --keep-dirlinks treat symlinked dir on receiver as dir\n");
+@@ -295,6 +301,9 @@ void usage(enum logcode F)
+ rprintf(F," -H, --hard-links preserve hard links\n");
rprintf(F," -p, --perms preserve permissions\n");
rprintf(F," -E, --executability preserve the file's executability\n");
+#ifdef SUPPORT_ACLS
rprintf(F," --chmod=CHMOD change destination permissions\n");
rprintf(F," -o, --owner preserve owner (super-user only)\n");
rprintf(F," -g, --group preserve group\n");
-@@ -409,6 +418,9 @@ static struct poptOption long_options[]
+@@ -410,6 +419,9 @@ static struct poptOption long_options[]
{"no-perms", 0, POPT_ARG_VAL, &preserve_perms, 0, 0, 0 },
{"no-p", 0, POPT_ARG_VAL, &preserve_perms, 0, 0, 0 },
{"executability", 'E', POPT_ARG_NONE, &preserve_executability, 0, 0, 0 },
{"times", 't', POPT_ARG_VAL, &preserve_times, 1, 0, 0 },
{"no-times", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
{"no-t", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
-@@ -1057,6 +1069,23 @@ int parse_arguments(int *argc, const cha
+@@ -1068,6 +1080,23 @@ int parse_arguments(int *argc, const cha
usage(FINFO);
exit_cleanup(0);
default:
/* A large opt value means that set_refuse_options()
* turned this option off. */
-@@ -1497,6 +1526,10 @@ void server_options(char **args,int *arg
+@@ -1511,6 +1540,10 @@ void server_options(char **args,int *arg
if (preserve_hard_links)
argstr[x++] = 'H';
if (preserve_gid)
--- old/receiver.c
+++ new/receiver.c
-@@ -410,6 +410,10 @@ int recv_files(int f_in, struct file_lis
+@@ -46,6 +46,7 @@ extern int keep_partial;
+ extern int checksum_seed;
+ extern int inplace;
+ extern int delay_updates;
++extern mode_t orig_umask;
+ extern struct stats stats;
+ extern char *log_format;
+ extern char *tmpdir;
+@@ -344,6 +345,10 @@ int recv_files(int f_in, struct file_lis
int itemizing = am_daemon ? daemon_log_format_has_i
: !am_server && log_format_has_i;
int max_phase = protocol_version >= 29 ? 2 : 1;
int i, recv_ok;
if (verbose > 2)
-@@ -607,7 +611,16 @@ int recv_files(int f_in, struct file_lis
+@@ -541,7 +546,16 @@ int recv_files(int f_in, struct file_lis
* mode based on the local permissions and some heuristics. */
if (!preserve_perms) {
int exists = fd1 != -1;
/* We now check to see if we are writing file "inplace" */
--- old/rsync.c
+++ new/rsync.c
-@@ -91,7 +91,8 @@ void free_sums(struct sum_struct *s)
+@@ -101,7 +101,8 @@ void free_sums(struct sum_struct *s)
/* This is only called when we aren't preserving permissions. Figure out what
* the permissions should be and return them merged back into the mode. */
--mode_t dest_mode(mode_t flist_mode, mode_t dest_mode, int exists)
-+mode_t dest_mode(mode_t flist_mode, mode_t dest_mode, int dflt_perms,
+-mode_t dest_mode(mode_t flist_mode, mode_t cur_mode, int exists)
++mode_t dest_mode(mode_t flist_mode, mode_t cur_mode, int dflt_perms,
+ int exists)
{
/* If the file already exists, we'll return the local permissions,
* possibly tweaked by the --executability option. */
-@@ -106,7 +107,7 @@ mode_t dest_mode(mode_t flist_mode, mode
- dest_mode |= (dest_mode & 0444) >> 2;
+@@ -116,7 +117,7 @@ mode_t dest_mode(mode_t flist_mode, mode
+ cur_mode |= (cur_mode & 0444) >> 2;
}
} else
-- dest_mode = flist_mode & ACCESSPERMS & ~orig_umask;
-+ dest_mode = (flist_mode & ACCESSPERMS & dflt_perms) | S_IWUSR;
- return (flist_mode & ~CHMOD_BITS) | (dest_mode & CHMOD_BITS);
- }
-
-@@ -205,6 +206,14 @@ int set_file_attrs(char *fname, struct f
+- cur_mode = flist_mode & ACCESSPERMS & ~orig_umask;
++ cur_mode = flist_mode & ACCESSPERMS & dflt_perms;
+ if (daemon_chmod_modes && !S_ISLNK(flist_mode))
+ cur_mode = tweak_mode(cur_mode, daemon_chmod_modes);
+ return (flist_mode & ~CHMOD_BITS) | (cur_mode & CHMOD_BITS);
+@@ -203,6 +204,13 @@ int set_file_attrs(char *fname, struct f
+ updated = 1;
}
- #endif
-+ /* If this is a directory, SET_ACL() will be called on the cleanup
-+ * receive_generator() pass (if we called it here, we might clobber
-+ * writability on the directory). Everything else is OK to do now. */
-+ if (!S_ISDIR(st->st_mode)) {
-+ if (SET_ACL(fname, file) == 0)
-+ updated = 1;
-+ }
++#ifdef SUPPORT_ACLS
++ /* It's OK to call set_acl() now, even for a dir, as the generator
++ * will enable owner-writability using chmod, if necessary. */
++ if (set_acl(fname, file) == 0)
++ updated = 1;
++#endif
+
- if (verbose > 1 && flags & ATTRS_REPORT) {
- enum logcode code = daemon_log_format_has_i || dry_run
- ? FCLIENT : FINFO;
+ #ifdef HAVE_CHMOD
+ if ((st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) {
+ int ret = do_chmod(fname, file->mode);
--- old/rsync.h
+++ new/rsync.h
-@@ -657,6 +657,44 @@ struct chmod_mode_struct;
+@@ -658,6 +658,20 @@ struct chmod_mode_struct;
#define UNUSED(x) x __attribute__((__unused__))
+#define ACLS_NEED_MASK 1
+#endif
+
-+#ifdef SUPPORT_ACLS
-+#ifdef HAVE_SYS_ACL_H
++#if defined SUPPORT_ACLS && defined HAVE_SYS_ACL_H
+#include <sys/acl.h>
+#endif
-+#define MAKE_ACL(file, fname) make_acl(file, fname)
-+#define SEND_ACL(file, f) send_acl(file, f)
-+#define RECEIVE_ACL(file, f) receive_acl(file, f)
-+#define SORT_FILE_ACL_INDEX_LISTS() sort_file_acl_index_lists()
-+#define SET_ACL(fname, file) set_acl(fname, file)
-+#define NEXT_ACL_UID() next_acl_uid()
-+#define ACL_UID_MAP(uid) acl_uid_map(uid)
-+#define PUSH_KEEP_BACKUP_ACL(file, orig, dest) \
-+ push_keep_backup_acl(file, orig, dest)
-+#define CLEANUP_KEEP_BACKUP_ACL() cleanup_keep_backup_acl()
-+#define DUP_ACL(orig, dest, mode) dup_acl(orig, dest, mode)
-+#else /* SUPPORT_ACLS */
-+#define MAKE_ACL(file, fname) 1 /* checked return value */
-+#define SEND_ACL(file, f)
-+#define RECEIVE_ACL(file, f)
-+#define SORT_FILE_ACL_INDEX_LISTS()
-+#define SET_ACL(fname, file) 1 /* checked return value */
-+#define NEXT_ACL_UID()
-+#define ACL_UID_MAP(uid)
-+#define PUSH_KEEP_BACKUP_ACL(file, orig, dest)
-+#define CLEANUP_KEEP_BACKUP_ACL()
-+#define DUP_ACL(src, orig, mode) 1 /* checked return value */
-+#endif /* SUPPORT_ACLS */
+#include "smb_acls.h"
+
#include "proto.h"
/* We have replacement versions of these if they're missing. */
--- old/rsync.yo
+++ new/rsync.yo
-@@ -317,6 +317,7 @@ to the detailed description below for a
- -K, --keep-dirlinks treat symlinked dir on receiver as dir
+@@ -321,6 +321,7 @@ to the detailed description below for a
+ -H, --hard-links preserve hard links
-p, --perms preserve permissions
-E, --executability preserve executability
+ -A, --acls preserve ACLs (implies -p) [non-standard]
--chmod=CHMOD change destination permissions
-o, --owner preserve owner (super-user only)
-g, --group preserve group
-@@ -691,7 +692,9 @@ quote(itemize(
+@@ -742,7 +743,9 @@ quote(itemize(
permissions, though the bf(--executability) option might change just
the execute permission for the file.
it() New files get their "normal" permission bits set to the source
their special permission bits disabled except in the case where a new
directory inherits a setgid bit from its parent directory.
))
-@@ -722,9 +725,11 @@ The preservation of the destination's se
+@@ -773,9 +776,11 @@ The preservation of the destination's se
directories when bf(--perms) is off was added in rsync 2.6.7. Older rsync
versions erroneously preserved the three special permission bits for
newly-created files when bf(--perms) was off, while overriding the
dit(bf(-E, --executability)) This option causes rsync to preserve the
executability (or non-executability) of regular files when bf(--perms) is
-@@ -742,6 +747,10 @@ quote(itemize(
+@@ -793,6 +798,10 @@ quote(itemize(
If bf(--perms) is enabled, this option is ignored.
+#ifndef _SMB_ACLS_H
+#define _SMB_ACLS_H
+
-+#if defined(HAVE_POSIX_ACLS)
++#if defined HAVE_POSIX_ACLS
+
+/* This is an identity mapping (just remove the SMB_). */
+
+#define SMB_ACL_TYPE_ACCESS ACL_TYPE_ACCESS
+#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT
+
-+#elif defined(HAVE_TRU64_ACLS)
++#elif defined HAVE_TRU64_ACLS
+
+/* This is for DEC/Compaq Tru64 UNIX */
+
+#define SMB_ACL_TYPE_ACCESS ACL_TYPE_ACCESS
+#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT
+
-+#elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
++#elif defined HAVE_UNIXWARE_ACLS || defined HAVE_SOLARIS_ACLS
+/*
+ * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
+ * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
+#define SMB_ACL_TYPE_ACCESS 0
+#define SMB_ACL_TYPE_DEFAULT 1
+
-+#elif defined(HAVE_HPUX_ACLS)
++#elif defined HAVE_HPUX_ACLS
+
+/*
+ * Based on the Solaris & UnixWare code.
+#define SMB_ACL_TYPE_ACCESS 0
+#define SMB_ACL_TYPE_DEFAULT 1
+
-+#elif defined(HAVE_IRIX_ACLS)
++#elif defined HAVE_IRIX_ACLS
+
+#define SMB_ACL_TAG_T acl_tag_t
+#define SMB_ACL_TYPE_T acl_type_t
+#define SMB_ACL_TYPE_ACCESS ACL_TYPE_ACCESS
+#define SMB_ACL_TYPE_DEFAULT ACL_TYPE_DEFAULT
+
-+#elif defined(HAVE_AIX_ACLS)
++#elif defined HAVE_AIX_ACLS
+
+/* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
+
+ $RSYNC -rvv "$scratchdir/file" "$todir/to/anotherfile"
+ check_perms "$todir/to/anotherfile" $3 "Target $1"
+ # Make sure we obey default ACLs when not transferring a regular file
-+ $RSYNC -rvv "$scratchdir/dir" "$todir/to/anotherdir"
++ $RSYNC -rvv "$scratchdir/dir/" "$todir/to/anotherdir/"
+ check_perms "$todir/to/anotherdir" $4 "Target $1"
+}
+