summaryrefslogtreecommitdiff
path: root/src/btrfs-utils/with-btrfs-seed
blob: 637af5aadb93726a58d0ab940ceb3057a2bd3863 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/bin/sh

usage()
{
    cat >&2 <<EOF
usage: $0 [options] <file.iso> [command] [args ...]

    options:
        --resize <size>
        --btrfs-options <mount options>     (default: compress)
        --no-chroot
EOF
    exit $1
}

error()
{
    printf '%s: Error: %s\n' "$0" "$*" >&2
    exit 1
}

warning()
{
    printf '%s: Warning: %s\n' "$0" "$*" >&2
}

have_root()
{
    [ "$(id -u)" = 0 ]
}

main()
{
    have_root || error "you are not root"

    iso_file=$1
    shift

    iso_file_clone=${iso_file}.clone.tmp
    mountpoint=${iso_file%.iso}.mnt.tmp

    [ -f "$iso_file" ]                                        || error "not a file: $iso_file"
    [ ! -f "$iso_file_clone" ]                                || error "refusing to clobber existing file: $iso_file_clone"
    [ -d "$mountpoint" ] || mkdir "$mountpoint"               || error "could not create directory $mountpoint"
    ! mountpoint -q "$mountpoint"                             || error "directory is already a mountpoint: $mountpoint"

    cp --reflink=always "$iso_file" "$iso_file_clone"         || error "cp failed"
    trap 'rm -f "$iso_file_clone"' EXIT

    if [ "$RESIZE" ]; then
        truncate --size="$RESIZE" "$iso_file_clone"           || error "failed to resize image with truncate"
    fi

    btrfstune -f -S 0 "$iso_file_clone" 2>/dev/null           || error "btrfstune failed"
    mount_options=rw,loop${BTRFS_OPTIONS:+,$BTRFS_OPTIONS}
    mount -o "$mount_options" "$iso_file_clone" "$mountpoint" || error "failed to mount $iso_file"

    if [ "$RESIZE" ]; then
        btrfs filesystem resize max "$mountpoint"             || error "btrfs filesystem resize"
    fi

    if [ "$CHROOT" ]; then
        chroot "$mountpoint" "$@"
    else
        "$@" "$mountpoint"
    fi
    result=$?
    umount "$mountpoint" || warning "umount $mountpoint failed!  You had better do something about it"
    rmdir "$mountpoint"
    if [ "$result" = 0 ]; then
        btrfstune -S 1 "$iso_file_clone" || error "btrfstune failed.  The original ISO is unmodified."
        mv "$iso_file_clone" "$iso_file"
    else
        warning "The command executed within the chroot failed.  The original ISO is unmodified."
        rm "$iso_file_clone"
    fi
}

[ $# = 0 ] && usage 0

CHROOT=y
eval set -- "$(getopt -o '' --long shrink,no-chroot,resize:,fork:,btrfs-options: -n "$0" -- "$@")" || error 'getopt error'
while [ $# -gt 0 ]; do
    case "$1" in
        --) shift; break;;
        --resize) RESIZE=$2; shift 2;;
        --fork) FORK=$2; shift 2;;
        --btrfs-options) BTRFS_OPTIONS=$2; shift 2;;
        --no-chroot) CHROOT=; shift;;
        --shrink) SHRINK=y; shift;;
        *) error "unrecognized option: $1"
    esac
done

: ${BTRFS_OPTIONS:=compress}

[ "$FORK" ] && error "unimplemented option: --fork"

main "$@"