summaryrefslogtreecommitdiff
path: root/src/btrfs-utils
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2017-03-29 22:50:05 -0400
committerAndrew Cady <d@jerkface.net>2017-03-29 22:50:30 -0400
commitb30a2be0105bae41479e518711364a4ae21fbcbd (patch)
tree857c96f118541671d2ad18572bc54491818e53f6 /src/btrfs-utils
parent0ec9e1b2b1f4c08d8588f9cfe01712c34a6eb8ab (diff)
split btrfs-shrink out of btarfs
Diffstat (limited to 'src/btrfs-utils')
-rwxr-xr-xsrc/btrfs-utils/btarfs105
-rwxr-xr-xsrc/btrfs-utils/btrfs-shrink52
-rwxr-xr-xsrc/btrfs-utils/with-btrfs-seed99
3 files changed, 256 insertions, 0 deletions
diff --git a/src/btrfs-utils/btarfs b/src/btrfs-utils/btarfs
new file mode 100755
index 0000000..a51b2ef
--- /dev/null
+++ b/src/btrfs-utils/btarfs
@@ -0,0 +1,105 @@
1#!/bin/sh
2
3die() { printf "%s: Error: %s\n" "$0" "$*" >&2; exit 1; }
4
5[ "$(id -u)" = 0 ] || die 'you are not root'
6
7TEMP="$(getopt -o 'f:vcxz' --long size:,file:,create,extract,gzip,gunzip,ungzip -n "$0" -- "$@")" ||
8 die 'getopt error'
9eval set -- "$TEMP"
10
11MIN_BYTES=$((128 * 1024 * 1024))
12
13FILE=
14MODE=
15ZIP=y
16BYTES=$((256 * 1024 * 1024))
17while [ $# -gt 0 ]; do
18 case "$1" in
19 --size)
20 BYTES=$(( $2 * 1024 * 1024))
21 [ "$BYTES" -ge "$MIN_BYTES" ] || die "invalid size (too small or not a number)"
22 SIZE="$2"
23 shift 2 ;;
24 -f|--file)
25 [ "$FILE" ] && die "only one archive file can be specified"
26 FILE="$2"
27 shift 2 ;;
28 -c|--create)
29 [ "$MODE" ] && die "incompatible modes"
30 MODE=create
31 shift ;;
32 -x|--extract)
33 [ "$MODE" ] && die "incompatible modes"
34 MODE=extract
35 shift ;;
36 -v)
37 VERBOSE=y
38 shift ;;
39 -z|--gzip|--gunzip|--ungzip)
40 ZIP=y
41 shift ;;
42 --)
43 shift; break;;
44 *) die 'getopt error';;
45 esac
46done
47[ "$FILE" ] || die "you must specify a file (this is not tar, there is no stdout)"
48
49create()
50{
51 TMPFILE=$(dirname "$FILE")/.~.$(basename "$FILE")
52# [ ! -e "$FILE" ] || die "refusing to overwrite '$FILE'"
53# [ ! -e "$TMPFILE" ] || die "refusing to overwrite '.~.$FILE'"
54 rm -f "$TMPFILE"
55 fallocate -l "$BYTES" "$TMPFILE"
56 mountpoint=$(mktemp -d) || die
57 trap 'umount "$mountpoint"; rmdir "$mountpoint"; rm "$TMPFILE"' EXIT
58 mkfs.btrfs "$TMPFILE" || die
59 mount -o ${ZIP:+compress,}loop "$TMPFILE" "$mountpoint" || die
60 rsync -a ${VERBOSE:+ -i} "$@" "$mountpoint" || die
61
62 shrink "$mountpoint"
63 umount "$mountpoint" || die
64 btrfs_truncate "$TMPFILE"
65
66 rmdir "$mountpoint"
67 btrfstune -S1 "$TMPFILE" || die
68 mv "$TMPFILE" "$FILE"
69 trap '' EXIT
70}
71
72btrfs_truncate()
73{
74 local img="$1" bytes
75 bytes=$(file "$img" | sed -ne 's?.*/\([0-9]*\) bytes used.*?\1?p')
76 if [ "$bytes" ]; then
77 truncate -s "$bytes" "$img"
78 fi
79}
80
81
82get_k()
83{
84 local mountpoint="$1" kilos
85 kilos=$(btrfs fi usage -k "$mountpoint"|sed -ne 's/[\t ]*Device size:[\t ]*//p')
86 case "$kilos" in
87 *.00KiB) echo "${kilos%.00KiB}";;
88 *) return 1;;
89 esac
90}
91
92shrink()
93{
94 shrinkmegs=100
95 while true; do
96 while ! btrfs filesystem resize -${shrinkmegs}M "$mountpoint"/; do
97 shrinkmegs=$((shrinkmegs - 10 ))
98 if [ $shrinkmegs -lt 10 ]; then
99 return
100 fi
101 done
102 done
103}
104
105$MODE "$@"
diff --git a/src/btrfs-utils/btrfs-shrink b/src/btrfs-utils/btrfs-shrink
new file mode 100755
index 0000000..f3dbbb0
--- /dev/null
+++ b/src/btrfs-utils/btrfs-shrink
@@ -0,0 +1,52 @@
1#!/bin/sh
2
3die() { printf "%s: Error: %s\n" "$0" "$*" >&2; exit 1; }
4
5[ "$(id -u)" = 0 ] || die 'you are not root'
6
7shrink()
8{
9 shrinkmegs=100
10 while true; do
11 while ! btrfs filesystem resize -${shrinkmegs}M "$mountpoint"/; do
12 shrinkmegs=$((shrinkmegs - 10 ))
13 if [ $shrinkmegs -lt 10 ]; then
14 return
15 fi
16 done
17 done
18}
19
20btrfs_truncate()
21{
22 local img="$1" bytes
23 bytes=$(file "$img" | sed -ne 's?.*/\([0-9]*\)/[0-9]* bytes used.*?\1?p')
24# 548044800/1176715264 bytes used
25 if [ "$bytes" ]; then
26 truncate -s "$bytes" "$img"
27 fi
28}
29
30main()
31{
32 if [ -d "$1" ]; then
33 mountpoint -q "$1" || die "not a mountpoint: $1"
34 shrink "$1"
35 elif [ -f "$1" ]; then
36 mkdir "$1".mnt.tmp
37 mount -t btrfs "$1" "$1".mnt.tmp
38 result=$?
39 if [ $result = 0 ]; then
40 shrink "$1".mnt.tmp
41 result=$?
42 fi
43 umount "$1".mnt.tmp
44 rmdir "$1".mnt.tmp
45 btrfs_truncate "$1"
46 return $result
47 else
48 die "not a file or directory: $1"
49 fi
50}
51
52main "$@"
diff --git a/src/btrfs-utils/with-btrfs-seed b/src/btrfs-utils/with-btrfs-seed
new file mode 100755
index 0000000..637af5a
--- /dev/null
+++ b/src/btrfs-utils/with-btrfs-seed
@@ -0,0 +1,99 @@
1#!/bin/sh
2
3usage()
4{
5 cat >&2 <<EOF
6usage: $0 [options] <file.iso> [command] [args ...]
7
8 options:
9 --resize <size>
10 --btrfs-options <mount options> (default: compress)
11 --no-chroot
12EOF
13 exit $1
14}
15
16error()
17{
18 printf '%s: Error: %s\n' "$0" "$*" >&2
19 exit 1
20}
21
22warning()
23{
24 printf '%s: Warning: %s\n' "$0" "$*" >&2
25}
26
27have_root()
28{
29 [ "$(id -u)" = 0 ]
30}
31
32main()
33{
34 have_root || error "you are not root"
35
36 iso_file=$1
37 shift
38
39 iso_file_clone=${iso_file}.clone.tmp
40 mountpoint=${iso_file%.iso}.mnt.tmp
41
42 [ -f "$iso_file" ] || error "not a file: $iso_file"
43 [ ! -f "$iso_file_clone" ] || error "refusing to clobber existing file: $iso_file_clone"
44 [ -d "$mountpoint" ] || mkdir "$mountpoint" || error "could not create directory $mountpoint"
45 ! mountpoint -q "$mountpoint" || error "directory is already a mountpoint: $mountpoint"
46
47 cp --reflink=always "$iso_file" "$iso_file_clone" || error "cp failed"
48 trap 'rm -f "$iso_file_clone"' EXIT
49
50 if [ "$RESIZE" ]; then
51 truncate --size="$RESIZE" "$iso_file_clone" || error "failed to resize image with truncate"
52 fi
53
54 btrfstune -f -S 0 "$iso_file_clone" 2>/dev/null || error "btrfstune failed"
55 mount_options=rw,loop${BTRFS_OPTIONS:+,$BTRFS_OPTIONS}
56 mount -o "$mount_options" "$iso_file_clone" "$mountpoint" || error "failed to mount $iso_file"
57
58 if [ "$RESIZE" ]; then
59 btrfs filesystem resize max "$mountpoint" || error "btrfs filesystem resize"
60 fi
61
62 if [ "$CHROOT" ]; then
63 chroot "$mountpoint" "$@"
64 else
65 "$@" "$mountpoint"
66 fi
67 result=$?
68 umount "$mountpoint" || warning "umount $mountpoint failed! You had better do something about it"
69 rmdir "$mountpoint"
70 if [ "$result" = 0 ]; then
71 btrfstune -S 1 "$iso_file_clone" || error "btrfstune failed. The original ISO is unmodified."
72 mv "$iso_file_clone" "$iso_file"
73 else
74 warning "The command executed within the chroot failed. The original ISO is unmodified."
75 rm "$iso_file_clone"
76 fi
77}
78
79[ $# = 0 ] && usage 0
80
81CHROOT=y
82eval set -- "$(getopt -o '' --long shrink,no-chroot,resize:,fork:,btrfs-options: -n "$0" -- "$@")" || error 'getopt error'
83while [ $# -gt 0 ]; do
84 case "$1" in
85 --) shift; break;;
86 --resize) RESIZE=$2; shift 2;;
87 --fork) FORK=$2; shift 2;;
88 --btrfs-options) BTRFS_OPTIONS=$2; shift 2;;
89 --no-chroot) CHROOT=; shift;;
90 --shrink) SHRINK=y; shift;;
91 *) error "unrecognized option: $1"
92 esac
93done
94
95: ${BTRFS_OPTIONS:=compress}
96
97[ "$FORK" ] && error "unimplemented option: --fork"
98
99main "$@"