#!/bin/bash

# rsync bug demo
# rsyncd clips trims relative symlinks outside of source tree

# Usage:
#   -r copy from client to server (reverse), otherwise server to client
#   -f do the copy, otherwise just a --dry-run

comment="
# On rsync server
cd
mkdir testrsync
cd testrsync
# create symlink outside of tree
ln -s '../foo'

# /etc/rsyncd.conf
[testrsync]
       path = /home/chris/testrsync
       read only = no
       list = yes
       uid = chris
       gid = users
       #auth users = username
       #secrets file = /etc/rsyncd.scrt
       munge symlinks = no
       use chroot = no

# On client
cd
mkdir testrsync

% rsync --version
rsync  version 3.1.3  protocol version 31

% cd; bash testrsync.sh -f
receiving incremental file list
./
foo -> ../foo
# symlink is preserved server -> client, still '../foo'

% cd; bash testrsync.sh -r
sending incremental file list
foo -> ../foo
# Why is it copying? The file has not been changed?

% cd; bash testrsync.sh -rf
sending incremental file list
foo -> ../foo
# Client claims to be copying correctly but the server clips the leading '../' leaving only a simlink to 'foo'

% cd; bash testrsync.sh
receiving incremental file list
foo -> foo
# File comes back to us with leading '../' clipped.

# How do I get the client to server copy to stop trimming symlinks outside of the tree?
"

_o_dry='--dry-run'
_o_rev=0

while getopts 'rfdu' opt; do
  case "${opt}" in
    r) _o_rev=1;;
    f) _o_dry='';;
  esac
done

_opts=()
_cmds=('rsync://128.0.0.206/testrsync/' 'testrsync/')
if [ "${_o_rev}" -ne 0 ]; then
  _test="${_cmds[0]}"; _cmds[0]="${_cmds[1]}"; _cmds[1]="${_test}"
  unset test
fi

rsync ${_o_dry} -av "${_cmds[@]}"
