I want to make an "exact" copy of a directory tree (as far as
practical). I was hoping cp -Rp would do the trick (assuming
I have no hard-linked files), but it fails on several counts:
1) modification times on directories get smashed
2) UNIX (er, "local") domain sockets aren't copied
3) unless run as root, can't copy _from_ write-protected
directories
This context diff (against /usr/src/bin/cp/ from 3.5.1-RELEASE)
is intended as a starting point for discussion; if you can come
up with something more elegant, by all means commit that instead.
-=EPS=-
-------
*** cp.c.orig Sat Dec 11 12:33:31 1999
--- cp.c
***************
*** 271,278 ****
warnx("%s: directory causes a cycle", curr->fts_path);
badcp = rval = 1;
continue;
- case FTS_DP: /* Ignore, continue. */
- continue;
}
/*
--- 271,276 ----
***************
*** 330,335 ****
--- 328,339 ----
STRIP_TRAILING_SLASH(to);
}
+ if (curr->fts_info == FTS_DP) {
+ if (pflag && setfile(curr->fts_statp, 0))
+ badcp = rval = 1;
+ continue;
+ }
+
/* Not an error but need to remember it happened */
if (stat(to.p_path, &to_stat) == -1)
dne = 1;
***************
*** 388,398 ****
* umask; arguably wrong, but it's been that way
* forever.
*/
! if (pflag && setfile(curr->fts_statp, 0))
! badcp = rval = 1;
! else if (dne)
! (void)chmod(to.p_path,
! curr->fts_statp->st_mode);
break;
case S_IFBLK:
case S_IFCHR:
--- 392,399 ----
* umask; arguably wrong, but it's been that way
* forever.
*/
! if (!pflag && dne) (void)chmod(to.p_path,
! curr->fts_statp->st_mode);
break;
case S_IFBLK:
case S_IFCHR:
***************
*** 407,412 ****
--- 408,422 ----
case S_IFIFO:
if (Rflag) {
if (copy_fifo(curr->fts_statp, !dne))
+ badcp = rval = 1;
+ } else {
+ if (copy_file(curr, dne))
+ badcp = rval = 1;
+ }
+ break;
+ case S_IFSOCK:
+ if (Rflag) {
+ if (copy_socket(curr->fts_statp, !dne))
badcp = rval = 1;
} else {
if (copy_file(curr, dne))
*** extern.h.orig Sun Aug 29 07:11:34 1999
--- extern.h
***************
*** 50,55 ****
--- 50,56 ----
int copy_fifo __P((struct stat *, int));
int copy_file __P((FTSENT *, int));
int copy_link __P((FTSENT *, int));
+ int copy_socket __P((struct stat *, int));
int copy_special __P((struct stat *, int));
int setfile __P((struct stat *, int));
void usage __P((void));
*** utils.c.orig Sat Dec 11 12:33:31 1999
--- utils.c
***************
*** 44,49 ****
--- 44,51 ----
#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
#include <sys/mman.h>
#endif
+ #include <sys/socket.h>
+ #include <sys/un.h>
#include <err.h>
#include <errno.h>
***************
*** 51,56 ****
--- 53,59 ----
#include <fts.h>
#include <stdio.h>
#include <sysexits.h>
+ #include <string.h>
#include <unistd.h>
#include "extern.h"
***************
*** 255,260 ****
--- 258,302 ----
warn("mknod: %s", to.p_path);
return (1);
}
+ return (pflag ? setfile(from_stat, 0) : 0);
+ }
+
+ int
+ copy_socket(from_stat, exists)
+ struct stat *from_stat;
+ int exists;
+ {
+ register int s, n;
+ union {
+ char data[256];
+ struct sockaddr_un un;
+ } u;
+
+ if (exists && unlink(to.p_path)) {
+ warn("unlink: %s", to.p_path);
+ return (1);
+ }
+ if ((s = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
+ warn("socket: %s", to.p_path);
+ return (1);
+ }
+ bzero((void *)&u, sizeof u);
+ u.un.sun_len = 255;
+ u.un.sun_family = AF_UNIX;
+ if ((n = strlen(to.p_path)) >
+ sizeof u - (sizeof u.un - sizeof u.un.sun_path)) {
+ warn("bind: %s", to.p_path);
+ (void)close(s);
+ return (1);
+ }
+ (void)strcpy(u.un.sun_path, to.p_path);
+ if (bind(s, (struct sockaddr *)&u.un,
+ sizeof u.un - sizeof u.un.sun_path + n)) {
+ warn("bind: %s", to.p_path);
+ (void)close(s);
+ return (1);
+ }
+ (void)close(s);
return (pflag ? setfile(from_stat, 0) : 0);
}
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message