jinx 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972
  1. #! /bin/sh
  2. # Copyright (C) 2022-2024 mintsuki
  3. # Redistribution and use in source and binary forms, with or without
  4. # modification, are permitted provided that the following conditions are met:
  5. # 1. Redistributions of source code must retain the above copyright notice,
  6. # this list of conditions and the following disclaimer.
  7. # 2. Redistributions in binary form must reproduce the above copyright notice,
  8. # this list of conditions and the following disclaimer in the documentation
  9. # and/or other materials provided with the distribution.
  10. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  11. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  12. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  13. # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  14. # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  15. # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  16. # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  17. # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  18. # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  19. # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  20. # POSSIBILITY OF SUCH DAMAGE.
  21. set -e
  22. IFS=" "" "'
  23. '
  24. LC_COLLATE=C
  25. export LC_COLLATE
  26. umask 0022
  27. jinx_major_ver="0.4"
  28. jinx_minor_ver="7"
  29. jinx_version="${jinx_major_ver}.${jinx_minor_ver}"
  30. die() {
  31. echo "$1"
  32. exit 1
  33. }
  34. case "$1" in
  35. version|--version)
  36. echo "Jinx version $jinx_version"
  37. exit 0
  38. ;;
  39. esac
  40. if ! [ "$(uname -s)" = "Linux" ]; then
  41. die "$0: Jinx only supports running on Linux hosts."
  42. fi
  43. if [ "$(id -u)" = "0" ]; then
  44. die "$0: Jinx does not support running as root."
  45. fi
  46. debian_snapshot="20241203T084120Z"
  47. case "$(uname -m)" in
  48. x86_64)
  49. debian_architecture=amd64
  50. debian_rootfs_b2sum=9e5ca2b7d987c3ac1d463a20fc57fe3bca0189663118d0dd97869dff9e4eb94935f55ede26cba3df89be16cce17a7bc1dbe78f3f0ad646833a323bfc7ca29e82
  51. ;;
  52. aarch64)
  53. debian_architecture=arm64
  54. debian_rootfs_b2sum=196ed3de6038b3b0d71d2edff1949a0fc21ee63f9e302453f3b8df13971fb7e544d728f3b6fd033495669b8a23a9f5141e31d2b74a9e919b3f2d840998cae4c2
  55. ;;
  56. arm*)
  57. debian_architecture=armhf
  58. debian_rootfs_b2sum=14248e197538f3c26ef08d48c0827dcd5dfe0ddb6964fd2766095302ef8f3742f9bd280ec775bc9ffeb985085ba1691275e84c482e26a8c4119dc03acd3b9504
  59. ;;
  60. i?86)
  61. debian_architecture=i386
  62. debian_rootfs_b2sum=c55b07876f97530a9315f18b62632b89e5839bcb2eb5d4b75b047ce5a392c6a5aec9b24e38e06b994a6a45c8476dad48b8fedbe6576534c1816eb8f329d46cb9
  63. ;;
  64. mips64el)
  65. debian_architecture=mips64el
  66. debian_rootfs_b2sum=2bf08471d53eeec532cdbe2b0dc0f8d6fc020f8b12a2fe8b0c4f26733525ec1b47be605e8d9e906aa91e22be7cfe68285877130fd51c207efce81833977d74df
  67. ;;
  68. ppc64le)
  69. debian_architecture=ppc64el
  70. debian_rootfs_b2sum=57028eedb1edaa27497ed4e607ac814256569c31472fb32c37bdc8fc09100471ebda6abbd6d7b3d670ab1d4f23a3dd67c9a9bf0c8f3a5b841920d871699406f4
  71. ;;
  72. riscv64)
  73. debian_architecture=riscv64
  74. debian_rootfs_b2sum=5efb44776a3fae5f14cfdb711b0408b4b0842172dc67ce524a77545467bf163dea07c2017c0a823f3585f36a0ee28b52ec7f4490ed620017ee6e8c33cea722d0
  75. ;;
  76. s390x)
  77. debian_architecture=s390x
  78. debian_rootfs_b2sum=776f818f15ca2c506d8a553eb036d7bfea33fe6c74f9134198e0b37e38b3a0eefdf9b8a9862d41dd0baddde610ebd7b626e2019c9359b8c4b43326339382fcf0
  79. ;;
  80. *)
  81. die "$0: Unsupported architecture: $(uname -m)"
  82. ;;
  83. esac
  84. XSTOW_VERSION=1.1.1
  85. make_dir() {
  86. for d in "$@"; do
  87. mkdir -p "$d"
  88. dn="$(cd "$d" && pwd -P)"
  89. while true; do
  90. if [ "$dn" = "$base_dir" ] || [ "$dn" = "$build_dir" ] || [ "$dn" = "/" ]; then
  91. break
  92. fi
  93. chmod 755 "$dn"
  94. dn="$(dirname "$dn")"
  95. done
  96. done
  97. }
  98. if [ -z "$JINX_PARALLELISM" ]; then
  99. max_threads_by_mem="$(( ((($(free | awk '/^Mem:/{print $2}') + 1048575) / 1048576) + 1) / 2 ))"
  100. parallelism="$(nproc 2>/dev/null || echo 1)"
  101. parallelism="$(( $parallelism < $max_threads_by_mem ? $parallelism : $max_threads_by_mem ))"
  102. else
  103. parallelism="$JINX_PARALLELISM"
  104. fi
  105. build_dir="$(pwd -P)"
  106. if [ -z "$JINX_SOURCE_DIR" ]; then
  107. base_dir="$build_dir"
  108. else
  109. base_dir="$(cd "$JINX_SOURCE_DIR" && pwd -P)"
  110. fi
  111. script_name="$(basename "$0")"
  112. script_dir="$(dirname "$0")"
  113. if [ "$script_dir" = "." ] || [ -z "$script_dir" ]; then
  114. if echo "$0" | grep "/" >/dev/null 2>&1; then
  115. script_dir=.
  116. else
  117. script_dir="$(dirname $(which "${script_name}"))"
  118. fi
  119. fi
  120. script_dir="$(cd "${script_dir}" && pwd -P)"
  121. script="${script_dir}/${script_name}"
  122. if [ -z "$JINX_CONFIG_FILE" ]; then
  123. JINX_CONFIG_FILE="${base_dir}/jinx-config"
  124. fi
  125. if ! [ -d "$(dirname "$JINX_CONFIG_FILE")" ]; then
  126. die "$0: cannot access config file directory"
  127. fi
  128. JINX_CONFIG_FILE="$(cd "$(dirname "$JINX_CONFIG_FILE")" && pwd -P)"/"$(basename "$JINX_CONFIG_FILE")"
  129. if [ -z "$JINX_CACHE_DIR" ]; then
  130. JINX_CACHE_DIR="${build_dir}/.jinx-cache"
  131. fi
  132. if ! [ -d "$(dirname "$JINX_CACHE_DIR")" ]; then
  133. die "$0: cannot access cache directory parent"
  134. fi
  135. make_dir "$JINX_CACHE_DIR"
  136. JINX_CACHE_DIR="$(cd "$JINX_CACHE_DIR" && pwd -P)"
  137. in_container=false
  138. if [ "$script" = "//jinx" ]; then
  139. in_container=true
  140. fi
  141. if [ "$in_container" = "false" ]; then
  142. make_dir "${base_dir}/sources" "${build_dir}/host-builds" "${build_dir}/host-pkgs" "${build_dir}/builds" "${build_dir}/pkgs"
  143. fi
  144. apt_cache="$JINX_CACHE_DIR/apt-cache"
  145. temp_collect=""
  146. trap 'eval rm -rf "$temp_collect"' EXIT
  147. make_temp() {
  148. tmp="$(mktemp "$JINX_CACHE_DIR/tmp.XXXXXXXX")"
  149. temp_collect="${temp_collect} \"${tmp}\""
  150. if [ "$1" = "-d" ]; then
  151. rm -f "${tmp}"
  152. make_dir "${tmp}"
  153. fi
  154. }
  155. build_hostdeps() {
  156. for hostdep in ${hostdeps} ${hostrundeps}; do
  157. [ -f "${base_dir}"/host-recipes/${hostdep} ] || die "missing host dependency '${hostdep}' for recipe '${name}'"
  158. [ -d "${build_dir}"/host-pkgs/${hostdep} ] && continue
  159. "${script}" host-build ${hostdep}
  160. done
  161. }
  162. build_deps() {
  163. for dep in ${deps} ${builddeps}; do
  164. [ -f "${base_dir}"/recipes/${dep} ] || die "missing dependency '${dep}' for recipe '${name}'"
  165. [ -d "${build_dir}"/pkgs/${dep} ] && continue
  166. "${script}" build ${dep}
  167. done
  168. }
  169. get_hostdeps_file_run() {
  170. deps_to_do=""
  171. for hostdep in ${hostrundeps}; do
  172. grep " ${hostdep} " "${hostdeps_file}" >/dev/null 2>&1 || deps_to_do="${deps_to_do} ${hostdep}"
  173. grep " ${hostdep} " "${hostdeps_file}" >/dev/null 2>&1 || printf " ${hostdep} " >> "${hostdeps_file}"
  174. done
  175. for hostdep in ${deps_to_do}; do
  176. "${script}" internal-get-hostdeps-file-run ${hostdep} "${hostdeps_file}"
  177. done
  178. }
  179. get_hostdeps_file() {
  180. deps_to_do=""
  181. for hostdep in ${hostdeps} ${hostrundeps}; do
  182. grep " ${hostdep} " "${hostdeps_file}" >/dev/null 2>&1 || deps_to_do="${deps_to_do} ${hostdep}"
  183. grep " ${hostdep} " "${hostdeps_file}" >/dev/null 2>&1 || printf " ${hostdep} " >> "${hostdeps_file}"
  184. done
  185. for hostdep in ${deps_to_do}; do
  186. "${script}" internal-get-hostdeps-file-run ${hostdep} "${hostdeps_file}"
  187. done
  188. }
  189. get_builddeps_file() {
  190. deps_to_do=""
  191. for dep in ${deps} ${builddeps}; do
  192. grep " ${dep} " "${deps_file}" >/dev/null 2>&1 || deps_to_do="${deps_to_do} ${dep}"
  193. grep " ${dep} " "${deps_file}" >/dev/null 2>&1 || printf " ${dep} " >> "${deps_file}"
  194. done
  195. for dep in ${deps_to_do}; do
  196. "${script}" internal-get-deps-file ${dep} "${deps_file}"
  197. done
  198. }
  199. get_deps_file() {
  200. deps_to_do=""
  201. for dep in ${deps}; do
  202. grep " ${dep} " "${deps_file}" >/dev/null 2>&1 || deps_to_do="${deps_to_do} ${dep}"
  203. grep " ${dep} " "${deps_file}" >/dev/null 2>&1 || printf " ${dep} " >> "${deps_file}"
  204. done
  205. for dep in ${deps_to_do}; do
  206. "${script}" internal-get-deps-file ${dep} "${deps_file}"
  207. done
  208. }
  209. run_in_container1() {
  210. if ! [ -z "$TERM" ]; then
  211. run_in_cont1_term="--env TERM=\"$TERM\""
  212. fi
  213. if ! [ -z "$COLORTERM" ]; then
  214. run_in_cont1_colorterm="--env COLORTERM=\"$COLORTERM\""
  215. fi
  216. run_in_cont1_root="$1"
  217. shift 1
  218. "$JINX_CACHE_DIR/rbrt" \
  219. --root "$run_in_cont1_root" rw \
  220. --uid 0 \
  221. --gid 0 \
  222. --env HOME=/root \
  223. --env LANG=en_US.UTF-8 \
  224. --env LC_COLLATE=C \
  225. --env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin \
  226. --env LD_LIBRARY_PATH=/usr/local/lib64:/usr/local/lib:/usr/lib64:/usr/lib \
  227. ${run_in_cont1_term} \
  228. ${run_in_cont1_colorterm} \
  229. -m"${apt_cache}":/var/cache/apt/archives \
  230. -- \
  231. "$@"
  232. }
  233. check_duplicates() {
  234. for elem in $(cd "$1" && find .); do
  235. if [ -f "$2"/${elem} ] || [ -L "$2"/${elem} ]; then
  236. return 1
  237. fi
  238. done
  239. }
  240. prepare_container() {
  241. cd "${build_dir}"
  242. make_temp
  243. hostdeps_file="${tmp}"
  244. make_temp
  245. deps_file="${tmp}"
  246. build_hostdeps
  247. build_deps
  248. get_hostdeps_file
  249. get_builddeps_file
  250. make_temp -d
  251. container_pkgs="${tmp}"
  252. make_temp -d
  253. sysroot_dir="${tmp}"
  254. rm -rf "$JINX_CACHE_DIR"/saved-info-dir
  255. for dep in $(cat "${deps_file}"); do
  256. if [ -f "${build_dir}"/pkgs/${dep}/usr/share/info/dir ]; then
  257. mv "${build_dir}"/pkgs/${dep}/usr/share/info/dir "$JINX_CACHE_DIR"/saved-info-dir
  258. fi
  259. copy_failed=0
  260. check_duplicates "${build_dir}"/pkgs/${dep} "${sysroot_dir}" || copy_failed=1
  261. cp -Pplr "${build_dir}"/pkgs/${dep}/. "${sysroot_dir}"/
  262. if [ -f "$JINX_CACHE_DIR"/saved-info-dir ]; then
  263. mv "$JINX_CACHE_DIR"/saved-info-dir "${build_dir}"/pkgs/${dep}/usr/share/info/dir
  264. fi
  265. if [ "$copy_failed" = 1 ]; then
  266. die "jinx: error: Dependency '${dep}' contains file confilcts"
  267. fi
  268. done
  269. if [ "$JINX_NATIVE_MODE" = "yes" ] && [ -z "$cross_compile" ]; then
  270. imgroot="${sysroot_dir}"
  271. else
  272. for hostdep in $(cat "${hostdeps_file}"); do
  273. if [ -f "${build_dir}"/host-pkgs/${hostdep}/usr/local/share/info/dir ]; then
  274. mv "${build_dir}"/host-pkgs/${hostdep}/usr/local/share/info/dir "$JINX_CACHE_DIR"/saved-info-dir
  275. fi
  276. copy_failed=0
  277. check_duplicates "${build_dir}"/host-pkgs/${hostdep}/usr/local "${container_pkgs}" || copy_failed=1
  278. cp -Pplr "${build_dir}"/host-pkgs/${hostdep}/usr/local/. "${container_pkgs}"/
  279. if [ -f "$JINX_CACHE_DIR"/saved-info-dir ]; then
  280. mv "$JINX_CACHE_DIR"/saved-info-dir "${build_dir}"/host-pkgs/${hostdep}/usr/local/share/info/dir
  281. fi
  282. if [ "$copy_failed" = 1 ]; then
  283. die "jinx: error: Dependency '${hostdep}' contains file confilcts"
  284. fi
  285. done
  286. imagedeps="$(echo "${imagedeps}" | xargs -n1 | sort -u | xargs)"
  287. pkgset=""
  288. for pkg in ${imagedeps}; do
  289. pkgset="${pkgset}${pkg}/"
  290. if [ -f "$JINX_CACHE_DIR/sets/${pkgset}.image/.jinx-set-valid" ]; then
  291. continue
  292. fi
  293. make_dir "$JINX_CACHE_DIR/sets/${pkgset}"
  294. cp -Pplrf "$JINX_CACHE_DIR/sets/${pkgset}../.image" "$JINX_CACHE_DIR/sets/${pkgset}.image"
  295. rm -f "$JINX_CACHE_DIR/sets/${pkgset}.image/.jinx-set-valid"
  296. if ! run_in_container1 "$JINX_CACHE_DIR/sets/${pkgset}.image" apt-get install -y "${pkg}"; then
  297. die 'Jinx error: Installing an imagedep failed.'
  298. fi
  299. # Fix permissions of files
  300. for f in $(find "$JINX_CACHE_DIR/sets/${pkgset}.image" -perm 000 2>/dev/null); do
  301. chmod 755 "$f"
  302. done
  303. touch "$JINX_CACHE_DIR/sets/${pkgset}.image/.jinx-set-valid"
  304. done
  305. imgroot="$JINX_CACHE_DIR/sets/${pkgset}.image"
  306. fi
  307. }
  308. run_in_container() {
  309. if [ "${allow_network}" = "yes" ]; then
  310. unshare_net_flag=""
  311. else
  312. unshare_net_flag="-n"
  313. fi
  314. if [ ! -z "$TERM" ]; then
  315. run_in_cont_term="--env TERM=\"$TERM\""
  316. fi
  317. if ! [ -z "$COLORTERM" ]; then
  318. run_in_cont_colorterm="--env COLORTERM=\"$COLORTERM\""
  319. fi
  320. touch "${imgroot}/jinx"
  321. chmod +x "${imgroot}/jinx"
  322. touch "${imgroot}/jinx-config"
  323. make_dir "${imgroot}/base_dir" "${imgroot}/sources" "${imgroot}/build_dir"
  324. native_mode_mounts=""
  325. if ( [ "$JINX_NATIVE_MODE" = "yes" ] && [ "$cross_compile" = "yes" ] ) || ( ! [ "$JINX_NATIVE_MODE" = "yes" ] ); then
  326. make_dir "${imgroot}/sysroot"
  327. container_pkgs_native_mount="-m${container_pkgs}:/usr/local:ro"
  328. sysroot_native_mount="-m${sysroot_dir}:/sysroot:ro"
  329. run_in_cont_lang=en_US.UTF-8
  330. else
  331. if ! [ -z "$JINX_NATIVE_LANG" ]; then
  332. run_in_cont_lang="$JINX_NATIVE_LANG"
  333. else
  334. run_in_cont_lang=C
  335. fi
  336. fi
  337. run_in_cont_argvar=""
  338. for arg in "$@"; do
  339. run_in_cont_argvar="$run_in_cont_argvar \"$arg\""
  340. done
  341. shadow_git_dir_build=""
  342. if [ -d "${build_dir}"/.git ]; then
  343. make_temp -d
  344. shadow_git_dir_build="-m${tmp}:/build_dir/.git"
  345. fi
  346. shadow_git_dir_base=""
  347. if [ -d "${base_dir}"/.git ]; then
  348. make_temp -d
  349. shadow_git_dir_base="-m${tmp}:/base_dir/.git"
  350. fi
  351. "$JINX_CACHE_DIR/rbrt" \
  352. --root "${imgroot}" \
  353. --uid $(id -u) \
  354. --gid $(id -g) \
  355. --env HOME=/root \
  356. --env LANG=${run_in_cont_lang} \
  357. --env LC_COLLATE=C \
  358. --env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin \
  359. --env LD_LIBRARY_PATH=/usr/local/lib64:/usr/local/lib:/usr/lib64:/usr/lib \
  360. ${run_in_cont_term} \
  361. ${run_in_cont_colorterm} \
  362. --env JINX_PARALLELISM="$parallelism" \
  363. --env JINX_CONFIG_FILE=/jinx-config \
  364. --env JINX_SOURCE_DIR=/base_dir \
  365. ${container_pkgs_native_mount:+"${container_pkgs_native_mount}"} \
  366. ${sysroot_native_mount:+"${sysroot_native_mount}"} \
  367. -m"${script}":/jinx:ro \
  368. -m"${JINX_CONFIG_FILE}":/jinx-config:ro \
  369. -m"${base_dir}":/base_dir${container_base_dir_ro} \
  370. ${shadow_git_dir_base:+"${shadow_git_dir_base}"} \
  371. -m"${base_dir}"/sources:/base_dir/sources${container_sources_ro} \
  372. -m"${build_dir}":/build_dir \
  373. ${shadow_git_dir_build:+"${shadow_git_dir_build}"} \
  374. ${unshare_net_flag} \
  375. --workdir / \
  376. -- \
  377. /bin/bash -c "cd /build_dir && /bin/bash /jinx $run_in_cont_argvar"
  378. rm -rf "${imgroot}/sysroot" "${imgroot}/jinx" "${imgroot}/jinx-config" "${imgroot}/base_dir" "${imgroot}/sources" "${imgroot}/build_dir"
  379. }
  380. destroy_container() {
  381. rm -rf "${container_pkgs}" "${sysroot_dir}"
  382. }
  383. do_hg_fetch() {
  384. [ -d "${source_dir}" ] && return
  385. hg clone "${hg_url}" "${base_dir}"/sources/${name}
  386. ( cd "${base_dir}"/sources/${name} && hg up "${tag}" )
  387. }
  388. do_git_fetch() {
  389. [ -d "${source_dir}" ] && return
  390. if ! [ -z "${commit}" ]; then
  391. git clone "${git_url}" "${base_dir}"/sources/${name}
  392. ( cd "${base_dir}"/sources/${name} && git checkout ${commit} )
  393. elif [ "${shallow}" = "no" ]; then
  394. git clone "${git_url}" --branch="${branch}" "${base_dir}"/sources/${name}
  395. else
  396. git clone "${git_url}" --branch="${branch}" --depth=1 "${base_dir}"/sources/${name}
  397. fi
  398. }
  399. do_tarball_fetch() {
  400. [ -d "${source_dir}" ] && return
  401. tarball_path="${base_dir}"/sources/"$(basename "${tarball_url}")"
  402. if ! [ -f "$tarball_path" ]; then
  403. make_temp
  404. download_path="${tmp}"
  405. curl -L -o "${download_path}" "${tarball_url}"
  406. mv "${download_path}" "${tarball_path}"
  407. fi
  408. checksum_verified=no
  409. if ! [ -z "${tarball_sha256}" ]; then
  410. actual_sha256="$(sha256sum "${tarball_path}" | awk '{print $1;}')"
  411. if ! [ ${actual_sha256} = ${tarball_sha256} ]; then
  412. die "* error: Failed to verify SHA256 for ${name}.
  413. Expected '${tarball_sha256}';
  414. got '${actual_sha256}'."
  415. fi
  416. checksum_verified=yes
  417. fi
  418. if ! [ -z "${tarball_sha512}" ]; then
  419. actual_sha512="$(sha512sum "${tarball_path}" | awk '{print $1;}')"
  420. if ! [ ${actual_sha512} = ${tarball_sha512} ]; then
  421. die "* error: Failed to verify SHA512 for ${name}.
  422. Expected '${tarball_sha512}';
  423. got '${actual_sha512}'."
  424. fi
  425. checksum_verified=yes
  426. fi
  427. if ! [ -z "${tarball_blake2b}" ]; then
  428. actual_blake2b="$("$JINX_CACHE_DIR/b2sum" "${tarball_path}" | awk '{print $1;}')"
  429. if ! [ ${actual_blake2b} = ${tarball_blake2b} ]; then
  430. die "* error: Failed to verify BLAKE2B for ${name}.
  431. Expected '${tarball_blake2b}';
  432. got '${actual_blake2b}'."
  433. fi
  434. checksum_verified=yes
  435. fi
  436. if [ "${checksum_verified}" = "no" ]; then
  437. die "* error: No checksum method specified for ${name}"
  438. fi
  439. make_temp -d
  440. extract_dir="${tmp}"
  441. ( cd "${extract_dir}" && tar -xf "${tarball_path}" )
  442. mv "${extract_dir}"/* "${base_dir}"/sources/${name} >/dev/null 2>&1 || (
  443. make_dir "${base_dir}"/sources/${name}
  444. mv "${extract_dir}"/* "${base_dir}"/sources/${name}/
  445. )
  446. rm -rf "${extract_dir}" "${tarball_path}"
  447. }
  448. get_real_source_dir() {
  449. if [ -z "${source_dir}" ]; then
  450. source_dir="${base_dir}"/sources/${name}
  451. else
  452. source_dir="${base_dir}"/"${source_dir}"
  453. is_local_package=true
  454. fi
  455. }
  456. do_fetch() {
  457. make_dir "${base_dir}"/sources
  458. if ! [ -z "${git_url}" ]; then
  459. do_git_fetch
  460. elif ! [ -z "${hg_url}" ]; then
  461. do_hg_fetch
  462. elif ! [ -z "${tarball_url}" ]; then
  463. do_tarball_fetch
  464. fi
  465. }
  466. default_recipe_steps() {
  467. prepare() {
  468. true
  469. }
  470. configure() {
  471. true
  472. }
  473. build() {
  474. true
  475. }
  476. package() {
  477. true
  478. }
  479. }
  480. source_source_recipe() {
  481. if [ -f "${base_dir}"/source-recipes/$1 ]; then
  482. . "${base_dir}"/source-recipes/$1
  483. elif [ -f "${base_dir}"/recipes/$1 ]; then
  484. . "${base_dir}"/recipes/$1
  485. unset deps
  486. unset builddeps
  487. unset hostrundeps
  488. imagedeps="${source_imagedeps}"
  489. hostdeps="${source_hostdeps}"
  490. deps="${source_deps}"
  491. allow_network="${source_allow_network}"
  492. else
  493. die "* could not find source recipe '$1'"
  494. fi
  495. }
  496. cont_patch() {
  497. source_source_recipe $1
  498. get_real_source_dir
  499. make_temp
  500. patch_trash="${tmp}"
  501. cd "${source_dir}"
  502. if [ -d "${base_dir}"/patches/${name} ]; then
  503. for patch in "${base_dir}"/patches/${name}/*; do
  504. [ "${patch}" = "${base_dir}/patches/${name}/*" ] && break
  505. [ "${patch}" = "${base_dir}"/patches/${name}/jinx-working-patch.patch ] && continue
  506. patch --no-backup-if-mismatch -p1 -r "${patch_trash}" < "${patch}"
  507. done
  508. fi
  509. cp -rp "${source_dir}" "${base_dir}"/sources/${name}-clean
  510. if [ -f "${base_dir}"/patches/${name}/jinx-working-patch.patch ]; then
  511. patch --no-backup-if-mismatch -p1 -r "${patch_trash}" < "${base_dir}"/patches/${name}/jinx-working-patch.patch
  512. fi
  513. cp -rp "${source_dir}" "${base_dir}"/sources/${name}-workdir
  514. cd "${base_dir}"
  515. touch "${base_dir}"/sources/${name}.patched
  516. }
  517. do_prepare() {
  518. default_recipe_steps
  519. source_source_recipe $1
  520. get_real_source_dir
  521. [ -f "${base_dir}"/sources/${name}.prepared ] && return
  522. sysroot_dir="/sysroot"
  523. cd "${source_dir}"
  524. [ "${is_local_package}" = true ] || container_base_dir_ro=":ro"
  525. prepare
  526. container_base_dir_ro=""
  527. cd "${base_dir}"
  528. touch "${base_dir}"/sources/${name}.prepared
  529. }
  530. do_configure_host() {
  531. default_recipe_steps
  532. unset from_source
  533. . "${base_dir}"/host-recipes/$1
  534. make_dir "${build_dir}"/host-builds/${name}
  535. if ! [ -z "${from_source}" ]; then
  536. version=$(unset version && source_source_recipe ${from_source} && echo "$version")
  537. source_dir="$(unset source_dir && source_source_recipe ${from_source} && echo "$source_dir")"
  538. if [ -z "${source_dir}" ]; then
  539. source_dir="${base_dir}"/sources/${from_source}
  540. else
  541. source_dir="${base_dir}"/"${source_dir}"
  542. fi
  543. fi
  544. prefix="/usr/local"
  545. sysroot_dir="/sysroot"
  546. cd "${build_dir}"/host-builds/${name}
  547. configure
  548. cd "${base_dir}"
  549. }
  550. do_build_host() {
  551. default_recipe_steps
  552. unset from_source
  553. . "${base_dir}"/host-recipes/$1
  554. make_dir "${build_dir}"/host-builds/${name}
  555. if ! [ -z "${from_source}" ]; then
  556. version=$(unset version && source_source_recipe ${from_source} && echo "$version")
  557. source_dir="$(unset source_dir && source_source_recipe ${from_source} && echo "$source_dir")"
  558. if [ -z "${source_dir}" ]; then
  559. source_dir="${base_dir}"/sources/${from_source}
  560. else
  561. source_dir="${base_dir}"/"${source_dir}"
  562. fi
  563. fi
  564. prefix="/usr/local"
  565. sysroot_dir="/sysroot"
  566. cd "${build_dir}"/host-builds/${name}
  567. build
  568. cd "${base_dir}"
  569. }
  570. do_package_host() {
  571. default_recipe_steps
  572. unset from_source
  573. . "${base_dir}"/host-recipes/$1
  574. dest_dir="${build_dir}"/host-pkgs/${name}
  575. rm -rf "${dest_dir}"
  576. make_dir "${dest_dir}"
  577. if ! [ -z "${from_source}" ]; then
  578. version=$(unset version && source_source_recipe ${from_source} && echo "$version")
  579. source_dir="$(unset source_dir && source_source_recipe ${from_source} && echo "$source_dir")"
  580. if [ -z "${source_dir}" ]; then
  581. source_dir="${base_dir}"/sources/${from_source}
  582. else
  583. source_dir="${base_dir}"/"${source_dir}"
  584. fi
  585. fi
  586. prefix="/usr/local"
  587. sysroot_dir="/sysroot"
  588. make_dir "${dest_dir}${prefix}"
  589. cd "${build_dir}"/host-builds/${name}
  590. package
  591. cd "${base_dir}"
  592. # Remove libtool files
  593. for i in $(find "${dest_dir}${prefix}" -name "*.la"); do
  594. rm -rvf $i
  595. done
  596. }
  597. do_configure() {
  598. default_recipe_steps
  599. unset from_source
  600. . "${base_dir}"/recipes/$1
  601. make_dir "${build_dir}"/builds/${name}
  602. if ! [ -z "${from_source}" ] || ! [ -z "${tarball_url}" ] || ! [ -z "${git_url}" ] || ! [ -z "${hg_url}" ] || ! [ -z "${source_dir}" ]; then
  603. if ! [ -z "${from_source}" ]; then
  604. version=$(unset version && source_source_recipe ${from_source} && echo "$version")
  605. source_dir="$(unset source_dir && source_source_recipe ${from_source} && echo "$source_dir")"
  606. else
  607. from_source=${name}
  608. fi
  609. if [ -z "${source_dir}" ]; then
  610. source_dir="${base_dir}"/sources/${from_source}
  611. else
  612. source_dir="${base_dir}"/"${source_dir}"
  613. fi
  614. fi
  615. prefix="/usr"
  616. sysroot_dir="/sysroot"
  617. cd "${build_dir}"/builds/${name}
  618. configure
  619. cd "${base_dir}"
  620. }
  621. do_build() {
  622. default_recipe_steps
  623. unset from_source
  624. . "${base_dir}"/recipes/$1
  625. make_dir "${build_dir}"/builds/${name}
  626. if ! [ -z "${from_source}" ] || ! [ -z "${tarball_url}" ] || ! [ -z "${git_url}" ] || ! [ -z "${hg_url}" ] || ! [ -z "${source_dir}" ]; then
  627. if ! [ -z "${from_source}" ]; then
  628. version=$(unset version && source_source_recipe ${from_source} && echo "$version")
  629. source_dir="$(unset source_dir && source_source_recipe ${from_source} && echo "$source_dir")"
  630. else
  631. from_source=${name}
  632. fi
  633. if [ -z "${source_dir}" ]; then
  634. source_dir="${base_dir}"/sources/${from_source}
  635. else
  636. source_dir="${base_dir}"/"${source_dir}"
  637. fi
  638. fi
  639. prefix="/usr"
  640. sysroot_dir="/sysroot"
  641. cd "${build_dir}"/builds/${name}
  642. build
  643. cd "${base_dir}"
  644. }
  645. do_package() {
  646. default_recipe_steps
  647. unset from_source
  648. . "${base_dir}"/recipes/$1
  649. dest_dir="${build_dir}"/pkgs/${name}
  650. rm -rf "${dest_dir}"
  651. make_dir "${dest_dir}"
  652. if ! [ -z "${from_source}" ] || ! [ -z "${tarball_url}" ] || ! [ -z "${git_url}" ] || ! [ -z "${hg_url}" ] || ! [ -z "${source_dir}" ]; then
  653. if ! [ -z "${from_source}" ]; then
  654. version=$(unset version && source_source_recipe ${from_source} && echo "$version")
  655. source_dir="$(unset source_dir && source_source_recipe ${from_source} && echo "$source_dir")"
  656. else
  657. from_source=${name}
  658. fi
  659. if [ -z "${source_dir}" ]; then
  660. source_dir="${base_dir}"/sources/${from_source}
  661. else
  662. source_dir="${base_dir}"/"${source_dir}"
  663. fi
  664. fi
  665. prefix="/usr"
  666. sysroot_dir="/sysroot"
  667. make_dir "${dest_dir}${prefix}"
  668. cd "${build_dir}"/builds/${name}
  669. package
  670. cd "${base_dir}"
  671. # Remove libtool files
  672. for i in $(find "${dest_dir}${prefix}" -name "*.la"); do
  673. rm -rvf $i
  674. done
  675. }
  676. precont_patch() {
  677. [ -f "${base_dir}"/sources/$1.patched ] && return
  678. cross_compile=yes
  679. prepare_container
  680. run_in_container internal-cont-patch $1
  681. destroy_container
  682. }
  683. do_source() {
  684. source_source_recipe $1
  685. get_real_source_dir
  686. do_fetch
  687. "${script}" internal-precont-patch $1
  688. [ -f "${base_dir}"/sources/$1.prepared ] && return
  689. cross_compile=yes
  690. prepare_container
  691. run_in_container internal-prepare $1
  692. destroy_container
  693. }
  694. do_cmd_rebuild() {
  695. rm -rf "${build_dir}"/builds/"$1"
  696. do_pkg "$1"
  697. }
  698. do_cmd_host_rebuild() {
  699. rm -rf "${build_dir}"/host-builds/"$1"
  700. do_host_pkg "$1"
  701. }
  702. do_cmd_prepare() {
  703. source_source_recipe $1
  704. [ -f "${base_dir}"/sources/$1.patched ] || die "cannot regenerate non-built package"
  705. get_real_source_dir
  706. make_temp
  707. patch_file="${tmp}"
  708. if ! [ "${is_local_package}" = true ]; then
  709. cd "${base_dir}"/sources
  710. # exclude version control dirs
  711. make_temp -d
  712. vc_dir_clean="${tmp}"
  713. rm -rf "${vc_dir_clean}"
  714. make_temp -d
  715. vc_dir_workdir="${tmp}"
  716. rm -rf "${vc_dir_workdir}"
  717. if ! [ -z "${git_url}" ]; then
  718. mv $1-clean/.git "${vc_dir_clean}"
  719. mv $1-workdir/.git "${vc_dir_workdir}"
  720. elif ! [ -z "${hg_url}" ]; then
  721. mv $1-clean/.hg "${vc_dir_clean}"
  722. mv $1-workdir/.hg "${vc_dir_workdir}"
  723. fi
  724. git diff --no-index --no-prefix $1-clean $1-workdir >"${patch_file}" || true
  725. if ! [ -z "${git_url}" ]; then
  726. mv "${vc_dir_clean}" $1-clean/.git
  727. mv "${vc_dir_workdir}" $1-workdir/.git
  728. elif ! [ -z "${hg_url}" ]; then
  729. mv "${vc_dir_clean}" $1-clean/.hg
  730. mv "${vc_dir_workdir}" $1-workdir/.hg
  731. fi
  732. if [ -s "${patch_file}" ]; then
  733. make_dir "${base_dir}"/patches/$1
  734. mv "${patch_file}" "${base_dir}"/patches/$1/jinx-working-patch.patch
  735. fi
  736. cd "${base_dir}"
  737. rm -rf "${source_dir}"
  738. cp -rp "${base_dir}"/sources/$1-workdir "${source_dir}"
  739. fi
  740. rm -rf "${base_dir}"/sources/$1.prepared
  741. cross_compile=yes
  742. prepare_container
  743. run_in_container internal-prepare $1
  744. destroy_container
  745. }
  746. do_host_pkg() {
  747. unset from_source
  748. . "${base_dir}"/host-recipes/$1
  749. echo "* building host package: $name"
  750. if ! [ -z "${from_source}" ]; then
  751. from_source="$(. "${base_dir}"/host-recipes/$1 && echo "$from_source")"
  752. [ -f "${base_dir}"/sources/${from_source}.prepared ] || \
  753. "${script}" internal-source "${from_source}"
  754. fi
  755. cross_compile=yes
  756. prepare_container
  757. container_sources_ro=":ro"
  758. if ! [ -d "${base_dir}"/host-builds/$1 ]; then
  759. run_in_container internal-configure-host $1
  760. fi
  761. run_in_container internal-build-host $1
  762. rm -rf "${base_dir}"/host-pkgs/$1
  763. if ! run_in_container internal-package-host $1; then
  764. rm -rf "${base_dir}"/host-pkgs/$1
  765. return 1
  766. fi
  767. unset container_sources_ro
  768. destroy_container
  769. }
  770. do_pkg() {
  771. unset from_source
  772. . "${base_dir}"/recipes/$1
  773. echo "* building package: $name"
  774. if ! [ -z "${from_source}" ]; then
  775. from_source="$(. "${base_dir}"/recipes/$1 && echo "$from_source")"
  776. [ -f "${base_dir}"/sources/${from_source}.prepared ] || \
  777. "${script}" internal-source "${from_source}"
  778. fi
  779. if ! [ -z "${tarball_url}" ] || ! [ -z "${git_url}" ] || ! [ -z "${hg_url}" ] || ! [ -z "${source_dir}" ]; then
  780. "${script}" internal-source "${name}"
  781. fi
  782. prepare_container
  783. container_sources_ro=":ro"
  784. if ! [ -d "${base_dir}"/builds/$1 ]; then
  785. run_in_container internal-configure $1
  786. fi
  787. run_in_container internal-build $1
  788. rm -rf "${base_dir}"/pkgs/$1
  789. if ! run_in_container internal-package $1; then
  790. rm -rf "${base_dir}"/pkgs/$1
  791. return 1
  792. fi
  793. unset container_sources_ro
  794. destroy_container
  795. }
  796. cmd_host_build() {
  797. for ppkg in "$@"; do
  798. for pkg in $(eval '(' cd "'${base_dir}'"/host-recipes '&&' echo "${ppkg}" ')' ); do
  799. "${script}" internal-do-host-pkg "${pkg}"
  800. done
  801. done
  802. }
  803. cmd_build() {
  804. for ppkg in "$@"; do
  805. for pkg in $(eval '(' cd "'${base_dir}'"/recipes '&&' echo "${ppkg}" ')' ); do
  806. "${script}" internal-do-pkg "${pkg}"
  807. done
  808. done
  809. }
  810. cmd_prepare() {
  811. for i in "$@"; do
  812. "${script}" internal-do-prepare "$i"
  813. done
  814. }
  815. cmd_host_rebuild() {
  816. for ppkg in "$@"; do
  817. for pkg in $(eval '(' cd "'${base_dir}'"/host-recipes '&&' echo "${ppkg}" ')' ); do
  818. "${script}" internal-do-host-rebuild "${pkg}"
  819. done
  820. done
  821. }
  822. cmd_rebuild() {
  823. for ppkg in "$@"; do
  824. for pkg in $(eval '(' cd "'${base_dir}'"/recipes '&&' echo "${ppkg}" ')' ); do
  825. "${script}" internal-do-rebuild "${pkg}"
  826. done
  827. done
  828. }
  829. cmd_install() {
  830. sysroot="$1"
  831. shift 1
  832. mkdir -m 755 -p "${sysroot}"
  833. pkgs_to_install=""
  834. if [ "$1" = '*' ]; then
  835. for pkg in "${base_dir}"/recipes/*; do
  836. pkgs_to_install="${pkgs_to_install} $(basename "${pkg}")"
  837. done
  838. else
  839. for ppkg in "$@"; do
  840. for pkg in $(eval '(' cd "'${base_dir}'"/recipes '&&' echo "${ppkg}" ')' ); do
  841. deps="${deps} ${pkg}"
  842. done
  843. done
  844. make_temp
  845. deps_file="${tmp}"
  846. echo "* resolving dependencies..."
  847. get_deps_file
  848. pkgs_to_install="$(cat "${deps_file}")"
  849. fi
  850. make_temp
  851. all_files="${tmp}"
  852. pkg_dirs_to_install=""
  853. for pkg in ${pkgs_to_install}; do
  854. echo "* installing ${pkg}..."
  855. if ! [ -d "${build_dir}"/pkgs/${pkg} ]; then
  856. "${script}" internal-do-pkg "${pkg}"
  857. fi
  858. ( cd "${build_dir}"/pkgs/${pkg} && find . >>"${all_files}" )
  859. pkg_dirs_to_install="${pkg_dirs_to_install} ${pkg}/."
  860. done
  861. echo "* checking for conflicts..."
  862. make_temp
  863. all_files_sorted="${tmp}"
  864. make_temp
  865. all_files_uniq="${tmp}"
  866. sort <"${all_files}" >"${all_files_sorted}"
  867. uniq <"${all_files_sorted}" >"${all_files_uniq}"
  868. dup_elements="$(comm -23 "${all_files_sorted}" "${all_files_uniq}" | uniq)"
  869. rm -f "$JINX_CACHE_DIR/merged-info-dir"
  870. for pkg in ${pkgs_to_install}; do
  871. for elem in ${dup_elements}; do
  872. if [ -f "${build_dir}"/pkgs/${pkg}/${elem} ] || [ -L "${build_dir}"/pkgs/${pkg}/${elem} ]; then
  873. if [ "${elem}" = "./usr/share/info/dir" ]; then
  874. # Coalesce info directory
  875. if ! [ -f "$JINX_CACHE_DIR/merged-info-dir" ]; then
  876. cp "${build_dir}"/pkgs/${pkg}/${elem} "$JINX_CACHE_DIR/merged-info-dir"
  877. else
  878. "$JINX_CACHE_DIR/merge-info" -o "$JINX_CACHE_DIR/merged-info-dir" "${build_dir}"/pkgs/${pkg}/${elem} "$JINX_CACHE_DIR/merged-info-dir"
  879. fi
  880. continue
  881. fi
  882. die "* error: duplicate files were found in package '${pkg}': ${elem}"
  883. fi
  884. done
  885. done
  886. echo "* synchronising package files to sysroot '${sysroot}'..."
  887. sysroot_abs="$(cd "${sysroot}" && pwd -P)"
  888. ( cd "${build_dir}/pkgs" && rsync -urlptD ${pkg_dirs_to_install} "${sysroot_abs}"/ )
  889. # inject the merged info dir into sysroot
  890. if [ -f "${sysroot}"/usr/share/info/dir ] && [ -f "$JINX_CACHE_DIR/merged-info-dir" ]; then
  891. "$JINX_CACHE_DIR/merge-info" -o "${sysroot}"/usr/share/info/dir "$JINX_CACHE_DIR/merged-info-dir" "${sysroot}"/usr/share/info/dir
  892. else
  893. if [ -f "$JINX_CACHE_DIR/merged-info-dir" ]; then
  894. cp "$JINX_CACHE_DIR/merged-info-dir" "${sysroot}"/usr/share/info/dir
  895. fi
  896. fi
  897. }
  898. rebuild_b2sum() {
  899. cat <<'EOF' >"$JINX_CACHE_DIR/b2sum.c"
  900. // This blake2b implementation comes from the GNU coreutils project.
  901. // https://github.com/coreutils/coreutils/blob/master/src/blake2/blake2b-ref.c
  902. #include <stdbool.h>
  903. #include <stdint.h>
  904. #include <stddef.h>
  905. #include <stdio.h>
  906. #include <stdlib.h>
  907. #include <string.h>
  908. #define BLAKE2B_OUT_BYTES 64
  909. #define BLAKE2B_BLOCK_BYTES 128
  910. #define BLAKE2B_KEY_BYTES 64
  911. #define BLAKE2B_SALT_BYTES 16
  912. #define BLAKE2B_PERSONAL_BYTES 16
  913. static const uint64_t blake2b_iv[8] = {
  914. 0x6a09e667f3bcc908,
  915. 0xbb67ae8584caa73b,
  916. 0x3c6ef372fe94f82b,
  917. 0xa54ff53a5f1d36f1,
  918. 0x510e527fade682d1,
  919. 0x9b05688c2b3e6c1f,
  920. 0x1f83d9abfb41bd6b,
  921. 0x5be0cd19137e2179,
  922. };
  923. static const uint8_t blake2b_sigma[12][16] = {
  924. { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
  925. { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
  926. { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
  927. { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
  928. { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
  929. { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
  930. { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
  931. { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
  932. { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
  933. { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
  934. { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
  935. { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
  936. };
  937. struct blake2b_state {
  938. uint64_t h[8];
  939. uint64_t t[2];
  940. uint64_t f[2];
  941. uint8_t buf[BLAKE2B_BLOCK_BYTES];
  942. size_t buf_len;
  943. uint8_t last_node;
  944. };
  945. struct blake2b_param {
  946. uint8_t digest_length;
  947. uint8_t key_length;
  948. uint8_t fan_out;
  949. uint8_t depth;
  950. uint32_t leaf_length;
  951. uint32_t node_offset;
  952. uint32_t xof_length;
  953. uint8_t node_depth;
  954. uint8_t inner_length;
  955. uint8_t reserved[14];
  956. uint8_t salt[BLAKE2B_SALT_BYTES];
  957. uint8_t personal[BLAKE2B_PERSONAL_BYTES];
  958. } __attribute__((packed));
  959. static void blake2b_increment_counter(struct blake2b_state *state, uint64_t inc) {
  960. state->t[0] += inc;
  961. state->t[1] += state->t[0] < inc;
  962. }
  963. static inline uint64_t rotr64(uint64_t w, unsigned c) {
  964. return (w >> c) | (w << (64 - c));
  965. }
  966. #define G(r, i, a, b, c, d) do { \
  967. a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \
  968. d = rotr64(d ^ a, 32); \
  969. c = c + d; \
  970. b = rotr64(b ^ c, 24); \
  971. a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \
  972. d = rotr64(d ^ a, 16); \
  973. c = c + d; \
  974. b = rotr64(b ^ c, 63); \
  975. } while (0)
  976. #define ROUND(r) do { \
  977. G(r, 0, v[0], v[4], v[8], v[12]); \
  978. G(r, 1, v[1], v[5], v[9], v[13]); \
  979. G(r, 2, v[2], v[6], v[10], v[14]); \
  980. G(r, 3, v[3], v[7], v[11], v[15]); \
  981. G(r, 4, v[0], v[5], v[10], v[15]); \
  982. G(r, 5, v[1], v[6], v[11], v[12]); \
  983. G(r, 6, v[2], v[7], v[8], v[13]); \
  984. G(r, 7, v[3], v[4], v[9], v[14]); \
  985. } while (0)
  986. static void blake2b_compress(struct blake2b_state *state, const uint8_t block[static BLAKE2B_BLOCK_BYTES]) {
  987. uint64_t m[16];
  988. uint64_t v[16];
  989. for (int i = 0; i < 16; i++) {
  990. m[i] = *(uint64_t *)(block + i * sizeof(m[i]));
  991. }
  992. for (int i = 0; i < 8; i++) {
  993. v[i] = state->h[i];
  994. }
  995. v[8] = blake2b_iv[0];
  996. v[9] = blake2b_iv[1];
  997. v[10] = blake2b_iv[2];
  998. v[11] = blake2b_iv[3];
  999. v[12] = blake2b_iv[4] ^ state->t[0];
  1000. v[13] = blake2b_iv[5] ^ state->t[1];
  1001. v[14] = blake2b_iv[6] ^ state->f[0];
  1002. v[15] = blake2b_iv[7] ^ state->f[1];
  1003. ROUND(0);
  1004. ROUND(1);
  1005. ROUND(2);
  1006. ROUND(3);
  1007. ROUND(4);
  1008. ROUND(5);
  1009. ROUND(6);
  1010. ROUND(7);
  1011. ROUND(8);
  1012. ROUND(9);
  1013. ROUND(10);
  1014. ROUND(11);
  1015. for (int i = 0; i < 8; i++) {
  1016. state->h[i] = state->h[i] ^ v[i] ^ v[i + 8];
  1017. }
  1018. }
  1019. #undef G
  1020. #undef ROUND
  1021. static void blake2b_init(struct blake2b_state *state) {
  1022. struct blake2b_param param;
  1023. memset(&param, 0, sizeof(struct blake2b_param));
  1024. param.digest_length = BLAKE2B_OUT_BYTES;
  1025. param.fan_out = 1;
  1026. param.depth = 1;
  1027. memset(state, 0, sizeof(struct blake2b_state));
  1028. for (int i = 0; i < 8; i++) {
  1029. state->h[i] = blake2b_iv[i];
  1030. }
  1031. for (int i = 0; i < 8; i++) {
  1032. state->h[i] ^= *(uint64_t *)((void *)&param + sizeof(state->h[i]) * i);
  1033. }
  1034. }
  1035. static void blake2b_update(struct blake2b_state *state, const void *in, size_t in_len) {
  1036. if (in_len == 0) {
  1037. return;
  1038. }
  1039. size_t left = state->buf_len;
  1040. size_t fill = BLAKE2B_BLOCK_BYTES - left;
  1041. if (in_len > fill) {
  1042. state->buf_len = 0;
  1043. memcpy(state->buf + left, in, fill);
  1044. blake2b_increment_counter(state, BLAKE2B_BLOCK_BYTES);
  1045. blake2b_compress(state, state->buf);
  1046. in += fill;
  1047. in_len -= fill;
  1048. while (in_len > BLAKE2B_BLOCK_BYTES) {
  1049. blake2b_increment_counter(state, BLAKE2B_BLOCK_BYTES);
  1050. blake2b_compress(state, in);
  1051. in += fill;
  1052. in_len -= fill;
  1053. }
  1054. }
  1055. memcpy(state->buf + state->buf_len, in, in_len);
  1056. state->buf_len += in_len;
  1057. }
  1058. static void blake2b_final(struct blake2b_state *state, void *out) {
  1059. uint8_t buffer[BLAKE2B_OUT_BYTES] = {0};
  1060. blake2b_increment_counter(state, state->buf_len);
  1061. state->f[0] = (uint64_t)-1;
  1062. memset(state->buf + state->buf_len, 0, BLAKE2B_BLOCK_BYTES - state->buf_len);
  1063. blake2b_compress(state, state->buf);
  1064. for (int i = 0; i < 8; i++) {
  1065. *(uint64_t *)(buffer + sizeof(state->h[i]) * i) = state->h[i];
  1066. }
  1067. memcpy(out, buffer, BLAKE2B_OUT_BYTES);
  1068. memset(buffer, 0, sizeof(buffer));
  1069. }
  1070. static void blake2b(void *out, const void *in, size_t in_len) {
  1071. struct blake2b_state state = {0};
  1072. blake2b_init(&state);
  1073. blake2b_update(&state, in, in_len);
  1074. blake2b_final(&state, out);
  1075. }
  1076. int main(int argc, char *argv[]) {
  1077. if (argc < 2) {
  1078. return EXIT_FAILURE;
  1079. }
  1080. FILE *f = fopen(argv[1], "r");
  1081. if (f == NULL) {
  1082. return EXIT_FAILURE;
  1083. }
  1084. fseek(f, 0, SEEK_END);
  1085. size_t f_size = ftell(f);
  1086. rewind(f);
  1087. void *mem = malloc(f_size);
  1088. if (mem == NULL) {
  1089. return EXIT_FAILURE;
  1090. }
  1091. if (fread(mem, f_size, 1, f) != 1) {
  1092. return EXIT_FAILURE;
  1093. }
  1094. uint8_t out_buf[BLAKE2B_OUT_BYTES];
  1095. blake2b(out_buf, mem, f_size);
  1096. for (size_t i = 0; i < BLAKE2B_OUT_BYTES; i++) {
  1097. printf("%02x", out_buf[i]);
  1098. }
  1099. printf(" %s\n", argv[1]);
  1100. }
  1101. EOF
  1102. cc -O2 -pipe -fno-strict-aliasing -Wall -Wextra "$JINX_CACHE_DIR/b2sum.c" -o "$JINX_CACHE_DIR/b2sum"
  1103. }
  1104. rebuild_rbrt() {
  1105. cat <<'EOF' >"$JINX_CACHE_DIR/rbrt.c"
  1106. // Written by 48cf (iretq@riseup.net)
  1107. // Inspired heavily by https://github.com/managarm/cbuildrt/
  1108. #define _GNU_SOURCE
  1109. #include <stddef.h>
  1110. #include <stdbool.h>
  1111. #include <stdio.h>
  1112. #include <stdlib.h>
  1113. #include <string.h>
  1114. #include <limits.h>
  1115. #include <errno.h>
  1116. #include <unistd.h>
  1117. #include <fcntl.h>
  1118. #include <sched.h>
  1119. #include <sys/mount.h>
  1120. #include <sys/wait.h>
  1121. #define STRINGIFY(x) #x
  1122. #define TOSTRING(x) STRINGIFY(x)
  1123. int main(int argc, char *argv[]) {
  1124. int ok = 1;
  1125. const char *err_msg = "";
  1126. char *rootfs = NULL;
  1127. char **mounts = NULL;
  1128. char **envs = NULL;
  1129. char **process_args = NULL;
  1130. int mount_count = 0;
  1131. int mounts_size = 0;
  1132. int env_count = 0;
  1133. int envs_size = 0;
  1134. bool rw_root = false;
  1135. bool unshare_net = false;
  1136. int uid = -1, gid = -1;
  1137. int euid = geteuid();
  1138. int egid = getegid();
  1139. int setgroups_fd = -1;
  1140. int uid_map_fd = -1;
  1141. int gid_map_fd = -1;
  1142. char *workdir = "/";
  1143. for (int i = 1; i < argc; ) {
  1144. if (strcmp(argv[i], "--workdir") == 0) {
  1145. workdir = argv[i + 1];
  1146. i += 2;
  1147. } else if (strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--root") == 0) {
  1148. if (i == argc - 1) {
  1149. fprintf(stderr, "%s: '%s' requires a value\n", argv[0], argv[i]);
  1150. goto cleanup;
  1151. }
  1152. rootfs = argv[i + 1];
  1153. i += 2;
  1154. if (i < argc - 1 && strcmp(argv[i], "rw") == 0) {
  1155. rw_root = true;
  1156. i++;
  1157. }
  1158. } else if (strcmp(argv[i], "-u") == 0 || strcmp(argv[i], "--uid") == 0) {
  1159. if (i == argc - 1) {
  1160. fprintf(stderr, "%s: '%s' requires a value\n", argv[0], argv[i]);
  1161. goto cleanup;
  1162. }
  1163. if (sscanf(argv[i + 1], "%d", &uid) != 1) {
  1164. fprintf(stderr, "%s: '%s' is not a valid user ID\n", argv[0], argv[i + 1]);
  1165. goto cleanup;
  1166. }
  1167. i += 2;
  1168. } else if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "--gid") == 0) {
  1169. if (i == argc - 1) {
  1170. fprintf(stderr, "%s: '%s' requires a value\n", argv[0], argv[i]);
  1171. goto cleanup;
  1172. }
  1173. if (sscanf(argv[i + 1], "%d", &gid) != 1) {
  1174. fprintf(stderr, "%s: '%s' is not a valid group ID\n", argv[0], argv[i + 1]);
  1175. goto cleanup;
  1176. }
  1177. i += 2;
  1178. } else if (strncmp(argv[i], "-m", 2) == 0) {
  1179. if (mount_count == mounts_size) {
  1180. mounts_size = mounts_size == 0 ? 16 : mounts_size * 2;
  1181. char **tmp_mounts = realloc(mounts, sizeof(char *) * mounts_size);
  1182. if (tmp_mounts == NULL) {
  1183. fprintf(stderr, "%s: failed to allocate mounts array\n", argv[0]);
  1184. goto cleanup;
  1185. }
  1186. mounts = tmp_mounts;
  1187. }
  1188. char *target = argv[i] + 2;
  1189. while (*target && *target != ':') {
  1190. target++;
  1191. }
  1192. if (!*target) {
  1193. fprintf(stderr, "%s: mount points need to be provided in the 'source:target' format\n", argv[0]);
  1194. goto cleanup;
  1195. }
  1196. mounts[mount_count++] = argv[i] + 2;
  1197. i += 1;
  1198. } else if (strcmp(argv[i], "-e") == 0 || strcmp(argv[i], "--env") == 0) {
  1199. if (i == argc - 1) {
  1200. fprintf(stderr, "%s: '%s' requires a value\n", argv[0], argv[i]);
  1201. goto cleanup;
  1202. }
  1203. if (env_count == envs_size) {
  1204. envs_size = envs_size == 0 ? 16 : envs_size * 2;
  1205. char **tmp_envs = realloc(envs, sizeof(char *) * envs_size);
  1206. if (tmp_envs == NULL) {
  1207. fprintf(stderr, "%s: failed to allocate environment variables array\n", argv[0]);
  1208. goto cleanup;
  1209. }
  1210. envs = tmp_envs;
  1211. }
  1212. char *value = argv[i + 1];
  1213. while (*value && *value != '=') {
  1214. value++;
  1215. }
  1216. if (!*value) {
  1217. fprintf(stderr, "%s: environment variables need to be provided in the 'key=value' format\n", argv[0]);
  1218. goto cleanup;
  1219. }
  1220. envs[env_count++] = argv[i + 1];
  1221. i += 2;
  1222. } else if (strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--net") == 0) {
  1223. unshare_net = true;
  1224. i += 1;
  1225. } else if (strcmp(argv[i], "--") == 0) {
  1226. if (i == argc - 1) {
  1227. fprintf(stderr, "%s: at least one trailing argument is required\n", argv[0]);
  1228. goto cleanup;
  1229. }
  1230. process_args = &argv[i + 1];
  1231. break;
  1232. } else {
  1233. fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], argv[i]);
  1234. goto cleanup;
  1235. }
  1236. }
  1237. if (rootfs == NULL) {
  1238. fprintf(stderr, "%s: root file system path is required\n", argv[0]);
  1239. goto cleanup;
  1240. }
  1241. if (process_args == NULL) {
  1242. fprintf(stderr, "%s: process arguments are requires\n", argv[0]);
  1243. goto cleanup;
  1244. }
  1245. if (uid == -1 || gid == -1) {
  1246. fprintf(stderr, "%s: user and group IDs are both required\n", argv[0]);
  1247. goto cleanup;
  1248. }
  1249. if (unshare(CLONE_NEWUSER | CLONE_NEWPID) < 0) {
  1250. err_msg = "unshare() failure at line " TOSTRING(__LINE__);
  1251. goto errno_error;
  1252. }
  1253. char uid_map[64], gid_map[64];
  1254. int uid_map_len = snprintf(uid_map, 64, "%d %d 1", uid, euid);
  1255. int gid_map_len = snprintf(gid_map, 64, "%d %d 1", gid, egid);
  1256. setgroups_fd = open("/proc/self/setgroups", O_RDWR);
  1257. if (setgroups_fd < 0 || write(setgroups_fd, "deny", 4) < 0) {
  1258. err_msg = "failed to open or write to /proc/self/setgroups at line " TOSTRING(__LINE__);
  1259. goto errno_error;
  1260. }
  1261. close(setgroups_fd);
  1262. setgroups_fd = -1;
  1263. uid_map_fd = open("/proc/self/uid_map", O_RDWR);
  1264. if (uid_map_fd < 0 || write(uid_map_fd, uid_map, uid_map_len) < 0) {
  1265. err_msg = "failed to open or write to /proc/self/uid_map at line " TOSTRING(__LINE__);
  1266. goto errno_error;
  1267. }
  1268. close(uid_map_fd);
  1269. uid_map_fd = -1;
  1270. gid_map_fd = open("/proc/self/gid_map", O_RDWR);
  1271. if (gid_map_fd < 0 || write(gid_map_fd, gid_map, gid_map_len) < 0) {
  1272. err_msg = "failed to open or write to /proc/self/gid_map at line " TOSTRING(__LINE__);
  1273. goto errno_error;
  1274. }
  1275. close(gid_map_fd);
  1276. gid_map_fd = -1;
  1277. if (setuid(uid) < 0 || setgid(gid) < 0) {
  1278. err_msg = "setuid()/setgid() failure at line " TOSTRING(__LINE__);
  1279. goto errno_error;
  1280. }
  1281. int child_pid = fork();
  1282. if (child_pid == 0) {
  1283. if (unshare(CLONE_NEWNS) < 0) {
  1284. err_msg = "unshare() failure at line " TOSTRING(__LINE__);
  1285. goto errno_error;
  1286. }
  1287. if (mount(rootfs, rootfs, NULL, MS_BIND, NULL) < 0) {
  1288. err_msg = "mount() failure at line " TOSTRING(__LINE__);
  1289. goto errno_error;
  1290. }
  1291. int root_flags = MS_REMOUNT | MS_BIND | MS_NOSUID | MS_NODEV;
  1292. if (!rw_root) {
  1293. root_flags |= MS_RDONLY;
  1294. }
  1295. if (mount(rootfs, rootfs, NULL, root_flags, NULL) < 0) {
  1296. err_msg = "mount() failure at line " TOSTRING(__LINE__);
  1297. goto errno_error;
  1298. }
  1299. char target_path[PATH_MAX];
  1300. snprintf(target_path, PATH_MAX, "%s/etc/resolv.conf", rootfs);
  1301. if (mount("/etc/resolv.conf", target_path, NULL, MS_BIND, NULL) < 0) {
  1302. err_msg = "mount() failure at line " TOSTRING(__LINE__);
  1303. goto errno_error;
  1304. }
  1305. snprintf(target_path, PATH_MAX, "%s/dev", rootfs);
  1306. if (mount("/dev", target_path, NULL, MS_REC | MS_BIND | MS_SLAVE, NULL) < 0) {
  1307. err_msg = "mount() failure at line " TOSTRING(__LINE__);
  1308. goto errno_error;
  1309. }
  1310. snprintf(target_path, PATH_MAX, "%s/sys", rootfs);
  1311. if (mount("/sys", target_path, NULL, MS_REC | MS_BIND | MS_SLAVE, NULL) < 0) {
  1312. err_msg = "mount() failure at line " TOSTRING(__LINE__);
  1313. goto errno_error;
  1314. }
  1315. snprintf(target_path, PATH_MAX, "%s/run", rootfs);
  1316. if (mount(NULL, target_path, "tmpfs", 0, NULL) < 0) {
  1317. err_msg = "mount() failure at line " TOSTRING(__LINE__);
  1318. goto errno_error;
  1319. }
  1320. snprintf(target_path, PATH_MAX, "%s/tmp", rootfs);
  1321. if (mount(NULL, target_path, "tmpfs", 0, NULL) < 0) {
  1322. err_msg = "mount() failure at line " TOSTRING(__LINE__);
  1323. goto errno_error;
  1324. }
  1325. snprintf(target_path, PATH_MAX, "%s/var/tmp", rootfs);
  1326. if (mount(NULL, target_path, "tmpfs", 0, NULL) < 0) {
  1327. err_msg = "mount() failure at line " TOSTRING(__LINE__);
  1328. goto errno_error;
  1329. }
  1330. snprintf(target_path, PATH_MAX, "%s/proc", rootfs);
  1331. if (mount(NULL, target_path, "proc", 0, NULL) < 0) {
  1332. err_msg = "mount() failure at line " TOSTRING(__LINE__);
  1333. goto errno_error;
  1334. }
  1335. for (int i = 0; i < mount_count; i++) {
  1336. char *source = mounts[i];
  1337. char *target = source;
  1338. while (*target && *target != ':') {
  1339. target++;
  1340. }
  1341. *target++ = 0;
  1342. char *read_only = target;
  1343. while (*read_only && *read_only != ':') {
  1344. read_only++;
  1345. }
  1346. bool ro = false;
  1347. if (*read_only == ':') {
  1348. *read_only++ = 0;
  1349. ro = strcmp(read_only, "ro") == 0;
  1350. }
  1351. snprintf(target_path, PATH_MAX, "%s%s", rootfs, target);
  1352. if (mount(source, target_path, NULL, MS_BIND | (ro ? MS_RDONLY : 0), NULL) < 0) {
  1353. err_msg = "mount() failure at line " TOSTRING(__LINE__);
  1354. goto errno_error;
  1355. }
  1356. if (ro) {
  1357. if (mount(source, target_path, NULL, MS_REMOUNT | MS_BIND | MS_RDONLY, NULL) < 0) {
  1358. err_msg = "mount() failure at line " TOSTRING(__LINE__);
  1359. goto errno_error;
  1360. }
  1361. }
  1362. }
  1363. if (unshare_net && unshare(CLONE_NEWNET) < 0) {
  1364. err_msg = "unshare() failure at line " TOSTRING(__LINE__);
  1365. goto errno_error;
  1366. }
  1367. if (chroot(rootfs) < 0) {
  1368. err_msg = "chroot() failure at line " TOSTRING(__LINE__);
  1369. goto errno_error;
  1370. }
  1371. if (chdir(workdir) < 0) {
  1372. err_msg = "chdir() failure at line " TOSTRING(__LINE__);
  1373. goto errno_error;
  1374. }
  1375. int child = fork();
  1376. if (child == 0) {
  1377. clearenv();
  1378. setenv("HOME", "/root", 1);
  1379. setenv("LANG", "C", 1);
  1380. setenv("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 1);
  1381. for (int i = 0; i < env_count; i++) {
  1382. char *key = envs[i];
  1383. char *value = key;
  1384. while (*value && *value != '=') {
  1385. value++;
  1386. }
  1387. *value++ = 0;
  1388. setenv(key, value, 1);
  1389. }
  1390. if (execvp(process_args[0], process_args) < 0) {
  1391. err_msg = "execvp() failure at line " TOSTRING(__LINE__);
  1392. goto errno_error;
  1393. }
  1394. __builtin_unreachable();
  1395. } else {
  1396. int exit_code = -1;
  1397. if (waitpid(child, &exit_code, 0) < 0) {
  1398. err_msg = "waitpid() failure at line " TOSTRING(__LINE__);
  1399. goto errno_error;
  1400. }
  1401. ok = WEXITSTATUS(exit_code);
  1402. goto cleanup;
  1403. }
  1404. __builtin_unreachable();
  1405. } else {
  1406. int exit_code = -1;
  1407. if (waitpid(child_pid, &exit_code, 0) < 0) {
  1408. err_msg = "waitpid() failure at line " TOSTRING(__LINE__);
  1409. goto errno_error;
  1410. }
  1411. ok = WEXITSTATUS(exit_code);
  1412. goto cleanup;
  1413. }
  1414. errno_error:
  1415. fprintf(stderr, "%s: %s: %s\n", argv[0], err_msg, strerror(errno));
  1416. cleanup:
  1417. if (mounts != NULL) {
  1418. free(mounts);
  1419. }
  1420. if (envs != NULL) {
  1421. free(envs);
  1422. }
  1423. if (setgroups_fd >= 0) {
  1424. close(setgroups_fd);
  1425. }
  1426. if (uid_map_fd >= 0) {
  1427. close(uid_map_fd);
  1428. }
  1429. if (gid_map_fd >= 0) {
  1430. close(gid_map_fd);
  1431. }
  1432. return ok;
  1433. }
  1434. EOF
  1435. cc -O2 -pipe -Wall -Wextra "$JINX_CACHE_DIR/rbrt.c" -o "$JINX_CACHE_DIR/rbrt"
  1436. }
  1437. reinit_container() {
  1438. chmod -R 777 "$JINX_CACHE_DIR/sets" 2>/dev/null || true
  1439. chmod -R 777 "$JINX_CACHE_DIR/apt-cache" 2>/dev/null || true
  1440. rm -rf "$JINX_CACHE_DIR/debian-rootfs.tar.xz" "$JINX_CACHE_DIR/sets" "$JINX_CACHE_DIR/apt-cache"
  1441. make_dir "${apt_cache}"
  1442. curl -Lo "$JINX_CACHE_DIR/debian-rootfs.tar.xz" https://github.com/mintsuki/debian-rootfs/releases/download/${debian_snapshot}/debian-rootfs-${debian_architecture}.tar.xz
  1443. if ! "$JINX_CACHE_DIR/b2sum" "$JINX_CACHE_DIR/debian-rootfs.tar.xz" | grep "${debian_rootfs_b2sum}" >/dev/null 2>&1; then
  1444. die "Jinx: Failed to verify Debian rootfs tarball"
  1445. fi
  1446. ( cd "$JINX_CACHE_DIR" && xzcat debian-rootfs.tar.xz | tar -xf - )
  1447. rm "$JINX_CACHE_DIR/debian-rootfs.tar.xz"
  1448. make_dir "$JINX_CACHE_DIR/sets"
  1449. mv "$JINX_CACHE_DIR/debian-rootfs-${debian_architecture}" "$JINX_CACHE_DIR/sets/.image"
  1450. echo 'en_US.UTF-8 UTF-8' > "$JINX_CACHE_DIR/sets/.image/etc/locale.gen"
  1451. echo 'APT::Install-Suggests "0";
  1452. APT::Install-Recommends "0";
  1453. APT::Sandbox::User "root";
  1454. Acquire::Check-Valid-Until "0";' >> "$JINX_CACHE_DIR/sets/.image/etc/apt/apt.conf"
  1455. run_in_container1 "$JINX_CACHE_DIR/sets/.image" apt-get update
  1456. run_in_container1 "$JINX_CACHE_DIR/sets/.image" apt-get install -y locales
  1457. run_in_container1 "$JINX_CACHE_DIR/sets/.image" locale-gen
  1458. # Fix permissions of files
  1459. for f in $(find "$JINX_CACHE_DIR/sets/.image" -perm 000 2>/dev/null); do
  1460. chmod 755 "$f"
  1461. done
  1462. run_in_container1 "$JINX_CACHE_DIR/sets/.image" apt-get install -y autopoint bash bison bzip2 curl diffutils docbook-xsl doxygen file findutils flex gawk gettext grep gzip xsltproc m4 make patch perl python3 sed tar texinfo w3m which xmlto xz-utils
  1463. # Build xstow
  1464. XSTOW_BUILDENV="$JINX_CACHE_DIR/xstow_buildenv"
  1465. cp -Pprf "$JINX_CACHE_DIR/sets/.image/." "${XSTOW_BUILDENV}/"
  1466. curl -Lo "${XSTOW_BUILDENV}/xstow-${XSTOW_VERSION}.tar.gz" https://github.com/majorkingleo/xstow/releases/download/${XSTOW_VERSION}/xstow-${XSTOW_VERSION}.tar.gz
  1467. ( cd "${XSTOW_BUILDENV}" && gunzip < xstow-${XSTOW_VERSION}.tar.gz | tar -xf - )
  1468. run_in_container1 "${XSTOW_BUILDENV}" apt-get install -y build-essential
  1469. run_in_container1 "${XSTOW_BUILDENV}" sh -c "cd /xstow-${XSTOW_VERSION} && ./configure LDFLAGS='-static' --enable-static --enable-merge-info --without-curses && make -j${parallelism}"
  1470. mv "${XSTOW_BUILDENV}/xstow-${XSTOW_VERSION}/src/merge-info" "$JINX_CACHE_DIR/"
  1471. chmod -R 777 "$XSTOW_BUILDENV"
  1472. rm -rf "$XSTOW_BUILDENV"
  1473. }
  1474. first_use() {
  1475. echo "* preparing Jinx cache..."
  1476. make_dir "$JINX_CACHE_DIR"
  1477. rebuild_b2sum
  1478. rebuild_rbrt
  1479. reinit_container
  1480. echo "$jinx_version" > "$JINX_CACHE_DIR/version"
  1481. echo "* done"
  1482. }
  1483. redo_first_use() {
  1484. echo "* purging old Jinx cache..."
  1485. chmod -R 777 "$JINX_CACHE_DIR" || true
  1486. rm -rf "$JINX_CACHE_DIR"
  1487. first_use
  1488. }
  1489. if ! [ -f "$JINX_CONFIG_FILE" ]; then
  1490. die "$0: missing Jinx config file '$JINX_CONFIG_FILE'"
  1491. fi
  1492. . "${JINX_CONFIG_FILE}"
  1493. if [ -z "$JINX_MAJOR_VER" ]; then
  1494. die "$0: required config variable \$JINX_MAJOR_VER missing"
  1495. fi
  1496. if ! [ "$JINX_MAJOR_VER" = "$jinx_major_ver" ]; then
  1497. die "$0: needed major version ($JINX_MAJOR_VER) differs from Jinx-provided major version ($jinx_major_ver)"
  1498. fi
  1499. if ! [ -d "$JINX_CACHE_DIR" ]; then
  1500. first_use
  1501. fi
  1502. if ! [ -f "$JINX_CACHE_DIR/version" ] || ! [ "$(cat "$JINX_CACHE_DIR/version")" = "$jinx_version" ]; then
  1503. redo_first_use
  1504. fi
  1505. case "$1" in
  1506. internal-prepare)
  1507. do_prepare "$2"
  1508. ;;
  1509. internal-precont-patch)
  1510. precont_patch "$2"
  1511. ;;
  1512. internal-cont-patch)
  1513. cont_patch "$2"
  1514. ;;
  1515. internal-configure-host)
  1516. do_configure_host "$2"
  1517. ;;
  1518. internal-build-host)
  1519. do_build_host "$2"
  1520. ;;
  1521. internal-package-host)
  1522. do_package_host "$2"
  1523. ;;
  1524. internal-configure)
  1525. do_configure "$2"
  1526. ;;
  1527. internal-build)
  1528. do_build "$2"
  1529. ;;
  1530. internal-package)
  1531. do_package "$2"
  1532. ;;
  1533. internal-get-deps-file)
  1534. . "${base_dir}"/recipes/$2
  1535. deps_file="$3"
  1536. get_deps_file
  1537. ;;
  1538. internal-get-hostdeps-file-run)
  1539. . "${base_dir}"/host-recipes/$2
  1540. hostdeps_file="$3"
  1541. get_hostdeps_file_run
  1542. ;;
  1543. internal-source)
  1544. do_source "$2"
  1545. ;;
  1546. internal-do-host-pkg)
  1547. do_host_pkg "$2"
  1548. ;;
  1549. internal-do-pkg)
  1550. do_pkg "$2"
  1551. ;;
  1552. internal-do-prepare)
  1553. do_cmd_prepare "$2"
  1554. ;;
  1555. internal-do-host-rebuild)
  1556. do_cmd_host_rebuild "$2"
  1557. ;;
  1558. internal-do-rebuild)
  1559. do_cmd_rebuild "$2"
  1560. ;;
  1561. host-build)
  1562. shift 1
  1563. cmd_host_build "$@"
  1564. ;;
  1565. build)
  1566. shift 1
  1567. cmd_build "$@"
  1568. ;;
  1569. regenerate)
  1570. shift 1
  1571. cmd_prepare "$@"
  1572. ;;
  1573. host-rebuild)
  1574. shift 1
  1575. cmd_host_rebuild "$@"
  1576. ;;
  1577. rebuild)
  1578. shift 1
  1579. cmd_rebuild "$@"
  1580. ;;
  1581. install)
  1582. shift 1
  1583. cmd_install "$@"
  1584. ;;
  1585. rbrt)
  1586. rebuild_rbrt
  1587. ;;
  1588. rebuild-cache)
  1589. redo_first_use
  1590. ;;
  1591. *)
  1592. if [ -z "$1" ]; then
  1593. die "$0: no command specified."
  1594. else
  1595. die "$0: unknown command: $1"
  1596. fi
  1597. ;;
  1598. esac