![]()
|
diff -u --exclude=CVS -r -udbp configure.ac configure.ac
--- configure.ac 2004-04-16 20:03:07.000000000 -0700
+++ configure.ac 2005-02-21 18:46:25.000000000 -0800
@@ -2869,6 +2869,9 @@ if test "$ac_cv_lib_pam_pam_set_item" =
LIBS=`echo $LIBS | sed 's/-ldl //'`
fi
+AC_CHECK_FUNCS(copyfile)
+AC_CHECK_HEADERS(copyfile.h)
+
AC_EXEEXT
AC_CONFIG_FILES([Makefile openbsd-compat/Makefile scard/Makefile ssh_prng_cmds])
AC_OUTPUT
diff -u --exclude=CVS -r -udbp scp.1 scp.1
--- scp.1 2004-03-08 04:12:36.000000000 -0800
+++ scp.1 2005-02-21 18:46:25.000000000 -0800
@@ -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 -u --exclude=CVS -r -udbp scp.c scp.c
--- scp.c 2003-11-23 18:09:28.000000000 -0800
+++ scp.c 2005-02-21 18:46:52.000000000 -0800
@@ -80,6 +80,11 @@ RCSID("$OpenBSD: scp.c,v 1.113 2003/11/2
#include "misc.h"
#include "progressmeter.h"
+#ifdef HAVE_COPYFILE_H
+#include <libgen.h>
+#include <copyfile.h>
+#endif
+
#ifdef HAVE___PROGNAME
extern char *__progname;
#else
@@ -109,6 +114,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" : "");
@@ -507,6 +532,11 @@ source(int argc, char **argv)
int fd, 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];
@@ -519,6 +549,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) {
@@ -602,6 +643,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
}
}
@@ -748,6 +819,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) <= 0)
return;
@@ -873,6 +948,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;
@@ -959,6 +1057,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) {
@@ -1020,7 +1133,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);
syntax highlighted by Code2HTML, v. 0.9.1 |