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)
+{
+ "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
-@@ -132,6 +132,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 = '/';
-@@ -185,6 +186,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))) {
-@@ -260,6 +263,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/flist.c
+++ new/flist.c
-@@ -966,6 +966,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);
-@@ -977,6 +979,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;
}
-@@ -1365,6 +1371,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) || S_ISLNK(file->mode))
stats.total_size += file->length;
-@@ -1387,6 +1395,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);
}
if (S_ISDIR(file->mode)) {
-@@ -905,6 +912,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);
-@@ -1342,6 +1353,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;
}
} else
- cur_mode = flist_mode & ACCESSPERMS & ~orig_umask;
-+ cur_mode = (flist_mode & ACCESSPERMS & dflt_perms) | S_IWUSR;
++ 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);
-@@ -217,6 +218,14 @@ int set_file_attrs(char *fname, struct f
+@@ -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
-@@ -658,6 +658,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"
+#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 */
+