summaryrefslogtreecommitdiffstats
path: root/init_functions
blob: d9ffe4aeca9b7fa19cc8870e8aeb636980082a24 (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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# This file contains common functions used in init and in hooks

msg () {
    [ "${quiet}" != "y" ] && echo $@
}
err () {
    echo "ERROR: $@"
}

poll_device() {
    device="$1"
    if [ "$2" -ge 0 ]; then
        seconds="$2"
    else
        seconds=5
    fi
    if [ "${udevd_running}" -eq 1 ]; then
        msg "Waiting ${seconds} seconds for device ${device} ..."
        while [ ! -b "${device}" -a ${seconds} -gt 0 ]; do
            sleep 1
            seconds=$((${seconds}-1))
        done
    fi
    [ -b "${device}" ]
}

launch_interactive_shell() {
    export PS1='[ramfs \W]\$ '
    [ "$1" = "--exec" ] && exec /bin/sh -i
    /bin/sh -i
}

parse_cmdline() {
    local w in_quotes lhs rhs
    in_quotes=0
    for w in $(cat /proc/cmdline); do
        if [ ${in_quotes} -eq 0 ]; then
            case "${w}" in
                \#*) break ;; # ignore everything after a # in the commandline
                # The kernel passes those to init on its own
                [0123456Ss]) ;;
                single) ;;
                rw) readwrite="yes" ;;
                ro) readwrite="no" ;;
                # only export stuff that does work with ash :)
                *=*) rhs="$(echo "${w}" | cut -d= -f2-)"
                    lhs="$(echo "${w}" | cut -d= -f1 | sed 's|\.|_|g;s|-|_|g;')"
                    if [ "${rhs:0:1}" = "\"" ]; then
                        if [ "${rhs:$((${#rhs}-1))}" = "\"" ]; then
                            rhs="${rhs:1:$((${#rhs}-2))}"
                        else
                            rhs="${rhs:1}"
                            in_quotes=1
                            continue
                        fi
                    fi
                    (echo "${lhs}" | grep -qe '^[0-9]' -e '[^a-zA-Z0-9_]') || eval ${lhs}=\${rhs}
                    ;;
                *)  lhs="$(echo "${w}" | sed 's|\.|_|g;s|-|_|g;')"
                    (echo "${lhs}" | grep -qe '^[0-9]' -e '[^a-zA-Z0-9_]') || eval ${lhs}=y
                    ;;
            esac
        else
            if [ "${w:$((${#w}-1))}" = "\"" ]; then
                rhs="${rhs} ${w:0:$((${#w}-1))}"
                in_quotes=0
                (echo "${lhs}" | grep -qe '^[0-9]' -e '[^a-zA-Z0-9_]') || eval ${lhs}=\${rhs}
            else
                rhs="${rhs} ${w}"
            fi
        fi
    done
}

default_mount_handler() {
    # resolve tag name to block device
    if [ "${root:0:5}" = 'UUID=' ] || [ "${root:0:6}" = 'LABEL=' ]; then
        device=$(blkid -t "$root" -o device)
        if [ -n "$device" ]; then
            root=$device
        fi
        unset device
    fi

    if [ ${root:0:5} != "/dev/" ] || ! poll_device "${root}" ${rootdelay}; then
        msg "Root device '${root}' doesn't exist. Attempting to create it."
        major=""
        minor=""
        if [ ${root:0:5} = "/dev/" ]; then
            # It might be a block device (/dev/sda) -> /sys/block/sda/dev
            # or a partition (/dev/sda1) -> /sys/block/sda/sda1/dev
            for dir in /sys/block /sys/block/*; do
                if [ -f ${dir}/${root:5}/dev ]; then
                    major="$(cat ${dir}/${root:5}/dev | cut -d: -f1)"
                    minor="$(cat ${dir}/${root:5}/dev | cut -d: -f2)"
                    break
                fi
            done
        # It might be a major/minor pair (8:1)
        elif echo ${root} | grep -q :; then
            major="$(echo ${root} | cut -d: -f1)"
            minor="$(echo ${root} | cut -d: -f2)"
            root="/dev/root"
        # It might be major/minor encoded as a single hex-number (lilo-style) (801)
        elif [ ${#root} -le 4 -a ${#root} -gt 2 ] && echo "${root}" | grep -qe '^[A-Fa-f0-9]*$'; then
            str_offset=$((${#root}-2))
            major=$((0x${root:0:${str_offset}}))
            minor=$((0x${root:${str_offset}}))
            root="/dev/root"
        fi
        if [ -n "${major}" -a -n "${minor}" ]; then
            msg "Creating root device ${root} with major ${major} and minor ${minor}."
            mknod ${root} b ${major} ${minor}
        else
            err "Unable to determine major/minor number of root device '${root}'."
            echo "You are being dropped to a recovery shell"
            echo "    Type 'exit' to try and continue booting"
            launch_interactive_shell
            msg "Trying to continue (this will most likely fail) ..."
        fi
    fi
    # We didn't build filesystem support into busybox,
    # instead we use util-linux-ng's blkid for best compatibility
    if [ -n "${rootfstype}" ]; then
        fstype="${rootfstype}"
    else
        fstype=$(sbin/blkid -u filesystem -o value -s TYPE -p "${root}")
        if [ -z "${fstype}" ]; then
            err "Unable to determine the file system type of ${root}:"
            echo "Either it contains no filesystem, an unknown filesystem,"
            echo "or more than one valid file system signature was found."
            echo
            echo "Try adding"
            echo "    rootfstype=your_filesystem_type"
            echo "to the kernel command line."
            echo
            echo "You are now being dropped into an emergency shell."
            launch_interactive_shell
            msg "Trying to continue (this will most likely fail) ..."
        fi
    fi
    if [ "${readwrite}" = "yes" ]; then
        rwopt="rw"
    else
        rwopt="ro"
    fi
    mount ${fstype:+-t ${fstype}} -o ${rwopt}${rootflags:+,${rootflags}} "${root}" "$1"
}