|
|
@@ -0,0 +1,108 @@
|
|
|
+#!/usr/bin/env bash
|
|
|
+
|
|
|
+overlaycached(){
|
|
|
+ set -e
|
|
|
+
|
|
|
+ MOVE=false
|
|
|
+ SSHFS=""
|
|
|
+ DEPTH=1
|
|
|
+ while getopts ":dmS:D:-" opt; do
|
|
|
+ case $opt in
|
|
|
+ d )
|
|
|
+ DEBUG=true
|
|
|
+ ;;
|
|
|
+ m )
|
|
|
+ MOVE=true
|
|
|
+ ;;
|
|
|
+ S )
|
|
|
+ SSHFS="$OPTARG"
|
|
|
+ ;;
|
|
|
+ D )
|
|
|
+ DEPTH="$OPTARG"
|
|
|
+ ;;
|
|
|
+ - )
|
|
|
+ break
|
|
|
+ ;;
|
|
|
+ \? ) cat 1>&2 <<'USAGEEOF'
|
|
|
+
|
|
|
+Usage: <sharxz> [-d] [ -D DEPTH ] [-m | -S SSHFS | LOWER_DIR ] [ UPPER_DIR ] [ MOUNT_DIR ]
|
|
|
+-d DEBUG
|
|
|
+-D DEPTH=1 depth of inotify directory watches
|
|
|
+-S SSHFS mount sshfs for LOWER_DIR
|
|
|
+-m MOVE move MOUNT_DIR to another mount point and mount overlay
|
|
|
+-- stop parsing and pass remaining arguments
|
|
|
+
|
|
|
+USAGEEOF
|
|
|
+ exit 1
|
|
|
+ ;;
|
|
|
+ : )
|
|
|
+ echo "Invalid option: $OPTARG requires an argument" 1>&2
|
|
|
+ exit 1
|
|
|
+ ;;
|
|
|
+ esac
|
|
|
+ done
|
|
|
+ shift $((OPTIND -1))
|
|
|
+
|
|
|
+ $MOVE ||
|
|
|
+ [ -z "$SSHFS" ] &&
|
|
|
+ LOWER_DIR="$1" && shift 1
|
|
|
+ UPPER_DIR="$1"
|
|
|
+ MOUNT_DIR="$2"
|
|
|
+ WORK_DIR="$(realpath "$UPPER_DIR").work"
|
|
|
+ mkdir -p "$WORK_DIR"
|
|
|
+ CLEANUP_DIRS=(
|
|
|
+ "$WORK_DIR"
|
|
|
+ )
|
|
|
+ if $MOVE; then
|
|
|
+ LOWER_DIR="$(mktemp -d)"
|
|
|
+ CLEANUP_DIRS+=( "$LOWER_DIR" )
|
|
|
+ set -x
|
|
|
+ mount --move "$MOUNT_DIR" "$LOWER_DIR"
|
|
|
+ set +x
|
|
|
+ elif [ ! -z "$SSHFS" ]; then
|
|
|
+ LOWER_DIR="$(mktemp -d)"
|
|
|
+ CLEANUP_DIRS+=( "$LOWER_DIR" )
|
|
|
+ set -x
|
|
|
+ sshfs "$SSHFS" "$LOWER_DIR"
|
|
|
+ set +x
|
|
|
+ fi
|
|
|
+ show_workdir_contents
|
|
|
+
|
|
|
+ trap cleanup EXIT
|
|
|
+ set -x
|
|
|
+ mount -t overlay -o lowerdir="$LOWER_DIR",upperdir="$UPPER_DIR",workdir="$WORK_DIR" overlay "$MOUNT_DIR"
|
|
|
+ set +x
|
|
|
+ inotify_cmd $MOUNT_DIR |while read DIR EVT FILE;
|
|
|
+ do
|
|
|
+ echo "$DIR $EVT $FILE"
|
|
|
+ [[ "$EVT" =~ "ISDIR" ]] && continue
|
|
|
+ RELPATH="$(realpath --relative-to=$MOUNT_DIR $DIR)/$FILE"
|
|
|
+ [ ! -f "$UPPER_DIR/$RELPATH" ] && {
|
|
|
+ mkdir -p "$(dirname $UPPER_DIR/$RELPATH)"
|
|
|
+ cp -a "$LOWER_DIR/$RELPATH" "$UPPER_DIR/$RELPATH"
|
|
|
+ sync && mount -o remount "$MOUNT_DIR"
|
|
|
+ }
|
|
|
+ done
|
|
|
+}
|
|
|
+cleanup(){
|
|
|
+ umount "$MOUNT_DIR" 2> /dev/null
|
|
|
+ if $MOVE; then
|
|
|
+ mount --move "$LOWER_DIR" "$MOUNT_DIR"
|
|
|
+ fi
|
|
|
+ if [ -z "$SSHFS" ]; then
|
|
|
+ umount "$LOWER_DIR" 2> /dev/null
|
|
|
+ fi
|
|
|
+ for DIR in ${CLEANUP_DIRS[@]}; do
|
|
|
+ rm -rf "$DIR"
|
|
|
+ done
|
|
|
+}
|
|
|
+show_workdir_contents(){
|
|
|
+ (cd $WORK_DIR;pwd; ls -alsh)
|
|
|
+}
|
|
|
+inotify_cmd(){
|
|
|
+ inotifywait -m -e close_nowrite $(find_dirs $1)
|
|
|
+}
|
|
|
+find_dirs(){
|
|
|
+ find "$1" -maxdepth "$DEPTH" -type d
|
|
|
+}
|
|
|
+overlaycached "$@"
|