installer.sh.in 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521
  1. #!/bin/bash
  2. #-
  3. # Copyright (c) 2012-2015 Juan Romero Pardines <[email protected]>.
  4. # 2012 Dave Elusive <[email protected]>.
  5. # All rights reserved.
  6. #
  7. # Redistribution and use in source and binary forms, with or without
  8. # modification, are permitted provided that the following conditions
  9. # are met:
  10. # 1. Redistributions of source code must retain the above copyright
  11. # notice, this list of conditions and the following disclaimer.
  12. # 2. Redistributions in binary form must reproduce the above copyright
  13. # notice, this list of conditions and the following disclaimer in the
  14. # documentation and/or other materials provided with the distribution.
  15. #
  16. # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  17. # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  18. # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  19. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  21. # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  23. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  25. # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. #-
  27. # Make sure we don't inherit these from env.
  28. SOURCE_DONE=
  29. HOSTNAME_DONE=
  30. KEYBOARD_DONE=
  31. LOCALE_DONE=
  32. TIMEZONE_DONE=
  33. ROOTPASSWORD_DONE=
  34. USERLOGIN_DONE=
  35. USERPASSWORD_DONE=
  36. USERNAME_DONE=
  37. USERGROUPS_DONE=
  38. BOOTLOADER_DONE=
  39. PARTITIONS_DONE=
  40. NETWORK_DONE=
  41. FILESYSTEMS_DONE=
  42. MIRROR_DONE=
  43. TARGETDIR=/mnt/target
  44. LOG=/dev/tty8
  45. CONF_FILE=/tmp/.void-installer.conf
  46. if [ ! -f $CONF_FILE ]; then
  47. touch -f $CONF_FILE
  48. fi
  49. ANSWER=$(mktemp -t vinstall-XXXXXXXX || exit 1)
  50. TARGET_FSTAB=$(mktemp -t vinstall-fstab-XXXXXXXX || exit 1)
  51. trap "DIE" INT TERM QUIT
  52. # disable printk
  53. if [ -w /proc/sys/kernel/printk ]; then
  54. echo 0 >/proc/sys/kernel/printk
  55. fi
  56. # Detect if this is an EFI system.
  57. if [ -e /sys/firmware/efi/systab ]; then
  58. EFI_SYSTEM=1
  59. EFI_FW_BITS=$(cat /sys/firmware/efi/fw_platform_size)
  60. if [ $EFI_FW_BITS -eq 32 ]; then
  61. EFI_TARGET=i386-efi
  62. else
  63. EFI_TARGET=x86_64-efi
  64. fi
  65. fi
  66. # dialog colors
  67. BLACK="\Z0"
  68. RED="\Z1"
  69. GREEN="\Z2"
  70. YELLOW="\Z3"
  71. BLUE="\Z4"
  72. MAGENTA="\Z5"
  73. CYAN="\Z6"
  74. WHITE="\Z7"
  75. BOLD="\Zb"
  76. REVERSE="\Zr"
  77. UNDERLINE="\Zu"
  78. RESET="\Zn"
  79. # Properties shared per widget.
  80. MENULABEL="${BOLD}Use UP and DOWN keys to navigate \
  81. menus. Use TAB to switch between buttons and ENTER to select.${RESET}"
  82. MENUSIZE="14 60 0"
  83. INPUTSIZE="8 60"
  84. MSGBOXSIZE="8 70"
  85. YESNOSIZE="$INPUTSIZE"
  86. WIDGET_SIZE="10 70"
  87. DIALOG() {
  88. rm -f $ANSWER
  89. dialog --colors --keep-tite --no-shadow --no-mouse \
  90. --backtitle "${BOLD}${WHITE}Void Linux installation -- https://www.voidlinux.org (@@MKLIVE_VERSION@@)${RESET}" \
  91. --cancel-label "Back" --aspect 20 "$@" 2>$ANSWER
  92. return $?
  93. }
  94. INFOBOX() {
  95. # Note: dialog --infobox and --keep-tite don't work together
  96. dialog --colors --no-shadow --no-mouse \
  97. --backtitle "${BOLD}${WHITE}Void Linux installation -- https://www.voidlinux.org (@@MKLIVE_VERSION@@)${RESET}" \
  98. --title "${TITLE}" --aspect 20 --infobox "$@"
  99. }
  100. DIE() {
  101. rval=$1
  102. [ -z "$rval" ] && rval=0
  103. clear
  104. rm -f $ANSWER $TARGET_FSTAB
  105. # reenable printk
  106. if [ -w /proc/sys/kernel/printk ]; then
  107. echo 4 >/proc/sys/kernel/printk
  108. fi
  109. umount_filesystems
  110. exit $rval
  111. }
  112. set_option() {
  113. if grep -Eq "^${1}.*" $CONF_FILE; then
  114. sed -i -e "/^${1}.*/d" $CONF_FILE
  115. fi
  116. echo "${1} ${2}" >>$CONF_FILE
  117. }
  118. get_option() {
  119. echo $(grep -E "^${1}.*" $CONF_FILE|sed -e "s|${1}||")
  120. }
  121. # ISO-639 language names for locales
  122. iso639_language() {
  123. case "$1" in
  124. aa) echo "Afar" ;;
  125. af) echo "Afrikaans" ;;
  126. an) echo "Aragonese" ;;
  127. ar) echo "Arabic" ;;
  128. ast) echo "Asturian" ;;
  129. be) echo "Belgian" ;;
  130. bg) echo "Bulgarian" ;;
  131. bhb) echo "Bhili" ;;
  132. br) echo "Breton" ;;
  133. bs) echo "Bosnian" ;;
  134. ca) echo "Catalan" ;;
  135. cs) echo "Czech" ;;
  136. cy) echo "Welsh" ;;
  137. da) echo "Danish" ;;
  138. de) echo "German" ;;
  139. el) echo "Greek" ;;
  140. en) echo "English" ;;
  141. es) echo "Spanish" ;;
  142. et) echo "Estonian" ;;
  143. eu) echo "Basque" ;;
  144. fi) echo "Finnish" ;;
  145. fo) echo "Faroese" ;;
  146. fr) echo "French" ;;
  147. ga) echo "Irish" ;;
  148. gd) echo "Scottish Gaelic" ;;
  149. gl) echo "Galician" ;;
  150. gv) echo "Manx" ;;
  151. he) echo "Hebrew" ;;
  152. hr) echo "Croatian" ;;
  153. hsb) echo "Upper Sorbian" ;;
  154. hu) echo "Hungarian" ;;
  155. id) echo "Indonesian" ;;
  156. is) echo "Icelandic" ;;
  157. it) echo "Italian" ;;
  158. iw) echo "Hebrew" ;;
  159. ja) echo "Japanese" ;;
  160. ka) echo "Georgian" ;;
  161. kk) echo "Kazakh" ;;
  162. kl) echo "Kalaallisut" ;;
  163. ko) echo "Korean" ;;
  164. ku) echo "Kurdish" ;;
  165. kw) echo "Cornish" ;;
  166. lg) echo "Ganda" ;;
  167. lt) echo "Lithuanian" ;;
  168. lv) echo "Latvian" ;;
  169. mg) echo "Malagasy" ;;
  170. mi) echo "Maori" ;;
  171. mk) echo "Macedonian" ;;
  172. ms) echo "Malay" ;;
  173. mt) echo "Maltese" ;;
  174. nb) echo "Norwegian Bokmål" ;;
  175. nl) echo "Dutch" ;;
  176. nn) echo "Norwegian Nynorsk" ;;
  177. oc) echo "Occitan" ;;
  178. om) echo "Oromo" ;;
  179. pl) echo "Polish" ;;
  180. pt) echo "Portugese" ;;
  181. ro) echo "Romanian" ;;
  182. ru) echo "Russian" ;;
  183. sk) echo "Slovak" ;;
  184. sl) echo "Slovenian" ;;
  185. so) echo "Somali" ;;
  186. sq) echo "Albanian" ;;
  187. st) echo "Southern Sotho" ;;
  188. sv) echo "Swedish" ;;
  189. tcy) echo "Tulu" ;;
  190. tg) echo "Tajik" ;;
  191. th) echo "Thai" ;;
  192. tl) echo "Tagalog" ;;
  193. tr) echo "Turkish" ;;
  194. uk) echo "Ukrainian" ;;
  195. uz) echo "Uzbek" ;;
  196. wa) echo "Walloon" ;;
  197. xh) echo "Xhosa" ;;
  198. yi) echo "Yiddish" ;;
  199. zh) echo "Chinese" ;;
  200. zu) echo "Zulu" ;;
  201. *) echo "$1" ;;
  202. esac
  203. }
  204. # ISO-3166 country codes for locales
  205. iso3166_country() {
  206. case "$1" in
  207. AD) echo "Andorra" ;;
  208. AE) echo "United Arab Emirates" ;;
  209. AL) echo "Albania" ;;
  210. AR) echo "Argentina" ;;
  211. AT) echo "Austria" ;;
  212. AU) echo "Australia" ;;
  213. BA) echo "Bonsia and Herzegovina" ;;
  214. BE) echo "Belgium" ;;
  215. BG) echo "Bulgaria" ;;
  216. BH) echo "Bahrain" ;;
  217. BO) echo "Bolivia" ;;
  218. BR) echo "Brazil" ;;
  219. BW) echo "Botswana" ;;
  220. BY) echo "Belarus" ;;
  221. CA) echo "Canada" ;;
  222. CH) echo "Switzerland" ;;
  223. CL) echo "Chile" ;;
  224. CN) echo "China" ;;
  225. CO) echo "Colombia" ;;
  226. CR) echo "Costa Rica" ;;
  227. CY) echo "Cyprus" ;;
  228. CZ) echo "Czech Republic" ;;
  229. DE) echo "Germany" ;;
  230. DJ) echo "Djibouti" ;;
  231. DK) echo "Denmark" ;;
  232. DO) echo "Dominican Republic" ;;
  233. DZ) echo "Algeria" ;;
  234. EC) echo "Ecuador" ;;
  235. EE) echo "Estonia" ;;
  236. EG) echo "Egypt" ;;
  237. ES) echo "Spain" ;;
  238. FI) echo "Finland" ;;
  239. FO) echo "Faroe Islands" ;;
  240. FR) echo "France" ;;
  241. GB) echo "Great Britain" ;;
  242. GE) echo "Georgia" ;;
  243. GL) echo "Greenland" ;;
  244. GR) echo "Greece" ;;
  245. GT) echo "Guatemala" ;;
  246. HK) echo "Hong Kong" ;;
  247. HN) echo "Honduras" ;;
  248. HR) echo "Croatia" ;;
  249. HU) echo "Hungary" ;;
  250. ID) echo "Indonesia" ;;
  251. IE) echo "Ireland" ;;
  252. IL) echo "Israel" ;;
  253. IN) echo "India" ;;
  254. IQ) echo "Iraq" ;;
  255. IS) echo "Iceland" ;;
  256. IT) echo "Italy" ;;
  257. JO) echo "Jordan" ;;
  258. JP) echo "Japan" ;;
  259. KE) echo "Kenya" ;;
  260. KR) echo "Korea, Republic of" ;;
  261. KW) echo "Kuwait" ;;
  262. KZ) echo "Kazakhstan" ;;
  263. LB) echo "Lebanon" ;;
  264. LT) echo "Lithuania" ;;
  265. LU) echo "Luxembourg" ;;
  266. LV) echo "Latvia" ;;
  267. LY) echo "Libya" ;;
  268. MA) echo "Morocco" ;;
  269. MG) echo "Madagascar" ;;
  270. MK) echo "Macedonia" ;;
  271. MT) echo "Malta" ;;
  272. MX) echo "Mexico" ;;
  273. MY) echo "Malaysia" ;;
  274. NI) echo "Nicaragua" ;;
  275. NL) echo "Netherlands" ;;
  276. NO) echo "Norway" ;;
  277. NZ) echo "New Zealand" ;;
  278. OM) echo "Oman" ;;
  279. PA) echo "Panama" ;;
  280. PE) echo "Peru" ;;
  281. PH) echo "Philippines" ;;
  282. PL) echo "Poland" ;;
  283. PR) echo "Puerto Rico" ;;
  284. PT) echo "Portugal" ;;
  285. PY) echo "Paraguay" ;;
  286. QA) echo "Qatar" ;;
  287. RO) echo "Romania" ;;
  288. RU) echo "Russian Federation" ;;
  289. SA) echo "Saudi Arabia" ;;
  290. SD) echo "Sudan" ;;
  291. SE) echo "Sweden" ;;
  292. SG) echo "Singapore" ;;
  293. SI) echo "Slovenia" ;;
  294. SK) echo "Slovakia" ;;
  295. SO) echo "Somalia" ;;
  296. SV) echo "El Salvador" ;;
  297. SY) echo "Syria" ;;
  298. TH) echo "Thailand" ;;
  299. TJ) echo "Tajikistan" ;;
  300. TN) echo "Tunisia" ;;
  301. TR) echo "Turkey" ;;
  302. TW) echo "Taiwan" ;;
  303. UA) echo "Ukraine" ;;
  304. UG) echo "Uganda" ;;
  305. US) echo "United States of America" ;;
  306. UY) echo "Uruguay" ;;
  307. UZ) echo "Uzbekistan" ;;
  308. VE) echo "Venezuela" ;;
  309. YE) echo "Yemen" ;;
  310. ZA) echo "South Africa" ;;
  311. ZW) echo "Zimbabwe" ;;
  312. *) echo "$1" ;;
  313. esac
  314. }
  315. show_disks() {
  316. local dev size sectorsize gbytes
  317. # IDE
  318. for dev in $(ls /sys/block|grep -E '^hd'); do
  319. if [ "$(cat /sys/block/$dev/device/media)" = "disk" ]; then
  320. # Find out nr sectors and bytes per sector;
  321. echo "/dev/$dev"
  322. size=$(cat /sys/block/$dev/size)
  323. sectorsize=$(cat /sys/block/$dev/queue/hw_sector_size)
  324. gbytes="$(($size * $sectorsize / 1024 / 1024 / 1024))"
  325. echo "size:${gbytes}GB;sector_size:$sectorsize"
  326. fi
  327. done
  328. # SATA/SCSI and Virtual disks (virtio)
  329. for dev in $(ls /sys/block|grep -E '^([sv]|xv)d|mmcblk|nvme'); do
  330. echo "/dev/$dev"
  331. size=$(cat /sys/block/$dev/size)
  332. sectorsize=$(cat /sys/block/$dev/queue/hw_sector_size)
  333. gbytes="$(($size * $sectorsize / 1024 / 1024 / 1024))"
  334. echo "size:${gbytes}GB;sector_size:$sectorsize"
  335. done
  336. # cciss(4) devices
  337. for dev in $(ls /dev/cciss 2>/dev/null|grep -E 'c[0-9]d[0-9]$'); do
  338. echo "/dev/cciss/$dev"
  339. size=$(cat /sys/block/cciss\!$dev/size)
  340. sectorsize=$(cat /sys/block/cciss\!$dev/queue/hw_sector_size)
  341. gbytes="$(($size * $sectorsize / 1024 / 1024 / 1024))"
  342. echo "size:${gbytes}GB;sector_size:$sectorsize"
  343. done
  344. }
  345. show_partitions() {
  346. local dev fstype fssize p part
  347. set -- $(show_disks)
  348. while [ $# -ne 0 ]; do
  349. disk=$(basename $1)
  350. shift 2
  351. # ATA/SCSI/SATA
  352. for p in /sys/block/$disk/$disk*; do
  353. if [ -d $p ]; then
  354. part=$(basename $p)
  355. fstype=$(lsblk -nfr /dev/$part|awk '{print $2}'|head -1)
  356. [ "$fstype" = "iso9660" ] && continue
  357. [ "$fstype" = "crypto_LUKS" ] && continue
  358. [ "$fstype" = "LVM2_member" ] && continue
  359. fssize=$(lsblk -nr /dev/$part|awk '{print $4}'|head -1)
  360. echo "/dev/$part"
  361. echo "size:${fssize:-unknown};fstype:${fstype:-none}"
  362. fi
  363. done
  364. done
  365. # Device Mapper
  366. for p in /dev/mapper/*; do
  367. part=$(basename $p)
  368. [ "${part}" = "live-rw" ] && continue
  369. [ "${part}" = "live-base" ] && continue
  370. [ "${part}" = "control" ] && continue
  371. fstype=$(lsblk -nfr $p|awk '{print $2}'|head -1)
  372. fssize=$(lsblk -nr $p|awk '{print $4}'|head -1)
  373. echo "${p}"
  374. echo "size:${fssize:-unknown};fstype:${fstype:-none}"
  375. done
  376. # Software raid (md)
  377. for p in $(ls -d /dev/md* 2>/dev/null|grep '[0-9]'); do
  378. part=$(basename $p)
  379. if cat /proc/mdstat|grep -qw $part; then
  380. fstype=$(lsblk -nfr /dev/$part|awk '{print $2}')
  381. [ "$fstype" = "crypto_LUKS" ] && continue
  382. [ "$fstype" = "LVM2_member" ] && continue
  383. fssize=$(lsblk -nr /dev/$part|awk '{print $4}')
  384. echo "$p"
  385. echo "size:${fssize:-unknown};fstype:${fstype:-none}"
  386. fi
  387. done
  388. # cciss(4) devices
  389. for part in $(ls /dev/cciss 2>/dev/null|grep -E 'c[0-9]d[0-9]p[0-9]+'); do
  390. fstype=$(lsblk -nfr /dev/cciss/$part|awk '{print $2}')
  391. [ "$fstype" = "crypto_LUKS" ] && continue
  392. [ "$fstype" = "LVM2_member" ] && continue
  393. fssize=$(lsblk -nr /dev/cciss/$part|awk '{print $4}')
  394. echo "/dev/cciss/$part"
  395. echo "size:${fssize:-unknown};fstype:${fstype:-none}"
  396. done
  397. if [ -e /sbin/lvs ]; then
  398. # LVM
  399. lvs --noheadings|while read lvname vgname perms size; do
  400. echo "/dev/mapper/${vgname}-${lvname}"
  401. echo "size:${size};fstype:lvm"
  402. done
  403. fi
  404. }
  405. menu_filesystems() {
  406. local dev fstype fssize mntpoint reformat
  407. while true; do
  408. DIALOG --ok-label "Change" --cancel-label "Done" \
  409. --title " Select the partition to edit " --menu "$MENULABEL" \
  410. ${MENUSIZE} $(show_partitions)
  411. [ $? -ne 0 ] && return
  412. dev=$(cat $ANSWER)
  413. DIALOG --title " Select the filesystem type for $dev " \
  414. --menu "$MENULABEL" ${MENUSIZE} \
  415. "btrfs" "Oracle's Btrfs" \
  416. "ext2" "Linux ext2 (no journaling)" \
  417. "ext3" "Linux ext3 (journal)" \
  418. "ext4" "Linux ext4 (journal)" \
  419. "f2fs" "Flash-Friendly Filesystem" \
  420. "swap" "Linux swap" \
  421. "vfat" "FAT32" \
  422. "xfs" "SGI's XFS"
  423. if [ $? -eq 0 ]; then
  424. fstype=$(cat $ANSWER)
  425. else
  426. continue
  427. fi
  428. if [ "$fstype" != "swap" ]; then
  429. DIALOG --inputbox "Please specify the mount point for $dev:" ${INPUTSIZE}
  430. if [ $? -eq 0 ]; then
  431. mntpoint=$(cat $ANSWER)
  432. elif [ $? -eq 1 ]; then
  433. continue
  434. fi
  435. else
  436. mntpoint=swap
  437. fi
  438. DIALOG --yesno "Do you want to create a new filesystem on $dev?" ${YESNOSIZE}
  439. if [ $? -eq 0 ]; then
  440. reformat=1
  441. elif [ $? -eq 1 ]; then
  442. reformat=0
  443. else
  444. continue
  445. fi
  446. fssize=$(lsblk -nr $dev|awk '{print $4}')
  447. set -- "$fstype" "$fssize" "$mntpoint" "$reformat"
  448. if [ -n "$1" -a -n "$2" -a -n "$3" -a -n "$4" ]; then
  449. local bdev=$(basename $dev)
  450. local ddev=$(basename $(dirname $dev))
  451. if [ "$ddev" != "dev" ]; then
  452. sed -i -e "/^MOUNTPOINT \/dev\/${ddev}\/${bdev}.*/d" $CONF_FILE
  453. else
  454. sed -i -e "/^MOUNTPOINT \/dev\/${bdev}.*/d" $CONF_FILE
  455. fi
  456. echo "MOUNTPOINT $dev $1 $2 $3 $4" >>$CONF_FILE
  457. fi
  458. done
  459. }
  460. menu_partitions() {
  461. DIALOG --title " Select the disk to partition " \
  462. --menu "$MENULABEL" ${MENUSIZE} $(show_disks)
  463. if [ $? -eq 0 ]; then
  464. local device=$(cat $ANSWER)
  465. DIALOG --title " Select the software for partitioning " \
  466. --menu "$MENULABEL" ${MENUSIZE} \
  467. "cfdisk" "Easy to use" \
  468. "fdisk" "More advanced"
  469. if [ $? -eq 0 ]; then
  470. local software=$(cat $ANSWER)
  471. DIALOG --title "Modify Partition Table on $device" --msgbox "\n
  472. ${BOLD}${software} will be executed in disk $device.${RESET}\n\n
  473. For BIOS systems, MBR or GPT partition tables are supported.\n
  474. To use GPT on PC BIOS systems an empty partition of 1MB must be added\n
  475. at the first 2GB of the disk with the TOGGLE \`bios_grub' enabled.\n
  476. ${BOLD}NOTE: you don't need this on EFI systems.${RESET}\n\n
  477. For EFI systems GPT is mandatory and a FAT32 partition with at least\n
  478. 100MB must be created with the TOGGLE \`boot', this will be used as\n
  479. EFI System Partition. This partition must have mountpoint as \`/boot/efi'.\n\n
  480. At least 1 partition is required for the rootfs (/).\n
  481. For swap, RAM*2 must be really enough. For / 600MB are required.\n\n
  482. ${BOLD}WARNING: /usr is not supported as a separate partition.${RESET}\n
  483. ${RESET}\n" 18 80
  484. if [ $? -eq 0 ]; then
  485. while true; do
  486. clear; $software $device; PARTITIONS_DONE=1
  487. break
  488. done
  489. else
  490. return
  491. fi
  492. fi
  493. fi
  494. }
  495. menu_keymap() {
  496. local _keymaps="$(find /usr/share/kbd/keymaps/ -type f -iname "*.map.gz" -printf "%f\n" | sed 's|.map.gz||g' | sort)"
  497. local _KEYMAPS=
  498. for f in ${_keymaps}; do
  499. _KEYMAPS="${_KEYMAPS} ${f} -"
  500. done
  501. while true; do
  502. DIALOG --title " Select your keymap " --menu "$MENULABEL" 14 70 14 ${_KEYMAPS}
  503. if [ $? -eq 0 ]; then
  504. set_option KEYMAP "$(cat $ANSWER)"
  505. loadkeys "$(cat $ANSWER)"
  506. KEYBOARD_DONE=1
  507. break
  508. else
  509. return
  510. fi
  511. done
  512. }
  513. set_keymap() {
  514. local KEYMAP=$(get_option KEYMAP)
  515. if [ -f /etc/vconsole.conf ]; then
  516. sed -i -e "s|KEYMAP=.*|KEYMAP=$KEYMAP|g" $TARGETDIR/etc/vconsole.conf
  517. else
  518. sed -i -e "s|#\?KEYMAP=.*|KEYMAP=$KEYMAP|g" $TARGETDIR/etc/rc.conf
  519. fi
  520. }
  521. menu_locale() {
  522. local _locales="$(grep -E '\.UTF-8' /etc/default/libc-locales|awk '{print $1}'|sed -e 's/^#//')"
  523. local LOCALES ISO639 ISO3166
  524. local TMPFILE=$(mktemp -t vinstall-XXXXXXXX || exit 1)
  525. INFOBOX "Scanning locales ..." 4 60
  526. for f in ${_locales}; do
  527. eval $(echo $f | awk 'BEGIN { FS="." } \
  528. { FS="_"; split($1, a); printf "ISO639=%s ISO3166=%s\n", a[1], a[2] }')
  529. echo "$f|$(iso639_language $ISO639) ($(iso3166_country $ISO3166))|" >> $TMPFILE
  530. done
  531. clear
  532. # Sort by ISO-639 language names
  533. LOCALES=$(sort -t '|' -k 2 < $TMPFILE | xargs | sed -e's/| /|/g')
  534. rm -f $TMPFILE
  535. while true; do
  536. (IFS="|"; DIALOG --title " Select your locale " --menu "$MENULABEL" 18 70 18 ${LOCALES})
  537. if [ $? -eq 0 ]; then
  538. set_option LOCALE "$(cat $ANSWER)"
  539. LOCALE_DONE=1
  540. break
  541. else
  542. return
  543. fi
  544. done
  545. }
  546. set_locale() {
  547. if [ -f $TARGETDIR/etc/default/libc-locales ]; then
  548. local LOCALE="$(get_option LOCALE)"
  549. : "${LOCALE:=C.UTF-8}"
  550. sed -i -e "s|LANG=.*|LANG=$LOCALE|g" $TARGETDIR/etc/locale.conf
  551. # Uncomment locale from /etc/default/libc-locales and regenerate it.
  552. sed -e "/${LOCALE}/s/^\#//" -i $TARGETDIR/etc/default/libc-locales
  553. echo "Running xbps-reconfigure -f glibc-locales ..." >$LOG
  554. chroot $TARGETDIR xbps-reconfigure -f glibc-locales >$LOG 2>&1
  555. fi
  556. }
  557. menu_timezone() {
  558. local areas=(Africa America Antarctica Arctic Asia Atlantic Australia Europe Indian Pacific)
  559. local area locations location
  560. while (IFS='|'; DIALOG ${area:+--default-item|"$area"} --title " Select area " --menu "$MENULABEL" 19 51 19 $(printf '%s||' "${areas[@]}")); do
  561. area=$(cat $ANSWER)
  562. read -a locations -d '\n' < <(find /usr/share/zoneinfo/$area -type f -printf '%P\n' | sort)
  563. if (IFS='|'; DIALOG --title " Select location (${area}) " --menu "$MENULABEL" 19 51 19 $(printf '%s||' "${locations[@]//_/ }")); then
  564. location=$(tr ' ' '_' < $ANSWER)
  565. set_option TIMEZONE "$area/$location"
  566. TIMEZONE_DONE=1
  567. return 0
  568. else
  569. continue
  570. fi
  571. done
  572. return 1
  573. }
  574. set_timezone() {
  575. local TIMEZONE="$(get_option TIMEZONE)"
  576. ln -sf "/usr/share/zoneinfo/${TIMEZONE}" "${TARGETDIR}/etc/localtime"
  577. }
  578. menu_hostname() {
  579. while true; do
  580. DIALOG --inputbox "Set the machine hostname:" ${INPUTSIZE}
  581. if [ $? -eq 0 ]; then
  582. set_option HOSTNAME "$(cat $ANSWER)"
  583. HOSTNAME_DONE=1
  584. break
  585. else
  586. return
  587. fi
  588. done
  589. }
  590. set_hostname() {
  591. local hostname="$(get_option HOSTNAME)"
  592. echo "${hostname:-void}" > $TARGETDIR/etc/hostname
  593. }
  594. menu_rootpassword() {
  595. local _firstpass _secondpass _again _desc
  596. while true; do
  597. if [ -z "${_firstpass}" ]; then
  598. _desc="Enter the root password"
  599. else
  600. _again=" again"
  601. fi
  602. DIALOG --insecure --passwordbox "${_desc}${_again}" ${INPUTSIZE}
  603. if [ $? -eq 0 ]; then
  604. if [ -z "${_firstpass}" ]; then
  605. _firstpass="$(cat $ANSWER)"
  606. else
  607. _secondpass="$(cat $ANSWER)"
  608. fi
  609. if [ -n "${_firstpass}" -a -n "${_secondpass}" ]; then
  610. if [ "${_firstpass}" != "${_secondpass}" ]; then
  611. INFOBOX "Passwords do not match! Please enter again." 6 60
  612. unset _firstpass _secondpass _again
  613. sleep 2 && clear && continue
  614. fi
  615. set_option ROOTPASSWORD "${_firstpass}"
  616. ROOTPASSWORD_DONE=1
  617. break
  618. fi
  619. else
  620. return
  621. fi
  622. done
  623. }
  624. set_rootpassword() {
  625. echo "root:$(get_option ROOTPASSWORD)" | chroot $TARGETDIR chpasswd -c SHA512
  626. }
  627. menu_useraccount() {
  628. local _firstpass _secondpass _desc _again
  629. local _groups _status _group _checklist
  630. local _preset _userlogin
  631. while true; do
  632. _preset=$(get_option USERLOGIN)
  633. [ -z "$_preset" ] && _preset="void"
  634. DIALOG --inputbox "Enter a primary login name:" ${INPUTSIZE} "$_preset"
  635. if [ $? -eq 0 ]; then
  636. _userlogin="$(cat $ANSWER)"
  637. # based on useradd(8) § Caveats
  638. if [ "${#_userlogin}" -le 32 ] && [[ "${_userlogin}" =~ ^[a-z_][a-z0-9_-]*[$]?$ ]]; then
  639. set_option USERLOGIN "${_userlogin}"
  640. USERLOGIN_DONE=1
  641. break
  642. else
  643. INFOBOX "Invalid login name! Please try again." 6 60
  644. unset _userlogin
  645. sleep 2 && clear && continue
  646. fi
  647. else
  648. return
  649. fi
  650. done
  651. while true; do
  652. _preset=$(get_option USERNAME)
  653. [ -z "$_preset" ] && _preset="Void User"
  654. DIALOG --inputbox "Enter a user name for login '$(get_option USERLOGIN)' :" \
  655. ${INPUTSIZE} "$_preset"
  656. if [ $? -eq 0 ]; then
  657. set_option USERNAME "$(cat $ANSWER)"
  658. USERNAME_DONE=1
  659. break
  660. else
  661. return
  662. fi
  663. done
  664. while true; do
  665. if [ -z "${_firstpass}" ]; then
  666. _desc="Enter the password for login '$(get_option USERLOGIN)'"
  667. else
  668. _again=" again"
  669. fi
  670. DIALOG --insecure --passwordbox "${_desc}${_again}" ${INPUTSIZE}
  671. if [ $? -eq 0 ]; then
  672. if [ -z "${_firstpass}" ]; then
  673. _firstpass="$(cat $ANSWER)"
  674. else
  675. _secondpass="$(cat $ANSWER)"
  676. fi
  677. if [ -n "${_firstpass}" -a -n "${_secondpass}" ]; then
  678. if [ "${_firstpass}" != "${_secondpass}" ]; then
  679. INFOBOX "Passwords do not match! Please enter again." 6 60
  680. unset _firstpass _secondpass _again
  681. sleep 2 && clear && continue
  682. fi
  683. set_option USERPASSWORD "${_firstpass}"
  684. USERPASSWORD_DONE=1
  685. break
  686. fi
  687. else
  688. return
  689. fi
  690. done
  691. _groups="wheel,audio,video,floppy,cdrom,optical,kvm,xbuilder"
  692. while true; do
  693. _desc="Select group membership for login '$(get_option USERLOGIN)':"
  694. for _group in $(cat /etc/group); do
  695. _gid="$(echo ${_group} | cut -d: -f3)"
  696. _group="$(echo ${_group} | cut -d: -f1)"
  697. _status="$(echo ${_groups} | grep -w ${_group})"
  698. if [ -z "${_status}" ]; then
  699. _status=off
  700. else
  701. _status=on
  702. fi
  703. # ignore the groups of existing users and package groups
  704. if [[ "${_gid}" -ge 1000 || "${_group}" = "_"* ]]; then
  705. continue
  706. fi
  707. if [ -z "${_checklist}" ]; then
  708. _checklist="${_group} ${_group}:${_gid} ${_status}"
  709. else
  710. _checklist="${_checklist} ${_group} ${_group}:${_gid} ${_status}"
  711. fi
  712. done
  713. DIALOG --no-tags --checklist "${_desc}" 20 60 18 ${_checklist}
  714. if [ $? -eq 0 ]; then
  715. set_option USERGROUPS $(cat $ANSWER | sed -e's| |,|g')
  716. USERGROUPS_DONE=1
  717. break
  718. else
  719. return
  720. fi
  721. done
  722. }
  723. set_useraccount() {
  724. [ -z "$USERLOGIN_DONE" ] && return
  725. [ -z "$USERPASSWORD_DONE" ] && return
  726. [ -z "$USERNAME_DONE" ] && return
  727. [ -z "$USERGROUPS_DONE" ] && return
  728. chroot $TARGETDIR useradd -m -G "$(get_option USERGROUPS)" \
  729. -c "$(get_option USERNAME)" "$(get_option USERLOGIN)"
  730. echo "$(get_option USERLOGIN):$(get_option USERPASSWORD)" | \
  731. chroot $TARGETDIR chpasswd -c SHA512
  732. }
  733. menu_bootloader() {
  734. while true; do
  735. DIALOG --title " Select the disk to install the bootloader" \
  736. --menu "$MENULABEL" ${MENUSIZE} $(show_disks) none "Manage bootloader otherwise"
  737. if [ $? -eq 0 ]; then
  738. set_option BOOTLOADER "$(cat $ANSWER)"
  739. BOOTLOADER_DONE=1
  740. break
  741. else
  742. return
  743. fi
  744. done
  745. while true; do
  746. DIALOG --yesno "Use a graphical terminal for the boot loader?" ${YESNOSIZE}
  747. if [ $? -eq 0 ]; then
  748. set_option TEXTCONSOLE 0
  749. break
  750. elif [ $? -eq 1 ]; then
  751. set_option TEXTCONSOLE 1
  752. break
  753. else
  754. return
  755. fi
  756. done
  757. }
  758. set_bootloader() {
  759. local dev=$(get_option BOOTLOADER) grub_args=
  760. if [ "$dev" = "none" ]; then return; fi
  761. # Check if it's an EFI system via efivars module.
  762. if [ -n "$EFI_SYSTEM" ]; then
  763. grub_args="--target=$EFI_TARGET --efi-directory=/boot/efi --bootloader-id=void_grub --recheck"
  764. fi
  765. echo "Running grub-install $grub_args $dev..." >$LOG
  766. chroot $TARGETDIR grub-install $grub_args $dev >$LOG 2>&1
  767. if [ $? -ne 0 ]; then
  768. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  769. failed to install GRUB to $dev!\nCheck $LOG for errors." ${MSGBOXSIZE}
  770. DIE 1
  771. fi
  772. echo "Running grub-mkconfig on $TARGETDIR..." >$LOG
  773. chroot $TARGETDIR grub-mkconfig -o /boot/grub/grub.cfg >$LOG 2>&1
  774. if [ $? -ne 0 ]; then
  775. DIALOG --msgbox "${BOLD}${RED}ERROR${RESET}: \
  776. failed to run grub-mkconfig!\nCheck $LOG for errors." ${MSGBOXSIZE}
  777. DIE 1
  778. fi
  779. }
  780. test_network() {
  781. rm -f otime && \
  782. xbps-uhelper fetch https://repo-default.voidlinux.org/current/otime >$LOG 2>&1
  783. if [ $? -eq 0 ]; then
  784. DIALOG --msgbox "Network is working properly!" ${MSGBOXSIZE}
  785. NETWORK_DONE=1
  786. return 1
  787. fi
  788. if [ "$1" = "nm" ]; then
  789. DIALOG --msgbox "Network Manager is enabled but network is inaccessible, please set it up externally with nmcli, nmtui, or the Network Manager tray applet." ${MSGBOXSIZE}
  790. else
  791. DIALOG --msgbox "Network is inaccessible, please set it up properly." ${MSGBOXSIZE}
  792. fi
  793. }
  794. configure_wifi() {
  795. local dev="$1" ssid enc pass _wpasupconf=/etc/wpa_supplicant/wpa_supplicant.conf
  796. DIALOG --form "Wireless configuration for ${dev}\n(encryption type: wep or wpa)" 0 0 0 \
  797. "SSID:" 1 1 "" 1 16 30 0 \
  798. "Encryption:" 2 1 "" 2 16 4 3 \
  799. "Password:" 3 1 "" 3 16 63 0 || return 1
  800. readarray -t values <<<$(cat $ANSWER)
  801. ssid="${values[0]}"; enc="${values[1]}"; pass="${values[2]}"
  802. if [ -z "$ssid" ]; then
  803. DIALOG --msgbox "Invalid SSID." ${MSGBOXSIZE}
  804. return 1
  805. elif [ -z "$enc" -o "$enc" != "wep" -a "$enc" != "wpa" ]; then
  806. DIALOG --msgbox "Invalid encryption type (possible values: wep or wpa)." ${MSGBOXSIZE}
  807. return 1
  808. elif [ -z "$pass" ]; then
  809. DIALOG --msgbox "Invalid AP password." ${MSGBOXSIZE}
  810. fi
  811. # reset the configuration to the default, if necessary
  812. # otherwise backup the configuration
  813. if [ -f ${_wpasupconf}.orig ]; then
  814. cp -f ${_wpasupconf}.orig ${_wpasupconf}
  815. else
  816. cp -f ${_wpasupconf} ${_wpasupconf}.orig
  817. fi
  818. if [ "$enc" = "wep" ]; then
  819. cat << EOF >> ${_wpasupconf}
  820. network={
  821. ssid="$ssid"
  822. wep_key0="$pass"
  823. wep_tx_keyidx=0
  824. auth_alg=SHARED
  825. }
  826. EOF
  827. else
  828. wpa_passphrase "$ssid" "$pass" >> ${_wpasupconf}
  829. fi
  830. sv restart wpa_supplicant
  831. configure_net_dhcp $dev
  832. return $?
  833. }
  834. configure_net() {
  835. local dev="$1" rval
  836. DIALOG --yesno "Do you want to use DHCP for $dev?" ${YESNOSIZE}
  837. rval=$?
  838. if [ $rval -eq 0 ]; then
  839. configure_net_dhcp $dev
  840. elif [ $rval -eq 1 ]; then
  841. configure_net_static $dev
  842. fi
  843. }
  844. iface_setup() {
  845. ip addr show dev $1 | grep -q -e 'inet ' -e 'inet6 '
  846. return $?
  847. }
  848. configure_net_dhcp() {
  849. local dev="$1"
  850. iface_setup $dev
  851. if [ $? -eq 1 ]; then
  852. sv restart dhcpcd 2>&1 | tee $LOG | \
  853. DIALOG --progressbox "Initializing $dev via DHCP..." ${WIDGET_SIZE}
  854. if [ $? -ne 0 ]; then
  855. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} failed to run dhcpcd. See $LOG for details." ${MSGBOXSIZE}
  856. return 1
  857. fi
  858. export -f iface_setup
  859. timeout 10s bash -c "while true; do iface_setup $dev; sleep 0.25; done"
  860. if [ $? -eq 1 ]; then
  861. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} DHCP request failed for $dev. Check $LOG for errors." ${MSGBOXSIZE}
  862. return 1
  863. fi
  864. fi
  865. test_network
  866. if [ $? -eq 1 ]; then
  867. set_option NETWORK "${dev} dhcp"
  868. fi
  869. }
  870. configure_net_static() {
  871. local ip gw dns1 dns2 dev=$1
  872. DIALOG --form "Static IP configuration for $dev:" 0 0 0 \
  873. "IP address:" 1 1 "192.168.0.2" 1 21 20 0 \
  874. "Gateway:" 2 1 "192.168.0.1" 2 21 20 0 \
  875. "DNS Primary" 3 1 "8.8.8.8" 3 21 20 0 \
  876. "DNS Secondary" 4 1 "8.8.4.4" 4 21 20 0 || return 1
  877. set -- $(cat $ANSWER)
  878. ip=$1; gw=$2; dns1=$3; dns2=$4
  879. echo "running: ip link set dev $dev up" >$LOG
  880. ip link set dev $dev up >$LOG 2>&1
  881. if [ $? -ne 0 ]; then
  882. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} Failed to bring $dev interface." ${MSGBOXSIZE}
  883. return 1
  884. fi
  885. echo "running: ip addr add $ip dev $dev" >$LOG
  886. ip addr add $ip dev $dev >$LOG 2>&1
  887. if [ $? -ne 0 ]; then
  888. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} Failed to set ip to the $dev interface." ${MSGBOXSIZE}
  889. return 1
  890. fi
  891. ip route add default via $gw >$LOG 2>&1
  892. if [ $? -ne 0 ]; then
  893. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} failed to setup your gateway." ${MSGBOXSIZE}
  894. return 1
  895. fi
  896. echo "nameserver $dns1" >/etc/resolv.conf
  897. echo "nameserver $dns2" >>/etc/resolv.conf
  898. test_network
  899. if [ $? -eq 1 ]; then
  900. set_option NETWORK "${dev} static $ip $gw $dns1 $dns2"
  901. fi
  902. }
  903. menu_network() {
  904. local dev addr f DEVICES
  905. if [ -e /var/service/NetworkManager ]; then
  906. test_network nm
  907. return
  908. fi
  909. for f in $(ls /sys/class/net); do
  910. [ "$f" = "lo" ] && continue
  911. addr=$(cat /sys/class/net/$f/address)
  912. DEVICES="$DEVICES $f $addr"
  913. done
  914. DIALOG --title " Select the network interface to configure " \
  915. --menu "$MENULABEL" ${MENUSIZE} ${DEVICES}
  916. if [ $? -eq 0 ]; then
  917. dev=$(cat $ANSWER)
  918. if $(echo $dev|egrep -q "^wl.*" 2>/dev/null); then
  919. configure_wifi $dev
  920. else
  921. configure_net $dev
  922. fi
  923. fi
  924. }
  925. validate_filesystems() {
  926. local mnts dev size fstype mntpt mkfs rootfound fmt
  927. local usrfound efi_system_partition
  928. local bootdev=$(get_option BOOTLOADER)
  929. unset TARGETFS
  930. mnts=$(grep -E '^MOUNTPOINT.*' $CONF_FILE)
  931. set -- ${mnts}
  932. while [ $# -ne 0 ]; do
  933. fmt=""
  934. dev=$2; fstype=$3; size=$4; mntpt="$5"; mkfs=$6
  935. shift 6
  936. if [ "$mntpt" = "/" ]; then
  937. rootfound=1
  938. elif [ "$mntpt" = "/usr" ]; then
  939. usrfound=1
  940. elif [ "$fstype" = "vfat" -a "$mntpt" = "/boot/efi" ]; then
  941. efi_system_partition=1
  942. fi
  943. if [ "$mkfs" -eq 1 ]; then
  944. fmt="NEW FILESYSTEM: "
  945. fi
  946. if [ -z "$TARGETFS" ]; then
  947. TARGETFS="${fmt}$dev ($size) mounted on $mntpt as ${fstype}\n"
  948. else
  949. TARGETFS="${TARGETFS}${fmt}${dev} ($size) mounted on $mntpt as ${fstype}\n"
  950. fi
  951. done
  952. if [ -z "$rootfound" ]; then
  953. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  954. the mount point for the root filesystem (/) has not yet been configured." ${MSGBOXSIZE}
  955. return 1
  956. elif [ -n "$usrfound" ]; then
  957. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  958. /usr mount point has been configured but is not supported, please remove it to continue." ${MSGBOXSIZE}
  959. return 1
  960. elif [ -n "$EFI_SYSTEM" -a "$bootdev" != "none" -a -z "$efi_system_partition" ]; then
  961. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  962. The EFI System Partition has not yet been configured, please create it\n
  963. as FAT32, mountpoint /boot/efi and at least with 100MB of size." ${MSGBOXSIZE}
  964. return 1
  965. fi
  966. FILESYSTEMS_DONE=1
  967. }
  968. create_filesystems() {
  969. local mnts dev mntpt fstype fspassno mkfs size rv uuid
  970. mnts=$(grep -E '^MOUNTPOINT.*' $CONF_FILE)
  971. set -- ${mnts}
  972. while [ $# -ne 0 ]; do
  973. dev=$2; fstype=$3; mntpt="$5"; mkfs=$6
  974. shift 6
  975. # swap partitions
  976. if [ "$fstype" = "swap" ]; then
  977. swapoff $dev >/dev/null 2>&1
  978. if [ "$mkfs" -eq 1 ]; then
  979. mkswap $dev >$LOG 2>&1
  980. if [ $? -ne 0 ]; then
  981. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  982. failed to create swap on ${dev}!\ncheck $LOG for errors." ${MSGBOXSIZE}
  983. DIE 1
  984. fi
  985. fi
  986. swapon $dev >$LOG 2>&1
  987. if [ $? -ne 0 ]; then
  988. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  989. failed to activate swap on $dev!\ncheck $LOG for errors." ${MSGBOXSIZE}
  990. DIE 1
  991. fi
  992. # Add entry for target fstab
  993. uuid=$(blkid -o value -s UUID "$dev")
  994. echo "UUID=$uuid none swap defaults 0 0" >>$TARGET_FSTAB
  995. continue
  996. fi
  997. if [ "$mkfs" -eq 1 ]; then
  998. case "$fstype" in
  999. btrfs) MKFS="mkfs.btrfs -f"; modprobe btrfs >$LOG 2>&1;;
  1000. ext2) MKFS="mke2fs -F"; modprobe ext2 >$LOG 2>&1;;
  1001. ext3) MKFS="mke2fs -F -j"; modprobe ext3 >$LOG 2>&1;;
  1002. ext4) MKFS="mke2fs -F -t ext4"; modprobe ext4 >$LOG 2>&1;;
  1003. f2fs) MKFS="mkfs.f2fs -f"; modprobe f2fs >$LOG 2>&1;;
  1004. vfat) MKFS="mkfs.vfat -F32"; modprobe vfat >$LOG 2>&1;;
  1005. xfs) MKFS="mkfs.xfs -f -i sparse=0"; modprobe xfs >$LOG 2>&1;;
  1006. esac
  1007. TITLE="Check $LOG for details ..."
  1008. INFOBOX "Creating filesystem $fstype on $dev for $mntpt ..." 8 60
  1009. echo "Running $MKFS $dev..." >$LOG
  1010. $MKFS $dev >$LOG 2>&1; rv=$?
  1011. if [ $rv -ne 0 ]; then
  1012. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  1013. failed to create filesystem $fstype on $dev!\ncheck $LOG for errors." ${MSGBOXSIZE}
  1014. DIE 1
  1015. fi
  1016. fi
  1017. # Mount rootfs the first one.
  1018. [ "$mntpt" != "/" ] && continue
  1019. mkdir -p $TARGETDIR
  1020. echo "Mounting $dev on $mntpt ($fstype)..." >$LOG
  1021. mount -t $fstype $dev $TARGETDIR >$LOG 2>&1
  1022. if [ $? -ne 0 ]; then
  1023. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  1024. failed to mount $dev on ${mntpt}! check $LOG for errors." ${MSGBOXSIZE}
  1025. DIE 1
  1026. fi
  1027. # Add entry to target fstab
  1028. uuid=$(blkid -o value -s UUID "$dev")
  1029. if [ "$fstype" = "f2fs" -o "$fstype" = "btrfs" -o "$fstype" = "xfs" ]; then
  1030. fspassno=0
  1031. else
  1032. fspassno=1
  1033. fi
  1034. echo "UUID=$uuid $mntpt $fstype defaults 0 $fspassno" >>$TARGET_FSTAB
  1035. done
  1036. # mount all filesystems in target rootfs
  1037. mnts=$(grep -E '^MOUNTPOINT.*' $CONF_FILE)
  1038. set -- ${mnts}
  1039. while [ $# -ne 0 ]; do
  1040. dev=$2; fstype=$3; mntpt="$5"
  1041. shift 6
  1042. [ "$mntpt" = "/" -o "$fstype" = "swap" ] && continue
  1043. mkdir -p ${TARGETDIR}${mntpt}
  1044. echo "Mounting $dev on $mntpt ($fstype)..." >$LOG
  1045. mount -t $fstype $dev ${TARGETDIR}${mntpt} >$LOG 2>&1
  1046. if [ $? -ne 0 ]; then
  1047. DIALOG --msgbox "${BOLD}${RED}ERROR:${RESET} \
  1048. failed to mount $dev on $mntpt! check $LOG for errors." ${MSGBOXSIZE}
  1049. DIE
  1050. fi
  1051. # Add entry to target fstab
  1052. uuid=$(blkid -o value -s UUID "$dev")
  1053. if [ "$fstype" = "f2fs" -o "$fstype" = "btrfs" -o "$fstype" = "xfs" ]; then
  1054. fspassno=0
  1055. else
  1056. fspassno=2
  1057. fi
  1058. echo "UUID=$uuid $mntpt $fstype defaults 0 $fspassno" >>$TARGET_FSTAB
  1059. done
  1060. }
  1061. mount_filesystems() {
  1062. for f in sys proc dev; do
  1063. [ ! -d $TARGETDIR/$f ] && mkdir $TARGETDIR/$f
  1064. echo "Mounting $TARGETDIR/$f..." >$LOG
  1065. mount --rbind /$f $TARGETDIR/$f >$LOG 2>&1
  1066. done
  1067. }
  1068. umount_filesystems() {
  1069. local f
  1070. for f in sys/fs/fuse/connections sys proc dev; do
  1071. echo "Unmounting $TARGETDIR/$f..." >$LOG
  1072. umount $TARGETDIR/$f >$LOG 2>&1
  1073. done
  1074. local mnts="$(grep -E '^MOUNTPOINT.*$' $CONF_FILE)"
  1075. set -- ${mnts}
  1076. while [ $# -ne 0 ]; do
  1077. local dev=$2; local fstype=$3; local mntpt=$5
  1078. shift 6
  1079. if [ "$fstype" = "swap" ]; then
  1080. echo "Disabling swap space on $dev..." >$LOG
  1081. swapoff $dev >$LOG 2>&1
  1082. continue
  1083. fi
  1084. if [ "$mntpt" != "/" ]; then
  1085. echo "Unmounting $TARGETDIR/$mntpt..." >$LOG
  1086. umount $TARGETDIR/$mntpt >$LOG 2>&1
  1087. fi
  1088. done
  1089. echo "Unmounting $TARGETDIR..." >$LOG
  1090. umount $TARGETDIR >$LOG 2>&1
  1091. }
  1092. log_and_count() {
  1093. local progress whole tenth
  1094. while read line; do
  1095. echo "$line" >$LOG
  1096. copy_count=$((copy_count + 1))
  1097. progress=$((1000 * copy_count / copy_total))
  1098. if [ "$progress" != "$copy_progress" ]; then
  1099. whole=$((progress / 10))
  1100. tenth=$((progress % 10))
  1101. printf "Progress: %d.%d%% (%d of %d files)\n" $whole $tenth $copy_count $copy_total
  1102. copy_progress=$progress
  1103. fi
  1104. done
  1105. }
  1106. copy_rootfs() {
  1107. local tar_in="--create --one-file-system --xattrs"
  1108. TITLE="Check $LOG for details ..."
  1109. INFOBOX "Counting files, please be patient ..." 4 60
  1110. copy_total=$(tar ${tar_in} -v -f /dev/null / 2>/dev/null | wc -l)
  1111. export copy_total copy_count=0 copy_progress=
  1112. clear
  1113. tar ${tar_in} -f - / 2>/dev/null | \
  1114. tar --extract --xattrs --xattrs-include='*' --preserve-permissions -v -f - -C $TARGETDIR | \
  1115. log_and_count | \
  1116. DIALOG --title "${TITLE}" \
  1117. --progressbox "Copying live image to target rootfs." 5 60
  1118. if [ $? -ne 0 ]; then
  1119. DIE 1
  1120. fi
  1121. unset copy_total copy_count copy_percent
  1122. }
  1123. install_packages() {
  1124. local _grub= _syspkg=
  1125. if [ -n "$EFI_SYSTEM" ]; then
  1126. if [ $EFI_FW_BITS -eq 32 ]; then
  1127. _grub="grub-i386-efi"
  1128. else
  1129. _grub="grub-x86_64-efi"
  1130. fi
  1131. else
  1132. _grub="grub"
  1133. fi
  1134. _syspkg="base-system"
  1135. mkdir -p $TARGETDIR/var/db/xbps/keys $TARGETDIR/usr/share
  1136. cp -a /usr/share/xbps.d $TARGETDIR/usr/share/
  1137. cp /var/db/xbps/keys/*.plist $TARGETDIR/var/db/xbps/keys
  1138. if [ -n "$MIRROR_DONE" ]; then
  1139. mkdir -p $TARGETDIR/etc
  1140. cp -a /etc/xbps.d $TARGETDIR/etc
  1141. fi
  1142. mkdir -p $TARGETDIR/boot/grub
  1143. _arch=$(xbps-uhelper arch)
  1144. stdbuf -oL env XBPS_ARCH=${_arch} \
  1145. xbps-install -r $TARGETDIR -SyU ${_syspkg} ${_grub} 2>&1 | \
  1146. DIALOG --title "Installing base system packages..." \
  1147. --programbox 24 80
  1148. if [ $? -ne 0 ]; then
  1149. DIE 1
  1150. fi
  1151. xbps-reconfigure -r $TARGETDIR -f base-files >/dev/null 2>&1
  1152. chroot $TARGETDIR xbps-reconfigure -a
  1153. }
  1154. enable_dhcpd() {
  1155. ln -sf /etc/sv/dhcpcd $TARGETDIR/etc/runit/runsvdir/default/dhcpcd
  1156. }
  1157. menu_install() {
  1158. ROOTPASSWORD_DONE="$(get_option ROOTPASSWORD)"
  1159. BOOTLOADER_DONE="$(get_option BOOTLOADER)"
  1160. if [ -z "$ROOTPASSWORD_DONE" ]; then
  1161. DIALOG --msgbox "${BOLD}The root password has not been configured, \
  1162. please do so before starting the installation.${RESET}" ${MSGBOXSIZE}
  1163. return 1
  1164. elif [ -z "$BOOTLOADER_DONE" ]; then
  1165. DIALOG --msgbox "${BOLD}The disk to install the bootloader has not been \
  1166. configured, please do so before starting the installation.${RESET}" ${MSGBOXSIZE}
  1167. return 1
  1168. fi
  1169. # Validate filesystems after making sure bootloader is done,
  1170. # so that specific checks can be made based on the selection
  1171. validate_filesystems || return 1
  1172. if [ -z "$FILESYSTEMS_DONE" ]; then
  1173. DIALOG --msgbox "${BOLD}Required filesystems were not configured, \
  1174. please do so before starting the installation.${RESET}" ${MSGBOXSIZE}
  1175. return 1
  1176. fi
  1177. DIALOG --yesno "${BOLD}The following operations will be executed:${RESET}\n\n
  1178. ${BOLD}${TARGETFS}${RESET}\n
  1179. ${BOLD}${RED}WARNING: data on partitions will be COMPLETELY DESTROYED for new \
  1180. filesystems.${RESET}\n\n
  1181. ${BOLD}Do you want to continue?${RESET}" 20 80 || return
  1182. unset TARGETFS
  1183. # Create and mount filesystems
  1184. create_filesystems
  1185. # If source not set use defaults.
  1186. if [ "$(get_option SOURCE)" = "local" -o -z "$SOURCE_DONE" ]; then
  1187. copy_rootfs
  1188. . /etc/default/live.conf
  1189. rm -f $TARGETDIR/etc/motd
  1190. rm -f $TARGETDIR/etc/issue
  1191. rm -f $TARGETDIR/usr/sbin/void-installer
  1192. # Remove modified sddm.conf to let sddm use the defaults.
  1193. rm -f $TARGETDIR/etc/sddm.conf
  1194. # Remove live user.
  1195. echo "Removing $USERNAME live user from targetdir ..." >$LOG
  1196. chroot $TARGETDIR userdel -r $USERNAME >$LOG 2>&1
  1197. rm -f $TARGETDIR/etc/sudoers.d/99-void-live
  1198. TITLE="Check $LOG for details ..."
  1199. INFOBOX "Rebuilding initramfs for target ..." 4 60
  1200. echo "Rebuilding initramfs for target ..." >$LOG
  1201. # mount required fs
  1202. mount_filesystems
  1203. chroot $TARGETDIR dracut --no-hostonly --add-drivers "ahci" --force >>$LOG 2>&1
  1204. INFOBOX "Removing temporary packages from target ..." 4 60
  1205. echo "Removing temporary packages from target ..." >$LOG
  1206. xbps-remove -r $TARGETDIR -Ry dialog xtools-minimal xmirror >>$LOG 2>&1
  1207. rmdir $TARGETDIR/mnt/target
  1208. else
  1209. # mount required fs
  1210. mount_filesystems
  1211. # network install, use packages.
  1212. install_packages
  1213. fi
  1214. INFOBOX "Applying installer settings..." 4 60
  1215. # copy target fstab.
  1216. install -Dm644 $TARGET_FSTAB $TARGETDIR/etc/fstab
  1217. # Mount /tmp as tmpfs.
  1218. echo "tmpfs /tmp tmpfs defaults,nosuid,nodev 0 0" >> $TARGETDIR/etc/fstab
  1219. # set up keymap, locale, timezone, hostname, root passwd and user account.
  1220. set_keymap
  1221. set_locale
  1222. set_timezone
  1223. set_hostname
  1224. set_rootpassword
  1225. set_useraccount
  1226. # Copy /etc/skel files for root.
  1227. cp $TARGETDIR/etc/skel/.[bix]* $TARGETDIR/root
  1228. # network settings for target
  1229. if [ -n "$NETWORK_DONE" ]; then
  1230. local net="$(get_option NETWORK)"
  1231. set -- ${net}
  1232. local _dev="$1" _type="$2" _ip="$3" _gw="$4" _dns1="$5" _dns2="$6"
  1233. if [ -z "$_type" ]; then
  1234. # network type empty??!!!
  1235. :
  1236. elif [ "$_type" = "dhcp" ]; then
  1237. if $(echo $_dev|egrep -q "^wl.*" 2>/dev/null); then
  1238. cp /etc/wpa_supplicant/wpa_supplicant.conf $TARGETDIR/etc/wpa_supplicant
  1239. ln -sf /etc/sv/wpa_supplicant $TARGETDIR/etc/runit/runsvdir/default/wpa_supplicant
  1240. fi
  1241. enable_dhcpd
  1242. elif [ -n "$_dev" -a "$_type" = "static" ]; then
  1243. # static IP through dhcpcd.
  1244. mv $TARGETDIR/etc/dhcpcd.conf $TARGETDIR/etc/dhcpcd.conf.orig
  1245. echo "# Static IP configuration set by the void-installer for $_dev." \
  1246. >$TARGETDIR/etc/dhcpcd.conf
  1247. echo "interface $_dev" >>$TARGETDIR/etc/dhcpcd.conf
  1248. echo "static ip_address=$_ip" >>$TARGETDIR/etc/dhcpcd.conf
  1249. echo "static routers=$_gw" >>$TARGETDIR/etc/dhcpcd.conf
  1250. echo "static domain_name_servers=$_dns1 $_dns2" >>$TARGETDIR/etc/dhcpcd.conf
  1251. enable_dhcpd
  1252. fi
  1253. fi
  1254. if [ -d $TARGETDIR/etc/sudoers.d ]; then
  1255. USERLOGIN="$(get_option USERLOGIN)"
  1256. if [ -z "$(echo $(get_option USERGROUPS) | grep -w wheel)" -a -n "$USERLOGIN" ]; then
  1257. # enable sudo for primary user USERLOGIN who is not member of wheel
  1258. echo "# Enable sudo for login '$USERLOGIN'" > "$TARGETDIR/etc/sudoers.d/$USERLOGIN"
  1259. echo "$USERLOGIN ALL=(ALL:ALL) ALL" >> "$TARGETDIR/etc/sudoers.d/$USERLOGIN"
  1260. else
  1261. # enable the sudoers entry for members of group wheel
  1262. echo "%wheel ALL=(ALL:ALL) ALL" > "$TARGETDIR/etc/sudoers.d/wheel"
  1263. fi
  1264. unset USERLOGIN
  1265. fi
  1266. # clean up polkit rule - it's only useful in live systems
  1267. rm -f $TARGETDIR/etc/polkit-1/rules.d/void-live.rules
  1268. # enable text console for grub if chosen
  1269. if [ "$(get_option TEXTCONSOLE)" = "1" ]; then
  1270. sed -i $TARGETDIR/etc/default/grub \
  1271. -e 's|#\(GRUB_TERMINAL_INPUT\).*|\1=console|' \
  1272. -e 's|#\(GRUB_TERMINAL_OUTPUT\).*|\1=console|'
  1273. fi
  1274. # install bootloader.
  1275. set_bootloader
  1276. sync && sync && sync
  1277. # unmount all filesystems.
  1278. umount_filesystems
  1279. # installed successfully.
  1280. DIALOG --yesno "${BOLD}Void Linux has been installed successfully!${RESET}\n
  1281. Do you want to reboot the system?" ${YESNOSIZE}
  1282. if [ $? -eq 0 ]; then
  1283. shutdown -r now
  1284. else
  1285. return
  1286. fi
  1287. }
  1288. menu_source() {
  1289. local src=
  1290. DIALOG --title " Select installation source " \
  1291. --menu "$MENULABEL" 8 70 0 \
  1292. "Local" "Packages from ISO image" \
  1293. "Network" "Base system only, downloaded from official repository"
  1294. case "$(cat $ANSWER)" in
  1295. "Local") src="local";;
  1296. "Network") src="net";
  1297. if [ -z "$NETWORK_DONE" ]; then
  1298. menu_network;
  1299. fi;;
  1300. *) return 1;;
  1301. esac
  1302. SOURCE_DONE=1
  1303. set_option SOURCE $src
  1304. }
  1305. menu_mirror() {
  1306. xmirror 2>$LOG && MIRROR_DONE=1
  1307. }
  1308. menu() {
  1309. local AFTER_HOSTNAME
  1310. if [ -z "$DEFITEM" ]; then
  1311. DEFITEM="Keyboard"
  1312. fi
  1313. if xbps-uhelper arch | grep -qe '-musl$'; then
  1314. AFTER_HOSTNAME="Timezone"
  1315. DIALOG --default-item $DEFITEM \
  1316. --extra-button --extra-label "Settings" \
  1317. --title " Void Linux installation menu " \
  1318. --menu "$MENULABEL" 10 70 0 \
  1319. "Keyboard" "Set system keyboard" \
  1320. "Network" "Set up the network" \
  1321. "Source" "Set source installation" \
  1322. "Mirror" "Select XBPS mirror" \
  1323. "Hostname" "Set system hostname" \
  1324. "Timezone" "Set system time zone" \
  1325. "RootPassword" "Set system root password" \
  1326. "UserAccount" "Set primary user name and password" \
  1327. "BootLoader" "Set disk to install bootloader" \
  1328. "Partition" "Partition disk(s)" \
  1329. "Filesystems" "Configure filesystems and mount points" \
  1330. "Install" "Start installation with saved settings" \
  1331. "Exit" "Exit installation"
  1332. else
  1333. AFTER_HOSTNAME="Locale"
  1334. DIALOG --default-item $DEFITEM \
  1335. --extra-button --extra-label "Settings" \
  1336. --title " Void Linux installation menu " \
  1337. --menu "$MENULABEL" 10 70 0 \
  1338. "Keyboard" "Set system keyboard" \
  1339. "Network" "Set up the network" \
  1340. "Source" "Set source installation" \
  1341. "Mirror" "Select XBPS mirror" \
  1342. "Hostname" "Set system hostname" \
  1343. "Locale" "Set system locale" \
  1344. "Timezone" "Set system time zone" \
  1345. "RootPassword" "Set system root password" \
  1346. "UserAccount" "Set primary user name and password" \
  1347. "BootLoader" "Set disk to install bootloader" \
  1348. "Partition" "Partition disk(s)" \
  1349. "Filesystems" "Configure filesystems and mount points" \
  1350. "Install" "Start installation with saved settings" \
  1351. "Exit" "Exit installation"
  1352. fi
  1353. if [ $? -eq 3 ]; then
  1354. # Show settings
  1355. cp $CONF_FILE /tmp/conf_hidden.$$;
  1356. sed -i "s/^ROOTPASSWORD.*/ROOTPASSWORD <-hidden->/" /tmp/conf_hidden.$$
  1357. sed -i "s/^USERPASSWORD.*/USERPASSWORD <-hidden->/" /tmp/conf_hidden.$$
  1358. DIALOG --title "Saved settings for installation" --textbox /tmp/conf_hidden.$$ 14 60
  1359. rm /tmp/conf_hidden.$$
  1360. return
  1361. fi
  1362. case $(cat $ANSWER) in
  1363. "Keyboard") menu_keymap && [ -n "$KEYBOARD_DONE" ] && DEFITEM="Network";;
  1364. "Network") menu_network && [ -n "$NETWORK_DONE" ] && DEFITEM="Source";;
  1365. "Source") menu_source && [ -n "$SOURCE_DONE" ] && DEFITEM="Mirror";;
  1366. "Mirror") menu_mirror && [ -n "$MIRROR_DONE" ] && DEFITEM="Hostname";;
  1367. "Hostname") menu_hostname && [ -n "$HOSTNAME_DONE" ] && DEFITEM="$AFTER_HOSTNAME";;
  1368. "Locale") menu_locale && [ -n "$LOCALE_DONE" ] && DEFITEM="Timezone";;
  1369. "Timezone") menu_timezone && [ -n "$TIMEZONE_DONE" ] && DEFITEM="RootPassword";;
  1370. "RootPassword") menu_rootpassword && [ -n "$ROOTPASSWORD_DONE" ] && DEFITEM="UserAccount";;
  1371. "UserAccount") menu_useraccount && [ -n "$USERNAME_DONE" ] && [ -n "$USERPASSWORD_DONE" ] \
  1372. && DEFITEM="BootLoader";;
  1373. "BootLoader") menu_bootloader && [ -n "$BOOTLOADER_DONE" ] && DEFITEM="Partition";;
  1374. "Partition") menu_partitions && [ -n "$PARTITIONS_DONE" ] && DEFITEM="Filesystems";;
  1375. "Filesystems") menu_filesystems && [ -n "$FILESYSTEMS_DONE" ] && DEFITEM="Install";;
  1376. "Install") menu_install;;
  1377. "Exit") DIE;;
  1378. *) DIALOG --yesno "Abort Installation?" ${YESNOSIZE} && DIE
  1379. esac
  1380. }
  1381. if ! command -v dialog >/dev/null; then
  1382. echo "ERROR: missing dialog command, exiting..."
  1383. exit 1
  1384. fi
  1385. if [ "$(id -u)" != "0" ]; then
  1386. echo "void-installer must run as root" 1>&2
  1387. exit 1
  1388. fi
  1389. #
  1390. # main()
  1391. #
  1392. DIALOG --title "${BOLD}${RED} Enter the void ... ${RESET}" --msgbox "\n
  1393. Welcome to the Void Linux installation. A simple and minimal \
  1394. Linux distribution made from scratch and built from the source package tree \
  1395. available for XBPS, a new alternative binary package system.\n\n
  1396. The installation should be pretty straightforward. If you are in trouble \
  1397. please join us at ${BOLD}#voidlinux${RESET} on ${BOLD}irc.libera.chat${RESET}.\n\n
  1398. ${BOLD}https://www.voidlinux.org${RESET}\n\n" 16 80
  1399. while true; do
  1400. menu
  1401. done
  1402. exit 0
  1403. # vim: set ts=4 sw=4 et: