download_externals 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #!/usr/bin/env bash
  2. if [[ ( ${BASH_VERSINFO[0]} == 4 && ${BASH_VERSINFO[1]} > 1 ) || ${BASH_VERSINFO[0]} > 4 ]] ; then
  3. shopt -s compat41
  4. fi
  5. set -e
  6. ASTTOPDIR=${ASTTOPDIR:-.}
  7. export make=`sed -n -r -e "s/^MAKE\s*=\s*//gp" ${ASTTOPDIR}/makeopts`
  8. getvar() {
  9. $make --quiet --no-print-directory -f- <<EOF
  10. include ${ASTTOPDIR}/makeopts
  11. all:
  12. @echo "\$($1)"
  13. EOF
  14. }
  15. XMLSTARLET=`getvar XMLSTARLET`
  16. ASTMODDIR=`getvar ASTMODDIR`
  17. cache_dir=`getvar EXTERNALS_CACHE_DIR`
  18. DOWNLOAD_TO_STDOUT=`getvar DOWNLOAD_TO_STDOUT`
  19. HOST_CPU=`getvar HOST_CPU`
  20. INSTALL=`getvar INSTALL`
  21. module_name=${1%%-*}
  22. variant=${1##*-}
  23. if [[ "${variant}" = "${module_name}" ]] ; then
  24. unset variant
  25. fi
  26. if [[ -z ${module_name} ]] ; then
  27. echo "You must supply a module name."
  28. exit 64
  29. fi
  30. tmpdir=$(mktemp -d)
  31. if [[ -z "${tmpdir}" ]] ; then
  32. echo "${module_name}: Unable to create temporary directory."
  33. exit 1
  34. fi
  35. trap "rm -rf ${tmpdir}" EXIT
  36. if [[ -z "${ASTMODDIR}" ]] ; then
  37. echo "${module_name}: Unable to parse ${ASTTOPDIR}/makeopts."
  38. exit 1
  39. fi
  40. if [[ "${XMLSTARLET}" = ":" ]] ; then
  41. echo "${module_name}: The externals downloader requires xmlstarlet to be installed."
  42. exit 1
  43. fi
  44. if [[ -z ${cache_dir} ]] ; then
  45. cache_dir=${tmpdir}
  46. fi
  47. version=$(${ASTTOPDIR}/build_tools/make_version ${ASTTOPDIR})
  48. if [[ ! ${version} =~ ^(GIT-)?(certified/)?([^.-]+)[.-].* ]] ; then
  49. echo "${module_name}: Couldn't parse version ${version}"
  50. exit 1
  51. fi
  52. major_version=${BASH_REMATCH[3]}
  53. if [[ "${major_version}" == "master" ]] ; then
  54. echo "${module_name}: External module downloading is not available in the 'master' git branch. Please disable in menuselect and download manually."
  55. exit 1
  56. fi
  57. major_version=${major_version}.0
  58. if [[ "${HOST_CPU}" = "x86_64" ]] ; then
  59. host_bits=64
  60. else
  61. host_bits=32
  62. fi
  63. if [[ -z "${variant}" ]] ; then
  64. variants=$(${XMLSTARLET} sel -t -m "/menu/category/member[@name = '${module_name}']/member_data/downloader/variants/variant" -v "@tag" -n ${ASTTOPDIR}/menuselect-tree || :)
  65. member_name=${module_name}
  66. for tag in ${variants} ; do
  67. condition=$(${XMLSTARLET} sel -t -v "/menu/category/member[@name = '${module_name}']/member_data/downloader/variants/variant[@tag = '${tag}']/@condition" ${ASTTOPDIR}/menuselect-tree || :)
  68. variant=$(eval "if $condition ; then echo $tag ; fi")
  69. if [[ -n "${variant}" ]] ; then
  70. break
  71. fi
  72. done
  73. else
  74. member_name=${module_name}${variant:+-${variant}}
  75. fi
  76. full_name=${module_name}${variant:+-${variant}}
  77. variant_manifest=manifest${variant:+-${variant}}.xml
  78. # Override the remote base for all packages
  79. # useful for testing
  80. remote_url=${REMOTE_BASE:+${REMOTE_BASE}/asterisk-${major_version}/x86-${host_bits}}
  81. if [[ -z "${remote_url}" ]] ; then
  82. remote_url=$(${XMLSTARLET} sel -t -v "/menu/category/member[@name = '${member_name}']/member_data/downloader/@remote_url" ${ASTTOPDIR}/menuselect-tree || :)
  83. if [[ -n "${remote_url}" ]] ; then
  84. remote_url="${remote_url}/asterisk-${major_version}/x86-${host_bits}"
  85. else
  86. directory_name=$(${XMLSTARLET} sel -t -v "/menu/category/member[@name = '${member_name}']/member_data/downloader/@directory_name" ${ASTTOPDIR}/menuselect-tree || :)
  87. remote_url="http://downloads.digium.com/pub/telephony/${directory_name:-${module_name}}/asterisk-${major_version}/x86-${host_bits}"
  88. fi
  89. fi
  90. version_convert() {
  91. local v=${1##*_}
  92. if [[ ${v} =~ ([0-9]+)[.]([0-9]+)[.]([0-9]+) ]] ; then
  93. v=$(( ${BASH_REMATCH[1]}<<18 | ${BASH_REMATCH[2]}<<9 | ${BASH_REMATCH[3]} ))
  94. fi
  95. echo ${v}
  96. }
  97. ${DOWNLOAD_TO_STDOUT} ${remote_url}/${variant_manifest} > ${tmpdir}/${variant_manifest} || {
  98. echo "${full_name}: Unable to fetch ${remote_url}/${variant_manifest}"
  99. exit 1
  100. }
  101. rpv=$(${XMLSTARLET} sel -t -v "/package/@version" ${tmpdir}/${variant_manifest})
  102. rpvi=$(version_convert ${rpv})
  103. echo "${full_name}: Remote package version ${rpv} (${rpvi})"
  104. module_dir=${full_name}-${rpv}-x86_${host_bits}
  105. tarball=${module_dir}.tar.gz
  106. export need_install=0
  107. if [[ -f ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml ]] ; then
  108. package_arch=$(${XMLSTARLET} sel -t -v "/package/@arch" ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml)
  109. ipv=$(${XMLSTARLET} sel -t -v "/package/@version" ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml)
  110. package_variant=$(${XMLSTARLET} sel -t -v "/package/@variant" ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml || :)
  111. ipvi=$(version_convert ${ipv})
  112. ip_major=${ipv%_*}
  113. echo "${full_name}: Installed package version ${ipv} (${ipvi})"
  114. if [[ "${ip_major}" != "${major_version}" || "${package_arch}" != "x86_${host_bits}" || "${package_variant}" != "${variant}" ]] ; then
  115. echo "${full_name}: The installed package is not for this version of Asterisk. Reinstalling."
  116. need_install=1
  117. elif [[ ${rpvi} > ${ipvi} ]] ; then
  118. echo "${full_name}: A newer package is available"
  119. need_install=1
  120. else
  121. sums=$(${XMLSTARLET} sel -t -m "//file" -v "@md5sum" -n ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml)
  122. for sum in ${sums} ; do
  123. install_path=$(${XMLSTARLET} sel -t -v "//file[@md5sum = '${sum}']/@install_path" ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml )
  124. executable=$(${XMLSTARLET} sel -t -v "//file[@md5sum = '${sum}']/@executable" ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml || : )
  125. f=${DESTDIR}$(eval echo ${install_path})
  126. if [[ ! -f ${f} ]] ; then
  127. echo Not found: ${f}
  128. need_install=1
  129. break
  130. else
  131. if [[ "$executable" = "yes" ]] ; then
  132. # There are easier ways of doing this (objcopy --dump-section) but not in older bunutils
  133. length_offset=$(objdump -h $f | sed -n -r -e "s/^\s+[0-9]+\s+.ast_manifest\s+([0-9a-fA-F]+)\s+[0-9a-fA-F]+\s+[0-9a-fA-F]+\s+([0-9a-fA-F]+)\s+.*$/0x\1 0x\2/p")
  134. tags=$($(eval 'printf "dd if=$f bs=1 count=%d skip=%d\n" $length_offset') 2>/dev/null)
  135. if [[ -n "${tags}" && "${tags}" != "${module_name},${variant},${rpv}" ]] ; then
  136. echo Tag mismatch: ${f} File: "${tags}" Manifest: "${module_name},${variant},${rpv}"
  137. need_install=1
  138. break
  139. fi
  140. fi
  141. cs=$(${MD5} ${f} | cut -b1-32)
  142. if [[ "${cs}" != "${sum}" ]] ; then
  143. echo Checksum mismatch: ${f}
  144. need_install=1
  145. break
  146. fi
  147. fi
  148. done
  149. fi
  150. else
  151. need_install=1
  152. fi
  153. if [[ ${need_install} == 1 ]] ; then
  154. if [[ ( -n "${ipvi}" ) && ${ipvi} > ${rpvi} ]] ; then
  155. echo "${full_name}: Installed package is newer than that available for download."
  156. exit 0
  157. fi
  158. else
  159. echo "${full_name} is up to date."
  160. exit 0;
  161. fi
  162. need_download=1
  163. if [[ -f ${cache_dir}/${full_name}.manifest.xml ]] ; then
  164. cpv=$(${XMLSTARLET} sel -t -v "/package/@version" ${cache_dir}/${full_name}.manifest.xml)
  165. cpvi=$(version_convert ${cpv})
  166. echo "${full_name}: Cached package version ${cpv} (${cpvi})"
  167. if [[ ${cpvi} == ${rpvi} && ( -f ${cache_dir}/${tarball} ) ]] ; then
  168. echo "${full_name}: Cached version is available."
  169. need_download=0
  170. fi
  171. fi
  172. if [[ ${need_download} = 1 ]] ; then
  173. echo "${full_name}: Downloading ${remote_url}/${tarball} to ${cache_dir}/${tarball}"
  174. ${DOWNLOAD_TO_STDOUT} ${remote_url}/${tarball} > ${cache_dir}/${tarball} || {
  175. echo "${full_name}: Unable to fetch ${remote_url}/${tarball}"
  176. exit 1
  177. }
  178. cp ${tmpdir}/${variant_manifest} ${cache_dir}/${full_name}.manifest.xml
  179. fi
  180. tar -xzf ${cache_dir}/${tarball} -C ${cache_dir}
  181. trap "rm -rf ${cache_dir}/${module_dir} ; rm -rf ${tmpdir}" EXIT
  182. echo "${full_name}: Installing."
  183. if [[ $EUID == 0 ]] ; then
  184. install_params="-g 0 -o 0"
  185. fi
  186. names=$(${XMLSTARLET} sel -t -m "//file" -v "@name" -n ${cache_dir}/${module_dir}/manifest.xml)
  187. for name in ${names} ; do
  188. source_path=${cache_dir}/${module_dir}/${name}
  189. install_path=$(${XMLSTARLET} sel -t -v "//file[@name = '${name}']/@install_path" ${cache_dir}/${module_dir}/manifest.xml)
  190. install_path=${DESTDIR}$(eval echo ${install_path})
  191. executable=$(${XMLSTARLET} sel -t -v "//file[@name = '${name}']/@executable" ${cache_dir}/${module_dir}/manifest.xml || :)
  192. if [[ "${executable}" = "yes" ]] ; then
  193. mode=0755
  194. else
  195. mode=0644
  196. fi
  197. ${INSTALL} -Dp ${install_params} -m ${mode} ${source_path} ${install_path}
  198. done
  199. ${INSTALL} -Dp ${install_params} --mode=0644 ${cache_dir}/${module_dir}/manifest.xml ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml
  200. echo "${full_name}: Installed."