]>
Commit | Line | Data |
---|---|---|
fefab84f MS |
1 | #!/bin/sh |
2 | # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- | |
3 | # ex: ts=8 sw=4 sts=4 et filetype=sh | |
4 | ||
5 | type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh | |
6 | ||
7 | fsck_ask_reboot() { | |
8 | info "note - fsck suggests reboot, if you" | |
9 | info "leave shell, booting will continue normally" | |
10 | emergency_shell -n "(reboot ?)" | |
11 | } | |
12 | ||
13 | fsck_ask_err() { | |
14 | warn "*** An error occurred during the file system check." | |
15 | warn "*** Dropping you to a shell; the system will try" | |
16 | warn "*** to mount the filesystem(s), when you leave the shell." | |
17 | emergency_shell -n "(Repair filesystem)" | |
18 | } | |
19 | ||
20 | # inherits: _ret _drv _out | |
21 | fsck_tail() { | |
22 | [ $_ret -gt 0 ] && warn "$_drv returned with $_ret" | |
23 | if [ $_ret -ge 4 ]; then | |
24 | [ -n "$_out" ] && echo "$_out"|vwarn | |
25 | fsck_ask_err | |
26 | else | |
27 | [ -n "$_out" ] && echo "$_out"|vinfo | |
28 | [ $_ret -ge 2 ] && fsck_ask_reboot | |
29 | fi | |
30 | } | |
31 | ||
32 | # note: this function sets _drv of the caller | |
33 | fsck_able() { | |
34 | case "$1" in | |
35 | xfs) { | |
36 | type xfs_db && | |
37 | type xfs_repair && | |
38 | type xfs_check && | |
39 | type mount && | |
40 | type umount | |
41 | } >/dev/null 2>&1 && | |
42 | _drv="_drv=none fsck_drv_xfs" && | |
43 | return 0 | |
44 | ;; | |
45 | ext?) | |
46 | type e2fsck >/dev/null 2>&1 && | |
47 | _drv="_drv=e2fsck fsck_drv_com" && | |
48 | return 0 | |
49 | ;; | |
50 | jfs) | |
51 | type jfs_fsck >/dev/null 2>&1 && | |
52 | _drv="_drv=jfs_fsck fsck_drv_com" && | |
53 | return 0 | |
54 | ;; | |
55 | reiserfs) | |
56 | type reiserfsck >/dev/null 2>&1 && | |
57 | _drv="_drv=reiserfsck fsck_drv_com" && | |
58 | return 0 | |
59 | ;; | |
1afa0cb6 HH |
60 | btrfs) |
61 | type btrfsck >/dev/null 2>&1 && | |
62 | _drv="_drv=btrfsck fsck_drv_com" && | |
63 | return 0 | |
64 | ;; | |
fefab84f MS |
65 | *) |
66 | type fsck >/dev/null 2>&1 && | |
67 | _drv="_drv=fsck fsck_drv_std" && | |
68 | return 0 | |
69 | ;; | |
70 | esac | |
71 | ||
72 | return 1 | |
73 | } | |
74 | ||
75 | # note: all drivers inherit: _drv _fop _dev | |
76 | ||
77 | fsck_drv_xfs() { | |
78 | local _ret | |
79 | ||
80 | # fs must be cleanly mounted (and umounted) first, before attempting any | |
81 | # xfs tools - if this works, nothing else should be needed | |
82 | # note, that user is always dropped into the shell, if the filesystem is | |
83 | # not mountable or if -f flag is found among _fop | |
84 | mkdir -p /tmp/.xfs | |
85 | ||
86 | info "trying to mount $_dev" | |
87 | if mount -t xfs "$_dev" "/tmp/.xfs" >/dev/null 2>&1; then | |
88 | _ret=0 | |
89 | info "xfs: $_dev is clean" | |
90 | umount "$_dev" >/dev/null 2>&1 | |
91 | else | |
92 | _ret=4 | |
93 | warn "*** $_dev is unmountable" | |
94 | fi | |
95 | if [ $_ret -gt 0 ] || strstr "$_fop" "-f"; then | |
96 | warn "*** Dropping you to a shell. You have" | |
97 | warn "*** xfs_repair and xfs_check (xfs_db) available." | |
98 | warn "*** Note that if xfs didn't mount properly, it's" | |
99 | warn "*** probably pretty serious condition." | |
100 | emergency_shell -n "(Repair filesystem)" | |
101 | fi | |
102 | ||
103 | rm -r /tmp/.xfs | |
104 | return $_ret | |
105 | } | |
106 | ||
107 | # common code for checkers that follow usual subset of options and return codes | |
108 | fsck_drv_com() { | |
109 | local _ret | |
110 | local _out | |
111 | ||
112 | if ! strstr "$_fop" "-[ynap]"; then | |
113 | _fop="-a ${_fop}" | |
114 | fi | |
115 | ||
116 | info "issuing $_drv $_fop $_dev" | |
117 | # we enforce non-interactive run, so $() is fine | |
118 | _out=$($_drv $_fop "$_dev") | |
119 | _ret=$? | |
120 | fsck_tail | |
121 | ||
122 | return $_ret | |
123 | } | |
124 | ||
125 | # code for generic fsck, if the filesystem checked is "unknown" to us | |
126 | fsck_drv_std() { | |
127 | local _ret | |
128 | local _out | |
129 | unset _out | |
130 | ||
131 | info "issuing fsck $_fop $_dev" | |
132 | # note, we don't enforce -a here, thus fsck is being run (in theory) | |
133 | # interactively; otherwise some tool might complain about lack of terminal | |
134 | # (and using -a might not be safe) | |
135 | fsck $_fop "$_dev" >/dev/console 2>&1 | |
136 | _ret=$? | |
137 | fsck_tail | |
138 | ||
139 | return $_ret | |
140 | } | |
141 | ||
142 | # checks single filesystem, relying on specific "driver"; we don't rely on | |
143 | # automatic checking based on fstab, so empty one is passed; | |
144 | # takes 3 arguments - device, filesystem, additional fsck options; | |
145 | # first 2 arguments are mandatory (fs may be auto or "") | |
146 | # returns 255 if filesystem wasn't checked at all (e.g. due to lack of | |
147 | # necessary tools or insufficient options) | |
148 | fsck_single() { | |
149 | local FSTAB_FILE=/etc/fstab.fslib | |
150 | local _dev="$1" | |
151 | local _fs="${2:-auto}" | |
152 | local _fop="$3" | |
153 | local _drv | |
154 | ||
155 | [ $# -lt 2 ] && return 255 | |
156 | ||
157 | _fs=$(det_fs "$_dev" "$_fs") | |
158 | fsck_able "$_fs" || return 255 | |
159 | ||
160 | info "Checking $_fs: $_dev" | |
161 | export FSTAB_FILE | |
162 | eval "$_drv" "\"$_dev\"" "\"$_fop\"" | |
163 | return $? | |
164 | } | |
165 | ||
166 | # takes list of filesystems to check in parallel; we don't rely on automatic | |
167 | # checking based on fstab, so empty one is passed | |
168 | fsck_batch() { | |
169 | local FSTAB_FILE=/etc/fstab.fslib | |
170 | local _drv=fsck | |
171 | local _dev | |
172 | local _ret | |
173 | local _out | |
174 | ||
175 | [ $# -eq 0 ] && return 255 | |
176 | ||
177 | info "Checking filesystems (fsck -M -T -a):" | |
178 | for _dev in "$@"; do | |
179 | info " $_dev" | |
180 | done | |
181 | ||
182 | _out="$(fsck -M -T "$@" -- -a)" | |
183 | _ret=$? | |
184 | ||
185 | export FSTAB_FILE | |
186 | fsck_tail | |
187 | ||
188 | return $_ret | |
189 | } | |
190 | ||
191 | # verify supplied filesystem type: | |
192 | # if user provided the fs and we couldn't find it, assume user is right | |
193 | # if we found the fs, assume we're right | |
194 | det_fs() { | |
195 | local _dev="$1" | |
196 | local _orig="${2:-auto}" | |
197 | local _fs | |
198 | ||
199 | _fs=$(udevadm info --query=env --name="$_dev" | \ | |
200 | while read line; do | |
201 | if str_starts $line "ID_FS_TYPE="; then | |
202 | echo ${line#ID_FS_TYPE=} | |
203 | break | |
204 | fi | |
205 | done) | |
206 | _fs=${_fs:-auto} | |
207 | ||
208 | if [ "$_fs" = "auto" ]; then | |
209 | _fs="$_orig" | |
210 | fi | |
211 | echo "$_fs" | |
212 | } |