Handle separated devices and special files.
authorWayne Davison <wayned@samba.org>
Thu, 26 Jan 2006 10:38:58 +0000 (10:38 +0000)
committerWayne Davison <wayned@samba.org>
Thu, 26 Jan 2006 10:38:58 +0000 (10:38 +0000)
backup.c
flist.c
generator.c
options.c
rsync.h

index d36524a..11011cf 100644 (file)
--- a/backup.c
+++ b/backup.c
@@ -30,6 +30,7 @@ extern char *backup_dir;
 
 extern int am_root;
 extern int preserve_devices;
 
 extern int am_root;
 extern int preserve_devices;
+extern int preserve_specials;
 extern int preserve_links;
 extern int preserve_hard_links;
 extern int orig_umask;
 extern int preserve_links;
 extern int preserve_hard_links;
 extern int orig_umask;
@@ -187,7 +188,8 @@ static int keep_backup(char *fname)
                return 0;
 
        /* Check to see if this is a device file, or link */
                return 0;
 
        /* Check to see if this is a device file, or link */
-       if (IS_DEVICE(file->mode) && am_root && preserve_devices) {
+       if ((am_root && preserve_devices && IS_DEVICE(file->mode))
+        || (preserve_specials && IS_SPECIAL(file->mode))) {
                do_unlink(buf);
                if (do_mknod(buf, file->mode, file->u.rdev) < 0
                    && (errno != ENOENT || make_bak_dir(buf) < 0
                do_unlink(buf);
                if (do_mknod(buf, file->mode, file->u.rdev) < 0
                    && (errno != ENOENT || make_bak_dir(buf) < 0
diff --git a/flist.c b/flist.c
index 87a2ba7..763d826 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -48,6 +48,7 @@ extern int preserve_links;
 extern int preserve_hard_links;
 extern int preserve_perms;
 extern int preserve_devices;
 extern int preserve_hard_links;
 extern int preserve_perms;
 extern int preserve_devices;
+extern int preserve_specials;
 extern int preserve_uid;
 extern int preserve_gid;
 extern int relative_paths;
 extern int preserve_uid;
 extern int preserve_gid;
 extern int relative_paths;
@@ -343,16 +344,14 @@ static void send_file_entry(struct file_struct *file, int f)
                flags |= XMIT_SAME_MODE;
        else
                mode = file->mode;
                flags |= XMIT_SAME_MODE;
        else
                mode = file->mode;
-       if (preserve_devices) {
+       if ((preserve_devices && IS_DEVICE(mode))
+        || (preserve_specials && IS_SPECIAL(mode))) {
                if (protocol_version < 28) {
                if (protocol_version < 28) {
-                       if (IS_DEVICE(mode)) {
-                               if (file->u.rdev == rdev)
-                                       flags |= XMIT_SAME_RDEV_pre28;
-                               else
-                                       rdev = file->u.rdev;
-                       } else
-                               rdev = makedev(0, 0);
-               } else if (IS_DEVICE(mode)) {
+                       if (file->u.rdev == rdev)
+                               flags |= XMIT_SAME_RDEV_pre28;
+                       else
+                               rdev = file->u.rdev;
+               } else {
                        rdev = file->u.rdev;
                        if ((uint32)major(rdev) == rdev_major)
                                flags |= XMIT_SAME_RDEV_MAJOR;
                        rdev = file->u.rdev;
                        if ((uint32)major(rdev) == rdev_major)
                                flags |= XMIT_SAME_RDEV_MAJOR;
@@ -361,7 +360,8 @@ static void send_file_entry(struct file_struct *file, int f)
                        if ((uint32)minor(rdev) <= 0xFFu)
                                flags |= XMIT_RDEV_MINOR_IS_SMALL;
                }
                        if ((uint32)minor(rdev) <= 0xFFu)
                                flags |= XMIT_RDEV_MINOR_IS_SMALL;
                }
-       }
+       } else if (protocol_version < 28)
+               rdev = makedev(0, 0);
        if (file->uid == uid)
                flags |= XMIT_SAME_UID;
        else
        if (file->uid == uid)
                flags |= XMIT_SAME_UID;
        else
@@ -437,7 +437,8 @@ static void send_file_entry(struct file_struct *file, int f)
                        add_gid(gid);
                write_int(f, gid);
        }
                        add_gid(gid);
                write_int(f, gid);
        }
-       if (preserve_devices && IS_DEVICE(mode)) {
+       if ((preserve_devices && IS_DEVICE(mode))
+        || (preserve_specials && IS_SPECIAL(mode))) {
                if (protocol_version < 28) {
                        if (!(flags & XMIT_SAME_RDEV_pre28))
                                write_int(f, (int)rdev);
                if (protocol_version < 28) {
                        if (!(flags & XMIT_SAME_RDEV_pre28))
                                write_int(f, (int)rdev);
@@ -577,14 +578,12 @@ static struct file_struct *receive_file_entry(struct file_list *flist,
        if (preserve_gid && !(flags & XMIT_SAME_GID))
                gid = (gid_t)read_int(f);
 
        if (preserve_gid && !(flags & XMIT_SAME_GID))
                gid = (gid_t)read_int(f);
 
-       if (preserve_devices) {
+       if ((preserve_devices && IS_DEVICE(mode))
+        || (preserve_specials && IS_SPECIAL(mode))) {
                if (protocol_version < 28) {
                if (protocol_version < 28) {
-                       if (IS_DEVICE(mode)) {
-                               if (!(flags & XMIT_SAME_RDEV_pre28))
-                                       rdev = (dev_t)read_int(f);
-                       } else
-                               rdev = makedev(0, 0);
-               } else if (IS_DEVICE(mode)) {
+                       if (!(flags & XMIT_SAME_RDEV_pre28))
+                               rdev = (dev_t)read_int(f);
+               } else {
                        uint32 rdev_minor;
                        if (!(flags & XMIT_SAME_RDEV_MAJOR))
                                rdev_major = read_int(f);
                        uint32 rdev_minor;
                        if (!(flags & XMIT_SAME_RDEV_MAJOR))
                                rdev_major = read_int(f);
@@ -594,7 +593,8 @@ static struct file_struct *receive_file_entry(struct file_list *flist,
                                rdev_minor = read_int(f);
                        rdev = makedev(rdev_major, rdev_minor);
                }
                                rdev_minor = read_int(f);
                        rdev = makedev(rdev_major, rdev_minor);
                }
-       }
+       } else if (protocol_version < 28)
+               rdev = makedev(0, 0);
 
 #ifdef SUPPORT_LINKS
        if (preserve_links && S_ISLNK(mode)) {
 
 #ifdef SUPPORT_LINKS
        if (preserve_links && S_ISLNK(mode)) {
@@ -664,7 +664,8 @@ static struct file_struct *receive_file_entry(struct file_list *flist,
        memcpy(bp, basename, basename_len);
        bp += basename_len;
 
        memcpy(bp, basename, basename_len);
        bp += basename_len;
 
-       if (preserve_devices && IS_DEVICE(mode))
+       if ((preserve_devices && IS_DEVICE(mode))
+        || (preserve_specials && IS_SPECIAL(mode)))
                file->u.rdev = rdev;
 
 #ifdef SUPPORT_LINKS
                file->u.rdev = rdev;
 
 #ifdef SUPPORT_LINKS
@@ -916,7 +917,8 @@ struct file_struct *make_file(char *fname, struct file_list *flist,
        bp += basename_len;
 
 #ifdef HAVE_STRUCT_STAT_ST_RDEV
        bp += basename_len;
 
 #ifdef HAVE_STRUCT_STAT_ST_RDEV
-       if (preserve_devices && IS_DEVICE(st.st_mode))
+       if ((preserve_devices && IS_DEVICE(st.st_mode))
+        || (preserve_specials && IS_SPECIAL(st.st_mode)))
                file->u.rdev = st.st_rdev;
 #endif
 
                file->u.rdev = st.st_rdev;
 #endif
 
index fb0bc2d..b7aa8cf 100644 (file)
@@ -38,6 +38,7 @@ extern int relative_paths;
 extern int keep_dirlinks;
 extern int preserve_links;
 extern int preserve_devices;
 extern int keep_dirlinks;
 extern int preserve_links;
 extern int preserve_devices;
+extern int preserve_specials;
 extern int preserve_hard_links;
 extern int preserve_perms;
 extern int preserve_uid;
 extern int preserve_hard_links;
 extern int preserve_perms;
 extern int preserve_uid;
@@ -986,7 +987,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                return;
        }
 
                return;
        }
 
-       if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
+       if ((am_root && preserve_devices && IS_DEVICE(file->mode))
+        || (preserve_specials && IS_SPECIAL(file->mode))) {
                if (statret != 0
                 && (basis_dir[0] != NULL && can_link_devices)) {
                        if (try_dests_non(file, fname, ndx, itemizing,
                if (statret != 0
                 && (basis_dir[0] != NULL && can_link_devices)) {
                        if (try_dests_non(file, fname, ndx, itemizing,
@@ -1007,7 +1009,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                            && hard_link_check(file, ndx, fname, -1, &st,
                                               itemizing, code, HL_SKIP))
                                return;
                            && hard_link_check(file, ndx, fname, -1, &st,
                                               itemizing, code, HL_SKIP))
                                return;
-                       if (!IS_DEVICE(st.st_mode))
+                       if ((IS_DEVICE(file->mode) && !IS_DEVICE(st.st_mode))
+                        || (IS_SPECIAL(file->mode) && !IS_SPECIAL(st.st_mode)))
                                statret = -1;
                        if (verbose > 2) {
                                rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
                                statret = -1;
                        if (verbose > 2) {
                                rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
index 9a7c423..5800abe 100644 (file)
--- a/options.c
+++ b/options.c
@@ -46,6 +46,7 @@ int preserve_links = 0;
 int preserve_hard_links = 0;
 int preserve_perms = 0;
 int preserve_devices = 0;
 int preserve_hard_links = 0;
 int preserve_perms = 0;
 int preserve_devices = 0;
+int preserve_specials = 0;
 int preserve_uid = 0;
 int preserve_gid = 0;
 int preserve_times = 0;
 int preserve_uid = 0;
 int preserve_gid = 0;
 int preserve_times = 0;
@@ -290,7 +291,9 @@ void usage(enum logcode F)
   rprintf(F," -p, --perms                 preserve permissions\n");
   rprintf(F," -o, --owner                 preserve owner (root only)\n");
   rprintf(F," -g, --group                 preserve group\n");
   rprintf(F," -p, --perms                 preserve permissions\n");
   rprintf(F," -o, --owner                 preserve owner (root only)\n");
   rprintf(F," -g, --group                 preserve group\n");
-  rprintf(F," -D, --devices               preserve devices (root only)\n");
+  rprintf(F,"     --devices               preserve device files (root only)\n");
+  rprintf(F,"     --specials              preserve special files\n");
+  rprintf(F," -D                          same as --devices --specials\n");
   rprintf(F," -t, --times                 preserve times\n");
   rprintf(F," -O, --omit-dir-times        omit directories when preserving times\n");
   rprintf(F,"     --chmod=CHMOD           change destination permissions\n");
   rprintf(F," -t, --times                 preserve times\n");
   rprintf(F," -O, --omit-dir-times        omit directories when preserving times\n");
   rprintf(F,"     --chmod=CHMOD           change destination permissions\n");
@@ -373,6 +376,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
       OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP,
       OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD,
       OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
       OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP,
       OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD,
       OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
+      OPT_NO_D,
       OPT_SERVER, OPT_REFUSED_BASE = 9000};
 
 static struct poptOption long_options[] = {
       OPT_SERVER, OPT_REFUSED_BASE = 9000};
 
 static struct poptOption long_options[] = {
@@ -408,9 +412,12 @@ static struct poptOption long_options[] = {
   {"group",           'g', POPT_ARG_VAL,    &preserve_gid, 1, 0, 0 },
   {"no-group",         0,  POPT_ARG_VAL,    &preserve_gid, 0, 0, 0 },
   {"no-g",             0,  POPT_ARG_VAL,    &preserve_gid, 0, 0, 0 },
   {"group",           'g', POPT_ARG_VAL,    &preserve_gid, 1, 0, 0 },
   {"no-group",         0,  POPT_ARG_VAL,    &preserve_gid, 0, 0, 0 },
   {"no-g",             0,  POPT_ARG_VAL,    &preserve_gid, 0, 0, 0 },
-  {"devices",         'D', POPT_ARG_VAL,    &preserve_devices, 1, 0, 0 },
+  {0,                 'D', POPT_ARG_NONE,   0, 'D', 0, 0 },
+  {"no-D",             0,  POPT_ARG_NONE,   0, OPT_NO_D, 0, 0 },
+  {"devices",          0,  POPT_ARG_VAL,    &preserve_devices, 1, 0, 0 },
   {"no-devices",       0,  POPT_ARG_VAL,    &preserve_devices, 0, 0, 0 },
   {"no-devices",       0,  POPT_ARG_VAL,    &preserve_devices, 0, 0, 0 },
-  {"no-D",             0,  POPT_ARG_VAL,    &preserve_devices, 0, 0, 0 },
+  {"specials",         0,  POPT_ARG_VAL,    &preserve_specials, 1, 0, 0 },
+  {"no-specials",      0,  POPT_ARG_VAL,    &preserve_specials, 0, 0, 0 },
   {"links",           'l', POPT_ARG_VAL,    &preserve_links, 1, 0, 0 },
   {"no-links",         0,  POPT_ARG_VAL,    &preserve_links, 0, 0, 0 },
   {"no-l",             0,  POPT_ARG_VAL,    &preserve_links, 0, 0, 0 },
   {"links",           'l', POPT_ARG_VAL,    &preserve_links, 1, 0, 0 },
   {"no-links",         0,  POPT_ARG_VAL,    &preserve_links, 0, 0, 0 },
   {"no-l",             0,  POPT_ARG_VAL,    &preserve_links, 0, 0, 0 },
@@ -892,6 +899,15 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
                        preserve_gid = 1;
                        preserve_uid = 1;
                        preserve_devices = 1;
                        preserve_gid = 1;
                        preserve_uid = 1;
                        preserve_devices = 1;
+                       preserve_specials = 1;
+                       break;
+
+               case 'D':
+                       preserve_devices = preserve_specials = 1;
+                       break;
+
+               case OPT_NO_D:
+                       preserve_devices = preserve_specials = 0;
                        break;
 
                case 'i':
                        break;
 
                case 'i':
@@ -1464,7 +1480,7 @@ void server_options(char **args,int *argc)
                argstr[x++] = 'o';
        if (preserve_gid)
                argstr[x++] = 'g';
                argstr[x++] = 'o';
        if (preserve_gid)
                argstr[x++] = 'g';
-       if (preserve_devices)
+       if (preserve_devices) /* ignore preserve_specials here */
                argstr[x++] = 'D';
        if (preserve_times)
                argstr[x++] = 't';
                argstr[x++] = 'D';
        if (preserve_times)
                argstr[x++] = 't';
@@ -1517,6 +1533,13 @@ void server_options(char **args,int *argc)
                args[ac++] = arg;
        }
 
                args[ac++] = arg;
        }
 
+       if (preserve_devices) {
+               /* Note: sending "--devices" would not be backward-compatible. */
+               if (!preserve_specials)
+                       args[ac++] = "--no-specials"; /* -D is already set. */
+       } else if (preserve_specials)
+               args[ac++] = "--specials";
+
        /* The server side doesn't use our log-format, but in certain
         * circumstances they need to know a little about the option. */
        if (log_format && am_sender) {
        /* The server side doesn't use our log-format, but in certain
         * circumstances they need to know a little about the option. */
        if (log_format && am_sender) {
diff --git a/rsync.h b/rsync.h
index 2a40532..a5715a3 100644 (file)
--- a/rsync.h
+++ b/rsync.h
@@ -787,7 +787,8 @@ extern int errno;
 #define INADDR_NONE 0xffffffff
 #endif
 
 #define INADDR_NONE 0xffffffff
 #endif
 
-#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) || S_ISFIFO(mode))
+#define IS_SPECIAL(mode) (S_ISSOCK(mode) || S_ISFIFO(mode))
+#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode))
 
 /* Initial mask on permissions given to temporary files.  Mask off setuid
      bits and group access because of potential race-condition security
 
 /* Initial mask on permissions given to temporary files.  Mask off setuid
      bits and group access because of potential race-condition security