Tizen 2.1 base
[platform/upstream/sysvinit.git] / debian / src / initscripts / lib / init / usplash-fsck-functions.sh
1 #
2 # Functions for reporting fsck progress in usplash
3 #
4 # (C) 2008 Canonical Ltd.
5 # Author: Martin Pitt <martin.pitt@ubuntu.com>
6 #
7
8 # convert a "pass cur max" progress triple from fsck to a progress percentage
9 # based on calc_percent() from e2fsck
10 fsck_progress_to_percent() {
11     if [ $1 = 1 ]; then
12         PERCENT=$(($2 * 70 / $3))
13     elif [ $1 = 2 ]; then
14         PERCENT=$(($2 * 20 / $3 + 70))
15     elif [ $1 = 3 ]; then
16         PERCENT=$(($2 * 2 / $3 + 90))
17     elif [ $1 = 4 ]; then
18         PERCENT=$(($2 * 3 / $3 + 92))
19     elif [ $1 = 5 ]; then
20         PERCENT=$(($2 * 5 / $3 + 95))
21     else
22         PERCENT=100
23     fi
24 }
25
26 # read current fsck status ($PASS, $CUR, $MAX) from file descriptor 4
27 # this assumes that fsck was started in the background ($!)
28 get_fsck_status()
29 {
30         local a b c S
31
32         unset a
33         # only consider the last line
34         while true; do
35             PASS=$a
36             CUR=$b
37             MAX=$c
38             read a b c rest <&4
39             if [ -n "$PASS" ] && [ -z "$a" ]; then
40                 break;
41             fi
42
43             # if we did not read anything, check if the process is still
44             # actually running, or just waiting to be reaped
45             if [ -z "$PASS" ] && [ -z "$a" ]; then
46                 S=`ps -o state --no-headers -p $!` || break
47                 [ "$S" != "Z" ] || break
48                 # do not spin while waiting for fsck to start up
49                 sleep 0.1
50             fi
51         done
52 }
53
54 # Set $NAME to a human readable description of which partitions are currently
55 # being checked. Set $CLEAN if this is only a routine check on clean
56 # partitions which can be skipped.
57 get_checked_names ()
58 {
59         local DEVS DUMP LABEL
60
61         FSCKPROCS=$(ps --no-headers -C 'fsck.ext2 fsck.ext3 fsck.ext4 fsck.ext4dev' -o pid,args | grep /dev)
62         DEVS=$(echo "$FSCKPROCS" | sed 's_^.*\(/dev/[^[:space:]]*\).*$_\1_')
63         FSCKPIDS=$(echo "$FSCKPROCS" | sed 's_^[[:space:]]*\([[:digit:]]\+\).*$_\1_')
64
65         if [ -z "$DEVS" ]; then
66             unset NAME
67             return 0
68         fi
69
70         CLEAN=1
71         unset NAME
72         for DEV in $DEVS; do
73             DUMP=$(dumpe2fs -h $DEV)
74             if ! echo "$DUMP" | grep -q 'state:[[:space:]]*clean$'; then
75                 unset CLEAN
76             fi
77
78             LABEL=$(blkid $DEV | sed -rn '/LABEL="([^"]+)"/ { s/^.*LABEL="//; s/".*$//; p }')
79             [ -z "$NAME" ] || NAME="$NAME, "
80             if [ -n "$LABEL" ]; then
81                 NAME="$NAME$LABEL ($DEV)"
82             else
83                 NAME="$NAME$DEV"
84             fi
85         done
86 }
87
88 # Return true if usplash is active
89 usplash_running() {
90     if pidof usplash ; then
91         return 0
92     else
93         return 1
94     fi
95 }
96
97 # Read fsck progress from file $1 and display progress in usplash.
98 usplash_progress() {
99         exec 4<$1
100         unset CANCEL
101         ESCAPE=`/bin/echo -ne "\x1B"`
102         FIRST=1
103         PREVPERCENT=0
104
105         while true; do
106             sleep 0.5
107             get_fsck_status
108             [ -n "$PASS" ] || break
109
110             fsck_progress_to_percent "$PASS" "$CUR" "$MAX"
111
112             # check if fsck advanced to the next drive
113             if [ "$PREVPERCENT" -gt "$PERCENT" ]; then
114                 if [ -n "$CANCEL" ]; then
115                     usplash_write "STATUS skip                                                        "
116                 else
117                     usplash_write "STATUS                                                             "
118                 fi
119                 FIRST=1
120             fi
121             PREVPERCENT=$PERCENT
122
123             # lazy initialization of output and progress report on the first
124             # progress line that we receive; this avoids starting the output
125             # for clean or non-ext[234] partitions
126             if [ -n "$FIRST" ]; then
127                 usplash_write "TIMEOUT 0"
128
129                 # show which device is being checked
130                 get_checked_names
131                 [ -n "$NAME" ] || break
132
133                 usplash_write "VERBOSE on"
134                 if [ "$CLEAN" ]; then
135                     usplash_write "TEXT Routine check of drives: $NAME..."
136                     usplash_write "TEXT Press ESC to skip"
137                 else
138                     usplash_write "TEXT Unclean shutdown, checking drives:"
139                     usplash_write "TEXT $NAME..."
140                 fi
141
142                 unset FIRST
143             fi
144
145             usplash_write "STATUS $PERCENT% (stage $PASS/5, $CUR/$MAX)                       "
146             echo "Checking drive $NAME: $PERCENT% (stage $PASS/5, $CUR/$MAX)" >/dev/console
147
148             # ESC interrupts check for clean drives
149             if [ -n "$CLEAN" ]; then
150                 if FAIL_NO_USPLASH=1 usplash_write "INPUTCHAR"; then
151                     read ch < /dev/.initramfs/usplash_outfifo
152                     if [ "$ch" = "$ESCAPE" ]; then
153                         kill $FSCKPIDS
154                         CANCEL=1
155                         continue # there might be more drives, so do not break
156                     fi
157                 fi
158             fi
159         done
160
161         if [ -n "$CANCEL" ]; then
162             usplash_write "STATUS skip                                                        "
163         else
164             usplash_write "STATUS                                                             "
165         fi
166         usplash_write "VERBOSE default"
167         usplash_write "TEXT Drive checks finished."
168         usplash_write "TIMEOUT 15"
169         wait %1 # to collect fsck's exit code
170         EXITCODE=$?
171         [ -n "$CANCEL" ] && FSCKCODE=0 || FSCKCODE=$EXITCODE
172         if [ "$FSCKCODE" -gt 1 ]; then
173             # non-correctable failure which requires sulogin: quit usplash and
174             # restore stdin/out/err
175             usplash_write "QUIT"
176             exec </dev/console >/dev/console 2>/dev/console
177         fi
178 }