summaryrefslogtreecommitdiff
path: root/other/shrink2fs_partition
blob: 2674158b8d471fe827bc7461817e3fec5cba5132 (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
#!/bin/sh
DEPENDENCIES='tune2fs parted lsblk blkid'
READ_ONLY=y

die()
{
    echo "Error: $*" >&2
    exit 1
}

parted()
{
    if [ "$READ_ONLY" ]
    then
	echo parted "$@"
    else
	(set -x; command parted "$@")
    fi
}

check_deps()
{
    for dep in $DEPENDENCIES
    do
	command -v "$dep" >/dev/null || die "Missing dependency: $dep"
    done
}

filesystem_size() 
{ 
    [ "$1" ] || return
    fstype=$(blkid -o value -s TYPE "$1") || die "blkid could not determine FS type"
    case "$fstype" in
	ext[234]) filesystem_size_e2fs "$1";;
	*) die "Unsupported filesystem type: $FSTYPE";;
    esac
}

filesystem_size_e2fs() 
{ 
    tune2fs -l "$1" | { 
	unset block_count block_size
        while read line
       	do
            case "$line" in 
                'Block count:'*) block_count=${line#*:} ;;
                'Block size:'*) block_size=${line#*:} ;;
            esac
        done
	[ "$block_count" -a "$block_size" ] || return
        echo $((block_count * block_size))
    }
}

get_block_device_names() # Outputs: $PARTNAME $DEVNAME
{
    [ -b "$1" ] || die "Not a block device: $1"
    PARTNAME=/dev/$(lsblk -no KNAME "$1") || die "lsblk failed to get kernel device name for $1"

    [ -b "$PARTNAME" ] || die "Not a block device: $PARTNAME"
    DEVNAME=/dev/$(lsblk -no PKNAME "$PARTNAME") || die "lsblk failed to get parent device name for $PARTNAME"

    [ -b "$DEVNAME" ] || die "Not a block device: $DEVNAME"
}

shrink_partition()
{
    get_block_device_names "$1"
    partnum=${PARTNAME#$DEVNAME}
    [ "$PARTNAME" = "$DEVNAME$partnum" ] || die "Cannot compute partition number; (partname, devname) = ($PARTNAME, $DEVNAME)"

    partsize=$(filesystem_size "$PARTNAME") || die "Failed to obtain fs size"
    parted "$DEVNAME" resizepart "$partnum" $((partsize))B
}

check_deps

shrink_partition "$1"