Bug 2758 - "File exists" error using options -b and --backup-dir with device files.
Summary: "File exists" error using options -b and --backup-dir with device files.
Alias: None
Product: rsync
Classification: Unclassified
Component: core (show other bugs)
Version: 2.6.4
Hardware: All AIX
: P3 normal (vote)
Target Milestone: ---
Assignee: Wayne Davison
QA Contact: Rsync QA Contact
Depends on:
Reported: 2005-05-31 12:54 UTC by jonathan.townsend
Modified: 2006-03-12 02:56 UTC (History)
0 users

See Also:

A partial fix (1.80 KB, patch)
2005-06-07 10:56 UTC, Wayne Davison
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description jonathan.townsend 2005-05-31 12:54:43 UTC

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:

# Test rsync backup of device files

[[ -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

# 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


* 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)) {
Comment 1 Wayne Davison 2005-06-07 10:49:57 UTC
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
Comment 2 Wayne Davison 2005-06-07 10:56:38 UTC
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.
Comment 3 Wayne Davison 2005-07-15 12:12:17 UTC
I checked in a fix for this a while back.