]> git.ipfire.org Git - thirdparty/dracut.git/blob - modules.d/99fs-lib/fs-lib.sh
fix(fs-lib): shellcheck for modules.d/99fs-lib
[thirdparty/dracut.git] / modules.d / 99fs-lib / fs-lib.sh
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 _out=$($_drv "$_fop" "$_dev")
111 _ret=$?
112 fsck_tail
113
114 return $_ret
115 }
116
117 # code for generic fsck, if the filesystem checked is "unknown" to us
118 fsck_drv_std() {
119 local _ret
120 local _out
121 unset _out
122
123 info "issuing fsck $_fop $_dev"
124 # note, we don't enforce -a here, thus fsck is being run (in theory)
125 # interactively; otherwise some tool might complain about lack of terminal
126 # (and using -a might not be safe)
127 # shellcheck disable=SC2086
128 fsck $_fop "$_dev" > /dev/console 2>&1
129 _ret=$?
130 fsck_tail
131
132 return $_ret
133 }
134
135 # checks single filesystem, relying on specific "driver"; we don't rely on
136 # automatic checking based on fstab, so empty one is passed;
137 # takes 4 arguments - device, filesystem, filesystem options, additional fsck options;
138 # first 2 arguments are mandatory (fs may be auto or "")
139 # returns 255 if filesystem wasn't checked at all (e.g. due to lack of
140 # necessary tools or insufficient options)
141 fsck_single() {
142 local FSTAB_FILE=/etc/fstab.empty
143 local _dev="$1"
144 local _fs="${2:-auto}"
145 local _fop="$4"
146 local _drv
147
148 [ $# -lt 2 ] && return 255
149 # if UUID= marks more than one device, take only the first one
150 [ -e "$_dev" ] || _dev=$(devnames "$_dev" | while read -r line || [ -n "$line" ]; do if [ -n "$line" ]; then
151 echo "$line"
152 break
153 fi; done)
154 [ -e "$_dev" ] || return 255
155 _fs=$(det_fs "$_dev" "$_fs")
156 fsck_able "$_fs" || return 255
157
158 info "Checking $_fs: $_dev"
159 export FSTAB_FILE
160 eval "$_drv"
161 return $?
162 }
163
164 # takes list of filesystems to check in parallel; we don't rely on automatic
165 # checking based on fstab, so empty one is passed
166 fsck_batch() {
167 local FSTAB_FILE=/etc/fstab.empty
168 local _drv=fsck
169 local _dev
170 local _ret
171 local _out
172
173 [ $# -eq 0 ] || ! type fsck > /dev/null 2>&1 && return 255
174
175 info "Checking filesystems (fsck -M -T -a):"
176 for _dev in "$@"; do
177 info " $_dev"
178 done
179
180 export FSTAB_FILE
181 _out="$(fsck -M -T "$@" -- -a)"
182 _ret=$?
183
184 fsck_tail
185
186 return $_ret
187 }
188
189 # verify supplied filesystem type:
190 # if user provided the fs and we couldn't find it, assume user is right
191 # if we found the fs, assume we're right
192 det_fs() {
193 local _dev="$1"
194 local _orig="${2:-auto}"
195 local _fs
196
197 _fs=$(udevadm info --query=env --name="$_dev" \
198 | while read -r line || [ -n "$line" ]; do
199 if str_starts "$line" "ID_FS_TYPE="; then
200 echo "${line#ID_FS_TYPE=}"
201 break
202 fi
203 done)
204 _fs=${_fs:-auto}
205
206 if [ "$_fs" = "auto" ]; then
207 _fs="$_orig"
208 fi
209 echo "$_fs"
210 }
211
212 write_fs_tab() {
213 local _o
214 local _rw
215 local _root
216 local _rootfstype
217 local _rootflags
218 local _fspassno
219
220 _fspassno="0"
221 _root="$1"
222 _rootfstype="$2"
223 _rootflags="$3"
224 [ -z "$_rootfstype" ] && _rootfstype=$(getarg rootfstype=)
225 [ -z "$_rootflags" ] && _rootflags=$(getarg rootflags=)
226
227 [ -z "$_rootfstype" ] && _rootfstype="auto"
228
229 if [ -z "$_rootflags" ]; then
230 _rootflags="ro,x-initrd.mount"
231 else
232 _rootflags="ro,$_rootflags,x-initrd.mount"
233 fi
234
235 _rw=0
236
237 CMDLINE=$(getcmdline)
238 for _o in $CMDLINE; do
239 case $_o in
240 rw)
241 _rw=1
242 ;;
243 ro)
244 _rw=0
245 ;;
246 esac
247 done
248 if [ "$_rw" = "1" ]; then
249 _rootflags="$_rootflags,rw"
250 if ! getargbool 0 rd.skipfsck; then
251 _fspassno="1"
252 fi
253 fi
254
255 if grep -q "$_root /sysroot" /etc/fstab; then
256 echo "$_root /sysroot $_rootfstype $_rootflags $_fspassno 0" >> /etc/fstab
257 else
258 return
259 fi
260
261 if type systemctl > /dev/null 2> /dev/null; then
262 systemctl daemon-reload
263 systemctl --no-block start initrd-root-fs.target
264 fi
265 }