LibKernelUpgrade.sh 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. #!/bin/bash
  2. # This file is part of PrawnOS (https://www.prawnos.com)
  3. # Copyright (c) 2018 Hal Emmerich <hal@halemmerich.com>
  4. # Copyright (c) 2020 Fil Bergamo <fil@filberg.eu>
  5. # PrawnOS is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License version 2
  7. # as published by the Free Software Foundation.
  8. # PrawnOS is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. # You should have received a copy of the GNU General Public License
  13. # along with PrawnOS. If not, see <https://www.gnu.org/licenses/>.
  14. # ------------------------------------------------------
  15. # STATIC CONFIGURATION
  16. # ------------------------------------------------------
  17. #
  18. # Upstream url to be checked for source updates
  19. # Gets variable-expanded by filling in the version string "w.x.y"
  20. # through funcion expand_version_pattern()
  21. # Here, VER means the main version number,
  22. # MAJ the major revision number,
  23. # MIN the minor revision number
  24. # (e.g. "LATEST-VER.MAJ.N" + becomes "LATEST-5.4.N" for "5.4.43")
  25. src_url="https://linux-libre.fsfla.org/pub/linux-libre/releases/LATEST-VER.MAJ.N"
  26. #
  27. # Timeout, in seconds, for remote operations (rsyc, wget..)
  28. remote_timeout=15
  29. #
  30. # Number of retires after a remote operation times out
  31. remote_retries=2
  32. #
  33. # Seconds to wait before retrying failed remote operations
  34. remote_wait_retry=5
  35. #
  36. # The tool to be used to search for updates
  37. # can only choose between "rsync" and "wget"
  38. remote_tool="wget"
  39. #
  40. # The naming pattern of the actual source archive
  41. # as found in ${src_url}/${src_tar_pattern}
  42. # follows the same variable expansion as $src_url
  43. src_tar_pattern="linux-libre-VER.MAJ.MIN-gnu.tar.lz"
  44. #
  45. # Then naming pattern of the signature for the source archive
  46. src_tar_sig_pattern="${src_tar_pattern}.sign"
  47. #
  48. # The log file path (leave empty to disable logging)
  49. logfile=
  50. # ------------------------------------------------------
  51. log()
  52. {
  53. [ ! -z "$logfile" ] &&
  54. echo "$(date +'%Y-%m-%d %H:%M:%S') $1" >> $logfile
  55. }
  56. print_err()
  57. {
  58. printf "\033[0;31m%s\n" "[ERR] $1" 1>&2
  59. log "[ERR] $1"
  60. }
  61. print_warn()
  62. {
  63. echo "[WRN] $1" 1>&2
  64. log "[WRN] $1"
  65. }
  66. print_msg()
  67. {
  68. echo "[INF] $1"
  69. log "[INF] $1"
  70. }
  71. die()
  72. {
  73. print_err "$1"
  74. [ $# -gt 1 ] && exit $2
  75. exit 255
  76. }
  77. # function expand_version_pattern()
  78. # Replace VER, MAJ, MIN in the given pattern
  79. # with the given 'w', 'x' and 'y' values.
  80. # $1 = pattern
  81. # $2 = main version number ('w')
  82. # $3 = major revision number ('x')
  83. # $4 = minor revision number ('y')
  84. expand_version_pattern()
  85. {
  86. expanded=${1//VER/$2}
  87. expanded=${expanded//MAJ/$3}
  88. echo ${expanded//MIN/$4}
  89. }
  90. # function get_running_kver()
  91. # Print the upstream version of the currently running kernel
  92. # i.e. < w.x[.y] > without any trailing distro-specific version
  93. get_running_kver()
  94. {
  95. uname -r | cut -d '-' -f 1
  96. }
  97. # function split_version_string()
  98. # Split a 'w.x.y' version string into separate values.
  99. # Set $PRAWNOS_KVER_VER with the main version number ('w').
  100. # Set $PRAWNOS_KVER_MAJ wiht the major revision number ('x').
  101. # Set $PRAWNOS_KVER_MIN with the minor revision number ('y').
  102. # Return 0 on success, return 1 on failure.
  103. # $1 = version string in the 'w.x.y' format
  104. split_version_string()
  105. {
  106. # ver=$1
  107. # IFS='.' read -ra vscheme <<< "$ver"
  108. # PRAWNOS_KVER_VER=${vscheme[0]}
  109. # PRAWNOS_KVER_MAJ=${vscheme[1]}
  110. # PRAWNOS_KVER_MIN=${vscheme[2]}
  111. anynum="[0-9]{1,}"
  112. match_ver="($anynum)\.($anynum)\.($anynum)"
  113. if [[ $target =~ $search_fmt ]];then
  114. PRAWNOS_KVER_VER=${BASH_REMATCH[1]}
  115. PRAWNOS_KVER_MAJ=${BASH_REMATCH[2]}
  116. PRAWNOS_KVER_MIN=${BASH_REMATCH[3]}
  117. return 0
  118. else
  119. return 1
  120. fi
  121. }
  122. # function rsync_list_remote()
  123. # List contents of remote directory via rsync.
  124. # Return rsync's exit code.
  125. # $1 = remote rsync url to be listed
  126. rsync_list_remote()
  127. {
  128. rsync --timeout=$remote_timeout --list-only "$1" 2>&1
  129. ec=$?
  130. # rsync exit codes 30, 35 = timeout
  131. case $ec in
  132. 30|35)
  133. print_warn "rsync timeout while connecting to remote server"
  134. if [ $remote_retries -lt 1 ];then
  135. return $ec
  136. fi
  137. export remote_retries=$(( remote_retries - 1 ))
  138. print_warn "Waiting $remote_wait_retry seconds before retrying"
  139. sleep $remote_wait_retry
  140. rsync_list_remote $@
  141. return $?
  142. ;;
  143. *)
  144. return $ec
  145. ;;
  146. esac
  147. }
  148. # function rsync_search_url_pattern()
  149. # Search $src_url for the presence of a file
  150. # that matches $src_tar_pattern.
  151. # Print the bare file name matching the search.
  152. # $1 = main version number ('w')
  153. # $2 = major revision number ('x')
  154. rsync_search_url_pattern()
  155. {
  156. file_pattern=$(expand_version_pattern \
  157. "$src_url/$src_tar_pattern" $1 $2 "*")
  158. print_msg "Attempting to list remote file pattern $file_pattern..."
  159. file=$(rsync_list_remote $file_pattern)
  160. ec=$?
  161. if [ $ec -ne 0 ];then
  162. print_err "Failed to list remote file pattern"
  163. print_err "Output from rsync:"
  164. print_err "$file"
  165. return $ec
  166. fi
  167. fields=( $file )
  168. echo ${fields[-1]}
  169. }
  170. # function wget_search_url_pattern()
  171. # Search $src_url for an 'href' pointing to a file
  172. # that matches $src_tar_pattern.
  173. # Print the bare file name matching the search.
  174. # $1 = main version number ('w')
  175. # $2 = major revision number ('x')
  176. wget_search_url_pattern()
  177. {
  178. baseurl=$(expand_version_pattern "$src_url" "$1" "$2")
  179. outfile=$(tempfile)
  180. wget --timeout=$remote_timeout \
  181. --tries=$(( $remote_retries + 1 )) \
  182. --output-document="$outfile" \
  183. "$baseurl"
  184. ec=$?
  185. if [ $? -ne 0 ];then
  186. print_err "Failed to download url with wget."
  187. return $ec
  188. fi
  189. search_string=$(expand_version_pattern $src_tar_pattern "$1" "$2" "*")
  190. grep -o "href=\"$search_string\"" "$outfile" | grep -o "$search_string"
  191. rm "$outfile"
  192. }
  193. # function parse_value_from_template()
  194. # Match "$target" against "$template" and print
  195. # the first occurrence in "$target"
  196. # that matches the "$placeholder" part in "$template"
  197. # i.e. parse "$placeholder" out of "$target" using "$template"
  198. # $1 = template
  199. # $2 = target
  200. # $3 = placeholder
  201. # $4 = matching pattern
  202. parse_value_from_template()
  203. {
  204. template=$1
  205. target=$2
  206. phold=$3
  207. # replace $phold with a matching group in $template
  208. search_fmt=$(sed "s/$phold/($4)/g" <<< $template)
  209. [[ $target =~ $search_fmt ]] &&
  210. echo ${BASH_REMATCH[1]}
  211. }
  212. # function parse_version_from_filename()
  213. # Extract the version string from the given filename
  214. # and print it to stdout
  215. # $1 = filename matching $src_tar_pattern
  216. parse_version_from_filename()
  217. {
  218. if [ -z "$1" ];then
  219. print_err "Failed parsing version: empty file name received;"
  220. return 1
  221. fi
  222. anynum="[0-9]{1,}"
  223. set -x
  224. template_ver=$(expand_version_pattern "$src_tar_pattern" "VER" "$anynum" "$anynum")
  225. template_maj=$(expand_version_pattern "$src_tar_pattern" "$anynum" "MAJ" "$anynum")
  226. template_min=$(expand_version_pattern "$src_tar_pattern" "$anynum" "$anynum" "MIN")
  227. ver=$(parse_value_from_template "$template_ver" "$1" "VER" "$anynum")
  228. maj=$(parse_value_from_template "$template_maj" "$1" "MAJ" "$anynum")
  229. min=$(parse_value_from_template "$template_min" "$1" "MIN" "$anynum")
  230. echo "${ver}.${maj}.${min}"
  231. }
  232. # function get_latest_src_kver()
  233. # Check the upstream url for the latest source release.
  234. # Print the latest version available in the format 'w.x.y'
  235. # $1 = main version number ('w')
  236. # $2 = major revision number ('x')
  237. get_latest_src_kver()
  238. {
  239. case $remote_tool in
  240. wget)
  241. fname=$(wget_search_url_pattern $1 $2)
  242. ;;
  243. rsync)
  244. fname=$(rsync_search_url_pattern $1 $2)
  245. ;;
  246. *)
  247. print_err "Unknown remote tool: $remote_tool"
  248. return 1
  249. esac
  250. echo $fname
  251. parse_version_from_filename "$fname"
  252. }