#!/usr/bin/bash
# Author: Veerendra C. Date: Aug, 2014
# Release-2 : Oct 2018
# Adding LABEL mounting feature
# This script tries to mount the drives during 'first-boot'
# Adapted from RH dracut
# Copyright 2005-2013 Red Hat, Inc.  All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

# get a persistent path from a device
get_persistent_dev() {
    local i _tmp _dev

    _dev=$(get_maj_min "$1")
    [ -z "$_dev" ] && return

    for i in \
        /dev/mapper/* \
        /dev/disk/${persistent_policy:-by-uuid}/* \
        /dev/disk/by-label/* \
        /dev/disk/by-partuuid/* \
        /dev/disk/by-partlabel/* \
        /dev/disk/by-id/* \
        /dev/disk/by-path/* \
        /dev/disk/by-uuid/* \
        ; do
        [[ -e "$i" ]] || continue
        [[ $i == /dev/mapper/control ]] && continue
        [[ $i == /dev/mapper/mpath* ]] && continue
        _tmp=$(get_maj_min "$i")
        if [ "$_tmp" = "$_dev" ]; then
            printf -- "%s" "$i"
            return
        fi
    done
}

expand_persistent_dev() {
    local _dev=$1

    case "$_dev" in
        LABEL=*)
            _dev="/dev/disk/by-label/${_dev#LABEL=}"
            ;;
        UUID=*)
            _dev="${_dev#UUID=}"
            _dev="${_dev,,}"
            _dev="/dev/disk/by-uuid/${_dev}"
            ;;
        PARTUUID=*)
            _dev="${_dev#PARTUUID=}"
            _dev="${_dev,,}"
            _dev="/dev/disk/by-partuuid/${_dev}"
            ;;
        PARTLABEL=*)
            _dev="/dev/disk/by-partlabel/${_dev#PARTLABEL=}"
            ;;
    esac
    printf "%s" "$_dev"
}

shorten_persistent_dev() {
    local _dev="$1"
    case "$_dev" in
        /dev/disk/by-uuid/*)
            printf "%s" "UUID=${_dev##*/}";;
        /dev/disk/by-label/*)
            printf "%s" "LABEL=${_dev##*/}";;
        /dev/disk/by-partuuid/*)
            printf "%s" "PARTUUID=${_dev##*/}";;
        /dev/disk/by-partlabel/*)
            printf "%s" "PARTLABEL=${_dev##*/}";;
        *)
            printf "%s" "$_dev";;
    esac
}

# get_maj_min <device>
# Prints the major and minor of a device node.
# Example:
# $ get_maj_min /dev/sda2
# 8:2
get_maj_min() {
    local _maj _min _majmin
    _majmin="$(stat -L -c '%t:%T' "$1" 2>/dev/null)"
    printf "%s" "$((0x${_majmin%:*})):$((0x${_majmin#*:}))"
}
# find_block_device <mountpoint>
# Prints the major and minor number of the block device
# for a given mountpoint.
# Unless $use_fstab is set to "yes" the functions
# uses /proc/self/mountinfo as the primary source of the
# information and only falls back to /etc/fstab, if the mountpoint
# is not found there.
# Example:
# $ find_block_device /usr
# 8:4
find_block_device() {
    local _majmin _dev _majmin _find_mpt
    _find_mpt="$1"
    if [[ $use_fstab != yes ]]; then
        [[ -d $_find_mpt/. ]]
        findmnt -e -v -n -o 'MAJ:MIN,SOURCE' --target "$_find_mpt" | { \
            while read _majmin _dev; do
                if [[ -b $_dev ]]; then
                    if ! [[ $_majmin ]] || [[ $_majmin == 0:* ]]; then
                        _majmin=$(get_maj_min $_dev)
                    fi
                    if [[ $_majmin ]]; then
                        printf "%s\n" "$_majmin"
                    else
                        printf "%s\n" "$_dev"
                    fi
                    return 0
                fi
                if [[ $_dev = *:* ]]; then
                    printf "%s\n" "$_dev"
                    return 0
                fi
            done; return 1; } && return 0
    fi
    # fall back to /etc/fstab

    findmnt -e --fstab -v -n -o 'MAJ:MIN,SOURCE' --target "$_find_mpt" | { \
        while read _majmin _dev; do
            if ! [[ $_dev ]]; then
                _dev="$_majmin"
                unset _majmin
            fi
            if [[ -b $_dev ]]; then
                [[ $_majmin ]] || _majmin=$(get_maj_min $_dev)
                if [[ $_majmin ]]; then
                    printf "%s\n" "$_majmin"
                else
                    printf "%s\n" "$_dev"
                fi
                return 0
            fi
            if [[ $_dev = *:* ]]; then
                printf "%s\n" "$_dev"
                return 0
            fi
        done; return 1; } && return 0

    return 1
}
main () {
    # To fix the issues WP-7999 & WP-7280 where LVM partition
    # created but not available which cause multiples warning.
#    if lvscan | grep -q 'ACTIVE'; then
#	lvm vgchange -an
#	lvm vgchange -ay
     if dmsetup info -c --noheadings --separator ':' -o name,open 2>/dev/null |
        awk -F: '$1 ~ /^vg00-/ && ($2 + 0) > 0 { used=1 } END { exit !used }'
     then
         logger -t slos-premount \
            "vg00 has open logical volumes; skipping deactivate/reactivate"

        vgmknodes --refresh vg00 || true
        udevadm settle --timeout=10 || true
    else
        lvm vgchange -an vg00
        lvm vgchange -ay vg00
        udevadm settle --timeout=10 || true
    fi


    for mp in \
        "/" \
        "/etc" \
        "/bin" \
        "/sbin" \
        "/lib" \
        "/lib64" \
        "/usr" \
        "/usr/bin" \
        "/usr/sbin" \
        "/usr/lib" \
        "/usr/lib64" \
        "/boot" \
        "/boot/efi" \
        ;
    do
        mp=$(readlink -f "$mp")
        mountpoint "$mp" >/dev/null 2>&1 || continue
        _dev=$(find_block_device "$mp")
        _bdev=$(readlink -f "/dev/block/$_dev")
        [[ -b $_bdev ]] && _dev=$_bdev
        [[ "$mp" == "/" ]] && root_dev="$_dev"
    mount $_dev $mp 2>/dev/null; sleep 1
    done

    if [[ -f /etc/fstab ]]; then
      while read _d _m _t _o _r; do
        #echo $_d $_m $_t $_o $_r; sleep 1
        [[ "$_d" == \#* ]] && continue
        [[ $_d ]] || continue
        [[ "$_o" = "defaults" ]] &&  _o=
        [[ "$_o" ]] &&  _o="-o defaults"
        [[ $_t != "swap" ]] && _t="-t $_t"
        _d=$(expand_persistent_dev "$_d")
        #[[ "$_d" -ef "$dev" ]] || continue
        [[ $_d = "devpts" ]] && continue
        [[ $_d = "hugetlbfs" ]] && continue
        [[ $_d = "debugfs" ]] && continue
        [[ $_d = "tmpfs" ]] && continue
        [[ $_d = "mqueue" ]] && continue
        [[ $_d = "/dev" ]] && continue
        [[ $_d = "cgroup" ]] && continue
        [[ $_d = "proc" ]] && continue
        [[ ! "$_d" -ef "$dev" ]] || continue
        if [[ $_t == "swap" ]]; then
            if [[ ! -b "$_d" ]]; then
                echo "$_d is not available yet; leaving swap activation to systemd"
                logger -t slos-premount \
                    "$_d is not available yet; leaving swap activation to systemd"
                continue
            fi

            _swap_real=$(readlink -f -- "$_d")
            _swap_active=0

            while read -r _active_swap _rest; do
                [[ "$_active_swap" == "Filename" ]] && continue

                if [[ "$(readlink -f -- "$_active_swap")" == "$_swap_real" ]]; then
                    _swap_active=1
                    break
                fi
            done < /proc/swaps

            if (( _swap_active )); then
                echo "$_d is already active as swap; skipping swapon"
                logger -t slos-premount \
                    "$_d is already active as swap; skipping swapon"
            else
                if ! swapon "$_d"; then
                    # Handle a possible race where systemd activated it
                    # between our check and the swapon command.
                    if grep -qw "$(readlink -f -- "$_d")" /proc/swaps; then
                        logger -t slos-premount \
                            "$_d became active during swapon attempt"
                    else
                        logger -t slos-premount \
                            "Failed to activate swap device $_d"
                        return 1
                    fi
                fi
            fi

            continue
        else
            [ -r "$_d" ] || vgscan --mknodes
            mount | grep -qw "$_d" && continue
            mount $_t $_o "$_d" "$_m" 2>/dev/null
        fi
      done < /etc/fstab
    fi
} # main

main
