Problem: rsync does not check for exisitence of device file (in backup-dir) before trying to recreate it with mknod using options -b and --backup-dir. Backups all have the following errors when device files are updated rsync: mknod "/dev/pts/111" failed: File exists (17) rsync error: some files could not be transferred (code 23) at main.c(789) Test Script: #!/usr/bin/ksh # # Test rsync backup of device files # ROOT=/tmp/rsync_mknod [[ -d $ROOT ]] || mkdir $ROOT cd $ROOT # Create test dirs for x in src dst backup; do [[ -d $x ]] || mkdir $x [[ -e $x/nod ]] && rm $x/nod [[ -e $x/src/nod ]] && rm $x/src/nod done # Create test device file mknod $ROOT/src/nod c 255 255 chmod 666 $ROOT/src/nod # Initial rsync rsync -a -b --backup-dir=$ROOT/backup $ROOT/src $ROOT/dst # Update file causing backup to be made chmod 440 $ROOT/src/nod rsync -a -b --backup-dir=$ROOT/backup $ROOT/src $ROOT/dst # Update file again, this rsync should have the error chmod 666 $ROOT/src/nod rsync -a -b --backup-dir=$ROOT/backup $ROOT/src $ROOT/dst Patch: * only removes file if it was already a device file --- backup.c.gen Mon Feb 21 17:57:58 2005 +++ backup.c Tue May 31 11:33:30 2005 @@ -171,7 +171,7 @@ * We will move the file to be deleted into a parallel directory tree. */ static int keep_backup(char *fname) { - STRUCT_STAT st; + STRUCT_STAT st, bufst; struct file_struct *file; char *buf; int kept = 0; @@ -190,6 +190,12 @@ /* Check to see if this is a device file, or link */ if (IS_DEVICE(file->mode)) { if (am_root && preserve_devices) { + /* delete backup_dir destination device if it exists */ + if (do_stat(buf, &bufst) == 0 && IS_DEVICE(bufst.st_mode)) { + if (do_unlink(buf) < 0) + rsyserr(FERROR, errno, "unlink %s failed", + full_fname(buf)); + } if (do_mknod(buf, file->mode, file->u.rdev) < 0 && (errno != ENOENT || make_bak_dir(buf) < 0 || do_mknod(buf, file->mode, file->u.rdev) < 0)) {
Yes, this particular problem started in 2.6.4 because prior to that, rsync was failing to backup any updated devices (and apparently symlinks as well). A quick fix would be to try to delete the item in the way in the backup dir, but the backup code is systemically bad at overwriting existing objects (such as replacing a file with a dir or visa versa), so the code really needs some deep surgery.
Created attachment 1264 [details] A partial fix My version of the quick-fix that only deals with removing a device/file/symlink that's in the way of a device or symlink. It also fixes a couple problems in the logic in the code for backing up a device or a symlink. I didn't see any reason to constrain the prior object backed up to being another device when backing up a device, so my code just tries to get rid of anything that's in the way. It will still fail for dir/non-dir mismatches, but that's a deeper problem that has been around for a very long time.
I checked in a fix for this a while back.