Tuesday 5 February 2008

Vista reparse shenanigans with rsync

As part of my backup script overhaul, I have switched to using rsync. The main reason is I now have to support Windows XP, Vista, Linux and maybe Mac in future; and I don't fancy re-doing all this backup stuff each time.

The good news first: rsync works a treat on Linux (well duh!) and XP (via cygwin). I was extremely happy with how easy to configure and quick to run the Linux and XP backup's were. But it seems I was fooled into a false sense of security...

I tried running exactly the same rsync script (that worked on XP) on Vista and was greeted with a slew of errors, the most confusing being:
rsync: /cygdrive/X/your-file-here: Permission denied (13)
Initially I thought it was the old Vista UAC playing up. But I confirmed that I had disabled UAC. The "permission denied" in this case, was a red herring. The real problem was the reparse points. These little symbolic links are available in XP, but not used much. But in Vista they really went to town, and scattered them all about the file system like the Easter Bunny hiding eggs.

rsync (well more likely the way it works with cygwin) is not too happy about reparse points, and after more careful inspection of my "Permission denied" errors, it turns out they were all on reparse points.

My hack to get around this is pretty simple. The backup script, just before running rsync, generates a list of all the reparse points and tells rsync to exclude them. Thus rsync never encounters a scary directory it doesn't know how to deal with.


VER | findstr /i "6.0.6000" > nul
IF %ERRORLEVEL% EQU 0 GOTO backup_vista

...rest of script...


backup_vista:
REM (dir) build a list of all the reparse directories
REM (sed) swap around the path separators

REM append to a file to use in rsync

dir c:\Users /A:LD /S /B | sed "s/c\:\\/\//;s/\\/\//g" >> exclude.local.list

dir c:\ProgramData /A:LD /S /B | sed "s/c\:\\/\//;s/\\/\//g" >> exclude.local.list
rsync options --exclude-from=exclude.local.list /cygdrive/c/ destination
...rest of script...


It's not pretty, but (to quote Mr C. Monster) "it's good enough for me".

For bonus points, you could keep a copy of the reparse point list, and for a restore resurrect them all. I don't need this.