Initial Package Version: rsync 2.7.9 Origin: Taken as a diff from http://mattmccutchen.net/rsync/ Description: Adds ACL support to rsync Submitted By: animeloe Date: 6 Febuary 2008 Upstream Status: unkonwn diff -u rsync-2.6.9/Makefile.in rsync-acl-2.6.9/Makefile.in --- rsync-2.6.9/Makefile.in 2006-10-24 11:09:57.000000000 -0400 +++ rsync-acl-2.6.9/Makefile.in 2006-11-08 00:02:03.000000000 -0500 @@ -26,15 +26,15 @@ .SUFFIXES: .SUFFIXES: .c .o -HEADERS=byteorder.h config.h errcode.h proto.h rsync.h lib/pool_alloc.h +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 @LIBOBJS@ + lib/permstring.o lib/pool_alloc.o lib/sysacls.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 chmod.o + fileio.o batch.o clientname.o chmod.o acls.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 \ Only in rsync-acl-2.6.9/: acls.c diff -u rsync-2.6.9/backup.c rsync-acl-2.6.9/backup.c --- rsync-2.6.9/backup.c 2006-04-25 19:51:12.000000000 -0400 +++ rsync-acl-2.6.9/backup.c 2006-11-08 00:02:03.000000000 -0500 @@ -29,6 +29,7 @@ extern char *backup_dir; extern int am_root; +extern int preserve_acls; extern int preserve_devices; extern int preserve_specials; extern int preserve_links; @@ -94,7 +95,8 @@ ****************************************************************************/ static int make_bak_dir(char *fullpath) { - STRUCT_STAT st; + statx sx; + struct file_struct *file; char *rel = fullpath + backup_dir_len; char *end = rel + strlen(rel); char *p = end; @@ -126,13 +128,24 @@ if (p >= rel) { /* Try to transfer the directory settings of the * actual dir that the files are coming from. */ - if (do_stat(rel, &st) < 0) { + if (do_stat(rel, &sx.st) < 0) { rsyserr(FERROR, errno, "make_bak_dir stat %s failed", full_fname(rel)); } else { - do_lchown(fullpath, st.st_uid, st.st_gid); - do_chmod(fullpath, st.st_mode); +#ifdef SUPPORT_ACLS + sx.acc_acl = sx.def_acl = NULL; +#endif + if (!(file = make_file(rel, NULL, NULL, 0, NO_FILTERS))) + continue; +#ifdef SUPPORT_ACLS + if (preserve_acls) { + get_acl(rel, &sx); + cache_acl(file, &sx); + } +#endif + set_file_attrs(fullpath, file, NULL, 0); + free(file); } } *p = '/'; @@ -170,15 +183,18 @@ * We will move the file to be deleted into a parallel directory tree. */ static int keep_backup(char *fname) { - STRUCT_STAT st; + statx sx; struct file_struct *file; char *buf; int kept = 0; int ret_code; /* return if no file to keep */ - if (do_lstat(fname, &st) < 0) + if (do_lstat(fname, &sx.st) < 0) return 1; +#ifdef SUPPORT_ACLS + sx.acc_acl = sx.def_acl = NULL; +#endif if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) return 1; /* the file could have disappeared */ @@ -186,6 +202,13 @@ if (!(buf = get_backup_name(fname))) return 0; +#ifdef SUPPORT_ACLS + if (preserve_acls) { + get_acl(fname, &sx); + cache_acl(file, &sx); + } +#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))) { @@ -254,7 +277,7 @@ if (robust_move(fname, buf) != 0) { rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"", full_fname(fname), buf); - } else if (st.st_nlink > 1) { + } else if (sx.st.st_nlink > 1) { /* If someone has hard-linked the file into the backup * dir, rename() might return success but do nothing! */ robust_unlink(fname); /* Just in case... */ diff -u rsync-2.6.9/config.h.in rsync-acl-2.6.9/config.h.in --- rsync-2.6.9/config.h.in 2006-11-06 23:39:47.000000000 -0500 +++ rsync-acl-2.6.9/config.h.in 2006-11-08 00:02:04.000000000 -0500 @@ -27,6 +27,18 @@ /* Define to 1 if the `getpgrp' function requires zero arguments. */ #undef GETPGRP_VOID +/* Define to 1 if you have the `aclsort' function. */ +#undef HAVE_ACLSORT + +/* true if you have acl_get_perm_np */ +#undef HAVE_ACL_GET_PERM_NP + +/* Define to 1 if you have the header file. */ +#undef HAVE_ACL_LIBACL_H + +/* true if you have AIX ACLs */ +#undef HAVE_AIX_ACLS + /* Define to 1 if you have `alloca', as a function or macro. */ #undef HAVE_ALLOCA @@ -119,6 +131,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_GRP_H +/* true if you have HPUX ACLs */ +#undef HAVE_HPUX_ACLS + /* Define to 1 if you have the header file. */ #undef HAVE_ICONV_H @@ -134,6 +149,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H +/* true if you have IRIX ACLs */ +#undef HAVE_IRIX_ACLS + /* Define to 1 if you have the header file. */ #undef HAVE_LANGINFO_H @@ -143,6 +161,9 @@ /* Define to 1 if you have the `lchown' function. */ #undef HAVE_LCHOWN +/* Define to 1 if you have the `acl' library (-lacl). */ +#undef HAVE_LIBACL + /* Define to 1 if you have the header file. */ #undef HAVE_LIBCHARSET_H @@ -161,6 +182,9 @@ /* Define to 1 if you have the `resolv' library (-lresolv). */ #undef HAVE_LIBRESOLV +/* Define to 1 if you have the `sec' library (-lsec). */ +#undef HAVE_LIBSEC + /* Define to 1 if you have the `socket' library (-lsocket). */ #undef HAVE_LIBSOCKET @@ -226,9 +250,15 @@ /* Define to 1 if you have the `nl_langinfo' function. */ #undef HAVE_NL_LANGINFO +/* true if you don't have ACLs */ +#undef HAVE_NO_ACLS + /* Define to 1 if you have the `open64' function. */ #undef HAVE_OPEN64 +/* true if you have posix ACLs */ +#undef HAVE_POSIX_ACLS + /* Define to 1 if you have the `putenv' function. */ #undef HAVE_PUTENV @@ -280,6 +310,9 @@ /* Define to 1 if you have the "socketpair" function */ #undef HAVE_SOCKETPAIR +/* true if you have solaris ACLs */ +#undef HAVE_SOLARIS_ACLS + /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H @@ -325,6 +358,9 @@ /* Define to 1 if `st_rdev' is member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_RDEV +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_ACL_H + /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_DIR_H @@ -375,9 +411,15 @@ /* Define to 1 if you have the `tcgetpgrp' function. */ #undef HAVE_TCGETPGRP +/* true if you have Tru64 ACLs */ +#undef HAVE_TRU64_ACLS + /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H +/* true if you have UnixWare ACLs */ +#undef HAVE_UNIXWARE_ACLS + /* Define to 1 if you have the "struct utimbuf" type */ #undef HAVE_UTIMBUF @@ -408,6 +450,18 @@ /* Define to 1 if you have the `waitpid' function. */ #undef HAVE_WAITPID +/* Define to 1 if you have the `_acl' function. */ +#undef HAVE__ACL + +/* Define to 1 if you have the `_facl' function. */ +#undef HAVE__FACL + +/* Define to 1 if you have the `__acl' function. */ +#undef HAVE___ACL + +/* Define to 1 if you have the `__facl' function. */ +#undef HAVE___FACL + /* Define to 1 if you have the `__va_copy' function. */ #undef HAVE___VA_COPY diff -u rsync-2.6.9/configure rsync-acl-2.6.9/configure --- rsync-2.6.9/configure 2006-11-06 23:39:47.000000000 -0500 +++ rsync-acl-2.6.9/configure 2006-11-08 00:02:04.000000000 -0500 @@ -1258,6 +1258,7 @@ --disable-largefile omit support for large files --disable-ipv6 don't even try to use IPv6 --disable-locale turn off locale features + --enable-acl-support Include ACL support (default=no) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -12941,6 +12942,206 @@ fi +for ac_func in aclsort +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +if test x"$ac_cv_func_aclsort" = x"no"; then + +{ echo "$as_me:$LINENO: checking for aclsort in -lsec" >&5 +echo $ECHO_N "checking for aclsort in -lsec... $ECHO_C" >&6; } +if test "${ac_cv_lib_sec_aclsort+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsec $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char aclsort (); +int +main () +{ +return aclsort (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_sec_aclsort=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_sec_aclsort=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_sec_aclsort" >&5 +echo "${ECHO_T}$ac_cv_lib_sec_aclsort" >&6; } +if test $ac_cv_lib_sec_aclsort = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSEC 1 +_ACEOF + + LIBS="-lsec $LIBS" + +fi + +fi + + { echo "$as_me:$LINENO: checking whether utime accepts a null argument" >&5 echo $ECHO_N "checking whether utime accepts a null argument... $ECHO_C" >&6; } if test "${ac_cv_func_utime_null+set}" = set; then @@ -14808,6 +15009,625 @@ + + +for ac_header in sys/acl.h acl/libacl.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + +for ac_func in _acl __acl _facl __facl +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +################################################# +# check for ACL support + +{ echo "$as_me:$LINENO: checking whether to support ACLs" >&5 +echo $ECHO_N "checking whether to support ACLs... $ECHO_C" >&6; } +# Check whether --enable-acl-support was given. +if test "${enable_acl_support+set}" = set; then + enableval=$enable_acl_support; case "$enableval" in + yes) + + case "$host_os" in + *sysv5*) + { echo "$as_me:$LINENO: result: Using UnixWare ACLs" >&5 +echo "${ECHO_T}Using UnixWare ACLs" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_UNIXWARE_ACLS 1 +_ACEOF + + ;; + *solaris*|*cygwin*) + { echo "$as_me:$LINENO: result: Using solaris ACLs" >&5 +echo "${ECHO_T}Using solaris ACLs" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SOLARIS_ACLS 1 +_ACEOF + + ;; + *hpux*) + { echo "$as_me:$LINENO: result: Using HPUX ACLs" >&5 +echo "${ECHO_T}Using HPUX ACLs" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_HPUX_ACLS 1 +_ACEOF + + ;; + *irix*) + { echo "$as_me:$LINENO: result: Using IRIX ACLs" >&5 +echo "${ECHO_T}Using IRIX ACLs" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_IRIX_ACLS 1 +_ACEOF + + ;; + *aix*) + { echo "$as_me:$LINENO: result: Using AIX ACLs" >&5 +echo "${ECHO_T}Using AIX ACLs" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_AIX_ACLS 1 +_ACEOF + + ;; + *osf*) + { echo "$as_me:$LINENO: result: Using Tru64 ACLs" >&5 +echo "${ECHO_T}Using Tru64 ACLs" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TRU64_ACLS 1 +_ACEOF + + LIBS="$LIBS -lpacl" + ;; + *) + { echo "$as_me:$LINENO: result: ACLs requested -- running tests" >&5 +echo "${ECHO_T}ACLs requested -- running tests" >&6; } + +{ echo "$as_me:$LINENO: checking for acl_get_file in -lacl" >&5 +echo $ECHO_N "checking for acl_get_file in -lacl... $ECHO_C" >&6; } +if test "${ac_cv_lib_acl_acl_get_file+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lacl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char acl_get_file (); +int +main () +{ +return acl_get_file (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_acl_acl_get_file=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_acl_acl_get_file=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_acl_acl_get_file" >&5 +echo "${ECHO_T}$ac_cv_lib_acl_acl_get_file" >&6; } +if test $ac_cv_lib_acl_acl_get_file = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBACL 1 +_ACEOF + + LIBS="-lacl $LIBS" + +fi + + { echo "$as_me:$LINENO: checking for ACL support" >&5 +echo $ECHO_N "checking for ACL support... $ECHO_C" >&6; } +if test "${samba_cv_HAVE_POSIX_ACLS+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +int +main () +{ + acl_t acl; int entry_id; acl_entry_t *entry_p; return acl_get_entry( acl, entry_id, entry_p); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + samba_cv_HAVE_POSIX_ACLS=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + samba_cv_HAVE_POSIX_ACLS=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $samba_cv_HAVE_POSIX_ACLS" >&5 +echo "${ECHO_T}$samba_cv_HAVE_POSIX_ACLS" >&6; } + { echo "$as_me:$LINENO: checking ACL test results" >&5 +echo $ECHO_N "checking ACL test results... $ECHO_C" >&6; } + if test x"$samba_cv_HAVE_POSIX_ACLS" = x"yes"; then + { echo "$as_me:$LINENO: result: Using posix ACLs" >&5 +echo "${ECHO_T}Using posix ACLs" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_POSIX_ACLS 1 +_ACEOF + + { echo "$as_me:$LINENO: checking for acl_get_perm_np" >&5 +echo $ECHO_N "checking for acl_get_perm_np... $ECHO_C" >&6; } +if test "${samba_cv_HAVE_ACL_GET_PERM_NP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +int +main () +{ + acl_permset_t permset_d; acl_perm_t perm; return acl_get_perm_np( permset_d, perm); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + samba_cv_HAVE_ACL_GET_PERM_NP=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + samba_cv_HAVE_ACL_GET_PERM_NP=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $samba_cv_HAVE_ACL_GET_PERM_NP" >&5 +echo "${ECHO_T}$samba_cv_HAVE_ACL_GET_PERM_NP" >&6; } + if test x"$samba_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ACL_GET_PERM_NP 1 +_ACEOF + + fi + else + { { echo "$as_me:$LINENO: error: Failed to find ACL support" >&5 +echo "$as_me: error: Failed to find ACL support" >&2;} + { (exit 1); exit 1; }; } + fi + ;; + esac + ;; + *) + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_NO_ACLS 1 +_ACEOF + + ;; + esac +else + +cat >>confdefs.h <<\_ACEOF +#define HAVE_NO_ACLS 1 +_ACEOF + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + +fi + + ac_config_files="$ac_config_files Makefile lib/dummy zlib/dummy popt/dummy shconfig" cat >confcache <<\_ACEOF diff -u rsync-2.6.9/configure.in rsync-acl-2.6.9/configure.in --- rsync-2.6.9/configure.in 2006-11-06 23:39:47.000000000 -0500 +++ rsync-acl-2.6.9/configure.in 2006-11-08 00:02:03.000000000 -0500 @@ -515,6 +515,11 @@ AC_CHECK_LIB(resolv, strcasecmp) fi +AC_CHECK_FUNCS(aclsort) +if test x"$ac_cv_func_aclsort" = x"no"; then + AC_CHECK_LIB(sec, aclsort) +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. @@ -779,6 +784,78 @@ AC_SUBST(CC_SHOBJ_FLAG) AC_SUBST(BUILD_POPT) +AC_CHECK_HEADERS(sys/acl.h acl/libacl.h) +AC_CHECK_FUNCS(_acl __acl _facl __facl) +################################################# +# check for ACL support + +AC_MSG_CHECKING(whether to support ACLs) +AC_ARG_ENABLE(acl-support, +AC_HELP_STRING([--enable-acl-support], [Include ACL support (default=no)]), +[ case "$enableval" in + yes) + + case "$host_os" in + *sysv5*) + AC_MSG_RESULT(Using UnixWare ACLs) + AC_DEFINE(HAVE_UNIXWARE_ACLS, 1, [true if you have UnixWare ACLs]) + ;; + *solaris*|*cygwin*) + AC_MSG_RESULT(Using solaris ACLs) + AC_DEFINE(HAVE_SOLARIS_ACLS, 1, [true if you have solaris ACLs]) + ;; + *hpux*) + AC_MSG_RESULT(Using HPUX ACLs) + AC_DEFINE(HAVE_HPUX_ACLS, 1, [true if you have HPUX ACLs]) + ;; + *irix*) + AC_MSG_RESULT(Using IRIX ACLs) + AC_DEFINE(HAVE_IRIX_ACLS, 1, [true if you have IRIX ACLs]) + ;; + *aix*) + AC_MSG_RESULT(Using AIX ACLs) + AC_DEFINE(HAVE_AIX_ACLS, 1, [true if you have AIX ACLs]) + ;; + *osf*) + AC_MSG_RESULT(Using Tru64 ACLs) + AC_DEFINE(HAVE_TRU64_ACLS, 1, [true if you have Tru64 ACLs]) + LIBS="$LIBS -lpacl" + ;; + *) + AC_MSG_RESULT(ACLs requested -- running tests) + AC_CHECK_LIB(acl,acl_get_file) + AC_CACHE_CHECK([for ACL support],samba_cv_HAVE_POSIX_ACLS,[ + AC_TRY_LINK([#include +#include ], +[ acl_t acl; int entry_id; acl_entry_t *entry_p; return acl_get_entry( acl, entry_id, entry_p);], +samba_cv_HAVE_POSIX_ACLS=yes,samba_cv_HAVE_POSIX_ACLS=no)]) + AC_MSG_CHECKING(ACL test results) + if test x"$samba_cv_HAVE_POSIX_ACLS" = x"yes"; then + AC_MSG_RESULT(Using posix ACLs) + AC_DEFINE(HAVE_POSIX_ACLS, 1, [true if you have posix ACLs]) + AC_CACHE_CHECK([for acl_get_perm_np],samba_cv_HAVE_ACL_GET_PERM_NP,[ + AC_TRY_LINK([#include +#include ], +[ acl_permset_t permset_d; acl_perm_t perm; return acl_get_perm_np( permset_d, perm);], +samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_cv_HAVE_ACL_GET_PERM_NP=no)]) + if test x"$samba_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then + AC_DEFINE(HAVE_ACL_GET_PERM_NP, 1, [true if you have acl_get_perm_np]) + fi + else + AC_MSG_ERROR(Failed to find ACL support) + fi + ;; + esac + ;; + *) + AC_MSG_RESULT(no) + AC_DEFINE(HAVE_NO_ACLS, 1, [true if you don't have ACLs]) + ;; + esac ], + AC_DEFINE(HAVE_NO_ACLS, 1, [true if you don't have ACLs]) + AC_MSG_RESULT(no) +) + AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig]) AC_OUTPUT Common subdirectories: rsync-2.6.9/doc and rsync-acl-2.6.9/doc diff -u rsync-2.6.9/flist.c rsync-acl-2.6.9/flist.c --- rsync-2.6.9/flist.c 2006-10-13 21:17:36.000000000 -0400 +++ rsync-acl-2.6.9/flist.c 2006-11-08 00:02:03.000000000 -0500 @@ -40,6 +40,7 @@ extern int one_file_system; extern int copy_dirlinks; extern int keep_dirlinks; +extern int preserve_acls; extern int preserve_links; extern int preserve_hard_links; extern int preserve_devices; @@ -133,6 +134,8 @@ permstring(permbuf, f->mode); + /* TODO: indicate '+' if the entry has an ACL. */ + #ifdef SUPPORT_LINKS if (preserve_links && S_ISLNK(f->mode)) { rprintf(FINFO, "%s %11.0f %s %s -> %s\n", @@ -495,6 +498,9 @@ char thisname[MAXPATHLEN]; unsigned int l1 = 0, l2 = 0; int alloc_len, basename_len, dirname_len, linkname_len, sum_len; +#ifdef SUPPORT_ACLS + int xtra_len; +#endif OFF_T file_length; char *basename, *dirname, *bp; struct file_struct *file; @@ -598,13 +604,27 @@ sum_len = always_checksum && S_ISREG(mode) ? MD4_SUM_LENGTH : 0; +#ifdef SUPPORT_ACLS + /* We need one or two index int32s when we're preserving ACLs. */ + if (preserve_acls) + xtra_len = (S_ISDIR(mode) ? 2 : 1) * 4; + else + xtra_len = 0; +#endif + alloc_len = file_struct_len + dirname_len + basename_len +#ifdef SUPPORT_ACLS + + xtra_len +#endif + linkname_len + sum_len; bp = pool_alloc(flist->file_pool, alloc_len, "receive_file_entry"); file = (struct file_struct *)bp; memset(bp, 0, file_struct_len); bp += file_struct_len; +#ifdef SUPPORT_ACLS + bp += xtra_len; +#endif file->modtime = modtime; file->length = file_length; @@ -699,6 +719,11 @@ read_buf(f, sum, checksum_len); } +#ifdef SUPPORT_ACLS + if (preserve_acls) + receive_acl(file, f); +#endif + return file; } @@ -949,6 +974,9 @@ unsigned short flags) { struct file_struct *file; +#ifdef SUPPORT_ACLS + statx sx; +#endif file = make_file(fname, flist, stp, flags, f == -2 ? SERVER_FILTERS : ALL_FILTERS); @@ -958,6 +986,15 @@ if (chmod_modes && !S_ISLNK(file->mode)) file->mode = tweak_mode(file->mode, chmod_modes); +#ifdef SUPPORT_ACLS + if (preserve_acls) { + sx.st.st_mode = file->mode; + sx.acc_acl = sx.def_acl = NULL; + if (get_acl(fname, &sx) < 0) + return NULL; + } +#endif + maybe_emit_filelist_progress(flist->count + flist_count_offset); flist_expand(flist); @@ -965,6 +1002,15 @@ if (file->basename[0]) { flist->files[flist->count++] = file; send_file_entry(file, f); +#ifdef SUPPORT_ACLS + if (preserve_acls) + send_acl(&sx, f); +#endif + } else { +#ifdef SUPPORT_ACLS + if (preserve_acls) + free_acl(&sx); +#endif } return file; } diff -u rsync-2.6.9/generator.c rsync-acl-2.6.9/generator.c --- rsync-2.6.9/generator.c 2006-10-22 18:36:36.000000000 -0400 +++ rsync-acl-2.6.9/generator.c 2006-11-08 00:02:03.000000000 -0500 @@ -35,6 +35,7 @@ extern int relative_paths; extern int implied_dirs; extern int keep_dirlinks; +extern int preserve_acls; extern int preserve_links; extern int preserve_devices; extern int preserve_specials; @@ -85,6 +86,7 @@ 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; @@ -317,22 +319,27 @@ rprintf(FINFO, " \r"); } -int unchanged_attrs(struct file_struct *file, STRUCT_STAT *st) +int unchanged_attrs(struct file_struct *file, statx *sxp) { if (preserve_perms - && (st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) + && (sxp->st.st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) return 0; - if (am_root && preserve_uid && st->st_uid != file->uid) + if (am_root && preserve_uid && sxp->st.st_uid != file->uid) return 0; - if (preserve_gid && file->gid != GID_NONE && st->st_gid != file->gid) + if (preserve_gid && file->gid != GID_NONE && sxp->st.st_gid != file->gid) return 0; +#ifdef SUPPORT_ACLS + if (preserve_acls && set_acl(NULL, file, sxp) == 0) + return 0; +#endif + return 1; } -void itemize(struct file_struct *file, int ndx, int statret, STRUCT_STAT *st, +void itemize(struct file_struct *file, int ndx, int statret, statx *sxp, int32 iflags, uchar fnamecmp_type, char *xname) { if (statret >= 0) { /* A from-dest-dir statret can == 1! */ @@ -340,19 +347,23 @@ : S_ISDIR(file->mode) ? !omit_dir_times : !S_ISLNK(file->mode); - if (S_ISREG(file->mode) && file->length != st->st_size) + if (S_ISREG(file->mode) && file->length != sxp->st.st_size) iflags |= ITEM_REPORT_SIZE; if ((iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !keep_time && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname)) - || (keep_time && cmp_time(file->modtime, st->st_mtime) != 0)) + || (keep_time && cmp_time(file->modtime, sxp->st.st_mtime) != 0)) iflags |= ITEM_REPORT_TIME; - if ((file->mode & CHMOD_BITS) != (st->st_mode & CHMOD_BITS)) + if ((file->mode & CHMOD_BITS) != (sxp->st.st_mode & CHMOD_BITS)) iflags |= ITEM_REPORT_PERMS; - if (preserve_uid && am_root && file->uid != st->st_uid) + if (preserve_uid && am_root && file->uid != sxp->st.st_uid) iflags |= ITEM_REPORT_OWNER; if (preserve_gid && file->gid != GID_NONE - && st->st_gid != file->gid) + && sxp->st.st_gid != file->gid) iflags |= ITEM_REPORT_GROUP; +#ifdef SUPPORT_ACLS + if (preserve_acls && set_acl(NULL, file, sxp) == 0) + iflags |= ITEM_REPORT_ACL; +#endif } else iflags |= ITEM_IS_NEW; @@ -605,7 +616,7 @@ * handling the file, -1 if no dest-linking occurred, or a non-negative * value if we found an alternate basis file. */ static int try_dests_reg(struct file_struct *file, char *fname, int ndx, - char *cmpbuf, STRUCT_STAT *stp, int itemizing, + char *cmpbuf, statx *sxp, int itemizing, int maybe_ATTRS_REPORT, enum logcode code) { int best_match = -1; @@ -614,7 +625,7 @@ do { pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname); - if (link_stat(cmpbuf, stp, 0) < 0 || !S_ISREG(stp->st_mode)) + if (link_stat(cmpbuf, &sxp->st, 0) < 0 || !S_ISREG(sxp->st.st_mode)) continue; switch (match_level) { case 0: @@ -622,16 +633,20 @@ match_level = 1; /* FALL THROUGH */ case 1: - if (!unchanged_file(cmpbuf, file, stp)) + if (!unchanged_file(cmpbuf, file, &sxp->st)) continue; best_match = j; match_level = 2; /* FALL THROUGH */ case 2: - if (!unchanged_attrs(file, stp)) +#ifdef SUPPORT_ACLS + if (preserve_acls) + get_acl(cmpbuf, sxp); +#endif + if (!unchanged_attrs(file, sxp)) continue; if (always_checksum && preserve_times - && cmp_time(stp->st_mtime, file->modtime)) + && cmp_time(sxp->st.st_mtime, file->modtime)) continue; best_match = j; match_level = 3; @@ -646,14 +661,14 @@ if (j != best_match) { j = best_match; pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname); - if (link_stat(cmpbuf, stp, 0) < 0) + if (link_stat(cmpbuf, &sxp->st, 0) < 0) return -1; } if (match_level == 3 && !copy_dest) { #ifdef SUPPORT_HARD_LINKS if (link_dest) { - if (hard_link_one(file, ndx, fname, 0, stp, + if (hard_link_one(file, ndx, fname, 0, sxp, cmpbuf, 1, itemizing && verbose > 1, code) < 0) @@ -665,8 +680,13 @@ } } else #endif - if (itemizing) - itemize(file, ndx, 0, stp, 0, 0, NULL); + if (itemizing) { +#ifdef SUPPORT_ACLS + if (preserve_acls && !ACL_READY(*sxp)) + get_acl(fname, sxp); +#endif + itemize(file, ndx, 0, sxp, 0, 0, NULL); + } if (verbose > 1 && maybe_ATTRS_REPORT) { rprintf(FCLIENT, "%s is uptodate\n", fname); } @@ -682,8 +702,13 @@ } return -1; } - if (itemizing) - itemize(file, ndx, 0, stp, ITEM_LOCAL_CHANGE, 0, NULL); + if (itemizing) { +#ifdef SUPPORT_ACLS + if (preserve_acls && !ACL_READY(*sxp)) + get_acl(fname, sxp); +#endif + itemize(file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL); + } set_file_attrs(fname, file, NULL, 0); if (maybe_ATTRS_REPORT && ((!itemizing && verbose && match_level == 2) @@ -707,13 +732,18 @@ enum logcode code) { char fnamebuf[MAXPATHLEN]; - STRUCT_STAT st; + statx sx; int i = 0; do { pathjoin(fnamebuf, MAXPATHLEN, basis_dir[i], fname); - if (link_stat(fnamebuf, &st, 0) < 0 || S_ISDIR(st.st_mode) - || !unchanged_attrs(file, &st)) + if (link_stat(fnamebuf, &sx.st, 0) < 0 || S_ISDIR(sx.st.st_mode)) + continue; +#ifdef SUPPORT_ACLS + if (preserve_acls) + get_acl(fnamebuf, &sx); +#endif + if (!unchanged_attrs(file, &sx)) continue; if (S_ISLNK(file->mode)) { #ifdef SUPPORT_LINKS @@ -726,10 +756,10 @@ #endif continue; } else if (IS_SPECIAL(file->mode)) { - if (!IS_SPECIAL(st.st_mode) || st.st_rdev != file->u.rdev) + if (!IS_SPECIAL(sx.st.st_mode) || sx.st.st_rdev != file->u.rdev) continue; } else if (IS_DEVICE(file->mode)) { - if (!IS_DEVICE(st.st_mode) || st.st_rdev != file->u.rdev) + if (!IS_DEVICE(sx.st.st_mode) || sx.st.st_rdev != file->u.rdev) continue; } else { rprintf(FERROR, @@ -760,7 +790,15 @@ int changes = compare_dest ? 0 : ITEM_LOCAL_CHANGE + (link_dest ? ITEM_XNAME_FOLLOWS : 0); char *lp = link_dest ? "" : NULL; - itemize(file, ndx, 0, &st, changes, 0, lp); +#ifdef SUPPORT_ACLS + if (preserve_acls) + get_acl(fname, &sx); +#endif + itemize(file, ndx, 0, &sx, changes, 0, lp); +#ifdef SUPPORT_ACLS + if (preserve_acls) + free_acl(&sx); +#endif } if (verbose > 1 && maybe_ATTRS_REPORT) { rprintf(FCLIENT, "%s is uptodate\n", fname); @@ -772,6 +810,7 @@ } static int phase = 0; +static int dflt_perms; /* 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 @@ -793,7 +832,8 @@ static int need_fuzzy_dirlist = 0; struct file_struct *fuzzy_file = NULL; int fd = -1, f_copy = -1; - STRUCT_STAT st, real_st, partial_st; + statx sx, real_sx; + STRUCT_STAT partial_st; struct file_struct *back_file = NULL; int statret, real_ret, stat_errno; char *fnamecmp, *partialptr, *backupptr = NULL; @@ -849,6 +889,9 @@ } else if (!dry_run) return; } +#ifdef SUPPORT_ACLS + sx.acc_acl = sx.def_acl = NULL; +#endif if (dry_run > 1) { statret = -1; stat_errno = ENOENT; @@ -856,7 +899,7 @@ char *dn = file->dirname ? file->dirname : "."; if (parent_dirname != dn && strcmp(parent_dirname, dn) != 0) { if (relative_paths && !implied_dirs - && do_stat(dn, &st) < 0 + && do_stat(dn, &sx.st) < 0 && create_directory_path(fname) < 0) { rsyserr(FERROR, errno, "recv_generator: mkdir %s failed", @@ -868,6 +911,10 @@ } if (fuzzy_basis) need_fuzzy_dirlist = 1; +#ifdef SUPPORT_ACLS + if (!preserve_perms) + dflt_perms = default_perms_for_dir(dn); +#endif } parent_dirname = dn; @@ -876,7 +923,7 @@ need_fuzzy_dirlist = 0; } - statret = link_stat(fname, &st, + statret = link_stat(fname, &sx.st, keep_dirlinks && S_ISDIR(file->mode)); stat_errno = errno; } @@ -894,8 +941,9 @@ * mode based on the local permissions and some heuristics. */ if (!preserve_perms) { int exists = statret == 0 - && S_ISDIR(st.st_mode) == S_ISDIR(file->mode); - file->mode = dest_mode(file->mode, st.st_mode, exists); + && S_ISDIR(sx.st.st_mode) == S_ISDIR(file->mode); + file->mode = dest_mode(file->mode, sx.st.st_mode, dflt_perms, + exists); } if (S_ISDIR(file->mode)) { @@ -904,8 +952,8 @@ * file of that name and it is *not* a directory, then * we need to delete it. If it doesn't exist, then * (perhaps recursively) create it. */ - if (statret == 0 && !S_ISDIR(st.st_mode)) { - if (delete_item(fname, st.st_mode, del_opts) < 0) + if (statret == 0 && !S_ISDIR(sx.st.st_mode)) { + if (delete_item(fname, sx.st.st_mode, del_opts) < 0) return; statret = -1; } @@ -920,7 +968,11 @@ sr = -1; new_root_dir = 0; } - itemize(file, ndx, sr, &st, +#ifdef SUPPORT_ACLS + if (preserve_acls && sr == 0) + get_acl(fname, &sx); +#endif + itemize(file, ndx, sr, &sx, sr ? ITEM_LOCAL_CHANGE : 0, 0, NULL); } if (statret != 0 && do_mkdir(fname,file->mode) < 0 && errno != EEXIST) { @@ -940,19 +992,19 @@ return; } } - if (set_file_attrs(fname, file, statret ? NULL : &st, 0) + if (set_file_attrs(fname, file, statret ? NULL : &sx, 0) && verbose && code != FNONE && f_out != -1) rprintf(code, "%s/\n", fname); if (delete_during && f_out != -1 && !phase && dry_run < 2 && (file->flags & FLAG_DEL_HERE)) - delete_in_dir(the_file_list, fname, file, &st); - return; + delete_in_dir(the_file_list, fname, file, &sx.st); + goto cleanup; } if (preserve_hard_links && file->link_u.links - && hard_link_check(file, ndx, fname, statret, &st, + && hard_link_check(file, ndx, fname, statret, &sx, itemizing, code, HL_CHECK_MASTER)) - return; + goto cleanup; if (preserve_links && S_ISLNK(file->mode)) { #ifdef SUPPORT_LINKS @@ -970,7 +1022,7 @@ char lnk[MAXPATHLEN]; int len; - if (!S_ISDIR(st.st_mode) + if (!S_ISDIR(sx.st.st_mode) && (len = readlink(fname, lnk, MAXPATHLEN-1)) > 0) { lnk[len] = 0; /* A link already pointing to the @@ -978,10 +1030,10 @@ * required. */ if (strcmp(lnk, file->u.link) == 0) { if (itemizing) { - itemize(file, ndx, 0, &st, 0, + itemize(file, ndx, 0, &sx, 0, 0, NULL); } - set_file_attrs(fname, file, &st, + set_file_attrs(fname, file, &sx, maybe_ATTRS_REPORT); if (preserve_hard_links && file->link_u.links) { @@ -996,9 +1048,9 @@ } /* Not the right symlink (or not a symlink), so * delete it. */ - if (delete_item(fname, st.st_mode, del_opts) < 0) + if (delete_item(fname, sx.st.st_mode, del_opts) < 0) return; - if (!S_ISLNK(st.st_mode)) + if (!S_ISLNK(sx.st.st_mode)) statret = -1; } else if (basis_dir[0] != NULL) { if (try_dests_non(file, fname, ndx, itemizing, @@ -1015,7 +1067,7 @@ } } if (preserve_hard_links && file->link_u.links - && hard_link_check(file, ndx, fname, -1, &st, + && hard_link_check(file, ndx, fname, -1, &sx, itemizing, code, HL_SKIP)) return; if (do_symlink(file->u.link,fname) != 0) { @@ -1024,7 +1076,7 @@ } else { set_file_attrs(fname, file, NULL, 0); if (itemizing) { - itemize(file, ndx, statret, &st, + itemize(file, ndx, statret, &sx, ITEM_LOCAL_CHANGE, 0, NULL); } if (code != FNONE && verbose) { @@ -1059,18 +1111,22 @@ code = FNONE; } } +#ifdef SUPPORT_ACLS + if (preserve_acls && statret == 0) + get_acl(fname, &sx); +#endif if (statret != 0 - || (st.st_mode & ~CHMOD_BITS) != (file->mode & ~CHMOD_BITS) - || st.st_rdev != file->u.rdev) { + || (sx.st.st_mode & ~CHMOD_BITS) != (file->mode & ~CHMOD_BITS) + || sx.st.st_rdev != file->u.rdev) { if (statret == 0 - && delete_item(fname, st.st_mode, del_opts) < 0) - return; + && delete_item(fname, sx.st.st_mode, del_opts) < 0) + goto cleanup; if (preserve_hard_links && file->link_u.links - && hard_link_check(file, ndx, fname, -1, &st, + && hard_link_check(file, ndx, fname, -1, &sx, itemizing, code, HL_SKIP)) - return; - if ((IS_DEVICE(file->mode) && !IS_DEVICE(st.st_mode)) - || (IS_SPECIAL(file->mode) && !IS_SPECIAL(st.st_mode))) + goto cleanup; + if ((IS_DEVICE(file->mode) && !IS_DEVICE(sx.st.st_mode)) + || (IS_SPECIAL(file->mode) && !IS_SPECIAL(sx.st.st_mode))) statret = -1; if (verbose > 2) { rprintf(FINFO,"mknod(%s,0%o,0x%x)\n", @@ -1083,7 +1139,7 @@ } else { set_file_attrs(fname, file, NULL, 0); if (itemizing) { - itemize(file, ndx, statret, &st, + itemize(file, ndx, statret, &sx, ITEM_LOCAL_CHANGE, 0, NULL); } if (code != FNONE && verbose) @@ -1097,14 +1153,14 @@ } } else { if (itemizing) - itemize(file, ndx, statret, &st, 0, 0, NULL); - set_file_attrs(fname, file, &st, maybe_ATTRS_REPORT); + itemize(file, ndx, statret, &sx, 0, 0, NULL); + set_file_attrs(fname, file, &sx, maybe_ATTRS_REPORT); if (preserve_hard_links && file->link_u.links) hard_link_cluster(file, ndx, itemizing, code); if (remove_source_files == 1) goto return_with_success; } - return; + goto cleanup; } if (!S_ISREG(file->mode)) { @@ -1138,7 +1194,7 @@ } if (update_only && statret == 0 - && cmp_time(st.st_mtime, file->modtime) > 0) { + && cmp_time(sx.st.st_mtime, file->modtime) > 0) { if (verbose > 1) rprintf(FINFO, "%s is newer\n", fname); return; @@ -1147,20 +1203,20 @@ fnamecmp = fname; fnamecmp_type = FNAMECMP_FNAME; - if (statret == 0 && !S_ISREG(st.st_mode)) { - if (delete_item(fname, st.st_mode, del_opts) != 0) + if (statret == 0 && !S_ISREG(sx.st.st_mode)) { + if (delete_item(fname, sx.st.st_mode, del_opts) != 0) return; statret = -1; stat_errno = ENOENT; } if (statret != 0 && basis_dir[0] != NULL) { - int j = try_dests_reg(file, fname, ndx, fnamecmpbuf, &st, + int j = try_dests_reg(file, fname, ndx, fnamecmpbuf, &sx, itemizing, maybe_ATTRS_REPORT, code); if (j == -2) { if (remove_source_files == 1) goto return_with_success; - return; + goto cleanup; } if (j >= 0) { fnamecmp = fnamecmpbuf; @@ -1170,7 +1226,7 @@ } real_ret = statret; - real_st = st; + real_sx = sx; if (partial_dir && (partialptr = partial_dir_fname(fname)) != NULL && link_stat(partialptr, &partial_st, 0) == 0 @@ -1189,7 +1245,7 @@ rprintf(FINFO, "fuzzy basis selected for %s: %s\n", fname, fnamecmpbuf); } - st.st_size = fuzzy_file->length; + sx.st.st_size = fuzzy_file->length; statret = 0; fnamecmp = fnamecmpbuf; fnamecmp_type = FNAMECMP_FUZZY; @@ -1198,7 +1254,7 @@ if (statret != 0) { if (preserve_hard_links && file->link_u.links - && hard_link_check(file, ndx, fname, statret, &st, + && hard_link_check(file, ndx, fname, statret, &sx, itemizing, code, HL_SKIP)) return; if (stat_errno == ENOENT) @@ -1208,39 +1264,52 @@ return; } - if (append_mode && st.st_size > file->length) + if (append_mode && sx.st.st_size > file->length) return; if (fnamecmp_type <= FNAMECMP_BASIS_DIR_HIGH) ; else if (fnamecmp_type == FNAMECMP_FUZZY) ; - else if (unchanged_file(fnamecmp, file, &st)) { + else if (unchanged_file(fnamecmp, file, &sx.st)) { if (partialptr) { do_unlink(partialptr); handle_partial_dir(partialptr, PDIR_DELETE); } if (itemizing) { - itemize(file, ndx, real_ret, &real_st, +#ifdef SUPPORT_ACLS + if (preserve_acls && real_ret == 0) + get_acl(fnamecmp, &real_sx); +#endif + itemize(file, ndx, real_ret, &real_sx, 0, 0, NULL); +#ifdef SUPPORT_ACLS + if (preserve_acls) { + if (fnamecmp_type == FNAMECMP_FNAME) { + sx.acc_acl = real_sx.acc_acl; + sx.def_acl = real_sx.def_acl; + } else + free_acl(&real_sx); + } +#endif } - set_file_attrs(fname, file, &st, maybe_ATTRS_REPORT); + set_file_attrs(fname, file, &sx, maybe_ATTRS_REPORT); if (preserve_hard_links && file->link_u.links) hard_link_cluster(file, ndx, itemizing, code); if (remove_source_files != 1) - return; + goto cleanup; return_with_success: if (!dry_run) { char numbuf[4]; SIVAL(numbuf, 0, ndx); send_msg(MSG_SUCCESS, numbuf, 4); } - return; + goto cleanup; } prepare_to_open: if (partialptr) { - st = partial_st; + sx.st = partial_st; fnamecmp = partialptr; fnamecmp_type = FNAMECMP_PARTIAL_DIR; statret = 0; @@ -1264,17 +1333,21 @@ pretend_missing: /* pretend the file didn't exist */ if (preserve_hard_links && file->link_u.links - && hard_link_check(file, ndx, fname, statret, &st, + && hard_link_check(file, ndx, fname, statret, &sx, itemizing, code, HL_SKIP)) - return; + goto cleanup; statret = real_ret = -1; +#ifdef SUPPORT_ACLS + if (preserve_acls && ACL_READY(sx)) + free_acl(&sx); +#endif goto notify_others; } if (inplace && make_backups && fnamecmp_type == FNAMECMP_FNAME) { if (!(backupptr = get_backup_name(fname))) { close(fd); - return; + goto cleanup; } if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) { close(fd); @@ -1285,7 +1358,7 @@ full_fname(backupptr)); free(back_file); close(fd); - return; + goto cleanup; } if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) { @@ -1293,14 +1366,14 @@ full_fname(backupptr)); free(back_file); close(fd); - return; + goto cleanup; } fnamecmp_type = FNAMECMP_BACKUP; } if (verbose > 3) { rprintf(FINFO, "gen mapped %s of size %.0f\n", - fnamecmp, (double)st.st_size); + fnamecmp, (double)sx.st.st_size); } if (verbose > 2) @@ -1318,24 +1391,32 @@ iflags |= ITEM_BASIS_TYPE_FOLLOWS; if (fnamecmp_type == FNAMECMP_FUZZY) iflags |= ITEM_XNAME_FOLLOWS; - itemize(file, -1, real_ret, &real_st, iflags, fnamecmp_type, +#ifdef SUPPORT_ACLS + if (preserve_acls && real_ret == 0) + get_acl(fnamecmp, &real_sx); +#endif + itemize(file, -1, real_ret, &real_sx, iflags, fnamecmp_type, fuzzy_file ? fuzzy_file->basename : NULL); +#ifdef SUPPORT_ACLS + if (preserve_acls) + free_acl(&real_sx); +#endif } if (!do_xfers) { if (preserve_hard_links && file->link_u.links) hard_link_cluster(file, ndx, itemizing, code); - return; + goto cleanup; } if (read_batch) - return; + goto cleanup; if (statret != 0 || whole_file) { write_sum_head(f_out, NULL); - return; + goto cleanup; } - generate_and_send_sums(fd, st.st_size, f_out, f_copy); + generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy); if (f_copy >= 0) { close(f_copy); @@ -1348,6 +1429,13 @@ } close(fd); + + cleanup: +#ifdef SUPPORT_ACLS + if (preserve_acls) + free_acl(&sx); +#endif + return; } void generate_files(int f_out, struct file_list *flist, char *local_name) @@ -1407,6 +1495,8 @@ * notice that and let us know via the redo pipe (or its closing). */ ignore_timeout = 1; + dflt_perms = (ACCESSPERMS & ~orig_umask); + for (i = 0; i < flist->count; i++) { struct file_struct *file = flist->files[i]; diff -u rsync-2.6.9/hlink.c rsync-acl-2.6.9/hlink.c --- rsync-2.6.9/hlink.c 2006-10-17 14:49:04.000000000 -0400 +++ rsync-acl-2.6.9/hlink.c 2006-11-08 00:02:03.000000000 -0500 @@ -26,6 +26,7 @@ extern int verbose; extern int do_xfers; extern int link_dest; +extern int preserve_acls; extern int make_backups; extern int remove_source_files; extern int stdout_format_has_i; @@ -147,15 +148,19 @@ #ifdef SUPPORT_HARD_LINKS static int maybe_hard_link(struct file_struct *file, int ndx, - char *fname, int statret, STRUCT_STAT *st, + char *fname, int statret, statx *sxp, char *toname, STRUCT_STAT *to_st, int itemizing, enum logcode code) { if (statret == 0) { - if (st->st_dev == to_st->st_dev - && st->st_ino == to_st->st_ino) { + if (sxp->st.st_dev == to_st->st_dev + && sxp->st.st_ino == to_st->st_ino) { if (itemizing) { - itemize(file, ndx, statret, st, +#ifdef SUPPORT_ACLS + if (preserve_acls && !ACL_READY(*sxp)) + get_acl(fname, sxp); +#endif + itemize(file, ndx, statret, sxp, ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0, ""); } @@ -170,13 +175,13 @@ return -1; } } - return hard_link_one(file, ndx, fname, statret, st, toname, + return hard_link_one(file, ndx, fname, statret, sxp, toname, 0, itemizing, code); } #endif int hard_link_check(struct file_struct *file, int ndx, char *fname, - int statret, STRUCT_STAT *st, int itemizing, + int statret, statx *sxp, int itemizing, enum logcode code, int skip) { #ifdef SUPPORT_HARD_LINKS @@ -217,7 +222,7 @@ || st2.st_ino != st3.st_ino) continue; statret = 1; - st = &st3; + sxp->st = st3; if (verbose < 2 || !stdout_format_has_i) { itemizing = 0; code = FNONE; @@ -227,12 +232,16 @@ if (!unchanged_file(cmpbuf, file, &st3)) continue; statret = 1; - st = &st3; - if (unchanged_attrs(file, &st3)) + sxp->st = st3; +#ifdef SUPPORT_ACLS + if (preserve_acls) + get_acl(cmpbuf, sxp); +#endif + if (unchanged_attrs(file, sxp)) break; } while (basis_dir[++j] != NULL); } - maybe_hard_link(file, ndx, fname, statret, st, + maybe_hard_link(file, ndx, fname, statret, sxp, toname, &st2, itemizing, code); if (remove_source_files == 1 && do_xfers) { char numbuf[4]; @@ -250,7 +259,7 @@ #ifdef SUPPORT_HARD_LINKS int hard_link_one(struct file_struct *file, int ndx, char *fname, - int statret, STRUCT_STAT *st, char *toname, int terse, + int statret, statx *sxp, char *toname, int terse, int itemizing, enum logcode code) { if (do_link(toname, fname)) { @@ -266,7 +275,11 @@ } if (itemizing) { - itemize(file, ndx, statret, st, +#ifdef SUPPORT_ACLS + if (preserve_acls && statret == 0 && !ACL_READY(*sxp)) + get_acl(fname, sxp); +#endif + itemize(file, ndx, statret, sxp, ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0, terse ? "" : toname); } @@ -283,11 +296,12 @@ #ifdef SUPPORT_HARD_LINKS char hlink1[MAXPATHLEN]; char *hlink2; - STRUCT_STAT st1, st2; + statx sx; + STRUCT_STAT st; int statret, ndx = master; file->F_HLINDEX = FINISHED_LINK; - if (link_stat(f_name(file, hlink1), &st1, 0) < 0) + if (link_stat(f_name(file, hlink1), &st, 0) < 0) return; if (!(file->flags & FLAG_HLINK_TOL)) { while (!(file->flags & FLAG_HLINK_EOL)) { @@ -301,9 +315,13 @@ if (file->F_HLINDEX != SKIPPED_LINK) continue; hlink2 = f_name(file, NULL); - statret = link_stat(hlink2, &st2, 0); - maybe_hard_link(file, ndx, hlink2, statret, &st2, - hlink1, &st1, itemizing, code); + statret = link_stat(hlink2, &sx.st, 0); + maybe_hard_link(file, ndx, hlink2, statret, &sx, + hlink1, &st, itemizing, code); +#ifdef SUPPORT_ACLS + if (preserve_acls) + free_acl(&sx); +#endif if (remove_source_files == 1 && do_xfers) { char numbuf[4]; SIVAL(numbuf, 0, ndx); Common subdirectories: rsync-2.6.9/lib and rsync-acl-2.6.9/lib diff -u rsync-2.6.9/log.c rsync-acl-2.6.9/log.c --- rsync-2.6.9/log.c 2006-10-14 14:51:21.000000000 -0400 +++ rsync-acl-2.6.9/log.c 2006-11-08 00:02:03.000000000 -0500 @@ -606,8 +606,10 @@ n[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p'; n[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o'; n[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g'; - n[8] = '.'; - n[9] = '\0'; + n[8] = !(iflags & ITEM_REPORT_ATIME) ? '.' : 'u'; + n[9] = !(iflags & ITEM_REPORT_ACL) ? '.' : 'a'; + n[10] = !(iflags & ITEM_REPORT_XATTR) ? '.' : 'x'; + n[11] = '\0'; if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) { char ch = iflags & ITEM_IS_NEW ? '+' : '?'; diff -u rsync-2.6.9/options.c rsync-acl-2.6.9/options.c --- rsync-2.6.9/options.c 2006-10-23 20:36:38.000000000 -0400 +++ rsync-acl-2.6.9/options.c 2006-11-08 00:02:03.000000000 -0500 @@ -47,6 +47,7 @@ int copy_links = 0; int preserve_links = 0; int preserve_hard_links = 0; +int preserve_acls = 0; int preserve_perms = 0; int preserve_executability = 0; int preserve_devices = 0; @@ -199,6 +200,7 @@ char const *got_socketpair = "no "; char const *have_inplace = "no "; char const *hardlinks = "no "; + char const *acls = "no "; char const *links = "no "; char const *ipv6 = "no "; STRUCT_STAT *dumstat; @@ -215,6 +217,10 @@ hardlinks = ""; #endif +#ifdef SUPPORT_ACLS + acls = ""; +#endif + #ifdef SUPPORT_LINKS links = ""; #endif @@ -227,17 +233,16 @@ RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION); rprintf(f, "Copyright (C) 1996-2006 by Andrew Tridgell, Wayne Davison, and others.\n"); rprintf(f, "\n"); - rprintf(f, "Capabilities: %d-bit files, %ssocketpairs, " - "%shard links, %ssymlinks, batchfiles,\n", - (int) (sizeof (OFF_T) * 8), - got_socketpair, hardlinks, links); + rprintf(f, "Capabilities: %d-bit files, %ssocketpairs, %shard links, %ssymlinks,\n", + (int) (sizeof (OFF_T) * 8), got_socketpair, hardlinks, links); + + rprintf(f, " batchfiles, %sinplace, %sIPv6, %sACLs,\n", + have_inplace, ipv6, acls); /* 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", - have_inplace, ipv6, + rprintf(f, " %d-bit system inums, %d-bit internal inums\n", (int) (sizeof dumstat->st_ino * 8), (int) (sizeof (int64) * 8)); #ifdef MAINTAINER_MODE @@ -284,7 +289,7 @@ rprintf(F," -q, --quiet suppress non-error messages\n"); rprintf(F," --no-motd suppress daemon-mode MOTD (see manpage caveat)\n"); rprintf(F," -c, --checksum skip based on checksum, not mod-time & size\n"); - rprintf(F," -a, --archive archive mode; same as -rlptgoD (no -H)\n"); + rprintf(F," -a, --archive archive mode; same as -rlptgoD (no -H, -A)\n"); rprintf(F," --no-OPTION turn off an implied OPTION (e.g. --no-D)\n"); rprintf(F," -r, --recursive recurse into directories\n"); rprintf(F," -R, --relative use relative path names\n"); @@ -306,6 +311,9 @@ rprintf(F," -p, --perms preserve permissions\n"); rprintf(F," -E, --executability preserve the file's executability\n"); rprintf(F," --chmod=CHMOD affect file and/or directory permissions\n"); +#ifdef SUPPORT_ACLS + rprintf(F," -A, --acls preserve ACLs (implies --perms)\n"); +#endif rprintf(F," -o, --owner preserve owner (super-user only)\n"); rprintf(F," -g, --group preserve group\n"); rprintf(F," --devices preserve device files (super-user only)\n"); @@ -425,6 +433,9 @@ {"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 }, + {"acls", 'A', POPT_ARG_NONE, 0, 'A', 0, 0 }, + {"no-acls", 0, POPT_ARG_VAL, &preserve_acls, 0, 0, 0 }, + {"no-A", 0, POPT_ARG_VAL, &preserve_acls, 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 }, @@ -1089,6 +1100,24 @@ usage(FINFO); exit_cleanup(0); + case 'A': +#ifdef SUPPORT_ACLS + preserve_acls++; + preserve_perms = 1; + break; +#else + /* FIXME: this should probably be ignored with a + * warning and then countermeasures taken to + * restrict group and other access in the presence + * of any more restrictive ACLs, but this is safe + * for now */ + snprintf(err_buf,sizeof(err_buf), + "ACLs are not supported on this %s\n", + am_server ? "server" : "client"); + return 0; +#endif + + default: /* A large opt value means that set_refuse_options() * turned this option off. */ @@ -1530,6 +1559,10 @@ if (preserve_hard_links) argstr[x++] = 'H'; +#ifdef SUPPORT_ACLS + if (preserve_acls) + argstr[x++] = 'A'; +#endif if (preserve_uid) argstr[x++] = 'o'; if (preserve_gid) Common subdirectories: rsync-2.6.9/packaging and rsync-acl-2.6.9/packaging Common subdirectories: rsync-2.6.9/patches and rsync-acl-2.6.9/patches Common subdirectories: rsync-2.6.9/popt and rsync-acl-2.6.9/popt diff -u rsync-2.6.9/proto.h rsync-acl-2.6.9/proto.h --- rsync-2.6.9/proto.h 2006-11-06 23:39:47.000000000 -0500 +++ rsync-acl-2.6.9/proto.h 2006-11-08 00:02:04.000000000 -0500 @@ -1,6 +1,15 @@ /* This file is automatically generated with "make proto". DO NOT EDIT */ int allow_access(char *addr, char *host, char *allow_list, char *deny_list); +void free_acl(statx *sxp); +int get_acl(const char *fname, statx *sxp); +void send_acl(statx *sxp, int f); +void receive_acl(struct file_struct *file, int f); +void cache_acl(struct file_struct *file, statx *sxp); +int set_acl(const char *fname, const struct file_struct *file, statx *sxp); +id_t *next_acl_uid(); +id_t *next_acl_gid(); +int default_perms_for_dir(const char *dir); void base64_encode(char *buf, int len, char *out, int pad); char *auth_server(int f_in, int f_out, int module, char *host, char *addr, char *leader); @@ -83,18 +92,18 @@ char *f_name(struct file_struct *f, char *fbuf); struct file_list *get_dirlist(char *dirname, int dlen, int ignore_filter_rules); -int unchanged_attrs(struct file_struct *file, STRUCT_STAT *st); -void itemize(struct file_struct *file, int ndx, int statret, STRUCT_STAT *st, +int unchanged_attrs(struct file_struct *file, statx *sxp); +void itemize(struct file_struct *file, int ndx, int statret, statx *sxp, int32 iflags, uchar fnamecmp_type, char *xname); int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st); void check_for_finished_hlinks(int itemizing, enum logcode code); void generate_files(int f_out, struct file_list *flist, char *local_name); void init_hard_links(void); int hard_link_check(struct file_struct *file, int ndx, char *fname, - int statret, STRUCT_STAT *st, int itemizing, + int statret, statx *sxp, int itemizing, enum logcode code, int skip); int hard_link_one(struct file_struct *file, int ndx, char *fname, - int statret, STRUCT_STAT *st, char *toname, int terse, + int statret, statx *sxp, char *toname, int terse, int itemizing, enum logcode code); void hard_link_cluster(struct file_struct *file, int master, int itemizing, enum logcode code); @@ -223,8 +232,9 @@ int recv_files(int f_in, struct file_list *flist, char *local_name); void setup_iconv(); void free_sums(struct sum_struct *s); -mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int exists); -int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st, +mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms, + int exists); +int set_file_attrs(char *fname, struct file_struct *file, statx *sxp, int flags); RETSIGTYPE sig_int(UNUSED(int val)); void finish_transfer(char *fname, char *fnametmp, char *partialptr, @@ -320,4 +330,6 @@ void bitbag_clear_bit(struct bitbag *bb, int ndx); int bitbag_check_bit(struct bitbag *bb, int ndx); int bitbag_next_bit(struct bitbag *bb, int after); +void *expand_item_list(item_list *lp, size_t item_size, + const char *desc, int incr); int sys_gettimeofday(struct timeval *tv); diff -u rsync-2.6.9/receiver.c rsync-acl-2.6.9/receiver.c --- rsync-2.6.9/receiver.c 2006-10-13 03:18:29.000000000 -0400 +++ rsync-acl-2.6.9/receiver.c 2006-11-08 00:02:03.000000000 -0500 @@ -47,6 +47,7 @@ extern int checksum_seed; extern int inplace; extern int delay_updates; +extern mode_t orig_umask; extern struct stats stats; extern char *stdout_format; extern char *tmpdir; @@ -350,6 +351,10 @@ int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i; enum logcode log_code = log_before_transfer ? FLOG : FINFO; int max_phase = protocol_version >= 29 ? 2 : 1; + int dflt_perms = (ACCESSPERMS & ~orig_umask); +#ifdef SUPPORT_ACLS + char *parent_dirname = ""; +#endif int i, recv_ok; if (verbose > 2) @@ -553,7 +558,16 @@ * mode based on the local permissions and some heuristics. */ if (!preserve_perms) { int exists = fd1 != -1; - file->mode = dest_mode(file->mode, st.st_mode, exists); +#ifdef SUPPORT_ACLS + char *dn = file->dirname ? file->dirname : "."; + if (parent_dirname != dn + && strcmp(parent_dirname, dn) != 0) { + dflt_perms = default_perms_for_dir(dn); + parent_dirname = dn; + } +#endif + file->mode = dest_mode(file->mode, st.st_mode, + dflt_perms, exists); } /* We now check to see if we are writing the file "inplace" */ diff -u rsync-2.6.9/rsync.1 rsync-acl-2.6.9/rsync.1 --- rsync-2.6.9/rsync.1 2006-11-06 23:39:51.000000000 -0500 +++ rsync-acl-2.6.9/rsync.1 2006-11-08 00:02:04.000000000 -0500 @@ -367,7 +367,7 @@ \-q, \-\-quiet suppress non-error messages \-\-no\-motd suppress daemon-mode MOTD (see caveat) \-c, \-\-checksum skip based on checksum, not mod-time & size - \-a, \-\-archive archive mode; same as \-rlptgoD (no \-H) + \-a, \-\-archive archive mode; same as \-rlptgoD (no \-H, \-A) \-\-no\-OPTION turn off an implied OPTION (e\&.g\&. \-\-no\-D) \-r, \-\-recursive recurse into directories \-R, \-\-relative use relative path names @@ -389,6 +389,7 @@ \-p, \-\-perms preserve permissions \-E, \-\-executability preserve executability \-\-chmod=CHMOD affect file and/or directory permissions + \-A, \-\-acls preserve ACLs (implies \-p) [non-standard] \-o, \-\-owner preserve owner (super-user only) \-g, \-\-group preserve group \-\-devices preserve device files (super-user only) @@ -870,7 +871,9 @@ the execute permission for the file\&. .IP o New files get their "normal" permission bits set to the source -file\&'s permissions masked with the receiving end\&'s umask setting, and +file\&'s permissions masked with the receiving directory\&'s default +permissions (either the receiving process\&'s umask, or the permissions +specified via the destination directory\&'s default ACL), and their special permission bits disabled except in the case where a new directory inherits a setgid bit from its parent directory\&. .RE @@ -908,9 +911,11 @@ directories when \fB\-\-perms\fP is off was added in rsync 2\&.6\&.7\&. Older rsync versions erroneously preserved the three special permission bits for newly-created files when \fB\-\-perms\fP was off, while overriding the -destination\&'s setgid bit setting on a newly-created directory\&. (Keep in -mind that it is the version of the receiving rsync that affects this -behavior\&.) +destination\&'s setgid bit setting on a newly-created directory\&. Default ACL +observance was added to the ACL patch for rsync 2\&.6\&.7, so older (or +non-ACL-enabled) rsyncs use the umask even if default ACLs are present\&. +(Keep in mind that it is the version of the receiving rsync that affects +these behaviors\&.) .IP .IP "\fB\-E, \-\-executability\fP" This option causes rsync to preserve the @@ -932,6 +937,16 @@ .IP If \fB\-\-perms\fP is enabled, this option is ignored\&. .IP +.IP "\fB\-A, \-\-acls\fP" +This option causes rsync to update the destination +ACLs to be the same as the source ACLs\&. This nonstandard option only +works if the remote rsync also supports it\&. \fB\-\-acls\fP implies \fB\-\-perms\fP\&. +.IP +Note also that an optimization of the ACL-sending protocol used by this +version makes it incompatible with sending files to an older ACL-enabled +rsync unless you double the \fB\-\-acls\fP option (e\&.g\&. \fB\-AA\fP)\&. This +doubling is not needed when pulling files from an older rsync\&. +.IP .IP "\fB\-\-chmod\fP" This option tells rsync to apply one or more comma-separated "chmod" strings to the permission of the files in the @@ -1605,8 +1620,8 @@ with older versions of rsync, but that also turns on the output of other verbose messages)\&. .IP -The "%i" escape has a cryptic output that is 9 letters long\&. The general -format is like the string \fBYXcstpogz\fP, where \fBY\fP is replaced by the +The "%i" escape has a cryptic output that is 11 letters long\&. The general +format is like the string \fBYXcstpoguax\fP, where \fBY\fP is replaced by the type of update being done, \fBX\fP is replaced by the file-type, and the other letters represent attributes that may be output if they are being modified\&. @@ -1668,7 +1683,13 @@ A \fBg\fP means the group is different and is being updated to the sender\&'s value (requires \fB\-\-group\fP and the authority to set the group)\&. .IP o -The \fBz\fP slot is reserved for future use\&. +The \fBu\fP slot is reserved for reporting update (access) time changes +(a feature that is not yet released)\&. +.IP o +The \fBa\fP means that the ACL information changed\&. +.IP o +The \fBx\fP slot is reserved for reporting extended attribute changes +(a feature that is not yet released)\&. .RE .IP diff -u rsync-2.6.9/rsync.c rsync-acl-2.6.9/rsync.c --- rsync-2.6.9/rsync.c 2006-10-08 18:02:13.000000000 -0400 +++ rsync-acl-2.6.9/rsync.c 2006-11-08 00:02:03.000000000 -0500 @@ -32,6 +32,7 @@ extern int verbose; extern int dry_run; +extern int preserve_acls; extern int preserve_perms; extern int preserve_executability; extern int preserve_times; @@ -47,7 +48,6 @@ extern int inplace; extern int keep_dirlinks; extern int make_backups; -extern mode_t orig_umask; extern struct stats stats; extern struct chmod_mode_struct *daemon_chmod_modes; @@ -100,7 +100,8 @@ /* 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 stat_mode, int exists) +mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms, + int exists) { int new_mode; /* If the file already exists, we'll return the local permissions, @@ -117,56 +118,65 @@ new_mode |= (new_mode & 0444) >> 2; } } else { - /* Apply the umask and turn off special permissions. */ - new_mode = flist_mode & (~CHMOD_BITS | (ACCESSPERMS & ~orig_umask)); + /* Apply destination default permissions and turn + * off special permissions. */ + new_mode = flist_mode & (~CHMOD_BITS | dflt_perms); } return new_mode; } -int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st, +int set_file_attrs(char *fname, struct file_struct *file, statx *sxp, int flags) { int updated = 0; - STRUCT_STAT st2; + statx sx2; int change_uid, change_gid; mode_t new_mode = file->mode; - if (!st) { + if (!sxp) { if (dry_run) return 1; - if (link_stat(fname, &st2, 0) < 0) { + if (link_stat(fname, &sx2.st, 0) < 0) { rsyserr(FERROR, errno, "stat %s failed", full_fname(fname)); return 0; } - st = &st2; +#ifdef SUPPORT_ACLS + sx2.acc_acl = sx2.def_acl = NULL; +#endif if (!preserve_perms && S_ISDIR(new_mode) - && st->st_mode & S_ISGID) { + && sx2.st.st_mode & S_ISGID) { /* We just created this directory and its setgid * bit is on, so make sure it stays on. */ new_mode |= S_ISGID; } + sxp = &sx2; } - if (!preserve_times || (S_ISDIR(st->st_mode) && omit_dir_times)) +#ifdef SUPPORT_ACLS + if (preserve_acls && !ACL_READY(*sxp)) + get_acl(fname, sxp); +#endif + + if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && omit_dir_times)) flags |= ATTRS_SKIP_MTIME; if (!(flags & ATTRS_SKIP_MTIME) - && cmp_time(st->st_mtime, file->modtime) != 0) { - int ret = set_modtime(fname, file->modtime, st->st_mode); + && cmp_time(sxp->st.st_mtime, file->modtime) != 0) { + int ret = set_modtime(fname, file->modtime, sxp->st.st_mode); if (ret < 0) { rsyserr(FERROR, errno, "failed to set times on %s", full_fname(fname)); - return 0; + goto cleanup; } if (ret == 0) /* ret == 1 if symlink could not be set */ updated = 1; } - change_uid = am_root && preserve_uid && st->st_uid != file->uid; + change_uid = am_root && preserve_uid && sxp->st.st_uid != file->uid; change_gid = preserve_gid && file->gid != GID_NONE - && st->st_gid != file->gid; + && sxp->st.st_gid != file->gid; #if !defined HAVE_LCHOWN && !defined CHOWN_MODIFIES_SYMLINK - if (S_ISLNK(st->st_mode)) + if (S_ISLNK(sxp->st.st_mode)) ; else #endif @@ -176,45 +186,57 @@ rprintf(FINFO, "set uid of %s from %ld to %ld\n", fname, - (long)st->st_uid, (long)file->uid); + (long)sxp->st.st_uid, (long)file->uid); } if (change_gid) { rprintf(FINFO, "set gid of %s from %ld to %ld\n", fname, - (long)st->st_gid, (long)file->gid); + (long)sxp->st.st_gid, (long)file->gid); } } if (do_lchown(fname, - change_uid ? file->uid : st->st_uid, - change_gid ? file->gid : st->st_gid) != 0) { + change_uid ? file->uid : sxp->st.st_uid, + change_gid ? file->gid : sxp->st.st_gid) != 0) { /* shouldn't have attempted to change uid or gid * unless have the privilege */ rsyserr(FERROR, errno, "%s %s failed", change_uid ? "chown" : "chgrp", full_fname(fname)); - return 0; + goto cleanup; } /* a lchown had been done - we have to re-stat if the * destination had the setuid or setgid bits set due * to the side effect of the chown call */ - if (st->st_mode & (S_ISUID | S_ISGID)) { - link_stat(fname, st, - keep_dirlinks && S_ISDIR(st->st_mode)); + if (sxp->st.st_mode & (S_ISUID | S_ISGID)) { + link_stat(fname, &sxp->st, + keep_dirlinks && S_ISDIR(sxp->st.st_mode)); } updated = 1; } if (daemon_chmod_modes && !S_ISLNK(new_mode)) new_mode = tweak_mode(new_mode, daemon_chmod_modes); + +#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() changes permission bits in the process of setting + * an access ACL, it changes sxp->st.st_mode so we know whether we + * need to chmod(). */ + if (preserve_acls && set_acl(fname, file, sxp) == 0) + updated = 1; +#endif + #ifdef HAVE_CHMOD - if ((st->st_mode & CHMOD_BITS) != (new_mode & CHMOD_BITS)) { + if ((sxp->st.st_mode & CHMOD_BITS) != (new_mode & CHMOD_BITS)) { int ret = do_chmod(fname, new_mode); if (ret < 0) { rsyserr(FERROR, errno, "failed to set permissions on %s", full_fname(fname)); - return 0; + goto cleanup; } if (ret == 0) /* ret == 1 if symlink could not be set */ updated = 1; @@ -227,6 +249,11 @@ else rprintf(FCLIENT, "%s is uptodate\n", fname); } + cleanup: +#ifdef SUPPORT_ACLS + if (preserve_acls && sxp == &sx2) + free_acl(&sx2); +#endif return updated; } diff -u rsync-2.6.9/rsync.h rsync-acl-2.6.9/rsync.h --- rsync-2.6.9/rsync.h 2006-10-23 23:31:30.000000000 -0400 +++ rsync-acl-2.6.9/rsync.h 2006-11-08 00:02:03.000000000 -0500 @@ -492,6 +492,14 @@ #define IN_LOOPBACKNET 127 #endif +#ifndef HAVE_NO_ACLS +#define SUPPORT_ACLS 1 +#endif + +#if HAVE_UNIXWARE_ACLS|HAVE_SOLARIS_ACLS|HAVE_HPUX_ACLS +#define ACLS_NEED_MASK 1 +#endif + #define GID_NONE ((gid_t)-1) #define HL_CHECK_MASTER 0 @@ -653,6 +661,17 @@ 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/wildmatch.h" @@ -669,6 +688,16 @@ #define UNUSED(x) x __attribute__((__unused__)) #define NORETURN __attribute__((__noreturn__)) +typedef struct { + STRUCT_STAT st; +#ifdef SUPPORT_ACLS + struct rsync_acl *acc_acl; /* access ACL */ + struct rsync_acl *def_acl; /* default ACL */ +#endif +} statx; + +#define ACL_READY(sx) ((sx).acc_acl != NULL) + #include "proto.h" /* We have replacement versions of these if they're missing. */ diff -u rsync-2.6.9/rsync.yo rsync-acl-2.6.9/rsync.yo --- rsync-2.6.9/rsync.yo 2006-11-06 23:39:47.000000000 -0500 +++ rsync-acl-2.6.9/rsync.yo 2006-11-08 00:02:04.000000000 -0500 @@ -301,7 +301,7 @@ -q, --quiet suppress non-error messages --no-motd suppress daemon-mode MOTD (see caveat) -c, --checksum skip based on checksum, not mod-time & size - -a, --archive archive mode; same as -rlptgoD (no -H) + -a, --archive archive mode; same as -rlptgoD (no -H, -A) --no-OPTION turn off an implied OPTION (e.g. --no-D) -r, --recursive recurse into directories -R, --relative use relative path names @@ -323,6 +323,7 @@ -p, --perms preserve permissions -E, --executability preserve executability --chmod=CHMOD affect file and/or directory permissions + -A, --acls preserve ACLs (implies -p) [non-standard] -o, --owner preserve owner (super-user only) -g, --group preserve group --devices preserve device files (super-user only) @@ -753,7 +754,9 @@ 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 - file's permissions masked with the receiving end's umask setting, and + file's permissions masked with the receiving directory's default + permissions (either the receiving process's umask, or the permissions + specified via the destination directory's default ACL), and their special permission bits disabled except in the case where a new directory inherits a setgid bit from its parent directory. )) @@ -784,9 +787,11 @@ 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 -destination's setgid bit setting on a newly-created directory. (Keep in -mind that it is the version of the receiving rsync that affects this -behavior.) +destination's setgid bit setting on a newly-created directory. Default ACL +observance was added to the ACL patch for rsync 2.6.7, so older (or +non-ACL-enabled) rsyncs use the umask even if default ACLs are present. +(Keep in mind that it is the version of the receiving rsync that affects +these behaviors.) dit(bf(-E, --executability)) This option causes rsync to preserve the executability (or non-executability) of regular files when bf(--perms) is @@ -804,6 +809,15 @@ If bf(--perms) is enabled, this option is ignored. +dit(bf(-A, --acls)) This option causes rsync to update the destination +ACLs to be the same as the source ACLs. This nonstandard option only +works if the remote rsync also supports it. bf(--acls) implies bf(--perms). + +Note also that an optimization of the ACL-sending protocol used by this +version makes it incompatible with sending files to an older ACL-enabled +rsync unless you double the bf(--acls) option (e.g. bf(-AA)). This +doubling is not needed when pulling files from an older rsync. + dit(bf(--chmod)) This option tells rsync to apply one or more comma-separated "chmod" strings to the permission of the files in the transfer. The resulting value is treated as though it was the permissions @@ -1389,8 +1403,8 @@ with older versions of rsync, but that also turns on the output of other verbose messages). -The "%i" escape has a cryptic output that is 9 letters long. The general -format is like the string bf(YXcstpogz), where bf(Y) is replaced by the +The "%i" escape has a cryptic output that is 11 letters long. The general +format is like the string bf(YXcstpoguax), where bf(Y) is replaced by the type of update being done, bf(X) is replaced by the file-type, and the other letters represent attributes that may be output if they are being modified. @@ -1439,7 +1453,11 @@ sender's value (requires bf(--owner) and super-user privileges). it() A bf(g) means the group is different and is being updated to the sender's value (requires bf(--group) and the authority to set the group). - it() The bf(z) slot is reserved for future use. + it() The bf(u) slot is reserved for reporting update (access) time changes + (a feature that is not yet released). + it() The bf(a) means that the ACL information changed. + it() The bf(x) slot is reserved for reporting extended attribute changes + (a feature that is not yet released). )) One other output is possible: when deleting files, the "%i" will output Only in rsync-acl-2.6.9/: smb_acls.h Common subdirectories: rsync-2.6.9/support and rsync-acl-2.6.9/support Common subdirectories: rsync-2.6.9/testhelp and rsync-acl-2.6.9/testhelp Common subdirectories: rsync-2.6.9/testsuite and rsync-acl-2.6.9/testsuite diff -u rsync-2.6.9/uidlist.c rsync-acl-2.6.9/uidlist.c --- rsync-2.6.9/uidlist.c 2006-10-13 19:35:53.000000000 -0400 +++ rsync-acl-2.6.9/uidlist.c 2006-11-08 00:02:04.000000000 -0500 @@ -35,6 +35,7 @@ extern int verbose; extern int preserve_uid; extern int preserve_gid; +extern int preserve_acls; extern int numeric_ids; extern int am_root; @@ -273,7 +274,7 @@ if (numeric_ids) return; - if (preserve_uid) { + if (preserve_uid || preserve_acls) { int len; /* we send sequences of uid/byte-length/name */ for (list = uidlist; list; list = list->next) { @@ -290,7 +291,7 @@ write_int(f, 0); } - if (preserve_gid) { + if (preserve_gid || preserve_acls) { int len; for (list = gidlist; list; list = list->next) { if (!list->name) @@ -311,7 +312,7 @@ int id, i; char *name; - if (preserve_uid && !numeric_ids) { + if ((preserve_uid || preserve_acls) && !numeric_ids) { /* read the uid list */ while ((id = read_int(f)) != 0) { int len = read_byte(f); @@ -323,7 +324,7 @@ } } - if (preserve_gid && !numeric_ids) { + if ((preserve_gid || preserve_acls) && !numeric_ids) { /* read the gid list */ while ((id = read_int(f)) != 0) { int len = read_byte(f); @@ -335,6 +336,16 @@ } } +#ifdef SUPPORT_ACLS + if (preserve_acls && !numeric_ids) { + id_t *id; + while ((id = next_acl_uid(flist)) != NULL) + *id = match_uid(*id); + while ((id = next_acl_gid(flist)) != NULL) + *id = match_gid(*id); + } +#endif + /* Now convert all the uids/gids from sender values to our values. */ if (am_root && preserve_uid && !numeric_ids) { for (i = 0; i < flist->count; i++) diff -u rsync-2.6.9/util.c rsync-acl-2.6.9/util.c --- rsync-2.6.9/util.c 2006-10-14 16:31:33.000000000 -0400 +++ rsync-acl-2.6.9/util.c 2006-11-08 00:02:04.000000000 -0500 @@ -1468,3 +1468,31 @@ return -1; } + +void *expand_item_list(item_list *lp, size_t item_size, + const char *desc, int incr) +{ + /* First time through, 0 <= 0, so list is expanded. */ + if (lp->malloced <= lp->count) { + void *new_ptr; + size_t new_size = lp->malloced; + if (incr < 0) + new_size -= incr; /* increase slowly */ + else if (new_size < (size_t)incr) + new_size += incr; + else + new_size *= 2; + new_ptr = realloc_array(lp->items, char, new_size * item_size); + if (verbose >= 4) { + rprintf(FINFO, "[%s] expand %s to %.0f bytes, did%s move\n", + who_am_i(), desc, (double)new_size * item_size, + new_ptr == lp->items ? " not" : ""); + } + if (!new_ptr) + out_of_memory("expand_item_list"); + + lp->items = new_ptr; + lp->malloced = new_size; + } + return (char*)lp->items + (lp->count++ * item_size); +} Common subdirectories: rsync-2.6.9/zlib and rsync-acl-2.6.9/zlib