diff -Naurdp ../openssh.sacl/configure ./configure --- ../openssh.sacl/configure 2005-09-28 16:11:11.000000000 -0700 +++ ./configure 2005-09-28 16:39:28.000000000 -0700 @@ -25580,6 +25580,259 @@ fi CFLAGS="$CFLAGS $werror_flags" +for ac_func in copyfile +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 eval "test \"\${$as_ac_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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +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 +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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 conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&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 + + +for ac_header in copyfile.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&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 { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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 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 { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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;} + ( + cat <<\_ASBOX +## ------------------------------------------- ## +## Report this to openssh-unix-dev@mindrot.org ## +## ------------------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&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 + + + ac_config_files="$ac_config_files Makefile buildpkg.sh opensshd.init openbsd-compat/Makefile scard/Makefile ssh_prng_cmds survey.sh" cat >confcache <<\_ACEOF diff -Naurdp ../openssh.sacl/configure.ac ./configure.ac --- ../openssh.sacl/configure.ac 2005-09-28 16:11:11.000000000 -0700 +++ ./configure.ac 2005-09-28 16:38:55.000000000 -0700 @@ -3429,6 +3429,9 @@ dnl Adding -Werror to CFLAGS early preve dnl Add now. CFLAGS="$CFLAGS $werror_flags" +AC_CHECK_FUNCS(copyfile) +AC_CHECK_HEADERS(copyfile.h) + AC_EXEEXT AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openbsd-compat/Makefile \ scard/Makefile ssh_prng_cmds survey.sh]) diff -Naurdp ../openssh.sacl/scp.1 ./scp.1 --- ../openssh.sacl/scp.1 2005-09-28 16:11:11.000000000 -0700 +++ ./scp.1 2005-09-28 16:38:55.000000000 -0700 @@ -20,7 +20,7 @@ .Sh SYNOPSIS .Nm scp .Bk -words -.Op Fl 1246BCpqrv +.Op Fl 1246BCEpqrv .Op Fl c Ar cipher .Op Fl F Ar ssh_config .Op Fl i Ar identity_file @@ -87,6 +87,8 @@ Passes the flag to .Xr ssh 1 to enable compression. +.It Fl E +Preserves extended attributes, resource forks, and ACLs. Requires both ends to be running Mac OS X 10.4 or later. .It Fl c Ar cipher Selects the cipher to use for encrypting the data transfer. This option is directly passed to diff -Naurdp ../openssh.sacl/scp.c ./scp.c --- ../openssh.sacl/scp.c 2005-09-28 16:11:11.000000000 -0700 +++ ./scp.c 2005-09-28 16:38:55.000000000 -0700 @@ -80,6 +80,11 @@ RCSID("$OpenBSD: scp.c,v 1.125 2005/07/2 #include "misc.h" #include "progressmeter.h" +#ifdef HAVE_COPYFILE_H +#include +#include +#endif + extern char *__progname; void bwlimit(int); @@ -105,6 +110,12 @@ char *ssh_program = _PATH_SSH_PROGRAM; /* This is used to store the pid of ssh_program */ pid_t do_cmd_pid = -1; +#ifdef HAVE_COPYFILE +int copy_xattr = 0; +int md_flag = 0; +#endif + + static void killchild(int signo) { @@ -231,7 +242,11 @@ main(int argc, char **argv) addargs(&args, "-oClearAllForwardings yes"); fflag = tflag = 0; +#if HAVE_COPYFILE + while ((ch = getopt(argc, argv, "dfl:prtvBCEc:i:P:q1246S:o:F:")) != -1) +#else while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1) +#endif switch (ch) { /* User-visible flags. */ case '1': @@ -277,6 +292,11 @@ main(int argc, char **argv) showprogress = 0; break; +#ifdef HAVE_COPYFILE + case 'E': + copy_xattr = 1; + break; +#endif /* Server options. */ case 'd': targetshouldbedirectory = 1; @@ -326,7 +346,12 @@ main(int argc, char **argv) remin = remout = -1; do_cmd_pid = -1; /* Command to be executed on remote system using "ssh". */ +#if HAVE_COPYFILE + (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s%s", + copy_xattr ? " -E" : "", +#else (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s", +#endif verbose_mode ? " -v" : "", iamrecursive ? " -r" : "", pflag ? " -p" : "", targetshouldbedirectory ? " -d" : ""); @@ -509,6 +534,11 @@ source(int argc, char **argv) int fd = -1, haderr, indx; char *last, *name, buf[2048]; int len; +#if HAVE_COPYFILE + char md_name[MAXPATHLEN]; + char *md_tmp; +#endif + for (indx = 0; indx < argc; ++indx) { name = argv[indx]; @@ -521,6 +551,17 @@ source(int argc, char **argv) name); goto next; } +#if HAVE_COPYFILE +md_next: + statbytes = 0; + if (md_flag) { + fd = open(md_tmp, O_RDONLY, 0); + unlink(md_tmp); + free(md_tmp); + if (fd < 0) + goto syserr; + } else +#endif if ((fd = open(name, O_RDONLY, 0)) < 0) goto syserr; if (fstat(fd, &stb) < 0) { @@ -604,6 +645,36 @@ next: (void) close(fd); else run_err("%s: %s", name, strerror(haderr)); (void) response(); +#ifdef HAVE_COPYFILE + if (copy_xattr && md_flag == 0) + { + if (!copyfile(name, NULL, 0, + COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_CHECK)) + continue; + + /* + * this file will hold the actual metadata + * to be transferred + */ + md_tmp = strdup("/tmp/scp.md.XXXXXX"); + md_tmp = mktemp(md_tmp); + + if(copyfile(name, md_tmp, 0, + COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_PACK) == 0) + { + /* + * this is the fake name to display + */ + snprintf(md_name, sizeof md_name, "%s/._%s", dirname(name), basename(name)); + name = md_name; + md_flag = 1; + if (verbose_mode) + fprintf(stderr, "copyfile(%s, %s, PACK)\n", name, md_tmp); + goto md_next; + } + } else + md_flag = 0; +#endif } } @@ -751,6 +822,10 @@ sink(int argc, char **argv) if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) targisdir = 1; for (first = 1;; first = 0) { +#if HAVE_COPYFILE + char md_src[MAXPATHLEN]; + char md_dst[MAXPATHLEN]; +#endif cp = buf; if (atomicio(read, remin, cp, 1) != 1) return; @@ -884,6 +959,29 @@ sink(int argc, char **argv) } omode = mode; mode |= S_IWRITE; + +#if HAVE_COPYFILE + if (copy_xattr && !strncmp(basename(curfile), "._", 2)) + { + if (targisdir) + { + snprintf(md_src, sizeof md_src, "%s.XXX", np); + snprintf(md_dst, sizeof md_dst, "%s/%s", + dirname(np), basename(np) + 2); + if(mkstemp(md_src) < 0) + continue; + } + else + { + snprintf(md_src, sizeof md_src, "%s/._%s.XXX", + dirname(np), basename(np)); + snprintf(md_dst, sizeof md_dst, "%s", np); + if(mkstemp(md_src) < 0) + continue; + } + np = md_src; + } +#endif if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { bad: run_err("%s: %s", np, strerror(errno)); continue; @@ -971,6 +1069,21 @@ bad: run_err("%s: %s", np, strerror(er wrerrno = errno; } (void) response(); +#ifdef HAVE_COPYFILE + if (copy_xattr && strncmp(basename(np), "._", 2) == 0) + { + if (verbose_mode) + fprintf(stderr, "copyfile(%s, %s, UNPACK)\n", md_src, md_dst); + if(!copyfile(md_src, md_dst, 0, + COPYFILE_ACL | COPYFILE_XATTR | COPYFILE_UNPACK) < 0) + { + snprintf(md_dst, sizeof md_dst, "%s/._%s", + dirname(md_dst), basename(md_dst)); + rename(md_src, md_dst); + } else + unlink(md_src); + } else +#endif if (setimes && wrerr == NO) { setimes = 0; if (utimes(np, tv) < 0) { @@ -1032,7 +1145,11 @@ void usage(void) { (void) fprintf(stderr, +#if HAVE_COPYFILE + "usage: scp [-1246BCEpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n" +#else "usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n" +#endif " [-l limit] [-o ssh_option] [-P port] [-S program]\n" " [[user@]host1:]file1 [...] [[user@]host2:]file2\n"); exit(1); --- config.h.in 2005-02-22 13:45:22.000000000 -0800 +++ config.h.in 2005-02-22 14:03:52.000000000 -0800 @@ -354,6 +353,18 @@ /* getaddrinfo is broken (if present) */ #undef BROKEN_GETADDRINFO +/* platform uses an in-memory credentials cache */ +#undef USE_CCAPI + +/* platform has a Security Authorization Session API */ +#undef USE_SECURITY_SESSION_API + +/* Define to 1 if you have the `copyfile' function. */ +#undef HAVE_COPYFILE + +/* Define to 1 if you have the header file. */ +#undef HAVE_COPYFILE_H + /* updwtmpx is broken (if present) */ #undef BROKEN_UPDWTMPX