Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 3 Aug 2000 00:53:36 -0700 (PDT)
From:      eps@sirius.com (Eric P. Scott)
To:        freebsd-hackers@freebsd.org
Subject:   fixing longstanding cp -Rp misbehavior
Message-ID:  <200008030753.AAA62717@mail1.sirius.com>

next in thread | raw e-mail | index | archive | help
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 majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200008030753.AAA62717>