]>
Commit | Line | Data |
---|---|---|
1 | #!/bin/sh | |
2 | ||
3 | type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh | |
4 | ||
5 | fsck_ask_reboot() { | |
6 | info "note - fsck suggests reboot, if you" | |
7 | info "leave shell, booting will continue normally" | |
8 | emergency_shell -n "(reboot ?)" | |
9 | } | |
10 | ||
11 | fsck_ask_err() { | |
12 | warn "*** An error occurred during the file system check." | |
13 | warn "*** Dropping you to a shell; the system will try" | |
14 | warn "*** to mount the filesystem(s), when you leave the shell." | |
15 | emergency_shell -n "(Repair filesystem)" | |
16 | } | |
17 | ||
18 | # inherits: _ret _drv _out | |
19 | fsck_tail() { | |
20 | [ "$_ret" -gt 0 ] && warn "$_drv returned with $_ret" | |
21 | if [ "$_ret" -ge 4 ]; then | |
22 | [ -n "$_out" ] && echo "$_out" | vwarn | |
23 | fsck_ask_err | |
24 | else | |
25 | [ -n "$_out" ] && echo "$_out" | vinfo | |
26 | [ "$_ret" -ge 2 ] && fsck_ask_reboot | |
27 | fi | |
28 | } | |
29 | ||
30 | # note: this function sets _drv of the caller | |
31 | fsck_able() { | |
32 | case "$1" in | |
33 | xfs) | |
34 | # { | |
35 | # type xfs_db && | |
36 | # type xfs_repair && | |
37 | # type xfs_check && | |
38 | # type mount && | |
39 | # type umount | |
40 | # } >/dev/null 2>&1 && | |
41 | # _drv="_drv=none fsck_drv_xfs" && | |
42 | # return 0 | |
43 | return 1 | |
44 | ;; | |
45 | ext?) | |
46 | type e2fsck > /dev/null 2>&1 \ | |
47 | && _drv="fsck_drv_com e2fsck" \ | |
48 | && return 0 | |
49 | ;; | |
50 | f2fs) | |
51 | type fsck.f2fs > /dev/null 2>&1 \ | |
52 | && _drv="fsck_drv_com fsck.f2fs" \ | |
53 | && return 0 | |
54 | ;; | |
55 | jfs) | |
56 | type jfs_fsck > /dev/null 2>&1 \ | |
57 | && _drv="fsck_drv_com jfs_fsck" \ | |
58 | && return 0 | |
59 | ;; | |
60 | reiserfs) | |
61 | type reiserfsck > /dev/null 2>&1 \ | |
62 | && _drv="fsck_drv_com reiserfsck" \ | |
63 | && return 0 | |
64 | ;; | |
65 | btrfs) | |
66 | # type btrfsck >/dev/null 2>&1 && | |
67 | # _drv="_drv=none fsck_drv_btrfs" && | |
68 | # return 0 | |
69 | return 1 | |
70 | ;; | |
71 | nfs*) | |
72 | # nfs can be a nop, returning success | |
73 | _drv=":" \ | |
74 | && return 0 | |
75 | ;; | |
76 | *) | |
77 | type fsck > /dev/null 2>&1 \ | |
78 | && _drv="fsck_drv_std fsck" \ | |
79 | && return 0 | |
80 | ;; | |
81 | esac | |
82 | ||
83 | return 1 | |
84 | } | |
85 | ||
86 | # note: all drivers inherit: _drv _fop _dev | |
87 | ||
88 | fsck_drv_xfs() { | |
89 | # xfs fsck is not necessary... Either it mounts or not | |
90 | return 0 | |
91 | } | |
92 | ||
93 | fsck_drv_btrfs() { | |
94 | # btrfs fsck is not necessary... Either it mounts or not | |
95 | return 0 | |
96 | } | |
97 | ||
98 | # common code for checkers that follow usual subset of options and return codes | |
99 | fsck_drv_com() { | |
100 | local _drv="$1" | |
101 | local _ret | |
102 | local _out | |
103 | ||
104 | if ! strglobin "$_fop" "-[ynap]"; then | |
105 | _fop="-a${_fop:+ "$_fop"}" | |
106 | fi | |
107 | ||
108 | info "issuing $_drv $_fop $_dev" | |
109 | # we enforce non-interactive run, so $() is fine | |
110 | # shellcheck disable=SC2086 | |
111 | _out=$($_drv $_fop "$_dev") | |
112 | _ret=$? | |
113 | fsck_tail | |
114 | ||
115 | return $_ret | |
116 | } | |
117 | ||
118 | # code for generic fsck, if the filesystem checked is "unknown" to us | |
119 | fsck_drv_std() { | |
120 | local _ret | |
121 | local _out | |
122 | unset _out | |
123 | ||
124 | info "issuing fsck $_fop $_dev" | |
125 | # note, we don't enforce -a here, thus fsck is being run (in theory) | |
126 | # interactively; otherwise some tool might complain about lack of terminal | |
127 | # (and using -a might not be safe) | |
128 | # shellcheck disable=SC2086 | |
129 | fsck $_fop "$_dev" > /dev/console 2>&1 | |
130 | _ret=$? | |
131 | fsck_tail | |
132 | ||
133 | return $_ret | |
134 | } | |
135 | ||
136 | # checks single filesystem, relying on specific "driver"; we don't rely on | |
137 | # automatic checking based on fstab, so empty one is passed; | |
138 | # takes 4 arguments - device, filesystem, filesystem options, additional fsck options; | |
139 | # first 2 arguments are mandatory (fs may be auto or "") | |
140 | # returns 255 if filesystem wasn't checked at all (e.g. due to lack of | |
141 | # necessary tools or insufficient options) | |
142 | fsck_single() { | |
143 | local FSTAB_FILE=/etc/fstab.empty | |
144 | local _dev="$1" | |
145 | local _fs="${2:-auto}" | |
146 | local _fop="$4" | |
147 | local _drv | |
148 | ||
149 | [ $# -lt 2 ] && return 255 | |
150 | _dev=$(readlink -f "$(label_uuid_to_dev "$_dev")") | |
151 | [ -e "$_dev" ] || return 255 | |
152 | _fs=$(det_fs "$_dev" "$_fs") | |
153 | fsck_able "$_fs" || return 255 | |
154 | ||
155 | info "Checking $_fs: $_dev" | |
156 | export FSTAB_FILE | |
157 | eval "$_drv" | |
158 | return $? | |
159 | } | |
160 | ||
161 | # takes list of filesystems to check in parallel; we don't rely on automatic | |
162 | # checking based on fstab, so empty one is passed | |
163 | fsck_batch() { | |
164 | local FSTAB_FILE=/etc/fstab.empty | |
165 | local _drv=fsck | |
166 | local _dev | |
167 | local _ret | |
168 | local _out | |
169 | ||
170 | [ $# -eq 0 ] || ! type fsck > /dev/null 2>&1 && return 255 | |
171 | ||
172 | info "Checking filesystems (fsck -M -T -a):" | |
173 | for _dev in "$@"; do | |
174 | info " $_dev" | |
175 | done | |
176 | ||
177 | export FSTAB_FILE | |
178 | _out="$(fsck -M -T "$@" -- -a)" | |
179 | _ret=$? | |
180 | ||
181 | fsck_tail | |
182 | ||
183 | return $_ret | |
184 | } | |
185 | ||
186 | # verify supplied filesystem type: | |
187 | # if user provided the fs and we couldn't find it, assume user is right | |
188 | # if we found the fs, assume we're right | |
189 | det_fs() { | |
190 | local _dev="$1" | |
191 | local _orig="${2:-auto}" | |
192 | local _fs | |
193 | ||
194 | _fs=$(udevadm info --query=property --name="$_dev" \ | |
195 | | while read -r line || [ -n "$line" ]; do | |
196 | if str_starts "$line" "ID_FS_TYPE="; then | |
197 | echo "${line#ID_FS_TYPE=}" | |
198 | break | |
199 | fi | |
200 | done) | |
201 | _fs=${_fs:-auto} | |
202 | ||
203 | if [ "$_fs" = "auto" ]; then | |
204 | _fs="$_orig" | |
205 | fi | |
206 | echo "$_fs" | |
207 | } | |
208 | ||
209 | write_fs_tab() { | |
210 | local _o | |
211 | local _rw | |
212 | local _root | |
213 | local _rootfstype | |
214 | local _rootflags | |
215 | local _fspassno | |
216 | ||
217 | _fspassno="0" | |
218 | _root="$1" | |
219 | _rootfstype="$2" | |
220 | _rootflags="$3" | |
221 | [ -z "$_rootfstype" ] && _rootfstype=$(getarg rootfstype=) | |
222 | [ -z "$_rootflags" ] && _rootflags=$(getarg rootflags=) | |
223 | ||
224 | [ -z "$_rootfstype" ] && _rootfstype="auto" | |
225 | ||
226 | if [ -z "$_rootflags" ]; then | |
227 | _rootflags="ro,x-initrd.mount" | |
228 | else | |
229 | _rootflags="ro,$_rootflags,x-initrd.mount" | |
230 | fi | |
231 | ||
232 | _rw=0 | |
233 | ||
234 | CMDLINE=$(getcmdline) | |
235 | for _o in $CMDLINE; do | |
236 | case $_o in | |
237 | rw) | |
238 | _rw=1 | |
239 | ;; | |
240 | ro) | |
241 | _rw=0 | |
242 | ;; | |
243 | esac | |
244 | done | |
245 | if [ "$_rw" = "1" ]; then | |
246 | _rootflags="$_rootflags,rw" | |
247 | if ! getargbool 0 rd.skipfsck; then | |
248 | _fspassno="1" | |
249 | fi | |
250 | fi | |
251 | ||
252 | if grep -q "$_root /sysroot" /etc/fstab; then | |
253 | echo "$_root /sysroot $_rootfstype $_rootflags $_fspassno 0" >> /etc/fstab | |
254 | else | |
255 | return | |
256 | fi | |
257 | ||
258 | if type systemctl > /dev/null 2> /dev/null; then | |
259 | systemctl daemon-reload | |
260 | systemctl --no-block start initrd-root-fs.target | |
261 | fi | |
262 | } |