--- orig/backup.c 2005-06-10 21:33:27 +++ backup.c 2005-08-30 02:12:53 @@ -30,6 +30,7 @@ extern char *backup_dir; 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; @@ -188,7 +189,8 @@ static int keep_backup(char *fname) 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 --- orig/flist.c 2005-08-17 06:45:07 +++ flist.c 2005-08-30 02:12:54 @@ -48,6 +48,7 @@ extern int preserve_links; 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; @@ -347,16 +348,14 @@ void send_file_entry(struct file_struct 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 (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; @@ -365,7 +364,8 @@ void send_file_entry(struct file_struct 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 @@ -443,7 +443,8 @@ void send_file_entry(struct file_struct 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); @@ -586,14 +587,12 @@ static struct file_struct *receive_file_ 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 (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); @@ -603,7 +602,8 @@ static struct file_struct *receive_file_ 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)) { @@ -673,7 +673,8 @@ static struct file_struct *receive_file_ 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 @@ -921,7 +922,8 @@ skip_filters: 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 --- orig/generator.c 2005-08-17 06:45:07 +++ generator.c 2005-08-30 02:12:54 @@ -38,6 +38,7 @@ extern int relative_paths; 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; @@ -811,7 +812,8 @@ static void recv_generator(char *fname, 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 || (st.st_mode & ~CHMOD_BITS) != (file->mode & ~CHMOD_BITS) || st.st_rdev != file->u.rdev) { @@ -821,7 +823,8 @@ static void recv_generator(char *fname, && 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", --- orig/log.c 2005-06-10 21:33:28 +++ log.c 2005-08-30 02:12:54 @@ -494,12 +494,14 @@ static void log_formatted(enum logcode c : !(iflags & ITEM_TRANSFER) ? '.' : !local_server && *op == 's' ? '<' : '>'; n[1] = S_ISDIR(file->mode) ? 'd' + : IS_SPECIAL(file->mode) ? 's' : IS_DEVICE(file->mode) ? 'D' : S_ISLNK(file->mode) ? 'L' : 'f'; n[2] = !(iflags & ITEM_REPORT_CHECKSUM) ? '.' : 'c'; n[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's'; n[4] = !(iflags & ITEM_REPORT_TIME) ? '.' : !preserve_times || IS_DEVICE(file->mode) + || IS_SPECIAL(file->mode) || S_ISLNK(file->mode) ? 'T' : 't'; n[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p'; n[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o'; --- orig/options.c 2005-09-03 15:44:52 +++ options.c 2005-08-30 02:12:54 @@ -45,6 +45,7 @@ int preserve_links = 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; @@ -286,7 +287,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," -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," -S, --sparse handle sparse files efficiently\n"); @@ -397,9 +400,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 }, - {"devices", 'D', POPT_ARG_VAL, &preserve_devices, 1, 0, 0 }, + {0, 'D', POPT_ARG_NONE, 0, '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-D", 0, POPT_ARG_VAL, &preserve_devices, 0, 0, 0 }, +/* "no-D" is a popt alias */ + {"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 }, @@ -714,6 +720,19 @@ int parse_arguments(int *argc, const cha /* The context leaks in case of an error, but if there's a * problem we always exit anyhow. */ pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_options, 0); + { + struct poptAlias my_alias; + char **argv = new_array(char *, 3); + if (!argv + || !(argv[0] = strdup("--no-devices")) + || !(argv[1] = strdup("--no-specials"))) + out_of_memory("popt aliases"); + argv[2] = NULL; + my_alias.longName = "no-D", my_alias.shortName = '\0'; + my_alias.argc = 2; + my_alias.argv = (const char **)argv; + poptAddAlias(pc, my_alias, 0); + } poptReadDefaultConfig(pc, 0); while ((opt = poptGetNextOpt(pc)) != -1) { @@ -827,6 +846,11 @@ int parse_arguments(int *argc, const cha preserve_gid = 1; preserve_uid = 1; preserve_devices = 1; + preserve_specials = 1; + break; + + case 'D': + preserve_devices = preserve_specials = 1; break; case 'h': @@ -1353,7 +1377,7 @@ void server_options(char **args,int *arg 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'; @@ -1392,6 +1416,12 @@ void server_options(char **args,int *arg if (list_only > 1) args[ac++] = "--list-only"; + /* Note: sending "--devices" would not be backward-compatible. */ + if (preserve_devices && !preserve_specials) + args[ac++] = "--no-specials"; /* -D is already set. */ + else if (preserve_specials && !preserve_devices) + 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) { --- orig/rsync.h 2005-08-17 06:45:08 +++ rsync.h 2005-08-30 02:12:55 @@ -786,7 +786,8 @@ extern int errno; #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 --- orig/rsync.yo 2005-09-03 15:44:53 +++ rsync.yo 2005-08-30 02:12:56 @@ -321,7 +321,9 @@ to the detailed description below for a -p, --perms preserve permissions -o, --owner preserve owner (root only) -g, --group preserve group - -D, --devices preserve devices (root only) + --devices preserve device files (root only) + --specials preserve special files + -D same as --devices --specials -t, --times preserve times -O, --omit-dir-times omit directories when preserving times -S, --sparse handle sparse files efficiently @@ -681,10 +683,15 @@ receiver is a member of will be preserve is done by name, but may fall back to using the ID number in some circumstances. See the bf(--numeric-ids) option for a full discussion. -dit(bf(-D, --devices)) This option causes rsync to transfer character and +dit(bf(--devices)) This option causes rsync to transfer character and block device information to the remote system to recreate these devices. This option is only available to the super-user. +dit(bf(--specials)) This option causes rsync to transfer special files +such as named sockets and fifos. + +dit(bf(-D)) The bf(-D) option is equivalent to bf(--devices) bf(--specials). + dit(bf(-t, --times)) This tells rsync to transfer modification times along with the files and update them on the remote system. Note that if this option is not used, the optimization that excludes files that have not been