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

Reply via email to