From b5917e4b9b92d86b773ec4f4fd7f3a3a2d3790c1 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sat, 30 Apr 2016 00:27:11 -0400 Subject: add btarfs --- src/btarfs | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100755 src/btarfs (limited to 'src') diff --git a/src/btarfs b/src/btarfs new file mode 100755 index 0000000..bdd44de --- /dev/null +++ b/src/btarfs @@ -0,0 +1,105 @@ +#!/bin/sh + +die() { printf "%s: Error: %s\n" "$0" "$*" >&2; exit 1; } + +[ "$(id -u)" = 0 ] || die 'you are not root' + +TEMP="$(getopt -o 'f:vcxz' --long size:,file:,create,extract,gzip,gunzip,ungzip -n "$0" -- "$@")" || + die 'getopt error' +eval set -- "$TEMP" + +MIN_BYTES=$((128 * 1024 * 1024)) + +FILE= +MODE= +ZIP=y +BYTES=$((256 * 1024 * 1024)) +while [ $# -gt 0 ]; do + case "$1" in + --size) + BYTES=$(( $2 * 1024 * 1024)) + [ "$BYTES" -ge "$MIN_BYTES" ] || die "invalid size (too small or not a number)" + SIZE="$2" + shift 2 ;; + -f|--file) + [ "$FILE" ] && die "only one archive file can be specified" + FILE="$2" + shift 2 ;; + -c|--create) + [ "$MODE" ] && die "incompatible modes" + MODE=create + shift ;; + -x|--extract) + [ "$MODE" ] && die "incompatible modes" + MODE=extract + shift ;; + -v) + VERBOSE=y + shift ;; + -z|--gzip|--gunzip|--ungzip) + ZIP=y + shift ;; + --) + shift; break;; + *) die 'getopt error';; + esac +done +[ "$FILE" ] || die "you must specify a file (this is not tar, there is no stdout)" + +create() +{ + TMPFILE=.~."$FILE" +# [ ! -e "$FILE" ] || die "refusing to overwrite '$FILE'" +# [ ! -e "$TMPFILE" ] || die "refusing to overwrite '.~.$FILE'" + rm -f "$TMPFILE" + fallocate -l "$BYTES" "$TMPFILE" + mountpoint=$(mktemp -d) || die + trap 'umount "$mountpoint"; rmdir "$mountpoint"; rm "$TMPFILE"' EXIT + mkfs.btrfs "$TMPFILE" || die + mount -o ${ZIP:+compress,}loop "$TMPFILE" "$mountpoint" || die + rsync -a ${VERBOSE:+ -i} "$@" "$mountpoint" || die + + shrink "$mountpoint" + umount "$mountpoint" || die + btrfs_truncate "$TMPFILE" + + rmdir "$mountpoint" + btrfstune -S1 "$TMPFILE" || die + mv "$TMPFILE" "$FILE" + trap '' EXIT +} + +btrfs_truncate() +{ + local img="$1" bytes + bytes=$(file "$img" | sed -ne 's?.*/\([0-9]*\) bytes used.*?\1?p') + if [ "$bytes" ]; then + truncate -s "$bytes" "$img" + fi +} + + +get_k() +{ + local mountpoint="$1" kilos + kilos=$(btrfs fi usage -k "$mountpoint"|sed -ne 's/[\t ]*Device size:[\t ]*//p') + case "$kilos" in + *.00KiB) echo "${kilos%.00KiB}";; + *) return 1;; + esac +} + +shrink() +{ + shrinkmegs=100 + while true; do + while ! btrfs filesystem resize -${shrinkmegs}M "$mountpoint"/; do + shrinkmegs=$((shrinkmegs - 10 )) + if [ $shrinkmegs -lt 10 ]; then + return + fi + done + done +} + +$MODE "$@" -- cgit v1.2.3