When syncing specials, namely pipes and sockets from a Solaris host, rsync -a prints error 22. Remote version is 2.6.3pre1. sk@noether(~/rsnyc/rsync-3.0.6pre1)> ./rsync -a klein:/tmp/xhyjxhy . rsync: mknod "/home/sk/rsnyc/rsync-3.0.6pre1/xhyjxhy" failed: Invalid argument (22) rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1505) [generator=3.0.6pre1] Reason: rsync calls mknod ("filename", ..., 0xffffffff), which Linux rejects, as allowed by POSIX. rsync should clear the third parameter before calling mknod. Suggested patch in syscall.c, do_mknod: 111 #ifdef HAVE_MKNOD 112 if (S_ISSOCK (mode) || S_ISFIFO(mode)) { 113 /* this variable is not ignored by Linux 2.6. */ 114 dev = 0; 115 } 116 >-------return mknod(pathname, mode, dev); 117 #else
Three additional comments: 1. Updating the Solaris side of things to rsync-3.06 does not help. 2. Pushing to instead of pulling from Linux does not help. 3. Reproduce the behaviour with this code#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main () { if (mknod ("test_fifo_fifi", 0777 | S_IFIFO, (dev_t)-1)) { perror ("mknod"); return 1; } unlink ("test_fifo_fifi"); return 0; } This works on Solaris, and does not work on Linux. The Linux docs are not completely clear as to if this should work.
Does Solaris allow mknod("test_fifo_fifi", 0777 | S_IFIFO, (dev_t)0) to work? If so, the fix I'm contemplating is setting rdev to 0 down in flist.c's make_file(): #ifdef HAVE_STRUCT_STAT_ST_RDEV if (IS_DEVICE(st.st_mode)) { tmp_rdev = st.st_rdev; st.st_size = 0; } else if (IS_SPECIAL(st.st_mode)) { tmp_rdev = 0; st.st_size = 0; } #endif I wonder if that would break any OS? Perhaps a safer change would be for that final tmp_rdev assignment to be: tmp_rdev = st.st_rdev == (dev_t)-1 ? 0 : st.st_rdev;
Hi. from Solaris mknod(2): If mode does not indicate a block special or character special device, dev is ignored. Similar prose is in Linux mknod(2), but in the case of Solaris, it is actually true :-) In short, dev=0 works on Linux and Solaris. I'd prefer the fix being in the receiving end of rsync, that is, the one that does the actual mknod. This would maintain compatibility work legacy rsyncs on the remove host. Is make_file on the receiving end? Greetings, Sebastian
Created attachment 4082 [details] Changes to excise rdev use with special files Here's the patch I came up with. It has the following features: - Should avoid the error when talking to an older rsync version, regardless of the direction of transfer. - Makes the transmission of special files a little more efficient (and will be made even more efficient in protocol 31, which is being created for 3.1.0). - Saves memory by not remembering a useless rdev value for special files. I looked at the Linux kernel code, and all the file systems I saw validate that the dev value is a valid device number before figuring out what kind of device/special-file is being created. So, the code above ensures that mknod() should always see a valid device number.
Fix checked into git.
I tried the Git version in all combinations of patched/unpatched and Solaris/Linux. It works beautifully, tough I don't quite see the reason for a protocol change. Thank you very much for your help!