--- /dev/null
+#!/bin/bash
+
+: Usage: zfs-backup [filesystem] [destination_pool]
+
+tmpdir="/export/home/tmp"
+
+lockdir="/tmp/zfs-admin-lock"
+if ! mkdir "$lockdir" >/dev/null 2>&1; then
+ echo >&2 "ZFS admin lock directory is present."
+ exit 1
+fi
+
+cleanup() { rm -rf "$lockdir"; }
+trap cleanup EXIT
+
+fs=$1
+sourcepool=${1%%/*}
+fsname=${1#*/}
+destinationpool=$2
+
+if ! zpool list -H "$sourcepool" >/dev/null 2>&1; then
+ echo >&2 "The source pool, '$sourcepool' doesn't seem to exist."
+ exit 1
+fi
+
+if ! zpool list -H "$destinationpool" >/dev/null 2>&1; then
+ echo >&2 "The destination pool, '$destinationpool' doesn't seem to exist."
+ exit 1
+fi
+
+if ! zfs list -H "$fs" >/dev/null 2>&1; then
+ echo >&2 "The source filesytem, '$fs' doesn't seem to exist."
+ exit 1
+fi
+
+printsnaps() {
+sed 's,.*/,,' | awk '{print $1}'
+}
+
+zfs list -rH -t snapshot $sourcepool/$fsname | printsnaps > /tmp/source-list
+zfs list -rH -t snapshot $destinationpool/$fsname | printsnaps > /tmp/destination-list
+diff -u /tmp/source-list /tmp/destination-list | grep -v '^+++' | awk '/^\+/ {print}' | sed "s,^\+,$destinationpool/," > /tmp/obsolete-snapshots
+rm -f /tmp/source-list /tmp/destination-list
+
+echo >&2 "Removing obsolete backups from the destination pool"
+for snapshot in $(cat /tmp/obsolete-snapshots); do
+ echo >&2 "Removing '$snapshot' from destination."
+ zfs destroy "$snapshot"
+done
+
+echo >&2 "Rolling back to the most recent snapshot on the destination."
+zfs rollback $(zfs list -rH -t snapshot $destinationpool/$fsname | awk '{snap=$1} END {print snap}')
+
+echo >&2 "Calculating the most recent common snapshot between the two filesystems."
+common=""
+if zfs list -H "$destinationpool/$fsname" >/dev/null 2>&1; then
+ for snap in $(zfs list -rH -t snapshot "$destinationpool/$fsname" |
+ sed 's,.*@,,' | awk '{print$1}'); do
+ if zfs list -rH -t snapshot "$fs" | sed 's,.*@,,' | awk '{print$1}' | grep "^${snap}$" >/dev/null 2>&1; then
+ common=$snap
+ fi
+ done
+fi
+
+base=$common
+foundcommon=false
+if [ -z "$common" ]; then
+ foundcommon=true
+fi
+
+for snap in $(zfs list -rH -t snapshot "$fs" |
+ sed 's,.*@,,' | awk '{print$1}'); do
+ if [ "$snap" = "$common" ]; then
+ foundcommon=true
+ continue
+ fi
+
+ if $foundcommon; then
+ if [ -z "$base" ]; then
+ echo >&2 "Sending '$1/$snap'"
+ zfs send "$1@$snap" > $tmpdir/zfs.part
+ mv $tmpdir/zfs.part $tmpdir/zfs.data
+ zfs recv "$destinationpool/$fsname" < $tmpdir/zfs.data
+ rm -f $tmpdir/zfs.data
+ zfs set readonly=on "$destinationpool"
+ zfs set atime=off "$destinationpool"
+ zfs set sharenfs=off "$destinationpool"
+ zfs set mountpoint=legacy "$destinationpool"
+ zfs unmount "$destinationpool/$fsname"
+ zfs rollback "$destinationpool/$fsname@$snap"
+ else
+ echo >&2 "Sending '$1@$base' -> '$1/$snap'"
+ zfs send -i "$1@$base" "$1@$snap" > $tmpdir/zfs.part
+ mv $tmpdir/zfs.part $tmpdir/zfs.data
+ zfs recv "$destinationpool/$fsname" < $tmpdir/zfs.data
+ rm -f $tmpdir/zfs.data
+ # zfs unmount "$destinationpool/$fsname"
+ # zfs rollback "$destinationpool/$fsname@$snap"
+ fi
+ base=$snap
+ fi
+done
+
+true