]> git.ipfire.org Git - thirdparty/dracut.git/blob - modules.d/45url-lib/url-lib.sh
fix: codespell
[thirdparty/dracut.git] / modules.d / 45url-lib / url-lib.sh
1 #!/bin/sh
2 # url-lib.sh - functions for handling URLs (file fetching etc.)
3 #
4 # Authors:
5 # Will Woods <wwoods@redhat.com>
6
7 type mkuniqdir > /dev/null 2>&1 || . /lib/dracut-lib.sh
8
9 # fetch_url URL [OUTFILE]
10 # fetch the given URL to a locally-visible location.
11 # if OUTFILE is given, the URL will be fetched to that filename,
12 # overwriting it if present.
13 # If the URL is something mountable (e.g. nfs://) and no OUTFILE is given,
14 # the server will be left mounted until pre-pivot.
15 # the return values are as follows:
16 # 0: success
17 # 253: unknown error (file missing)
18 # 254: unhandled URL scheme / protocol
19 # 255: bad arguments / unparsable URLs
20 # other: fetch command failure (whatever curl/mount/etc return)
21 fetch_url() {
22 local url="$1" outloc="$2"
23 local handler
24 handler="$(get_url_handler "$url")"
25 [ -n "$handler" ] || return 254
26 [ -n "$url" ] || return 255
27 "$handler" "$url" "$outloc"
28 }
29
30 # get_url_handler URL
31 # returns the first HANDLERNAME corresponding to the URL's scheme
32 get_url_handler() {
33 local scheme="${1%%:*}" item=""
34 for item in $url_handler_map; do
35 [ "$scheme" = "${item%%:*}" ] && echo "${item#*:}" && return 0
36 done
37 return 1
38 }
39
40 # add_url_handler HANDLERNAME SCHEME [SCHEME...]
41 # associate the named handler with the named scheme(s).
42 add_url_handler() {
43 local handler="$1"
44 shift
45 local schemes="$*" scheme=""
46 set --
47 for scheme in $schemes; do
48 [ "$(get_url_handler "$scheme")" = "$handler" ] && continue
49 set -- "$@" "$scheme:$handler"
50 done
51 set -- "$@" "$url_handler_map" # add new items to *front* of list
52 url_handler_map="$*"
53 }
54
55 ### HTTP, HTTPS, FTP #################################################
56
57 export CURL_HOME="/run/initramfs/url-lib"
58 mkdir -p $CURL_HOME
59 curl_args="--globoff --location --retry 3 --retry-connrefused --fail --show-error"
60 getargbool 0 rd.noverifyssl && curl_args="$curl_args --insecure"
61
62 proxy=$(getarg proxy=)
63 [ -n "$proxy" ] && curl_args="$curl_args --proxy $proxy"
64
65 curl_fetch_url() {
66 local url="$1" outloc="$2"
67 echo "$url" > /proc/self/fd/0
68 if [ -n "$outloc" ]; then
69 # shellcheck disable=SC2086
70 curl $curl_args --output "$outloc" -- "$url" || return $?
71 else
72 local outdir
73 outdir="$(mkuniqdir /tmp curl_fetch_url)"
74 (
75 cd "$outdir" || exit
76 # shellcheck disable=SC2086
77 curl $curl_args --remote-name "$url" || return $?
78 )
79 outloc="$outdir/$(ls -A "$outdir")"
80 fi
81 if ! [ -f "$outloc" ]; then
82 warn "Downloading '$url' failed!"
83 return 253
84 fi
85 if [ -z "$2" ]; then echo "$outloc"; fi
86 }
87 add_url_handler curl_fetch_url http https ftp tftp
88
89 set_http_header() {
90 echo "header = \"$1: $2\"" >> $CURL_HOME/.curlrc
91 }
92
93 ### TORRENT ##########################################################
94
95 ctorrent_args="-E 0 -e 0"
96
97 ctorrent_fetch_url() {
98 local url="$1" outloc="$2"
99 url=${url#*//}
100 torrent_outloc="$outloc.torrent"
101 echo "$url" > /proc/self/fd/0
102 if [ -n "$outloc" ]; then
103 # shellcheck disable=SC2086
104 curl $curl_args --output "$torrent_outloc" -- "$url" || return $?
105 else
106 local outdir
107 outdir="$(mkuniqdir /tmp torrent_fetch_url)"
108 (
109 cd "$outdir" || exit
110 # shellcheck disable=SC2086
111 curl $curl_args --remote-name "$url" || return $?
112 )
113 torrent_outloc="$outdir/$(ls -A "$outdir")"
114 outloc=${torrent_outloc%.*}
115 fi
116 if ! [ -f "$torrent_outloc" ]; then
117 warn "Downloading '$url' failed!"
118 return 253
119 fi
120 # shellcheck disable=SC2086
121 ctorrent $ctorrent_args -s "$outloc" "$torrent_outloc" >&2
122 if ! [ -f "$outloc" ]; then
123 warn "Torrent download of '$url' failed!"
124 return 253
125 fi
126 if [ -z "$2" ]; then echo "$outloc"; fi
127 }
128
129 command -v ctorrent > /dev/null \
130 && add_url_handler ctorrent_fetch_url torrent
131
132 ### NFS ##############################################################
133
134 [ -e /lib/nfs-lib.sh ] && . /lib/nfs-lib.sh
135
136 nfs_already_mounted() {
137 local server="$1" path="$2" s="" p=""
138 while read -r src mnt rest || [ -n "$src" ]; do
139 splitsep ":" "$src" s p
140 p=${p%/}
141 if [ "$server" = "$s" ]; then
142 if [ "$path" = "$p" ]; then
143 echo "$mnt"
144 elif str_starts "$path" "$p"; then
145 echo "$mnt"/"${path#"$p"/}"
146 fi
147 fi
148 done < /proc/mounts
149 }
150
151 nfs_fetch_url() {
152 local url="$1" outloc="$2" nfs="" server="" path="" options=""
153 nfs_to_var "$url" || return 255
154 local filepath="${path%/*}" filename="${path##*/}" mntdir=""
155
156 # skip mount if server:/filepath is already mounted
157 mntdir=$(nfs_already_mounted "$server" "$filepath")
158 if [ -z "$mntdir" ]; then
159 local mntdir
160 mntdir="$(mkuniqdir /run nfs_mnt)"
161 mount_nfs "$nfs:$server:$filepath${options:+:$options}" "$mntdir"
162 # lazy unmount during pre-pivot hook
163 inst_hook --hook pre-pivot --name 99url-lib-umount-nfs-"$(basename "$mntdir")" umount -l -- "$mntdir"
164 fi
165
166 if [ -z "$outloc" ]; then
167 outloc="$mntdir/$filename"
168 else
169 cp -f -- "$mntdir/$filename" "$outloc" || return $?
170 fi
171 [ -f "$outloc" ] || return 253
172 if [ -z "$2" ]; then echo "$outloc"; fi
173 }
174 command -v nfs_to_var > /dev/null && add_url_handler nfs_fetch_url nfs nfs4